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