Annotation of researchv10no/cmd/sign/verify.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.