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.102 2018/11/13 14:52:30 mlelstv 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 free(filename); 301 free(keyring); 302 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 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 free(filename); 321 (void) fprintf(stderr, "Can't write %s %s\n", name, 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) { 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 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 unsigned i; 588 char *s; 589 590 if (obj == NULL) { 591 (void) fprintf(stderr, "No object found\n"); 592 return; 593 } 594 595 mj_pretty(obj, fp, depth, ""); 596 } 597 598 /* return the time as a string */ 599 static char * 600 ptimestr(char *dest, size_t size, time_t t) 601 { 602 struct tm *tm; 603 604 tm = gmtime(&t); 605 (void) snprintf(dest, size, "%04d-%02d-%02d", 606 tm->tm_year + 1900, 607 tm->tm_mon + 1, 608 tm->tm_mday); 609 return dest; 610 } 611 612 /* format a JSON object */ 613 static void 614 format_json_key(FILE *fp, mj_t *obj, const int psigs) 615 { 616 int64_t birthtime; 617 int64_t duration; 618 time_t now; 619 char tbuf[32]; 620 char *s; 621 mj_t *sub; 622 int i; 623 624 if (pgp_get_debug_level(__FILE__)) { 625 mj_asprint(&s, obj, MJ_HUMAN); 626 (void) fprintf(stderr, "formatobj: json is '%s'\n", s); 627 free(s); 628 } 629 if (obj->c == 2 && obj->value.v[1].type == MJ_STRING && 630 strcmp(obj->value.v[1].value.s, "[REVOKED]") == 0) { 631 /* whole key has been rovoked - just return */ 632 return; 633 } 634 pobj(fp, &obj->value.v[mj_object_find(obj, "header", 0, 2) + 1], 0); 635 p(fp, " ", NULL); 636 pobj(fp, &obj->value.v[mj_object_find(obj, "key bits", 0, 2) + 1], 0); 637 p(fp, "/", NULL); 638 pobj(fp, &obj->value.v[mj_object_find(obj, "pka", 0, 2) + 1], 0); 639 p(fp, " ", NULL); 640 pobj(fp, &obj->value.v[mj_object_find(obj, "key id", 0, 2) + 1], 0); 641 birthtime = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "birthtime", 0, 2) + 1].value.s, NULL, 10); 642 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), birthtime), NULL); 643 duration = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "duration", 0, 2) + 1].value.s, NULL, 10); 644 if (duration > 0) { 645 now = time(NULL); 646 p(fp, " ", (birthtime + duration < now) ? "[EXPIRED " : "[EXPIRES ", 647 ptimestr(tbuf, sizeof(tbuf), birthtime + duration), "]", NULL); 648 } 649 p(fp, "\n", "Key fingerprint: ", NULL); 650 pobj(fp, &obj->value.v[mj_object_find(obj, "fingerprint", 0, 2) + 1], 0); 651 p(fp, "\n", NULL); 652 /* go to field after \"duration\" */ 653 for (i = mj_object_find(obj, "duration", 0, 2) + 2; i < mj_arraycount(obj) ; i += 2) { 654 if (strcmp(obj->value.v[i].value.s, "uid") == 0) { 655 sub = &obj->value.v[i + 1]; 656 p(fp, "uid", NULL); 657 pobj(fp, &sub->value.v[0], (psigs) ? 4 : 14); /* human name */ 658 pobj(fp, &sub->value.v[1], 1); /* any revocation */ 659 p(fp, "\n", NULL); 660 } else if (strcmp(obj->value.v[i].value.s, "encryption") == 0) { 661 sub = &obj->value.v[i + 1]; 662 p(fp, "encryption", NULL); 663 pobj(fp, &sub->value.v[0], 1); /* size */ 664 p(fp, "/", NULL); 665 pobj(fp, &sub->value.v[1], 0); /* alg */ 666 p(fp, " ", NULL); 667 pobj(fp, &sub->value.v[2], 0); /* id */ 668 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), 669 (time_t)strtoll(sub->value.v[3].value.s, NULL, 10)), 670 "\n", NULL); 671 } else if (strcmp(obj->value.v[i].value.s, "sig") == 0) { 672 sub = &obj->value.v[i + 1]; 673 p(fp, "sig", NULL); 674 pobj(fp, &sub->value.v[0], 8); /* size */ 675 p(fp, " ", ptimestr(tbuf, sizeof(tbuf), 676 (time_t)strtoll(sub->value.v[1].value.s, NULL, 10)), 677 " ", NULL); /* time */ 678 pobj(fp, &sub->value.v[2], 0); /* human name */ 679 p(fp, "\n", NULL); 680 } else { 681 fprintf(stderr, "weird '%s'\n", obj->value.v[i].value.s); 682 pobj(fp, &obj->value.v[i], 0); /* human name */ 683 } 684 } 685 p(fp, "\n", NULL); 686 } 687 688 /* save a pgp pubkey to a temp file */ 689 static int 690 savepubkey(char *res, char *f, size_t size) 691 { 692 size_t len; 693 int cc; 694 int wc; 695 int fd; 696 697 (void) snprintf(f, size, "/tmp/pgp2ssh.XXXXXXX"); 698 if ((fd = mkstemp(f)) < 0) { 699 (void) fprintf(stderr, "can't create temp file '%s'\n", f); 700 return 0; 701 } 702 len = strlen(res); 703 for (cc = 0 ; (wc = (int)write(fd, &res[cc], len - (size_t)cc)) > 0 ; cc += wc) { 704 } 705 (void) close(fd); 706 return 1; 707 } 708 709 /* format a uint32_t */ 710 static int 711 formatu32(uint8_t *buffer, uint32_t value) 712 { 713 buffer[0] = (uint8_t)(value >> 24) & 0xff; 714 buffer[1] = (uint8_t)(value >> 16) & 0xff; 715 buffer[2] = (uint8_t)(value >> 8) & 0xff; 716 buffer[3] = (uint8_t)value & 0xff; 717 return sizeof(uint32_t); 718 } 719 720 /* format a string as (len, string) */ 721 static int 722 formatstring(char *buffer, const uint8_t *s, size_t len) 723 { 724 int cc; 725 726 cc = formatu32((uint8_t *)buffer, (uint32_t)len); 727 (void) memcpy(&buffer[cc], s, len); 728 return cc + (int)len; 729 } 730 731 /* format a bignum, checking for "interesting" high bit values */ 732 static int 733 formatbignum(char *buffer, BIGNUM *bn) 734 { 735 size_t len; 736 uint8_t *cp; 737 int cc; 738 739 len = (size_t) BN_num_bytes(bn); 740 if ((cp = calloc(1, len + 1)) == NULL) { 741 (void) fprintf(stderr, "calloc failure in formatbignum\n"); 742 return 0; 743 } 744 (void) BN_bn2bin(bn, cp + 1); 745 cp[0] = 0x0; 746 cc = (cp[1] & 0x80) ? formatstring(buffer, cp, len + 1) : formatstring(buffer, &cp[1], len); 747 free(cp); 748 return cc; 749 } 750 751 #define MAX_PASSPHRASE_ATTEMPTS 3 752 #define INFINITE_ATTEMPTS -1 753 754 /* get the passphrase from the user */ 755 static int 756 find_passphrase(FILE *passfp, const char *id, char *passphrase, size_t size, int attempts) 757 { 758 char prompt[BUFSIZ]; 759 char buf[128]; 760 char *cp; 761 int cc; 762 int i; 763 764 if (passfp) { 765 if (fgets(passphrase, (int)size, passfp) == NULL) { 766 return 0; 767 } 768 return (int)strlen(passphrase); 769 } 770 for (i = 0 ; i < attempts ; i++) { 771 (void) snprintf(prompt, sizeof(prompt), "Enter passphrase for %.16s: ", id); 772 if ((cp = getpass(prompt)) == NULL) { 773 break; 774 } 775 cc = snprintf(buf, sizeof(buf), "%s", cp); 776 (void) snprintf(prompt, sizeof(prompt), "Repeat passphrase for %.16s: ", id); 777 if ((cp = getpass(prompt)) == NULL) { 778 break; 779 } 780 cc = snprintf(passphrase, size, "%s", cp); 781 if (strcmp(buf, passphrase) == 0) { 782 (void) memset(buf, 0x0, sizeof(buf)); 783 return cc; 784 } 785 } 786 (void) memset(buf, 0x0, sizeof(buf)); 787 (void) memset(passphrase, 0x0, size); 788 return 0; 789 } 790 791 /***************************************************************************/ 792 /* exported functions start here */ 793 /***************************************************************************/ 794 795 /* initialise a netpgp_t structure */ 796 int 797 netpgp_init(netpgp_t *netpgp) 798 { 799 pgp_io_t *io; 800 time_t t; 801 char id[MAX_ID_LENGTH]; 802 char *homedir; 803 char *userid; 804 char *stream; 805 char *passfd; 806 char *results; 807 int coredumps; 808 int last; 809 810 #ifdef HAVE_SYS_RESOURCE_H 811 struct rlimit limit; 812 813 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 814 if (!coredumps) { 815 (void) memset(&limit, 0x0, sizeof(limit)); 816 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 817 (void) fprintf(stderr, 818 "netpgp: warning - can't turn off core dumps\n"); 819 coredumps = 1; 820 } 821 } 822 #else 823 coredumps = 1; 824 #endif 825 if ((io = calloc(1, sizeof(*io))) == NULL) { 826 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 827 return 0; 828 } 829 io->outs = stdout; 830 if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && 831 strcmp(stream, "<stderr>") == 0) { 832 io->outs = stderr; 833 } 834 io->errs = stderr; 835 if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && 836 strcmp(stream, "<stdout>") == 0) { 837 io->errs = stdout; 838 } 839 if ((results = netpgp_getvar(netpgp, "res")) == NULL) { 840 io->res = io->errs; 841 } else if (strcmp(results, "<stdout>") == 0) { 842 io->res = stdout; 843 } else if (strcmp(results, "<stderr>") == 0) { 844 io->res = stderr; 845 } else { 846 if ((io->res = fopen(results, "w")) == NULL) { 847 (void) fprintf(io->errs, "Can't open results %s for writing\n", 848 results); 849 free(io); 850 return 0; 851 } 852 } 853 netpgp->io = io; 854 /* get passphrase from an fd */ 855 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 856 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 857 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 858 passfd); 859 return 0; 860 } 861 /* warn if core dumps are enabled */ 862 if (coredumps) { 863 (void) fprintf(io->errs, 864 "netpgp: warning: core dumps enabled\n"); 865 } 866 /* get home directory - where keyrings are in a subdir */ 867 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 868 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 869 return 0; 870 } 871 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 872 /* read from ordinary pgp keyrings */ 873 netpgp->pubring = readkeyring(netpgp, "pubring"); 874 if (netpgp->pubring == NULL) { 875 return 0; 876 } 877 /* if a userid has been given, we'll use it */ 878 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 879 /* also search in config file for default id */ 880 (void) memset(id, 0x0, sizeof(id)); 881 (void) conffile(netpgp, homedir, id, sizeof(id)); 882 if (id[0] != 0x0) { 883 netpgp_setvar(netpgp, "userid", userid = id); 884 } 885 } 886 /* only read secret keys if we need to */ 887 if (netpgp_getvar(netpgp, "need seckey")) { 888 /* read the secret ring */ 889 netpgp->secring = readkeyring(netpgp, "secring"); 890 if (netpgp->secring == NULL) { 891 return 0; 892 } 893 /* now, if we don't have a valid user, use the first in secring */ 894 if (!userid && netpgp_getvar(netpgp, "need userid") != NULL) { 895 /* signing - need userid and sec key */ 896 (void) memset(id, 0x0, sizeof(id)); 897 if (get_first_ring(netpgp->secring, id, sizeof(id), 0)) { 898 netpgp_setvar(netpgp, "userid", userid = id); 899 } 900 } 901 } else if (netpgp_getvar(netpgp, "need userid") != NULL) { 902 /* encrypting - get first in pubring */ 903 if (!userid && get_first_ring(netpgp->pubring, id, sizeof(id), 0)) { 904 (void) netpgp_setvar(netpgp, "userid", userid = id); 905 } 906 } 907 if (!userid && netpgp_getvar(netpgp, "need userid")) { 908 /* if we don't have a user id, and we need one, fail */ 909 (void) fprintf(io->errs, "Cannot find user id\n"); 910 return 0; 911 } 912 } else { 913 /* read from ssh keys */ 914 last = (netpgp->pubring != NULL); 915 if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need seckey"))) { 916 return 0; 917 } 918 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 919 get_first_ring(netpgp->pubring, id, sizeof(id), last); 920 netpgp_setvar(netpgp, "userid", userid = id); 921 } 922 if (userid == NULL) { 923 if (netpgp_getvar(netpgp, "need userid") != NULL) { 924 (void) fprintf(io->errs, 925 "Cannot find user id\n"); 926 return 0; 927 } 928 } else { 929 (void) netpgp_setvar(netpgp, "userid", userid); 930 } 931 } 932 t = time(NULL); 933 netpgp_setvar(netpgp, "initialised", ctime(&t)); 934 return 1; 935 } 936 937 /* finish off with the netpgp_t struct */ 938 int 939 netpgp_end(netpgp_t *netpgp) 940 { 941 unsigned i; 942 943 for (i = 0 ; i < netpgp->c ; i++) { 944 if (netpgp->name[i] != NULL) { 945 free(netpgp->name[i]); 946 } 947 if (netpgp->value[i] != NULL) { 948 free(netpgp->value[i]); 949 } 950 } 951 if (netpgp->name != NULL) { 952 free(netpgp->name); 953 } 954 if (netpgp->value != NULL) { 955 free(netpgp->value); 956 } 957 if (netpgp->pubring != NULL) { 958 pgp_keyring_free(netpgp->pubring); 959 } 960 if (netpgp->secring != NULL) { 961 pgp_keyring_free(netpgp->secring); 962 } 963 free(netpgp->io); 964 return 1; 965 } 966 967 /* list the keys in a keyring */ 968 int 969 netpgp_list_keys(netpgp_t *netpgp, const int psigs) 970 { 971 if (netpgp->pubring == NULL) { 972 (void) fprintf(stderr, "No keyring\n"); 973 return 0; 974 } 975 return pgp_keyring_list(netpgp->io, netpgp->pubring, psigs); 976 } 977 978 /* list the keys in a keyring, returning a JSON encoded string */ 979 int 980 netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs) 981 { 982 mj_t obj; 983 int ret; 984 985 if (netpgp->pubring == NULL) { 986 (void) fprintf(stderr, "No keyring\n"); 987 return 0; 988 } 989 (void) memset(&obj, 0x0, sizeof(obj)); 990 if (!pgp_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) { 991 (void) fprintf(stderr, "No keys in keyring\n"); 992 return 0; 993 } 994 ret = mj_asprint(json, &obj, MJ_JSON_ENCODE); 995 mj_delete(&obj); 996 return ret; 997 } 998 999 DEFINE_ARRAY(strings_t, char *); 1000 1001 #ifndef HKP_VERSION 1002 #define HKP_VERSION 1 1003 #endif 1004 1005 /* find and list some keys in a keyring */ 1006 int 1007 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs) 1008 { 1009 const pgp_key_t *key; 1010 unsigned k; 1011 strings_t pubs; 1012 FILE *fp = (FILE *)vp; 1013 1014 if (name[0] == '0' && name[1] == 'x') { 1015 name += 2; 1016 } 1017 (void) memset(&pubs, 0x0, sizeof(pubs)); 1018 k = 0; 1019 do { 1020 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1021 name, &k); 1022 if (key != NULL) { 1023 ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, 1024 "netpgp_match_keys", return 0); 1025 if (strcmp(fmt, "mr") == 0) { 1026 pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1027 key, &pubs.v[pubs.c], 1028 &key->key.pubkey, psigs); 1029 } else { 1030 pgp_sprint_keydata(netpgp->io, netpgp->pubring, 1031 key, &pubs.v[pubs.c], 1032 "signature ", 1033 &key->key.pubkey, psigs); 1034 } 1035 if (pubs.v[pubs.c] != NULL) { 1036 pubs.c += 1; 1037 } 1038 k += 1; 1039 } 1040 } while (key != NULL); 1041 if (strcmp(fmt, "mr") == 0) { 1042 (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); 1043 } else { 1044 (void) fprintf(fp, "%d key%s found\n", pubs.c, 1045 (pubs.c == 1) ? "" : "s"); 1046 } 1047 for (k = 0 ; k < pubs.c ; k++) { 1048 (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : ""); 1049 free(pubs.v[k]); 1050 } 1051 free(pubs.v); 1052 return pubs.c; 1053 } 1054 1055 /* find and list some keys in a keyring - return JSON string */ 1056 int 1057 netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs) 1058 { 1059 const pgp_key_t *key; 1060 unsigned k; 1061 mj_t id_array; 1062 char *newkey; 1063 int ret; 1064 1065 if (name[0] == '0' && name[1] == 'x') { 1066 name += 2; 1067 } 1068 (void) memset(&id_array, 0x0, sizeof(id_array)); 1069 k = 0; 1070 *json = NULL; 1071 mj_create(&id_array, "array"); 1072 do { 1073 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1074 name, &k); 1075 if (key != NULL) { 1076 if (strcmp(fmt, "mr") == 0) { 1077 pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1078 key, &newkey, 1079 &key->key.pubkey, 0); 1080 if (newkey) { 1081 printf("%s\n", newkey); 1082 free(newkey); 1083 } 1084 } else { 1085 ALLOC(mj_t, id_array.value.v, id_array.size, 1086 id_array.c, 10, 10, "netpgp_match_keys_json", return 0); 1087 pgp_sprint_mj(netpgp->io, netpgp->pubring, 1088 key, &id_array.value.v[id_array.c++], 1089 "signature", 1090 &key->key.pubkey, psigs); 1091 } 1092 k += 1; 1093 } 1094 } while (key != NULL); 1095 ret = mj_asprint(json, &id_array, MJ_JSON_ENCODE); 1096 mj_delete(&id_array); 1097 return ret; 1098 } 1099 1100 /* find and list some public keys in a keyring */ 1101 int 1102 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) 1103 { 1104 const pgp_key_t *key; 1105 unsigned k; 1106 ssize_t cc; 1107 char out[1024 * 64]; 1108 FILE *fp = (FILE *)vp; 1109 1110 k = 0; 1111 do { 1112 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, 1113 name, &k); 1114 if (key != NULL) { 1115 cc = pgp_sprint_pubkey(key, out, sizeof(out)); 1116 (void) fprintf(fp, "%.*s", (int)cc, out); 1117 k += 1; 1118 } 1119 } while (key != NULL); 1120 return k; 1121 } 1122 1123 /* find a key in a keyring */ 1124 int 1125 netpgp_find_key(netpgp_t *netpgp, char *id) 1126 { 1127 pgp_io_t *io; 1128 1129 io = netpgp->io; 1130 if (id == NULL) { 1131 (void) fprintf(io->errs, "NULL id to search for\n"); 1132 return 0; 1133 } 1134 return pgp_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 1135 } 1136 1137 /* get a key in a keyring */ 1138 char * 1139 netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt) 1140 { 1141 const pgp_key_t *key; 1142 char *newkey; 1143 1144 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1145 return NULL; 1146 } 1147 if (strcmp(fmt, "mr") == 0) { 1148 return (pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, 1149 key, &newkey, 1150 &key->key.pubkey, 1151 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1152 } 1153 return (pgp_sprint_keydata(netpgp->io, netpgp->pubring, 1154 key, &newkey, "signature", 1155 &key->key.pubkey, 1156 netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; 1157 } 1158 1159 /* export a given key */ 1160 char * 1161 netpgp_export_key(netpgp_t *netpgp, char *name) 1162 { 1163 const pgp_key_t *key; 1164 pgp_io_t *io; 1165 1166 io = netpgp->io; 1167 if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { 1168 return NULL; 1169 } 1170 return pgp_export_key(io, key, NULL); 1171 } 1172 1173 #define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----" 1174 1175 /* import a key into our keyring */ 1176 int 1177 netpgp_import_key(netpgp_t *netpgp, char *f) 1178 { 1179 pgp_io_t *io; 1180 unsigned realarmor; 1181 int done; 1182 pgp_keyring_t *keyring; 1183 pgp_key_t *key; 1184 const char *ringname; 1185 int rv; 1186 1187 io = netpgp->io; 1188 1189 if (f == NULL) { 1190 (void) fprintf(io->errs, "No input file given\n"); 1191 return 0; 1192 } 1193 1194 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1195 (void) fprintf(io->errs, "netpgp_import_key: bad alloc\n"); 1196 return 0; 1197 } 1198 1199 realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD); 1200 done = pgp_keyring_fileread(keyring, realarmor, f); 1201 if (!done || keyring->keyc == 0) { 1202 (void) fprintf(io->errs, "Cannot import key from file %s\n", f); 1203 pgp_keyring_free(keyring); 1204 return 0; 1205 } 1206 done = pgp_keyring_list(io, keyring, 0); 1207 if (!done) 1208 return 0; 1209 1210 key = keyring->keys; 1211 1212 if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { 1213 ringname = "pubring"; 1214 } else { 1215 ringname = "secring"; 1216 } 1217 1218 if (!done) { 1219 pgp_keyring_free(keyring); 1220 (void) fprintf(io->errs, "Bad append\n"); 1221 return 0; 1222 } 1223 1224 rv = appendtokeyring(netpgp, ringname, key); 1225 pgp_keyring_free(keyring); 1226 1227 return rv; 1228 } 1229 1230 #define ID_OFFSET 38 1231 1232 /* generate a new key */ 1233 int 1234 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 1235 { 1236 pgp_output_t *create; 1237 const unsigned noarmor = 0; 1238 pgp_key_t *key; 1239 pgp_io_t *io; 1240 uint8_t *uid; 1241 char passphrase[128]; 1242 char newid[1024]; 1243 char filename[MAXPATHLEN]; 1244 char dir[MAXPATHLEN]; 1245 char *cp; 1246 char *ringfile; 1247 char *numtries; 1248 int attempts; 1249 int passc; 1250 int fd; 1251 int cc; 1252 int rv = 0; 1253 1254 uid = NULL; 1255 io = netpgp->io; 1256 /* generate a new key */ 1257 if (id) { 1258 (void) snprintf(newid, sizeof(newid), "%s", id); 1259 } else { 1260 (void) snprintf(newid, sizeof(newid), 1261 "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME")); 1262 } 1263 uid = (uint8_t *)newid; 1264 key = pgp_rsa_new_selfsign_key(numbits, 65537UL, uid, 1265 netpgp_getvar(netpgp, "hash"), 1266 netpgp_getvar(netpgp, "cipher")); 1267 if (key == NULL) { 1268 (void) fprintf(io->errs, "Cannot generate key\n"); 1269 return 0; 1270 } 1271 cp = NULL; 1272 pgp_sprint_keydata(netpgp->io, NULL, key, &cp, "signature ", &key->key.seckey.pubkey, 0); 1273 (void) fprintf(stdout, "%s", cp); 1274 /* write public key */ 1275 cc = snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[ID_OFFSET]); 1276 netpgp_setvar(netpgp, "generated userid", &dir[cc - 16]); 1277 if (mkdir(dir, 0700) < 0) { 1278 (void) fprintf(io->errs, "can't mkdir '%s'\n", dir); 1279 goto out; 1280 } 1281 (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir); 1282 (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir); 1283 if (!appendkey(io, key, ringfile)) { 1284 (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile); 1285 goto out; 1286 } 1287 if (netpgp->pubring != NULL) { 1288 pgp_keyring_free(netpgp->pubring); 1289 } 1290 /* write secret key */ 1291 (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir); 1292 if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { 1293 fd = pgp_setup_file_write(&create, ringfile, 0); 1294 } 1295 if (fd < 0) { 1296 (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile); 1297 goto out; 1298 } 1299 /* get the passphrase */ 1300 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1301 (attempts = atoi(numtries)) <= 0) { 1302 attempts = MAX_PASSPHRASE_ATTEMPTS; 1303 } else if (strcmp(numtries, "unlimited") == 0) { 1304 attempts = INFINITE_ATTEMPTS; 1305 } 1306 passc = find_passphrase(netpgp->passfp, &cp[ID_OFFSET], passphrase, sizeof(passphrase), attempts); 1307 if (!pgp_write_xfer_seckey(create, key, (uint8_t *)passphrase, (const unsigned)passc, noarmor)) { 1308 (void) fprintf(io->errs, "Cannot write seckey\n"); 1309 goto out1; 1310 } 1311 rv = 1; 1312 out1: 1313 pgp_teardown_file_write(create, fd); 1314 if (netpgp->secring != NULL) { 1315 pgp_keyring_free(netpgp->secring); 1316 } 1317 out: 1318 pgp_keydata_free(key); 1319 free(cp); 1320 return rv; 1321 } 1322 1323 /* encrypt a file */ 1324 int 1325 netpgp_encrypt_file(netpgp_t *netpgp, 1326 const char *userid, 1327 const char *f, 1328 char *out, 1329 int armored) 1330 { 1331 const pgp_key_t *key; 1332 const unsigned overwrite = 1; 1333 const char *suffix; 1334 pgp_io_t *io; 1335 char outname[MAXPATHLEN]; 1336 1337 io = netpgp->io; 1338 if (f == NULL) { 1339 (void) fprintf(io->errs, 1340 "netpgp_encrypt_file: no filename specified\n"); 1341 return 0; 1342 } 1343 suffix = (armored) ? ".asc" : ".gpg"; 1344 /* get key with which to sign */ 1345 if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1346 return 0; 1347 } 1348 if (out == NULL) { 1349 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 1350 out = outname; 1351 } 1352 return (int)pgp_encrypt_file(io, f, out, key, (unsigned)armored, 1353 overwrite, netpgp_getvar(netpgp, "cipher")); 1354 } 1355 1356 #define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----" 1357 1358 /* decrypt a file */ 1359 int 1360 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 1361 { 1362 const unsigned overwrite = 1; 1363 pgp_io_t *io; 1364 unsigned realarmor; 1365 unsigned sshkeys; 1366 char *numtries; 1367 int attempts; 1368 1369 __PGP_USED(armored); 1370 io = netpgp->io; 1371 if (f == NULL) { 1372 (void) fprintf(io->errs, 1373 "netpgp_decrypt_file: no filename specified\n"); 1374 return 0; 1375 } 1376 realarmor = isarmoured(io, f, NULL, ARMOR_HEAD); 1377 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1378 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1379 (attempts = atoi(numtries)) <= 0) { 1380 attempts = MAX_PASSPHRASE_ATTEMPTS; 1381 } else if (strcmp(numtries, "unlimited") == 0) { 1382 attempts = INFINITE_ATTEMPTS; 1383 } 1384 return pgp_decrypt_file(netpgp->io, f, out, netpgp->secring, 1385 netpgp->pubring, 1386 realarmor, overwrite, sshkeys, 1387 netpgp->passfp, attempts, get_passphrase_cb); 1388 } 1389 1390 /* sign a file */ 1391 int 1392 netpgp_sign_file(netpgp_t *netpgp, 1393 const char *userid, 1394 const char *f, 1395 char *out, 1396 int armored, 1397 int cleartext, 1398 int detached) 1399 { 1400 const pgp_key_t *keypair; 1401 const pgp_key_t *pubkey; 1402 const unsigned overwrite = 1; 1403 pgp_seckey_t *seckey; 1404 const char *hashalg; 1405 pgp_io_t *io; 1406 char *numtries; 1407 int attempts; 1408 int ret; 1409 int i; 1410 1411 io = netpgp->io; 1412 if (f == NULL) { 1413 (void) fprintf(io->errs, 1414 "netpgp_sign_file: no filename specified\n"); 1415 return 0; 1416 } 1417 /* get key with which to sign */ 1418 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1419 return 0; 1420 } 1421 ret = 1; 1422 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1423 (attempts = atoi(numtries)) <= 0) { 1424 attempts = MAX_PASSPHRASE_ATTEMPTS; 1425 } else if (strcmp(numtries, "unlimited") == 0) { 1426 attempts = INFINITE_ATTEMPTS; 1427 } 1428 for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { 1429 if (netpgp->passfp == NULL) { 1430 /* print out the user id */ 1431 pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); 1432 if (pubkey == NULL) { 1433 (void) fprintf(io->errs, 1434 "netpgp: warning - using pubkey from secring\n"); 1435 pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", 1436 &keypair->key.seckey.pubkey, 0); 1437 } else { 1438 pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1439 &pubkey->key.pubkey, 0); 1440 } 1441 } 1442 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1443 /* now decrypt key */ 1444 seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); 1445 if (seckey == NULL) { 1446 (void) fprintf(io->errs, "Bad passphrase\n"); 1447 } 1448 } else { 1449 pgp_keyring_t *secring; 1450 1451 secring = netpgp->secring; 1452 seckey = &secring->keys[0].key.seckey; 1453 } 1454 } 1455 if (seckey == NULL) { 1456 (void) fprintf(io->errs, "Bad passphrase\n"); 1457 return 0; 1458 } 1459 /* sign file */ 1460 hashalg = netpgp_getvar(netpgp, "hash"); 1461 if (seckey->pubkey.alg == PGP_PKA_DSA) { 1462 hashalg = "sha1"; 1463 } 1464 if (detached) { 1465 ret = pgp_sign_detached(io, f, out, seckey, hashalg, 1466 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1467 get_duration(netpgp_getvar(netpgp, "duration")), 1468 (unsigned)armored, 1469 overwrite); 1470 } else { 1471 ret = pgp_sign_file(io, f, out, seckey, hashalg, 1472 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1473 get_duration(netpgp_getvar(netpgp, "duration")), 1474 (unsigned)armored, (unsigned)cleartext, 1475 overwrite); 1476 } 1477 pgp_forget(seckey, sizeof(*seckey)); 1478 return ret; 1479 } 1480 1481 #define ARMOR_SIG_HEAD "-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----" 1482 1483 /* verify a file */ 1484 int 1485 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 1486 { 1487 pgp_validation_t result; 1488 pgp_io_t *io; 1489 unsigned realarmor; 1490 1491 __PGP_USED(armored); 1492 (void) memset(&result, 0x0, sizeof(result)); 1493 io = netpgp->io; 1494 if (in == NULL) { 1495 (void) fprintf(io->errs, 1496 "netpgp_verify_file: no filename specified\n"); 1497 return 0; 1498 } 1499 realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD); 1500 if (pgp_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) { 1501 resultp(io, in, &result, netpgp->pubring); 1502 return 1; 1503 } 1504 if (result.validc + result.invalidc + result.unknownc == 0) { 1505 (void) fprintf(io->errs, 1506 "\"%s\": No signatures found - is this a signed file?\n", 1507 in); 1508 } else if (result.invalidc == 0 && result.unknownc == 0) { 1509 (void) fprintf(io->errs, 1510 "\"%s\": file verification failure: invalid signature time\n", in); 1511 } else { 1512 (void) fprintf(io->errs, 1513 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 1514 in, result.invalidc, result.unknownc); 1515 } 1516 return 0; 1517 } 1518 1519 /* sign some memory */ 1520 int 1521 netpgp_sign_memory(netpgp_t *netpgp, 1522 const char *userid, 1523 char *mem, 1524 size_t size, 1525 char *out, 1526 size_t outsize, 1527 const unsigned armored, 1528 const unsigned cleartext) 1529 { 1530 const pgp_key_t *keypair; 1531 const pgp_key_t *pubkey; 1532 pgp_seckey_t *seckey; 1533 pgp_memory_t *signedmem; 1534 const char *hashalg; 1535 pgp_io_t *io; 1536 char *numtries; 1537 int attempts; 1538 int ret; 1539 int i; 1540 1541 io = netpgp->io; 1542 if (mem == NULL) { 1543 (void) fprintf(io->errs, 1544 "netpgp_sign_memory: no memory to sign\n"); 1545 return 0; 1546 } 1547 if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { 1548 return 0; 1549 } 1550 ret = 1; 1551 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1552 (attempts = atoi(numtries)) <= 0) { 1553 attempts = MAX_PASSPHRASE_ATTEMPTS; 1554 } else if (strcmp(numtries, "unlimited") == 0) { 1555 attempts = INFINITE_ATTEMPTS; 1556 } 1557 for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { 1558 if (netpgp->passfp == NULL) { 1559 /* print out the user id */ 1560 pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); 1561 if (pubkey == NULL) { 1562 (void) fprintf(io->errs, 1563 "netpgp: warning - using pubkey from secring\n"); 1564 pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", 1565 &keypair->key.seckey.pubkey, 0); 1566 } else { 1567 pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", 1568 &pubkey->key.pubkey, 0); 1569 } 1570 } 1571 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 1572 /* now decrypt key */ 1573 seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); 1574 if (seckey == NULL) { 1575 (void) fprintf(io->errs, "Bad passphrase\n"); 1576 } 1577 } else { 1578 pgp_keyring_t *secring; 1579 1580 secring = netpgp->secring; 1581 seckey = &secring->keys[0].key.seckey; 1582 } 1583 } 1584 if (seckey == NULL) { 1585 (void) fprintf(io->errs, "Bad passphrase\n"); 1586 return 0; 1587 } 1588 /* sign file */ 1589 (void) memset(out, 0x0, outsize); 1590 hashalg = netpgp_getvar(netpgp, "hash"); 1591 if (seckey->pubkey.alg == PGP_PKA_DSA) { 1592 hashalg = "sha1"; 1593 } 1594 signedmem = pgp_sign_buf(io, mem, size, seckey, 1595 get_birthtime(netpgp_getvar(netpgp, "birthtime")), 1596 get_duration(netpgp_getvar(netpgp, "duration")), 1597 hashalg, armored, cleartext); 1598 if (signedmem) { 1599 size_t m; 1600 1601 m = MIN(pgp_mem_len(signedmem), outsize); 1602 (void) memcpy(out, pgp_mem_data(signedmem), m); 1603 pgp_memory_free(signedmem); 1604 ret = (int)m; 1605 } else { 1606 ret = 0; 1607 } 1608 pgp_forget(seckey, sizeof(*seckey)); 1609 return ret; 1610 } 1611 1612 /* verify memory */ 1613 int 1614 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, 1615 void *out, size_t outsize, const int armored) 1616 { 1617 pgp_validation_t result; 1618 pgp_memory_t *signedmem; 1619 pgp_memory_t *cat; 1620 pgp_io_t *io; 1621 size_t m; 1622 int ret; 1623 1624 (void) memset(&result, 0x0, sizeof(result)); 1625 io = netpgp->io; 1626 if (in == NULL) { 1627 (void) fprintf(io->errs, 1628 "netpgp_verify_memory: no memory to verify\n"); 1629 return 0; 1630 } 1631 signedmem = pgp_memory_new(); 1632 pgp_memory_add(signedmem, in, size); 1633 if (out) { 1634 cat = pgp_memory_new(); 1635 } 1636 ret = pgp_validate_mem(io, &result, signedmem, 1637 (out) ? &cat : NULL, 1638 armored, netpgp->pubring); 1639 /* signedmem is freed from pgp_validate_mem */ 1640 if (ret) { 1641 resultp(io, "<stdin>", &result, netpgp->pubring); 1642 if (out) { 1643 m = MIN(pgp_mem_len(cat), outsize); 1644 (void) memcpy(out, pgp_mem_data(cat), m); 1645 pgp_memory_free(cat); 1646 } else { 1647 m = 1; 1648 } 1649 return (int)m; 1650 } 1651 if (result.validc + result.invalidc + result.unknownc == 0) { 1652 (void) fprintf(io->errs, 1653 "No signatures found - is this memory signed?\n"); 1654 } else if (result.invalidc == 0 && result.unknownc == 0) { 1655 (void) fprintf(io->errs, 1656 "memory verification failure: invalid signature time\n"); 1657 } else { 1658 (void) fprintf(io->errs, 1659 "memory verification failure: %u invalid signatures, %u unknown signatures\n", 1660 result.invalidc, result.unknownc); 1661 } 1662 return 0; 1663 } 1664 1665 /* encrypt some memory */ 1666 int 1667 netpgp_encrypt_memory(netpgp_t *netpgp, 1668 const char *userid, 1669 void *in, 1670 const size_t insize, 1671 char *out, 1672 size_t outsize, 1673 int armored) 1674 { 1675 const pgp_key_t *keypair; 1676 pgp_memory_t *enc; 1677 pgp_io_t *io; 1678 size_t m; 1679 1680 io = netpgp->io; 1681 if (in == NULL) { 1682 (void) fprintf(io->errs, 1683 "netpgp_encrypt_buf: no memory to encrypt\n"); 1684 return 0; 1685 } 1686 if ((keypair = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { 1687 return 0; 1688 } 1689 if (in == out) { 1690 (void) fprintf(io->errs, 1691 "netpgp_encrypt_buf: input and output bufs need to be different\n"); 1692 return 0; 1693 } 1694 if (outsize < insize) { 1695 (void) fprintf(io->errs, 1696 "netpgp_encrypt_buf: input size is larger than output size\n"); 1697 return 0; 1698 } 1699 enc = pgp_encrypt_buf(io, in, insize, keypair, (unsigned)armored, 1700 netpgp_getvar(netpgp, "cipher")); 1701 m = MIN(pgp_mem_len(enc), outsize); 1702 (void) memcpy(out, pgp_mem_data(enc), m); 1703 pgp_memory_free(enc); 1704 return (int)m; 1705 } 1706 1707 /* decrypt a chunk of memory */ 1708 int 1709 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize, 1710 char *out, size_t outsize, const int armored) 1711 { 1712 pgp_memory_t *mem; 1713 pgp_io_t *io; 1714 unsigned realarmour; 1715 unsigned sshkeys; 1716 size_t m; 1717 char *numtries; 1718 int attempts; 1719 1720 __PGP_USED(armored); 1721 io = netpgp->io; 1722 if (input == NULL) { 1723 (void) fprintf(io->errs, 1724 "netpgp_decrypt_memory: no memory\n"); 1725 return 0; 1726 } 1727 realarmour = isarmoured(io, NULL, input, ARMOR_HEAD); 1728 sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); 1729 if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || 1730 (attempts = atoi(numtries)) <= 0) { 1731 attempts = MAX_PASSPHRASE_ATTEMPTS; 1732 } else if (strcmp(numtries, "unlimited") == 0) { 1733 attempts = INFINITE_ATTEMPTS; 1734 } 1735 mem = pgp_decrypt_buf(netpgp->io, input, insize, netpgp->secring, 1736 netpgp->pubring, 1737 realarmour, sshkeys, 1738 netpgp->passfp, 1739 attempts, 1740 get_passphrase_cb); 1741 if (mem == NULL) { 1742 return -1; 1743 } 1744 m = MIN(pgp_mem_len(mem), outsize); 1745 (void) memcpy(out, pgp_mem_data(mem), m); 1746 pgp_memory_free(mem); 1747 return (int)m; 1748 } 1749 1750 /* wrappers for the ops_debug_level functions we added to openpgpsdk */ 1751 1752 /* set the debugging level per filename */ 1753 int 1754 netpgp_set_debug(const char *f) 1755 { 1756 return pgp_set_debug_level(f); 1757 } 1758 1759 /* get the debugging level per filename */ 1760 int 1761 netpgp_get_debug(const char *f) 1762 { 1763 return pgp_get_debug_level(f); 1764 } 1765 1766 /* return the version for the library */ 1767 const char * 1768 netpgp_get_info(const char *type) 1769 { 1770 return pgp_get_info(type); 1771 } 1772 1773 /* list all the packets in a file */ 1774 int 1775 netpgp_list_packets(netpgp_t *netpgp, char *f, int armor, char *pubringname) 1776 { 1777 pgp_keyring_t *keyring; 1778 const unsigned noarmor = 0; 1779 struct stat st; 1780 pgp_io_t *io; 1781 char ringname[MAXPATHLEN]; 1782 char *homedir; 1783 int ret; 1784 1785 io = netpgp->io; 1786 if (f == NULL) { 1787 (void) fprintf(io->errs, "No file containing packets\n"); 1788 return 0; 1789 } 1790 if (stat(f, &st) < 0) { 1791 (void) fprintf(io->errs, "No such file '%s'\n", f); 1792 return 0; 1793 } 1794 homedir = netpgp_getvar(netpgp, "homedir"); 1795 if (pubringname == NULL) { 1796 (void) snprintf(ringname, sizeof(ringname), 1797 "%s/pubring.gpg", homedir); 1798 pubringname = ringname; 1799 } 1800 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1801 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); 1802 return 0; 1803 } 1804 if (!pgp_keyring_fileread(keyring, noarmor, pubringname)) { 1805 free(keyring); 1806 (void) fprintf(io->errs, "Cannot read pub keyring %s\n", 1807 pubringname); 1808 return 0; 1809 } 1810 netpgp->pubring = keyring; 1811 netpgp_setvar(netpgp, "pubring", pubringname); 1812 ret = pgp_list_packets(io, f, (unsigned)armor, 1813 netpgp->secring, 1814 netpgp->pubring, 1815 netpgp->passfp, 1816 get_passphrase_cb); 1817 free(keyring); 1818 return ret; 1819 } 1820 1821 /* set a variable */ 1822 int 1823 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) 1824 { 1825 char *newval; 1826 int i; 1827 1828 /* protect against the case where 'value' is netpgp->value[i] */ 1829 newval = netpgp_strdup(value); 1830 if ((i = findvar(netpgp, name)) < 0) { 1831 /* add the element to the array */ 1832 if (size_arrays(netpgp, netpgp->size + 15)) { 1833 netpgp->name[i = netpgp->c++] = netpgp_strdup(name); 1834 } 1835 } else { 1836 /* replace the element in the array */ 1837 if (netpgp->value[i]) { 1838 free(netpgp->value[i]); 1839 netpgp->value[i] = NULL; 1840 } 1841 } 1842 /* sanity checks for range of values */ 1843 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { 1844 if (pgp_str_to_hash_alg(newval) == PGP_HASH_UNKNOWN) { 1845 free(newval); 1846 return 0; 1847 } 1848 } 1849 netpgp->value[i] = newval; 1850 return 1; 1851 } 1852 1853 /* unset a variable */ 1854 int 1855 netpgp_unsetvar(netpgp_t *netpgp, const char *name) 1856 { 1857 int i; 1858 1859 if ((i = findvar(netpgp, name)) >= 0) { 1860 if (netpgp->value[i]) { 1861 free(netpgp->value[i]); 1862 netpgp->value[i] = NULL; 1863 } 1864 netpgp->value[i] = NULL; 1865 return 1; 1866 } 1867 return 0; 1868 } 1869 1870 /* get a variable's value (NULL if not set) */ 1871 char * 1872 netpgp_getvar(netpgp_t *netpgp, const char *name) 1873 { 1874 int i; 1875 1876 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; 1877 } 1878 1879 /* increment a value */ 1880 int 1881 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) 1882 { 1883 char *cp; 1884 char num[16]; 1885 int val; 1886 1887 val = 0; 1888 if ((cp = netpgp_getvar(netpgp, name)) != NULL) { 1889 val = atoi(cp); 1890 } 1891 (void) snprintf(num, sizeof(num), "%d", val + delta); 1892 netpgp_setvar(netpgp, name, num); 1893 return 1; 1894 } 1895 1896 /* set the home directory value to "home/subdir" */ 1897 int 1898 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) 1899 { 1900 struct stat st; 1901 char d[MAXPATHLEN]; 1902 1903 if (home == NULL) { 1904 if (!quiet) { 1905 (void) fprintf(stderr, "NULL HOME directory\n"); 1906 } 1907 return 0; 1908 } 1909 (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); 1910 if (stat(d, &st) == 0) { 1911 if ((st.st_mode & S_IFMT) == S_IFDIR) { 1912 netpgp_setvar(netpgp, "homedir", d); 1913 return 1; 1914 } 1915 (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", 1916 d); 1917 return 0; 1918 } 1919 if (!quiet) { 1920 (void) fprintf(stderr, 1921 "netpgp: warning homedir \"%s\" not found\n", d); 1922 } 1923 netpgp_setvar(netpgp, "homedir", d); 1924 return 1; 1925 } 1926 1927 /* validate all sigs in the pub keyring */ 1928 int 1929 netpgp_validate_sigs(netpgp_t *netpgp) 1930 { 1931 pgp_validation_t result; 1932 1933 return (int)pgp_validate_all_sigs(&result, netpgp->pubring, NULL); 1934 } 1935 1936 /* print the json out on 'fp' */ 1937 int 1938 netpgp_format_json(void *vp, const char *json, const int psigs) 1939 { 1940 mj_t ids; 1941 FILE *fp; 1942 int from; 1943 int idc; 1944 int tok; 1945 int to; 1946 int i; 1947 1948 if ((fp = (FILE *)vp) == NULL || json == NULL) { 1949 return 0; 1950 } 1951 /* ids is an array of strings, each containing 1 entry */ 1952 (void) memset(&ids, 0x0, sizeof(ids)); 1953 from = to = tok = 0; 1954 /* convert from string into an mj structure */ 1955 (void) mj_parse(&ids, json, &from, &to, &tok); 1956 if ((idc = mj_arraycount(&ids)) == 1 && strchr(json, '{') == NULL) { 1957 idc = 0; 1958 } 1959 (void) fprintf(fp, "%d key%s found\n", idc, (idc == 1) ? "" : "s"); 1960 for (i = 0 ; i < idc ; i++) { 1961 format_json_key(fp, &ids.value.v[i], psigs); 1962 } 1963 /* clean up */ 1964 mj_delete(&ids); 1965 return idc; 1966 } 1967 1968 /* find a key in keyring, and write it in ssh format */ 1969 int 1970 netpgp_write_sshkey(netpgp_t *netpgp, char *s, const char *userid, char *out, size_t size) 1971 { 1972 const pgp_key_t *key; 1973 pgp_keyring_t *keyring; 1974 pgp_io_t *io; 1975 unsigned k; 1976 size_t cc; 1977 char f[MAXPATHLEN]; 1978 1979 keyring = NULL; 1980 io = NULL; 1981 cc = 0; 1982 if ((io = calloc(1, sizeof(pgp_io_t))) == NULL) { 1983 (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 1\n"); 1984 goto done; 1985 } 1986 io->outs = stdout; 1987 io->errs = stderr; 1988 io->res = stderr; 1989 netpgp->io = io; 1990 /* write new to temp file */ 1991 savepubkey(s, f, sizeof(f)); 1992 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 1993 (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 2\n"); 1994 goto done; 1995 } 1996 if (!pgp_keyring_fileread(netpgp->pubring = keyring, 1, f)) { 1997 (void) fprintf(stderr, "can't import key\n"); 1998 goto done; 1999 } 2000 /* get rsa key */ 2001 k = 0; 2002 key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, userid, &k); 2003 if (key == NULL) { 2004 (void) fprintf(stderr, "no key found for '%s'\n", userid); 2005 goto done; 2006 } 2007 if (key->key.pubkey.alg != PGP_PKA_RSA) { 2008 /* we're not interested in supporting DSA either :-) */ 2009 (void) fprintf(stderr, "key not RSA '%s'\n", userid); 2010 goto done; 2011 } 2012 /* XXX - check trust sigs */ 2013 /* XXX - check expiry */ 2014 /* XXX - check start */ 2015 /* XXX - check not weak key */ 2016 /* get rsa e and n */ 2017 (void) memset(out, 0x0, size); 2018 cc = formatstring((char *)out, (const uint8_t *)"ssh-rsa", 7); 2019 cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.e); 2020 cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.n); 2021 done: 2022 if (io) { 2023 free(io); 2024 } 2025 if (keyring) { 2026 free(keyring); 2027 } 2028 return (int)cc; 2029 } 2030