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