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.106 2022/08/27 08:58:32 rillig 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 "ssh2pgp.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 __PGP_USED(netpgp); 97 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); 98 if ((fp = fopen(buf, "r")) == NULL) { 99 return 0; 100 } 101 (void) memset(&keyre, 0x0, sizeof(keyre)); 102 (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", 103 REG_EXTENDED); 104 while (fgets(buf, (int)sizeof(buf), fp) != NULL) { 105 if (regexec(&keyre, buf, 10, matchv, 0) == 0) { 106 (void) memcpy(userid, &buf[(int)matchv[1].rm_so], 107 MIN((unsigned)(matchv[1].rm_eo - 108 matchv[1].rm_so), length)); 109 if (netpgp->passfp == NULL) { 110 (void) fprintf(stderr, 111 "netpgp: default key set to \"%.*s\"\n", 112 (int)(matchv[1].rm_eo - matchv[1].rm_so), 113 &buf[(int)matchv[1].rm_so]); 114 } 115 } 116 } 117 (void) fclose(fp); 118 regfree(&keyre); 119 return 1; 120 } 121 122 /* small function to pretty print an 8-character raw userid */ 123 static char * 124 userid_to_id(const uint8_t *userid, char *id) 125 { 126 static const char *hexes = "0123456789abcdef"; 127 int i; 128 129 for (i = 0; i < 8 ; i++) { 130 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; 131 id[(i * 2) + 1] = hexes[userid[i] & 0xf]; 132 } 133 id[8 * 2] = 0x0; 134 return id; 135 } 136 137 /* print out the successful signature information */ 138 static void 139 resultp(pgp_io_t *io, 140 const char *f, 141 pgp_validation_t *res, 142 pgp_keyring_t *ring) 143 { 144 const pgp_key_t *key; 145 pgp_pubkey_t *sigkey; 146 unsigned from; 147 unsigned i; 148 time_t t; 149 char id[MAX_ID_LENGTH + 1]; 150 151 for (i = 0; i < res->validc; i++) { 152 (void) fprintf(io->res, 153 "Good signature for %s made %s", 154 (f) ? f : "<stdin>", 155 ctime(&res->valid_sigs[i].birthtime)); 156 if (res->duration > 0) { 157 t = res->birthtime + res->duration; 158 (void) fprintf(io->res, "Valid until %s", ctime(&t)); 159 } 160 (void) fprintf(io->res, 161 "using %s key %s\n", 162 pgp_show_pka(res->valid_sigs[i].key_alg), 163 userid_to_id(res->valid_sigs[i].signer_id, id)); 164 from = 0; 165 key = pgp_getkeybyid(io, ring, 166 (const uint8_t *) res->valid_sigs[i].signer_id, 167 &from, &sigkey); 168 if (sigkey == &key->enckey) { 169 (void) fprintf(io->res, 170 "WARNING: signature for %s made with encryption key\n", 171 (f) ? f : "<stdin>"); 172 } 173 pgp_print_keydata(io, ring, key, "signature ", &key->key.pubkey, 0); 174 } 175 } 176 177 /* check there's enough space in the arrays */ 178 static int 179 size_arrays(netpgp_t *netpgp, unsigned needed) 180 { 181 char **temp; 182 183 if (netpgp->size == 0) { 184 /* only get here first time around */ 185 netpgp->size = needed; 186 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { 187 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 188 return 0; 189 } 190 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { 191 free(netpgp->name); 192 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 193 return 0; 194 } 195 } else if (netpgp->c == netpgp->size) { 196 /* only uses 'needed' when filled array */ 197 netpgp->size += needed; 198 temp = realloc(netpgp->name, sizeof(char *) * needed); 199 if (temp == NULL) { 200 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 201 return 0; 202 } 203 netpgp->name = temp; 204 temp = realloc(netpgp->value, sizeof(char *) * needed); 205 if (temp == NULL) { 206 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 207 return 0; 208 } 209 netpgp->value = temp; 210 } 211 return 1; 212 } 213 214 /* find the name in the array */ 215 static int 216 findvar(netpgp_t *netpgp, const char *name) 217 { 218 unsigned i; 219 220 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { 221 } 222 return (i == netpgp->c) ? -1 : (int)i; 223 } 224 225 /* append a key to a keyring */ 226 static int 227 appendkey(pgp_io_t *io, pgp_key_t *key, char *ringfile) 228 { 229 pgp_output_t *create; 230 const unsigned noarmor = 0; 231 int fd; 232 233 if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { 234 fd = pgp_setup_file_write(&create, ringfile, 0); 235 } 236 if (fd < 0) { 237 (void) fprintf(io->errs, "can't open pubring '%s'\n", ringfile); 238 return 0; 239 } 240 if (!pgp_write_xfer_pubkey(create, key, noarmor)) { 241 (void) fprintf(io->errs, "Cannot write pubkey\n"); 242 return 0; 243 } 244 pgp_teardown_file_write(create, fd); 245 return 1; 246 } 247 248 /* return filename of a keyring */ 249 static char * 250 keyringfile(netpgp_t *netpgp, const char *name) 251 { 252 char f[MAXPATHLEN]; 253 char *homedir; 254 char *filename; 255 256 homedir = netpgp_getvar(netpgp, "homedir"); 257 filename = netpgp_getvar(netpgp, name); 258 if (filename == NULL || filename[0] == '\0') { 259 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); 260 filename = f; 261 } 262 263 return netpgp_strdup(filename); 264 } 265 266 /* return an empty keyring */ 267 static void * 268 newkeyring(netpgp_t *netpgp, const char *name) 269 { 270 pgp_keyring_t *keyring; 271 char *filename; 272 273 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 274 (void) fprintf(stderr, "newkeyring: bad alloc\n"); 275 return NULL; 276 } 277 278 filename = keyringfile(netpgp, name); 279 netpgp_setvar(netpgp, name, filename); 280 free(filename); 281 282 return keyring; 283 } 284 285 /* read a keyring and return it */ 286 static void * 287 readkeyring(netpgp_t *netpgp, const char *name) 288 { 289 pgp_keyring_t *keyring; 290 const unsigned noarmor = 0; 291 char *filename; 292 293 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 294 (void) fprintf(stderr, "readkeyring: bad alloc\n"); 295 return NULL; 296 } 297 298 filename = keyringfile(netpgp, name); 299 if (!pgp_keyring_fileread(keyring, noarmor, filename)) { 300 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 301 free(filename); 302 free(keyring); 303 return NULL; 304 } 305 netpgp_setvar(netpgp, name, filename); 306 free(filename); 307 308 return keyring; 309 } 310 311 /* write a keyring */ 312 static int 313 writekeyring(netpgp_t *netpgp, const char *name, pgp_keyring_t *keyring, uint8_t *passphrase) 314 { 315 const unsigned noarmor = 0; 316 char *filename; 317 318 filename = keyringfile(netpgp, name); 319 if (!pgp_keyring_filewrite(keyring, noarmor, filename, passphrase)) { 320 (void) fprintf(stderr, "Can't write %s %s\n", name, filename); 321 free(filename); 322 return 0; 323 } 324 netpgp_setvar(netpgp, name, filename); 325 free(filename); 326 327 return 1; 328 } 329 330 /* append key to a keyring */ 331 static int 332 appendtokeyring(netpgp_t *netpgp, const char *name, pgp_key_t *key) 333 { 334 char *filename; 335 int ret; 336 337 filename = keyringfile(netpgp, name); 338 ret = appendkey(netpgp->io, key, filename); 339 free(filename); 340 341 return ret; 342 } 343 344 /* read keys from ssh key files */ 345 static int 346 readsshkeys(netpgp_t *netpgp, char *homedir, const char *needseckey) 347 { 348 pgp_keyring_t *pubring; 349 pgp_keyring_t *secring; 350 struct stat st; 351 unsigned hashtype; 352 char *hash; 353 char f[MAXPATHLEN]; 354 char *filename; 355 356 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) { 357 /* set reasonable default for RSA key */ 358 (void) snprintf(f, sizeof(f), "%s/id_rsa.pub", homedir); 359 filename = f; 360 } else if (strcmp(&filename[strlen(filename) - 4], ".pub") != 0) { 361 /* got ssh keys, check for pub file name */ 362 (void) snprintf(f, sizeof(f), "%s.pub", filename); 363 filename = f; 364 } 365 /* check the pub file exists */ 366 if (stat(filename, &st) != 0) { 367 (void) fprintf(stderr, "readsshkeys: bad pubkey filename '%s'\n", filename); 368 return 0; 369 } 370 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { 371 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 372 return 0; 373 } 374 /* openssh2 keys use md5 by default */ 375 hashtype = PGP_HASH_MD5; 376 if ((hash = netpgp_getvar(netpgp, "hash")) != NULL) { 377 /* openssh 2 hasn't really caught up to anything else yet */ 378 if (netpgp_strcasecmp(hash, "md5") == 0) { 379 hashtype = PGP_HASH_MD5; 380 } else if (netpgp_strcasecmp(hash, "sha1") == 0) { 381 hashtype = PGP_HASH_SHA1; 382 } else if (netpgp_strcasecmp(hash, "sha256") == 0) { 383 hashtype = PGP_HASH_SHA256; 384 } 385 } 386 if (!pgp_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL, hashtype)) { 387 free(pubring); 388 (void) fprintf(stderr, "readsshkeys: can't read %s\n", 389 filename); 390 return 0; 391 } 392 if (netpgp->pubring == NULL) { 393 netpgp->pubring = pubring; 394 } else { 395 pgp_append_keyring(netpgp->pubring, pubring); 396 } 397 if (needseckey) { 398 netpgp_setvar(netpgp, "sshpubfile", filename); 399 /* try to take the ".pub" off the end */ 400 if (filename == f) { 401 f[strlen(f) - 4] = 0x0; 402 } else { 403 (void) snprintf(f, sizeof(f), "%.*s", 404 (int)strlen(filename) - 4, filename); 405 filename = f; 406 } 407 if ((secring = calloc(1, sizeof(*secring))) == NULL) { 408 free(pubring); 409 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 410 return 0; 411 } 412 if (!pgp_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename, hashtype)) { 413 free(pubring); 414 free(secring); 415 (void) fprintf(stderr, "readsshkeys: can't read sec %s\n", filename); 416 return 0; 417 } 418 netpgp->secring = secring; 419 netpgp_setvar(netpgp, "sshsecfile", filename); 420 } 421 return 1; 422 } 423 424 /* get the uid of the first key in the keyring */ 425 static int 426 get_first_ring(pgp_keyring_t *ring, char *id, size_t len, int last) 427 { 428 uint8_t *src; 429 int i; 430 int n; 431 432 if (ring == NULL || ring->keyc == 0) { 433 return 0; 434 } 435 (void) memset(id, 0x0, len); 436 src = ring->keys[(last) ? ring->keyc - 1 : 0].sigid; 437 for (i = 0, n = 0 ; i < PGP_KEY_ID_SIZE ; i += 2) { 438 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); 439 } 440 id[n] = 0x0; 441 return 1; 442 } 443 444 /* find the time - in a specific %Y-%m-%d format - using a regexp */ 445 static int 446 grabdate(char *s, int64_t *t) 447 { 448 static regex_t r; 449 static int compiled; 450 regmatch_t matches[10]; 451 struct tm tm; 452 453 if (!compiled) { 454 compiled = 1; 455 (void) regcomp(&r, "([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])", REG_EXTENDED); 456 } 457 if (regexec(&r, s, 10, matches, 0) == 0) { 458 (void) memset(&tm, 0x0, sizeof(tm)); 459 tm.tm_year = (int)strtol(&s[(int)matches[1].rm_so], NULL, 10); 460 tm.tm_mon = (int)strtol(&s[(int)matches[2].rm_so], NULL, 10) - 1; 461 tm.tm_mday = (int)strtol(&s[(int)matches[3].rm_so], NULL, 10); 462 *t = mktime(&tm); 463 return 1; 464 } 465 return 0; 466 } 467 468 /* get expiration in seconds */ 469 static uint64_t 470 get_duration(char *s) 471 { 472 uint64_t now; 473 int64_t t; 474 const char *mult; 475 476 if (s == NULL) { 477 return 0; 478 } 479 now = (uint64_t)strtoull(s, NULL, 10); 480 if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) { 481 switch(*mult) { 482 case 'h': 483 return now * 60 * 60; 484 case 'd': 485 return now * 60 * 60 * 24; 486 case 'w': 487 return now * 60 * 60 * 24 * 7; 488 case 'm': 489 return now * 60 * 60 * 24 * 31; 490 case 'y': 491 return now * 60 * 60 * 24 * 365; 492 } 493 } 494 if (grabdate(s, &t)) { 495 return t; 496 } 497 return (uint64_t)strtoll(s, NULL, 10); 498 } 499 500 /* get birthtime in seconds */ 501 static int64_t 502 get_birthtime(char *s) 503 { 504 int64_t t; 505 506 if (s == NULL) { 507 return time(NULL); 508 } 509 if (grabdate(s, &t)) { 510 return t; 511 } 512 return (uint64_t)strtoll(s, NULL, 10); 513 } 514 515 /* resolve the userid */ 516 static const pgp_key_t * 517 resolve_userid(netpgp_t *netpgp, const pgp_keyring_t *keyring, const char *userid) 518 { 519 const pgp_key_t *key; 520 pgp_io_t *io; 521 522 if (userid == NULL) { 523 userid = netpgp_getvar(netpgp, "userid"); 524 if (userid == NULL) 525 return NULL; 526 } else if (userid[0] == '0' && userid[1] == 'x') { 527 userid += 2; 528 } 529 io = netpgp->io; 530 if ((key = pgp_getkeybyname(io, keyring, userid)) == NULL) { 531 (void) fprintf(io->errs, "Can't find key '%s'\n", userid); 532 } 533 return key; 534 } 535 536 /* return 1 if the file contains ascii-armoured text */ 537 static unsigned 538 isarmoured(pgp_io_t *io, const char *f, const void *memory, const char *text) 539 { 540 regmatch_t matches[10]; 541 unsigned armoured; 542 regex_t r; 543 FILE *fp; 544 char buf[BUFSIZ]; 545 546 armoured = 0; 547 (void) regcomp(&r, text, REG_EXTENDED); 548 if (f) { 549 if ((fp = fopen(f, "r")) == NULL) { 550 (void) fprintf(io->errs, "isarmoured: can't open '%s'\n", f); 551 regfree(&r); 552 return 0; 553 } 554 if (fgets(buf, (int)sizeof(buf), fp) != NULL) { 555 if (regexec(&r, buf, 10, matches, 0) == 0) { 556 armoured = 1; 557 } 558 } 559 (void) fclose(fp); 560 } else { 561 if (regexec(&r, memory, 10, matches, 0) == 0) { 562 armoured = 1; 563 } 564 } 565 regfree(&r); 566 return armoured; 567 } 568 569 /* vararg print function */ 570 static void 571 p(FILE *fp, const char *s, ...) 572 { 573 va_list args; 574 575 va_start(args, s); 576 while (s != NULL) { 577 (void) fprintf(fp, "%s", s); 578 s = va_arg(args, char *); 579 } 580 va_end(args); 581 } 582 583 /* print a JSON object to the FILE stream */ 584 static void 585 pobj(FILE *fp, mj_t *obj, int depth) 586 { 587 588 if (obj == NULL) { 589 (void) fprintf(stderr, "No object found\n"); 590 return; 591 } 592 593 mj_pretty(obj, fp, depth, ""); 594 } 595 596 /* return the time as a string */ 597 static char * 598 ptimestr(char *dest, size_t size, time_t t) 599 { 600 struct tm *tm; 601 602 tm = gmtime(&t); 603 (void) snprintf(dest, size, "%04d-%02d-%02d", 604 tm->tm_year + 1900, 605 tm->tm_mon + 1, 606 tm->tm_mday); 607 return dest; 608 } 609 610 /* format a JSON object */ 611 static void 612 format_json_key(FILE *fp, mj_t *obj, const int psigs) 613 { 614 int64_t birthtime; 615 int64_t duration; 616 time_t now; 617 char tbuf[32]; 618 char *s; 619 mj_t *sub; 620 int i; 621 622 if (pgp_get_debug_level(__FILE__)) { 623 mj_asprint(&s, obj, MJ_HUMAN); 624 (void) fprintf(stderr, "formatobj: json is '%s'\n", s); 625 free(s); 626 } 627 if (obj->c == 2 && obj->value.v[1].type == MJ_STRING && 628 strcmp(obj->value.v[1].value.s, "[REVOKED]") == 0) { 629 /* whole key has been rovoked - just return */ 630 return; 631 } 632 pobj(fp, &obj->value.v[mj_object_find(obj, "header", 0, 2) + 1], 0); 633 p(fp, " ", NULL); 634 pobj(fp, &obj->value.v[mj_object_find(obj, "key bits", 0, 2) + 1], 0); 635 p(fp, "/", NULL); 636 pobj(fp, &obj->value.v[mj_object_find(obj, "pka", 0, 2) + 1], 0); 637 p(fp, " ", NULL); 638 pobj(fp, &obj->value.v[mj_object_find(obj, "key id", 0, 2) + 1], 0); 639 birthtime = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "birthtime", 0, 2) + 1].value.s, NULL, 10); 640 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), birthtime), NULL); 641 duration = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "duration", 0, 2) + 1].value.s, NULL, 10); 642 if (duration > 0) { 643 now = time(NULL); 644 p(fp, " ", (birthtime + duration < now) ? "[EXPIRED " : "[EXPIRES ", 645 ptimestr(tbuf, sizeof(tbuf), birthtime + duration), "]", NULL); 646 } 647 p(fp, "\n", "Key fingerprint: ", NULL); 648 pobj(fp, &obj->value.v[mj_object_find(obj, "fingerprint", 0, 2) + 1], 0); 649 p(fp, "\n", NULL); 650 /* go to field after \"duration\" */ 651 for (i = mj_object_find(obj, "duration", 0, 2) + 2; i < mj_arraycount(obj) ; i += 2) { 652 if (strcmp(obj->value.v[i].value.s, "uid") == 0) { 653 sub = &obj->value.v[i + 1]; 654 p(fp, "uid", NULL); 655 pobj(fp, &sub->value.v[0], (psigs) ? 4 : 14); /* human name */ 656 pobj(fp, &sub->value.v[1], 1); /* any revocation */ 657 p(fp, "\n", NULL); 658 } else if (strcmp(obj->value.v[i].value.s, "encryption") == 0) { 659 sub = &obj->value.v[i + 1]; 660 p(fp, "encryption", NULL); 661 pobj(fp, &sub->value.v[0], 1); /* size */ 662 p(fp, "/", NULL); 663 pobj(fp, &sub->value.v[1], 0); /* alg */ 664 p(fp, " ", NULL); 665 pobj(fp, &sub->value.v[2], 0); /* id */ 666 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), 667 (time_t)strtoll(sub->value.v[3].value.s, NULL, 10)), 668 "\n", NULL); 669 } else if (strcmp(obj->value.v[i].value.s, "sig") == 0) { 670 sub = &obj->value.v[i + 1]; 671 p(fp, "sig", NULL); 672 pobj(fp, &sub->value.v[0], 8); /* size */ 673 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), 674 (time_t)strtoll(sub->value.v[1].value.s, NULL, 10)), 675 " ", NULL); /* time */ 676 pobj(fp, &sub->value.v[2], 0); /* human name */ 677 p(fp, "\n", NULL); 678 } else { 679 fprintf(stderr, "weird '%s'\n", obj->value.v[i].value.s); 680 pobj(fp, &obj->value.v[i], 0); /* human name */ 681 } 682 } 683 p(fp, "\n", NULL); 684 } 685 686 /* save a pgp pubkey to a temp file */ 687 static int 688 savepubkey(char *res, char *f, size_t size) 689 { 690 size_t len; 691 int cc; 692 int wc; 693 int fd; 694 695 (void) snprintf(f, size, "/tmp/pgp2ssh.XXXXXXX"); 696 if ((fd = mkstemp(f)) < 0) { 697 (void) fprintf(stderr, "can't create temp file '%s'\n", f); 698 return 0; 699 } 700 len = strlen(res); 701 for (cc = 0 ; (wc = (int)write(fd, &res[cc], len - (size_t)cc)) > 0 ; cc += wc) { 702 } 703 (void) close(fd); 704 return 1; 705 } 706 707 /* format a uint32_t */ 708 static int 709 formatu32(uint8_t *buffer, uint32_t value) 710 { 711 buffer[0] = (uint8_t)(value >> 24) & 0xff; 712 buffer[1] = (uint8_t)(value >> 16) & 0xff; 713 buffer[2] = (uint8_t)(value >> 8) & 0xff; 714 buffer[3] = (uint8_t)value & 0xff; 715 return sizeof(uint32_t); 716 } 717 718 /* format a string as (len, string) */ 719 static int 720 formatstring(char *buffer, const uint8_t *s, size_t len) 721 { 722 int cc; 723 724 cc = formatu32((uint8_t *)buffer, (uint32_t)len); 725 (void) memcpy(&buffer[cc], s, len); 726 return cc + (int)len; 727 } 728 729 /* format a bignum, checking for "interesting" high bit values */ 730 static int 731 formatbignum(char *buffer, BIGNUM *bn) 732 { 733 size_t len; 734 uint8_t *cp; 735 int cc; 736 737 len = (size_t) BN_num_bytes(bn); 738 if ((cp = calloc(1, len + 1)) == NULL) { 739 (void) fprintf(stderr, "calloc failure in formatbignum\n"); 740 return 0; 741 } 742 (void) BN_bn2bin(bn, cp + 1); 743 cp[0] = 0x0; 744 cc = (cp[1] & 0x80) ? formatstring(buffer, cp, len + 1) : formatstring(buffer, &cp[1], len); 745 free(cp); 746 return cc; 747 } 748 749 #define MAX_PASSPHRASE_ATTEMPTS 3 750 #define INFINITE_ATTEMPTS -1 751 752 /* get the passphrase from the user */ 753 static int 754 find_passphrase(FILE *passfp, const char *id, char *passphrase, size_t size, int attempts) 755 { 756 char prompt[BUFSIZ]; 757 char buf[128]; 758 char *cp; 759 int cc; 760 int i; 761 762 if (passfp) { 763 if (fgets(passphrase, (int)size, passfp) == NULL) { 764 return 0; 765 } 766 return (int)strlen(passphrase); 767 } 768 for (i = 0 ; i < attempts ; i++) { 769 (void) snprintf(prompt, sizeof(prompt), "Enter passphrase for %.16s: ", id); 770 if ((cp = getpass(prompt)) == NULL) { 771 break; 772 } 773 cc = snprintf(buf, sizeof(buf), "%s", cp); 774 (void) snprintf(prompt, sizeof(prompt), "Repeat passphrase for %.16s: ", id); 775 if ((cp = getpass(prompt)) == NULL) { 776 break; 777 } 778 cc = snprintf(passphrase, size, "%s", cp); 779 if (strcmp(buf, passphrase) == 0) { 780 (void) memset(buf, 0x0, sizeof(buf)); 781 return cc; 782 } 783 } 784 (void) memset(buf, 0x0, sizeof(buf)); 785 (void) memset(passphrase, 0x0, size); 786 return 0; 787 } 788 789 /***************************************************************************/ 790 /* exported functions start here */ 791 /***************************************************************************/ 792 793 /* initialise a netpgp_t structure */ 794 int 795 netpgp_init(netpgp_t *netpgp) 796 { 797 pgp_io_t *io; 798 time_t t; 799 char id[MAX_ID_LENGTH]; 800 char *homedir; 801 char *userid; 802 char *stream; 803 char *passfd; 804 char *results; 805 int coredumps; 806 int last; 807 808 #ifdef HAVE_SYS_RESOURCE_H 809 struct rlimit limit; 810 811 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 812 if (!coredumps) { 813 (void) memset(&limit, 0x0, sizeof(limit)); 814 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 815 (void) fprintf(stderr, 816 "netpgp: warning - can't turn off core dumps\n"); 817 coredumps = 1; 818 } 819 } 820 #else 821 coredumps = 1; 822 #endif 823 if ((io = calloc(1, sizeof(*io))) == NULL) { 824 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 825 return 0; 826 } 827 io->outs = stdout; 828 if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && 829 strcmp(stream, "<stderr>") == 0) { 830 io->outs = stderr; 831 } 832 io->errs = stderr; 833 if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && 834 strcmp(stream, "<stdout>") == 0) { 835 io->errs = stdout; 836 } 837 if ((results = netpgp_getvar(netpgp, "res")) == NULL) { 838 io->res = io->errs; 839 } else if (strcmp(results, "<stdout>") == 0) { 840 io->res = stdout; 841 } else if (strcmp(results, "<stderr>") == 0) { 842 io->res = stderr; 843 } else { 844 if ((io->res = fopen(results, "w")) == NULL) { 845 (void) fprintf(io->errs, "Can't open results %s for writing\n", 846 results); 847 free(io); 848 return 0; 849 } 850 } 851 netpgp->io = io; 852 /* get passphrase from an fd */ 853 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 854 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 855 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 856 passfd); 857 return 0; 858 } 859 /* warn if core dumps are enabled */ 860 if (coredumps) { 861 (void) fprintf(io->errs, 862 "netpgp: warning: core dumps enabled\n"); 863 } 864 /* get home directory - where keyrings are in a subdir */ 865 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 866 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 867 return 0; 868 } 869 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 870 /* read from ordinary pgp keyrings */ 871 netpgp->pubring = readkeyring(netpgp, "pubring"); 872 if (netpgp->pubring == NULL) { 873 return 0; 874 } 875 /* if a userid has been given, we'll use it */ 876 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 877 /* also search in config file for default id */ 878 (void) memset(id, 0x0, sizeof(id)); 879 (void) conffile(netpgp, homedir, id, sizeof(id)); 880 if (id[0] != 0x0) { 881 netpgp_setvar(netpgp, "userid", userid = id); 882 } 883 } 884 /* only read secret keys if we need to */ 885 if (netpgp_getvar(netpgp, "need seckey")) { 886 /* read the secret ring */ 887 netpgp->secring = readkeyring(netpgp, "secring"); 888 if (netpgp->secring == NULL) { 889 return 0; 890 } 891 /* now, if we don't have a valid user, use the first in secring */ 892 if (!userid && netpgp_getvar(netpgp, "need userid") != NULL) { 893 /* signing - need userid and sec key */ 894 (void) memset(id, 0x0, sizeof(id)); 895 if (get_first_ring(netpgp->secring, id, sizeof(id), 0)) { 896 netpgp_setvar(netpgp, "userid", userid = id); 897 } 898 } 899 } else if (netpgp_getvar(netpgp, "need userid") != NULL) { 900 /* encrypting - get first in pubring */ 901 if (!userid && get_first_ring(netpgp->pubring, id, sizeof(id), 0)) { 902 (void) netpgp_setvar(netpgp, "userid", userid = id); 903 } 904 } 905 if (!userid && netpgp_getvar(netpgp, "need userid")) { 906 /* if we don't have a user id, and we need one, fail */ 907 (void) fprintf(io->errs, "Cannot find user id\n"); 908 return 0; 909 } 910 } else { 911 /* read from ssh keys */ 912 last = (netpgp->pubring != NULL); 913 if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need seckey"))) { 914 return 0; 915 } 916 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 917 get_first_ring(netpgp->pubring, id, sizeof(id), last); 918 netpgp_setvar(netpgp, "userid", userid = id); 919 } 920 if (userid == NULL) { 921 if (netpgp_getvar(netpgp, "need userid") != NULL) { 922 (void) fprintf(io->errs, 923 "Cannot find user id\n"); 924 return 0; 925 } 926 } else { 927 (void) netpgp_setvar(netpgp, "userid", userid); 928 } 929 } 930 t = time(NULL); 931 netpgp_setvar(netpgp, "initialised", ctime(&t)); 932 return 1; 933 } 934 935 /* finish off with the netpgp_t struct */ 936 int 937 netpgp_end(netpgp_t *netpgp) 938 { 939 unsigned i; 940 941 for (i = 0 ; i < netpgp->c ; i++) { 942 if (netpgp->name[i] != NULL) { 943 free(netpgp->name[i]); 944 } 945 if (netpgp->value[i] != NULL) { 946 free(netpgp->value[i]); 947 } 948 } 949 if (netpgp->name != NULL) { 950 free(netpgp->name); 951 } 952 if (netpgp->value != NULL) { 953 free(netpgp->value); 954 } 955 if (netpgp->pubring != NULL) { 956 pgp_keyring_free(netpgp->pubring); 957 } 958 if (netpgp->secring != NULL) { 959 pgp_keyring_free(netpgp->secring); 960 } 961 free(netpgp->io); 962 return 1; 963 } 964 965 /* list the keys in a keyring */ 966 int 967 netpgp_list_keys(netpgp_t *netpgp, const int psigs) 968 { 969 if (netpgp->pubring == NULL) { 970 (void) fprintf(stderr, "No keyring\n"); 971 return 0; 972 } 973 return pgp_keyring_list(netpgp->io, netpgp->pubring, psigs); 974 } 975 976 /* list the keys in a keyring, returning a JSON encoded string */ 977 int 978 netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs) 979 { 980 mj_t obj; 981 int ret; 982 983 if (netpgp->pubring == NULL) { 984 (void) fprintf(stderr, "No keyring\n"); 985 return 0; 986 } 987 (void) memset(&obj, 0x0, sizeof(obj)); 988 if (!pgp_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) { 989 (void) fprintf(stderr, "No keys in keyring\n"); 990 return 0; 991 } 992 ret = mj_asprint(json, &obj, MJ_JSON_ENCODE); 993 mj_delete(&obj); 994 return ret; 995 } 996 997 DEFINE_ARRAY(strings_t, char *); 998 999 #ifndef HKP_VERSION 1000 #define HKP_VERSION 1 1001 #endif 1002 1003 /* find and list some keys in a keyring */ 1004 int 1005 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs) 1006 { 1007 const pgp_key_t *key; 1008 unsigned k; 1009 strings_t pubs; 1010 FILE *fp = (FILE *)vp; 1011 1012 if (name[0] == '0' && name[1] == 'x') { 1013 name += 2; 1014 } 1015 (void) memset(&pubs, 0x0, sizeof(pubs)); 1016 k = 0; 1017 do { 1018 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1019 name, &k); 1020 if (key != NULL) { 1021 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 1022 "netpgp_match_keys", return 0); 1023 if (strcmp(fmt, "mr") == 0) { 1024 pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1025 key, &pubs.v[pubs.c], 1026 &key->key.pubkey, psigs); 1027 } else { 1028 pgp_sprint_keydata(netpgp->io, netpgp->pubring, 1029 key, &pubs.v[pubs.c], 1030 "signature ", 1031 &key->key.pubkey, psigs); 1032 } 1033 if (pubs.v[pubs.c] != NULL) { 1034 pubs.c += 1; 1035 } 1036 k += 1; 1037 } 1038 } while (key != NULL); 1039 if (strcmp(fmt, "mr") == 0) { 1040 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 1041 } else { 1042 (void) fprintf(fp, "%d key%s found\n", pubs.c, 1043 (pubs.c == 1) ? "" : "s"); 1044 } 1045 for (k = 0 ; k < pubs.c ; k++) { 1046 (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : ""); 1047 free(pubs.v[k]); 1048 } 1049 free(pubs.v); 1050 return pubs.c; 1051 } 1052 1053 /* find and list some keys in a keyring - return JSON string */ 1054 int 1055 netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs) 1056 { 1057 const pgp_key_t *key; 1058 unsigned k; 1059 mj_t id_array; 1060 char *newkey; 1061 int ret; 1062 1063 if (name[0] == '0' && name[1] == 'x') { 1064 name += 2; 1065 } 1066 (void) memset(&id_array, 0x0, sizeof(id_array)); 1067 k = 0; 1068 *json = NULL; 1069 mj_create(&id_array, "array"); 1070 do { 1071 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1072 name, &k); 1073 if (key != NULL) { 1074 if (strcmp(fmt, "mr") == 0) { 1075 pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1076 key, &newkey, 1077 &key->key.pubkey, 0); 1078 if (newkey) { 1079 printf("%s\n", newkey); 1080 free(newkey); 1081 } 1082 } else { 1083 ALLOC(mj_t, id_array.value.v, id_array.size, 1084 id_array.c, 10, 10, "netpgp_match_keys_json", return 0); 1085 pgp_sprint_mj(netpgp->io, netpgp->pubring, 1086 key, &id_array.value.v[id_array.c++], 1087 "signature", 1088 &key->key.pubkey, psigs); 1089 } 1090 k += 1; 1091 } 1092 } while (key != NULL); 1093 ret = mj_asprint(json, &id_array, MJ_JSON_ENCODE); 1094 mj_delete(&id_array); 1095 return ret; 1096 } 1097 1098 /* find and list some public keys in a keyring */ 1099 int 1100 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) 1101 { 1102 const pgp_key_t *key; 1103 unsigned k; 1104 ssize_t cc; 1105 char out[1024 * 64]; 1106 FILE *fp = (FILE *)vp; 1107 1108 k = 0; 1109 do { 1110 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1111 name, &k); 1112 if (key != NULL) { 1113 cc = pgp_sprint_pubkey(key, out, sizeof(out)); 1114 (void) fprintf(fp, "%.*s", (int)cc, out); 1115 k += 1; 1116 } 1117 } while (key != NULL); 1118 return k; 1119 } 1120 1121 /* find a key in a keyring */ 1122 int 1123 netpgp_find_key(netpgp_t *netpgp, char *id) 1124 { 1125 pgp_io_t *io; 1126 1127 io = netpgp->io; 1128 if (id == NULL) { 1129 (void) fprintf(io->errs, "NULL id to search for\n"); 1130 return 0; 1131 } 1132 return pgp_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 1133 } 1134 1135 /* get a key in a keyring */ 1136 char * 1137 netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt) 1138 { 1139 const pgp_key_t *key; 1140 char *newkey; 1141 1142 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1143 return NULL; 1144 } 1145 if (strcmp(fmt, "mr") == 0) { 1146 return (pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1147 key, &newkey, 1148 &key->key.pubkey, 1149 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1150 } 1151 return (pgp_sprint_keydata(netpgp->io, netpgp->pubring, 1152 key, &newkey, "signature", 1153 &key->key.pubkey, 1154 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1155 } 1156 1157 /* export a given key */ 1158 char * 1159 netpgp_export_key(netpgp_t *netpgp, char *name) 1160 { 1161 const pgp_key_t *key; 1162 pgp_io_t *io; 1163 1164 io = netpgp->io; 1165 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1166 return NULL; 1167 } 1168 return pgp_export_key(io, key, NULL); 1169 } 1170 1171 #define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----" 1172 1173 /* import a key into our keyring */ 1174 int 1175 netpgp_import_key(netpgp_t *netpgp, char *f) 1176 { 1177 pgp_io_t *io; 1178 unsigned realarmor; 1179 int done; 1180 pgp_keyring_t *keyring; 1181 pgp_key_t *key; 1182 const char *ringname; 1183 int rv; 1184 1185 io = netpgp->io; 1186 1187 if (f == NULL) { 1188 (void) fprintf(io->errs, "No input file given\n"); 1189 return 0; 1190 } 1191 1192 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1193 (void) fprintf(io->errs, "netpgp_import_key: bad alloc\n"); 1194 return 0; 1195 } 1196 1197 realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD); 1198 done = pgp_keyring_fileread(keyring, realarmor, f); 1199 if (!done || keyring->keyc == 0) { 1200 (void) fprintf(io->errs, "Cannot import key from file %s\n", f); 1201 pgp_keyring_free(keyring); 1202 return 0; 1203 } 1204 done = pgp_keyring_list(io, keyring, 0); 1205 if (!done) 1206 return 0; 1207 1208 key = keyring->keys; 1209 1210 if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { 1211 ringname = "pubring"; 1212 } else { 1213 ringname = "secring"; 1214 } 1215 1216 if (!done) { 1217 pgp_keyring_free(keyring); 1218 (void) fprintf(io->errs, "Bad append\n"); 1219 return 0; 1220 } 1221 1222 rv = appendtokeyring(netpgp, ringname, key); 1223 pgp_keyring_free(keyring); 1224 1225 return rv; 1226 } 1227 1228 #define ID_OFFSET 38 1229 1230 /* generate a new key */ 1231 int 1232 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 1233 { 1234 pgp_output_t *create; 1235 const unsigned noarmor = 0; 1236 pgp_key_t *key; 1237 pgp_io_t *io; 1238 uint8_t *uid; 1239 char passphrase[128]; 1240 char newid[1024]; 1241 char filename[MAXPATHLEN]; 1242 char dir[MAXPATHLEN]; 1243 char *cp; 1244 char *ringfile; 1245 char *numtries; 1246 int attempts; 1247 int passc; 1248 int fd; 1249 int cc; 1250 int rv = 0; 1251 1252 uid = NULL; 1253 io = netpgp->io; 1254 /* generate a new key */ 1255 if (id) { 1256 (void) snprintf(newid, sizeof(newid), "%s", id); 1257 } else { 1258 (void) snprintf(newid, sizeof(newid), 1259 "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME")); 1260 } 1261 uid = (uint8_t *)newid; 1262 key = pgp_rsa_new_selfsign_key(numbits, 65537UL, uid, 1263 netpgp_getvar(netpgp, "hash"), 1264 netpgp_getvar(netpgp, "cipher")); 1265 if (key == NULL) { 1266 (void) fprintf(io->errs, "Cannot generate key\n"); 1267 return 0; 1268 } 1269 cp = NULL; 1270 pgp_sprint_keydata(netpgp->io, NULL, key, &cp, "signature ", &key->key.seckey.pubkey, 0); 1271 (void) fprintf(stdout, "%s", cp); 1272 /* write public key */ 1273 cc = snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[ID_OFFSET]); 1274 netpgp_setvar(netpgp, "generated userid", &dir[cc - 16]); 1275 if (mkdir(dir, 0700) < 0) { 1276 (void) fprintf(io->errs, "can't mkdir '%s'\n", dir); 1277 goto out; 1278 } 1279 (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir); 1280 (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir); 1281 if (!appendkey(io, key, ringfile)) { 1282 (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile); 1283 goto out; 1284 } 1285 if (netpgp->pubring != NULL) { 1286 pgp_keyring_free(netpgp->pubring); 1287 } 1288 /* write secret key */ 1289 (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir); 1290 if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { 1291 fd = pgp_setup_file_write(&create, ringfile, 0); 1292 } 1293 if (fd < 0) { 1294 (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile); 1295 goto out; 1296 } 1297 /* get the passphrase */ 1298 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1299 (attempts = atoi(numtries)) <= 0) { 1300 attempts = MAX_PASSPHRASE_ATTEMPTS; 1301 } else if (strcmp(numtries, "unlimited") == 0) { 1302 attempts = INFINITE_ATTEMPTS; 1303 } 1304 passc = find_passphrase(netpgp->passfp, &cp[ID_OFFSET], passphrase, sizeof(passphrase), attempts); 1305 if (!pgp_write_xfer_seckey(create, key, (uint8_t *)passphrase, (const unsigned)passc, noarmor)) { 1306 (void) fprintf(io->errs, "Cannot write seckey\n"); 1307 goto out1; 1308 } 1309 rv = 1; 1310 out1: 1311 pgp_teardown_file_write(create, fd); 1312 if (netpgp->secring != NULL) { 1313 pgp_keyring_free(netpgp->secring); 1314 } 1315 out: 1316 pgp_keydata_free(key); 1317 free(cp); 1318 return rv; 1319 } 1320 1321 /* encrypt a file */ 1322 int 1323 netpgp_encrypt_file(netpgp_t *netpgp, 1324 const char *userid, 1325 const char *f, 1326 char *out, 1327 int armored) 1328 { 1329 const pgp_key_t *key; 1330 const unsigned overwrite = 1; 1331 const char *suffix; 1332 pgp_io_t *io; 1333 char outname[MAXPATHLEN]; 1334 1335 io = netpgp->io; 1336 if (f == NULL) { 1337 (void) fprintf(io->errs, 1338 "netpgp_encrypt_file: no filename specified\n"); 1339 return 0; 1340 } 1341 suffix = (armored) ? ".asc" : ".gpg"; 1342 /* get key with which to sign */ 1343 if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1344 return 0; 1345 } 1346 if (out == NULL) { 1347 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 1348 out = outname; 1349 } 1350 return (int)pgp_encrypt_file(io, f, out, key, (unsigned)armored, 1351 overwrite, netpgp_getvar(netpgp, "cipher")); 1352 } 1353 1354 #define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----" 1355 1356 /* decrypt a file */ 1357 int 1358 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 1359 { 1360 const unsigned overwrite = 1; 1361 pgp_io_t *io; 1362 unsigned realarmor; 1363 unsigned sshkeys; 1364 char *numtries; 1365 int attempts; 1366 1367 __PGP_USED(armored); 1368 io = netpgp->io; 1369 if (f == NULL) { 1370 (void) fprintf(io->errs, 1371 "netpgp_decrypt_file: no filename specified\n"); 1372 return 0; 1373 } 1374 realarmor = isarmoured(io, f, NULL, ARMOR_HEAD); 1375 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1376 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1377 (attempts = atoi(numtries)) <= 0) { 1378 attempts = MAX_PASSPHRASE_ATTEMPTS; 1379 } else if (strcmp(numtries, "unlimited") == 0) { 1380 attempts = INFINITE_ATTEMPTS; 1381 } 1382 return pgp_decrypt_file(netpgp->io, f, out, netpgp->secring, 1383 netpgp->pubring, 1384 realarmor, overwrite, sshkeys, 1385 netpgp->passfp, attempts, get_passphrase_cb); 1386 } 1387 1388 /* sign a file */ 1389 int 1390 netpgp_sign_file(netpgp_t *netpgp, 1391 const char *userid, 1392 const char *f, 1393 char *out, 1394 int armored, 1395 int cleartext, 1396 int detached) 1397 { 1398 const pgp_key_t *keypair; 1399 const pgp_key_t *pubkey; 1400 const unsigned overwrite = 1; 1401 pgp_seckey_t *seckey; 1402 const char *hashalg; 1403 pgp_io_t *io; 1404 char *numtries; 1405 int attempts; 1406 int ret; 1407 int i; 1408 1409 io = netpgp->io; 1410 if (f == NULL) { 1411 (void) fprintf(io->errs, 1412 "netpgp_sign_file: no filename specified\n"); 1413 return 0; 1414 } 1415 /* get key with which to sign */ 1416 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1417 return 0; 1418 } 1419 ret = 1; 1420 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1421 (attempts = atoi(numtries)) <= 0) { 1422 attempts = MAX_PASSPHRASE_ATTEMPTS; 1423 } else if (strcmp(numtries, "unlimited") == 0) { 1424 attempts = INFINITE_ATTEMPTS; 1425 } 1426 for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { 1427 if (netpgp->passfp == NULL) { 1428 /* print out the user id */ 1429 pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); 1430 if (pubkey == NULL) { 1431 (void) fprintf(io->errs, 1432 "netpgp: warning - using pubkey from secring\n"); 1433 pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", 1434 &keypair->key.seckey.pubkey, 0); 1435 } else { 1436 pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1437 &pubkey->key.pubkey, 0); 1438 } 1439 } 1440 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1441 /* now decrypt key */ 1442 seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); 1443 if (seckey == NULL) { 1444 (void) fprintf(io->errs, "Bad passphrase\n"); 1445 } 1446 } else { 1447 pgp_keyring_t *secring; 1448 1449 secring = netpgp->secring; 1450 seckey = &secring->keys[0].key.seckey; 1451 } 1452 } 1453 if (seckey == NULL) { 1454 (void) fprintf(io->errs, "Bad passphrase\n"); 1455 return 0; 1456 } 1457 /* sign file */ 1458 hashalg = netpgp_getvar(netpgp, "hash"); 1459 if (seckey->pubkey.alg == PGP_PKA_DSA) { 1460 hashalg = "sha1"; 1461 } 1462 if (detached) { 1463 ret = pgp_sign_detached(io, f, out, seckey, hashalg, 1464 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1465 get_duration(netpgp_getvar(netpgp, "duration")), 1466 (unsigned)armored, 1467 overwrite); 1468 } else { 1469 ret = pgp_sign_file(io, f, out, seckey, hashalg, 1470 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1471 get_duration(netpgp_getvar(netpgp, "duration")), 1472 (unsigned)armored, (unsigned)cleartext, 1473 overwrite); 1474 } 1475 pgp_forget(seckey, sizeof(*seckey)); 1476 return ret; 1477 } 1478 1479 #define ARMOR_SIG_HEAD "-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----" 1480 1481 /* verify a file */ 1482 int 1483 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 1484 { 1485 pgp_validation_t result; 1486 pgp_io_t *io; 1487 unsigned realarmor; 1488 1489 __PGP_USED(armored); 1490 (void) memset(&result, 0x0, sizeof(result)); 1491 io = netpgp->io; 1492 if (in == NULL) { 1493 (void) fprintf(io->errs, 1494 "netpgp_verify_file: no filename specified\n"); 1495 return 0; 1496 } 1497 realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD); 1498 if (pgp_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) { 1499 resultp(io, in, &result, netpgp->pubring); 1500 return 1; 1501 } 1502 if (result.validc + result.invalidc + result.unknownc == 0) { 1503 (void) fprintf(io->errs, 1504 "\"%s\": No signatures found - is this a signed file?\n", 1505 in); 1506 } else if (result.invalidc == 0 && result.unknownc == 0) { 1507 (void) fprintf(io->errs, 1508 "\"%s\": file verification failure: invalid signature time\n", in); 1509 } else { 1510 (void) fprintf(io->errs, 1511 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 1512 in, result.invalidc, result.unknownc); 1513 } 1514 return 0; 1515 } 1516 1517 /* sign some memory */ 1518 int 1519 netpgp_sign_memory(netpgp_t *netpgp, 1520 const char *userid, 1521 char *mem, 1522 size_t size, 1523 char *out, 1524 size_t outsize, 1525 const unsigned armored, 1526 const unsigned cleartext) 1527 { 1528 const pgp_key_t *keypair; 1529 const pgp_key_t *pubkey; 1530 pgp_seckey_t *seckey; 1531 pgp_memory_t *signedmem; 1532 const char *hashalg; 1533 pgp_io_t *io; 1534 char *numtries; 1535 int attempts; 1536 int ret; 1537 int i; 1538 1539 io = netpgp->io; 1540 if (mem == NULL) { 1541 (void) fprintf(io->errs, 1542 "netpgp_sign_memory: no memory to sign\n"); 1543 return 0; 1544 } 1545 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1546 return 0; 1547 } 1548 ret = 1; 1549 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1550 (attempts = atoi(numtries)) <= 0) { 1551 attempts = MAX_PASSPHRASE_ATTEMPTS; 1552 } else if (strcmp(numtries, "unlimited") == 0) { 1553 attempts = INFINITE_ATTEMPTS; 1554 } 1555 for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { 1556 if (netpgp->passfp == NULL) { 1557 /* print out the user id */ 1558 pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); 1559 if (pubkey == NULL) { 1560 (void) fprintf(io->errs, 1561 "netpgp: warning - using pubkey from secring\n"); 1562 pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", 1563 &keypair->key.seckey.pubkey, 0); 1564 } else { 1565 pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1566 &pubkey->key.pubkey, 0); 1567 } 1568 } 1569 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1570 /* now decrypt key */ 1571 seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); 1572 if (seckey == NULL) { 1573 (void) fprintf(io->errs, "Bad passphrase\n"); 1574 } 1575 } else { 1576 pgp_keyring_t *secring; 1577 1578 secring = netpgp->secring; 1579 seckey = &secring->keys[0].key.seckey; 1580 } 1581 } 1582 if (seckey == NULL) { 1583 (void) fprintf(io->errs, "Bad passphrase\n"); 1584 return 0; 1585 } 1586 /* sign file */ 1587 (void) memset(out, 0x0, outsize); 1588 hashalg = netpgp_getvar(netpgp, "hash"); 1589 if (seckey->pubkey.alg == PGP_PKA_DSA) { 1590 hashalg = "sha1"; 1591 } 1592 signedmem = pgp_sign_buf(io, mem, size, seckey, 1593 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1594 get_duration(netpgp_getvar(netpgp, "duration")), 1595 hashalg, armored, cleartext); 1596 if (signedmem) { 1597 size_t m; 1598 1599 m = MIN(pgp_mem_len(signedmem), outsize); 1600 (void) memcpy(out, pgp_mem_data(signedmem), m); 1601 pgp_memory_free(signedmem); 1602 ret = (int)m; 1603 } else { 1604 ret = 0; 1605 } 1606 pgp_forget(seckey, sizeof(*seckey)); 1607 return ret; 1608 } 1609 1610 /* verify memory */ 1611 int 1612 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, 1613 void *out, size_t outsize, const int armored) 1614 { 1615 pgp_validation_t result; 1616 pgp_memory_t *signedmem; 1617 pgp_memory_t *cat; 1618 pgp_io_t *io; 1619 size_t m; 1620 int ret; 1621 1622 (void) memset(&result, 0x0, sizeof(result)); 1623 io = netpgp->io; 1624 if (in == NULL) { 1625 (void) fprintf(io->errs, 1626 "netpgp_verify_memory: no memory to verify\n"); 1627 return 0; 1628 } 1629 signedmem = pgp_memory_new(); 1630 pgp_memory_add(signedmem, in, size); 1631 if (out) { 1632 cat = pgp_memory_new(); 1633 } 1634 ret = pgp_validate_mem(io, &result, signedmem, 1635 (out) ? &cat : NULL, 1636 armored, netpgp->pubring); 1637 /* signedmem is freed from pgp_validate_mem */ 1638 if (ret) { 1639 resultp(io, "<stdin>", &result, netpgp->pubring); 1640 if (out) { 1641 m = MIN(pgp_mem_len(cat), outsize); 1642 (void) memcpy(out, pgp_mem_data(cat), m); 1643 pgp_memory_free(cat); 1644 } else { 1645 m = 1; 1646 } 1647 return (int)m; 1648 } 1649 if (result.validc + result.invalidc + result.unknownc == 0) { 1650 (void) fprintf(io->errs, 1651 "No signatures found - is this memory signed?\n"); 1652 } else if (result.invalidc == 0 && result.unknownc == 0) { 1653 (void) fprintf(io->errs, 1654 "memory verification failure: invalid signature time\n"); 1655 } else { 1656 (void) fprintf(io->errs, 1657 "memory verification failure: %u invalid signatures, %u unknown signatures\n", 1658 result.invalidc, result.unknownc); 1659 } 1660 return 0; 1661 } 1662 1663 /* encrypt some memory */ 1664 int 1665 netpgp_encrypt_memory(netpgp_t *netpgp, 1666 const char *userid, 1667 void *in, 1668 const size_t insize, 1669 char *out, 1670 size_t outsize, 1671 int armored) 1672 { 1673 const pgp_key_t *keypair; 1674 pgp_memory_t *enc; 1675 pgp_io_t *io; 1676 size_t m; 1677 1678 io = netpgp->io; 1679 if (in == NULL) { 1680 (void) fprintf(io->errs, 1681 "netpgp_encrypt_buf: no memory to encrypt\n"); 1682 return 0; 1683 } 1684 if ((keypair = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1685 return 0; 1686 } 1687 if (in == out) { 1688 (void) fprintf(io->errs, 1689 "netpgp_encrypt_buf: input and output bufs need to be different\n"); 1690 return 0; 1691 } 1692 if (outsize < insize) { 1693 (void) fprintf(io->errs, 1694 "netpgp_encrypt_buf: input size is larger than output size\n"); 1695 return 0; 1696 } 1697 enc = pgp_encrypt_buf(io, in, insize, keypair, (unsigned)armored, 1698 netpgp_getvar(netpgp, "cipher")); 1699 m = MIN(pgp_mem_len(enc), outsize); 1700 (void) memcpy(out, pgp_mem_data(enc), m); 1701 pgp_memory_free(enc); 1702 return (int)m; 1703 } 1704 1705 /* decrypt a chunk of memory */ 1706 int 1707 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize, 1708 char *out, size_t outsize, const int armored) 1709 { 1710 pgp_memory_t *mem; 1711 pgp_io_t *io; 1712 unsigned realarmour; 1713 unsigned sshkeys; 1714 size_t m; 1715 char *numtries; 1716 int attempts; 1717 1718 __PGP_USED(armored); 1719 io = netpgp->io; 1720 if (input == NULL) { 1721 (void) fprintf(io->errs, 1722 "netpgp_decrypt_memory: no memory\n"); 1723 return 0; 1724 } 1725 realarmour = isarmoured(io, NULL, input, ARMOR_HEAD); 1726 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1727 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1728 (attempts = atoi(numtries)) <= 0) { 1729 attempts = MAX_PASSPHRASE_ATTEMPTS; 1730 } else if (strcmp(numtries, "unlimited") == 0) { 1731 attempts = INFINITE_ATTEMPTS; 1732 } 1733 mem = pgp_decrypt_buf(netpgp->io, input, insize, netpgp->secring, 1734 netpgp->pubring, 1735 realarmour, sshkeys, 1736 netpgp->passfp, 1737 attempts, 1738 get_passphrase_cb); 1739 if (mem == NULL) { 1740 return -1; 1741 } 1742 m = MIN(pgp_mem_len(mem), outsize); 1743 (void) memcpy(out, pgp_mem_data(mem), m); 1744 pgp_memory_free(mem); 1745 return (int)m; 1746 } 1747 1748 /* wrappers for the ops_debug_level functions we added to openpgpsdk */ 1749 1750 /* set the debugging level per filename */ 1751 int 1752 netpgp_set_debug(const char *f) 1753 { 1754 return pgp_set_debug_level(f); 1755 } 1756 1757 /* get the debugging level per filename */ 1758 int 1759 netpgp_get_debug(const char *f) 1760 { 1761 return pgp_get_debug_level(f); 1762 } 1763 1764 /* return the version for the library */ 1765 const char * 1766 netpgp_get_info(const char *type) 1767 { 1768 return pgp_get_info(type); 1769 } 1770 1771 /* list all the packets in a file */ 1772 int 1773 netpgp_list_packets(netpgp_t *netpgp, char *f, int armor, char *pubringname) 1774 { 1775 pgp_keyring_t *keyring; 1776 const unsigned noarmor = 0; 1777 struct stat st; 1778 pgp_io_t *io; 1779 char ringname[MAXPATHLEN]; 1780 char *homedir; 1781 int ret; 1782 1783 io = netpgp->io; 1784 if (f == NULL) { 1785 (void) fprintf(io->errs, "No file containing packets\n"); 1786 return 0; 1787 } 1788 if (stat(f, &st) < 0) { 1789 (void) fprintf(io->errs, "No such file '%s'\n", f); 1790 return 0; 1791 } 1792 homedir = netpgp_getvar(netpgp, "homedir"); 1793 if (pubringname == NULL) { 1794 (void) snprintf(ringname, sizeof(ringname), 1795 "%s/pubring.gpg", homedir); 1796 pubringname = ringname; 1797 } 1798 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1799 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); 1800 return 0; 1801 } 1802 if (!pgp_keyring_fileread(keyring, noarmor, pubringname)) { 1803 free(keyring); 1804 (void) fprintf(io->errs, "Cannot read pub keyring %s\n", 1805 pubringname); 1806 return 0; 1807 } 1808 netpgp->pubring = keyring; 1809 netpgp_setvar(netpgp, "pubring", pubringname); 1810 ret = pgp_list_packets(io, f, (unsigned)armor, 1811 netpgp->secring, 1812 netpgp->pubring, 1813 netpgp->passfp, 1814 get_passphrase_cb); 1815 free(keyring); 1816 return ret; 1817 } 1818 1819 /* set a variable */ 1820 int 1821 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) 1822 { 1823 char *newval; 1824 int i; 1825 1826 /* protect against the case where 'value' is netpgp->value[i] */ 1827 newval = netpgp_strdup(value); 1828 if ((i = findvar(netpgp, name)) < 0) { 1829 /* add the element to the array */ 1830 if (size_arrays(netpgp, netpgp->size + 15)) { 1831 netpgp->name[i = netpgp->c++] = netpgp_strdup(name); 1832 } 1833 } else { 1834 /* replace the element in the array */ 1835 if (netpgp->value[i]) { 1836 free(netpgp->value[i]); 1837 netpgp->value[i] = NULL; 1838 } 1839 } 1840 /* sanity checks for range of values */ 1841 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { 1842 if (pgp_str_to_hash_alg(newval) == PGP_HASH_UNKNOWN) { 1843 free(newval); 1844 return 0; 1845 } 1846 } 1847 netpgp->value[i] = newval; 1848 return 1; 1849 } 1850 1851 /* unset a variable */ 1852 int 1853 netpgp_unsetvar(netpgp_t *netpgp, const char *name) 1854 { 1855 int i; 1856 1857 if ((i = findvar(netpgp, name)) >= 0) { 1858 if (netpgp->value[i]) { 1859 free(netpgp->value[i]); 1860 netpgp->value[i] = NULL; 1861 } 1862 netpgp->value[i] = NULL; 1863 return 1; 1864 } 1865 return 0; 1866 } 1867 1868 /* get a variable's value (NULL if not set) */ 1869 char * 1870 netpgp_getvar(netpgp_t *netpgp, const char *name) 1871 { 1872 int i; 1873 1874 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; 1875 } 1876 1877 /* increment a value */ 1878 int 1879 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) 1880 { 1881 char *cp; 1882 char num[16]; 1883 int val; 1884 1885 val = 0; 1886 if ((cp = netpgp_getvar(netpgp, name)) != NULL) { 1887 val = atoi(cp); 1888 } 1889 (void) snprintf(num, sizeof(num), "%d", val + delta); 1890 netpgp_setvar(netpgp, name, num); 1891 return 1; 1892 } 1893 1894 /* set the home directory value to "home/subdir" */ 1895 int 1896 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) 1897 { 1898 struct stat st; 1899 char d[MAXPATHLEN]; 1900 1901 if (home == NULL) { 1902 if (!quiet) { 1903 (void) fprintf(stderr, "NULL HOME directory\n"); 1904 } 1905 return 0; 1906 } 1907 (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); 1908 if (stat(d, &st) == 0) { 1909 if ((st.st_mode & S_IFMT) == S_IFDIR) { 1910 netpgp_setvar(netpgp, "homedir", d); 1911 return 1; 1912 } 1913 (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", 1914 d); 1915 return 0; 1916 } 1917 if (!quiet) { 1918 (void) fprintf(stderr, 1919 "netpgp: warning homedir \"%s\" not found\n", d); 1920 } 1921 netpgp_setvar(netpgp, "homedir", d); 1922 return 1; 1923 } 1924 1925 /* validate all sigs in the pub keyring */ 1926 int 1927 netpgp_validate_sigs(netpgp_t *netpgp) 1928 { 1929 pgp_validation_t result; 1930 1931 return (int)pgp_validate_all_sigs(&result, netpgp->pubring, NULL); 1932 } 1933 1934 /* print the json out on 'fp' */ 1935 int 1936 netpgp_format_json(void *vp, const char *json, const int psigs) 1937 { 1938 mj_t ids; 1939 FILE *fp; 1940 int from; 1941 int idc; 1942 int tok; 1943 int to; 1944 int i; 1945 1946 if ((fp = (FILE *)vp) == NULL || json == NULL) { 1947 return 0; 1948 } 1949 /* ids is an array of strings, each containing 1 entry */ 1950 (void) memset(&ids, 0x0, sizeof(ids)); 1951 from = to = tok = 0; 1952 /* convert from string into an mj structure */ 1953 (void) mj_parse(&ids, json, &from, &to, &tok); 1954 if ((idc = mj_arraycount(&ids)) == 1 && strchr(json, '{') == NULL) { 1955 idc = 0; 1956 } 1957 (void) fprintf(fp, "%d key%s found\n", idc, (idc == 1) ? "" : "s"); 1958 for (i = 0 ; i < idc ; i++) { 1959 format_json_key(fp, &ids.value.v[i], psigs); 1960 } 1961 /* clean up */ 1962 mj_delete(&ids); 1963 return idc; 1964 } 1965 1966 /* find a key in keyring, and write it in ssh format */ 1967 int 1968 netpgp_write_sshkey(netpgp_t *netpgp, char *s, const char *userid, char *out, size_t size) 1969 { 1970 const pgp_key_t *key; 1971 pgp_keyring_t *keyring; 1972 pgp_io_t *io; 1973 unsigned k; 1974 size_t cc; 1975 char f[MAXPATHLEN]; 1976 1977 keyring = NULL; 1978 io = NULL; 1979 cc = 0; 1980 if ((io = calloc(1, sizeof(pgp_io_t))) == NULL) { 1981 (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 1\n"); 1982 goto done; 1983 } 1984 io->outs = stdout; 1985 io->errs = stderr; 1986 io->res = stderr; 1987 netpgp->io = io; 1988 /* write new to temp file */ 1989 savepubkey(s, f, sizeof(f)); 1990 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1991 (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 2\n"); 1992 goto done; 1993 } 1994 if (!pgp_keyring_fileread(netpgp->pubring = keyring, 1, f)) { 1995 (void) fprintf(stderr, "can't import key\n"); 1996 goto done; 1997 } 1998 /* get rsa key */ 1999 k = 0; 2000 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, userid, &k); 2001 if (key == NULL) { 2002 (void) fprintf(stderr, "no key found for '%s'\n", userid); 2003 goto done; 2004 } 2005 if (key->key.pubkey.alg != PGP_PKA_RSA) { 2006 /* we're not interested in supporting DSA either :-) */ 2007 (void) fprintf(stderr, "key not RSA '%s'\n", userid); 2008 goto done; 2009 } 2010 /* XXX - check trust sigs */ 2011 /* XXX - check expiry */ 2012 /* XXX - check start */ 2013 /* XXX - check not weak key */ 2014 /* get rsa e and n */ 2015 (void) memset(out, 0x0, size); 2016 cc = formatstring((char *)out, (const uint8_t *)"ssh-rsa", 7); 2017 cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.e); 2018 cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.n); 2019 done: 2020 if (io) { 2021 free(io); 2022 } 2023 if (keyring) { 2024 free(keyring); 2025 } 2026 return (int)cc; 2027 } 2028