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