1 /* $OpenBSD: ikeca.c,v 1.40 2015/11/02 12:21:27 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Jonathan Gray <jsg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <stdio.h> 22 #include <unistd.h> 23 #include <err.h> 24 #include <errno.h> 25 #include <string.h> 26 #include <stdlib.h> 27 #include <pwd.h> 28 #include <fcntl.h> 29 #include <fts.h> 30 #include <dirent.h> 31 #include <limits.h> 32 33 #include <openssl/rand.h> 34 #include <openssl/rsa.h> 35 #include <openssl/pem.h> 36 37 #include "types.h" 38 #include "parser.h" 39 40 #ifndef PREFIX 41 #define PREFIX "" 42 #endif 43 #ifndef SSLDIR 44 #define SSLDIR PREFIX "/etc/ssl" 45 #endif 46 #define SSL_CNF SSLDIR "/openssl.cnf" 47 #define X509_CNF SSLDIR "/x509v3.cnf" 48 #define IKECA_CNF SSLDIR "/ikeca.cnf" 49 #define KEYBASE PREFIX "/etc/iked" 50 #ifndef EXPDIR 51 #define EXPDIR PREFIX "/usr/share/iked" 52 #endif 53 54 #ifndef PATH_OPENSSL 55 #define PATH_OPENSSL "/usr/bin/openssl" 56 #endif 57 #ifndef PATH_ZIP 58 #define PATH_ZIP "/usr/local/bin/zip" 59 #endif 60 #ifndef PATH_TAR 61 #define PATH_TAR "/bin/tar" 62 #endif 63 64 struct ca { 65 char sslpath[PATH_MAX]; 66 char passfile[PATH_MAX]; 67 char index[PATH_MAX]; 68 char serial[PATH_MAX]; 69 char sslcnf[PATH_MAX]; 70 char extcnf[PATH_MAX]; 71 char batch[PATH_MAX]; 72 char *caname; 73 }; 74 75 struct { 76 char *dir; 77 mode_t mode; 78 } hier[] = { 79 { "", 0755 }, 80 { "/ca", 0755 }, 81 { "/certs", 0755 }, 82 { "/crls", 0755 }, 83 { "/export", 0755 }, 84 { "/private", 0700 } 85 }; 86 87 /* explicitly list allowed variables */ 88 const char *ca_env[][2] = { 89 { "$ENV::CADB", NULL }, 90 { "$ENV::CASERIAL", NULL }, 91 { "$ENV::CERTFQDN", NULL }, 92 { "$ENV::CERTIP", NULL }, 93 { "$ENV::CERTPATHLEN", NULL }, 94 { "$ENV::CERTUSAGE", NULL }, 95 { "$ENV::CERT_C", NULL }, 96 { "$ENV::CERT_CN", NULL }, 97 { "$ENV::CERT_EMAIL", NULL }, 98 { "$ENV::CERT_L", NULL }, 99 { "$ENV::CERT_O", NULL }, 100 { "$ENV::CERT_OU", NULL }, 101 { "$ENV::CERT_ST", NULL }, 102 { "$ENV::EXTCERTUSAGE", NULL }, 103 { "$ENV::NSCERTTYPE", NULL }, 104 { NULL } 105 }; 106 107 int ca_sign(struct ca *, char *, int); 108 int ca_request(struct ca *, char *); 109 void ca_newpass(char *, char *); 110 char *ca_readpass(char *, size_t *); 111 int fcopy(char *, char *, mode_t); 112 void fcopy_env(const char *, const char *, mode_t); 113 int rm_dir(char *); 114 void ca_hier(char *); 115 void ca_setenv(const char *, const char *); 116 void ca_clrenv(void); 117 void ca_setcnf(struct ca *, const char *); 118 void ca_create_index(struct ca *); 119 120 /* util.c */ 121 int expand_string(char *, size_t, const char *, const char *); 122 123 int 124 ca_delete(struct ca *ca) 125 { 126 return (rm_dir(ca->sslpath)); 127 } 128 129 int 130 ca_key_create(struct ca *ca, char *keyname) 131 { 132 struct stat st; 133 char cmd[PATH_MAX * 2]; 134 char path[PATH_MAX]; 135 136 snprintf(path, sizeof(path), "%s/private/%s.key", ca->sslpath, keyname); 137 138 /* don't recreate key if one is already present */ 139 if (stat(path, &st) == 0) { 140 return (0); 141 } 142 143 snprintf(cmd, sizeof(cmd), 144 "%s genrsa -out %s 2048", 145 PATH_OPENSSL, path); 146 system(cmd); 147 chmod(path, 0600); 148 149 return (0); 150 } 151 152 int 153 ca_key_import(struct ca *ca, char *keyname, char *import) 154 { 155 struct stat st; 156 char dst[PATH_MAX]; 157 158 if (stat(import, &st) != 0) { 159 warn("could not access keyfile %s", import); 160 return (1); 161 } 162 163 snprintf(dst, sizeof(dst), "%s/private/%s.key", ca->sslpath, keyname); 164 fcopy(import, dst, 0600); 165 166 return (0); 167 } 168 169 int 170 ca_key_delete(struct ca *ca, char *keyname) 171 { 172 char path[PATH_MAX]; 173 174 snprintf(path, sizeof(path), "%s/private/%s.key", ca->sslpath, keyname); 175 unlink(path); 176 177 return (0); 178 } 179 180 int 181 ca_delkey(struct ca *ca, char *keyname) 182 { 183 char file[PATH_MAX]; 184 185 snprintf(file, sizeof(file), "%s/%s.crt", ca->sslpath, keyname); 186 unlink(file); 187 188 snprintf(file, sizeof(file), "%s/private/%s.key", ca->sslpath, keyname); 189 unlink(file); 190 191 snprintf(file, sizeof(file), "%s/private/%s.csr", ca->sslpath, keyname); 192 unlink(file); 193 194 snprintf(file, sizeof(file), "%s/private/%s.pfx", ca->sslpath, keyname); 195 unlink(file); 196 197 return (0); 198 } 199 200 int 201 ca_request(struct ca *ca, char *keyname) 202 { 203 char cmd[PATH_MAX * 2]; 204 char path[PATH_MAX]; 205 206 ca_setenv("$ENV::CERT_CN", keyname); 207 ca_setcnf(ca, keyname); 208 209 snprintf(path, sizeof(path), "%s/private/%s.csr", ca->sslpath, keyname); 210 snprintf(cmd, sizeof(cmd), "%s req %s-new" 211 " -key %s/private/%s.key -out %s -config %s", 212 PATH_OPENSSL, ca->batch, ca->sslpath, keyname, 213 path, ca->sslcnf); 214 215 system(cmd); 216 chmod(path, 0600); 217 218 return (0); 219 } 220 221 int 222 ca_sign(struct ca *ca, char *keyname, int type) 223 { 224 char cmd[PATH_MAX * 2]; 225 char hostname[HOST_NAME_MAX+1]; 226 char name[128]; 227 const char *extensions = NULL; 228 229 strlcpy(name, keyname, sizeof(name)); 230 231 if (type == HOST_IPADDR) { 232 ca_setenv("$ENV::CERTIP", name); 233 extensions = "x509v3_IPAddr"; 234 } else if (type == HOST_FQDN) { 235 if (!strcmp(keyname, "local")) { 236 if (gethostname(hostname, sizeof(hostname))) 237 err(1, "gethostname"); 238 strlcpy(name, hostname, sizeof(name)); 239 } 240 ca_setenv("$ENV::CERTFQDN", name); 241 extensions = "x509v3_FQDN"; 242 } else { 243 errx(1, "unknown host type %d", type); 244 } 245 246 ca_create_index(ca); 247 248 ca_setenv("$ENV::CADB", ca->index); 249 ca_setenv("$ENV::CASERIAL", ca->serial); 250 ca_setcnf(ca, keyname); 251 252 snprintf(cmd, sizeof(cmd), 253 "%s ca -config %s -keyfile %s/private/ca.key" 254 " -cert %s/ca.crt" 255 " -extfile %s -extensions %s -out %s/%s.crt" 256 " -in %s/private/%s.csr" 257 " -passin file:%s -outdir %s -batch", 258 PATH_OPENSSL, ca->sslcnf, ca->sslpath, 259 ca->sslpath, 260 ca->extcnf, extensions, ca->sslpath, keyname, 261 ca->sslpath, keyname, 262 ca->passfile, ca->sslpath); 263 264 system(cmd); 265 266 return (0); 267 } 268 269 int 270 ca_certificate(struct ca *ca, char *keyname, int type, int action) 271 { 272 ca_clrenv(); 273 274 switch (action) { 275 case CA_SERVER: 276 ca_setenv("$ENV::EXTCERTUSAGE", "serverAuth"); 277 ca_setenv("$ENV::NSCERTTYPE", "server"); 278 ca_setenv("$ENV::CERTUSAGE", 279 "digitalSignature,keyEncipherment"); 280 break; 281 case CA_CLIENT: 282 ca_setenv("$ENV::EXTCERTUSAGE", "clientAuth"); 283 ca_setenv("$ENV::NSCERTTYPE", "client"); 284 ca_setenv("$ENV::CERTUSAGE", 285 "digitalSignature,keyAgreement"); 286 break; 287 case CA_OCSP: 288 ca_setenv("$ENV::EXTCERTUSAGE", "OCSPSigning"); 289 ca_setenv("$ENV::CERTUSAGE", 290 "nonRepudiation,digitalSignature,keyEncipherment"); 291 break; 292 default: 293 break; 294 } 295 296 ca_key_create(ca, keyname); 297 ca_request(ca, keyname); 298 ca_sign(ca, keyname, type); 299 300 return (0); 301 } 302 303 int 304 ca_key_install(struct ca *ca, char *keyname, char *dir) 305 { 306 struct stat st; 307 char cmd[PATH_MAX * 2]; 308 char src[PATH_MAX]; 309 char dst[PATH_MAX]; 310 char *p = NULL; 311 312 snprintf(src, sizeof(src), "%s/private/%s.key", ca->sslpath, keyname); 313 if (stat(src, &st) == -1) { 314 if (errno == ENOENT) 315 printf("key for '%s' does not exist\n", ca->caname); 316 else 317 warn("could not access key"); 318 return (1); 319 } 320 321 if (dir == NULL) 322 p = dir = strdup(KEYBASE); 323 324 ca_hier(dir); 325 326 snprintf(dst, sizeof(dst), "%s/private/local.key", dir); 327 fcopy(src, dst, 0600); 328 329 snprintf(cmd, sizeof(cmd), "%s rsa -out %s/local.pub" 330 " -in %s/private/local.key -pubout", PATH_OPENSSL, dir, dir); 331 system(cmd); 332 333 free(p); 334 335 return (0); 336 } 337 338 int 339 ca_cert_install(struct ca *ca, char *keyname, char *dir) 340 { 341 char src[PATH_MAX]; 342 char dst[PATH_MAX]; 343 int r; 344 char *p = NULL; 345 346 if (dir == NULL) 347 p = dir = strdup(KEYBASE); 348 349 ca_hier(dir); 350 351 if ((r = ca_key_install(ca, keyname, dir)) != 0) { 352 free(dir); 353 return (r); 354 } 355 356 snprintf(src, sizeof(src), "%s/%s.crt", ca->sslpath, keyname); 357 snprintf(dst, sizeof(dst), "%s/certs/%s.crt", dir, keyname); 358 fcopy(src, dst, 0644); 359 360 free(p); 361 362 return (0); 363 } 364 365 void 366 ca_newpass(char *passfile, char *password) 367 { 368 FILE *f; 369 char *pass; 370 char prev[_PASSWORD_LEN + 1]; 371 372 if (password != NULL) { 373 pass = password; 374 goto done; 375 } 376 377 pass = getpass("CA passphrase:"); 378 if (pass == NULL || *pass == '\0') 379 err(1, "password not set"); 380 381 strlcpy(prev, pass, sizeof(prev)); 382 pass = getpass("Retype CA passphrase:"); 383 if (pass == NULL || strcmp(prev, pass) != 0) 384 errx(1, "passphrase does not match!"); 385 386 done: 387 if ((f = fopen(passfile, "wb")) == NULL) 388 err(1, "could not open passfile %s", passfile); 389 chmod(passfile, 0600); 390 391 fprintf(f, "%s\n%s\n", pass, pass); 392 393 fclose(f); 394 } 395 396 int 397 ca_create(struct ca *ca) 398 { 399 char cmd[PATH_MAX * 2]; 400 char path[PATH_MAX]; 401 402 ca_clrenv(); 403 404 snprintf(path, sizeof(path), "%s/private/ca.key", ca->sslpath); 405 snprintf(cmd, sizeof(cmd), "%s genrsa -aes256 -out" 406 " %s -passout file:%s 2048", PATH_OPENSSL, 407 path, ca->passfile); 408 system(cmd); 409 chmod(path, 0600); 410 411 ca_setenv("$ENV::CERT_CN", "VPN CA"); 412 ca_setcnf(ca, "ca"); 413 414 snprintf(path, sizeof(path), "%s/private/ca.csr", ca->sslpath); 415 snprintf(cmd, sizeof(cmd), "%s req %s-new" 416 " -key %s/private/ca.key" 417 " -config %s -out %s -passin file:%s", PATH_OPENSSL, 418 ca->batch, ca->sslpath, ca->sslcnf, path, ca->passfile); 419 system(cmd); 420 chmod(path, 0600); 421 422 snprintf(cmd, sizeof(cmd), "%s x509 -req -days 365" 423 " -in %s/private/ca.csr -signkey %s/private/ca.key" 424 " -sha256" 425 " -extfile %s -extensions x509v3_CA -out %s/ca.crt -passin file:%s", 426 PATH_OPENSSL, ca->sslpath, ca->sslpath, ca->extcnf, ca->sslpath, 427 ca->passfile); 428 system(cmd); 429 430 /* Create the CRL revocation list */ 431 ca_revoke(ca, NULL); 432 433 return (0); 434 } 435 436 int 437 ca_install(struct ca *ca, char *dir) 438 { 439 struct stat st; 440 char src[PATH_MAX]; 441 char dst[PATH_MAX]; 442 char *p = NULL; 443 444 snprintf(src, sizeof(src), "%s/ca.crt", ca->sslpath); 445 if (stat(src, &st) == -1) { 446 printf("CA '%s' does not exist\n", ca->caname); 447 return (1); 448 } 449 450 if (dir == NULL) 451 p = dir = strdup(KEYBASE); 452 453 ca_hier(dir); 454 455 snprintf(dst, sizeof(dst), "%s/ca/ca.crt", dir); 456 if (fcopy(src, dst, 0644) == 0) 457 printf("certificate for CA '%s' installed into %s\n", 458 ca->caname, dst); 459 460 snprintf(src, sizeof(src), "%s/ca.crl", ca->sslpath); 461 if (stat(src, &st) == 0) { 462 snprintf(dst, sizeof(dst), "%s/crls/ca.crl", dir); 463 if (fcopy(src, dst, 0644) == 0) 464 printf("CRL for CA '%s' installed to %s\n", 465 ca->caname, dst); 466 } 467 468 free(p); 469 470 return (0); 471 } 472 473 int 474 ca_show_certs(struct ca *ca, char *name) 475 { 476 DIR *dir; 477 struct dirent *de; 478 char cmd[PATH_MAX * 2]; 479 char path[PATH_MAX]; 480 char *p; 481 struct stat st; 482 483 if (name != NULL) { 484 snprintf(path, sizeof(path), "%s/%s.crt", 485 ca->sslpath, name); 486 if (stat(path, &st) != 0) 487 err(1, "could not open file %s.crt", name); 488 snprintf(cmd, sizeof(cmd), "%s x509 -text" 489 " -in %s", PATH_OPENSSL, path); 490 system(cmd); 491 printf("\n"); 492 return (0); 493 } 494 495 if ((dir = opendir(ca->sslpath)) == NULL) 496 err(1, "could not open directory %s", ca->sslpath); 497 498 while ((de = readdir(dir)) != NULL) { 499 if (de->d_namlen > 4) { 500 p = de->d_name + de->d_namlen - 4; 501 if (strcmp(".crt", p) != 0) 502 continue; 503 snprintf(path, sizeof(path), "%s/%s", ca->sslpath, 504 de->d_name); 505 snprintf(cmd, sizeof(cmd), "%s x509 -subject" 506 " -fingerprint -dates -noout -in %s", 507 PATH_OPENSSL, path); 508 system(cmd); 509 printf("\n"); 510 } 511 } 512 513 closedir(dir); 514 515 return (0); 516 } 517 518 int 519 fcopy(char *src, char *dst, mode_t mode) 520 { 521 int ifd, ofd; 522 uint8_t buf[BUFSIZ]; 523 ssize_t r; 524 525 if ((ifd = open(src, O_RDONLY)) == -1) 526 err(1, "open %s", src); 527 528 if ((ofd = open(dst, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1) { 529 int saved_errno = errno; 530 close(ifd); 531 errc(1, saved_errno, "open %s", dst); 532 } 533 534 while ((r = read(ifd, buf, sizeof(buf))) > 0) { 535 write(ofd, buf, r); 536 } 537 538 close(ofd); 539 close(ifd); 540 541 return (r == -1); 542 } 543 544 void 545 fcopy_env(const char *src, const char *dst, mode_t mode) 546 { 547 int ofd = -1, i; 548 uint8_t buf[BUFSIZ]; 549 ssize_t r = -1, len; 550 FILE *ifp = NULL; 551 int saved_errno; 552 553 if ((ifp = fopen(src, "r")) == NULL) 554 err(1, "fopen %s", src); 555 556 if ((ofd = open(dst, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1) 557 goto done; 558 559 while (fgets(buf, sizeof(buf), ifp) != NULL) { 560 for (i = 0; ca_env[i][0] != NULL; i++) { 561 if (ca_env[i][1] == NULL) 562 continue; 563 if (expand_string(buf, sizeof(buf), 564 ca_env[i][0], ca_env[i][1]) == -1) 565 errx(1, "env %s value too long", ca_env[i][0]); 566 } 567 len = strlen(buf); 568 if (write(ofd, buf, len) != len) 569 goto done; 570 } 571 572 r = 0; 573 574 done: 575 saved_errno = errno; 576 close(ofd); 577 if (ifp != NULL) 578 fclose(ifp); 579 if (r == -1) 580 errc(1, saved_errno, "open %s", dst); 581 } 582 583 int 584 rm_dir(char *path) 585 { 586 FTS *fts; 587 FTSENT *p; 588 static char *fpath[] = { NULL, NULL }; 589 590 fpath[0] = path; 591 if ((fts = fts_open(fpath, FTS_PHYSICAL, NULL)) == NULL) { 592 warn("fts_open %s", path); 593 return (1); 594 } 595 596 while ((p = fts_read(fts)) != NULL) { 597 switch (p->fts_info) { 598 case FTS_DP: 599 case FTS_DNR: 600 if (rmdir(p->fts_accpath) == -1) 601 warn("rmdir %s", p->fts_accpath); 602 break; 603 case FTS_F: 604 if (unlink(p->fts_accpath) == -1) 605 warn("unlink %s", p->fts_accpath); 606 break; 607 case FTS_D: 608 case FTS_DOT: 609 default: 610 continue; 611 } 612 } 613 fts_close(fts); 614 615 return (0); 616 } 617 618 void 619 ca_hier(char *path) 620 { 621 struct stat st; 622 char dst[PATH_MAX]; 623 unsigned int i; 624 625 for (i = 0; i < nitems(hier); i++) { 626 strlcpy(dst, path, sizeof(dst)); 627 strlcat(dst, hier[i].dir, sizeof(dst)); 628 if (stat(dst, &st) != 0 && errno == ENOENT && 629 mkdir(dst, hier[i].mode) != 0) 630 err(1, "failed to create dir %s", dst); 631 } 632 } 633 634 int 635 ca_export(struct ca *ca, char *keyname, char *myname, char *password) 636 { 637 DIR *dexp; 638 struct dirent *de; 639 struct stat st; 640 char *pass; 641 char prev[_PASSWORD_LEN + 1]; 642 char cmd[PATH_MAX * 2]; 643 char oname[PATH_MAX]; 644 char src[PATH_MAX]; 645 char dst[PATH_MAX]; 646 char *p; 647 char tpl[] = "/tmp/ikectl.XXXXXXXXXX"; 648 unsigned int i; 649 int fd; 650 651 if (keyname != NULL) { 652 if (strlcpy(oname, keyname, sizeof(oname)) >= sizeof(oname)) 653 errx(1, "name too long"); 654 } else { 655 strlcpy(oname, "ca", sizeof(oname)); 656 } 657 658 /* colons are not valid characters in windows filenames... */ 659 while ((p = strchr(oname, ':')) != NULL) 660 *p = '_'; 661 662 if (password != NULL) 663 pass = password; 664 else { 665 pass = getpass("Export passphrase:"); 666 if (pass == NULL || *pass == '\0') 667 err(1, "password not set"); 668 669 strlcpy(prev, pass, sizeof(prev)); 670 pass = getpass("Retype export passphrase:"); 671 if (pass == NULL || strcmp(prev, pass) != 0) 672 errx(1, "passphrase does not match!"); 673 } 674 675 if (keyname != NULL) { 676 snprintf(cmd, sizeof(cmd), "env EXPASS=%s %s pkcs12 -export" 677 " -name %s -CAfile %s/ca.crt -inkey %s/private/%s.key" 678 " -in %s/%s.crt -out %s/private/%s.pfx -passout env:EXPASS" 679 " -passin file:%s", pass, PATH_OPENSSL, keyname, 680 ca->sslpath, ca->sslpath, keyname, ca->sslpath, keyname, 681 ca->sslpath, oname, ca->passfile); 682 system(cmd); 683 } 684 685 snprintf(cmd, sizeof(cmd), "env EXPASS=%s %s pkcs12 -export" 686 " -caname '%s' -name '%s' -cacerts -nokeys" 687 " -in %s/ca.crt -out %s/ca.pfx -passout env:EXPASS -passin file:%s", 688 pass, PATH_OPENSSL, ca->caname, ca->caname, ca->sslpath, 689 ca->sslpath, ca->passfile); 690 system(cmd); 691 692 if ((p = mkdtemp(tpl)) == NULL) 693 err(1, "could not create temp dir"); 694 695 chmod(p, 0755); 696 697 for (i = 0; i < nitems(hier); i++) { 698 strlcpy(dst, p, sizeof(dst)); 699 strlcat(dst, hier[i].dir, sizeof(dst)); 700 if (stat(dst, &st) != 0 && errno == ENOENT && 701 mkdir(dst, hier[i].mode) != 0) 702 err(1, "failed to create dir %s", dst); 703 } 704 705 /* create a file with the address of the peer to connect to */ 706 if (myname != NULL) { 707 snprintf(dst, sizeof(dst), "%s/export/peer.txt", p); 708 if ((fd = open(dst, O_WRONLY|O_CREAT, 0644)) == -1) 709 err(1, "open %s", dst); 710 write(fd, myname, strlen(myname)); 711 close(fd); 712 } 713 714 snprintf(src, sizeof(src), "%s/ca.pfx", ca->sslpath); 715 snprintf(dst, sizeof(dst), "%s/export/ca.pfx", p); 716 fcopy(src, dst, 0644); 717 718 snprintf(src, sizeof(src), "%s/ca.crt", ca->sslpath); 719 snprintf(dst, sizeof(dst), "%s/ca/ca.crt", p); 720 fcopy(src, dst, 0644); 721 722 snprintf(src, sizeof(src), "%s/ca.crl", ca->sslpath); 723 if (stat(src, &st) == 0) { 724 snprintf(dst, sizeof(dst), "%s/crls/ca.crl", p); 725 fcopy(src, dst, 0644); 726 } 727 728 if (keyname != NULL) { 729 snprintf(src, sizeof(src), "%s/private/%s.pfx", ca->sslpath, 730 oname); 731 snprintf(dst, sizeof(dst), "%s/export/%s.pfx", p, oname); 732 fcopy(src, dst, 0644); 733 734 snprintf(src, sizeof(src), "%s/private/%s.key", ca->sslpath, 735 keyname); 736 snprintf(dst, sizeof(dst), "%s/private/%s.key", p, keyname); 737 fcopy(src, dst, 0600); 738 snprintf(dst, sizeof(dst), "%s/private/local.key", p); 739 fcopy(src, dst, 0600); 740 741 snprintf(src, sizeof(src), "%s/%s.crt", ca->sslpath, keyname); 742 snprintf(dst, sizeof(dst), "%s/certs/%s.crt", p, keyname); 743 fcopy(src, dst, 0644); 744 745 snprintf(cmd, sizeof(cmd), "%s rsa -out %s/local.pub" 746 " -in %s/private/%s.key -pubout", PATH_OPENSSL, p, 747 ca->sslpath, keyname); 748 system(cmd); 749 } 750 751 if (stat(PATH_TAR, &st) == 0) { 752 if (keyname == NULL) 753 snprintf(cmd, sizeof(cmd), "%s -zcf %s.tgz -C %s .", 754 PATH_TAR, oname, ca->sslpath); 755 else 756 snprintf(cmd, sizeof(cmd), "%s -zcf %s.tgz -C %s .", 757 PATH_TAR, oname, p); 758 system(cmd); 759 snprintf(src, sizeof(src), "%s.tgz", oname); 760 if (realpath(src, dst) != NULL) 761 printf("exported files in %s\n", dst); 762 } 763 764 if (stat(PATH_ZIP, &st) == 0) { 765 dexp = opendir(EXPDIR); 766 if (dexp) { 767 while ((de = readdir(dexp)) != NULL) { 768 if (!strcmp(de->d_name, ".") || 769 !strcmp(de->d_name, "..")) 770 continue; 771 snprintf(src, sizeof(src), "%s/%s", EXPDIR, 772 de->d_name); 773 snprintf(dst, sizeof(dst), "%s/export/%s", p, 774 de->d_name); 775 fcopy(src, dst, 0644); 776 } 777 closedir(dexp); 778 } 779 780 snprintf(dst, sizeof(dst), "%s/export", p); 781 if (getcwd(src, sizeof(src)) == NULL) 782 err(1, "could not get cwd"); 783 784 if (chdir(dst) == -1) 785 err(1, "could not change %s", dst); 786 787 snprintf(dst, sizeof(dst), "%s/%s.zip", src, oname); 788 snprintf(cmd, sizeof(cmd), "%s -qr %s .", PATH_ZIP, dst); 789 system(cmd); 790 printf("exported files in %s\n", dst); 791 792 if (chdir(src) == -1) 793 err(1, "could not change %s", dst); 794 } 795 796 rm_dir(p); 797 798 return (0); 799 } 800 801 char * 802 ca_readpass(char *path, size_t *len) 803 { 804 FILE *f; 805 char *p, *r; 806 807 if ((f = fopen(path, "r")) == NULL) { 808 warn("fopen %s", path); 809 return (NULL); 810 } 811 812 if ((p = fgetln(f, len)) != NULL) { 813 if ((r = malloc(*len + 1)) == NULL) 814 err(1, "malloc"); 815 memcpy(r, p, *len); 816 if (r[*len - 1] == '\n') 817 r[*len - 1] = '\0'; 818 else 819 r[*len] = '\0'; 820 } else 821 r = NULL; 822 823 fclose(f); 824 825 return (r); 826 } 827 828 /* create index if it doesn't already exist */ 829 void 830 ca_create_index(struct ca *ca) 831 { 832 struct stat st; 833 int fd; 834 835 if (snprintf(ca->index, sizeof(ca->index), "%s/index.txt", 836 ca->sslpath) < 0) 837 err(1, "snprintf"); 838 if (stat(ca->index, &st) != 0) { 839 if (errno == ENOENT) { 840 if ((fd = open(ca->index, O_WRONLY | O_CREAT, 0644)) 841 == -1) 842 err(1, "could not create file %s", ca->index); 843 close(fd); 844 } else 845 err(1, "could not access %s", ca->index); 846 } 847 848 if (snprintf(ca->serial, sizeof(ca->serial), "%s/serial.txt", 849 ca->sslpath) < 0) 850 err(1, "snprintf"); 851 if (stat(ca->serial, &st) != 0) { 852 if (errno == ENOENT) { 853 if ((fd = open(ca->serial, O_WRONLY | O_CREAT, 0644)) 854 == -1) 855 err(1, "could not create file %s", ca->serial); 856 /* serial file must be created with a number */ 857 if (write(fd, "01\n", 3) != 3) 858 err(1, "write %s", ca->serial); 859 close(fd); 860 } else 861 err(1, "could not access %s", ca->serial); 862 } 863 } 864 865 int 866 ca_revoke(struct ca *ca, char *keyname) 867 { 868 struct stat st; 869 char cmd[PATH_MAX * 2]; 870 char path[PATH_MAX]; 871 char *pass; 872 size_t len; 873 874 if (keyname) { 875 snprintf(path, sizeof(path), "%s/%s.crt", 876 ca->sslpath, keyname); 877 if (stat(path, &st) != 0) { 878 warn("Problem with certificate for '%s'", keyname); 879 return (1); 880 } 881 } 882 883 snprintf(path, sizeof(path), "%s/ikeca.passwd", ca->sslpath); 884 pass = ca_readpass(path, &len); 885 if (pass == NULL) 886 errx(1, "could not open passphrase file"); 887 888 ca_create_index(ca); 889 890 ca_setenv("$ENV::CADB", ca->index); 891 ca_setenv("$ENV::CASERIAL", ca->serial); 892 ca_setcnf(ca, "ca-revoke"); 893 894 if (keyname) { 895 snprintf(cmd, sizeof(cmd), 896 "%s ca %s-config %s -keyfile %s/private/ca.key" 897 " -key %s" 898 " -cert %s/ca.crt" 899 " -revoke %s/%s.crt", 900 PATH_OPENSSL, ca->batch, ca->sslcnf, 901 ca->sslpath, pass, ca->sslpath, ca->sslpath, keyname); 902 system(cmd); 903 } 904 905 snprintf(cmd, sizeof(cmd), 906 "%s ca %s-config %s -keyfile %s/private/ca.key" 907 " -key %s" 908 " -gencrl" 909 " -cert %s/ca.crt" 910 " -crldays 365" 911 " -out %s/ca.crl", 912 PATH_OPENSSL, ca->batch, ca->sslcnf, ca->sslpath, 913 pass, ca->sslpath, ca->sslpath); 914 system(cmd); 915 916 explicit_bzero(pass, len); 917 free(pass); 918 919 return (0); 920 } 921 922 void 923 ca_clrenv(void) 924 { 925 int i; 926 for (i = 0; ca_env[i][0] != NULL; i++) 927 ca_env[i][1] = NULL; 928 } 929 930 void 931 ca_setenv(const char *key, const char *value) 932 { 933 int i; 934 935 for (i = 0; ca_env[i][0] != NULL; i++) { 936 if (strcmp(ca_env[i][0], key) == 0) { 937 if (ca_env[i][1] != NULL) 938 errx(1, "env %s already set: %s", key, value); 939 ca_env[i][1] = value; 940 return; 941 } 942 } 943 errx(1, "env %s invalid", key); 944 } 945 946 void 947 ca_setcnf(struct ca *ca, const char *keyname) 948 { 949 struct stat st; 950 const char *extcnf, *sslcnf; 951 952 if (stat(IKECA_CNF, &st) == 0) { 953 extcnf = IKECA_CNF; 954 sslcnf = IKECA_CNF; 955 } else { 956 extcnf = X509_CNF; 957 sslcnf = SSL_CNF; 958 } 959 960 snprintf(ca->extcnf, sizeof(ca->extcnf), "%s/%s-ext.cnf", 961 ca->sslpath, keyname); 962 snprintf(ca->sslcnf, sizeof(ca->sslcnf), "%s/%s-ssl.cnf", 963 ca->sslpath, keyname); 964 965 fcopy_env(extcnf, ca->extcnf, 0400); 966 fcopy_env(sslcnf, ca->sslcnf, 0400); 967 } 968 969 struct ca * 970 ca_setup(char *caname, int create, int quiet, char *pass) 971 { 972 struct stat st; 973 struct ca *ca; 974 char path[PATH_MAX]; 975 976 if (stat(PATH_OPENSSL, &st) == -1) 977 err(1, "openssl binary not available"); 978 979 if ((ca = calloc(1, sizeof(struct ca))) == NULL) 980 err(1, "calloc"); 981 982 ca->caname = strdup(caname); 983 snprintf(ca->sslpath, sizeof(ca->sslpath), SSLDIR "/%s", caname); 984 strlcpy(ca->passfile, ca->sslpath, sizeof(ca->passfile)); 985 strlcat(ca->passfile, "/ikeca.passwd", sizeof(ca->passfile)); 986 987 if (quiet) 988 strlcpy(ca->batch, "-batch ", sizeof(ca->batch)); 989 990 if (create == 0 && stat(ca->sslpath, &st) == -1) { 991 free(ca->caname); 992 free(ca); 993 errx(1, "CA '%s' does not exist", caname); 994 } 995 996 strlcpy(path, ca->sslpath, sizeof(path)); 997 if (mkdir(path, 0777) == -1 && errno != EEXIST) 998 err(1, "failed to create dir %s", path); 999 strlcat(path, "/private", sizeof(path)); 1000 if (mkdir(path, 0700) == -1 && errno != EEXIST) 1001 err(1, "failed to create dir %s", path); 1002 1003 if (create && stat(ca->passfile, &st) == -1 && errno == ENOENT) 1004 ca_newpass(ca->passfile, pass); 1005 1006 return (ca); 1007 } 1008