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