The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Wednesday, April 26, 2000

Woo hoo! Bug free the first time through …

It's always nice when code I write works the first time.

mod_blog advancing yet some more. I was going to embed the HTML within the module, but when I wrote some sample code (to make the archives on the current site) it just got real messy real quick and I didn't even bother finishing it up.

Instead, I quickly wrote code to process template files. This side works pretty much like I think I'm going to end up doing it. I set up a subdirectory containing the templates, each file containing just a portion of a much larger page. In effect, each file is a chunk of HTML code that is processed. During the processing, anything between double hash signs is taken as the name of a callback function.

So for example, in the HTML code I have:

<html>
<head>

  <title>##title## - The Boston Diaries - Captain Napalm<title>

</head>

And the callbacks are currently defined in C as such:

static void archive_callback(FILE *fpout,void *data)
{
  struct tm *ptm = data;
  char       date[BUFSIZ];

  strftime(date,BUFSIZ,"%B %Y",ptm);
  fprintf(fpout,"%s",date);
}

/***************************************************/

void do_archive(
		  FILE *fpout,
                  int   year,
		  int   month,
                  int   stday,
                  int   endday)
{
  static struct chunk_callback cb 
    = { "title" , archive_callback };
  struct tm thisday;

  /* code to set thisday properly snipped */

  ChunkProcess(fpout,"archivehead",&cb,1,&thisday);
  ChunkProcess(fpout,"bostontitle",NULL,0,NULL);
  ChunkProcess(fpout,"bartitle",&cb,1,&thisday);
  
  /* code to generate links for each day */

  ChunkProcess(fpout,"end",NULL,0,NULL);
}

The call to ChunkProcess() takes an output file, the name of the chunk to display, a structure declaring the callbacks, the size of that array, and an extra pointer that is passed to the callback, in this case, to a struct tm * to the date we're processing.

The only thing I may change is the way callbacks are registered, but the mechanics certainly work.


Walkthrough

Now, how did I go about writing 145 lines of bug-free C code to implement the chunk mechanism? Easy. I broke it down into simpler steps. The main routine, ChunkProcess() takes five parameters, an output file, the name of the chunk, the callbacks, number of callbacks, and an arbitrary pointer to data passed back to the callbacks.

So, basically, we have:

int (ChunkProcess)(
                    FILE                  *fpout,
                    char                  *name,
                    struct chunk_callback *pcc,
                    size_t                 scc,
                    void                  *data
                  )
{
  char  fname[FILENAME_LEN];
  FILE *fpin;
  int   c;

  assert(fpout != NULL);
  assert(name  != NULL);
  assert(pcc   != NULL);
  assert(scc   >  0);

  sprintf(fname,"chunks/%s",name);
  fpin = fopen(fname,"r");
  if (fpin == NULL)
    return(CHUNKERR_OPEN);

  while(1)
  {
    c = fgetc(fpin);
    if (c == '#')
    {
      c = fgetc(fpin);
      if (c == '#')
      {
        chunk_handle(fpin,fpout,pcc,scc,data);
        continue;
      }

      fputc('#',fpout);
    }
  
    if (c == EOF) break;
    fputc(c,fpout);
  }
 
  fclose(fpin);
  return(ERR_OKAY);
}

I just basically look for two consecutive hash marks, and if I find them, I call chunk_handle() to do the work for me (I should note my convention I'm using here—StudlyCaps has external linkage, visible to other modules. lower_case is local to this module). So we now have:

static void chunk_handle(
                          FILE                  *fpin,
                          FILE                  *fpout,
                          struct chunk_callback *pcc,
                          size_t                 scc,
                          void                  *data
                        )
{
  char  cmdbuf[BUFSIZ];
  char *cmd;
  char *p;

  assert(fpin  != NULL);
  assert(fpout != NULL);
  assert(pcc   != NULL);
  assert(scc   >  0);

  chunk_readcallback(fpin,cmdbuf,BUFSIZ);

  for (
        p = cmdbuf ; 
        (cmd = strtok(p," \t\v\r\n")) != NULL ; 
        p = NULL 
      )
  {
    chunk_docallback(fpout,cmd,pcc,scc,data);
  }
}

chunk_readcallback() reads the text just past the double hash mark to the following double hash mark. Then using strtok() (easy since it's there, I know how to use it and I'm not worried about threading issues yet) I break it up. This allows us to specify multiple callbacks within a single entry and for each callback, we find it and call the function.

static void chunk_docallback(
                              FILE                  *fpout,
                              char                  *cmd,
                              struct chunk_callback *pcc,
                              size_t                 scc,
                              void                  *data
                            )
{
  int i;

  assert(fpout != NULL);
  assert(cmd   != NULL);
  assert(pcc   != NULL);
  assert(scc   >  0);

  for (i = 0 ; i < SCC ; i++)
  {
    if (strcmp(cmd,pcc[i].name) == 0)
    {
      (*pcc->callback)(fpout,data);
      return;
    }
  }
  fprintf(fpout,"##processing error - can't find [%s] ##",cmd);
}

Again, since I'm just playing around and want something that works, the linear scan doesn't scale, but since I'm not planning on having a dozen or more callbacks, it doesn't hurt. It can be changed easily though since we do pass in the size of the array and as long as it's noted that the array should be sorted alphabetically we can later change to a binary search.

I'm not sure if a hash table is the way to go at this point—that might require a different way of passing in or registering the callbacks, and as it stands right now, I can use the same templates and have different code for the callbacks. The chunk “bartitle” which I defined is used all over the place, and the title itself may not be a date, so the ability to change what ##title## does depending upon what I'm displaying is crucial—I just pass in a different callback array.

The fprintf() is there for diagnostics—I can leave it out with the effect of undefined callbacks don't generate any output at all, but there is no notification of the undefined callback either. I put it in but another way of handling it might be to print out the callback as found in the text, between double hashmarks.

And that's it. The code for chunk_readcallback() is easy enough to leave it as an exercise for the reader, as well as the definition of struct callback.

The trick is just breaking it up into simple pieces.

Saturday, April 26, 2003

My Quiet Place

Spring and the kids are in central Florida, visiting Cape Canaveral. I stayed behind to stay in my quiet place.

Tuesday, April 26, 2005

… and the cops go wizzing by …

The last time I saw this many cops was a few years ago when the bank our company was above was being robbed.* This time however, about two dozen cop cars (at least, maybe more) just flew by our office, sirens blaring and turned right at the corner into one of the many commercial parks in this section of Boca Raton, Florida. I figure we'll hear about it on the news later tonight, tomorrow at the latest.

* It was a Friday afternoon in '98 or '99 when the building we were in was surrouded by Boca's Finest. Shortly afterwards, the SWAT team showed up, and took positions around the building. A police officer managed to make it up the back stairs to our office and told us to keep the door locked. After a few tense hours the suspect was arrested—it turned out he was an escaped mental patient.


Waiting … waiting … waiting.

Compiling on the Cobalt RaQ2 isn't fast. It's actually rather sluggish when you come right down to it. Now whether that is a function of the MIPS chip, a slow bus speed, or a slow IDE drive, I can't say, although I suspect it may be a slow bus speed (the MIPS based SGI system I used at FAU, while only 33 MHz, was fast—the only things faster were the newer MIPS based SGIs).

Time it took to compile various packages on a 250MHz MIPS based Cobalt RaQ2
Package Real time User time System time
MySQL 4.1.11 312m, 31.074s 288m, 52.820s  20m, 32.900s
Bind 9.3.1 51m,  0.245s 47m,  2.640s  3m, 20.260s
Apache 2.0.54 84m, 26.658s 66m,  6.710s 16m, 45.680s
PHP 4.3.11 56m, 17.193s 45m, 44.070s  9m, 52.470s

These were just the packages I kept the compile times for—the rest (like OpenSSL or NTP were just as slow to compile.

I wonder though … if there is a way to tune the IDE drivers to get some better throughput …

Wednesday, April 26, 2006

That sick feeling in your stomach when you know you created a huge mess

I thought I would go ahead and remove the firewall between our core router and the DSL router. I made as much preparation as I could before 5:00 pm, the end of the business day.

At about 5:05 pm I swapped some network cables around.

And the Internet broke.

I'm not sure why it didn't work. At first, I thought maybe it was the VLAN I created on the core router for the DSL router port (to segregate the network traffic and cut down on broadcasts) and reverted that.

The DSL circuit was still down, and my phone started ringing.

I then thought that I needed a crossover cable, but I was getting a link light when using the existing cable.

And the DSL circuit was still down.

The routing changes I had to make looked good, but still, no DSL.

Clearing the ARP tables didn't help [but I just now realized, in writing this, that I only cleared the ARP table on the core router, and not on the DSL router—hmmmm].

So I had to revert everything back while trying to keep myself from getting sick.

Blah.

Thursday, April 26, 2007

Rethinking computer security

I came across this Google Tech Talk about computer security given by Rik Farrow wherein his thesis is that we need to rethink what we're trying to accomplish.

One thought struck me during the discussion on buffer overflow attacks—the Motorola 6809 had two stack pointers, one used by the CPU itself to store return addresses, but another one that I always assumed was supposed to be used solely for parameter passing. So instead of passing parameters on the default stack like, say, the 8086:

MSG.1	DB	'%s',0
MSG.2	DB	'Hello world',13,10,0

	...

	MOV	AX,OFFSET MSG.1
	PUSH	AX		; save on SP
	MOV	AX,OFFSET MSG.2
	PUSH	AX		; save on SP
	CALL	_printf		; return address also on SP

where everything gets pushed onto one stack and you run the risk of overwriting the return address, on the 6809, use the other stack for parameters:

MSG.1	FCS	'%s',0
MSG.2	FCS	'Hello world',13,10,0


	...

	LDX	#MSG.2
	PSHU	X	* push onto the User stack
	LDX	#MSG.1
	PSHU	X	* push onto the User stack
	JSR	_printf	* return address on System stack

Using a separate stack means you only overwrite program data, not critical system information (especially important when arrays are defined on the stack). But, in reading about some of the ways that buffer overwrites can be exploited, this may not foil every attack. But it's a start, and modern CPUs certainly have enough registers to have a separate parameter stack (although in reading interviews with the 6809 designers, it seems the user stack register was meant to construct stack frames on a single stack, much like the x86's use of the SP and BP registers).

That also reminded me of the Intel 432, which treated everything as an object with set memory limits, so gaining a buffer overwrite exploit on a 432-based system would be exceedingly difficult indeed (too bad it died—it's an interesting chip).

But the basic thrust of the talk was that our computer security models are severely outdated and come from a time when a single computer was shared among several people, whereas today, we have a single user shared among computers (or at the very least, a single user per system, and in this talk, he considered something like Apache as a user) using software (say, certain email clients) that accepts code from Lord knows where (say, evil spammers) and simply executes it (because it goes out of its way to press execute the oh so shiny button code). We need to rethink what we want from computer security.

Saturday, April 26, 2014

Just because there's a standard doesn't mean it's consistent

I came across this URL today that has some base64 encoded data in it. Curious as to what it might be, I tossed the data into a base64 decoder only to have it reject the data as bad.

Okay. It certainly looks like base64 encoded data. But the data doesn't match the RFC-2045 specification. Don't tell me there's more than one … oh for heaven's sake! Really? Thirteen variations?

Standards! There are so many to choose from!


An unexpected feature

As I was writing the link to RFC-2045 in the previous post, an idea suddenly struck me—why should I have to type out the entire URL? I already have a shortcut to link to Amazon (all I have to do is write a link like <a href="asin:B00BWQW73E"> and mod_blog converts it to <a class="book" href="http://www.amazon.com/exec/obidos/ASIN/B00BWQW73E/conmanlaborat-20">) so it shouldn't be that hard to add.

I was fully expecting it to take maybe fifteen minutes or so to add the code, but to my surprise, no code change was required! The configuration file has this bit:

affiliate =
{
  {
    proto = "asin",
    link  = "http://www.amazon.com/exec/obidos/ASIN/%s/conmanlaborat-20"
  }
}

It was originally intended for affiliate links, but it'll work for this as well. A slight modification:

affiliate =
{
  {
    proto = "asin",
    link  = "http://www.amazon.com/exec/obidos/ASIN/%s/conmanlaborat-20"
  },
  {
    proto = "rfc",
    link  = "http://www.ietf.org/rfc/rfc%s.txt"
  },
}

Now all I have to do is write <a href="rfc:2045"> and mod_blog will convert it to <a href="http://www.ietf.org/rfc/rfc2045.txt">. I love it when stuff like this happens.


Beware typosquatting

When I initially added the links to the IETF RFC database I made a typo. Instead of linking to “I-E-T-F dot O-R-G” I instead typed it as “I-E-F-T dot O-R-G” and … wow. Easily a dozen redirects, probably half a dozen attempts to infect my computer and landing on some company website I never heard of hawking seminars to help you pass Cisco training and certificaitons.

Shudder.

Sunday, April 26, 2015

Just a quick note on something I noticed going on today on the home network

The script kiddies are active tonight.

Chain ssh-block (1 references)
 pkts bytes target     prot opt in     out     source               destination         
   17  1812 REJECT     all  --  *      *       188.135.202.39       0.0.0.0/0           reject-with icmp-port-unreachable 
   38  2272 REJECT     all  --  *      *       113.106.85.23        0.0.0.0/0           reject-with icmp-port-unreachable 
    4   348 REJECT     all  --  *      *       117.253.105.235      0.0.0.0/0           reject-with icmp-port-unreachable 
   19  2080 REJECT     all  --  *      *       37.190.87.219        0.0.0.0/0           reject-with icmp-port-unreachable 
   20  2316 REJECT     all  --  *      *       187.72.49.52         0.0.0.0/0           reject-with icmp-port-unreachable 
   16  1796 REJECT     all  --  *      *       201.75.109.180       0.0.0.0/0           reject-with icmp-port-unreachable 
  512 25388 REJECT     all  --  *      *       218.83.6.81          0.0.0.0/0           reject-with icmp-port-unreachable 
   20  2248 REJECT     all  --  *      *       177.70.122.255       0.0.0.0/0           reject-with icmp-port-unreachable 
   15  1800 REJECT     all  --  *      *       117.253.215.122      0.0.0.0/0           reject-with icmp-port-unreachable 
   17  2032 REJECT     all  --  *      *       117.244.25.226       0.0.0.0/0           reject-with icmp-port-unreachable 
   18  2048 REJECT     all  --  *      *       134.255.165.240      0.0.0.0/0           reject-with icmp-port-unreachable 
   17  1964 REJECT     all  --  *      *       187.49.248.42        0.0.0.0/0           reject-with icmp-port-unreachable 

These are just the script kiddies caught trying to brute force a login to my home machine over the past hour (they're blocked after five attempts, and the block remains for an hour lest I end up with hundreds of entries). I wonder if there's a quota they have to meet?

Obligatory Picture

[The future's so bright, I gotta wear shades]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2024 by Sean Conner. All Rights Reserved.