|
|
1.1 ! root 1: #include "regexp.h" ! 2: #include <stdio.h> ! 3: #include <string.h> ! 4: ! 5: /* version history of certificates ! 6: version 0, installed Jun 6 1991 ! 7: Signed by name, ctime-date ! 8: sum=string, count=number ! 9: ------ ! 10: message ! 11: ------ ! 12: sum=string, count=number ! 13: End name, ctime-date ! 14: version 1, installed Jun 10 1991 ! 15: Signed by name, ctime-date ! 16: sum=string, date=gmtime-hex, count=number, ver=1 ! 17: ------ ! 18: message with comma before each line, counted in sum ! 19: ------ ! 20: sum=string, date=gmtime-hex, count=number, ver=1 ! 21: End name, ctime-date ! 22: */ ! 23: ! 24: extern char *malloc(), *realloc(); ! 25: extern long time(); ! 26: extern char *ctime(); ! 27: extern void exit(); ! 28: extern char *getline(); ! 29: ! 30: #define SIZEOF(a) (sizeof(a)/sizeof(*a)) ! 31: ! 32: int version = 0; ! 33: ! 34: struct field { ! 35: char *name, *pat; ! 36: int len, seq; ! 37: char *val; ! 38: }; ! 39: ! 40: struct field head[] = { ! 41: { "signer", "^..?.?.?.?.?.?.?$" }, ! 42: { "ctime", "^... ... .. ..:..:.. ....$" } ! 43: }; ! 44: enum { NAME, CTIME }; ! 45: ! 46: struct field data[] = { ! 47: { "sum", "^[0-9a-f]+$" }, ! 48: { "date", "^[0-9a-f]+$" }, ! 49: { "count", "^[0-9]+$" }, ! 50: { "ver", "^[0-9]+$" } ! 51: }; ! 52: enum { SUM, DATE, COUNT, VERS }; ! 53: int ndata[] = { 2, 4 }; /* # of fields in version */ ! 54: ! 55: char occ[][SIZEOF(data)] = { /* sequence of fields in version*/ ! 56: { 1,0,2,0 }, ! 57: { 1,2,3,4 } ! 58: }; ! 59: ! 60: main(ac,av) ! 61: char **av; ! 62: { ! 63: regsubexp mv[10]; ! 64: char *s, *body; ! 65: int headlen, len1; ! 66: long tloc; ! 67: char *now; ! 68: int i, lines; ! 69: char canon[50]; ! 70: FILE *fil = stdin; ! 71: int sflag = 0; ! 72: regexp *l1= regcomp("Signed by (.+), (.+)$"); ! 73: char *pat = "signer=\\1, ctime=\\2"; ! 74: regexp *dashes = regcomp("------$"); ! 75: regexp *l3 = regcomp("End (.+), (.+)$"); ! 76: ! 77: if(ac>1 && strcmp(av[1],"-s")==0) { ! 78: sflag++; ! 79: av++; ! 80: ac--; ! 81: } ! 82: if(ac>1 && (fil=fopen(av[1],"r"))==0) { ! 83: write(2,"verify: ",8); ! 84: perror(av[1]); ! 85: exit(1); ! 86: } ! 87: ! 88: while(s=getline(fil)) { ! 89: if(regexec(l1,s,mv,3)==0) continue; ! 90: regsub(pat,canon,mv,3); /* make the non-u uniform */ ! 91: if(parse(canon,head,SIZEOF(head))==2) ! 92: break; ! 93: for(i=0; i<SIZEOF(head); i++) ! 94: head[i].val = 0; ! 95: } ! 96: if(s==0) error("cannot find signature line"); ! 97: ! 98: s = getline(fil); ! 99: if(s==0 || parse(s,data,SIZEOF(data))<2) ! 100: error("cannot identify checksum line"); ! 101: version = data[VERS].val==0? 0: atoi(data[VERS].val); ! 102: if(version >= SIZEOF(ndata)) ! 103: error("improper version number"); ! 104: for(i=0; i<SIZEOF(data); i++) ! 105: if(data[i].seq != occ[version][i]) ! 106: error("incorrect field sequence"); ! 107: ! 108: s = getline(fil); ! 109: if(s==0 || regexec(dashes,s,mv,0)==0) ! 110: error("cannot find beginning cut mark"); ! 111: ! 112: len1 = atoi(data[COUNT].val); ! 113: headlen = head[CTIME].len; ! 114: if(version==1) ! 115: headlen += data[DATE].len+head[NAME].len; ! 116: body = malloc(len1+headlen+1); ! 117: if(body==0) overflow(); ! 118: strcpy(body,head[CTIME].val); ! 119: if(version!=0) ! 120: strcat(strcat(body,data[DATE].val),head[NAME].val); ! 121: if(input(body+headlen,len1,fil)==0) ! 122: error("cannot read full signed text"); ! 123: ! 124: s = getline(fil); ! 125: if(s==0 || regexec(dashes,s,mv,0)==0) ! 126: error("cannot find ending cut mark"); ! 127: ! 128: s = getline(fil); ! 129: if(s==0 || parse(s,data,SIZEOF(data))!=ndata[version]) ! 130: error("cannot find matching checksum line"); ! 131: ! 132: s = getline(fil); ! 133: if(s==0 || regexec(l3,s,mv,3)==0) ! 134: error("cannot find matching signature line"); ! 135: regsub(pat,canon,mv,3); ! 136: if(parse(canon,head,SIZEOF(head))!=2) ! 137: error("cannot find matching signature line"); ! 138: ! 139: lines = 0; ! 140: if(version!=0) for(i=headlen+len1; --i>=headlen; ) ! 141: if(body[i]=='\n') lines++; ! 142: ! 143: switch(verify(head[NAME].val, data[SUM].val, body, headlen+len1)){ ! 144: case 1: ! 145: (void)time(&tloc); ! 146: now = ctime(&tloc); ! 147: printf("Signature by %s, %s\n", ! 148: head[NAME].val, head[DATE].val); ! 149: printf("verified %.24s, count=%d\n",now, len1-lines); ! 150: if(sflag) exit(0); ! 151: printf("-----\n"); ! 152: output(body+headlen,len1); ! 153: printf("-----\n"); ! 154: printf("verified %.24s, count=%d\n",now, len1-lines); ! 155: printf("End %s, %s\n", ! 156: head[NAME].val, head[DATE].val); ! 157: exit(0); ! 158: case 0: ! 159: fprintf(stderr,"verify: Bogus\n"); ! 160: exit(1); ! 161: case -1: ! 162: fprintf(stderr,"verify: server unavailable; try later\n"); ! 163: exit(2); ! 164: } ! 165: /*NOTREACHED*/ ! 166: } ! 167: ! 168: error(err) ! 169: char *err; ! 170: { ! 171: fprintf(stderr,"verify: document format error: %s\n", err); ! 172: exit(1); ! 173: } ! 174: ! 175: overflow() ! 176: { ! 177: fprintf(stderr,"verify: out of space\n"); ! 178: exit(2); ! 179: } ! 180: ! 181: output(s, n) ! 182: char *s; ! 183: { ! 184: int d = version!=0; ! 185: ! 186: s += d; ! 187: n -= d; ! 188: while(--n >= 0) { ! 189: putchar(*s); ! 190: if(*s == '\n') ! 191: s+=d, n-=d; ! 192: s++; ! 193: } ! 194: } ! 195: ! 196: input(s, n, fil) ! 197: char *s; ! 198: FILE *fil; ! 199: { ! 200: int c, nl; ! 201: ! 202: nl = 1; ! 203: while(n>0) { ! 204: c = getc(fil); ! 205: if(c==EOF) break; ! 206: if(nl && version!=0 && c!=',') ! 207: continue; ! 208: nl = 0; ! 209: *s++ = c; ! 210: n--; ! 211: if(c=='\n') nl++; ! 212: } ! 213: return n==0; ! 214: } ! 215: ! 216: parse(s,field,n) /* extract name=val fields */ ! 217: char *s; ! 218: struct field *field; ! 219: { ! 220: regsubexp mv[3]; ! 221: int c = ','; ! 222: regexp *nameval, *re; ! 223: int seq, len, i; ! 224: ! 225: nameval = regcomp("^ *([a-z]+)=([^,]+)"); ! 226: if(nameval==0) overflow(); ! 227: ! 228: for(seq=1; c==',' && regexec(nameval,s,mv,3); seq++) { ! 229: c = mv[0].ep[0]; ! 230: s = mv[0].ep + 1; ! 231: for(i=0; i<n; i++) { ! 232: mv[1].ep[0] = 0; ! 233: if(strcmp(field[i].name,mv[1].sp)==0) ! 234: break; ! 235: } ! 236: if(i >= n) ! 237: return -1; ! 238: len = mv[2].ep - mv[2].sp; ! 239: if(field[i].val==0) { /* 1st time make entry */ ! 240: field[i].len = len; ! 241: field[i].seq = seq; ! 242: mv[2].ep[0] = 0; ! 243: field[i].val = strdup(mv[2].sp); ! 244: if(field[i].val==0) overflow(); ! 245: re = regcomp(field[i].pat); ! 246: if(re==0) overflow(); ! 247: if(regexec(re,field[i].val,mv,0)==0) ! 248: return -1; ! 249: free((char*)re); ! 250: } ! 251: else /* 2nd time check entry (hack) */ ! 252: if(field[i].len!=len || field[i].seq!=seq || ! 253: strncmp(field[i].val,mv[2].sp,len)!=0) ! 254: return -1; ! 255: } ! 256: free((char*)nameval); ! 257: return c!=0? -1: seq-1; ! 258: } ! 259: ! 260: char * ! 261: getline(fil) ! 262: FILE *fil; ! 263: { ! 264: static char *s; ! 265: static len; ! 266: int n, c; ! 267: ! 268: if(s==0) { ! 269: len = BUFSIZ; ! 270: s = malloc(len); ! 271: if(s==0) overflow(); ! 272: } ! 273: n = 0; ! 274: for(;;) { ! 275: if(n>=len) { ! 276: len += BUFSIZ; ! 277: s = realloc(s,len); ! 278: if(s==0) overflow(); ! 279: } ! 280: c = getc(fil); ! 281: switch(c) { ! 282: case EOF: ! 283: return 0; ! 284: case '\n': ! 285: s[n] = 0; ! 286: return s; ! 287: default: ! 288: s[n++] = c; ! 289: } ! 290: } ! 291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.