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