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