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.31 2009/12/05 07:08:19 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 86 /* read any gpg config file */ 87 static int 88 conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length) 89 { 90 regmatch_t matchv[10]; 91 regex_t keyre; 92 char buf[BUFSIZ]; 93 FILE *fp; 94 95 __OPS_USED(netpgp); 96 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); 97 if ((fp = fopen(buf, "r")) == NULL) { 98 return 0; 99 } 100 (void) memset(&keyre, 0x0, sizeof(keyre)); 101 (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", 102 REG_EXTENDED); 103 while (fgets(buf, sizeof(buf), fp) != NULL) { 104 if (regexec(&keyre, buf, 10, matchv, 0) == 0) { 105 (void) memcpy(userid, &buf[(int)matchv[1].rm_so], 106 MIN((unsigned)(matchv[1].rm_eo - 107 matchv[1].rm_so), length)); 108 (void) fprintf(stderr, 109 "netpgp: default key set to \"%.*s\"\n", 110 (int)(matchv[1].rm_eo - matchv[1].rm_so), 111 &buf[(int)matchv[1].rm_so]); 112 } 113 } 114 (void) fclose(fp); 115 return 1; 116 } 117 118 /* small function to pretty print an 8-character raw userid */ 119 static char * 120 userid_to_id(const unsigned char *userid, char *id) 121 { 122 static const char *hexes = "0123456789abcdef"; 123 int i; 124 125 for (i = 0; i < 8 ; i++) { 126 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; 127 id[(i * 2) + 1] = hexes[userid[i] & 0xf]; 128 } 129 id[8 * 2] = 0x0; 130 return id; 131 } 132 133 /* print out the successful signature information */ 134 static void 135 resultp(__ops_io_t *io, 136 const char *f, 137 __ops_validation_t *res, 138 __ops_keyring_t *ring) 139 { 140 const __ops_key_t *pubkey; 141 unsigned i; 142 char id[MAX_ID_LENGTH + 1]; 143 144 for (i = 0; i < res->validc; i++) { 145 (void) fprintf(io->res, 146 "Good signature for %s made %susing %s key %s\n", 147 f, 148 ctime(&res->valid_sigs[i].birthtime), 149 __ops_show_pka(res->valid_sigs[i].key_alg), 150 userid_to_id(res->valid_sigs[i].signer_id, id)); 151 pubkey = __ops_getkeybyid(io, ring, 152 (const unsigned char *) res->valid_sigs[i].signer_id); 153 __ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey); 154 } 155 } 156 157 /* check there's enough space in the arrays */ 158 static int 159 size_arrays(netpgp_t *netpgp, unsigned needed) 160 { 161 char **temp; 162 163 if (netpgp->size == 0) { 164 /* only get here first time around */ 165 netpgp->size = needed; 166 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { 167 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 168 return 0; 169 } 170 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { 171 free(netpgp->name); 172 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 173 return 0; 174 } 175 } else if (netpgp->c == netpgp->size) { 176 /* only uses 'needed' when filled array */ 177 netpgp->size += needed; 178 temp = realloc(netpgp->name, sizeof(char *) * needed); 179 if (temp == NULL) { 180 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 181 return 0; 182 } 183 netpgp->name = temp; 184 temp = realloc(netpgp->value, sizeof(char *) * needed); 185 if (temp == NULL) { 186 (void) fprintf(stderr, "size_arrays: bad alloc\n"); 187 return 0; 188 } 189 netpgp->value = temp; 190 } 191 return 1; 192 } 193 194 /* find the name in the array */ 195 static int 196 findvar(netpgp_t *netpgp, const char *name) 197 { 198 unsigned i; 199 200 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { 201 } 202 return (i == netpgp->c) ? -1 : (int)i; 203 } 204 205 /* read a keyring and return it */ 206 static void * 207 readkeyring(netpgp_t *netpgp, const char *name) 208 { 209 __ops_keyring_t *keyring; 210 const unsigned noarmor = 0; 211 char f[MAXPATHLEN]; 212 char *filename; 213 char *homedir; 214 215 homedir = netpgp_getvar(netpgp, "homedir"); 216 if ((filename = netpgp_getvar(netpgp, name)) == NULL) { 217 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); 218 filename = f; 219 } 220 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 221 (void) fprintf(stderr, "readkeyring: bad alloc\n"); 222 return NULL; 223 } 224 if (!__ops_keyring_fileread(keyring, noarmor, filename)) { 225 free(keyring); 226 (void) fprintf(stderr, "Can't read %s %s\n", name, filename); 227 return NULL; 228 } 229 netpgp_setvar(netpgp, name, filename); 230 return keyring; 231 } 232 233 /* read keys from ssh host key files */ 234 static int 235 readsshkeys(netpgp_t *netpgp, const char *pubname, const char *secname) 236 { 237 __ops_keyring_t *pubring; 238 __ops_keyring_t *secring; 239 char f[MAXPATHLEN]; 240 char *filename; 241 char *etcdir; 242 243 __OPS_USED(secname); 244 etcdir = netpgp_getvar(netpgp, "sshetcdir"); 245 if ((filename = netpgp_getvar(netpgp, pubname)) == NULL) { 246 (void) snprintf(f, sizeof(f), "%s/ssh_host_rsa_key.pub", etcdir); 247 filename = f; 248 } 249 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { 250 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 251 return 0; 252 } 253 if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL)) { 254 free(pubring); 255 (void) fprintf(stderr, "readsshkeys: can't read %s\n", filename); 256 return 0; 257 } 258 netpgp->pubring = pubring; 259 netpgp_setvar(netpgp, pubname, filename); 260 if ((filename = netpgp_getvar(netpgp, secname)) == NULL) { 261 (void) snprintf(f, sizeof(f), "%s/ssh_host_rsa_key", etcdir); 262 filename = f; 263 } 264 if ((secring = calloc(1, sizeof(*secring))) == NULL) { 265 (void) fprintf(stderr, "readsshkeys: bad alloc\n"); 266 return 0; 267 } 268 if (__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename)) { 269 netpgp->secring = secring; 270 netpgp_setvar(netpgp, secname, filename); 271 } else { 272 (void) fprintf(stderr, "readsshkeys: can't read sec %s (%d)\n", filename, errno); 273 } 274 return 1; 275 } 276 277 /***************************************************************************/ 278 /* exported functions start here */ 279 /***************************************************************************/ 280 281 /* initialise a netpgp_t structure */ 282 int 283 netpgp_init(netpgp_t *netpgp) 284 { 285 __ops_io_t *io; 286 char id[MAX_ID_LENGTH]; 287 char *homedir; 288 char *userid; 289 char *stream; 290 char *passfd; 291 char *results; 292 int coredumps; 293 294 #ifdef HAVE_SYS_RESOURCE_H 295 struct rlimit limit; 296 297 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; 298 if (!coredumps) { 299 (void) memset(&limit, 0x0, sizeof(limit)); 300 if (setrlimit(RLIMIT_CORE, &limit) != 0) { 301 (void) fprintf(stderr, 302 "netpgp_init: warning - can't turn off core dumps\n"); 303 coredumps = 1; 304 } 305 } 306 #else 307 coredumps = 1; 308 #endif 309 if ((io = calloc(1, sizeof(*io))) == NULL) { 310 (void) fprintf(stderr, "netpgp_init: bad alloc\n"); 311 return 0; 312 } 313 io->outs = stdout; 314 if ((stream = netpgp_getvar(netpgp, "stdout")) != NULL && 315 strcmp(stream, "stderr") == 0) { 316 io->outs = stderr; 317 } 318 io->errs = stderr; 319 if ((stream = netpgp_getvar(netpgp, "stderr")) != NULL && 320 strcmp(stream, "stdout") == 0) { 321 io->errs = stdout; 322 } 323 if ((results = netpgp_getvar(netpgp, "results")) == NULL) { 324 io->res = io->errs; 325 } else if ((io->res = fopen(results, "w")) == NULL) { 326 (void) fprintf(io->errs, "Can't open results %s for writing\n", 327 results); 328 return 0; 329 } 330 netpgp->io = io; 331 if (coredumps) { 332 (void) fprintf(io->errs, 333 "netpgp: warning: core dumps enabled\n"); 334 } 335 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { 336 (void) fprintf(io->errs, "netpgp: bad homedir\n"); 337 return 0; 338 } 339 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { 340 (void) memset(id, 0x0, sizeof(id)); 341 (void) conffile(netpgp, homedir, id, sizeof(id)); 342 if (id[0] != 0x0) { 343 netpgp_setvar(netpgp, "userid", userid = id); 344 } 345 } 346 if (userid == NULL) { 347 if (netpgp_getvar(netpgp, "need userid") != NULL) { 348 (void) fprintf(io->errs, "Cannot find user id\n"); 349 return 0; 350 } 351 } else { 352 (void) netpgp_setvar(netpgp, "userid", userid); 353 } 354 /* read from either gpg files or ssh host keys */ 355 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 356 if ((netpgp->pubring = readkeyring(netpgp, "pubring")) == NULL) { 357 (void) fprintf(io->errs, "Can't read pub keyring\n"); 358 return 0; 359 } 360 if ((netpgp->secring = readkeyring(netpgp, "secring")) == NULL) { 361 (void) fprintf(io->errs, "Can't read sec keyring\n"); 362 return 0; 363 } 364 } else { 365 if (!readsshkeys(netpgp, "ssh pub key", "ssh sec file")) { 366 (void) fprintf(io->errs, "Can't read ssh host pub key\n"); 367 return 0; 368 } 369 } 370 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && 371 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { 372 (void) fprintf(io->errs, "Can't open fd %s for reading\n", 373 passfd); 374 return 0; 375 } 376 return 1; 377 } 378 379 /* finish off with the netpgp_t struct */ 380 int 381 netpgp_end(netpgp_t *netpgp) 382 { 383 unsigned i; 384 385 for (i = 0 ; i < netpgp->c ; i++) { 386 if (netpgp->name[i] != NULL) { 387 free(netpgp->name[i]); 388 } 389 if (netpgp->value[i] != NULL) { 390 free(netpgp->value[i]); 391 } 392 } 393 if (netpgp->name != NULL) { 394 free(netpgp->name); 395 } 396 if (netpgp->value != NULL) { 397 free(netpgp->value); 398 } 399 if (netpgp->pubring != NULL) { 400 __ops_keyring_free(netpgp->pubring); 401 } 402 if (netpgp->secring != NULL) { 403 __ops_keyring_free(netpgp->secring); 404 } 405 free(netpgp->io); 406 return 1; 407 } 408 409 /* list the keys in a keyring */ 410 int 411 netpgp_list_keys(netpgp_t *netpgp) 412 { 413 return __ops_keyring_list(netpgp->io, netpgp->pubring); 414 } 415 416 /* find a key in a keyring */ 417 int 418 netpgp_find_key(netpgp_t *netpgp, char *id) 419 { 420 __ops_io_t *io; 421 422 io = netpgp->io; 423 if (id == NULL) { 424 (void) fprintf(io->errs, "NULL id to search for\n"); 425 return 0; 426 } 427 return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; 428 } 429 430 /* get a key in a keyring */ 431 char * 432 netpgp_get_key(netpgp_t *netpgp, const char *id) 433 { 434 const __ops_key_t *key; 435 __ops_io_t *io; 436 char *newkey; 437 438 io = netpgp->io; 439 if (id == NULL) { 440 (void) fprintf(io->errs, "NULL id to search for\n"); 441 return NULL; 442 } 443 if ((key = __ops_getkeybyname(netpgp->io, netpgp->pubring, id)) == NULL) { 444 (void) fprintf(io->errs, "Can't find key '%s'\n", id); 445 return NULL; 446 } 447 return (__ops_sprint_keydata(key, &newkey, "pub", &key->key.pubkey) > 0) ? newkey : NULL; 448 } 449 450 /* export a given key */ 451 int 452 netpgp_export_key(netpgp_t *netpgp, char *userid) 453 { 454 const __ops_key_t *keypair; 455 __ops_io_t *io; 456 457 io = netpgp->io; 458 if (userid == NULL) { 459 userid = netpgp_getvar(netpgp, "userid"); 460 } 461 keypair = __ops_getkeybyname(io, netpgp->pubring, userid); 462 if (keypair == NULL) { 463 (void) fprintf(io->errs, 464 "Cannot find own key \"%s\" in keyring\n", userid); 465 return 0; 466 } 467 return __ops_export_key(keypair, NULL); 468 } 469 470 /* import a key into our keyring */ 471 int 472 netpgp_import_key(netpgp_t *netpgp, char *f) 473 { 474 const unsigned noarmor = 0; 475 const unsigned armor = 1; 476 __ops_io_t *io; 477 int done; 478 479 io = netpgp->io; 480 if ((done = __ops_keyring_fileread(netpgp->pubring, noarmor, f)) == 0) { 481 done = __ops_keyring_fileread(netpgp->pubring, armor, f); 482 } 483 if (!done) { 484 (void) fprintf(io->errs, "Cannot import key from file %s\n", 485 f); 486 return 0; 487 } 488 return __ops_keyring_list(io, netpgp->pubring); 489 } 490 491 /* generate a new key */ 492 int 493 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) 494 { 495 __ops_key_t *keypair; 496 __ops_userid_t uid; 497 __ops_output_t *create; 498 const unsigned noarmor = 0; 499 __ops_io_t *io; 500 char *ringfile; 501 int fd; 502 503 (void) memset(&uid, 0x0, sizeof(uid)); 504 io = netpgp->io; 505 /* generate a new key for 'id' */ 506 uid.userid = (unsigned char *) id; 507 keypair = __ops_rsa_new_selfsign_key(numbits, 65537UL, &uid); 508 if (keypair == NULL) { 509 (void) fprintf(io->errs, "Cannot generate key\n"); 510 return 0; 511 } 512 /* write public key, and try to re-read it */ 513 ringfile = netpgp_getvar(netpgp, "pubring"); 514 fd = __ops_setup_file_append(&create, ringfile); 515 if (!__ops_write_xfer_pubkey(create, keypair, noarmor)) { 516 (void) fprintf(io->errs, "Cannot write pubkey\n"); 517 return 0; 518 } 519 __ops_teardown_file_write(create, fd); 520 __ops_keyring_free(netpgp->pubring); 521 if (!__ops_keyring_fileread(netpgp->pubring, noarmor, ringfile)) { 522 (void) fprintf(io->errs, "Cannot read pubring %s\n", ringfile); 523 return 0; 524 } 525 /* write secret key, and try to re-read it */ 526 ringfile = netpgp_getvar(netpgp, "sec ring file"); 527 fd = __ops_setup_file_append(&create, ringfile); 528 if (!__ops_write_xfer_seckey(create, keypair, NULL, 0, noarmor)) { 529 (void) fprintf(io->errs, "Cannot write seckey\n"); 530 return 0; 531 } 532 __ops_teardown_file_write(create, fd); 533 __ops_keyring_free(netpgp->secring); 534 if (!__ops_keyring_fileread(netpgp->secring, noarmor, ringfile)) { 535 (void) fprintf(io->errs, "Can't read secring %s\n", ringfile); 536 return 0; 537 } 538 __ops_keydata_free(keypair); 539 return 1; 540 } 541 542 /* encrypt a file */ 543 int 544 netpgp_encrypt_file(netpgp_t *netpgp, 545 const char *userid, 546 const char *f, 547 char *out, 548 int armored) 549 { 550 const __ops_key_t *keypair; 551 const unsigned overwrite = 1; 552 const char *suffix; 553 __ops_io_t *io; 554 char outname[MAXPATHLEN]; 555 556 io = netpgp->io; 557 if (f == NULL) { 558 (void) fprintf(io->errs, 559 "netpgp_encrypt_file: no filename specified\n"); 560 return 0; 561 } 562 if (userid == NULL) { 563 userid = netpgp_getvar(netpgp, "userid"); 564 } 565 suffix = (armored) ? ".asc" : ".gpg"; 566 keypair = __ops_getkeybyname(io, netpgp->pubring, userid); 567 if (keypair == NULL) { 568 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 569 userid); 570 return 0; 571 } 572 if (out == NULL) { 573 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); 574 out = outname; 575 } 576 return (int)__ops_encrypt_file(io, f, out, keypair, (unsigned)armored, 577 overwrite); 578 } 579 580 /* decrypt a file */ 581 int 582 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) 583 { 584 const unsigned overwrite = 1; 585 __ops_io_t *io; 586 587 io = netpgp->io; 588 if (f == NULL) { 589 (void) fprintf(io->errs, 590 "netpgp_decrypt_file: no filename specified\n"); 591 return 0; 592 } 593 return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring, 594 (unsigned)armored, overwrite, netpgp->passfp, 595 get_passphrase_cb); 596 } 597 598 /* sign a file */ 599 int 600 netpgp_sign_file(netpgp_t *netpgp, 601 const char *userid, 602 const char *f, 603 char *out, 604 int armored, 605 int cleartext, 606 int detached) 607 { 608 const __ops_key_t *keypair; 609 __ops_seckey_t *seckey; 610 const unsigned overwrite = 1; 611 __ops_io_t *io; 612 char *hashalg; 613 int ret; 614 615 io = netpgp->io; 616 if (f == NULL) { 617 (void) fprintf(io->errs, 618 "netpgp_sign_file: no filename specified\n"); 619 return 0; 620 } 621 if (userid == NULL) { 622 userid = netpgp_getvar(netpgp, "userid"); 623 } 624 /* get key with which to sign */ 625 keypair = __ops_getkeybyname(io, netpgp->secring, userid); 626 if (keypair == NULL) { 627 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 628 userid); 629 return 0; 630 } 631 ret = 1; 632 do { 633 /* print out the user id */ 634 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey); 635 if (netpgp_getvar(netpgp, "ssh keys") == NULL) { 636 /* now decrypt key */ 637 seckey = __ops_decrypt_seckey(keypair); 638 if (seckey == NULL) { 639 (void) fprintf(io->errs, "Bad passphrase\n"); 640 } 641 } else { 642 __ops_keyring_t *secring; 643 644 secring = netpgp->secring; 645 seckey = &secring->keys[0].key.seckey; 646 } 647 } while (seckey == NULL); 648 /* sign file */ 649 hashalg = netpgp_getvar(netpgp, "hash"); 650 if (detached) { 651 ret = __ops_sign_detached(io, f, out, seckey, hashalg); 652 } else { 653 ret = __ops_sign_file(io, f, out, seckey, hashalg, 654 (unsigned)armored, (unsigned)cleartext, overwrite); 655 } 656 __ops_forget(seckey, sizeof(*seckey)); 657 return ret; 658 } 659 660 /* verify a file */ 661 int 662 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) 663 { 664 __ops_validation_t result; 665 __ops_io_t *io; 666 667 (void) memset(&result, 0x0, sizeof(result)); 668 io = netpgp->io; 669 if (in == NULL) { 670 (void) fprintf(io->errs, 671 "netpgp_verify_file: no filename specified\n"); 672 return 0; 673 } 674 if (__ops_validate_file(io, &result, in, out, armored, 675 netpgp->pubring)) { 676 resultp(io, in, &result, netpgp->pubring); 677 return 1; 678 } 679 if (result.validc + result.invalidc + result.unknownc == 0) { 680 (void) fprintf(io->errs, 681 "\"%s\": No signatures found - is this a signed file?\n", 682 in); 683 } else { 684 (void) fprintf(io->errs, 685 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", 686 in, result.invalidc, result.unknownc); 687 } 688 return 0; 689 } 690 691 /* sign some memory */ 692 int 693 netpgp_sign_memory(netpgp_t *netpgp, 694 const char *userid, 695 char *mem, 696 size_t size, 697 char *out, 698 size_t outsize, 699 const unsigned armored, 700 const unsigned cleartext) 701 { 702 const __ops_key_t *keypair; 703 __ops_seckey_t *seckey; 704 __ops_memory_t *signedmem; 705 __ops_io_t *io; 706 char *hashalg; 707 int ret; 708 709 io = netpgp->io; 710 if (mem == NULL) { 711 (void) fprintf(io->errs, 712 "netpgp_sign_memory: no memory to sign\n"); 713 return 0; 714 } 715 if (userid == NULL) { 716 userid = netpgp_getvar(netpgp, "userid"); 717 } 718 /* get key with which to sign */ 719 keypair = __ops_getkeybyname(io, netpgp->secring, userid); 720 if (keypair == NULL) { 721 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n", 722 userid); 723 return 0; 724 } 725 ret = 1; 726 do { 727 /* print out the user id */ 728 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey); 729 /* now decrypt key */ 730 seckey = __ops_decrypt_seckey(keypair); 731 if (seckey == NULL) { 732 (void) fprintf(io->errs, "Bad passphrase\n"); 733 } 734 } while (seckey == NULL); 735 /* sign file */ 736 hashalg = netpgp_getvar(netpgp, "hash"); 737 signedmem = __ops_sign_buf(io, mem, size, seckey, hashalg, 738 armored, cleartext); 739 if (signedmem) { 740 size_t m; 741 742 m = MIN(__ops_mem_len(signedmem), outsize); 743 (void) memcpy(out, __ops_mem_data(signedmem), m); 744 __ops_memory_free(signedmem); 745 } 746 __ops_forget(seckey, sizeof(*seckey)); 747 return ret; 748 } 749 750 /* verify memory */ 751 int 752 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, const int armored) 753 { 754 __ops_validation_t result; 755 __ops_memory_t *signedmem; 756 __ops_io_t *io; 757 int ret; 758 759 (void) memset(&result, 0x0, sizeof(result)); 760 io = netpgp->io; 761 if (in == NULL) { 762 (void) fprintf(io->errs, 763 "netpgp_verify_memory: no memory to verify\n"); 764 return 0; 765 } 766 signedmem = __ops_memory_new(); 767 __ops_memory_add(signedmem, in, size); 768 ret = __ops_validate_mem(io, &result, signedmem, armored, 769 netpgp->pubring); 770 __ops_memory_free(signedmem); 771 if (ret) { 772 resultp(io, in, &result, netpgp->pubring); 773 return 1; 774 } 775 if (result.validc + result.invalidc + result.unknownc == 0) { 776 (void) fprintf(io->errs, 777 "No signatures found - is this memory signed?\n"); 778 } else { 779 (void) fprintf(io->errs, 780 "memory verification failure: %u invalid signatures, %u unknown signatures\n", 781 result.invalidc, result.unknownc); 782 } 783 return 0; 784 } 785 786 /* wrappers for the ops_debug_level functions we added to openpgpsdk */ 787 788 /* set the debugging level per filename */ 789 int 790 netpgp_set_debug(const char *f) 791 { 792 return __ops_set_debug_level(f); 793 } 794 795 /* get the debugging level per filename */ 796 int 797 netpgp_get_debug(const char *f) 798 { 799 return __ops_get_debug_level(f); 800 } 801 802 /* return the version for the library */ 803 const char * 804 netpgp_get_info(const char *type) 805 { 806 return __ops_get_info(type); 807 } 808 809 /* list all the packets in a file */ 810 int 811 netpgp_list_packets(netpgp_t *netpgp, char *f, int armour, char *pubringname) 812 { 813 __ops_keyring_t *keyring; 814 const unsigned noarmor = 0; 815 __ops_io_t *io; 816 char ringname[MAXPATHLEN]; 817 char *homedir; 818 int ret; 819 820 io = netpgp->io; 821 if (f == NULL) { 822 (void) fprintf(io->errs, "No file containing packets\n"); 823 return 0; 824 } 825 homedir = netpgp_getvar(netpgp, "homedir"); 826 if (pubringname == NULL) { 827 (void) snprintf(ringname, sizeof(ringname), 828 "%s/pubring.gpg", homedir); 829 pubringname = ringname; 830 } 831 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { 832 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); 833 return 0; 834 } 835 if (!__ops_keyring_fileread(keyring, noarmor, pubringname)) { 836 free(keyring); 837 (void) fprintf(io->errs, "Cannot read pub keyring %s\n", 838 pubringname); 839 return 0; 840 } 841 netpgp->pubring = keyring; 842 netpgp_setvar(netpgp, "pubring", pubringname); 843 ret = __ops_list_packets(io, f, (unsigned)armour, keyring, 844 netpgp->passfp, 845 get_passphrase_cb); 846 free(keyring); 847 return ret; 848 } 849 850 /* set a variable */ 851 int 852 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) 853 { 854 int i; 855 856 if ((i = findvar(netpgp, name)) < 0) { 857 /* add the element to the array */ 858 if (size_arrays(netpgp, netpgp->size + 15)) { 859 netpgp->name[i = netpgp->c++] = strdup(name); 860 } 861 } else { 862 /* replace the element in the array */ 863 if (netpgp->value[i]) { 864 free(netpgp->value[i]); 865 netpgp->value[i] = NULL; 866 } 867 } 868 /* sanity checks for range of values */ 869 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { 870 if (__ops_str_to_hash_alg(value) == OPS_HASH_UNKNOWN) { 871 return 0; 872 } 873 } 874 netpgp->value[i] = strdup(value); 875 return 1; 876 } 877 878 /* get a variable's value (NULL if not set) */ 879 char * 880 netpgp_getvar(netpgp_t *netpgp, const char *name) 881 { 882 int i; 883 884 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; 885 } 886