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