/*Id:$*/ /*Name:$*/ #include "stralloc.h" #include "surf.h" #include "uint32.h" #include "makehash.h" typedef struct { uint32 seed[32]; uint32 sum[8]; uint32 out[8]; uint32 in[12]; int todo; } surfpcs; #define SURFPCS_LEN 32 static void surfpcs_init(s,k) surfpcs *s; uint32 k[32]; { int i; for (i = 0;i < 32;++i) s->seed[i] = k[i]; for (i = 0;i < 8;++i) s->sum[i] = 0; for (i = 0;i < 12;++i) s->in[i] = 0; s->todo = 0; } static uint32 littleendian[8] = { 50462976, 117835012, 185207048, 252579084, 319951120, 387323156, 454695192, 522067228 } ; #define end ((unsigned char *) littleendian) #define data ((unsigned char *) s->in) #define outdata ((unsigned char *) s->out) static void surfpcs_addlc(s,x,n) /* modified from Dan's surfpcs_add by skipping ' ' & '\t' and */ /* case-independence */ surfpcs *s; unsigned char *x; unsigned int n; { register unsigned char ch; int i; while (n--) { ch = *x++; if (ch == ' ' || ch == '\t') continue; if (ch >= 'A' && ch <= 'Z') data[end[s->todo++]] = ch - 'A' + 'a'; else data[end[s->todo++]] = ch; if (s->todo == 32) { s->todo = 0; if (!++s->in[8]) if (!++s->in[9]) if (!++s->in[10]) ++s->in[11]; surf(s->out,s->in,s->seed); for (i = 0;i < 8;++i) s->sum[i] += s->out[i]; } } } static void surfpcs_out(s,h) surfpcs *s; unsigned char h[32]; { int i; surfpcs_addlc(s,".",1); while (s->todo) surfpcs_addlc(s,"",1); for (i = 0;i < 8;++i) s->in[i] = s->sum[i]; for (;i < 12;++i) s->in[i] = 0; surf(s->out,s->in,s->seed); for (i = 0;i < 32;++i) h[i] = outdata[end[i]]; } void makehash(indata,inlen,hash) char *indata; unsigned int inlen; char *hash; /* makes hash[COOKIE=20] from stralloc *indata, ignoring case and */ /* SPACE/TAB */ { unsigned char h[32]; surfpcs s; uint32 seed[32]; int i; for (i = 0;i < 32;++i) seed[i] = 0; surfpcs_init(&s,seed); surfpcs_addlc(&s,indata,inlen); surfpcs_out(&s,h); for (i = 0;i < 20;++i) hash[i] = 'a' + (h[i] & 15); } static stralloc dummy = {0}; void mkauthhash(s,len,h) char *s; unsigned int len; char *h; /* This is a string that should be the same for all messages from a given */ /* author. Doesn't have to be the real rfc822 address. We look for a '@' */ /* and grab everything up to the next '>', ' ', or ';'. We go back the same */ /* way, then take everything up to the '@' or the first '-'. The latter */ /* avoids problems with posters that band their addresses. */ { unsigned int i,j,k,l; register char ch; j = k = l = 0; i = byte_rchr(s,len,'@'); if (i < len) { /* if not then i=sa->len, j=k=l=0 */ j = i; while (++j < len) { /* if not found, then j=sa->len */ ch = s[j]; if (ch == '>' || ch == ' ' || ch == ';') break; } k = i; while (k > 0) { /* k <= i */ ch = s[--k]; if (ch == '<' || ch == ' ' || ch == ';') break; } l = k; /* k <= l <= i; */ while (l < i && s[l] != '-') ++l; if (!stralloc_copyb(&dummy,s + k, l - k)) die_nomem(); if (!stralloc_catb(&dummy,s + i, j - i)) die_nomem(); makehash(dummy.s,dummy.len,h); } else /* use entire line if no '@' found */ makehash(s,len,h); }