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