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.69 2010/08/15 16:10:56 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, (int)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 regfree(&keyre); 119 return 1; 120 } 121 122 /* small function to pretty print an 8-character raw userid */ 123 static char * 124 userid_to_id(const uint8_t *userid, char *id) 125 { 126 static const char *hexes = "0123456789abcdef"; 127 int i; 128 129 for (i = 0; i < 8 ; i++) { 130 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; 131 id[(i * 2) + 1] = hexes[userid[i] & 0xf]; 132 } 133 id[8 * 2] = 0x0; 134 return id; 135 } 136 137 /* print out the successful signature information */ 138 static void 139 resultp(__ops_io_t *io, 140 const char *f, 141 __ops_validation_t *res, 142 __ops_keyring_t *ring) 143 { 144 const __ops_key_t *key; 145 __ops_pubkey_t *sigkey; 146 unsigned from; 147 unsigned i; 148 time_t t; 149 char id[MAX_ID_LENGTH + 1]; 150 151 for (i = 0; i < res->validc; i++) { 152 (void) fprintf(io->res, 153 "Good signature for %s made %s", 154 (f) ? f : "<stdin>", 155 ctime(&res->valid_sigs[i].birthtime)); 156 if (res->duration > 0) { 157 t = res->birthtime + res->duration; 158 (void) fprintf(io->res, "Valid until %s", ctime(&t)); 159 } 160 (void) fprintf(io->res, 161 "using %s key %s\n", 162 __ops_show_pka(res->valid_sigs[i].key_alg), 163 userid_to_id(res->valid_sigs[i].signer_id, id)); 164 from = 0; 165 key = __ops_getkeybyid(io, ring, 166 (const uint8_t *) res->valid_sigs[i].signer_id, 167 &from, &sigkey); 168 if (sigkey == &key->enckey) { 169 (void) fprintf(io->res, 170 "WARNING: signature for %s made with encryption key\n", 171 (f) ? f : "<stdin>"); 172 } 173 __ops_print_keydata(io, ring, key, "pub", &key->key.pubkey, 0); 174 } 175 } 176 177 /* check there's enough space in the arrays */ 178 static int 179 size_arrays(netpgp_t *netpgp, unsigned needed) 180 { 181 char **temp; 182 183 if (netpgp->size == 0) { 184 /* only get here first time around */ 185 netpgp->size = needed; 186 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { 187 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 188 return 0; 189 } 190 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { 191 free(netpgp->name); 192 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 193 return 0; 194 } 195 } else if (netpgp->c == netpgp->size) { 196 /* only uses 'needed' when filled array */ 197 netpgp->size += needed; 198 temp = realloc(netpgp->name, sizeof(char *) * needed); 199 if (temp == NULL) { 200 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 201 return 0; 202 } 203 netpgp->name = temp; 204 temp = realloc(netpgp->value, sizeof(char *) * needed); 205 if (temp == NULL) { 206 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 207 return 0; 208 } 209 netpgp->value = temp; 210 } 211 return 1; 212 } 213 214 /* find the name in the array */ 215 static int 216 findvar(netpgp_t *netpgp, const char *name) 217 { 218 unsigned i; 219 220 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { 221 } 222 return (i == netpgp->c) ? -1 : (int)i; 223 } 224 225 /* read a keyring and return it */ 226 static void * 227 readkeyring(netpgp_t *netpgp, const char *name) 228 { 229 __ops_keyring_t *keyring; 230 const unsigned noarmor = 0; 231 char f[MAXPATHLEN]; 232 char *filename; 233 char *homedir; 234 235 homedir = netpgp_getvar(netpgp, "homedir"); 236 if ((filename = netpgp_getvar(netpgp, name)) == NULL) { 237 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); 238 filename = f; 239 } 240 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 241 (void) fprintf(stderr, "readkeyring: bad alloc\n"); 242 return NULL; 243 } 244 if (!__ops_keyring_fileread(keyring, noarmor, filename)) { 245 free(keyring); 246 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 247 return NULL; 248 } 249 netpgp_setvar(netpgp, name, filename); 250 return keyring; 251 } 252 253 /* read keys from ssh key files */ 254 static int 255 readsshkeys(netpgp_t *netpgp, char *homedir, const char *needseckey) 256 { 257 __ops_keyring_t *pubring; 258 __ops_keyring_t *secring; 259 unsigned hashtype; 260 char *hash; 261 char f[MAXPATHLEN]; 262 char *filename; 263 264 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) { 265 (void) snprintf(f, sizeof(f), "%s/id_rsa.pub", homedir); 266 filename = f; 267 } 268 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { 269 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 270 return 0; 271 } 272 /* openssh2 keys use md5 by default */ 273 hashtype = OPS_HASH_MD5; 274 if ((hash = netpgp_getvar(netpgp, "hash")) != NULL) { 275 /* openssh 2 hasn't really caught up to anything else yet */ 276 if (netpgp_strcasecmp(hash, "md5") == 0) { 277 hashtype = OPS_HASH_MD5; 278 } else if (netpgp_strcasecmp(hash, "sha1") == 0) { 279 hashtype = OPS_HASH_SHA1; 280 } else if (netpgp_strcasecmp(hash, "sha256") == 0) { 281 hashtype = OPS_HASH_SHA256; 282 } 283 } 284 if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL, hashtype)) { 285 free(pubring); 286 (void) fprintf(stderr, "readsshkeys: can't read %s\n", 287 filename); 288 return 0; 289 } 290 if (netpgp->pubring == NULL) { 291 netpgp->pubring = pubring; 292 } else { 293 __ops_append_keyring(netpgp->pubring, pubring); 294 } 295 if (needseckey) { 296 netpgp_setvar(netpgp, "sshpubfile", filename); 297 /* try to take the ".pub" off the end */ 298 if (filename == f) { 299 f[strlen(f) - 4] = 0x0; 300 } else { 301 (void) snprintf(f, sizeof(f), "%.*s", 302 (int)strlen(filename) - 4, filename); 303 filename = f; 304 } 305 if ((secring = calloc(1, sizeof(*secring))) == NULL) { 306 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 307 return 0; 308 } 309 if (!__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename, hashtype)) { 310 (void) fprintf(stderr, "readsshkeys: can't read sec %s\n", filename); 311 return 0; 312 } 313 netpgp->secring = secring; 314 netpgp_setvar(netpgp, "sshsecfile", filename); 315 } 316 return 1; 317 } 318 319 /* set ssh uid to first one in pubring */ 320 static void 321 set_first_pubring(__ops_keyring_t *pubring, char *id, size_t len, int last) 322 { 323 uint8_t *src; 324 int i; 325 int n; 326 327 (void) memset(id, 0x0, len); 328 src = pubring->keys[(last) ? pubring->keyc - 1 : 0].sigid; 329 for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) { 330 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); 331 } 332 id[n] = 0x0; 333 } 334 335 /* find the time - in a specific %Y-%m-%d format - using a regexp */ 336 static int 337 grabdate(char *s, int64_t *t) 338 { 339 static regex_t r; 340 static int compiled; 341 regmatch_t matches[10]; 342 struct tm tm; 343 344 if (!compiled) { 345 compiled = 1; 346 (void) regcomp(&r, "([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])", REG_EXTENDED); 347 } 348 if (regexec(&r, s, 10, matches, 0) == 0) { 349 (void) memset(&tm, 0x0, sizeof(tm)); 350 tm.tm_year = (int)strtol(&s[(int)matches[1].rm_so], NULL, 10); 351 tm.tm_mon = (int)strtol(&s[(int)matches[2].rm_so], NULL, 10) - 1; 352 tm.tm_mday = (int)strtol(&s[(int)matches[3].rm_so], NULL, 10); 353 *t = mktime(&tm); 354 return 1; 355 } 356 return 0; 357 } 358 359 /* get expiration in seconds */ 360 static uint64_t 361 get_duration(char *s) 362 { 363 uint64_t now; 364 int64_t t; 365 char *mult; 366 367 if (s == NULL) { 368 return 0; 369 } 370 now = (uint64_t)strtoull(s, NULL, 10); 371 if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) { 372 switch(*mult) { 373 case 'h': 374 return now * 60 * 60; 375 case 'd': 376 return now * 60 * 60 * 24; 377 case 'w': 378 return now * 60 * 60 * 24 * 7; 379 case 'm': 380 return now * 60 * 60 * 24 * 31; 381 case 'y': 382 return now * 60 * 60 * 24 * 365; 383 } 384 } 385 if (grabdate(s, &t)) { 386 return t; 387 } 388 return (uint64_t)strtoll(s, NULL, 10); 389 } 390 391 /* get birthtime in seconds */ 392 static int64_t 393 get_birthtime(char *s) 394 { 395 int64_t t; 396 397 if (s == NULL) { 398 return time(NULL); 399 } 400 if (grabdate(s, &t)) { 401 return t; 402 } 403 return (uint64_t)strtoll(s, NULL, 10); 404 } 405 406 /* resolve the userid */ 407 static const __ops_key_t * 408 resolve_userid(netpgp_t *netpgp, const __ops_keyring_t *keyring, const char *userid) 409 { 410 const __ops_key_t *key; 411 __ops_io_t *io; 412 413 if (userid == NULL) { 414 userid = netpgp_getvar(netpgp, "userid"); 415 } else if (userid[0] == '0' && userid[1] == 'x') { 416 userid += 2; 417 } 418 io = netpgp->io; 419 if ((key = __ops_getkeybyname(io, keyring, userid)) == NULL) { 420 (void) fprintf(io->errs, "Can't find key '%s'\n", userid); 421 } 422 return key; 423 } 424 425 /* append a key to a keyring */ 426 static int 427 appendkey(__ops_io_t *io, __ops_key_t *key, char *ringfile) 428 { 429 __ops_output_t *create; 430 const unsigned noarmor = 0; 431 int fd; 432 433 if ((fd = __ops_setup_file_append(&create, ringfile)) < 0) { 434 fd = __ops_setup_file_write(&create, ringfile, 0); 435 } 436 if (fd < 0) { 437 (void) fprintf(io->errs, "can't open pubring '%s'\n", ringfile); 438 return 0; 439 } 440 if (!__ops_write_xfer_pubkey(create, key, noarmor)) { 441 (void) fprintf(io->errs, "Cannot write pubkey\n"); 442 return 0; 443 } 444 __ops_teardown_file_write(create, fd); 445 return 1; 446 } 447 448 /* return 1 if the file contains ascii-armoured text */ 449 static unsigned 450 isarmoured(__ops_io_t *io, const char *f, const void *memory, const char *text) 451 { 452 unsigned armoured; 453 FILE *fp; 454 char buf[BUFSIZ]; 455 456 armoured = 0; 457 if (f) { 458 if ((fp = fopen(f, "r")) == NULL) { 459 (void) fprintf(io->errs, "isarmoured: can't open '%s'\n", f); 460 return 0; 461 } 462 if (fgets(buf, (int)sizeof(buf), fp) != NULL) { 463 armoured = (strncmp(buf, text, strlen(text)) == 0); 464 } 465 (void) fclose(fp); 466 } else { 467 armoured = (strncmp(memory, text, strlen(text)) == 0); 468 } 469 return armoured; 470 } 471 472 /***************************************************************************/ 473 /* exported functions start here */ 474 /***************************************************************************/ 475 476 /* initialise a netpgp_t structure */ 477 int 478 netpgp_init(netpgp_t *netpgp) 479 { 480 __ops_io_t *io; 481 char id[MAX_ID_LENGTH]; 482 char *homedir; 483 char *userid; 484 char *stream; 485 char *passfd; 486 char *results; 487 int coredumps; 488 int last; 489 490 #ifdef HAVE_SYS_RESOURCE_H 491 struct rlimit limit; 492 493 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 494 if (!coredumps) { 495 (void) memset(&limit, 0x0, sizeof(limit)); 496 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 497 (void) fprintf(stderr, 498 "netpgp: warning - can't turn off core dumps\n"); 499 coredumps = 1; 500 } 501 } 502 #else 503 coredumps = 1; 504 #endif 505 if ((io = calloc(1, sizeof(*io))) == NULL) { 506 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 507 return 0; 508 } 509 io->outs = stdout; 510 if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && 511 strcmp(stream, "<stderr>") == 0) { 512 io->outs = stderr; 513 } 514 io->errs = stderr; 515 if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && 516 strcmp(stream, "<stdout>") == 0) { 517 io->errs = stdout; 518 } 519 if ((results = netpgp_getvar(netpgp, "res")) == NULL) { 520 io->res = io->errs; 521 } else if (strcmp(results, "<stdout>") == 0) { 522 io->res = stdout; 523 } else if (strcmp(results, "<stderr>") == 0) { 524 io->res = stderr; 525 } else { 526 if ((io->res = fopen(results, "w")) == NULL) { 527 (void) fprintf(io->errs, "Can't open results %s for writing\n", 528 results); 529 free(io); 530 return 0; 531 } 532 } 533 netpgp->io = io; 534 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 535 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 536 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 537 passfd); 538 return 0; 539 } 540 if (coredumps) { 541 (void) fprintf(io->errs, 542 "netpgp: warning: core dumps enabled\n"); 543 } 544 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 545 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 546 return 0; 547 } 548 /* read from either gpg files or ssh keys */ 549 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 550 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 551 (void) memset(id, 0x0, sizeof(id)); 552 (void) conffile(netpgp, homedir, id, sizeof(id)); 553 if (id[0] != 0x0) { 554 netpgp_setvar(netpgp, "userid", userid = id); 555 } 556 } 557 if (userid == NULL) { 558 if (netpgp_getvar(netpgp, "need userid") != NULL) { 559 (void) fprintf(io->errs, 560 "Cannot find user id\n"); 561 return 0; 562 } 563 } else { 564 (void) netpgp_setvar(netpgp, "userid", userid); 565 } 566 netpgp->pubring = readkeyring(netpgp, "pubring"); 567 if (netpgp->pubring == NULL) { 568 (void) fprintf(io->errs, "Can't read pub keyring\n"); 569 return 0; 570 } 571 netpgp->secring = readkeyring(netpgp, "secring"); 572 if (netpgp->secring == NULL) { 573 (void) fprintf(io->errs, "Can't read sec keyring\n"); 574 return 0; 575 } 576 } else { 577 last = (netpgp->pubring != NULL); 578 if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need userid"))) { 579 (void) fprintf(io->errs, "Can't read ssh keys\n"); 580 return 0; 581 } 582 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 583 set_first_pubring(netpgp->pubring, id, sizeof(id), last); 584 netpgp_setvar(netpgp, "userid", userid = id); 585 } 586 if (userid == NULL) { 587 if (netpgp_getvar(netpgp, "need userid") != NULL) { 588 (void) fprintf(io->errs, 589 "Cannot find user id\n"); 590 return 0; 591 } 592 } else { 593 (void) netpgp_setvar(netpgp, "userid", userid); 594 } 595 } 596 return 1; 597 } 598 599 /* finish off with the netpgp_t struct */ 600 int 601 netpgp_end(netpgp_t *netpgp) 602 { 603 unsigned i; 604 605 for (i = 0 ; i < netpgp->c ; i++) { 606 if (netpgp->name[i] != NULL) { 607 free(netpgp->name[i]); 608 } 609 if (netpgp->value[i] != NULL) { 610 free(netpgp->value[i]); 611 } 612 } 613 if (netpgp->name != NULL) { 614 free(netpgp->name); 615 } 616 if (netpgp->value != NULL) { 617 free(netpgp->value); 618 } 619 if (netpgp->pubring != NULL) { 620 __ops_keyring_free(netpgp->pubring); 621 } 622 if (netpgp->secring != NULL) { 623 __ops_keyring_free(netpgp->secring); 624 } 625 free(netpgp->io); 626 return 1; 627 } 628 629 /* list the keys in a keyring */ 630 int 631 netpgp_list_keys(netpgp_t *netpgp, const int psigs) 632 { 633 if (netpgp->pubring == NULL) { 634 (void) fprintf(stderr, "No keyring\n"); 635 return 0; 636 } 637 return __ops_keyring_list(netpgp->io, netpgp->pubring, psigs); 638 } 639 640 /* list the keys in a keyring, returning a JSON string */ 641 int 642 netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs) 643 { 644 mj_t obj; 645 int ret; 646 647 if (netpgp->pubring == NULL) { 648 (void) fprintf(stderr, "No keyring\n"); 649 return 0; 650 } 651 (void) memset(&obj, 0x0, sizeof(obj)); 652 if (!__ops_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) { 653 (void) fprintf(stderr, "No keys in keyring\n"); 654 return 0; 655 } 656 ret = mj_asprint(json, &obj); 657 mj_delete(&obj); 658 return ret; 659 } 660 661 DEFINE_ARRAY(strings_t, char *); 662 663 #ifndef HKP_VERSION 664 #define HKP_VERSION 1 665 #endif 666 667 /* find and list some keys in a keyring */ 668 int 669 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs) 670 { 671 const __ops_key_t *key; 672 unsigned k; 673 strings_t pubs; 674 FILE *fp = (FILE *)vp; 675 676 if (name[0] == '0' && name[1] == 'x') { 677 name += 2; 678 } 679 (void) memset(&pubs, 0x0, sizeof(pubs)); 680 k = 0; 681 do { 682 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 683 name, &k); 684 if (key != NULL) { 685 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 686 "netpgp_match_keys", return 0); 687 if (strcmp(fmt, "mr") == 0) { 688 __ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 689 key, &pubs.v[pubs.c], 690 &key->key.pubkey, psigs); 691 } else { 692 __ops_sprint_keydata(netpgp->io, netpgp->pubring, 693 key, &pubs.v[pubs.c], 694 "pub", 695 &key->key.pubkey, psigs); 696 } 697 if (pubs.v[pubs.c] != NULL) { 698 pubs.c += 1; 699 } 700 k += 1; 701 } 702 } while (key != NULL); 703 if (strcmp(fmt, "mr") == 0) { 704 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 705 } else { 706 (void) fprintf(fp, "%d key%s found\n", pubs.c, 707 (pubs.c == 1) ? "" : "s"); 708 } 709 for (k = 0 ; k < pubs.c ; k++) { 710 (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : ""); 711 free(pubs.v[k]); 712 } 713 free(pubs.v); 714 return pubs.c; 715 } 716 717 /* find and list some keys in a keyring - return JSON string */ 718 int 719 netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs) 720 { 721 const __ops_key_t *key; 722 unsigned k; 723 mj_t id_array; 724 int ret; 725 726 if (name[0] == '0' && name[1] == 'x') { 727 name += 2; 728 } 729 (void) memset(&id_array, 0x0, sizeof(id_array)); 730 k = 0; 731 *json = NULL; 732 mj_create(&id_array, "array"); 733 do { 734 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 735 name, &k); 736 if (key != NULL) { 737 if (strcmp(fmt, "mr") == 0) { 738 #if 0 739 __ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 740 key, &pubs.v[pubs.c], 741 &key->key.pubkey, psigs); 742 #endif 743 } else { 744 ALLOC(mj_t, id_array.value.v, id_array.size, 745 id_array.c, 10, 10, "netpgp_match_keys_json", return 0); 746 __ops_sprint_mj(netpgp->io, netpgp->pubring, 747 key, &id_array.value.v[id_array.c++], 748 "signature ", 749 &key->key.pubkey, psigs); 750 } 751 k += 1; 752 } 753 } while (key != NULL); 754 ret = mj_asprint(json, &id_array); 755 mj_delete(&id_array); 756 return ret; 757 } 758 759 /* find and list some public keys in a keyring */ 760 int 761 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) 762 { 763 const __ops_key_t *key; 764 unsigned k; 765 strings_t pubs; 766 FILE *fp = (FILE *)vp; 767 768 (void) memset(&pubs, 0x0, sizeof(pubs)); 769 do { 770 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, 771 name, &k); 772 if (key != NULL) { 773 char out[1024 * 64]; 774 775 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 776 "netpgp_match_pubkeys", return 0); 777 (void) __ops_sprint_pubkey(key, out, sizeof(out)); 778 pubs.v[pubs.c++] = netpgp_strdup(out); 779 k += 1; 780 } 781 } while (key != NULL); 782 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 783 for (k = 0 ; k < pubs.c ; k++) { 784 (void) fprintf(fp, "%s", pubs.v[k]); 785 free(pubs.v[k]); 786 } 787 free(pubs.v); 788 return pubs.c; 789 } 790 791 /* find a key in a keyring */ 792 int 793 netpgp_find_key(netpgp_t *netpgp, char *id) 794 { 795 __ops_io_t *io; 796 797 io = netpgp->io; 798 if (id == NULL) { 799 (void) fprintf(io->errs, "NULL id to search for\n"); 800 return 0; 801 } 802 return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 803 } 804 805 /* get a key in a keyring */ 806 char * 807 netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt) 808 { 809 const __ops_key_t *key; 810 char *newkey; 811 812 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 813 return NULL; 814 } 815 if (strcmp(fmt, "mr") == 0) { 816 return (__ops_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 817 key, &newkey, 818 &key->key.pubkey, 819 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 820 } 821 return (__ops_sprint_keydata(netpgp->io, netpgp->pubring, 822 key, &newkey, "pub", 823 &key->key.pubkey, 824 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 825 } 826 827 /* export a given key */ 828 char * 829 netpgp_export_key(netpgp_t *netpgp, char *name) 830 { 831 const __ops_key_t *key; 832 __ops_io_t *io; 833 834 io = netpgp->io; 835 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 836 return NULL; 837 } 838 return __ops_export_key(io, key, NULL); 839 } 840 841 #define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----" 842 843 /* import a key into our keyring */ 844 int 845 netpgp_import_key(netpgp_t *netpgp, char *f) 846 { 847 __ops_io_t *io; 848 unsigned realarmor; 849 int done; 850 851 io = netpgp->io; 852 realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD); 853 done = __ops_keyring_fileread(netpgp->pubring, realarmor, f); 854 if (!done) { 855 (void) fprintf(io->errs, "Cannot import key from file %s\n", f); 856 return 0; 857 } 858 return __ops_keyring_list(io, netpgp->pubring, 0); 859 } 860 861 /* generate a new key */ 862 int 863 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 864 { 865 __ops_output_t *create; 866 const unsigned noarmor = 0; 867 __ops_key_t *key; 868 __ops_io_t *io; 869 uint8_t *uid; 870 char newid[1024]; 871 char filename[MAXPATHLEN]; 872 char dir[MAXPATHLEN]; 873 char *cp; 874 char *ringfile; 875 int fd; 876 877 uid = NULL; 878 io = netpgp->io; 879 /* generate a new key */ 880 if (id) { 881 (void) snprintf(newid, sizeof(newid), "%s", id); 882 } else { 883 (void) snprintf(newid, sizeof(newid), "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME")); 884 } 885 uid = (uint8_t *)newid; 886 key = __ops_rsa_new_selfsign_key(numbits, 65537UL, uid, netpgp_getvar(netpgp, "hash")); 887 if (key == NULL) { 888 (void) fprintf(io->errs, "Cannot generate key\n"); 889 return 0; 890 } 891 cp = NULL; 892 __ops_sprint_keydata(netpgp->io, NULL, key, &cp, "pub", &key->key.seckey.pubkey, 0); 893 (void) fprintf(stdout, "%s", cp); 894 /* write public key */ 895 (void) snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[31]); 896 if (mkdir(dir, 0700) < 0) { 897 (void) fprintf(io->errs, "can't mkdir '%s'\n", dir); 898 return 0; 899 } 900 (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir); 901 (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir); 902 if (!appendkey(io, key, ringfile)) { 903 (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile); 904 return 0; 905 } 906 if (netpgp->pubring != NULL) { 907 __ops_keyring_free(netpgp->pubring); 908 } 909 /* write secret key */ 910 (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir); 911 if ((fd = __ops_setup_file_append(&create, ringfile)) < 0) { 912 fd = __ops_setup_file_write(&create, ringfile, 0); 913 } 914 if (fd < 0) { 915 (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile); 916 return 0; 917 } 918 if (!__ops_write_xfer_seckey(create, key, NULL, 0, noarmor)) { 919 (void) fprintf(io->errs, "Cannot write seckey\n"); 920 return 0; 921 } 922 __ops_teardown_file_write(create, fd); 923 if (netpgp->secring != NULL) { 924 __ops_keyring_free(netpgp->secring); 925 } 926 __ops_keydata_free(key); 927 free(cp); 928 return 1; 929 } 930 931 /* encrypt a file */ 932 int 933 netpgp_encrypt_file(netpgp_t *netpgp, 934 const char *userid, 935 const char *f, 936 char *out, 937 int armored) 938 { 939 const __ops_key_t *key; 940 const unsigned overwrite = 1; 941 const char *suffix; 942 __ops_io_t *io; 943 char outname[MAXPATHLEN]; 944 945 io = netpgp->io; 946 if (f == NULL) { 947 (void) fprintf(io->errs, 948 "netpgp_encrypt_file: no filename specified\n"); 949 return 0; 950 } 951 suffix = (armored) ? ".asc" : ".gpg"; 952 /* get key with which to sign */ 953 if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 954 return 0; 955 } 956 if (out == NULL) { 957 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 958 out = outname; 959 } 960 return (int)__ops_encrypt_file(io, f, out, key, (unsigned)armored, 961 overwrite); 962 } 963 964 #define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----" 965 966 /* decrypt a file */ 967 int 968 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 969 { 970 const unsigned overwrite = 1; 971 __ops_io_t *io; 972 unsigned realarmor; 973 974 __OPS_USED(armored); 975 io = netpgp->io; 976 if (f == NULL) { 977 (void) fprintf(io->errs, 978 "netpgp_decrypt_file: no filename specified\n"); 979 return 0; 980 } 981 realarmor = isarmoured(io, f, NULL, ARMOR_HEAD); 982 return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring, 983 netpgp->pubring, 984 realarmor, overwrite, 985 netpgp->passfp, get_passphrase_cb); 986 } 987 988 /* sign a file */ 989 int 990 netpgp_sign_file(netpgp_t *netpgp, 991 const char *userid, 992 const char *f, 993 char *out, 994 int armored, 995 int cleartext, 996 int detached) 997 { 998 const __ops_key_t *keypair; 999 const __ops_key_t *pubkey; 1000 __ops_seckey_t *seckey; 1001 const unsigned overwrite = 1; 1002 __ops_io_t *io; 1003 const char *hashalg; 1004 int ret; 1005 1006 io = netpgp->io; 1007 if (f == NULL) { 1008 (void) fprintf(io->errs, 1009 "netpgp_sign_file: no filename specified\n"); 1010 return 0; 1011 } 1012 /* get key with which to sign */ 1013 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1014 return 0; 1015 } 1016 ret = 1; 1017 do { 1018 if (netpgp->passfp == NULL) { 1019 /* print out the user id */ 1020 pubkey = __ops_getkeybyname(io, netpgp->pubring, userid); 1021 if (pubkey == NULL) { 1022 (void) fprintf(io->errs, 1023 "netpgp: warning - using pubkey from secring\n"); 1024 __ops_print_keydata(io, netpgp->pubring, keypair, "signature ", 1025 &keypair->key.seckey.pubkey, 0); 1026 } else { 1027 __ops_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1028 &pubkey->key.pubkey, 0); 1029 } 1030 } 1031 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1032 /* now decrypt key */ 1033 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp); 1034 if (seckey == NULL) { 1035 (void) fprintf(io->errs, "Bad passphrase\n"); 1036 } 1037 } else { 1038 __ops_keyring_t *secring; 1039 1040 secring = netpgp->secring; 1041 seckey = &secring->keys[0].key.seckey; 1042 } 1043 } while (seckey == NULL); 1044 /* sign file */ 1045 hashalg = netpgp_getvar(netpgp, "hash"); 1046 if (seckey->pubkey.alg == OPS_PKA_DSA) { 1047 hashalg = "sha1"; 1048 } 1049 if (detached) { 1050 ret = __ops_sign_detached(io, f, out, seckey, hashalg, 1051 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1052 get_duration(netpgp_getvar(netpgp, "duration")), 1053 (unsigned)armored, 1054 overwrite); 1055 } else { 1056 ret = __ops_sign_file(io, f, out, seckey, hashalg, 1057 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1058 get_duration(netpgp_getvar(netpgp, "duration")), 1059 (unsigned)armored, (unsigned)cleartext, 1060 overwrite); 1061 } 1062 __ops_forget(seckey, (unsigned)sizeof(*seckey)); 1063 return ret; 1064 } 1065 1066 #define ARMOR_SIG_HEAD "-----BEGIN PGP SIGNATURE-----\r\n" 1067 1068 /* verify a file */ 1069 int 1070 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 1071 { 1072 __ops_validation_t result; 1073 __ops_io_t *io; 1074 unsigned realarmor; 1075 1076 __OPS_USED(armored); 1077 (void) memset(&result, 0x0, sizeof(result)); 1078 io = netpgp->io; 1079 if (in == NULL) { 1080 (void) fprintf(io->errs, 1081 "netpgp_verify_file: no filename specified\n"); 1082 return 0; 1083 } 1084 realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD); 1085 if (__ops_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) { 1086 resultp(io, in, &result, netpgp->pubring); 1087 return 1; 1088 } 1089 if (result.validc + result.invalidc + result.unknownc == 0) { 1090 (void) fprintf(io->errs, 1091 "\"%s\": No signatures found - is this a signed file?\n", 1092 in); 1093 } else if (result.invalidc == 0 && result.unknownc == 0) { 1094 (void) fprintf(io->errs, 1095 "\"%s\": file verification failure: invalid signature time\n", in); 1096 } else { 1097 (void) fprintf(io->errs, 1098 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 1099 in, result.invalidc, result.unknownc); 1100 } 1101 return 0; 1102 } 1103 1104 /* sign some memory */ 1105 int 1106 netpgp_sign_memory(netpgp_t *netpgp, 1107 const char *userid, 1108 char *mem, 1109 size_t size, 1110 char *out, 1111 size_t outsize, 1112 const unsigned armored, 1113 const unsigned cleartext) 1114 { 1115 const __ops_key_t *keypair; 1116 const __ops_key_t *pubkey; 1117 __ops_seckey_t *seckey; 1118 __ops_memory_t *signedmem; 1119 __ops_io_t *io; 1120 const char *hashalg; 1121 int ret; 1122 1123 io = netpgp->io; 1124 if (mem == NULL) { 1125 (void) fprintf(io->errs, 1126 "netpgp_sign_memory: no memory to sign\n"); 1127 return 0; 1128 } 1129 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1130 return 0; 1131 } 1132 ret = 1; 1133 do { 1134 if (netpgp->passfp == NULL) { 1135 /* print out the user id */ 1136 pubkey = __ops_getkeybyname(io, netpgp->pubring, userid); 1137 if (pubkey == NULL) { 1138 (void) fprintf(io->errs, 1139 "netpgp: warning - using pubkey from secring\n"); 1140 __ops_print_keydata(io, netpgp->pubring, keypair, "pub", 1141 &keypair->key.seckey.pubkey, 0); 1142 } else { 1143 __ops_print_keydata(io, netpgp->pubring, pubkey, "pub", &pubkey->key.pubkey, 0); 1144 } 1145 } 1146 /* now decrypt key */ 1147 seckey = __ops_decrypt_seckey(keypair, netpgp->passfp); 1148 if (seckey == NULL) { 1149 (void) fprintf(io->errs, "Bad passphrase\n"); 1150 } 1151 } while (seckey == NULL); 1152 /* sign file */ 1153 (void) memset(out, 0x0, outsize); 1154 hashalg = netpgp_getvar(netpgp, "hash"); 1155 if (seckey->pubkey.alg == OPS_PKA_DSA) { 1156 hashalg = "sha1"; 1157 } 1158 signedmem = __ops_sign_buf(io, mem, size, seckey, 1159 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1160 get_duration(netpgp_getvar(netpgp, "duration")), 1161 hashalg, armored, cleartext); 1162 if (signedmem) { 1163 size_t m; 1164 1165 m = MIN(__ops_mem_len(signedmem), outsize); 1166 (void) memcpy(out, __ops_mem_data(signedmem), m); 1167 __ops_memory_free(signedmem); 1168 ret = (int)m; 1169 } else { 1170 ret = 0; 1171 } 1172 __ops_forget(seckey, (unsigned)sizeof(*seckey)); 1173 return ret; 1174 } 1175 1176 /* verify memory */ 1177 int 1178 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, 1179 void *out, size_t outsize, const int armored) 1180 { 1181 __ops_validation_t result; 1182 __ops_memory_t *signedmem; 1183 __ops_memory_t *cat; 1184 __ops_io_t *io; 1185 size_t m; 1186 int ret; 1187 1188 (void) memset(&result, 0x0, sizeof(result)); 1189 io = netpgp->io; 1190 if (in == NULL) { 1191 (void) fprintf(io->errs, 1192 "netpgp_verify_memory: no memory to verify\n"); 1193 return 0; 1194 } 1195 signedmem = __ops_memory_new(); 1196 __ops_memory_add(signedmem, in, size); 1197 if (out) { 1198 cat = __ops_memory_new(); 1199 } 1200 ret = __ops_validate_mem(io, &result, signedmem, 1201 (out) ? &cat : NULL, 1202 armored, netpgp->pubring); 1203 __ops_memory_free(signedmem); 1204 if (ret) { 1205 resultp(io, "<stdin>", &result, netpgp->pubring); 1206 if (out) { 1207 m = MIN(__ops_mem_len(cat), outsize); 1208 (void) memcpy(out, __ops_mem_data(cat), m); 1209 __ops_memory_free(cat); 1210 } else { 1211 m = 1; 1212 } 1213 return (int)m; 1214 } 1215 if (result.validc + result.invalidc + result.unknownc == 0) { 1216 (void) fprintf(io->errs, 1217 "No signatures found - is this memory signed?\n"); 1218 } else if (result.invalidc == 0 && result.unknownc == 0) { 1219 (void) fprintf(io->errs, 1220 "memory verification failure: invalid signature time\n"); 1221 } else { 1222 (void) fprintf(io->errs, 1223 "memory verification failure: %u invalid signatures, %u unknown signatures\n", 1224 result.invalidc, result.unknownc); 1225 } 1226 return 0; 1227 } 1228 1229 /* encrypt some memory */ 1230 int 1231 netpgp_encrypt_memory(netpgp_t *netpgp, 1232 const char *userid, 1233 void *in, 1234 const size_t insize, 1235 char *out, 1236 size_t outsize, 1237 int armored) 1238 { 1239 const __ops_key_t *keypair; 1240 __ops_memory_t *enc; 1241 __ops_io_t *io; 1242 size_t m; 1243 1244 io = netpgp->io; 1245 if (in == NULL) { 1246 (void) fprintf(io->errs, 1247 "netpgp_encrypt_buf: no memory to encrypt\n"); 1248 return 0; 1249 } 1250 if ((keypair = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1251 return 0; 1252 } 1253 if (in == out) { 1254 (void) fprintf(io->errs, 1255 "netpgp_encrypt_buf: input and output bufs need to be different\n"); 1256 return 0; 1257 } 1258 if (outsize < insize) { 1259 (void) fprintf(io->errs, 1260 "netpgp_encrypt_buf: input size is larger than output size\n"); 1261 return 0; 1262 } 1263 enc = __ops_encrypt_buf(io, in, insize, keypair, (unsigned)armored); 1264 m = MIN(__ops_mem_len(enc), outsize); 1265 (void) memcpy(out, __ops_mem_data(enc), m); 1266 __ops_memory_free(enc); 1267 return (int)m; 1268 } 1269 1270 /* decrypt a chunk of memory */ 1271 int 1272 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize, 1273 char *out, size_t outsize, const int armored) 1274 { 1275 __ops_memory_t *mem; 1276 __ops_io_t *io; 1277 unsigned realarmour; 1278 size_t m; 1279 1280 __OPS_USED(armored); 1281 io = netpgp->io; 1282 if (input == NULL) { 1283 (void) fprintf(io->errs, 1284 "netpgp_decrypt_memory: no memory\n"); 1285 return 0; 1286 } 1287 realarmour = isarmoured(io, NULL, input, ARMOR_HEAD); 1288 mem = __ops_decrypt_buf(netpgp->io, input, insize, netpgp->secring, 1289 netpgp->pubring, 1290 realarmour, netpgp->passfp, 1291 get_passphrase_cb); 1292 m = MIN(__ops_mem_len(mem), outsize); 1293 (void) memcpy(out, __ops_mem_data(mem), m); 1294 __ops_memory_free(mem); 1295 return (int)m; 1296 } 1297 1298 /* wrappers for the ops_debug_level functions we added to openpgpsdk */ 1299 1300 /* set the debugging level per filename */ 1301 int 1302 netpgp_set_debug(const char *f) 1303 { 1304 return __ops_set_debug_level(f); 1305 } 1306 1307 /* get the debugging level per filename */ 1308 int 1309 netpgp_get_debug(const char *f) 1310 { 1311 return __ops_get_debug_level(f); 1312 } 1313 1314 /* return the version for the library */ 1315 const char * 1316 netpgp_get_info(const char *type) 1317 { 1318 return __ops_get_info(type); 1319 } 1320 1321 /* list all the packets in a file */ 1322 int 1323 netpgp_list_packets(netpgp_t *netpgp, char *f, int armor, char *pubringname) 1324 { 1325 __ops_keyring_t *keyring; 1326 const unsigned noarmor = 0; 1327 struct stat st; 1328 __ops_io_t *io; 1329 char ringname[MAXPATHLEN]; 1330 char *homedir; 1331 int ret; 1332 1333 io = netpgp->io; 1334 if (f == NULL) { 1335 (void) fprintf(io->errs, "No file containing packets\n"); 1336 return 0; 1337 } 1338 if (stat(f, &st) < 0) { 1339 (void) fprintf(io->errs, "No such file '%s'\n", f); 1340 return 0; 1341 } 1342 homedir = netpgp_getvar(netpgp, "homedir"); 1343 if (pubringname == NULL) { 1344 (void) snprintf(ringname, sizeof(ringname), 1345 "%s/pubring.gpg", homedir); 1346 pubringname = ringname; 1347 } 1348 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1349 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); 1350 return 0; 1351 } 1352 if (!__ops_keyring_fileread(keyring, noarmor, pubringname)) { 1353 free(keyring); 1354 (void) fprintf(io->errs, "Cannot read pub keyring %s\n", 1355 pubringname); 1356 return 0; 1357 } 1358 netpgp->pubring = keyring; 1359 netpgp_setvar(netpgp, "pubring", pubringname); 1360 ret = __ops_list_packets(io, f, (unsigned)armor, 1361 netpgp->secring, 1362 netpgp->pubring, 1363 netpgp->passfp, 1364 get_passphrase_cb); 1365 free(keyring); 1366 return ret; 1367 } 1368 1369 /* set a variable */ 1370 int 1371 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) 1372 { 1373 char *newval; 1374 int i; 1375 1376 /* protect against the case where 'value' is netpgp->value[i] */ 1377 newval = netpgp_strdup(value); 1378 if ((i = findvar(netpgp, name)) < 0) { 1379 /* add the element to the array */ 1380 if (size_arrays(netpgp, netpgp->size + 15)) { 1381 netpgp->name[i = netpgp->c++] = netpgp_strdup(name); 1382 } 1383 } else { 1384 /* replace the element in the array */ 1385 if (netpgp->value[i]) { 1386 free(netpgp->value[i]); 1387 netpgp->value[i] = NULL; 1388 } 1389 } 1390 /* sanity checks for range of values */ 1391 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { 1392 if (__ops_str_to_hash_alg(newval) == OPS_HASH_UNKNOWN) { 1393 free(newval); 1394 return 0; 1395 } 1396 } 1397 netpgp->value[i] = newval; 1398 return 1; 1399 } 1400 1401 /* unset a variable */ 1402 int 1403 netpgp_unsetvar(netpgp_t *netpgp, const char *name) 1404 { 1405 int i; 1406 1407 if ((i = findvar(netpgp, name)) >= 0) { 1408 if (netpgp->value[i]) { 1409 free(netpgp->value[i]); 1410 netpgp->value[i] = NULL; 1411 } 1412 netpgp->value[i] = NULL; 1413 return 1; 1414 } 1415 return 0; 1416 } 1417 1418 /* get a variable's value (NULL if not set) */ 1419 char * 1420 netpgp_getvar(netpgp_t *netpgp, const char *name) 1421 { 1422 int i; 1423 1424 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; 1425 } 1426 1427 /* increment a value */ 1428 int 1429 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) 1430 { 1431 char *cp; 1432 char num[16]; 1433 int val; 1434 1435 val = 0; 1436 if ((cp = netpgp_getvar(netpgp, name)) != NULL) { 1437 val = atoi(cp); 1438 } 1439 (void) snprintf(num, sizeof(num), "%d", val + delta); 1440 netpgp_setvar(netpgp, name, num); 1441 return 1; 1442 } 1443 1444 /* set the home directory value to "home/subdir" */ 1445 int 1446 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) 1447 { 1448 struct stat st; 1449 char d[MAXPATHLEN]; 1450 1451 if (home == NULL) { 1452 if (!quiet) { 1453 (void) fprintf(stderr, "NULL HOME directory\n"); 1454 } 1455 return 0; 1456 } 1457 (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); 1458 if (stat(d, &st) == 0) { 1459 if ((st.st_mode & S_IFMT) == S_IFDIR) { 1460 netpgp_setvar(netpgp, "homedir", d); 1461 return 1; 1462 } 1463 (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", 1464 d); 1465 return 0; 1466 } 1467 if (!quiet) { 1468 (void) fprintf(stderr, 1469 "netpgp: warning homedir \"%s\" not found\n", d); 1470 } 1471 netpgp_setvar(netpgp, "homedir", d); 1472 return 1; 1473 } 1474 1475 /* validate all sigs in the pub keyring */ 1476 int 1477 netpgp_validate_sigs(netpgp_t *netpgp) 1478 { 1479 __ops_validation_t result; 1480 1481 return (int)__ops_validate_all_sigs(&result, netpgp->pubring, NULL); 1482 } 1483 1484 #if 0 1485 #include "sshkey.h" 1486 1487 int 1488 netpgp_pgpkey_to_sshkey(netpgp_t *netpgp, char *name, SSHKey *sshkey) 1489 { 1490 const __ops_key_t *pgpkey; 1491 unsigned k; 1492 1493 k = 0; 1494 pgpkey = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, name, &k); 1495 if (pgpkey == NULL) { 1496 pgpkey = __ops_getkeybyname(io, netpgp->pubring, userid); 1497 } 1498 if (pgpkey == NULL) { 1499 (void) fprintf(stderr, "No key matching '%s'\n", name); 1500 return 0; 1501 } 1502 switch(pgpkey->key.pubkey.alg) { 1503 case OPS_PKA_RSA: 1504 sshkey->type = KEY_RSA; 1505 sshkey->rsa = calloc(1, sizeof(*sshkey->rsa); 1506 if (sshkey->rsa == NULL) { 1507 (void) fprintf(stderr, "RSA memory problems\n"); 1508 return 0; 1509 } 1510 sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n; 1511 sshkey->rsa->e = pgpkey->key.pubkey.key.rsa.e; 1512 sshkey->rsa->d = pgpkey->key.seckey.key.rsa.d; 1513 sshkey->rsa->p = pgpkey->key.seckey.key.rsa.p; 1514 sshkey->rsa->q = pgpkey->key.seckey.key.rsa.q; 1515 sshkey->rsa->iqmp = pgpkey->key.seckey.key.rsa.u; 1516 break; 1517 case OPS_PKA_DSA: 1518 sshkey->type = KEY_DSA; 1519 sshkey->dsa = calloc(1, sizeof(*sshkey->dsa); 1520 if (sshkey->dsa == NULL) { 1521 (void) fprintf(stderr, "DSA memory problems\n"); 1522 return 0; 1523 } 1524 sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n; 1525 key->dsa->p = pgpkey->key.pubkey.key.dsa.p; 1526 key->dsa->q = pgpkey->key.pubkey.key.dsa.q; 1527 key->dsa->g = pgpkey->key.pubkey.key.dsa.g; 1528 key->dsa->pub_key = pgpkey->key.pubkey.key.dsa.y; 1529 key->dsa->priv_key = pgpkey->key.seckey.key.dsa.x; 1530 break; 1531 default: 1532 (void) fprintf(stderr, "weird type\n"); 1533 return 0; 1534 } 1535 return 1; 1536 } 1537 #endif 1538