1 /*- 2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Alistair Crooks (agc@NetBSD.org) 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 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 #include "config.h" 30 31 #ifdef HAVE_SYS_CDEFS_H 32 #include <sys/cdefs.h> 33 #endif 34 35 #if defined(__NetBSD__) 36 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 37 __RCSID("$NetBSD: netpgp.c,v 1.37 2010/02/06 02:24:33 agc Exp $"); 38 #endif 39 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <sys/param.h> 43 #include <sys/mman.h> 44 45 #ifdef HAVE_SYS_RESOURCE_H 46 #include <sys/resource.h> 47 #endif 48 49 #ifdef HAVE_FCNTL_H 50 #include <fcntl.h> 51 #endif 52 53 #include <errno.h> 54 #include <regex.h> 55 #include <stdarg.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <time.h> 59 60 #ifdef HAVE_UNISTD_H 61 #include <unistd.h> 62 #endif 63 64 #include <errno.h> 65 66 #ifdef HAVE_LIMITS_H 67 #include <limits.h> 68 #endif 69 70 #include <netpgp.h> 71 72 #include "packet.h" 73 #include "packet-parse.h" 74 #include "keyring.h" 75 #include "errors.h" 76 #include "packet-show.h" 77 #include "create.h" 78 #include "netpgpsdk.h" 79 #include "memory.h" 80 #include "validate.h" 81 #include "readerwriter.h" 82 #include "netpgpdefs.h" 83 #include "crypto.h" 84 #include "ops-ssh.h" 85 #include "defs.h" 86 87 /* read any gpg config file */ 88 static int 89 conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length) 90 { 91 regmatch_t matchv[10]; 92 regex_t keyre; 93 char buf[BUFSIZ]; 94 FILE *fp; 95 96 __OPS_USED(netpgp); 97 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); 98 if ((fp = fopen(buf, "r")) == NULL) { 99 return 0; 100 } 101 (void) memset(&keyre, 0x0, sizeof(keyre)); 102 (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", 103 REG_EXTENDED); 104 while (fgets(buf, sizeof(buf), fp) != NULL) { 105 if (regexec(&keyre, buf, 10, matchv, 0) == 0) { 106 (void) memcpy(userid, &buf[(int)matchv[1].rm_so], 107 MIN((unsigned)(matchv[1].rm_eo - 108 matchv[1].rm_so), length)); 109 if (netpgp->passfp == NULL) { 110 (void) fprintf(stderr, 111 "netpgp: default key set to \"%.*s\"\n", 112 (int)(matchv[1].rm_eo - matchv[1].rm_so), 113 &buf[(int)matchv[1].rm_so]); 114 } 115 } 116 } 117 (void) fclose(fp); 118 return 1; 119 } 120 121 /* small function to pretty print an 8-character raw userid */ 122 static char * 123 userid_to_id(const unsigned char *userid, char *id) 124 { 125 static const char *hexes = "0123456789abcdef"; 126 int i; 127 128 for (i = 0; i < 8 ; i++) { 129 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; 130 id[(i * 2) + 1] = hexes[userid[i] & 0xf]; 131 } 132 id[8 * 2] = 0x0; 133 return id; 134 } 135 136 /* print out the successful signature information */ 137 static void 138 resultp(__ops_io_t *io, 139 const char *f, 140 __ops_validation_t *res, 141 __ops_keyring_t *ring) 142 { 143 const __ops_key_t *pubkey; 144 unsigned from; 145 unsigned i; 146 time_t t; 147 char id[MAX_ID_LENGTH + 1]; 148 149 for (i = 0; i < res->validc; i++) { 150 (void) fprintf(io->res, 151 "Good signature for %s made %s", 152 (f) ? f : "<stdin>", 153 ctime(&res->valid_sigs[i].birthtime)); 154 if (res->duration > 0) { 155 t = res->birthtime + res->duration; 156 (void) fprintf(io->res, "Valid until %s", ctime(&t)); 157 } 158 (void) fprintf(io->res, 159 "using %s key %s\n", 160 __ops_show_pka(res->valid_sigs[i].key_alg), 161 userid_to_id(res->valid_sigs[i].signer_id, id)); 162 from = 0; 163 pubkey = __ops_getkeybyid(io, ring, 164 (const unsigned char *) res->valid_sigs[i].signer_id, 165 &from); 166 __ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey); 167 } 168 } 169 170 /* check there's enough space in the arrays */ 171 static int 172 size_arrays(netpgp_t *netpgp, unsigned needed) 173 { 174 char **temp; 175 176 if (netpgp->size == 0) { 177 /* only get here first time around */ 178 netpgp->size = needed; 179 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { 180 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 181 return 0; 182 } 183 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { 184 free(netpgp->name); 185 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 186 return 0; 187 } 188 } else if (netpgp->c == netpgp->size) { 189 /* only uses 'needed' when filled array */ 190 netpgp->size += needed; 191 temp = realloc(netpgp->name, sizeof(char *) * needed); 192 if (temp == NULL) { 193 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 194 return 0; 195 } 196 netpgp->name = temp; 197 temp = realloc(netpgp->value, sizeof(char *) * needed); 198 if (temp == NULL) { 199 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 200 return 0; 201 } 202 netpgp->value = temp; 203 } 204 return 1; 205 } 206 207 /* find the name in the array */ 208 static int 209 findvar(netpgp_t *netpgp, const char *name) 210 { 211 unsigned i; 212 213 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { 214 } 215 return (i == netpgp->c) ? -1 : (int)i; 216 } 217 218 /* read a keyring and return it */ 219 static void * 220 readkeyring(netpgp_t *netpgp, const char *name) 221 { 222 __ops_keyring_t *keyring; 223 const unsigned noarmor = 0; 224 char f[MAXPATHLEN]; 225 char *filename; 226 char *homedir; 227 228 homedir = netpgp_getvar(netpgp, "homedir"); 229 if ((filename = netpgp_getvar(netpgp, name)) == NULL) { 230 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); 231 filename = f; 232 } 233 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 234 (void) fprintf(stderr, "readkeyring: bad alloc\n"); 235 return NULL; 236 } 237 if (!__ops_keyring_fileread(keyring, noarmor, filename)) { 238 free(keyring); 239 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 240 return NULL; 241 } 242 netpgp_setvar(netpgp, name, filename); 243 return keyring; 244 } 245 246 /* read keys from ssh key files */ 247 static int 248 readsshkeys(netpgp_t *netpgp, char *homedir) 249 { 250 __ops_keyring_t *pubring; 251 __ops_keyring_t *secring; 252 char f[MAXPATHLEN]; 253 char *filename; 254 255 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) { 256 (void) snprintf(f, sizeof(f), "%s/.ssh/is_rsa.pub", homedir); 257 filename = f; 258 } 259 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { 260 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 261 return 0; 262 } 263 if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL)) { 264 free(pubring); 265 (void) fprintf(stderr, "readsshkeys: can't read %s\n", 266 filename); 267 return 0; 268 } 269 if (netpgp->pubring == NULL) { 270 netpgp->pubring = pubring; 271 } else { 272 __ops_append_keyring(netpgp->pubring, pubring); 273 } 274 netpgp_setvar(netpgp, "sshpubfile", filename); 275 /* try to take the ".pub" off the end */ 276 if (filename == f) { 277 f[strlen(f) - 4] = 0x0; 278 } else { 279 (void) snprintf(f, sizeof(f), "%.*s", 280 (int)strlen(filename) - 4, filename); 281 filename = f; 282 } 283 if ((secring = calloc(1, sizeof(*secring))) == NULL) { 284 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 285 return 0; 286 } 287 if (__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename)) { 288 netpgp->secring = secring; 289 netpgp_setvar(netpgp, "sshsecfile", filename); 290 } else { 291 (void) fprintf(stderr, "readsshkeys: can't read sec %s (%d)\n", 292 filename, errno); 293 } 294 return 1; 295 } 296 297 /* set ssh uid to first one in ring */ 298 static void 299 set_ssh_userid(__ops_keyring_t *pubring, char *id, size_t len, int last) 300 { 301 unsigned char *src; 302 int i; 303 int n; 304 305 (void) memset(id, 0x0, len); 306 src = pubring->keys[(last) ? pubring->keyc - 1 : 0].key_id; 307 for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) { 308 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); 309 } 310 id[n] = 0x0; 311 } 312 313 /* get expiration in seconds */ 314 static uint64_t 315 get_duration(char *s) 316 { 317 struct tm tm; 318 uint64_t now; 319 char *mult; 320 321 if (s == NULL) { 322 return 0; 323 } 324 now = strtoull(s, NULL, 10); 325 if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) { 326 switch(*mult) { 327 case 'h': 328 return now * 60 * 60; 329 case 'd': 330 return now * 60 * 60 * 24; 331 case 'w': 332 return now * 60 * 60 * 24 * 7; 333 case 'm': 334 return now * 60 * 60 * 24 * 31; 335 case 'y': 336 return now * 60 * 60 * 24 * 365; 337 } 338 } 339 if (strptime(s, "%Y-%m-%d", &tm) != NULL) { 340 return mktime(&tm); 341 } 342 if (strptime(s, "%Y/%m/%d", &tm) != NULL) { 343 return mktime(&tm); 344 } 345 return (uint64_t)strtoll(s, NULL, 10); 346 } 347 348 /* get birthtime in seconds */ 349 static int64_t 350 get_birthtime(char *s) 351 { 352 struct tm tm; 353 354 if (s == NULL) { 355 return time(NULL); 356 } 357 if (strptime(s, "%Y-%m-%d", &tm) != NULL) { 358 return mktime(&tm); 359 } 360 if (strptime(s, "%Y/%m/%d", &tm) != NULL) { 361 return mktime(&tm); 362 } 363 return (uint64_t)strtoll(s, NULL, 10); 364 } 365 366 /***************************************************************************/ 367 /* exported functions start here */ 368 /***************************************************************************/ 369 370 /* initialise a netpgp_t structure */ 371 int 372 netpgp_init(netpgp_t *netpgp) 373 { 374 __ops_io_t *io; 375 char id[MAX_ID_LENGTH]; 376 char *homedir; 377 char *userid; 378 char *stream; 379 char *passfd; 380 char *results; 381 int coredumps; 382 int last; 383 384 #ifdef HAVE_SYS_RESOURCE_H 385 struct rlimit limit; 386 387 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 388 if (!coredumps) { 389 (void) memset(&limit, 0x0, sizeof(limit)); 390 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 391 (void) fprintf(stderr, 392 "netpgp_init: warning - can't turn off core dumps\n"); 393 coredumps = 1; 394 } 395 } 396 #else 397 coredumps = 1; 398 #endif 399 if ((io = calloc(1, sizeof(*io))) == NULL) { 400 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 401 return 0; 402 } 403 io->outs = stdout; 404 if ((stream = netpgp_getvar(netpgp, "stdout")) != NULL && 405 strcmp(stream, "stderr") == 0) { 406 io->outs = stderr; 407 } 408 io->errs = stderr; 409 if ((stream = netpgp_getvar(netpgp, "stderr")) != NULL && 410 strcmp(stream, "stdout") == 0) { 411 io->errs = stdout; 412 } 413 if ((results = netpgp_getvar(netpgp, "results")) == NULL) { 414 io->res = io->errs; 415 } else if ((io->res = fopen(results, "w")) == NULL) { 416 (void) fprintf(io->errs, "Can't open results %s for writing\n", 417 results); 418 return 0; 419 } 420 netpgp->io = io; 421 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 422 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 423 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 424 passfd); 425 return 0; 426 } 427 if (coredumps) { 428 (void) fprintf(io->errs, 429 "netpgp: warning: core dumps enabled\n"); 430 } 431 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 432 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 433 return 0; 434 } 435 /* read from either gpg files or ssh keys */ 436 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 437 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 438 (void) memset(id, 0x0, sizeof(id)); 439 (void) conffile(netpgp, homedir, id, sizeof(id)); 440 if (id[0] != 0x0) { 441 netpgp_setvar(netpgp, "userid", userid = id); 442 } 443 } 444 if (userid == NULL) { 445 if (netpgp_getvar(netpgp, "need userid") != NULL) { 446 (void) fprintf(io->errs, 447 "Cannot find user id\n"); 448 return 0; 449 } 450 } else { 451 (void) netpgp_setvar(netpgp, "userid", userid); 452 } 453 netpgp->pubring = readkeyring(netpgp, "pubring"); 454 if (netpgp->pubring == NULL) { 455 (void) fprintf(io->errs, "Can't read pub keyring\n"); 456 return 0; 457 } 458 netpgp->secring = readkeyring(netpgp, "secring"); 459 if (netpgp->secring == NULL) { 460 (void) fprintf(io->errs, "Can't read sec keyring\n"); 461 return 0; 462 } 463 } else { 464 last = (netpgp->pubring != NULL); 465 if (!readsshkeys(netpgp, homedir)) { 466 (void) fprintf(io->errs, "Can't read ssh pub key\n"); 467 return 0; 468 } 469 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 470 set_ssh_userid(netpgp->pubring, id, sizeof(id), last); 471 netpgp_setvar(netpgp, "userid", userid = id); 472 } 473 if (userid == NULL) { 474 if (netpgp_getvar(netpgp, "need userid") != NULL) { 475 (void) fprintf(io->errs, 476 "Cannot find user id\n"); 477 return 0; 478 } 479 } else { 480 (void) netpgp_setvar(netpgp, "userid", userid); 481 } 482 } 483 return 1; 484 } 485 486 /* finish off with the netpgp_t struct */ 487 int 488 netpgp_end(netpgp_t *netpgp) 489 { 490 unsigned i; 491 492 for (i = 0 ; i < netpgp->c ; i++) { 493 if (netpgp->name[i] != NULL) { 494 free(netpgp->name[i]); 495 } 496 if (netpgp->value[i] != NULL) { 497 free(netpgp->value[i]); 498 } 499 } 500 if (netpgp->name != NULL) { 501 free(netpgp->name); 502 } 503 if (netpgp->value != NULL) { 504 free(netpgp->value); 505 } 506 if (netpgp->pubring != NULL) { 507 __ops_keyring_free(netpgp->pubring); 508 } 509 if (netpgp->secring != NULL) { 510 __ops_keyring_free(netpgp->secring); 511 } 512 free(netpgp->io); 513 return 1; 514 } 515 516 /* list the keys in a keyring */ 517 int 518 netpgp_list_keys(netpgp_t *netpgp) 519 { 520 return __ops_keyring_list(netpgp->io, netpgp->pubring); 521 } 522 523 DEFINE_ARRAY(strings_t, char *); 524 525 #ifndef HKP_VERSION 526 #define HKP_VERSION 1 527 #endif 528 529 /* find and list some keys in a keyring */ 530 int 531 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp) 532 { 533 const __ops_key_t *key; 534 unsigned k; 535 strings_t pubs; 536 FILE *fp = (FILE *)vp; 537 538 (void) memset(&pubs, 0x0, sizeof(pubs)); 539 k = 0; 540 do { 541 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 542 name, &k); 543 if (key != NULL) { 544 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 545 "netpgp_match_keys", return 0); 546 if (strcmp(fmt, "mr") == 0) { 547 __ops_hkp_sprint_keydata( 548 key, &pubs.v[pubs.c], 549 &key->key.pubkey); 550 } else { 551 __ops_sprint_keydata( 552 key, &pubs.v[pubs.c], 553 "pub", 554 &key->key.pubkey); 555 } 556 pubs.c += 1; 557 k += 1; 558 } 559 } while (key != NULL); 560 if (strcmp(fmt, "mr") == 0) { 561 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 562 } else { 563 (void) fprintf(fp, "%d keys found\n", pubs.c); 564 } 565 for (k = 0 ; k < pubs.c ; k++) { 566 (void) fprintf(fp, "%s", pubs.v[k]); 567 free(pubs.v[k]); 568 } 569 free(pubs.v); 570 return pubs.c; 571 } 572 573 /* find and list some public keys in a keyring */ 574 int 575 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) 576 { 577 const __ops_key_t *key; 578 unsigned k; 579 strings_t pubs; 580 FILE *fp = (FILE *)vp; 581 582 (void) memset(&pubs, 0x0, sizeof(pubs)); 583 do { 584 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 585 name, &k); 586 if (key != NULL) { 587 char out[1024 * 64]; 588 589 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 590 "netpgp_match_pubkeys", return 0); 591 (void) __ops_sprint_pubkey(key, out, sizeof(out)); 592 pubs.v[pubs.c++] = strdup(out); 593 k += 1; 594 } 595 } while (key != NULL); 596 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 597 for (k = 0 ; k < pubs.c ; k++) { 598 (void) fprintf(fp, "%s", pubs.v[k]); 599 free(pubs.v[k]); 600 } 601 free(pubs.v); 602 return pubs.c; 603 } 604 605 /* find a key in a keyring */ 606 int 607 netpgp_find_key(netpgp_t *netpgp, char *id) 608 { 609 __ops_io_t *io; 610 611 io = netpgp->io; 612 if (id == NULL) { 613 (void) fprintf(io->errs, "NULL id to search for\n"); 614 return 0; 615 } 616 return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 617 } 618 619 /* get a key in a keyring */ 620 char * 621 netpgp_get_key(netpgp_t *netpgp, const char *id) 622 { 623 const __ops_key_t *key; 624 __ops_io_t *io; 625 char *newkey; 626 627 io = netpgp->io; 628 if (id == NULL) { 629 /* just get the default userid */ 630 id = netpgp_getvar(netpgp, "userid"); 631 } 632 key = __ops_getkeybyname(netpgp->io, netpgp->pubring, id); 633 if (key == NULL) { 634 (void) fprintf(io->errs, "Can't find key '%s'\n", id); 635 return NULL; 636 } 637 return (__ops_sprint_keydata(key, &newkey, "pub", 638 &key->key.pubkey) > 0) ? newkey : NULL; 639 } 640 641 /* export a given key */ 642 int 643 netpgp_export_key(netpgp_t *netpgp, char *userid) 644 { 645 const __ops_key_t *keypair; 646 __ops_io_t *io; 647 648 io = netpgp->io; 649 if (userid == NULL) { 650 userid = netpgp_getvar(netpgp, "userid"); 651 } 652 keypair = __ops_getkeybyname(io, netpgp->pubring, userid); 653 if (keypair == NULL) { 654 (void) fprintf(io->errs, 655 "Cannot find own key \"%s\" in keyring\n", userid); 656 return 0; 657 } 658 return __ops_export_key(keypair, NULL); 659 } 660 661 /* import a key into our keyring */ 662 int 663 netpgp_import_key(netpgp_t *netpgp, char *f) 664 { 665 const unsigned noarmor = 0; 666 const unsigned armor = 1; 667 __ops_io_t *io; 668 int done; 669 670 io = netpgp->io; 671 if ((done = __ops_keyring_fileread(netpgp->pubring, noarmor, f)) == 0) { 672 done = __ops_keyring_fileread(netpgp->pubring, armor, f); 673 } 674 if (!done) { 675 (void) fprintf(io->errs, "Cannot import key from file %s\n", 676 f); 677 return 0; 678 } 679 return __ops_keyring_list(io, netpgp->pubring); 680 } 681 682 /* generate a new key */ 683 int 684 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 685 { 686 __ops_key_t *keypair; 687 __ops_userid_t uid; 688 __ops_output_t *create; 689 const unsigned noarmor = 0; 690 __ops_io_t *io; 691 char *ringfile; 692 int fd; 693 694 (void) memset(&uid, 0x0, sizeof(uid)); 695 io = netpgp->io; 696 /* generate a new key for 'id' */ 697 uid.userid = (unsigned char *) id; 698 keypair = __ops_rsa_new_selfsign_key(numbits, 65537UL, &uid); 699 if (keypair == NULL) { 700 (void) fprintf(io->errs, "Cannot generate key\n"); 701 return 0; 702 } 703 /* write public key, and try to re-read it */ 704 ringfile = netpgp_getvar(netpgp, "pubring"); 705 fd = __ops_setup_file_append(&create, ringfile); 706 if (!__ops_write_xfer_pubkey(create, keypair, noarmor)) { 707 (void) fprintf(io->errs, "Cannot write pubkey\n"); 708 return 0; 709 } 710 __ops_teardown_file_write(create, fd); 711 __ops_keyring_free(netpgp->pubring); 712 if (!__ops_keyring_fileread(netpgp->pubring, noarmor, ringfile)) { 713 (void) fprintf(io->errs, "Cannot read pubring %s\n", ringfile); 714 return 0; 715 } 716 /* write secret key, and try to re-read it */ 717 ringfile = netpgp_getvar(netpgp, "sec ring file"); 718 fd = __ops_setup_file_append(&create, ringfile); 719 if (!__ops_write_xfer_seckey(create, keypair, NULL, 0, noarmor)) { 720 (void) fprintf(io->errs, "Cannot write seckey\n"); 721 return 0; 722 } 723 __ops_teardown_file_write(create, fd); 724 __ops_keyring_free(netpgp->secring); 725 if (!__ops_keyring_fileread(netpgp->secring, noarmor, ringfile)) { 726 (void) fprintf(io->errs, "Can't read secring %s\n", ringfile); 727 return 0; 728 } 729 __ops_keydata_free(keypair); 730 return 1; 731 } 732 733 /* encrypt a file */ 734 int 735 netpgp_encrypt_file(netpgp_t *netpgp, 736 const char *userid, 737 const char *f, 738 char *out, 739 int armored) 740 { 741 const __ops_key_t *keypair; 742 const unsigned overwrite = 1; 743 const char *suffix; 744 __ops_io_t *io; 745 char outname[MAXPATHLEN]; 746 747 io = netpgp->io; 748 if (f == NULL) { 749 (void) fprintf(io->errs, 750 "netpgp_encrypt_file: no filename specified\n"); 751 return 0; 752 } 753 if (userid == NULL) { 754 userid = netpgp_getvar(netpgp, "userid"); 755 } 756 suffix = (armored) ? ".asc" : ".gpg"; 757 keypair = __ops_getkeybyname(io, netpgp->pubring, userid); 758 if (keypair == NULL) { 759 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 760 userid); 761 return 0; 762 } 763 if (out == NULL) { 764 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 765 out = outname; 766 } 767 return (int)__ops_encrypt_file(io, f, out, keypair, (unsigned)armored, 768 overwrite); 769 } 770 771 #define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----\r\n" 772 773 /* decrypt a file */ 774 int 775 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 776 { 777 const unsigned overwrite = 1; 778 __ops_io_t *io; 779 unsigned realarmour; 780 FILE *fp; 781 char buf[BUFSIZ]; 782 783 io = netpgp->io; 784 if (f == NULL) { 785 (void) fprintf(io->errs, 786 "netpgp_decrypt_file: no filename specified\n"); 787 return 0; 788 } 789 realarmour = (unsigned)armored; 790 if ((fp = fopen(f, "r")) == NULL) { 791 (void) fprintf(io->errs, 792 "netpgp_decrypt_file: can't open '%s'\n", f); 793 return 0; 794 } 795 if (fgets(buf, sizeof(buf), fp) == NULL) { 796 realarmour = 0; 797 } else { 798 realarmour = (strcmp(buf, ARMOR_HEAD) == 0); 799 } 800 (void) fclose(fp); 801 return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring, 802 (unsigned)realarmour, overwrite, 803 netpgp->passfp, get_passphrase_cb); 804 } 805 806 /* sign a file */ 807 int 808 netpgp_sign_file(netpgp_t *netpgp, 809 const char *userid, 810 const char *f, 811 char *out, 812 int armored, 813 int cleartext, 814 int detached) 815 { 816 const __ops_key_t *keypair; 817 __ops_seckey_t *seckey; 818 const unsigned overwrite = 1; 819 __ops_io_t *io; 820 char *hashalg; 821 int ret; 822 823 io = netpgp->io; 824 if (f == NULL) { 825 (void) fprintf(io->errs, 826 "netpgp_sign_file: no filename specified\n"); 827 return 0; 828 } 829 if (userid == NULL) { 830 userid = netpgp_getvar(netpgp, "userid"); 831 } 832 /* get key with which to sign */ 833 keypair = __ops_getkeybyname(io, netpgp->secring, userid); 834 if (keypair == NULL) { 835 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 836 userid); 837 return 0; 838 } 839 ret = 1; 840 do { 841 if (netpgp->passfp == NULL) { 842 /* print out the user id */ 843 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey); 844 } 845 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 846 /* now decrypt key */ 847 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp); 848 if (seckey == NULL) { 849 (void) fprintf(io->errs, "Bad passphrase\n"); 850 } 851 } else { 852 __ops_keyring_t *secring; 853 854 secring = netpgp->secring; 855 seckey = &secring->keys[0].key.seckey; 856 } 857 } while (seckey == NULL); 858 /* sign file */ 859 hashalg = netpgp_getvar(netpgp, "hash"); 860 if (detached) { 861 ret = __ops_sign_detached(io, f, out, seckey, hashalg, 862 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 863 get_duration(netpgp_getvar(netpgp, "duration"))); 864 } else { 865 ret = __ops_sign_file(io, f, out, seckey, hashalg, 866 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 867 get_duration(netpgp_getvar(netpgp, "duration")), 868 (unsigned)armored, (unsigned)cleartext, 869 overwrite); 870 } 871 __ops_forget(seckey, sizeof(*seckey)); 872 return ret; 873 } 874 875 /* verify a file */ 876 int 877 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 878 { 879 __ops_validation_t result; 880 __ops_io_t *io; 881 882 (void) memset(&result, 0x0, sizeof(result)); 883 io = netpgp->io; 884 if (in == NULL) { 885 (void) fprintf(io->errs, 886 "netpgp_verify_file: no filename specified\n"); 887 return 0; 888 } 889 if (__ops_validate_file(io, &result, in, out, armored, 890 netpgp->pubring)) { 891 resultp(io, in, &result, netpgp->pubring); 892 return 1; 893 } 894 if (result.validc + result.invalidc + result.unknownc == 0) { 895 (void) fprintf(io->errs, 896 "\"%s\": No signatures found - is this a signed file?\n", 897 in); 898 } else if (result.invalidc == 0 && result.unknownc == 0) { 899 (void) fprintf(io->errs, 900 "\"%s\": file verification failure: invalid signature time\n", in); 901 } else { 902 (void) fprintf(io->errs, 903 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 904 in, result.invalidc, result.unknownc); 905 } 906 return 0; 907 } 908 909 /* sign some memory */ 910 int 911 netpgp_sign_memory(netpgp_t *netpgp, 912 const char *userid, 913 char *mem, 914 size_t size, 915 char *out, 916 size_t outsize, 917 const unsigned armored, 918 const unsigned cleartext) 919 { 920 const __ops_key_t *keypair; 921 __ops_seckey_t *seckey; 922 __ops_memory_t *signedmem; 923 __ops_io_t *io; 924 char *hashalg; 925 int ret; 926 927 io = netpgp->io; 928 if (mem == NULL) { 929 (void) fprintf(io->errs, 930 "netpgp_sign_memory: no memory to sign\n"); 931 return 0; 932 } 933 if (userid == NULL) { 934 userid = netpgp_getvar(netpgp, "userid"); 935 } 936 /* get key with which to sign */ 937 keypair = __ops_getkeybyname(io, netpgp->secring, userid); 938 if (keypair == NULL) { 939 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 940 userid); 941 return 0; 942 } 943 ret = 1; 944 do { 945 if (netpgp->passfp == NULL) { 946 /* print out the user id */ 947 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey); 948 } 949 /* now decrypt key */ 950 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp); 951 if (seckey == NULL) { 952 (void) fprintf(io->errs, "Bad passphrase\n"); 953 } 954 } while (seckey == NULL); 955 /* sign file */ 956 (void) memset(out, 0x0, outsize); 957 hashalg = netpgp_getvar(netpgp, "hash"); 958 signedmem = __ops_sign_buf(io, mem, size, seckey, 959 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 960 get_duration(netpgp_getvar(netpgp, "duration")), 961 hashalg, armored, cleartext); 962 if (signedmem) { 963 size_t m; 964 965 m = MIN(__ops_mem_len(signedmem), outsize); 966 (void) memcpy(out, __ops_mem_data(signedmem), m); 967 __ops_memory_free(signedmem); 968 ret = (int)m; 969 } else { 970 ret = 0; 971 } 972 __ops_forget(seckey, sizeof(*seckey)); 973 return ret; 974 } 975 976 /* verify memory */ 977 int 978 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, 979 void *out, size_t outsize, const int armored) 980 { 981 __ops_validation_t result; 982 __ops_memory_t *signedmem; 983 __ops_memory_t *cat; 984 __ops_io_t *io; 985 size_t m; 986 int ret; 987 988 (void) memset(&result, 0x0, sizeof(result)); 989 io = netpgp->io; 990 if (in == NULL) { 991 (void) fprintf(io->errs, 992 "netpgp_verify_memory: no memory to verify\n"); 993 return 0; 994 } 995 signedmem = __ops_memory_new(); 996 __ops_memory_add(signedmem, in, size); 997 ret = __ops_validate_mem(io, &result, signedmem, 998 (out) ? &cat : NULL, 999 armored, netpgp->pubring); 1000 __ops_memory_free(signedmem); 1001 if (ret) { 1002 resultp(io, "<stdin>", &result, netpgp->pubring); 1003 if (out) { 1004 m = MIN(__ops_mem_len(cat), outsize); 1005 (void) memcpy(out, __ops_mem_data(cat), m); 1006 __ops_memory_free(cat); 1007 } else { 1008 m = 1; 1009 } 1010 return (int)m; 1011 } 1012 if (result.validc + result.invalidc + result.unknownc == 0) { 1013 (void) fprintf(io->errs, 1014 "No signatures found - is this memory signed?\n"); 1015 } else if (result.invalidc == 0 && result.unknownc == 0) { 1016 (void) fprintf(io->errs, 1017 "memory verification failure: invalid signature time\n"); 1018 } else { 1019 (void) fprintf(io->errs, 1020 "memory verification failure: %u invalid signatures, %u unknown signatures\n", 1021 result.invalidc, result.unknownc); 1022 } 1023 return 0; 1024 } 1025 1026 /* encrypt some memory */ 1027 int 1028 netpgp_encrypt_memory(netpgp_t *netpgp, 1029 const char *userid, 1030 void *in, 1031 const size_t insize, 1032 char *out, 1033 size_t outsize, 1034 int armored) 1035 { 1036 const __ops_key_t *keypair; 1037 __ops_memory_t *enc; 1038 __ops_io_t *io; 1039 size_t m; 1040 1041 io = netpgp->io; 1042 if (in == NULL) { 1043 (void) fprintf(io->errs, 1044 "netpgp_encrypt_buf: no memory to encrypt\n"); 1045 return 0; 1046 } 1047 if (userid == NULL) { 1048 userid = netpgp_getvar(netpgp, "userid"); 1049 } 1050 keypair = __ops_getkeybyname(io, netpgp->pubring, userid); 1051 if (keypair == NULL) { 1052 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 1053 userid); 1054 return 0; 1055 } 1056 if (in == out) { 1057 (void) fprintf(io->errs, 1058 "netpgp_encrypt_buf: input and output bufs need to be different\n"); 1059 return 0; 1060 } 1061 if (outsize < insize) { 1062 (void) fprintf(io->errs, 1063 "netpgp_encrypt_buf: input size is larger than output size\n"); 1064 return 0; 1065 } 1066 enc = __ops_encrypt_buf(io, in, insize, keypair, (unsigned)armored); 1067 m = MIN(__ops_mem_len(enc), outsize); 1068 (void) memcpy(out, __ops_mem_data(enc), m); 1069 __ops_memory_free(enc); 1070 return (int)m; 1071 } 1072 1073 /* decrypt a chunk of memory */ 1074 int 1075 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize, 1076 char *out, size_t outsize, const int armored) 1077 { 1078 __ops_memory_t *mem; 1079 __ops_io_t *io; 1080 unsigned realarmour; 1081 size_t m; 1082 1083 io = netpgp->io; 1084 realarmour = (unsigned) armored; 1085 if (input == NULL) { 1086 (void) fprintf(io->errs, 1087 "netpgp_decrypt_memory: no memory\n"); 1088 return 0; 1089 } 1090 realarmour = (strncmp(input, ARMOR_HEAD, sizeof(ARMOR_HEAD) - 1) == 0); 1091 mem = __ops_decrypt_buf(netpgp->io, input, insize, netpgp->secring, 1092 realarmour, netpgp->passfp, 1093 get_passphrase_cb); 1094 m = MIN(__ops_mem_len(mem), outsize); 1095 (void) memcpy(out, __ops_mem_data(mem), m); 1096 __ops_memory_free(mem); 1097 return (int)m; 1098 } 1099 1100 /* wrappers for the ops_debug_level functions we added to openpgpsdk */ 1101 1102 /* set the debugging level per filename */ 1103 int 1104 netpgp_set_debug(const char *f) 1105 { 1106 return __ops_set_debug_level(f); 1107 } 1108 1109 /* get the debugging level per filename */ 1110 int 1111 netpgp_get_debug(const char *f) 1112 { 1113 return __ops_get_debug_level(f); 1114 } 1115 1116 /* return the version for the library */ 1117 const char * 1118 netpgp_get_info(const char *type) 1119 { 1120 return __ops_get_info(type); 1121 } 1122 1123 /* list all the packets in a file */ 1124 int 1125 netpgp_list_packets(netpgp_t *netpgp, char *f, int armour, char *pubringname) 1126 { 1127 __ops_keyring_t *keyring; 1128 const unsigned noarmor = 0; 1129 struct stat st; 1130 __ops_io_t *io; 1131 char ringname[MAXPATHLEN]; 1132 char *homedir; 1133 int ret; 1134 1135 io = netpgp->io; 1136 if (f == NULL) { 1137 (void) fprintf(io->errs, "No file containing packets\n"); 1138 return 0; 1139 } 1140 if (stat(f, &st) < 0) { 1141 (void) fprintf(io->errs, "No such file '%s'\n", f); 1142 return 0; 1143 } 1144 homedir = netpgp_getvar(netpgp, "homedir"); 1145 if (pubringname == NULL) { 1146 (void) snprintf(ringname, sizeof(ringname), 1147 "%s/pubring.gpg", homedir); 1148 pubringname = ringname; 1149 } 1150 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1151 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); 1152 return 0; 1153 } 1154 if (!__ops_keyring_fileread(keyring, noarmor, pubringname)) { 1155 free(keyring); 1156 (void) fprintf(io->errs, "Cannot read pub keyring %s\n", 1157 pubringname); 1158 return 0; 1159 } 1160 netpgp->pubring = keyring; 1161 netpgp_setvar(netpgp, "pubring", pubringname); 1162 ret = __ops_list_packets(io, f, (unsigned)armour, keyring, 1163 netpgp->passfp, 1164 get_passphrase_cb); 1165 free(keyring); 1166 return ret; 1167 } 1168 1169 /* set a variable */ 1170 int 1171 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) 1172 { 1173 int i; 1174 1175 if ((i = findvar(netpgp, name)) < 0) { 1176 /* add the element to the array */ 1177 if (size_arrays(netpgp, netpgp->size + 15)) { 1178 netpgp->name[i = netpgp->c++] = strdup(name); 1179 } 1180 } else { 1181 /* replace the element in the array */ 1182 if (netpgp->value[i]) { 1183 free(netpgp->value[i]); 1184 netpgp->value[i] = NULL; 1185 } 1186 } 1187 /* sanity checks for range of values */ 1188 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { 1189 if (__ops_str_to_hash_alg(value) == OPS_HASH_UNKNOWN) { 1190 return 0; 1191 } 1192 } 1193 netpgp->value[i] = strdup(value); 1194 return 1; 1195 } 1196 1197 /* get a variable's value (NULL if not set) */ 1198 char * 1199 netpgp_getvar(netpgp_t *netpgp, const char *name) 1200 { 1201 int i; 1202 1203 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; 1204 } 1205 1206 /* increment a value */ 1207 int 1208 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) 1209 { 1210 char *cp; 1211 char num[16]; 1212 int val; 1213 1214 val = 0; 1215 if ((cp = netpgp_getvar(netpgp, name)) != NULL) { 1216 val = atoi(cp); 1217 } 1218 (void) snprintf(num, sizeof(num), "%d", val + delta); 1219 netpgp_setvar(netpgp, name, num); 1220 return 1; 1221 } 1222 1223 /* set the home directory value to "home/subdir" */ 1224 int 1225 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) 1226 { 1227 struct stat st; 1228 char d[MAXPATHLEN]; 1229 1230 if (home == NULL) { 1231 if (!quiet) { 1232 (void) fprintf(stderr, "NULL HOME directory\n"); 1233 } 1234 return 0; 1235 } 1236 (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); 1237 if (stat(d, &st) == 0) { 1238 if ((st.st_mode & S_IFMT) == S_IFDIR) { 1239 netpgp_setvar(netpgp, "homedir", d); 1240 return 1; 1241 } 1242 (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", 1243 d); 1244 return 0; 1245 } 1246 if (!quiet) { 1247 (void) fprintf(stderr, 1248 "netpgp: warning homedir \"%s\" not found\n", d); 1249 } 1250 return 1; 1251 } 1252 1253 /* validate all sigs in the pub keyring */ 1254 int 1255 netpgp_validate_sigs(netpgp_t *netpgp) 1256 { 1257 __ops_validation_t result; 1258 1259 return (int)__ops_validate_all_sigs(&result, netpgp->pubring, NULL); 1260 } 1261 1262 #if 0 1263 #include "sshkey.h" 1264 1265 int 1266 netpgp_pgpkey_to_sshkey(netpgp_t *netpgp, char *name, SSHKey *sshkey) 1267 { 1268 const __ops_key_t *pgpkey; 1269 unsigned k; 1270 1271 k = 0; 1272 pgpkey = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, name, &k); 1273 if (pgpkey == NULL) { 1274 pgpkey = __ops_getkeybyname(io, netpgp->pubring, userid); 1275 } 1276 if (pgpkey == NULL) { 1277 (void) fprintf(stderr, "No key matching '%s'\n", name); 1278 return 0; 1279 } 1280 switch(pgpkey->key.pubkey.alg) { 1281 case OPS_PKA_RSA: 1282 sshkey->type = KEY_RSA; 1283 sshkey->rsa = calloc(1, sizeof(*sshkey->rsa); 1284 if (sshkey->rsa == NULL) { 1285 (void) fprintf(stderr, "RSA memory problems\n"); 1286 return 0; 1287 } 1288 sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n; 1289 sshkey->rsa->e = pgpkey->key.pubkey.key.rsa.e; 1290 sshkey->rsa->d = pgpkey->key.seckey.key.rsa.d; 1291 sshkey->rsa->p = pgpkey->key.seckey.key.rsa.p; 1292 sshkey->rsa->q = pgpkey->key.seckey.key.rsa.q; 1293 sshkey->rsa->iqmp = pgpkey->key.seckey.key.rsa.u; 1294 break; 1295 case OPS_PKA_DSA: 1296 sshkey->type = KEY_DSA; 1297 sshkey->dsa = calloc(1, sizeof(*sshkey->dsa); 1298 if (sshkey->dsa == NULL) { 1299 (void) fprintf(stderr, "DSA memory problems\n"); 1300 return 0; 1301 } 1302 sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n; 1303 key->dsa->p = pgpkey->key.pubkey.key.dsa.p; 1304 key->dsa->q = pgpkey->key.pubkey.key.dsa.q; 1305 key->dsa->g = pgpkey->key.pubkey.key.dsa.g; 1306 key->dsa->pub_key = pgpkey->key.pubkey.key.dsa.y; 1307 key->dsa->priv_key = pgpkey->key.seckey.key.dsa.x; 1308 break; 1309 default: 1310 (void) fprintf(stderr, "weird type\n"); 1311 return 0; 1312 } 1313 return 1; 1314 } 1315 #endif 1316