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 1292 get_key(opt->key_string, 1293 opt->generate_key_string, 1294 opt->key_bits_integer, 1295 &signer); 1296 1297 hx509_request_init(context, &req); 1298 1299 if (opt->subject_string) { 1300 hx509_name name = NULL; 1301 1302 ret = hx509_parse_name(context, opt->subject_string, &name); 1303 if (ret) 1304 errx(1, "hx509_parse_name: %d\n", ret); 1305 hx509_request_set_name(context, req, name); 1306 1307 if (opt->verbose_flag) { 1308 char *s; 1309 hx509_name_to_string(name, &s); 1310 printf("%s\n", s); 1311 } 1312 hx509_name_free(&name); 1313 } 1314 1315 for (i = 0; i < opt->email_strings.num_strings; i++) { 1316 ret = _hx509_request_add_email(context, req, 1317 opt->email_strings.strings[i]); 1318 if (ret) 1319 hx509_err(context, 1, ret, "hx509_request_add_email"); 1320 } 1321 1322 for (i = 0; i < opt->dnsname_strings.num_strings; i++) { 1323 ret = _hx509_request_add_dns_name(context, req, 1324 opt->dnsname_strings.strings[i]); 1325 if (ret) 1326 hx509_err(context, 1, ret, "hx509_request_add_dns_name"); 1327 } 1328 1329 1330 ret = hx509_private_key2SPKI(context, signer, &key); 1331 if (ret) 1332 errx(1, "hx509_private_key2SPKI: %d\n", ret); 1333 1334 ret = hx509_request_set_SubjectPublicKeyInfo(context, 1335 req, 1336 &key); 1337 free_SubjectPublicKeyInfo(&key); 1338 if (ret) 1339 hx509_err(context, 1, ret, "hx509_request_set_SubjectPublicKeyInfo"); 1340 1341 ret = _hx509_request_to_pkcs10(context, 1342 req, 1343 signer, 1344 &request); 1345 if (ret) 1346 hx509_err(context, 1, ret, "_hx509_request_to_pkcs10"); 1347 1348 hx509_private_key_free(&signer); 1349 hx509_request_free(&req); 1350 1351 if (ret == 0) 1352 rk_dumpdata(outfile, request.data, request.length); 1353 der_free_octet_string(&request); 1354 1355 return 0; 1356 } 1357 1358 int 1359 request_print(struct request_print_options *opt, int argc, char **argv) 1360 { 1361 int ret, i; 1362 1363 printf("request print\n"); 1364 1365 for (i = 0; i < argc; i++) { 1366 hx509_request req; 1367 1368 ret = _hx509_request_parse(context, argv[i], &req); 1369 if (ret) 1370 hx509_err(context, 1, ret, "parse_request: %s", argv[i]); 1371 1372 ret = _hx509_request_print(context, req, stdout); 1373 hx509_request_free(&req); 1374 if (ret) 1375 hx509_err(context, 1, ret, "Failed to print file %s", argv[i]); 1376 } 1377 1378 return 0; 1379 } 1380 1381 int 1382 info(void *opt, int argc, char **argv) 1383 { 1384 1385 ENGINE_add_conf_module(); 1386 1387 { 1388 const RSA_METHOD *m = RSA_get_default_method(); 1389 if (m != NULL) 1390 printf("rsa: %s\n", m->name); 1391 } 1392 { 1393 const DH_METHOD *m = DH_get_default_method(); 1394 if (m != NULL) 1395 printf("dh: %s\n", m->name); 1396 } 1397 #ifdef HAVE_OPENSSL 1398 { 1399 printf("ecdsa: ECDSA_METHOD-not-export\n"); 1400 } 1401 #else 1402 { 1403 printf("ecdsa: hcrypto null\n"); 1404 } 1405 #endif 1406 { 1407 int ret = RAND_status(); 1408 printf("rand: %s\n", ret == 1 ? "ok" : "not available"); 1409 } 1410 1411 return 0; 1412 } 1413 1414 int 1415 random_data(void *opt, int argc, char **argv) 1416 { 1417 void *ptr; 1418 int len, ret; 1419 1420 len = parse_bytes(argv[0], "byte"); 1421 if (len <= 0) { 1422 fprintf(stderr, "bad argument to random-data\n"); 1423 return 1; 1424 } 1425 1426 ptr = malloc(len); 1427 if (ptr == NULL) { 1428 fprintf(stderr, "out of memory\n"); 1429 return 1; 1430 } 1431 1432 ret = RAND_bytes(ptr, len); 1433 if (ret != 1) { 1434 free(ptr); 1435 fprintf(stderr, "did not get cryptographic strong random\n"); 1436 return 1; 1437 } 1438 1439 fwrite(ptr, len, 1, stdout); 1440 fflush(stdout); 1441 1442 free(ptr); 1443 1444 return 0; 1445 } 1446 1447 int 1448 crypto_available(struct crypto_available_options *opt, int argc, char **argv) 1449 { 1450 AlgorithmIdentifier *val; 1451 unsigned int len, i; 1452 int ret, type = HX509_SELECT_ALL; 1453 1454 if (opt->type_string) { 1455 if (strcmp(opt->type_string, "all") == 0) 1456 type = HX509_SELECT_ALL; 1457 else if (strcmp(opt->type_string, "digest") == 0) 1458 type = HX509_SELECT_DIGEST; 1459 else if (strcmp(opt->type_string, "public-sig") == 0) 1460 type = HX509_SELECT_PUBLIC_SIG; 1461 else if (strcmp(opt->type_string, "secret") == 0) 1462 type = HX509_SELECT_SECRET_ENC; 1463 else 1464 errx(1, "unknown type: %s", opt->type_string); 1465 } 1466 1467 ret = hx509_crypto_available(context, type, NULL, &val, &len); 1468 if (ret) 1469 errx(1, "hx509_crypto_available"); 1470 1471 for (i = 0; i < len; i++) { 1472 char *s; 1473 der_print_heim_oid (&val[i].algorithm, '.', &s); 1474 printf("%s\n", s); 1475 free(s); 1476 } 1477 1478 hx509_crypto_free_algs(val, len); 1479 1480 return 0; 1481 } 1482 1483 int 1484 crypto_select(struct crypto_select_options *opt, int argc, char **argv) 1485 { 1486 hx509_peer_info peer = NULL; 1487 AlgorithmIdentifier selected; 1488 int ret, type = HX509_SELECT_DIGEST; 1489 char *s; 1490 1491 if (opt->type_string) { 1492 if (strcmp(opt->type_string, "digest") == 0) 1493 type = HX509_SELECT_DIGEST; 1494 else if (strcmp(opt->type_string, "public-sig") == 0) 1495 type = HX509_SELECT_PUBLIC_SIG; 1496 else if (strcmp(opt->type_string, "secret") == 0) 1497 type = HX509_SELECT_SECRET_ENC; 1498 else 1499 errx(1, "unknown type: %s", opt->type_string); 1500 } 1501 1502 if (opt->peer_cmstype_strings.num_strings) 1503 peer_strings(context, &peer, &opt->peer_cmstype_strings); 1504 1505 ret = hx509_crypto_select(context, type, NULL, peer, &selected); 1506 if (ret) 1507 errx(1, "hx509_crypto_available"); 1508 1509 der_print_heim_oid (&selected.algorithm, '.', &s); 1510 printf("%s\n", s); 1511 free(s); 1512 free_AlgorithmIdentifier(&selected); 1513 1514 hx509_peer_info_free(peer); 1515 1516 return 0; 1517 } 1518 1519 int 1520 hxtool_hex(struct hex_options *opt, int argc, char **argv) 1521 { 1522 1523 if (opt->decode_flag) { 1524 char buf[1024], buf2[1024], *p; 1525 ssize_t len; 1526 1527 while(fgets(buf, sizeof(buf), stdin) != NULL) { 1528 buf[strcspn(buf, "\r\n")] = '\0'; 1529 p = buf; 1530 while(isspace(*(unsigned char *)p)) 1531 p++; 1532 len = hex_decode(p, buf2, strlen(p)); 1533 if (len < 0) 1534 errx(1, "hex_decode failed"); 1535 if (fwrite(buf2, 1, len, stdout) != (size_t)len) 1536 errx(1, "fwrite failed"); 1537 } 1538 } else { 1539 char buf[28], *p; 1540 ssize_t len; 1541 1542 while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) { 1543 len = hex_encode(buf, len, &p); 1544 if (len < 0) 1545 continue; 1546 fprintf(stdout, "%s\n", p); 1547 free(p); 1548 } 1549 } 1550 return 0; 1551 } 1552 1553 struct cert_type_opt { 1554 int pkinit; 1555 }; 1556 1557 1558 static int 1559 https_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1560 { 1561 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); 1562 } 1563 1564 static int 1565 https_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1566 { 1567 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_clientAuth); 1568 } 1569 1570 static int 1571 peap_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1572 { 1573 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); 1574 } 1575 1576 static int 1577 pkinit_kdc(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1578 { 1579 opt->pkinit++; 1580 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkkdcekuoid); 1581 } 1582 1583 static int 1584 pkinit_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1585 { 1586 int ret; 1587 1588 opt->pkinit++; 1589 1590 ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkekuoid); 1591 if (ret) 1592 return ret; 1593 1594 ret = hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_ms_client_authentication); 1595 if (ret) 1596 return ret; 1597 1598 return hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_pkinit_ms_eku); 1599 } 1600 1601 static int 1602 email_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) 1603 { 1604 return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_emailProtection); 1605 } 1606 1607 struct { 1608 const char *type; 1609 const char *desc; 1610 int (*eval)(hx509_context, hx509_ca_tbs, struct cert_type_opt *); 1611 } certtypes[] = { 1612 { 1613 "https-server", 1614 "Used for HTTPS server and many other TLS server certificate types", 1615 https_server 1616 }, 1617 { 1618 "https-client", 1619 "Used for HTTPS client certificates", 1620 https_client 1621 }, 1622 { 1623 "email-client", 1624 "Certificate will be use for email", 1625 email_client 1626 }, 1627 { 1628 "pkinit-client", 1629 "Certificate used for Kerberos PK-INIT client certificates", 1630 pkinit_client 1631 }, 1632 { 1633 "pkinit-kdc", 1634 "Certificates used for Kerberos PK-INIT KDC certificates", 1635 pkinit_kdc 1636 }, 1637 { 1638 "peap-server", 1639 "Certificate used for Radius PEAP (Protected EAP)", 1640 peap_server 1641 } 1642 }; 1643 1644 static void 1645 print_eval_types(FILE *out) 1646 { 1647 rtbl_t table; 1648 unsigned i; 1649 1650 table = rtbl_create(); 1651 rtbl_add_column_by_id (table, 0, "Name", 0); 1652 rtbl_add_column_by_id (table, 1, "Description", 0); 1653 1654 for (i = 0; i < sizeof(certtypes)/sizeof(certtypes[0]); i++) { 1655 rtbl_add_column_entry_by_id(table, 0, certtypes[i].type); 1656 rtbl_add_column_entry_by_id(table, 1, certtypes[i].desc); 1657 } 1658 1659 rtbl_format (table, out); 1660 rtbl_destroy (table); 1661 } 1662 1663 static int 1664 eval_types(hx509_context contextp, 1665 hx509_ca_tbs tbs, 1666 const struct certificate_sign_options *opt) 1667 { 1668 struct cert_type_opt ctopt; 1669 int i; 1670 size_t j; 1671 int ret; 1672 1673 memset(&ctopt, 0, sizeof(ctopt)); 1674 1675 for (i = 0; i < opt->type_strings.num_strings; i++) { 1676 const char *type = opt->type_strings.strings[i]; 1677 1678 for (j = 0; j < sizeof(certtypes)/sizeof(certtypes[0]); j++) { 1679 if (strcasecmp(type, certtypes[j].type) == 0) { 1680 ret = (*certtypes[j].eval)(contextp, tbs, &ctopt); 1681 if (ret) 1682 hx509_err(contextp, 1, ret, 1683 "Failed to evaluate cert type %s", type); 1684 break; 1685 } 1686 } 1687 if (j >= sizeof(certtypes)/sizeof(certtypes[0])) { 1688 fprintf(stderr, "Unknown certificate type %s\n\n", type); 1689 fprintf(stderr, "Available types:\n"); 1690 print_eval_types(stderr); 1691 exit(1); 1692 } 1693 } 1694 1695 if (opt->pk_init_principal_string) { 1696 if (!ctopt.pkinit) 1697 errx(1, "pk-init principal given but no pk-init oid"); 1698 1699 ret = hx509_ca_tbs_add_san_pkinit(contextp, tbs, 1700 opt->pk_init_principal_string); 1701 if (ret) 1702 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_pkinit"); 1703 } 1704 1705 if (opt->ms_upn_string) { 1706 if (!ctopt.pkinit) 1707 errx(1, "MS upn given but no pk-init oid"); 1708 1709 ret = hx509_ca_tbs_add_san_ms_upn(contextp, tbs, opt->ms_upn_string); 1710 if (ret) 1711 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_ms_upn"); 1712 } 1713 1714 1715 for (i = 0; i < opt->hostname_strings.num_strings; i++) { 1716 const char *hostname = opt->hostname_strings.strings[i]; 1717 1718 ret = hx509_ca_tbs_add_san_hostname(contextp, tbs, hostname); 1719 if (ret) 1720 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); 1721 } 1722 1723 for (i = 0; i < opt->email_strings.num_strings; i++) { 1724 const char *email = opt->email_strings.strings[i]; 1725 1726 ret = hx509_ca_tbs_add_san_rfc822name(contextp, tbs, email); 1727 if (ret) 1728 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); 1729 1730 ret = hx509_ca_tbs_add_eku(contextp, tbs, 1731 &asn1_oid_id_pkix_kp_emailProtection); 1732 if (ret) 1733 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_eku"); 1734 } 1735 1736 if (opt->jid_string) { 1737 ret = hx509_ca_tbs_add_san_jid(contextp, tbs, opt->jid_string); 1738 if (ret) 1739 hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_jid"); 1740 } 1741 1742 return 0; 1743 } 1744 1745 int 1746 hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) 1747 { 1748 int ret; 1749 hx509_ca_tbs tbs; 1750 hx509_cert signer = NULL, cert = NULL; 1751 hx509_private_key private_key = NULL; 1752 hx509_private_key cert_key = NULL; 1753 hx509_name subject = NULL; 1754 SubjectPublicKeyInfo spki; 1755 int delta = 0; 1756 1757 memset(&spki, 0, sizeof(spki)); 1758 1759 if (opt->ca_certificate_string == NULL && !opt->self_signed_flag) 1760 errx(1, "--ca-certificate argument missing (not using --self-signed)"); 1761 if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag) 1762 errx(1, "--ca-private-key argument missing (using --self-signed)"); 1763 if (opt->certificate_string == NULL) 1764 errx(1, "--certificate argument missing"); 1765 1766 if (opt->template_certificate_string) { 1767 if (opt->template_fields_string == NULL) 1768 errx(1, "--template-certificate not no --template-fields"); 1769 } 1770 1771 if (opt->lifetime_string) { 1772 delta = parse_time(opt->lifetime_string, "day"); 1773 if (delta < 0) 1774 errx(1, "Invalid lifetime: %s", opt->lifetime_string); 1775 } 1776 1777 if (opt->ca_certificate_string) { 1778 hx509_certs cacerts = NULL; 1779 hx509_query *q; 1780 1781 ret = hx509_certs_init(context, opt->ca_certificate_string, 0, 1782 NULL, &cacerts); 1783 if (ret) 1784 hx509_err(context, 1, ret, 1785 "hx509_certs_init: %s", opt->ca_certificate_string); 1786 1787 ret = hx509_query_alloc(context, &q); 1788 if (ret) 1789 errx(1, "hx509_query_alloc: %d", ret); 1790 1791 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1792 if (!opt->issue_proxy_flag) 1793 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN); 1794 1795 ret = hx509_certs_find(context, cacerts, q, &signer); 1796 hx509_query_free(context, q); 1797 hx509_certs_free(&cacerts); 1798 if (ret) 1799 hx509_err(context, 1, ret, "no CA certificate found"); 1800 } else if (opt->self_signed_flag) { 1801 if (opt->generate_key_string == NULL 1802 && opt->ca_private_key_string == NULL) 1803 errx(1, "no signing private key"); 1804 1805 if (opt->req_string) 1806 errx(1, "can't be self-signing and have a request at the same time"); 1807 } else 1808 errx(1, "missing ca key"); 1809 1810 if (opt->ca_private_key_string) { 1811 1812 ret = read_private_key(opt->ca_private_key_string, &private_key); 1813 if (ret) 1814 err(1, "read_private_key"); 1815 1816 ret = hx509_private_key2SPKI(context, private_key, &spki); 1817 if (ret) 1818 errx(1, "hx509_private_key2SPKI: %d\n", ret); 1819 1820 if (opt->self_signed_flag) 1821 cert_key = private_key; 1822 } 1823 1824 if (opt->req_string) { 1825 hx509_request req; 1826 1827 ret = _hx509_request_parse(context, opt->req_string, &req); 1828 if (ret) 1829 hx509_err(context, 1, ret, "parse_request: %s", opt->req_string); 1830 ret = hx509_request_get_name(context, req, &subject); 1831 if (ret) 1832 hx509_err(context, 1, ret, "get name"); 1833 ret = hx509_request_get_SubjectPublicKeyInfo(context, req, &spki); 1834 if (ret) 1835 hx509_err(context, 1, ret, "get spki"); 1836 hx509_request_free(&req); 1837 } 1838 1839 if (opt->generate_key_string) { 1840 struct hx509_generate_private_context *keyctx; 1841 1842 ret = _hx509_generate_private_key_init(context, 1843 &asn1_oid_id_pkcs1_rsaEncryption, 1844 &keyctx); 1845 if (ret) 1846 hx509_err(context, 1, ret, "generate private key"); 1847 1848 if (opt->issue_ca_flag) 1849 _hx509_generate_private_key_is_ca(context, keyctx); 1850 1851 if (opt->key_bits_integer) 1852 _hx509_generate_private_key_bits(context, keyctx, 1853 opt->key_bits_integer); 1854 1855 ret = _hx509_generate_private_key(context, keyctx, 1856 &cert_key); 1857 _hx509_generate_private_key_free(&keyctx); 1858 if (ret) 1859 hx509_err(context, 1, ret, "generate private key"); 1860 1861 ret = hx509_private_key2SPKI(context, cert_key, &spki); 1862 if (ret) 1863 errx(1, "hx509_private_key2SPKI: %d\n", ret); 1864 1865 if (opt->self_signed_flag) 1866 private_key = cert_key; 1867 } 1868 1869 if (opt->certificate_private_key_string) { 1870 ret = read_private_key(opt->certificate_private_key_string, &cert_key); 1871 if (ret) 1872 err(1, "read_private_key for certificate"); 1873 } 1874 1875 if (opt->subject_string) { 1876 if (subject) 1877 hx509_name_free(&subject); 1878 ret = hx509_parse_name(context, opt->subject_string, &subject); 1879 if (ret) 1880 hx509_err(context, 1, ret, "hx509_parse_name"); 1881 } 1882 1883 /* 1884 * 1885 */ 1886 1887 ret = hx509_ca_tbs_init(context, &tbs); 1888 if (ret) 1889 hx509_err(context, 1, ret, "hx509_ca_tbs_init"); 1890 1891 if (opt->template_certificate_string) { 1892 hx509_cert template; 1893 hx509_certs tcerts; 1894 int flags; 1895 1896 ret = hx509_certs_init(context, opt->template_certificate_string, 0, 1897 NULL, &tcerts); 1898 if (ret) 1899 hx509_err(context, 1, ret, 1900 "hx509_certs_init: %s", opt->template_certificate_string); 1901 1902 ret = hx509_get_one_cert(context, tcerts, &template); 1903 1904 hx509_certs_free(&tcerts); 1905 if (ret) 1906 hx509_err(context, 1, ret, "no template certificate found"); 1907 1908 flags = parse_units(opt->template_fields_string, 1909 hx509_ca_tbs_template_units(), ""); 1910 1911 ret = hx509_ca_tbs_set_template(context, tbs, flags, template); 1912 if (ret) 1913 hx509_err(context, 1, ret, "hx509_ca_tbs_set_template"); 1914 1915 hx509_cert_free(template); 1916 } 1917 1918 if (opt->serial_number_string) { 1919 heim_integer serialNumber; 1920 1921 ret = der_parse_hex_heim_integer(opt->serial_number_string, 1922 &serialNumber); 1923 if (ret) 1924 err(1, "der_parse_hex_heim_integer"); 1925 ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber); 1926 if (ret) 1927 hx509_err(context, 1, ret, "hx509_ca_tbs_init"); 1928 der_free_heim_integer(&serialNumber); 1929 } 1930 1931 if (spki.subjectPublicKey.length) { 1932 ret = hx509_ca_tbs_set_spki(context, tbs, &spki); 1933 if (ret) 1934 hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki"); 1935 } 1936 1937 if (subject) { 1938 ret = hx509_ca_tbs_set_subject(context, tbs, subject); 1939 if (ret) 1940 hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject"); 1941 } 1942 1943 if (opt->crl_uri_string) { 1944 ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs, 1945 opt->crl_uri_string, NULL); 1946 if (ret) 1947 hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri"); 1948 } 1949 1950 eval_types(context, tbs, opt); 1951 1952 if (opt->issue_ca_flag) { 1953 ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer); 1954 if (ret) 1955 hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca"); 1956 } 1957 if (opt->issue_proxy_flag) { 1958 ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer); 1959 if (ret) 1960 hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy"); 1961 } 1962 if (opt->domain_controller_flag) { 1963 hx509_ca_tbs_set_domaincontroller(context, tbs); 1964 if (ret) 1965 hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller"); 1966 } 1967 1968 if (delta) { 1969 ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta); 1970 if (ret) 1971 hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime"); 1972 } 1973 1974 if (opt->self_signed_flag) { 1975 ret = hx509_ca_sign_self(context, tbs, private_key, &cert); 1976 if (ret) 1977 hx509_err(context, 1, ret, "hx509_ca_sign_self"); 1978 } else { 1979 ret = hx509_ca_sign(context, tbs, signer, &cert); 1980 if (ret) 1981 hx509_err(context, 1, ret, "hx509_ca_sign"); 1982 } 1983 1984 if (cert_key) { 1985 ret = _hx509_cert_assign_key(cert, cert_key); 1986 if (ret) 1987 hx509_err(context, 1, ret, "_hx509_cert_assign_key"); 1988 } 1989 1990 { 1991 hx509_certs certs; 1992 1993 ret = hx509_certs_init(context, opt->certificate_string, 1994 HX509_CERTS_CREATE, NULL, &certs); 1995 if (ret) 1996 hx509_err(context, 1, ret, "hx509_certs_init"); 1997 1998 ret = hx509_certs_add(context, certs, cert); 1999 if (ret) 2000 hx509_err(context, 1, ret, "hx509_certs_add"); 2001 2002 ret = hx509_certs_store(context, certs, 0, NULL); 2003 if (ret) 2004 hx509_err(context, 1, ret, "hx509_certs_store"); 2005 2006 hx509_certs_free(&certs); 2007 } 2008 2009 if (subject) 2010 hx509_name_free(&subject); 2011 if (signer) 2012 hx509_cert_free(signer); 2013 hx509_cert_free(cert); 2014 free_SubjectPublicKeyInfo(&spki); 2015 2016 if (private_key != cert_key) 2017 hx509_private_key_free(&private_key); 2018 hx509_private_key_free(&cert_key); 2019 2020 hx509_ca_tbs_free(&tbs); 2021 2022 return 0; 2023 } 2024 2025 static int 2026 test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert) 2027 { 2028 heim_octet_string sd, c; 2029 hx509_verify_ctx vctx = ctx; 2030 hx509_certs signer = NULL; 2031 heim_oid type; 2032 int ret; 2033 2034 if (_hx509_cert_private_key(cert) == NULL) 2035 return 0; 2036 2037 ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0, 2038 NULL, cert, NULL, NULL, NULL, &sd); 2039 if (ret) 2040 errx(1, "hx509_cms_create_signed_1"); 2041 2042 ret = hx509_cms_verify_signed(context, vctx, 0, sd.data, sd.length, 2043 NULL, NULL, &type, &c, &signer); 2044 free(sd.data); 2045 if (ret) 2046 hx509_err(context, 1, ret, "hx509_cms_verify_signed"); 2047 2048 printf("create-signature verify-sigature done\n"); 2049 2050 free(c.data); 2051 2052 return 0; 2053 } 2054 2055 int 2056 test_crypto(struct test_crypto_options *opt, int argc, char ** argv) 2057 { 2058 hx509_verify_ctx vctx; 2059 hx509_certs certs; 2060 hx509_lock lock; 2061 int i, ret; 2062 2063 hx509_lock_init(context, &lock); 2064 lock_strings(lock, &opt->pass_strings); 2065 2066 ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs); 2067 if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); 2068 2069 for (i = 0; i < argc; i++) { 2070 ret = hx509_certs_append(context, certs, lock, argv[i]); 2071 if (ret) 2072 hx509_err(context, 1, ret, "hx509_certs_append"); 2073 } 2074 2075 ret = hx509_verify_init_ctx(context, &vctx); 2076 if (ret) 2077 hx509_err(context, 1, ret, "hx509_verify_init_ctx"); 2078 2079 hx509_verify_attach_anchors(vctx, certs); 2080 2081 ret = hx509_certs_iter_f(context, certs, test_one_cert, vctx); 2082 if (ret) 2083 hx509_err(context, 1, ret, "hx509_cert_iter"); 2084 2085 hx509_certs_free(&certs); 2086 2087 return 0; 2088 } 2089 2090 int 2091 statistic_print(struct statistic_print_options*opt, int argc, char **argv) 2092 { 2093 int type = 0; 2094 2095 if (stat_file_string == NULL) 2096 errx(1, "no stat file"); 2097 2098 if (opt->type_integer) 2099 type = opt->type_integer; 2100 2101 hx509_query_unparse_stats(context, type, stdout); 2102 return 0; 2103 } 2104 2105 /* 2106 * 2107 */ 2108 2109 int 2110 crl_sign(struct crl_sign_options *opt, int argc, char **argv) 2111 { 2112 hx509_crl crl; 2113 heim_octet_string os; 2114 hx509_cert signer = NULL; 2115 hx509_lock lock; 2116 int ret; 2117 2118 hx509_lock_init(context, &lock); 2119 lock_strings(lock, &opt->pass_strings); 2120 2121 ret = hx509_crl_alloc(context, &crl); 2122 if (ret) 2123 errx(1, "crl alloc"); 2124 2125 if (opt->signer_string == NULL) 2126 errx(1, "signer missing"); 2127 2128 { 2129 hx509_certs certs = NULL; 2130 hx509_query *q; 2131 2132 ret = hx509_certs_init(context, opt->signer_string, 0, 2133 NULL, &certs); 2134 if (ret) 2135 hx509_err(context, 1, ret, 2136 "hx509_certs_init: %s", opt->signer_string); 2137 2138 ret = hx509_query_alloc(context, &q); 2139 if (ret) 2140 hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret); 2141 2142 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 2143 2144 ret = hx509_certs_find(context, certs, q, &signer); 2145 hx509_query_free(context, q); 2146 hx509_certs_free(&certs); 2147 if (ret) 2148 hx509_err(context, 1, ret, "no signer certificate found"); 2149 } 2150 2151 if (opt->lifetime_string) { 2152 int delta; 2153 2154 delta = parse_time(opt->lifetime_string, "day"); 2155 if (delta < 0) 2156 errx(1, "Invalid lifetime: %s", opt->lifetime_string); 2157 2158 hx509_crl_lifetime(context, crl, delta); 2159 } 2160 2161 { 2162 hx509_certs revoked = NULL; 2163 int i; 2164 2165 ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0, 2166 NULL, &revoked); 2167 if (ret) 2168 hx509_err(context, 1, ret, 2169 "hx509_certs_init: MEMORY cert"); 2170 2171 for (i = 0; i < argc; i++) { 2172 ret = hx509_certs_append(context, revoked, lock, argv[i]); 2173 if (ret) 2174 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); 2175 } 2176 2177 hx509_crl_add_revoked_certs(context, crl, revoked); 2178 hx509_certs_free(&revoked); 2179 } 2180 2181 hx509_crl_sign(context, signer, crl, &os); 2182 2183 if (opt->crl_file_string) 2184 rk_dumpdata(opt->crl_file_string, os.data, os.length); 2185 2186 free(os.data); 2187 2188 hx509_crl_free(context, &crl); 2189 hx509_cert_free(signer); 2190 hx509_lock_free(lock); 2191 2192 return 0; 2193 } 2194 2195 /* 2196 * 2197 */ 2198 2199 int 2200 help(void *opt, int argc, char **argv) 2201 { 2202 sl_slc_help(commands, argc, argv); 2203 return 0; 2204 } 2205 2206 int 2207 main(int argc, char **argv) 2208 { 2209 int ret, optidx = 0; 2210 2211 setprogname (argv[0]); 2212 2213 if(getarg(args, num_args, argc, argv, &optidx)) 2214 usage(1); 2215 if(help_flag) 2216 usage(0); 2217 if(version_flag) { 2218 print_version(NULL); 2219 exit(0); 2220 } 2221 argv += optidx; 2222 argc -= optidx; 2223 2224 if (argc == 0) 2225 usage(1); 2226 2227 ret = hx509_context_init(&context); 2228 if (ret) 2229 errx(1, "hx509_context_init failed with %d", ret); 2230 2231 if (stat_file_string) 2232 hx509_query_statistic_file(context, stat_file_string); 2233 2234 ret = sl_command(commands, argc, argv); 2235 if(ret == -1) 2236 warnx ("unrecognized command: %s", argv[0]); 2237 2238 hx509_context_free(&context); 2239 2240 return ret; 2241 } 2242