static int decode64(dearmour_arg_t *arg,ops_error_t **errors, ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) { unsigned n; int n2; unsigned long l; int c; int ret; if(!(arg->buffered == 0)) // ASSERT(arg->buffered == 0); { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly formed base64"); return 0; } ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&l); if(ret < 0) { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly formed base64"); return 0; } if(n == 3) { if(c != '=') { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (2)"); return 0; } arg->buffered=2; arg->eof64=ops_true; l >>= 2; } else if(n == 2)
static ops_boolean_t error_writer(const unsigned char *src, unsigned length, ops_error_t **errors, ops_writer_info_t *winfo) { OPS_USED(src); OPS_USED(length); error_arg_t *arg=ops_writer_get_arg(winfo); arg->times_called++; CU_ASSERT(arg->times_called <= arg->count); if (arg->times_called == arg->count) { OPS_ERROR(errors, arg->code, arg->msg); return ops_false; } else { return ops_true; } }
/* Note that this skips CRs so implementations always see just straight LFs as line terminators */ static int process_dash_escaped(dearmour_arg_t *arg,ops_error_t **errors, ops_reader_info_t *rinfo, ops_parse_cb_info_t *cbinfo) { ops_parser_content_t content; ops_parser_content_t content2; ops_signed_cleartext_body_t *body=&content.content.signed_cleartext_body; ops_signed_cleartext_trailer_t *trailer =&content2.content.signed_cleartext_trailer; const char *hashstr; ops_hash_t *hash; int total; hash=malloc(sizeof *hash); hashstr=ops_find_header(&arg->headers,"Hash"); if(hashstr) { ops_hash_algorithm_t alg; alg=ops_hash_algorithm_from_text(hashstr); if(!ops_is_hash_alg_supported(&alg)) { free(hash); OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unsupported hash algorithm '%s'",hashstr); return -1; } if(alg == OPS_HASH_UNKNOWN) { free(hash); OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unknown hash algorithm '%s'",hashstr); return -1; } ops_hash_any(hash,alg); } else ops_hash_md5(hash); hash->init(hash); body->length=0; total=0; for( ; ; ) { int c; unsigned count; if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) return -1; if(arg->prev_nl && c == '-') { if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) return -1; if(c != ' ') { /* then this had better be a trailer! */ if(c != '-') OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping"); for(count=2 ; count < 5 ; ++count) { if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) return -1; if(c != '-') OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping (2)"); } arg->state=AT_TRAILER_NAME; break; } /* otherwise we read the next character */ if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) return -1; } if(c == '\n' && body->length) { if(!(memchr(body->data+1,'\n',body->length-1) == NULL)) // ASSERT(memchr(body->data+1,'\n',body->length-1) == NULL); { fprintf(stderr,"no \\n in armoured file.") ; return -1 ; } if(body->data[0] == '\n') hash->add(hash,(unsigned char *)"\r",1); hash->add(hash,body->data,body->length); if (debug) { fprintf(stderr,"Got body:\n%s\n",body->data); } CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); body->length=0; } body->data[body->length++]=c; ++total; if(body->length == sizeof body->data) { if (debug) { fprintf(stderr,"Got body (2):\n%s\n",body->data); } CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); body->length=0; } } if(!(body->data[0] == '\n')) // ASSERT(body->data[0] == '\n'); { fprintf(stderr,"Body should end with \\n\n"); return -1 ; } if(!(body->length == 1)) // ASSERT(body->length == 1); { fprintf(stderr,"Body length error\n"); return -1 ; } /* don't send that one character, because its part of the trailer. */ trailer->hash=hash; CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER,&content2); return total; }
/* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */ static int parse_headers(dearmour_arg_t *arg,ops_error_t **errors, ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) { int rtn=1; char *buf; unsigned nbuf; unsigned size; ops_boolean_t first=ops_true; //ops_parser_content_t content; buf=NULL; nbuf=size=0; for( ; ; ) { int c; if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Unexpected EOF"); rtn=-1; break; } if(c == '\n') { char *s; if(nbuf == 0) break; if(!(nbuf < size)) // ASSERT(nbuf < size); { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Size error in armour header"); return -1 ; } buf[nbuf]='\0'; s=strchr(buf,':'); if(!s) if(!first && !arg->allow_headers_without_gap) { // then we have seriously malformed armour OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No colon in armour header"); rtn=-1; break; } else { if(first && !(arg->allow_headers_without_gap || arg->allow_no_gap)) { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No colon in armour header (2)"); // then we have a nasty armoured block with no // headers, not even a blank line. buf[nbuf]='\n'; push_back(arg,(unsigned char *)buf,nbuf+1); rtn=-1; break; } } else { *s='\0'; if(s[1] != ' ') { OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No space in armour header"); rtn=-1; goto end; } if (!add_header(arg,buf,s+2)) { OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Invalid header %s", buf); rtn=-1; goto end; } nbuf=0; } first=ops_false; } else { if(size <= nbuf+1) { size+=size+80; char *nbuf; nbuf=realloc(buf,size); if (nbuf == NULL) { free(buf); buf = NULL ; rtn=-1; goto end; } buf = nbuf; } buf[nbuf++]=c; } } end: free(buf); return rtn; }
static int set_lastseen_headerline(dearmour_arg_t* arg, char* buf, ops_error_t **errors) { char* begin_msg="BEGIN PGP MESSAGE"; char* begin_public="BEGIN PGP PUBLIC KEY BLOCK"; char* begin_private="BEGIN PGP PRIVATE KEY BLOCK"; char* begin_multi="BEGIN PGP MESSAGE, PART "; char* begin_sig="BEGIN PGP SIGNATURE"; char* end_msg="END PGP MESSAGE"; char* end_public="END PGP PUBLIC KEY BLOCK"; char* end_private="END PGP PRIVATE KEY BLOCK"; char* end_multi="END PGP MESSAGE, PART "; char* end_sig="END PGP SIGNATURE"; char* begin_signed_msg="BEGIN PGP SIGNED MESSAGE"; int prev=arg->lastseen; if (!strncmp(buf,begin_msg,strlen(begin_msg))) arg->lastseen=BEGIN_PGP_MESSAGE; else if (!strncmp(buf,begin_public,strlen(begin_public))) arg->lastseen=BEGIN_PGP_PUBLIC_KEY_BLOCK; else if (!strncmp(buf,begin_private,strlen(begin_private))) arg->lastseen=BEGIN_PGP_PRIVATE_KEY_BLOCK; else if (!strncmp(buf,begin_multi,strlen(begin_multi))) arg->lastseen=BEGIN_PGP_MULTI; else if (!strncmp(buf,begin_sig,strlen(begin_sig))) arg->lastseen=BEGIN_PGP_SIGNATURE; else if (!strncmp(buf,end_msg,strlen(end_msg))) arg->lastseen=END_PGP_MESSAGE; else if (!strncmp(buf,end_public,strlen(end_public))) arg->lastseen=END_PGP_PUBLIC_KEY_BLOCK; else if (!strncmp(buf,end_private,strlen(end_private))) arg->lastseen=END_PGP_PRIVATE_KEY_BLOCK; else if (!strncmp(buf,end_multi,strlen(end_multi))) arg->lastseen=END_PGP_MULTI; else if (!strncmp(buf,end_sig,strlen(end_sig))) arg->lastseen=END_PGP_SIGNATURE; else if (!strncmp(buf,begin_signed_msg,strlen(begin_signed_msg))) arg->lastseen=BEGIN_PGP_SIGNED_MESSAGE; else { OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unrecognised Header Line %s", buf); return 0; } if (debug) printf("set header: buf=%s, arg->lastseen=%d, prev=%d\n", buf, arg->lastseen, prev); switch (arg->lastseen) { case NONE: OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unrecognised last seen Header Line %s", buf); break; case END_PGP_MESSAGE: if (prev!=BEGIN_PGP_MESSAGE) OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP MESSAGE, but not after BEGIN"); break; case END_PGP_PUBLIC_KEY_BLOCK: if (prev!=BEGIN_PGP_PUBLIC_KEY_BLOCK) OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP PUBLIC KEY BLOCK, but not after BEGIN"); break; case END_PGP_PRIVATE_KEY_BLOCK: if (prev!=BEGIN_PGP_PRIVATE_KEY_BLOCK) OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP PRIVATE KEY BLOCK, but not after BEGIN"); break; case BEGIN_PGP_MULTI: case END_PGP_MULTI: OPS_ERROR(errors,OPS_E_R_UNSUPPORTED,"Multi-part messages are not yet supported"); break; case END_PGP_SIGNATURE: if (prev!=BEGIN_PGP_SIGNATURE) OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP SIGNATURE, but not after BEGIN"); break; case BEGIN_PGP_MESSAGE: case BEGIN_PGP_PUBLIC_KEY_BLOCK: case BEGIN_PGP_PRIVATE_KEY_BLOCK: case BEGIN_PGP_SIGNATURE: case BEGIN_PGP_SIGNED_MESSAGE: break; } return 1; }