1 /* 2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "hx_locl.h" 35 36 #include <hxtool-commands.h> 37 #include <sl.h> 38 #include <rtbl.h> 39 #include <parse_time.h> 40 41 static hx509_context context; 42 43 static char *stat_file_string; 44 static int version_flag; 45 static int help_flag; 46 47 struct getargs args[] = { 48 { "statistic-file", 0, arg_string, &stat_file_string, NULL, NULL }, 49 { "version", 0, arg_flag, &version_flag, NULL, NULL }, 50 { "help", 0, arg_flag, &help_flag, NULL, NULL } 51 }; 52 int num_args = sizeof(args) / sizeof(args[0]); 53 54 static void 55 usage(int code) 56 { 57 arg_printusage(args, num_args, NULL, "command"); 58 printf("Use \"%s help\" to get more help\n", getprogname()); 59 exit(code); 60 } 61 62 /* 63 * 64 */ 65 66 static void 67 lock_strings(hx509_lock lock, getarg_strings *pass) 68 { 69 int i; 70 for (i = 0; i < pass->num_strings; i++) { 71 int ret = hx509_lock_command_string(lock, pass->strings[i]); 72 if (ret) 73 errx(1, "hx509_lock_command_string: %s: %d", 74 pass->strings[i], ret); 75 } 76 } 77 78 /* 79 * 80 */ 81 82 static void 83 certs_strings(hx509_context contextp, const char *type, hx509_certs certs, 84 hx509_lock lock, const getarg_strings *s) 85 { 86 int i, ret; 87 88 for (i = 0; i < s->num_strings; i++) { 89 ret = hx509_certs_append(contextp, certs, lock, s->strings[i]); 90 if (ret) 91 hx509_err(contextp, 1, ret, 92 "hx509_certs_append: %s %s", type, s->strings[i]); 93 } 94 } 95 96 /* 97 * 98 */ 99 100 static void 101 parse_oid(const char *str, const heim_oid *def, heim_oid *oid) 102 { 103 int ret; 104 if (str) 105 ret = der_parse_heim_oid (str, " .", oid); 106 else 107 ret = der_copy_oid(def, oid); 108 if (ret) 109 errx(1, "parse_oid failed for: %s", str ? str : "default oid"); 110 } 111 112 /* 113 * 114 */ 115 116 static void 117 peer_strings(hx509_context contextp, 118 hx509_peer_info *peer, 119 const getarg_strings *s) 120 { 121 AlgorithmIdentifier *val; 122 int ret, i; 123 124 ret = hx509_peer_info_alloc(contextp, peer); 125 if (ret) 126 hx509_err(contextp, 1, ret, "hx509_peer_info_alloc"); 127 128 val = calloc(s->num_strings, sizeof(*val)); 129 if (val == NULL) 130 err(1, "malloc"); 131 132 for (i = 0; i < s->num_strings; i++) 133 parse_oid(s->strings[i], NULL, &val[i].algorithm); 134 135 ret = hx509_peer_info_set_cms_algs(contextp, *peer, val, s->num_strings); 136 if (ret) 137 hx509_err(contextp, 1, ret, "hx509_peer_info_set_cms_algs"); 138 139 for (i = 0; i < s->num_strings; i++) 140 free_AlgorithmIdentifier(&val[i]); 141 free(val); 142 } 143 144 /* 145 * 146 */ 147 148 struct pem_data { 149 heim_octet_string *os; 150 int detached_data; 151 }; 152 153 static int 154 pem_reader(hx509_context contextp, const char *type, 155 const hx509_pem_header *headers, 156 const void *data , size_t length, void *ctx) 157 { 158 struct pem_data *p = (struct pem_data *)ctx; 159 const char *h; 160 161 p->os->data = malloc(length); 162 if (p->os->data == NULL) 163 return ENOMEM; 164 memcpy(p->os->data, data, length); 165 p->os->length = length; 166 167 h = hx509_pem_find_header(headers, "Content-disposition"); 168 if (h && strcasecmp(h, "detached") == 0) 169 p->detached_data = 1; 170 171 return 0; 172 } 173 174 /* 175 * 176 */ 177 178 int 179 cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) 180 { 181 hx509_verify_ctx ctx = NULL; 182 heim_oid type; 183 heim_octet_string c, co, signeddata, *sd = NULL; 184 hx509_certs store = NULL; 185 hx509_certs signers = NULL; 186 hx509_certs anchors = NULL; 187 hx509_lock lock; 188 int ret, flags = 0; 189 190 size_t sz; 191 void *p = NULL; 192 193 if (opt->missing_revoke_flag) 194 hx509_context_set_missing_revoke(context, 1); 195 196 hx509_lock_init(context, &lock); 197 lock_strings(lock, &opt->pass_strings); 198 199 ret = hx509_verify_init_ctx(context, &ctx); 200 if (ret) 201 hx509_err(context, 1, ret, "hx509_verify_init_ctx"); 202 203 ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors); 204 if (ret) 205 hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 206 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); 207 if (ret) 208 hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 209 210 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); 211 certs_strings(context, "store", store, lock, &opt->certificate_strings); 212 213 if (opt->pem_flag) { 214 struct pem_data pd; 215 FILE *f; 216 217 pd.os = &co; 218 pd.detached_data = 0; 219 220 f = fopen(argv[0], "r"); 221 if (f == NULL) 222 err(1, "Failed to open file %s", argv[0]); 223 224 ret = hx509_pem_read(context, f, pem_reader, &pd); 225 fclose(f); 226 if (ret) 227 errx(1, "PEM reader failed: %d", ret); 228 229 if (pd.detached_data && opt->signed_content_string == NULL) { 230 char *r = strrchr(argv[0], '.'); 231 if (r && strcasecmp(r, ".pem") == 0) { 232 char *s = strdup(argv[0]); 233 if (s == NULL) 234 errx(1, "malloc: out of memory"); 235 s[r - argv[0]] = '\0'; 236 ret = _hx509_map_file_os(s, &signeddata); 237 if (ret) 238 errx(1, "map_file: %s: %d", s, ret); 239 free(s); 240 sd = &signeddata; 241 } 242 } 243 244 } else { 245 ret = rk_undumpdata(argv[0], &p, &sz); 246 if (ret) 247 err(1, "map_file: %s: %d", argv[0], ret); 248 249 co.data = p; 250 co.length = sz; 251 } 252 253 if (opt->signed_content_string) { 254 ret = _hx509_map_file_os(opt->signed_content_string, &signeddata); 255 if (ret) 256 errx(1, "map_file: %s: %d", opt->signed_content_string, ret); 257 sd = &signeddata; 258 } 259 260 if (opt->content_info_flag) { 261 heim_octet_string uwco; 262 heim_oid oid; 263 264 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL); 265 if (ret) 266 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); 267 268 if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_signedData) != 0) 269 errx(1, "Content is not SignedData"); 270 der_free_oid(&oid); 271 272 if (p == NULL) 273 der_free_octet_string(&co); 274 else { 275 rk_xfree(p); 276 p = NULL; 277 } 278 co = uwco; 279 } 280 281 hx509_verify_attach_anchors(ctx, anchors); 282 283 if (!opt->signer_allowed_flag) 284 flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER; 285 if (opt->allow_wrong_oid_flag) 286 flags |= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; 287 288 ret = hx509_cms_verify_signed(context, ctx, flags, co.data, co.length, sd, 289 store, &type, &c, &signers); 290 if (p != co.data) 291 der_free_octet_string(&co); 292 else 293 rk_xfree(p); 294 if (ret) 295 hx509_err(context, 1, ret, "hx509_cms_verify_signed"); 296 297 { 298 char *str; 299 der_print_heim_oid(&type, '.', &str); 300 printf("type: %s\n", str); 301 free(str); 302 der_free_oid(&type); 303 } 304 if (signers == NULL) { 305 printf("unsigned\n"); 306 } else { 307 printf("signers:\n"); 308 hx509_certs_iter_f(context, signers, hx509_ci_print_names, stdout); 309 } 310 311 hx509_verify_destroy_ctx(ctx); 312 313 hx509_certs_free(&store); 314 hx509_certs_free(&signers); 315 hx509_certs_free(&anchors); 316 317 hx509_lock_free(lock); 318 319 if (argc > 1) { 320 ret = _hx509_write_file(argv[1], c.data, c.length); 321 if (ret) 322 errx(1, "hx509_write_file: %d", ret); 323 } 324 325 der_free_octet_string(&c); 326 327 if (sd) 328 _hx509_unmap_file_os(sd); 329 330 return 0; 331 } 332 333 static int 334 print_signer(hx509_context contextp, void *ctx, hx509_cert cert) 335 { 336 hx509_pem_header **header = ctx; 337 char *signer_name = NULL; 338 hx509_name name; 339 int ret; 340 341 ret = hx509_cert_get_subject(cert, &name); 342 if (ret) 343 errx(1, "hx509_cert_get_subject"); 344 345 ret = hx509_name_to_string(name, &signer_name); 346 hx509_name_free(&name); 347 if (ret) 348 errx(1, "hx509_name_to_string"); 349 350 hx509_pem_add_header(header, "Signer", signer_name); 351 352 free(signer_name); 353 return 0; 354 } 355 356 int 357 cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) 358 { 359 heim_oid contentType; 360 hx509_peer_info peer = NULL; 361 heim_octet_string o; 362 hx509_query *q; 363 hx509_lock lock; 364 hx509_certs store, pool, anchors, signer = NULL; 365 size_t sz; 366 void *p; 367 int ret, flags = 0; 368 char *infile, *outfile = NULL; 369 370 memset(&contentType, 0, sizeof(contentType)); 371 372 infile = argv[0]; 373 374 if (argc < 2) { 375 asprintf(&outfile, "%s.%s", infile, 376 opt->pem_flag ? "pem" : "cms-signeddata"); 377 if (outfile == NULL) 378 errx(1, "out of memory"); 379 } else 380 outfile = argv[1]; 381 382 hx509_lock_init(context, &lock); 383 lock_strings(lock, &opt->pass_strings); 384 385 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); 386 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 387 ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool); 388 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 389 390 certs_strings(context, "store", store, lock, &opt->certificate_strings); 391 certs_strings(context, "pool", pool, lock, &opt->pool_strings); 392 393 if (opt->anchors_strings.num_strings) { 394 ret = hx509_certs_init(context, "MEMORY:cert-anchors", 395 0, NULL, &anchors); 396 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 397 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); 398 } else 399 anchors = NULL; 400 401 if (opt->detached_signature_flag) 402 flags |= HX509_CMS_SIGNATURE_DETACHED; 403 if (opt->id_by_name_flag) 404 flags |= HX509_CMS_SIGNATURE_ID_NAME; 405 if (!opt->signer_flag) { 406 flags |= HX509_CMS_SIGNATURE_NO_SIGNER; 407 408 } 409 410 if (opt->signer_flag) { 411 ret = hx509_query_alloc(context, &q); 412 if (ret) 413 errx(1, "hx509_query_alloc: %d", ret); 414 415 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 416 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); 417 418 if (opt->signer_string) 419 hx509_query_match_friendly_name(q, opt->signer_string); 420 421 ret = hx509_certs_filter(context, store, q, &signer); 422 hx509_query_free(context, q); 423 if (ret) 424 hx509_err(context, 1, ret, "hx509_certs_find"); 425 } 426 if (!opt->embedded_certs_flag) 427 flags |= HX509_CMS_SIGNATURE_NO_CERTS; 428 if (opt->embed_leaf_only_flag) 429 flags |= HX509_CMS_SIGNATURE_LEAF_ONLY; 430 431 ret = rk_undumpdata(infile, &p, &sz); 432 if (ret) 433 err(1, "map_file: %s: %d", infile, ret); 434 435 if (opt->peer_alg_strings.num_strings) 436 peer_strings(context, &peer, &opt->peer_alg_strings); 437 438 parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType); 439 440 ret = hx509_cms_create_signed(context, 441 flags, 442 &contentType, 443 p, 444 sz, 445 NULL, 446 signer, 447 peer, 448 anchors, 449 pool, 450 &o); 451 if (ret) 452 hx509_err(context, 1, ret, "hx509_cms_create_signed: %d", ret); 453 454 hx509_certs_free(&anchors); 455 hx509_certs_free(&pool); 456 hx509_certs_free(&store); 457 rk_xfree(p); 458 hx509_lock_free(lock); 459 hx509_peer_info_free(peer); 460 der_free_oid(&contentType); 461 462 if (opt->content_info_flag) { 463 heim_octet_string wo; 464 465 ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &o, &wo); 466 if (ret) 467 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); 468 469 der_free_octet_string(&o); 470 o = wo; 471 } 472 473 if (opt->pem_flag) { 474 hx509_pem_header *header = NULL; 475 FILE *f; 476 477 hx509_pem_add_header(&header, "Content-disposition", 478 opt->detached_signature_flag ? 479 "detached" : "inline"); 480 if (signer) { 481 ret = hx509_certs_iter_f(context, signer, print_signer, header); 482 if (ret) 483 hx509_err(context, 1, ret, "print signer"); 484 } 485 486 f = fopen(outfile, "w"); 487 if (f == NULL) 488 err(1, "open %s", outfile); 489 490 ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f, 491 o.data, o.length); 492 fclose(f); 493 hx509_pem_free_header(header); 494 if (ret) 495 errx(1, "hx509_pem_write: %d", ret); 496 497 } else { 498 ret = _hx509_write_file(outfile, o.data, o.length); 499 if (ret) 500 errx(1, "hx509_write_file: %d", ret); 501 } 502 503 hx509_certs_free(&signer); 504 free(o.data); 505 506 return 0; 507 } 508 509 int 510 cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv) 511 { 512 heim_oid contentType = { 0, NULL }; 513 heim_octet_string o, co; 514 hx509_certs certs; 515 size_t sz; 516 void *p; 517 int ret; 518 hx509_lock lock; 519 int flags = 0; 520 521 hx509_lock_init(context, &lock); 522 lock_strings(lock, &opt->pass_strings); 523 524 ret = rk_undumpdata(argv[0], &p, &sz); 525 if (ret) 526 err(1, "map_file: %s: %d", argv[0], ret); 527 528 co.data = p; 529 co.length = sz; 530 531 if (opt->content_info_flag) { 532 heim_octet_string uwco; 533 heim_oid oid; 534 535 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL); 536 if (ret) 537 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); 538 539 if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_envelopedData) != 0) 540 errx(1, "Content is not SignedData"); 541 der_free_oid(&oid); 542 543 co = uwco; 544 } 545 546 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); 547 if (ret) 548 errx(1, "hx509_certs_init: MEMORY: %d", ret); 549 550 certs_strings(context, "store", certs, lock, &opt->certificate_strings); 551 552 if (opt->allow_weak_crypto_flag) 553 flags |= HX509_CMS_UE_ALLOW_WEAK; 554 555 ret = hx509_cms_unenvelope(context, certs, flags, co.data, co.length, 556 NULL, 0, &contentType, &o); 557 if (co.data != p) 558 der_free_octet_string(&co); 559 if (ret) 560 hx509_err(context, 1, ret, "hx509_cms_unenvelope"); 561 562 rk_xfree(p); 563 hx509_lock_free(lock); 564 hx509_certs_free(&certs); 565 der_free_oid(&contentType); 566 567 ret = _hx509_write_file(argv[1], o.data, o.length); 568 if (ret) 569 errx(1, "hx509_write_file: %d", ret); 570 571 der_free_octet_string(&o); 572 573 return 0; 574 } 575 576 int 577 cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) 578 { 579 heim_oid contentType; 580 heim_octet_string o; 581 const heim_oid *enctype = NULL; 582 hx509_query *q; 583 hx509_certs certs; 584 hx509_cert cert; 585 int ret; 586 size_t sz; 587 void *p; 588 hx509_lock lock; 589 int flags = 0; 590 591 memset(&contentType, 0, sizeof(contentType)); 592 593 hx509_lock_init(context, &lock); 594 lock_strings(lock, &opt->pass_strings); 595 596 ret = rk_undumpdata(argv[0], &p, &sz); 597 if (ret) 598 err(1, "map_file: %s: %d", argv[0], ret); 599 600 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); 601 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 602 603 certs_strings(context, "store", certs, lock, &opt->certificate_strings); 604 605 if (opt->allow_weak_crypto_flag) 606 flags |= HX509_CMS_EV_ALLOW_WEAK; 607 608 if (opt->encryption_type_string) { 609 enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string); 610 if (enctype == NULL) 611 errx(1, "encryption type: %s no found", 612 opt->encryption_type_string); 613 } 614 615 ret = hx509_query_alloc(context, &q); 616 if (ret) 617 errx(1, "hx509_query_alloc: %d", ret); 618 619 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT); 620 621 ret = hx509_certs_find(context, certs, q, &cert); 622 hx509_query_free(context, q); 623 if (ret) 624 errx(1, "hx509_certs_find: %d", ret); 625 626 parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType); 627 628 ret = hx509_cms_envelope_1(context, flags, cert, p, sz, enctype, 629 &contentType, &o); 630 if (ret) 631 errx(1, "hx509_cms_envelope_1: %d", ret); 632 633 hx509_cert_free(cert); 634 hx509_certs_free(&certs); 635 rk_xfree(p); 636 der_free_oid(&contentType); 637 638 if (opt->content_info_flag) { 639 heim_octet_string wo; 640 641 ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_envelopedData, &o, &wo); 642 if (ret) 643 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); 644 645 der_free_octet_string(&o); 646 o = wo; 647 } 648 649 hx509_lock_free(lock); 650 651 ret = _hx509_write_file(argv[1], o.data, o.length); 652 if (ret) 653 errx(1, "hx509_write_file: %d", ret); 654 655 der_free_octet_string(&o); 656 657 return 0; 658 } 659 660 static void 661 print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose) 662 { 663 const char *fn; 664 int ret; 665 666 fn = hx509_cert_get_friendly_name(cert); 667 if (fn) 668 printf(" friendly name: %s\n", fn); 669 printf(" private key: %s\n", 670 _hx509_cert_private_key(cert) ? "yes" : "no"); 671 672 ret = hx509_print_cert(hxcontext, cert, NULL); 673 if (ret) 674 errx(1, "failed to print cert"); 675 676 if (verbose) { 677 hx509_validate_ctx vctx; 678 679 hx509_validate_ctx_init(hxcontext, &vctx); 680 hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout); 681 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE); 682 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE); 683 684 hx509_validate_cert(hxcontext, vctx, cert); 685 686 hx509_validate_ctx_free(vctx); 687 } 688 } 689 690 691 struct print_s { 692 int counter; 693 int verbose; 694 }; 695 696 static int 697 print_f(hx509_context hxcontext, void *ctx, hx509_cert cert) 698 { 699 struct print_s *s = ctx; 700 701 printf("cert: %d\n", s->counter++); 702 print_certificate(context, cert, s->verbose); 703 704 return 0; 705 } 706 707 int 708 pcert_print(struct print_options *opt, int argc, char **argv) 709 { 710 hx509_certs certs; 711 hx509_lock lock; 712 struct print_s s; 713 714 s.counter = 0; 715 s.verbose = opt->content_flag; 716 717 hx509_lock_init(context, &lock); 718 lock_strings(lock, &opt->pass_strings); 719 720 while(argc--) { 721 int ret; 722 ret = hx509_certs_init(context, argv[0], 0, lock, &certs); 723 if (ret) { 724 if (opt->never_fail_flag) { 725 printf("ignoreing failure: %d\n", ret); 726 continue; 727 } 728 hx509_err(context, 1, ret, "hx509_certs_init"); 729 } 730 if (opt->info_flag) 731 hx509_certs_info(context, certs, NULL, NULL); 732 hx509_certs_iter_f(context, certs, print_f, &s); 733 hx509_certs_free(&certs); 734 argv++; 735 } 736 737 hx509_lock_free(lock); 738 739 return 0; 740 } 741 742 743 static int 744 validate_f(hx509_context hxcontext, void *ctx, hx509_cert c) 745 { 746 hx509_validate_cert(hxcontext, ctx, c); 747 return 0; 748 } 749 750 int 751 pcert_validate(struct validate_options *opt, int argc, char **argv) 752 { 753 hx509_validate_ctx ctx; 754 hx509_certs certs; 755 hx509_lock lock; 756 757 hx509_lock_init(context, &lock); 758 lock_strings(lock, &opt->pass_strings); 759 760 hx509_validate_ctx_init(context, &ctx); 761 hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout); 762 hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VALIDATE); 763 764 while(argc--) { 765 int ret; 766 ret = hx509_certs_init(context, argv[0], 0, lock, &certs); 767 if (ret) 768 errx(1, "hx509_certs_init: %d", ret); 769 hx509_certs_iter_f(context, certs, validate_f, ctx); 770 hx509_certs_free(&certs); 771 argv++; 772 } 773 hx509_validate_ctx_free(ctx); 774 775 hx509_lock_free(lock); 776 777 return 0; 778 } 779 780 int 781 certificate_copy(struct certificate_copy_options *opt, int argc, char **argv) 782 { 783 hx509_certs certs; 784 hx509_lock inlock, outlock = NULL; 785 int ret; 786 787 hx509_lock_init(context, &inlock); 788 lock_strings(inlock, &opt->in_pass_strings); 789 790 if (opt->out_pass_string) { 791 hx509_lock_init(context, &outlock); 792 ret = hx509_lock_command_string(outlock, opt->out_pass_string); 793 if (ret) 794 errx(1, "hx509_lock_command_string: %s: %d", 795 opt->out_pass_string, ret); 796 } 797 798 ret = hx509_certs_init(context, argv[argc - 1], 799 HX509_CERTS_CREATE, inlock, &certs); 800 if (ret) 801 hx509_err(context, 1, ret, "hx509_certs_init"); 802 803 while(argc-- > 1) { 804 int retx; 805 retx = hx509_certs_append(context, certs, inlock, argv[0]); 806 if (retx) 807 hx509_err(context, 1, retx, "hx509_certs_append"); 808 argv++; 809 } 810 811 ret = hx509_certs_store(context, certs, 0, outlock); 812 if (ret) 813 hx509_err(context, 1, ret, "hx509_certs_store"); 814 815 hx509_certs_free(&certs); 816 hx509_lock_free(inlock); 817 hx509_lock_free(outlock); 818 819 return 0; 820 } 821 822 struct verify { 823 hx509_verify_ctx ctx; 824 hx509_certs chain; 825 const char *hostname; 826 int errors; 827 int count; 828 }; 829 830 static int 831 verify_f(hx509_context hxcontext, void *ctx, hx509_cert c) 832 { 833 struct verify *v = ctx; 834 int ret; 835 836 ret = hx509_verify_path(hxcontext, v->ctx, c, v->chain); 837 if (ret) { 838 char *s = hx509_get_error_string(hxcontext, ret); 839 printf("verify_path: %s: %d\n", s, ret); 840 hx509_free_error_string(s); 841 v->errors++; 842 } else { 843 v->count++; 844 printf("path ok\n"); 845 } 846 847 if (v->hostname) { 848 ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME, 849 v->hostname, NULL, 0); 850 if (ret) { 851 printf("verify_hostname: %d\n", ret); 852 v->errors++; 853 } 854 } 855 856 return 0; 857 } 858 859 int 860 pcert_verify(struct verify_options *opt, int argc, char **argv) 861 { 862 hx509_certs anchors, chain, certs; 863 hx509_revoke_ctx revoke_ctx; 864 hx509_verify_ctx ctx; 865 struct verify v; 866 int ret; 867 868 memset(&v, 0, sizeof(v)); 869 870 if (opt->missing_revoke_flag) 871 hx509_context_set_missing_revoke(context, 1); 872 873 ret = hx509_verify_init_ctx(context, &ctx); 874 if (ret) 875 hx509_err(context, 1, ret, "hx509_verify_init_ctx"); 876 ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors); 877 if (ret) 878 hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 879 ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain); 880 if (ret) 881 hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 882 ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); 883 if (ret) 884 hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 885 886 if (opt->allow_proxy_certificate_flag) 887 hx509_verify_set_proxy_certificate(ctx, 1); 888 889 if (opt->time_string) { 890 const char *p; 891 struct tm tm; 892 time_t t; 893 894 memset(&tm, 0, sizeof(tm)); 895 896 p = strptime (opt->time_string, "%Y-%m-%d", &tm); 897 if (p == NULL) 898 errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d", 899 opt->time_string); 900 901 t = tm2time (tm, 0); 902 903 hx509_verify_set_time(ctx, t); 904 } 905 906 if (opt->hostname_string) 907 v.hostname = opt->hostname_string; 908 if (opt->max_depth_integer) 909 hx509_verify_set_max_depth(ctx, opt->max_depth_integer); 910 911 ret = hx509_revoke_init(context, &revoke_ctx); 912 if (ret) 913 errx(1, "hx509_revoke_init: %d", ret); 914 915 while(argc--) { 916 char *s = *argv++; 917 918 if (strncmp(s, "chain:", 6) == 0) { 919 s += 6; 920 921 ret = hx509_certs_append(context, chain, NULL, s); 922 if (ret) 923 hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", s, ret); 924 925 } else if (strncmp(s, "anchor:", 7) == 0) { 926 s += 7; 927 928 ret = hx509_certs_append(context, anchors, NULL, s); 929 if (ret) 930 hx509_err(context, 1, ret, "hx509_certs_append: anchor: %s: %d", s, ret); 931 932 } else if (strncmp(s, "cert:", 5) == 0) { 933 s += 5; 934 935 ret = hx509_certs_append(context, certs, NULL, s); 936 if (ret) 937 hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d", 938 s, ret); 939 940 } else if (strncmp(s, "crl:", 4) == 0) { 941 s += 4; 942 943 ret = hx509_revoke_add_crl(context, revoke_ctx, s); 944 if (ret) 945 errx(1, "hx509_revoke_add_crl: %s: %d", s, ret); 946 947 } else if (strncmp(s, "ocsp:", 4) == 0) { 948 s += 5; 949 950 ret = hx509_revoke_add_ocsp(context, revoke_ctx, s); 951 if (ret) 952 errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret); 953 954 } else { 955 errx(1, "unknown option to verify: `%s'\n", s); 956 } 957 } 958 959 hx509_verify_attach_anchors(ctx, anchors); 960 hx509_verify_attach_revoke(ctx, revoke_ctx); 961 962 v.ctx = ctx; 963 v.chain = chain; 964 965 hx509_certs_iter_f(context, certs, verify_f, &v); 966 967 hx509_verify_destroy_ctx(ctx); 968 969 hx509_certs_free(&certs); 970 hx509_certs_free(&chain); 971 hx509_certs_free(&anchors); 972 973 hx509_revoke_free(&revoke_ctx); 974 975 976 if (v.count == 0) { 977 printf("no certs verify at all\n"); 978 return 1; 979 } 980 981 if (v.errors) { 982 printf("failed verifing %d checks\n", v.errors); 983 return 1; 984 } 985 986 return 0; 987 } 988 989 int 990 query(struct query_options *opt, int argc, char **argv) 991 { 992 hx509_lock lock; 993 hx509_query *q; 994 hx509_certs certs; 995 hx509_cert c; 996 int ret; 997 998 ret = hx509_query_alloc(context, &q); 999 if (ret) 1000 errx(1, "hx509_query_alloc: %d", ret); 1001 1002 hx509_lock_init(context, &lock); 1003 lock_strings(lock, &opt->pass_strings); 1004 1005 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); 1006 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 1007 1008 while (argc > 0) { 1009 1010 ret = hx509_certs_append(context, certs, lock, argv[0]); 1011 if (ret) 1012 errx(1, "hx509_certs_append: %s: %d", argv[0], ret); 1013 1014 argc--; 1015 argv++; 1016 } 1017 1018 if (opt->friendlyname_string) 1019 hx509_query_match_friendly_name(q, opt->friendlyname_string); 1020 1021 if (opt->eku_string) { 1022 heim_oid oid; 1023 1024 parse_oid(opt->eku_string, NULL, &oid); 1025 1026 ret = hx509_query_match_eku(q, &oid); 1027 if (ret) 1028 errx(1, "hx509_query_match_eku: %d", ret); 1029 der_free_oid(&oid); 1030 } 1031 1032 if (opt->private_key_flag) 1033 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1034 1035 if (opt->keyEncipherment_flag) 1036 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT); 1037 1038 if (opt->digitalSignature_flag) 1039 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); 1040 1041 if (opt->expr_string) 1042 hx509_query_match_expr(context, q, opt->expr_string); 1043 1044 ret = hx509_certs_find(context, certs, q, &c); 1045 hx509_query_free(context, q); 1046 if (ret) 1047 printf("no match found (%d)\n", ret); 1048 else { 1049 printf("match found\n"); 1050 if (opt->print_flag) 1051 print_certificate(context, c, 0); 1052 } 1053 1054 hx509_cert_free(c); 1055 hx509_certs_free(&certs); 1056 1057 hx509_lock_free(lock); 1058 1059 return ret; 1060 } 1061 1062 int 1063 ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv) 1064 { 1065 hx509_certs reqcerts, pool; 1066 heim_octet_string req, nonce_data, *nonce = &nonce_data; 1067 hx509_lock lock; 1068 int i, ret; 1069 char *file; 1070 const char *url = "/"; 1071 1072 memset(&nonce, 0, sizeof(nonce)); 1073 1074 hx509_lock_init(context, &lock); 1075 lock_strings(lock, &opt->pass_strings); 1076 1077 /* no nonce */ 1078 if (!opt->nonce_flag) 1079 nonce = NULL; 1080 1081 if (opt->url_path_string) 1082 url = opt->url_path_string; 1083 1084 ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool); 1085 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 1086 1087 certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings); 1088 1089 file = argv[0]; 1090 1091 ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts); 1092 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 1093 1094 for (i = 1; i < argc; i++) { 1095 ret = hx509_certs_append(context, reqcerts, lock, argv[i]); 1096 if (ret) 1097 errx(1, "hx509_certs_append: req: %s: %d", argv[i], ret); 1098 } 1099 1100 ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce); 1101 if (ret) 1102 errx(1, "hx509_ocsp_request: req: %d", ret); 1103 1104 { 1105 FILE *f; 1106 1107 f = fopen(file, "w"); 1108 if (f == NULL) 1109 abort(); 1110 1111 fprintf(f, 1112 "POST %s HTTP/1.0\r\n" 1113 "Content-Type: application/ocsp-request\r\n" 1114 "Content-Length: %ld\r\n" 1115 "\r\n", 1116 url, 1117 (unsigned long)req.length); 1118 fwrite(req.data, req.length, 1, f); 1119 fclose(f); 1120 } 1121 1122 if (nonce) 1123 der_free_octet_string(nonce); 1124 1125 hx509_certs_free(&reqcerts); 1126 hx509_certs_free(&pool); 1127 1128 return 0; 1129 } 1130 1131 int 1132 ocsp_print(struct ocsp_print_options *opt, int argc, char **argv) 1133 { 1134 hx509_revoke_ocsp_print(context, argv[0], stdout); 1135 return 0; 1136 } 1137 1138 /* 1139 * 1140 */ 1141 1142 static int 1143 verify_o(hx509_context hxcontext, void *ctx, hx509_cert c) 1144 { 1145 heim_octet_string *os = ctx; 1146 time_t expiration; 1147 int ret; 1148 1149 ret = hx509_ocsp_verify(context, 0, c, 0, 1150 os->data, os->length, &expiration); 1151 if (ret) { 1152 char *s = hx509_get_error_string(hxcontext, ret); 1153 printf("ocsp_verify: %s: %d\n", s, ret); 1154 hx509_free_error_string(s); 1155 } else 1156 printf("expire: %d\n", (int)expiration); 1157 1158 return ret; 1159 } 1160 1161 1162 int 1163 ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv) 1164 { 1165 hx509_lock lock; 1166 hx509_certs certs; 1167 int ret, i; 1168 heim_octet_string os; 1169 1170 hx509_lock_init(context, &lock); 1171 1172 if (opt->ocsp_file_string == NULL) 1173 errx(1, "no ocsp file given"); 1174 1175 ret = _hx509_map_file_os(opt->ocsp_file_string, &os); 1176 if (ret) 1177 err(1, "map_file: %s: %d", argv[0], ret); 1178 1179 ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs); 1180 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 1181 1182 for (i = 0; i < argc; i++) { 1183 ret = hx509_certs_append(context, certs, lock, argv[i]); 1184 if (ret) 1185 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); 1186 } 1187 1188 ret = hx509_certs_iter_f(context, certs, verify_o, &os); 1189 1190 hx509_certs_free(&certs); 1191 _hx509_unmap_file_os(&os); 1192 hx509_lock_free(lock); 1193 1194 return ret; 1195 } 1196 1197 static int 1198 read_private_key(const char *fn, hx509_private_key *key) 1199 { 1200 hx509_private_key *keys; 1201 hx509_certs certs; 1202 int ret; 1203 1204 *key = NULL; 1205 1206 ret = hx509_certs_init(context, fn, 0, NULL, &certs); 1207 if (ret) 1208 hx509_err(context, 1, ret, "hx509_certs_init: %s", fn); 1209 1210 ret = _hx509_certs_keys_get(context, certs, &keys); 1211 hx509_certs_free(&certs); 1212 if (ret) 1213 hx509_err(context, 1, ret, "hx509_certs_keys_get"); 1214 if (keys[0] == NULL) 1215 errx(1, "no keys in key store: %s", fn); 1216 1217 *key = _hx509_private_key_ref(keys[0]); 1218 _hx509_certs_keys_free(context, keys); 1219 1220 return 0; 1221 } 1222 1223 static void 1224 get_key(const char *fn, const char *type, int optbits, 1225 hx509_private_key *signer) 1226 { 1227 int ret; 1228 1229 if (type) { 1230 BIGNUM *e; 1231 RSA *rsa; 1232 unsigned char *p0, *p; 1233 size_t len; 1234 int bits = 1024; 1235 1236 if (fn == NULL) 1237 errx(1, "no key argument, don't know here to store key"); 1238 1239 if (strcasecmp(type, "rsa") != 0) 1240 errx(1, "can only handle rsa keys for now"); 1241 1242 e = BN_new(); 1243 BN_set_word(e, 0x10001); 1244 1245 if (optbits) 1246 bits = optbits; 1247 1248 rsa = RSA_new(); 1249 if(rsa == NULL) 1250 errx(1, "RSA_new failed"); 1251 1252 ret = RSA_generate_key_ex(rsa, bits, e, NULL); 1253 if(ret != 1) 1254 errx(1, "RSA_new failed"); 1255 1256 BN_free(e); 1257 1258 len = i2d_RSAPrivateKey(rsa, NULL); 1259 1260 p0 = p = malloc(len); 1261 if (p == NULL) 1262 errx(1, "out of memory"); 1263 1264 i2d_RSAPrivateKey(rsa, &p); 1265 1266 rk_dumpdata(fn, p0, len); 1267 memset(p0, 0, len); 1268 free(p0); 1269 1270 RSA_free(rsa); 1271 1272 } else if (fn == NULL) 1273 err(1, "no private key"); 1274 1275 ret = read_private_key(fn, signer); 1276 if (ret) 1277 err(1, "read_private_key"); 1278 } 1279 1280 int 1281 request_create(struct request_create_options *opt, int argc, char **argv) 1282 { 1283 heim_octet_string request; 1284 hx509_request req; 1285 int ret, i; 1286 hx509_private_key signer; 1287 SubjectPublicKeyInfo key; 1288 const char *outfile = argv[0]; 1289 1290 memset(&key, 0, sizeof(key)); 1291 memset(&signer, 0, sizeof(signer)); 1292 1293 get_key(opt->key_string, 1294 opt->generate_key_string, 1295 opt->key_bits_integer, 1296 &signer); 1297 1298 hx509_request_init(context, &req); 1299 1300 if (opt->subject_string) { 1301 hx509_name name = NULL; 1302 1303 ret = hx509_parse_name(context, opt->subject_string, &name); 1304 if (ret) 1305 errx(1, "hx509_parse_name: %d\n", ret); 1306 hx509_request_set_name(context, req, name); 1307 1308 if (opt->verbose_flag) { 1309 char *s; 1310 hx509_name_to_string(name, &s); 1311 printf("%s\n", s); 1312 } 1313 hx509_name_free(&name); 1314 } 1315 1316 for (i = 0; i < opt->email_strings.num_strings; i++) { 1317 ret = _hx509_request_add_email(context, req, 1318 opt->email_strings.strings[i]); 1319 if (ret) 1320 hx509_err(context, 1, ret, "hx509_request_add_email"); 1321 } 1322 1323 for (i = 0; i < opt->dnsname_strings.num_strings; i++) { 1324 ret = _hx509_request_add_dns_name(context, req, 1325 opt->dnsname_strings.strings[i]); 1326 if (ret) 1327 hx509_err(context, 1, ret, "hx509_request_add_dns_name"); 1328 } 1329 1330 1331 ret = hx509_private_key2SPKI(context, signer, &key); 1332 if (ret) 1333 errx(1, "hx509_private_key2SPKI: %d\n", ret); 1334 1335 ret = hx509_request_set_SubjectPublicKeyInfo(context, 1336 req, 1337 &key); 1338 free_SubjectPublicKeyInfo(&key); 1339 if (ret) 1340 hx509_err(context, 1, ret, "hx509_request_set_SubjectPublicKeyInfo"); 1341 1342 ret = _hx509_request_to_pkcs10(context, 1343 req, 1344 signer, 1345 &request); 1346 if (ret) 1347 hx509_err(context, 1, ret, "_hx509_request_to_pkcs10"); 1348 1349 hx509_private_key_free(&signer); 1350 hx509_request_free(&req); 1351 1352 if (ret == 0) 1353 rk_dumpdata(outfile, request.data, request.length); 1354 der_free_octet_string(&request); 1355 1356 return 0; 1357 } 1358 1359 int 1360 request_print(struct request_print_options *opt, int argc, char **argv) 1361 { 1362 int ret, i; 1363 1364 printf("request print\n"); 1365 1366 for (i = 0; i < argc; i++) { 1367 hx509_request req; 1368 1369 ret = _hx509_request_parse(context, argv[i], &req); 1370 if (ret) 1371 hx509_err(context, 1, ret, "parse_request: %s", argv[i]); 1372 1373 ret = _hx509_request_print(context, req, stdout); 1374 hx509_request_free(&req); 1375 if (ret) 1376 hx509_err(context, 1, ret, "Failed to print file %s", argv[i]); 1377 } 1378 1379 return 0; 1380 } 1381 1382 int 1383 info(void *opt, int argc, char **argv) 1384 { 1385 1386 ENGINE_add_conf_module(); 1387 1388 { 1389 const RSA_METHOD *m = RSA_get_default_method(); 1390 if (m != NULL) 1391 printf("rsa: %s\n", RSA_meth_get0_name(m)); 1392 } 1393 { 1394 const DH_METHOD *m = DH_get_default_method(); 1395 if (m != NULL) 1396 printf("dh: %s\n", DH_meth_get0_name(m)); 1397 } 1398 #ifdef HAVE_OPENSSL 1399 { 1400 printf("ecdsa: ECDSA_METHOD-not-export\n"); 1401 } 1402 #else 1403 { 1404 printf("ecdsa: hcrypto null\n"); 1405 } 1406 #endif 1407 { 1408 int ret = RAND_status(); 1409 printf("rand: %s\n", ret == 1 ? "ok" : "not available"); 1410 } 1411 1412 return 0; 1413 } 1414 1415 int 1416 random_data(void *opt, int argc, char **argv) 1417 { 1418 void *ptr; 1419 int len, ret; 1420 1421 len = parse_bytes(argv[0], "byte"); 1422 if (len <= 0) { 1423 fprintf(stderr, "bad argument to random-data\n"); 1424 return 1; 1425 } 1426 1427 ptr = malloc(len); 1428 if (ptr == NULL) { 1429 fprintf(stderr, "out of memory\n"); 1430 return 1; 1431 } 1432 1433 ret = RAND_bytes(ptr, len); 1434 if (ret != 1) { 1435 free(ptr); 1436 fprintf(stderr, "did not get cryptographic strong random\n"); 1437 return 1; 1438 } 1439 1440 fwrite(ptr, len, 1, stdout); 1441 fflush(stdout); 1442 1443 free(ptr); 1444 1445 return 0; 1446 } 1447 1448 int 1449 crypto_available(struct crypto_available_options *opt, int argc, char **argv) 1450 { 1451 AlgorithmIdentifier *val; 1452 unsigned int len, i; 1453 int ret, type = HX509_SELECT_ALL; 1454 1455 if (opt->type_string) { 1456 if (strcmp(opt->type_string, "all") == 0) 1457 type = HX509_SELECT_ALL; 1458 else if (strcmp(opt->type_string, "digest") == 0) 1459 type = HX509_SELECT_DIGEST; 1460 else if (strcmp(opt->type_string, "public-sig") == 0) 1461 type = HX509_SELECT_PUBLIC_SIG; 1462 else if (strcmp(opt->type_string, "secret") == 0) 1463 type = HX509_SELECT_SECRET_ENC; 1464 else 1465 errx(1, "unknown type: %s", opt->type_string); 1466 } 1467 1468 ret = hx509_crypto_available(context, type, NULL, &val, &len); 1469 if (ret) 1470 errx(1, "hx509_crypto_available"); 1471 1472 for (i = 0; i < len; i++) { 1473 char *s; 1474 der_print_heim_oid (&val[i].algorithm, '.', &s); 1475 printf("%s\n", s); 1476 free(s); 1477 } 1478 1479 hx509_crypto_free_algs(val, len); 1480 1481 return 0; 1482 } 1483 1484 int 1485 crypto_select(struct crypto_select_options *opt, int argc, char **argv) 1486 { 1487 hx509_peer_info peer = NULL; 1488 AlgorithmIdentifier selected; 1489 int ret, type = HX509_SELECT_DIGEST; 1490 char *s; 1491 1492 if (opt->type_string) { 1493 if (strcmp(opt->type_string, "digest") == 0) 1494 type = HX509_SELECT_DIGEST; 1495 else if (strcmp(opt->type_string, "public-sig") == 0) 1496 type = HX509_SELECT_PUBLIC_SIG; 1497 else if (strcmp(opt->type_string, "secret") == 0) 1498 type = HX509_SELECT_SECRET_ENC; 1499 else 1500 errx(1, "unknown type: %s", opt->type_string); 1501 } 1502 1503 if (opt->peer_cmstype_strings.num_strings) 1504 peer_strings(context, &peer, &opt->peer_cmstype_strings); 1505 1506 ret = hx509_crypto_select(context, type, NULL, peer, &selected); 1507 if (ret) 1508 errx(1, "hx509_crypto_available"); 1509 1510 der_print_heim_oid (&selected.algorithm, '.', &s); 1511 printf("%s\n", s); 1512 free(s); 1513 free_AlgorithmIdentifier(&selected); 1514 1515 hx509_peer_info_free(peer); 1516 1517 return 0; 1518 } 1519 1520 int 1521 hxtool_hex(struct hex_options *opt, int argc, char **argv) 1522 { 1523 1524 if (opt->decode_flag) { 1525 char buf[1024], buf2[1024], *p; 1526 ssize_t len; 1527 1528 while(fgets(buf, sizeof(buf), stdin) != NULL) { 1529 buf[strcspn(buf, "\r\n")] = '\0'; 1530 p = buf; 1531 while(isspace(*(unsigned char *)p)) 1532 p++; 1533 len = hex_decode(p, buf2, strlen(p)); 1534 if (len < 0) 1535 errx(1, "hex_decode failed"); 1536 if (fwrite(buf2, 1, len, stdout) != (size_t)len) 1537 errx(1, "fwrite failed"); 1538 } 1539 } else { 1540 char buf[28], *p; 1541 ssize_t len; 1542 1543 while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) { 1544 len = hex_encode(buf, len, &p); 1545 if (len < 0) 1546 continue; 1547 fprintf(stdout, "%s\n", p); 1548 free(p); 1549 } 1550 } 1551 return 0; 1552 } 1553 1554 struct cert_type_opt { 1555 int pkinit; 1556 }; 1557 1558 1559 static int 1560 https_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1561 { 1562 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); 1563 } 1564 1565 static int 1566 https_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1567 { 1568 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_clientAuth); 1569 } 1570 1571 static int 1572 peap_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1573 { 1574 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); 1575 } 1576 1577 static int 1578 pkinit_kdc(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1579 { 1580 opt->pkinit++; 1581 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkkdcekuoid); 1582 } 1583 1584 static int 1585 pkinit_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1586 { 1587 int ret; 1588 1589 opt->pkinit++; 1590 1591 ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkekuoid); 1592 if (ret) 1593 return ret; 1594 1595 ret = hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_ms_client_authentication); 1596 if (ret) 1597 return ret; 1598 1599 return hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_pkinit_ms_eku); 1600 } 1601 1602 static int 1603 email_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1604 { 1605 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_emailProtection); 1606 } 1607 1608 struct { 1609 const char *type; 1610 const char *desc; 1611 int (*eval)(hx509_context, hx509_ca_tbs, struct cert_type_opt *); 1612 } certtypes[] = { 1613 { 1614 "https-server", 1615 "Used for HTTPS server and many other TLS server certificate types", 1616 https_server 1617 }, 1618 { 1619 "https-client", 1620 "Used for HTTPS client certificates", 1621 https_client 1622 }, 1623 { 1624 "email-client", 1625 "Certificate will be use for email", 1626 email_client 1627 }, 1628 { 1629 "pkinit-client", 1630 "Certificate used for Kerberos PK-INIT client certificates", 1631 pkinit_client 1632 }, 1633 { 1634 "pkinit-kdc", 1635 "Certificates used for Kerberos PK-INIT KDC certificates", 1636 pkinit_kdc 1637 }, 1638 { 1639 "peap-server", 1640 "Certificate used for Radius PEAP (Protected EAP)", 1641 peap_server 1642 } 1643 }; 1644 1645 static void 1646 print_eval_types(FILE *out) 1647 { 1648 rtbl_t table; 1649 unsigned i; 1650 1651 table = rtbl_create(); 1652 rtbl_add_column_by_id (table, 0, "Name", 0); 1653 rtbl_add_column_by_id (table, 1, "Description", 0); 1654 1655 for (i = 0; i < sizeof(certtypes)/sizeof(certtypes[0]); i++) { 1656 rtbl_add_column_entry_by_id(table, 0, certtypes[i].type); 1657 rtbl_add_column_entry_by_id(table, 1, certtypes[i].desc); 1658 } 1659 1660 rtbl_format (table, out); 1661 rtbl_destroy (table); 1662 } 1663 1664 static int 1665 eval_types(hx509_context contextp, 1666 hx509_ca_tbs tbs, 1667 const struct certificate_sign_options *opt) 1668 { 1669 struct cert_type_opt ctopt; 1670 int i; 1671 size_t j; 1672 int ret; 1673 1674 memset(&ctopt, 0, sizeof(ctopt)); 1675 1676 for (i = 0; i < opt->type_strings.num_strings; i++) { 1677 const char *type = opt->type_strings.strings[i]; 1678 1679 for (j = 0; j < sizeof(certtypes)/sizeof(certtypes[0]); j++) { 1680 if (strcasecmp(type, certtypes[j].type) == 0) { 1681 ret = (*certtypes[j].eval)(contextp, tbs, &ctopt); 1682 if (ret) 1683 hx509_err(contextp, 1, ret, 1684 "Failed to evaluate cert type %s", type); 1685 break; 1686 } 1687 } 1688 if (j >= sizeof(certtypes)/sizeof(certtypes[0])) { 1689 fprintf(stderr, "Unknown certificate type %s\n\n", type); 1690 fprintf(stderr, "Available types:\n"); 1691 print_eval_types(stderr); 1692 exit(1); 1693 } 1694 } 1695 1696 if (opt->pk_init_principal_string) { 1697 if (!ctopt.pkinit) 1698 errx(1, "pk-init principal given but no pk-init oid"); 1699 1700 ret = hx509_ca_tbs_add_san_pkinit(contextp, tbs, 1701 opt->pk_init_principal_string); 1702 if (ret) 1703 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_pkinit"); 1704 } 1705 1706 if (opt->ms_upn_string) { 1707 if (!ctopt.pkinit) 1708 errx(1, "MS upn given but no pk-init oid"); 1709 1710 ret = hx509_ca_tbs_add_san_ms_upn(contextp, tbs, opt->ms_upn_string); 1711 if (ret) 1712 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_ms_upn"); 1713 } 1714 1715 1716 for (i = 0; i < opt->hostname_strings.num_strings; i++) { 1717 const char *hostname = opt->hostname_strings.strings[i]; 1718 1719 ret = hx509_ca_tbs_add_san_hostname(contextp, tbs, hostname); 1720 if (ret) 1721 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); 1722 } 1723 1724 for (i = 0; i < opt->email_strings.num_strings; i++) { 1725 const char *email = opt->email_strings.strings[i]; 1726 1727 ret = hx509_ca_tbs_add_san_rfc822name(contextp, tbs, email); 1728 if (ret) 1729 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); 1730 1731 ret = hx509_ca_tbs_add_eku(contextp, tbs, 1732 &asn1_oid_id_pkix_kp_emailProtection); 1733 if (ret) 1734 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_eku"); 1735 } 1736 1737 if (opt->jid_string) { 1738 ret = hx509_ca_tbs_add_san_jid(contextp, tbs, opt->jid_string); 1739 if (ret) 1740 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_jid"); 1741 } 1742 1743 return 0; 1744 } 1745 1746 int 1747 hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) 1748 { 1749 int ret; 1750 hx509_ca_tbs tbs; 1751 hx509_cert signer = NULL, cert = NULL; 1752 hx509_private_key private_key = NULL; 1753 hx509_private_key cert_key = NULL; 1754 hx509_name subject = NULL; 1755 SubjectPublicKeyInfo spki; 1756 int delta = 0; 1757 1758 memset(&spki, 0, sizeof(spki)); 1759 1760 if (opt->ca_certificate_string == NULL && !opt->self_signed_flag) 1761 errx(1, "--ca-certificate argument missing (not using --self-signed)"); 1762 if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag) 1763 errx(1, "--ca-private-key argument missing (using --self-signed)"); 1764 if (opt->certificate_string == NULL) 1765 errx(1, "--certificate argument missing"); 1766 1767 if (opt->template_certificate_string) { 1768 if (opt->template_fields_string == NULL) 1769 errx(1, "--template-certificate not no --template-fields"); 1770 } 1771 1772 if (opt->lifetime_string) { 1773 delta = parse_time(opt->lifetime_string, "day"); 1774 if (delta < 0) 1775 errx(1, "Invalid lifetime: %s", opt->lifetime_string); 1776 } 1777 1778 if (opt->ca_certificate_string) { 1779 hx509_certs cacerts = NULL; 1780 hx509_query *q; 1781 1782 ret = hx509_certs_init(context, opt->ca_certificate_string, 0, 1783 NULL, &cacerts); 1784 if (ret) 1785 hx509_err(context, 1, ret, 1786 "hx509_certs_init: %s", opt->ca_certificate_string); 1787 1788 ret = hx509_query_alloc(context, &q); 1789 if (ret) 1790 errx(1, "hx509_query_alloc: %d", ret); 1791 1792 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1793 if (!opt->issue_proxy_flag) 1794 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN); 1795 1796 ret = hx509_certs_find(context, cacerts, q, &signer); 1797 hx509_query_free(context, q); 1798 hx509_certs_free(&cacerts); 1799 if (ret) 1800 hx509_err(context, 1, ret, "no CA certificate found"); 1801 } else if (opt->self_signed_flag) { 1802 if (opt->generate_key_string == NULL 1803 && opt->ca_private_key_string == NULL) 1804 errx(1, "no signing private key"); 1805 1806 if (opt->req_string) 1807 errx(1, "can't be self-signing and have a request at the same time"); 1808 } else 1809 errx(1, "missing ca key"); 1810 1811 if (opt->ca_private_key_string) { 1812 1813 ret = read_private_key(opt->ca_private_key_string, &private_key); 1814 if (ret) 1815 err(1, "read_private_key"); 1816 1817 ret = hx509_private_key2SPKI(context, private_key, &spki); 1818 if (ret) 1819 errx(1, "hx509_private_key2SPKI: %d\n", ret); 1820 1821 if (opt->self_signed_flag) 1822 cert_key = private_key; 1823 } 1824 1825 if (opt->req_string) { 1826 hx509_request req; 1827 1828 ret = _hx509_request_parse(context, opt->req_string, &req); 1829 if (ret) 1830 hx509_err(context, 1, ret, "parse_request: %s", opt->req_string); 1831 ret = hx509_request_get_name(context, req, &subject); 1832 if (ret) 1833 hx509_err(context, 1, ret, "get name"); 1834 ret = hx509_request_get_SubjectPublicKeyInfo(context, req, &spki); 1835 if (ret) 1836 hx509_err(context, 1, ret, "get spki"); 1837 hx509_request_free(&req); 1838 } 1839 1840 if (opt->generate_key_string) { 1841 struct hx509_generate_private_context *keyctx; 1842 1843 ret = _hx509_generate_private_key_init(context, 1844 &asn1_oid_id_pkcs1_rsaEncryption, 1845 &keyctx); 1846 if (ret) 1847 hx509_err(context, 1, ret, "generate private key"); 1848 1849 if (opt->issue_ca_flag) 1850 _hx509_generate_private_key_is_ca(context, keyctx); 1851 1852 if (opt->key_bits_integer) 1853 _hx509_generate_private_key_bits(context, keyctx, 1854 opt->key_bits_integer); 1855 1856 ret = _hx509_generate_private_key(context, keyctx, 1857 &cert_key); 1858 _hx509_generate_private_key_free(&keyctx); 1859 if (ret) 1860 hx509_err(context, 1, ret, "generate private key"); 1861 1862 ret = hx509_private_key2SPKI(context, cert_key, &spki); 1863 if (ret) 1864 errx(1, "hx509_private_key2SPKI: %d\n", ret); 1865 1866 if (opt->self_signed_flag) 1867 private_key = cert_key; 1868 } 1869 1870 if (opt->certificate_private_key_string) { 1871 ret = read_private_key(opt->certificate_private_key_string, &cert_key); 1872 if (ret) 1873 err(1, "read_private_key for certificate"); 1874 } 1875 1876 if (opt->subject_string) { 1877 if (subject) 1878 hx509_name_free(&subject); 1879 ret = hx509_parse_name(context, opt->subject_string, &subject); 1880 if (ret) 1881 hx509_err(context, 1, ret, "hx509_parse_name"); 1882 } 1883 1884 /* 1885 * 1886 */ 1887 1888 ret = hx509_ca_tbs_init(context, &tbs); 1889 if (ret) 1890 hx509_err(context, 1, ret, "hx509_ca_tbs_init"); 1891 1892 if (opt->template_certificate_string) { 1893 hx509_cert template; 1894 hx509_certs tcerts; 1895 int flags; 1896 1897 ret = hx509_certs_init(context, opt->template_certificate_string, 0, 1898 NULL, &tcerts); 1899 if (ret) 1900 hx509_err(context, 1, ret, 1901 "hx509_certs_init: %s", opt->template_certificate_string); 1902 1903 ret = hx509_get_one_cert(context, tcerts, &template); 1904 1905 hx509_certs_free(&tcerts); 1906 if (ret) 1907 hx509_err(context, 1, ret, "no template certificate found"); 1908 1909 flags = parse_units(opt->template_fields_string, 1910 hx509_ca_tbs_template_units(), ""); 1911 1912 ret = hx509_ca_tbs_set_template(context, tbs, flags, template); 1913 if (ret) 1914 hx509_err(context, 1, ret, "hx509_ca_tbs_set_template"); 1915 1916 hx509_cert_free(template); 1917 } 1918 1919 if (opt->serial_number_string) { 1920 heim_integer serialNumber; 1921 1922 ret = der_parse_hex_heim_integer(opt->serial_number_string, 1923 &serialNumber); 1924 if (ret) 1925 err(1, "der_parse_hex_heim_integer"); 1926 ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber); 1927 if (ret) 1928 hx509_err(context, 1, ret, "hx509_ca_tbs_init"); 1929 der_free_heim_integer(&serialNumber); 1930 } 1931 1932 if (spki.subjectPublicKey.length) { 1933 ret = hx509_ca_tbs_set_spki(context, tbs, &spki); 1934 if (ret) 1935 hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki"); 1936 } 1937 1938 if (subject) { 1939 ret = hx509_ca_tbs_set_subject(context, tbs, subject); 1940 if (ret) 1941 hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject"); 1942 } 1943 1944 if (opt->crl_uri_string) { 1945 ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs, 1946 opt->crl_uri_string, NULL); 1947 if (ret) 1948 hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri"); 1949 } 1950 1951 eval_types(context, tbs, opt); 1952 1953 if (opt->issue_ca_flag) { 1954 ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer); 1955 if (ret) 1956 hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca"); 1957 } 1958 if (opt->issue_proxy_flag) { 1959 ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer); 1960 if (ret) 1961 hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy"); 1962 } 1963 if (opt->domain_controller_flag) { 1964 hx509_ca_tbs_set_domaincontroller(context, tbs); 1965 if (ret) 1966 hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller"); 1967 } 1968 1969 if (delta) { 1970 ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta); 1971 if (ret) 1972 hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime"); 1973 } 1974 1975 if (opt->self_signed_flag) { 1976 ret = hx509_ca_sign_self(context, tbs, private_key, &cert); 1977 if (ret) 1978 hx509_err(context, 1, ret, "hx509_ca_sign_self"); 1979 } else { 1980 ret = hx509_ca_sign(context, tbs, signer, &cert); 1981 if (ret) 1982 hx509_err(context, 1, ret, "hx509_ca_sign"); 1983 } 1984 1985 if (cert_key) { 1986 ret = _hx509_cert_assign_key(cert, cert_key); 1987 if (ret) 1988 hx509_err(context, 1, ret, "_hx509_cert_assign_key"); 1989 } 1990 1991 { 1992 hx509_certs certs; 1993 1994 ret = hx509_certs_init(context, opt->certificate_string, 1995 HX509_CERTS_CREATE, NULL, &certs); 1996 if (ret) 1997 hx509_err(context, 1, ret, "hx509_certs_init"); 1998 1999 ret = hx509_certs_add(context, certs, cert); 2000 if (ret) 2001 hx509_err(context, 1, ret, "hx509_certs_add"); 2002 2003 ret = hx509_certs_store(context, certs, 0, NULL); 2004 if (ret) 2005 hx509_err(context, 1, ret, "hx509_certs_store"); 2006 2007 hx509_certs_free(&certs); 2008 } 2009 2010 if (subject) 2011 hx509_name_free(&subject); 2012 if (signer) 2013 hx509_cert_free(signer); 2014 hx509_cert_free(cert); 2015 free_SubjectPublicKeyInfo(&spki); 2016 2017 if (private_key != cert_key) 2018 hx509_private_key_free(&private_key); 2019 hx509_private_key_free(&cert_key); 2020 2021 hx509_ca_tbs_free(&tbs); 2022 2023 return 0; 2024 } 2025 2026 static int 2027 test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert) 2028 { 2029 heim_octet_string sd, c; 2030 hx509_verify_ctx vctx = ctx; 2031 hx509_certs signer = NULL; 2032 heim_oid type; 2033 int ret; 2034 2035 if (_hx509_cert_private_key(cert) == NULL) 2036 return 0; 2037 2038 ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0, 2039 NULL, cert, NULL, NULL, NULL, &sd); 2040 if (ret) 2041 errx(1, "hx509_cms_create_signed_1"); 2042 2043 ret = hx509_cms_verify_signed(context, vctx, 0, sd.data, sd.length, 2044 NULL, NULL, &type, &c, &signer); 2045 free(sd.data); 2046 if (ret) 2047 hx509_err(context, 1, ret, "hx509_cms_verify_signed"); 2048 2049 printf("create-signature verify-sigature done\n"); 2050 2051 free(c.data); 2052 2053 return 0; 2054 } 2055 2056 int 2057 test_crypto(struct test_crypto_options *opt, int argc, char ** argv) 2058 { 2059 hx509_verify_ctx vctx; 2060 hx509_certs certs; 2061 hx509_lock lock; 2062 int i, ret; 2063 2064 hx509_lock_init(context, &lock); 2065 lock_strings(lock, &opt->pass_strings); 2066 2067 ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs); 2068 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 2069 2070 for (i = 0; i < argc; i++) { 2071 ret = hx509_certs_append(context, certs, lock, argv[i]); 2072 if (ret) 2073 hx509_err(context, 1, ret, "hx509_certs_append"); 2074 } 2075 2076 ret = hx509_verify_init_ctx(context, &vctx); 2077 if (ret) 2078 hx509_err(context, 1, ret, "hx509_verify_init_ctx"); 2079 2080 hx509_verify_attach_anchors(vctx, certs); 2081 2082 ret = hx509_certs_iter_f(context, certs, test_one_cert, vctx); 2083 if (ret) 2084 hx509_err(context, 1, ret, "hx509_cert_iter"); 2085 2086 hx509_certs_free(&certs); 2087 2088 return 0; 2089 } 2090 2091 int 2092 statistic_print(struct statistic_print_options*opt, int argc, char **argv) 2093 { 2094 int type = 0; 2095 2096 if (stat_file_string == NULL) 2097 errx(1, "no stat file"); 2098 2099 if (opt->type_integer) 2100 type = opt->type_integer; 2101 2102 hx509_query_unparse_stats(context, type, stdout); 2103 return 0; 2104 } 2105 2106 /* 2107 * 2108 */ 2109 2110 int 2111 crl_sign(struct crl_sign_options *opt, int argc, char **argv) 2112 { 2113 hx509_crl crl; 2114 heim_octet_string os; 2115 hx509_cert signer = NULL; 2116 hx509_lock lock; 2117 int ret; 2118 2119 hx509_lock_init(context, &lock); 2120 lock_strings(lock, &opt->pass_strings); 2121 2122 ret = hx509_crl_alloc(context, &crl); 2123 if (ret) 2124 errx(1, "crl alloc"); 2125 2126 if (opt->signer_string == NULL) 2127 errx(1, "signer missing"); 2128 2129 { 2130 hx509_certs certs = NULL; 2131 hx509_query *q; 2132 2133 ret = hx509_certs_init(context, opt->signer_string, 0, 2134 NULL, &certs); 2135 if (ret) 2136 hx509_err(context, 1, ret, 2137 "hx509_certs_init: %s", opt->signer_string); 2138 2139 ret = hx509_query_alloc(context, &q); 2140 if (ret) 2141 hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret); 2142 2143 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 2144 2145 ret = hx509_certs_find(context, certs, q, &signer); 2146 hx509_query_free(context, q); 2147 hx509_certs_free(&certs); 2148 if (ret) 2149 hx509_err(context, 1, ret, "no signer certificate found"); 2150 } 2151 2152 if (opt->lifetime_string) { 2153 int delta; 2154 2155 delta = parse_time(opt->lifetime_string, "day"); 2156 if (delta < 0) 2157 errx(1, "Invalid lifetime: %s", opt->lifetime_string); 2158 2159 hx509_crl_lifetime(context, crl, delta); 2160 } 2161 2162 { 2163 hx509_certs revoked = NULL; 2164 int i; 2165 2166 ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0, 2167 NULL, &revoked); 2168 if (ret) 2169 hx509_err(context, 1, ret, 2170 "hx509_certs_init: MEMORY cert"); 2171 2172 for (i = 0; i < argc; i++) { 2173 ret = hx509_certs_append(context, revoked, lock, argv[i]); 2174 if (ret) 2175 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); 2176 } 2177 2178 hx509_crl_add_revoked_certs(context, crl, revoked); 2179 hx509_certs_free(&revoked); 2180 } 2181 2182 hx509_crl_sign(context, signer, crl, &os); 2183 2184 if (opt->crl_file_string) 2185 rk_dumpdata(opt->crl_file_string, os.data, os.length); 2186 2187 free(os.data); 2188 2189 hx509_crl_free(context, &crl); 2190 hx509_cert_free(signer); 2191 hx509_lock_free(lock); 2192 2193 return 0; 2194 } 2195 2196 /* 2197 * 2198 */ 2199 2200 int 2201 help(void *opt, int argc, char **argv) 2202 { 2203 sl_slc_help(commands, argc, argv); 2204 return 0; 2205 } 2206 2207 int 2208 main(int argc, char **argv) 2209 { 2210 int ret, optidx = 0; 2211 2212 setprogname (argv[0]); 2213 2214 if(getarg(args, num_args, argc, argv, &optidx)) 2215 usage(1); 2216 if(help_flag) 2217 usage(0); 2218 if(version_flag) { 2219 print_version(NULL); 2220 exit(0); 2221 } 2222 argv += optidx; 2223 argc -= optidx; 2224 2225 if (argc == 0) 2226 usage(1); 2227 2228 ret = hx509_context_init(&context); 2229 if (ret) 2230 errx(1, "hx509_context_init failed with %d", ret); 2231 2232 if (stat_file_string) 2233 hx509_query_statistic_file(context, stat_file_string); 2234 2235 ret = sl_command(commands, argc, argv); 2236 if(ret == -1) 2237 warnx ("unrecognized command: %s", argv[0]); 2238 2239 hx509_context_free(&context); 2240 2241 return ret; 2242 } 2243