| 38 | | static void format_error(ops_parser_content_t *content, |
|---|
| 39 | | const char * const fmt,...) |
|---|
| 40 | | { |
|---|
| 41 | | va_list va; |
|---|
| 42 | | static char buf[8192]; |
|---|
| 43 | | |
|---|
| 44 | | va_start(va,fmt); |
|---|
| 45 | | vsprintf(buf,fmt,va); |
|---|
| 46 | | va_end(va); |
|---|
| 47 | | content->content.error.error=buf; |
|---|
| 48 | | } |
|---|
| 49 | | |
|---|
| 50 | | static ops_reader_ret_t base_read(unsigned char *dest,unsigned *plength, |
|---|
| 51 | | ops_reader_flags_t flags, |
|---|
| 52 | | ops_parse_options_t *opt) |
|---|
| 53 | | { |
|---|
| 54 | | ops_reader_ret_t ret=opt->reader(dest,plength,flags,opt->reader_arg); |
|---|
| 55 | | if(ret != OPS_R_OK |
|---|
| 56 | | && !(ret == OPS_R_EOF && !(flags&OPS_RETURN_LENGTH))) |
|---|
| 57 | | return ret; |
|---|
| 58 | | |
|---|
| 59 | | if(opt->accumulate) |
|---|
| | 39 | static void |
|---|
| | 40 | format_error (ops_parser_content_t * content, const char *const fmt, ...) |
|---|
| | 41 | { |
|---|
| | 42 | va_list va; |
|---|
| | 43 | static char buf[8192]; |
|---|
| | 44 | |
|---|
| | 45 | va_start (va, fmt); |
|---|
| | 46 | vsprintf (buf, fmt, va); |
|---|
| | 47 | va_end (va); |
|---|
| | 48 | content->content.error.error = buf; |
|---|
| | 49 | } |
|---|
| | 50 | |
|---|
| | 51 | static ops_reader_ret_t |
|---|
| | 52 | base_read (unsigned char *dest, unsigned *plength, |
|---|
| | 53 | ops_reader_flags_t flags, ops_parse_options_t * opt) |
|---|
| | 54 | { |
|---|
| | 55 | ops_reader_ret_t ret = opt->reader (dest, plength, flags, opt->reader_arg); |
|---|
| | 56 | if (ret != OPS_R_OK && !(ret == OPS_R_EOF && !(flags & OPS_RETURN_LENGTH))) |
|---|
| | 57 | return ret; |
|---|
| | 58 | |
|---|
| | 59 | if (opt->accumulate) |
|---|
| | 60 | { |
|---|
| | 61 | assert (opt->asize >= opt->alength); |
|---|
| | 62 | if (opt->alength + *plength > opt->asize) |
|---|
| 127 | | int ops_limited_read(unsigned char *dest,unsigned length, |
|---|
| 128 | | ops_region_t *region,ops_parse_options_t *opt) |
|---|
| 129 | | { |
|---|
| 130 | | ops_parser_content_t content; |
|---|
| 131 | | |
|---|
| 132 | | if(region->length_read+length > region->length) |
|---|
| 133 | | ERR("Not enough data left"); |
|---|
| 134 | | |
|---|
| 135 | | if(base_read(dest,&length,region->indeterminate ? OPS_RETURN_LENGTH: 0,opt) |
|---|
| 136 | | != OPS_R_OK) |
|---|
| 137 | | ERR("Read failed"); |
|---|
| 138 | | |
|---|
| 139 | | region->last_read=length; |
|---|
| 140 | | do |
|---|
| 141 | | { |
|---|
| 142 | | region->length_read+=length; |
|---|
| 143 | | assert(!region->parent || region->length <= region->parent->length); |
|---|
| 144 | | } |
|---|
| 145 | | while((region=region->parent)); |
|---|
| 146 | | |
|---|
| 147 | | return 1; |
|---|
| 148 | | } |
|---|
| | 127 | int |
|---|
| | 128 | ops_limited_read (unsigned char *dest, unsigned length, |
|---|
| | 129 | ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 130 | { |
|---|
| | 131 | ops_parser_content_t content; |
|---|
| | 132 | |
|---|
| | 133 | if (region->length_read + length > region->length) |
|---|
| | 134 | ERR ("Not enough data left"); |
|---|
| | 135 | |
|---|
| | 136 | if (base_read |
|---|
| | 137 | (dest, &length, region->indeterminate ? OPS_RETURN_LENGTH : 0, |
|---|
| | 138 | opt) != OPS_R_OK) |
|---|
| | 139 | ERR ("Read failed"); |
|---|
| | 140 | |
|---|
| | 141 | region->last_read = length; |
|---|
| | 142 | do |
|---|
| | 143 | { |
|---|
| | 144 | region->length_read += length; |
|---|
| | 145 | assert (!region->parent || region->length <= region->parent->length); |
|---|
| | 146 | } |
|---|
| | 147 | while ((region = region->parent)); |
|---|
| | 148 | |
|---|
| | 149 | return 1; |
|---|
| | 150 | } |
|---|
| 256 | | static int limited_read_mpi(BIGNUM **pbn,ops_region_t *region, |
|---|
| 257 | | ops_parse_options_t *opt) |
|---|
| 258 | | { |
|---|
| 259 | | unsigned length; |
|---|
| 260 | | unsigned nonzero; |
|---|
| 261 | | unsigned char buf[8192]; /* an MPI has a 2 byte length part. Length |
|---|
| 262 | | is given in bits, so the largest we should |
|---|
| 263 | | ever need for the buffer is 8192 bytes. */ |
|---|
| 264 | | ops_parser_content_t content; |
|---|
| 265 | | |
|---|
| 266 | | if(!limited_read_scalar(&length,2,region,opt)) |
|---|
| 267 | | return 0; |
|---|
| 268 | | |
|---|
| 269 | | nonzero=length&7; /* there should be this many zero bits in the MS byte */ |
|---|
| 270 | | if(!nonzero) |
|---|
| 271 | | nonzero=8; |
|---|
| 272 | | length=(length+7)/8; |
|---|
| 273 | | |
|---|
| 274 | | assert(length <= 8192); |
|---|
| 275 | | if(!ops_limited_read(buf,length,region,opt)) |
|---|
| 276 | | return 0; |
|---|
| 277 | | |
|---|
| 278 | | if((buf[0] >> nonzero) != 0 || !(buf[0]&(1 << (nonzero-1)))) |
|---|
| 279 | | ERR("MPI format error"); /* XXX: Ben, one part of this constraint does not apply to encrypted MPIs the draft says. -- peter */ |
|---|
| 280 | | |
|---|
| 281 | | *pbn=BN_bin2bn(buf,length,NULL); |
|---|
| 282 | | return 1; |
|---|
| 283 | | } |
|---|
| | 260 | static int |
|---|
| | 261 | limited_read_mpi (BIGNUM ** pbn, ops_region_t * region, |
|---|
| | 262 | ops_parse_options_t * opt) |
|---|
| | 263 | { |
|---|
| | 264 | unsigned length; |
|---|
| | 265 | unsigned nonzero; |
|---|
| | 266 | unsigned char buf[8192]; /* an MPI has a 2 byte length part. Length |
|---|
| | 267 | is given in bits, so the largest we should |
|---|
| | 268 | ever need for the buffer is 8192 bytes. */ |
|---|
| | 269 | ops_parser_content_t content; |
|---|
| | 270 | |
|---|
| | 271 | if (!limited_read_scalar (&length, 2, region, opt)) |
|---|
| | 272 | return 0; |
|---|
| | 273 | |
|---|
| | 274 | nonzero = length & 7; /* there should be this many zero bits in the MS byte */ |
|---|
| | 275 | if (!nonzero) |
|---|
| | 276 | nonzero = 8; |
|---|
| | 277 | length = (length + 7) / 8; |
|---|
| | 278 | |
|---|
| | 279 | assert (length <= 8192); |
|---|
| | 280 | if (!ops_limited_read (buf, length, region, opt)) |
|---|
| | 281 | return 0; |
|---|
| | 282 | |
|---|
| | 283 | if ((buf[0] >> nonzero) != 0 || !(buf[0] & (1 << (nonzero - 1)))) |
|---|
| | 284 | ERR ("MPI format error"); /* XXX: Ben, one part of this constraint does not apply to encrypted MPIs the draft says. -- peter */ |
|---|
| | 285 | |
|---|
| | 286 | *pbn = BN_bin2bn (buf, length, NULL); |
|---|
| | 287 | return 1; |
|---|
| | 288 | } |
|---|
| 302 | | static int limited_read_new_length(unsigned *length,ops_region_t *region, |
|---|
| 303 | | ops_parse_options_t *opt) |
|---|
| 304 | | { |
|---|
| 305 | | unsigned char c[1]; |
|---|
| 306 | | |
|---|
| 307 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 308 | | return 0; |
|---|
| 309 | | if(c[0] < 192) |
|---|
| 310 | | { |
|---|
| 311 | | *length=c[0]; |
|---|
| 312 | | return 1; |
|---|
| 313 | | } |
|---|
| 314 | | if(c[0] < 255) |
|---|
| 315 | | { |
|---|
| 316 | | unsigned t=(c[0]-192) << 8; |
|---|
| 317 | | |
|---|
| 318 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 319 | | return 0; |
|---|
| 320 | | *length=t+c[1]+192; |
|---|
| 321 | | return 1; |
|---|
| 322 | | } |
|---|
| 323 | | return limited_read_scalar(length,4,region,opt); |
|---|
| 324 | | } |
|---|
| 325 | | |
|---|
| 326 | | void ops_packet_free(ops_packet_t *packet) |
|---|
| 327 | | { |
|---|
| 328 | | free(packet->raw); |
|---|
| 329 | | packet->raw=NULL; |
|---|
| 330 | | } |
|---|
| 331 | | |
|---|
| 332 | | void ops_parser_content_free(ops_parser_content_t *c) |
|---|
| 333 | | { |
|---|
| 334 | | switch(c->tag) |
|---|
| 335 | | { |
|---|
| | 307 | static int |
|---|
| | 308 | limited_read_new_length (unsigned *length, ops_region_t * region, |
|---|
| | 309 | ops_parse_options_t * opt) |
|---|
| | 310 | { |
|---|
| | 311 | unsigned char c[1]; |
|---|
| | 312 | |
|---|
| | 313 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 314 | return 0; |
|---|
| | 315 | if (c[0] < 192) |
|---|
| | 316 | { |
|---|
| | 317 | *length = c[0]; |
|---|
| | 318 | return 1; |
|---|
| | 319 | } |
|---|
| | 320 | if (c[0] < 255) |
|---|
| | 321 | { |
|---|
| | 322 | unsigned t = (c[0] - 192) << 8; |
|---|
| | 323 | |
|---|
| | 324 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 325 | return 0; |
|---|
| | 326 | *length = t + c[1] + 192; |
|---|
| | 327 | return 1; |
|---|
| | 328 | } |
|---|
| | 329 | return limited_read_scalar (length, 4, region, opt); |
|---|
| | 330 | } |
|---|
| | 331 | |
|---|
| | 332 | void |
|---|
| | 333 | ops_packet_free (ops_packet_t * packet) |
|---|
| | 334 | { |
|---|
| | 335 | free (packet->raw); |
|---|
| | 336 | packet->raw = NULL; |
|---|
| | 337 | } |
|---|
| | 338 | |
|---|
| | 339 | void |
|---|
| | 340 | ops_parser_content_free (ops_parser_content_t * c) |
|---|
| | 341 | { |
|---|
| | 342 | switch (c->tag) |
|---|
| | 343 | { |
|---|
| 417 | | static int parse_public_key(ops_content_tag_t tag,ops_region_t *region, |
|---|
| 418 | | ops_parse_options_t *opt) |
|---|
| 419 | | { |
|---|
| 420 | | ops_parser_content_t content; |
|---|
| 421 | | unsigned char c[1]; |
|---|
| 422 | | |
|---|
| 423 | | assert (region->length_read == 0); /* We should not have read anything so far */ |
|---|
| 424 | | |
|---|
| 425 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 426 | | return 0; |
|---|
| 427 | | C.public_key.version=c[0]; |
|---|
| 428 | | if(C.public_key.version < 2 || C.public_key.version > 4) |
|---|
| 429 | | ERR1("Bad public key version (0x%02x)",C.public_key.version); |
|---|
| 430 | | |
|---|
| 431 | | if(!limited_read_time(&C.public_key.creation_time,region,opt)) |
|---|
| 432 | | return 0; |
|---|
| 433 | | |
|---|
| 434 | | C.public_key.days_valid=0; |
|---|
| 435 | | if((C.public_key.version == 2 || C.public_key.version == 3) |
|---|
| 436 | | && !limited_read_scalar(&C.public_key.days_valid,2,region,opt)) |
|---|
| 437 | | return 0; |
|---|
| 438 | | |
|---|
| 439 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 440 | | return 0; |
|---|
| 441 | | |
|---|
| 442 | | C.public_key.algorithm=c[0]; |
|---|
| 443 | | |
|---|
| 444 | | switch(C.public_key.algorithm) |
|---|
| 445 | | { |
|---|
| | 427 | static int |
|---|
| | 428 | parse_public_key (ops_content_tag_t tag, ops_region_t * region, |
|---|
| | 429 | ops_parse_options_t * opt) |
|---|
| | 430 | { |
|---|
| | 431 | ops_parser_content_t content; |
|---|
| | 432 | unsigned char c[1]; |
|---|
| | 433 | |
|---|
| | 434 | assert (region->length_read == 0); /* We should not have read anything so far */ |
|---|
| | 435 | |
|---|
| | 436 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 437 | return 0; |
|---|
| | 438 | C.public_key.version = c[0]; |
|---|
| | 439 | if (C.public_key.version < 2 || C.public_key.version > 4) |
|---|
| | 440 | ERR1 ("Bad public key version (0x%02x)", C.public_key.version); |
|---|
| | 441 | |
|---|
| | 442 | if (!limited_read_time (&C.public_key.creation_time, region, opt)) |
|---|
| | 443 | return 0; |
|---|
| | 444 | |
|---|
| | 445 | C.public_key.days_valid = 0; |
|---|
| | 446 | if ((C.public_key.version == 2 || C.public_key.version == 3) |
|---|
| | 447 | && !limited_read_scalar (&C.public_key.days_valid, 2, region, opt)) |
|---|
| | 448 | return 0; |
|---|
| | 449 | |
|---|
| | 450 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 451 | return 0; |
|---|
| | 452 | |
|---|
| | 453 | C.public_key.algorithm = c[0]; |
|---|
| | 454 | |
|---|
| | 455 | switch (C.public_key.algorithm) |
|---|
| | 456 | { |
|---|
| 504 | | static int parse_user_id(ops_region_t *region,ops_parse_options_t *opt) |
|---|
| 505 | | { |
|---|
| 506 | | ops_parser_content_t content; |
|---|
| 507 | | |
|---|
| 508 | | assert (region->length_read == 0); /* We should not have read anything so far */ |
|---|
| 509 | | |
|---|
| 510 | | assert(region->length); |
|---|
| 511 | | C.user_id.user_id=malloc(region->length+1); /* XXX should we not like check malloc's return value? */ |
|---|
| 512 | | if(!ops_limited_read(C.user_id.user_id,region->length,region,opt)) |
|---|
| 513 | | return 0; |
|---|
| 514 | | C.user_id.user_id[region->length] = 0; /* terminate the string */ |
|---|
| 515 | | |
|---|
| 516 | | CB(OPS_PTAG_CT_USER_ID,&content); |
|---|
| 517 | | |
|---|
| 518 | | return 1; |
|---|
| 519 | | } |
|---|
| 520 | | |
|---|
| 521 | | void ops_signature_free(ops_signature_t *sig) |
|---|
| 522 | | { |
|---|
| 523 | | switch(sig->key_algorithm) |
|---|
| 524 | | { |
|---|
| | 516 | static int |
|---|
| | 517 | parse_user_id (ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 518 | { |
|---|
| | 519 | ops_parser_content_t content; |
|---|
| | 520 | |
|---|
| | 521 | assert (region->length_read == 0); /* We should not have read anything so far */ |
|---|
| | 522 | |
|---|
| | 523 | assert (region->length); |
|---|
| | 524 | C.user_id.user_id = malloc (region->length + 1); /* XXX should we not like check malloc's return value? */ |
|---|
| | 525 | if (!ops_limited_read (C.user_id.user_id, region->length, region, opt)) |
|---|
| | 526 | return 0; |
|---|
| | 527 | C.user_id.user_id[region->length] = 0; /* terminate the string */ |
|---|
| | 528 | |
|---|
| | 529 | CB (OPS_PTAG_CT_USER_ID, &content); |
|---|
| | 530 | |
|---|
| | 531 | return 1; |
|---|
| | 532 | } |
|---|
| | 533 | |
|---|
| | 534 | void |
|---|
| | 535 | ops_signature_free (ops_signature_t * sig) |
|---|
| | 536 | { |
|---|
| | 537 | switch (sig->key_algorithm) |
|---|
| | 538 | { |
|---|
| 552 | | static int parse_v3_signature(ops_region_t *region,ops_parse_options_t *opt) |
|---|
| 553 | | { |
|---|
| 554 | | unsigned char c[1]; |
|---|
| 555 | | ops_parser_content_t content; |
|---|
| 556 | | |
|---|
| 557 | | C.signature.version=OPS_SIG_V3; |
|---|
| 558 | | |
|---|
| 559 | | /* hash info length */ |
|---|
| 560 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 561 | | return 0; |
|---|
| 562 | | if(c[0] != 5) |
|---|
| 563 | | ERR("bad hash info length"); |
|---|
| 564 | | |
|---|
| 565 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 566 | | return 0; |
|---|
| 567 | | C.signature.type=c[0]; |
|---|
| 568 | | /* XXX: check signature type */ |
|---|
| 569 | | |
|---|
| 570 | | if(!limited_read_time(&C.signature.creation_time,region,opt)) |
|---|
| 571 | | return 0; |
|---|
| 572 | | |
|---|
| 573 | | if(!ops_limited_read(C.signature.signer_id,8,region,opt)) |
|---|
| 574 | | return 0; |
|---|
| 575 | | |
|---|
| 576 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 577 | | return 0; |
|---|
| 578 | | C.signature.key_algorithm=c[0]; |
|---|
| 579 | | /* XXX: check algorithm */ |
|---|
| 580 | | |
|---|
| 581 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 582 | | return 0; |
|---|
| 583 | | C.signature.hash_algorithm=c[0]; |
|---|
| 584 | | /* XXX: check algorithm */ |
|---|
| 585 | | |
|---|
| 586 | | if(!ops_limited_read(C.signature.hash2,2,region,opt)) |
|---|
| 587 | | return 0; |
|---|
| 588 | | |
|---|
| 589 | | switch(C.signature.key_algorithm) |
|---|
| 590 | | { |
|---|
| | 566 | static int |
|---|
| | 567 | parse_v3_signature (ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 568 | { |
|---|
| | 569 | unsigned char c[1]; |
|---|
| | 570 | ops_parser_content_t content; |
|---|
| | 571 | |
|---|
| | 572 | C.signature.version = OPS_SIG_V3; |
|---|
| | 573 | |
|---|
| | 574 | /* hash info length */ |
|---|
| | 575 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 576 | return 0; |
|---|
| | 577 | if (c[0] != 5) |
|---|
| | 578 | ERR ("bad hash info length"); |
|---|
| | 579 | |
|---|
| | 580 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 581 | return 0; |
|---|
| | 582 | C.signature.type = c[0]; |
|---|
| | 583 | /* XXX: check signature type */ |
|---|
| | 584 | |
|---|
| | 585 | if (!limited_read_time (&C.signature.creation_time, region, opt)) |
|---|
| | 586 | return 0; |
|---|
| | 587 | |
|---|
| | 588 | if (!ops_limited_read (C.signature.signer_id, 8, region, opt)) |
|---|
| | 589 | return 0; |
|---|
| | 590 | |
|---|
| | 591 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 592 | return 0; |
|---|
| | 593 | C.signature.key_algorithm = c[0]; |
|---|
| | 594 | /* XXX: check algorithm */ |
|---|
| | 595 | |
|---|
| | 596 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 597 | return 0; |
|---|
| | 598 | C.signature.hash_algorithm = c[0]; |
|---|
| | 599 | /* XXX: check algorithm */ |
|---|
| | 600 | |
|---|
| | 601 | if (!ops_limited_read (C.signature.hash2, 2, region, opt)) |
|---|
| | 602 | return 0; |
|---|
| | 603 | |
|---|
| | 604 | switch (C.signature.key_algorithm) |
|---|
| | 605 | { |
|---|
| 630 | | static int parse_one_signature_subpacket(ops_signature_t *sig, |
|---|
| 631 | | ops_region_t *region, |
|---|
| 632 | | ops_parse_options_t *opt) |
|---|
| 633 | | { |
|---|
| 634 | | ops_region_t subregion; |
|---|
| 635 | | char c[1]; |
|---|
| 636 | | ops_parser_content_t content; |
|---|
| 637 | | unsigned t8,t7; |
|---|
| 638 | | ops_boolean_t read=ops_true; |
|---|
| 639 | | |
|---|
| 640 | | init_subregion(&subregion,region); |
|---|
| 641 | | if(!limited_read_new_length(&subregion.length,region,opt)) |
|---|
| 642 | | return 0; |
|---|
| 643 | | |
|---|
| 644 | | if(!ops_limited_read(c,1,&subregion,opt)) |
|---|
| 645 | | return 0; |
|---|
| 646 | | |
|---|
| 647 | | t8=(c[0]&0x7f)/8; |
|---|
| 648 | | t7=1 << (c[0]&7); |
|---|
| 649 | | |
|---|
| 650 | | content.critical=c[0] >> 7; |
|---|
| 651 | | content.tag=OPS_PTAG_SIGNATURE_SUBPACKET_BASE+(c[0]&0x7f); |
|---|
| 652 | | |
|---|
| 653 | | /* Application wants it delivered raw */ |
|---|
| 654 | | if(opt->ss_raw[t8]&t7) |
|---|
| 655 | | { |
|---|
| 656 | | C.ss_raw.tag=content.tag; |
|---|
| 657 | | C.ss_raw.length=subregion.length-1; |
|---|
| 658 | | C.ss_raw.raw=malloc(C.ss_raw.length); |
|---|
| 659 | | if(!ops_limited_read(C.ss_raw.raw,C.ss_raw.length,&subregion,opt)) |
|---|
| 660 | | return 0; |
|---|
| 661 | | CB(OPS_PTAG_RAW_SS,&content); |
|---|
| 662 | | return 1; |
|---|
| 663 | | } |
|---|
| 664 | | |
|---|
| 665 | | switch(content.tag) |
|---|
| 666 | | { |
|---|
| | 645 | static int |
|---|
| | 646 | parse_one_signature_subpacket (ops_signature_t * sig, |
|---|
| | 647 | ops_region_t * region, |
|---|
| | 648 | ops_parse_options_t * opt) |
|---|
| | 649 | { |
|---|
| | 650 | ops_region_t subregion; |
|---|
| | 651 | char c[1]; |
|---|
| | 652 | unsigned char bool; |
|---|
| | 653 | ops_parser_content_t content; |
|---|
| | 654 | unsigned t8, t7; |
|---|
| | 655 | ops_boolean_t read = ops_true; |
|---|
| | 656 | |
|---|
| | 657 | init_subregion (&subregion, region); |
|---|
| | 658 | if (!limited_read_new_length (&subregion.length, region, opt)) |
|---|
| | 659 | return 0; |
|---|
| | 660 | |
|---|
| | 661 | if (!ops_limited_read (c, 1, &subregion, opt)) |
|---|
| | 662 | return 0; |
|---|
| | 663 | |
|---|
| | 664 | t8 = (c[0] & 0x7f) / 8; |
|---|
| | 665 | t7 = 1 << (c[0] & 7); |
|---|
| | 666 | |
|---|
| | 667 | content.critical = c[0] >> 7; |
|---|
| | 668 | content.tag = OPS_PTAG_SIGNATURE_SUBPACKET_BASE + (c[0] & 0x7f); |
|---|
| | 669 | |
|---|
| | 670 | /* Application wants it delivered raw */ |
|---|
| | 671 | if (opt->ss_raw[t8] & t7) |
|---|
| | 672 | { |
|---|
| | 673 | C.ss_raw.tag = content.tag; |
|---|
| | 674 | C.ss_raw.length = subregion.length - 1; |
|---|
| | 675 | C.ss_raw.raw = malloc (C.ss_raw.length); |
|---|
| | 676 | if (!ops_limited_read (C.ss_raw.raw, C.ss_raw.length, &subregion, opt)) |
|---|
| | 677 | return 0; |
|---|
| | 678 | CB (OPS_PTAG_RAW_SS, &content); |
|---|
| | 679 | return 1; |
|---|
| | 680 | } |
|---|
| | 681 | |
|---|
| | 682 | switch (content.tag) |
|---|
| | 683 | { |
|---|
| 687 | | /* should this be malloc-ed? or done as fixed array? |
|---|
| 688 | | * use fixed arraysize for now. Ben? - Rachel */ |
|---|
| 689 | | |
|---|
| 690 | | C.ss_preferred_ska.len = subregion.length - subregion.length_read; |
|---|
| 691 | | if (!ops_limited_read(C.ss_preferred_ska.data, |
|---|
| 692 | | C.ss_preferred_ska.len, &subregion, opt)) |
|---|
| 693 | | return 0; |
|---|
| 694 | | break; |
|---|
| 695 | | |
|---|
| | 704 | /* should this be malloc-ed? or done as fixed array? |
|---|
| | 705 | * use fixed arraysize for now. Ben? - Rachel */ |
|---|
| | 706 | |
|---|
| | 707 | C.ss_preferred_ska.len = subregion.length - subregion.length_read; |
|---|
| | 708 | /* Do sanity check on length */ |
|---|
| | 709 | if (C.ss_preferred_ska.len > MAX_PREFERRED_SKA) |
|---|
| | 710 | { |
|---|
| | 711 | ERR1 |
|---|
| | 712 | ("Warning: Truncated Preferred Symmetric Algorithm - subpacket %d octets", |
|---|
| | 713 | C.ss_preferred_ska.len); |
|---|
| | 714 | C.ss_preferred_ska.len = MAX_PREFERRED_SKA; |
|---|
| | 715 | } |
|---|
| | 716 | if (!ops_limited_read (C.ss_preferred_ska.data, |
|---|
| | 717 | C.ss_preferred_ska.len, &subregion, opt)) |
|---|
| | 718 | return 0; |
|---|
| | 719 | break; |
|---|
| | 720 | |
|---|
| | 721 | case OPS_PTAG_SS_PRIMARY_USER_ID: |
|---|
| | 722 | if (!ops_limited_read (&bool, 1, &subregion, opt)) |
|---|
| | 723 | return 0; |
|---|
| | 724 | C.ss_primary_user_id.primary_user_id = !!bool; |
|---|
| | 725 | break; |
|---|
| | 726 | |
|---|
| | 727 | case OPS_PTAG_SS_REVOCATION_KEY: |
|---|
| | 728 | printf ("Sizeof struct is %d\n", sizeof (ops_ss_revocation_key_t)); |
|---|
| | 729 | |
|---|
| | 730 | /* octet 0 = class. Bit 0x80 must be set */ |
|---|
| | 731 | if (!ops_limited_read (&C.ss_revocation_key.class, 1, &subregion, opt)) |
|---|
| | 732 | return 0; |
|---|
| | 733 | if (!(C.ss_revocation_key.class & 0x80)) |
|---|
| | 734 | { |
|---|
| | 735 | printf |
|---|
| | 736 | ("Warning: OPS_PTAG_SS_REVOCATION_KEY class: Bit 0x80 should be set\n"); |
|---|
| | 737 | return 0; |
|---|
| | 738 | } |
|---|
| | 739 | |
|---|
| | 740 | /* octet 1 = algid */ |
|---|
| | 741 | if (!ops_limited_read (&C.ss_revocation_key.algid, 1, &subregion, opt)) |
|---|
| | 742 | return 0; |
|---|
| | 743 | |
|---|
| | 744 | /* octets 2-21 = fingerprint */ |
|---|
| | 745 | if (!ops_limited_read |
|---|
| | 746 | ((unsigned char *) &C.ss_revocation_key.fingerprint, 20, &subregion, |
|---|
| | 747 | opt)) |
|---|
| | 748 | return 0; |
|---|
| | 749 | break; |
|---|
| | 750 | |
|---|
| 697 | | if(opt->ss_parsed[t8]&t7) |
|---|
| 698 | | ERR1("Unknown signature subpacket type (%d)",c[0]&0x7f); |
|---|
| 699 | | read=ops_false; |
|---|
| 700 | | break; |
|---|
| 701 | | } |
|---|
| 702 | | |
|---|
| 703 | | /* Application doesn't want it delivered parsed */ |
|---|
| 704 | | if(!(opt->ss_parsed[t8]&t7)) |
|---|
| 705 | | { |
|---|
| 706 | | if(content.critical) |
|---|
| 707 | | ERR1("Critical signature subpacket ignored (%d)",c[0]&0x7f); |
|---|
| 708 | | if(!read && !limited_skip(subregion.length-1,&subregion,opt)) |
|---|
| 709 | | return 0; |
|---|
| 710 | | // printf("skipped %d length %d\n",c[0]&0x7f,subregion.length); |
|---|
| 711 | | if(read) |
|---|
| 712 | | ops_parser_content_free(&content); |
|---|
| 713 | | return 1; |
|---|
| 714 | | } |
|---|
| 715 | | |
|---|
| 716 | | if(read && subregion.length_read != subregion.length) |
|---|
| 717 | | ERR1("Unconsumed data (%d)", subregion.length-subregion.length_read); |
|---|
| 718 | | |
|---|
| 719 | | opt->cb(&content,opt->cb_arg); |
|---|
| 720 | | |
|---|
| 721 | | return 1; |
|---|
| 722 | | } |
|---|
| | 752 | if (opt->ss_parsed[t8] & t7) |
|---|
| | 753 | ERR1 ("Unknown signature subpacket type (%d)", c[0] & 0x7f); |
|---|
| | 754 | read = ops_false; |
|---|
| | 755 | break; |
|---|
| | 756 | } |
|---|
| | 757 | |
|---|
| | 758 | /* Application doesn't want it delivered parsed */ |
|---|
| | 759 | if (!(opt->ss_parsed[t8] & t7)) |
|---|
| | 760 | { |
|---|
| | 761 | if (content.critical) |
|---|
| | 762 | ERR1 ("Critical signature subpacket ignored (%d)", c[0] & 0x7f); |
|---|
| | 763 | if (!read && !limited_skip (subregion.length - 1, &subregion, opt)) |
|---|
| | 764 | return 0; |
|---|
| | 765 | // printf("skipped %d length %d\n",c[0]&0x7f,subregion.length); |
|---|
| | 766 | if (read) |
|---|
| | 767 | ops_parser_content_free (&content); |
|---|
| | 768 | return 1; |
|---|
| | 769 | } |
|---|
| | 770 | |
|---|
| | 771 | if (read && subregion.length_read != subregion.length) |
|---|
| | 772 | ERR1 ("Unconsumed data (%d)", subregion.length - subregion.length_read); |
|---|
| | 773 | |
|---|
| | 774 | opt->cb (&content, opt->cb_arg); |
|---|
| | 775 | |
|---|
| | 776 | return 1; |
|---|
| | 777 | } |
|---|
| 739 | | static int parse_signature_subpackets(ops_signature_t *sig, |
|---|
| 740 | | ops_region_t *region, |
|---|
| 741 | | ops_parse_options_t *opt) |
|---|
| 742 | | { |
|---|
| 743 | | ops_region_t subregion; |
|---|
| 744 | | |
|---|
| 745 | | init_subregion(&subregion,region); |
|---|
| 746 | | if(!limited_read_scalar(&subregion.length,2,region,opt)) |
|---|
| 747 | | return 0; |
|---|
| 748 | | |
|---|
| 749 | | while(subregion.length_read < subregion.length) |
|---|
| 750 | | if(!parse_one_signature_subpacket(sig,&subregion,opt)) |
|---|
| 751 | | return 0; |
|---|
| 752 | | |
|---|
| 753 | | assert(subregion.length_read == subregion.length); /* XXX: this should not be an assert but a parse error. It's not |
|---|
| 754 | | our fault if the packet is inconsistent with itself. */ |
|---|
| 755 | | |
|---|
| 756 | | return 1; |
|---|
| 757 | | } |
|---|
| | 794 | static int |
|---|
| | 795 | parse_signature_subpackets (ops_signature_t * sig, |
|---|
| | 796 | ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 797 | { |
|---|
| | 798 | ops_region_t subregion; |
|---|
| | 799 | |
|---|
| | 800 | init_subregion (&subregion, region); |
|---|
| | 801 | if (!limited_read_scalar (&subregion.length, 2, region, opt)) |
|---|
| | 802 | return 0; |
|---|
| | 803 | |
|---|
| | 804 | while (subregion.length_read < subregion.length) |
|---|
| | 805 | if (!parse_one_signature_subpacket (sig, &subregion, opt)) |
|---|
| | 806 | return 0; |
|---|
| | 807 | |
|---|
| | 808 | assert (subregion.length_read == subregion.length); /* XXX: this should not be an assert but a parse error. It's not |
|---|
| | 809 | our fault if the packet is inconsistent with itself. */ |
|---|
| | 810 | |
|---|
| | 811 | return 1; |
|---|
| | 812 | } |
|---|
| 772 | | static int parse_v4_signature(ops_region_t *region,ops_parse_options_t *opt, |
|---|
| 773 | | size_t v4_hashed_data_start) |
|---|
| 774 | | { |
|---|
| 775 | | unsigned char c[1]; |
|---|
| 776 | | ops_parser_content_t content; |
|---|
| 777 | | |
|---|
| 778 | | C.signature.version=OPS_SIG_V4; |
|---|
| 779 | | C.signature.v4_hashed_data_start=v4_hashed_data_start; |
|---|
| 780 | | |
|---|
| 781 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 782 | | return 0; |
|---|
| 783 | | C.signature.type=c[0]; |
|---|
| 784 | | /* XXX: check signature type */ |
|---|
| 785 | | |
|---|
| 786 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 787 | | return 0; |
|---|
| 788 | | C.signature.key_algorithm=c[0]; |
|---|
| 789 | | /* XXX: check algorithm */ |
|---|
| 790 | | |
|---|
| 791 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 792 | | return 0; |
|---|
| 793 | | C.signature.hash_algorithm=c[0]; |
|---|
| 794 | | /* XXX: check algorithm */ |
|---|
| 795 | | |
|---|
| 796 | | if(!parse_signature_subpackets(&C.signature,region,opt)) |
|---|
| 797 | | return 0; |
|---|
| 798 | | C.signature.v4_hashed_data_length=opt->alength |
|---|
| 799 | | -C.signature.v4_hashed_data_start; |
|---|
| 800 | | |
|---|
| 801 | | if(!parse_signature_subpackets(&C.signature,region,opt)) |
|---|
| 802 | | return 0; |
|---|
| 803 | | |
|---|
| 804 | | if(!ops_limited_read(C.signature.hash2,2,region,opt)) |
|---|
| 805 | | return 0; |
|---|
| 806 | | |
|---|
| 807 | | switch(C.signature.key_algorithm) |
|---|
| 808 | | { |
|---|
| | 827 | static int |
|---|
| | 828 | parse_v4_signature (ops_region_t * region, ops_parse_options_t * opt, |
|---|
| | 829 | size_t v4_hashed_data_start) |
|---|
| | 830 | { |
|---|
| | 831 | unsigned char c[1]; |
|---|
| | 832 | ops_parser_content_t content; |
|---|
| | 833 | |
|---|
| | 834 | C.signature.version = OPS_SIG_V4; |
|---|
| | 835 | C.signature.v4_hashed_data_start = v4_hashed_data_start; |
|---|
| | 836 | |
|---|
| | 837 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 838 | return 0; |
|---|
| | 839 | C.signature.type = c[0]; |
|---|
| | 840 | /* XXX: check signature type */ |
|---|
| | 841 | |
|---|
| | 842 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 843 | return 0; |
|---|
| | 844 | C.signature.key_algorithm = c[0]; |
|---|
| | 845 | /* XXX: check algorithm */ |
|---|
| | 846 | |
|---|
| | 847 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 848 | return 0; |
|---|
| | 849 | C.signature.hash_algorithm = c[0]; |
|---|
| | 850 | /* XXX: check algorithm */ |
|---|
| | 851 | |
|---|
| | 852 | if (!parse_signature_subpackets (&C.signature, region, opt)) |
|---|
| | 853 | return 0; |
|---|
| | 854 | C.signature.v4_hashed_data_length = opt->alength |
|---|
| | 855 | - C.signature.v4_hashed_data_start; |
|---|
| | 856 | |
|---|
| | 857 | if (!parse_signature_subpackets (&C.signature, region, opt)) |
|---|
| | 858 | return 0; |
|---|
| | 859 | |
|---|
| | 860 | if (!ops_limited_read (C.signature.hash2, 2, region, opt)) |
|---|
| | 861 | return 0; |
|---|
| | 862 | |
|---|
| | 863 | switch (C.signature.key_algorithm) |
|---|
| | 864 | { |
|---|
| 843 | | static int parse_signature(ops_region_t *region,ops_parse_options_t *opt) |
|---|
| 844 | | { |
|---|
| 845 | | unsigned char c[1]; |
|---|
| 846 | | ops_parser_content_t content; |
|---|
| 847 | | size_t v4_hashed_data_start; |
|---|
| 848 | | |
|---|
| 849 | | assert(region->length_read == 0); /* We should not have read anything so far */ |
|---|
| 850 | | |
|---|
| 851 | | memset(&content,'\0',sizeof content); |
|---|
| 852 | | |
|---|
| 853 | | v4_hashed_data_start=opt->alength; |
|---|
| 854 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 855 | | return 0; |
|---|
| 856 | | |
|---|
| 857 | | /* XXX: More V2 issues! - Ben*/ |
|---|
| 858 | | /* XXX: are there v2 signatures? - Peter */ |
|---|
| 859 | | if(c[0] == 2 || c[0] == 3) |
|---|
| 860 | | return parse_v3_signature(region,opt); |
|---|
| 861 | | else if(c[0] == 4) |
|---|
| 862 | | return parse_v4_signature(region,opt,v4_hashed_data_start); |
|---|
| 863 | | ERR1("Bad signature version (%d)",c[0]); |
|---|
| 864 | | } |
|---|
| 865 | | |
|---|
| 866 | | static int parse_compressed(ops_region_t *region,ops_parse_options_t *opt) |
|---|
| 867 | | { |
|---|
| 868 | | unsigned char c[1]; |
|---|
| 869 | | ops_parser_content_t content; |
|---|
| 870 | | |
|---|
| 871 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 872 | | return 0; |
|---|
| 873 | | |
|---|
| 874 | | C.compressed.type=c[0]; |
|---|
| 875 | | |
|---|
| 876 | | CB(OPS_PTAG_CT_COMPRESSED,&content); |
|---|
| 877 | | |
|---|
| 878 | | /* The content of a compressed data packet is more OpenPGP packets |
|---|
| 879 | | once decmppressed, so recursively handle them */ |
|---|
| 880 | | |
|---|
| 881 | | return ops_decompress(region,opt); |
|---|
| 882 | | } |
|---|
| 883 | | |
|---|
| 884 | | static int parse_one_pass(ops_region_t *region,ops_parse_options_t *opt) |
|---|
| 885 | | { |
|---|
| 886 | | unsigned char c[1]; |
|---|
| 887 | | ops_parser_content_t content; |
|---|
| 888 | | |
|---|
| 889 | | if(!ops_limited_read(&C.one_pass_signature.version,1,region,opt)) |
|---|
| 890 | | return 0; |
|---|
| 891 | | if(C.one_pass_signature.version != 3) |
|---|
| 892 | | ERR1("Bad one-pass signature version (%d)", |
|---|
| 893 | | C.one_pass_signature.version); |
|---|
| 894 | | |
|---|
| 895 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 896 | | return 0; |
|---|
| 897 | | C.one_pass_signature.sig_type=c[0]; |
|---|
| 898 | | |
|---|
| 899 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 900 | | return 0; |
|---|
| 901 | | C.one_pass_signature.hash_algorithm=c[0]; |
|---|
| 902 | | |
|---|
| 903 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 904 | | return 0; |
|---|
| 905 | | C.one_pass_signature.key_algorithm=c[0]; |
|---|
| 906 | | |
|---|
| 907 | | if(!ops_limited_read(&C.one_pass_signature.keyid,8,region,opt)) |
|---|
| 908 | | return 0; |
|---|
| 909 | | |
|---|
| 910 | | if(!ops_limited_read(c,1,region,opt)) |
|---|
| 911 | | return 0; |
|---|
| 912 | | C.one_pass_signature.nested=!!c[0]; |
|---|
| 913 | | |
|---|
| 914 | | CB(OPS_PTAG_CT_ONE_PASS_SIGNATURE,&content); |
|---|
| 915 | | |
|---|
| 916 | | return 1; |
|---|
| 917 | | } |
|---|
| | 899 | static int |
|---|
| | 900 | parse_signature (ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 901 | { |
|---|
| | 902 | unsigned char c[1]; |
|---|
| | 903 | ops_parser_content_t content; |
|---|
| | 904 | size_t v4_hashed_data_start; |
|---|
| | 905 | |
|---|
| | 906 | assert (region->length_read == 0); /* We should not have read anything so far */ |
|---|
| | 907 | |
|---|
| | 908 | memset (&content, '\0', sizeof content); |
|---|
| | 909 | |
|---|
| | 910 | v4_hashed_data_start = opt->alength; |
|---|
| | 911 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 912 | return 0; |
|---|
| | 913 | |
|---|
| | 914 | /* XXX: More V2 issues! - Ben */ |
|---|
| | 915 | /* XXX: are there v2 signatures? - Peter */ |
|---|
| | 916 | if (c[0] == 2 || c[0] == 3) |
|---|
| | 917 | return parse_v3_signature (region, opt); |
|---|
| | 918 | else if (c[0] == 4) |
|---|
| | 919 | return parse_v4_signature (region, opt, v4_hashed_data_start); |
|---|
| | 920 | ERR1 ("Bad signature version (%d)", c[0]); |
|---|
| | 921 | } |
|---|
| | 922 | |
|---|
| | 923 | static int |
|---|
| | 924 | parse_compressed (ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 925 | { |
|---|
| | 926 | unsigned char c[1]; |
|---|
| | 927 | ops_parser_content_t content; |
|---|
| | 928 | |
|---|
| | 929 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 930 | return 0; |
|---|
| | 931 | |
|---|
| | 932 | C.compressed.type = c[0]; |
|---|
| | 933 | |
|---|
| | 934 | CB (OPS_PTAG_CT_COMPRESSED, &content); |
|---|
| | 935 | |
|---|
| | 936 | /* The content of a compressed data packet is more OpenPGP packets |
|---|
| | 937 | once decmppressed, so recursively handle them */ |
|---|
| | 938 | |
|---|
| | 939 | return ops_decompress (region, opt); |
|---|
| | 940 | } |
|---|
| | 941 | |
|---|
| | 942 | static int |
|---|
| | 943 | parse_one_pass (ops_region_t * region, ops_parse_options_t * opt) |
|---|
| | 944 | { |
|---|
| | 945 | unsigned char c[1]; |
|---|
| | 946 | ops_parser_content_t content; |
|---|
| | 947 | |
|---|
| | 948 | if (!ops_limited_read (&C.one_pass_signature.version, 1, region, opt)) |
|---|
| | 949 | return 0; |
|---|
| | 950 | if (C.one_pass_signature.version != 3) |
|---|
| | 951 | ERR1 ("Bad one-pass signature version (%d)", |
|---|
| | 952 | C.one_pass_signature.version); |
|---|
| | 953 | |
|---|
| | 954 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 955 | return 0; |
|---|
| | 956 | C.one_pass_signature.sig_type = c[0]; |
|---|
| | 957 | |
|---|
| | 958 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 959 | return 0; |
|---|
| | 960 | C.one_pass_signature.hash_algorithm = c[0]; |
|---|
| | 961 | |
|---|
| | 962 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 963 | return 0; |
|---|
| | 964 | C.one_pass_signature.key_algorithm = c[0]; |
|---|
| | 965 | |
|---|
| | 966 | if (!ops_limited_read (&C.one_pass_signature.keyid, 8, region, opt)) |
|---|
| | 967 | return 0; |
|---|
| | 968 | |
|---|
| | 969 | if (!ops_limited_read (c, 1, region, opt)) |
|---|
| | 970 | return 0; |
|---|
| | 971 | C.one_pass_signature.nested = !!c[0]; |
|---|
| | 972 | |
|---|
| | 973 | CB (OPS_PTAG_CT_ONE_PASS_SIGNATURE, &content); |
|---|
| | 974 | |
|---|
| | 975 | return 1; |
|---|
| | 976 | } |
|---|
| 929 | | static int ops_parse_one_packet(ops_parse_options_t *opt) |
|---|
| 930 | | { |
|---|
| 931 | | char ptag[1]; |
|---|
| 932 | | ops_reader_ret_t ret; |
|---|
| 933 | | ops_parser_content_t content; |
|---|
| 934 | | int r; |
|---|
| 935 | | ops_region_t region; |
|---|
| 936 | | unsigned one=1; |
|---|
| 937 | | ops_boolean_t indeterminate=ops_false; |
|---|
| 938 | | |
|---|
| 939 | | ret=base_read(ptag,&one,0,opt); |
|---|
| 940 | | if(ret == OPS_R_EOF) |
|---|
| 941 | | return 0; |
|---|
| 942 | | |
|---|
| 943 | | assert(ret == OPS_R_OK); |
|---|
| 944 | | if(!(*ptag&OPS_PTAG_ALWAYS_SET)) |
|---|
| | 988 | static int |
|---|
| | 989 | ops_parse_one_packet (ops_parse_options_t * opt) |
|---|
| | 990 | { |
|---|
| | 991 | char ptag[1]; |
|---|
| | 992 | ops_reader_ret_t ret; |
|---|
| | 993 | ops_parser_content_t content; |
|---|
| | 994 | int r; |
|---|
| | 995 | ops_region_t region; |
|---|
| | 996 | unsigned one = 1; |
|---|
| | 997 | ops_boolean_t indeterminate = ops_false; |
|---|
| | 998 | |
|---|
| | 999 | ret = base_read (ptag, &one, 0, opt); |
|---|
| | 1000 | if (ret == OPS_R_EOF) |
|---|
| | 1001 | return 0; |
|---|
| | 1002 | |
|---|
| | 1003 | assert (ret == OPS_R_OK); |
|---|
| | 1004 | if (!(*ptag & OPS_PTAG_ALWAYS_SET)) |
|---|
| | 1005 | { |
|---|
| | 1006 | C.error.error = "Format error (ptag bit not set)"; |
|---|
| | 1007 | CB (OPS_PARSER_ERROR, &content); |
|---|
| | 1008 | return 0; |
|---|
| | 1009 | } |
|---|
| | 1010 | C.ptag.new_format = !!(*ptag & OPS_PTAG_NEW_FORMAT); |
|---|
| | 1011 | if (C.ptag.new_format) |
|---|
| | 1012 | { |
|---|
| | 1013 | C.ptag.content_tag = *ptag & OPS_PTAG_NF_CONTENT_TAG_MASK; |
|---|
| | 1014 | C.ptag.length_type = 0; |
|---|
| | 1015 | } |
|---|
| | 1016 | else |
|---|
| | 1017 | { |
|---|
| | 1018 | C.ptag.content_tag = (*ptag & OPS_PTAG_OF_CONTENT_TAG_MASK) |
|---|
| | 1019 | >> OPS_PTAG_OF_CONTENT_TAG_SHIFT; |
|---|
| | 1020 | C.ptag.length_type = *ptag & OPS_PTAG_OF_LENGTH_TYPE_MASK; |
|---|
| | 1021 | switch (C.ptag.length_type) |
|---|
| 950 | | C.ptag.new_format=!!(*ptag&OPS_PTAG_NEW_FORMAT); |
|---|
| 951 | | if(C.ptag.new_format) |
|---|
| 952 | | { |
|---|
| 953 | | C.ptag.content_tag=*ptag&OPS_PTAG_NF_CONTENT_TAG_MASK; |
|---|
| 954 | | C.ptag.length_type=0; |
|---|
| 955 | | } |
|---|
| 956 | | else |
|---|
| 957 | | { |
|---|
| 958 | | C.ptag.content_tag=(*ptag&OPS_PTAG_OF_CONTENT_TAG_MASK) |
|---|
| 959 | | >> OPS_PTAG_OF_CONTENT_TAG_SHIFT; |
|---|
| 960 | | C.ptag.length_type=*ptag&OPS_PTAG_OF_LENGTH_TYPE_MASK; |
|---|
| 961 | | switch(C.ptag.length_type) |
|---|
| 962 | | { |
|---|
| 963 | | case OPS_PTAG_OF_LT_ONE_BYTE: |
|---|
| 964 | | ret=read_scalar(&C.ptag.length,1,opt); |
|---|
| 965 | | assert(ret == OPS_R_OK); |
|---|
| 966 | | break; |
|---|
| 967 | | |
|---|
| 968 | | case OPS_PTAG_OF_LT_TWO_BYTE: |
|---|
| 969 | | ret=read_scalar(&C.ptag.length,2,opt); |
|---|
| 970 | | assert(ret == OPS_R_OK); |
|---|
| 971 | | break; |
|---|
| 972 | | |
|---|
| 973 | | case OPS_PTAG_OF_LT_FOUR_BYTE: |
|---|
| 974 | | ret=read_scalar(&C.ptag.length,4,opt); |
|---|
| 975 | | assert(ret == OPS_R_OK); |
|---|
| 976 | | break; |
|---|
| 977 | | |
|---|
| 978 | | case OPS_PTAG_OF_LT_INDETERMINATE: |
|---|
| 979 | | C.ptag.length=0; |
|---|
| 980 | | indeterminate=ops_true; |
|---|
| 981 | | break; |
|---|
| 982 | | } |
|---|
| 983 | | } |
|---|
| 984 | | |
|---|
| 985 | | CB(OPS_PARSER_PTAG,&content); |
|---|
| 986 | | |
|---|
| 987 | | init_subregion(®ion,NULL); |
|---|
| 988 | | region.length=C.ptag.length; |
|---|
| 989 | | region.indeterminate=indeterminate; |
|---|
| 990 | | switch(C.ptag.content_tag) |
|---|
| 991 | | { |
|---|
| | 1043 | } |
|---|
| | 1044 | |
|---|
| | 1045 | CB (OPS_PARSER_PTAG, &content); |
|---|
| | 1046 | |
|---|
| | 1047 | init_subregion (®ion, NULL); |
|---|
| | 1048 | region.length = C.ptag.length; |
|---|
| | 1049 | region.indeterminate = indeterminate; |
|---|
| | 1050 | switch (C.ptag.content_tag) |
|---|
| | 1051 | { |
|---|