Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / crypto / external / bsd / netpgp / dist / src / lib / netpgp.c
blobb23d61dc7454a2ccf354b8324c3afccd075cf8b9
1 /*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
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.
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.
29 #include "config.h"
31 #ifdef HAVE_SYS_CDEFS_H
32 #include <sys/cdefs.h>
33 #endif
35 #if defined(__NetBSD__)
36 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
37 __RCSID("$NetBSD: netpgp.c,v 1.35 2009/12/22 06:53:26 agc Exp $");
38 #endif
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/param.h>
43 #include <sys/mman.h>
45 #ifdef HAVE_SYS_RESOURCE_H
46 #include <sys/resource.h>
47 #endif
49 #ifdef HAVE_FCNTL_H
50 #include <fcntl.h>
51 #endif
53 #include <errno.h>
54 #include <regex.h>
55 #include <stdarg.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <time.h>
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
64 #include <errno.h>
66 #ifdef HAVE_LIMITS_H
67 #include <limits.h>
68 #endif
70 #include <netpgp.h>
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"
86 /* read any gpg config file */
87 static int
88 conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length)
90 regmatch_t matchv[10];
91 regex_t keyre;
92 char buf[BUFSIZ];
93 FILE *fp;
95 __OPS_USED(netpgp);
96 (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir);
97 if ((fp = fopen(buf, "r")) == NULL) {
98 return 0;
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]);
114 (void) fclose(fp);
115 return 1;
118 /* small function to pretty print an 8-character raw userid */
119 static char *
120 userid_to_id(const unsigned char *userid, char *id)
122 static const char *hexes = "0123456789abcdef";
123 int i;
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];
129 id[8 * 2] = 0x0;
130 return id;
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)
140 const __ops_key_t *pubkey;
141 unsigned from;
142 unsigned i;
143 char id[MAX_ID_LENGTH + 1];
145 for (i = 0; i < res->validc; i++) {
146 (void) fprintf(io->res,
147 "Good signature for %s made %susing %s key %s\n",
148 (f) ? f : "<stdin>",
149 ctime(&res->valid_sigs[i].birthtime),
150 __ops_show_pka(res->valid_sigs[i].key_alg),
151 userid_to_id(res->valid_sigs[i].signer_id, id));
152 from = 0;
153 pubkey = __ops_getkeybyid(io, ring,
154 (const unsigned char *) res->valid_sigs[i].signer_id,
155 &from);
156 __ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey);
160 /* check there's enough space in the arrays */
161 static int
162 size_arrays(netpgp_t *netpgp, unsigned needed)
164 char **temp;
166 if (netpgp->size == 0) {
167 /* only get here first time around */
168 netpgp->size = needed;
169 if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) {
170 (void) fprintf(stderr, "size_arrays: bad alloc\n");
171 return 0;
173 if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) {
174 free(netpgp->name);
175 (void) fprintf(stderr, "size_arrays: bad alloc\n");
176 return 0;
178 } else if (netpgp->c == netpgp->size) {
179 /* only uses 'needed' when filled array */
180 netpgp->size += needed;
181 temp = realloc(netpgp->name, sizeof(char *) * needed);
182 if (temp == NULL) {
183 (void) fprintf(stderr, "size_arrays: bad alloc\n");
184 return 0;
186 netpgp->name = temp;
187 temp = realloc(netpgp->value, sizeof(char *) * needed);
188 if (temp == NULL) {
189 (void) fprintf(stderr, "size_arrays: bad alloc\n");
190 return 0;
192 netpgp->value = temp;
194 return 1;
197 /* find the name in the array */
198 static int
199 findvar(netpgp_t *netpgp, const char *name)
201 unsigned i;
203 for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) {
205 return (i == netpgp->c) ? -1 : (int)i;
208 /* read a keyring and return it */
209 static void *
210 readkeyring(netpgp_t *netpgp, const char *name)
212 __ops_keyring_t *keyring;
213 const unsigned noarmor = 0;
214 char f[MAXPATHLEN];
215 char *filename;
216 char *homedir;
218 homedir = netpgp_getvar(netpgp, "homedir");
219 if ((filename = netpgp_getvar(netpgp, name)) == NULL) {
220 (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name);
221 filename = f;
223 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) {
224 (void) fprintf(stderr, "readkeyring: bad alloc\n");
225 return NULL;
227 if (!__ops_keyring_fileread(keyring, noarmor, filename)) {
228 free(keyring);
229 (void) fprintf(stderr, "Can't read %s %s\n", name, filename);
230 return NULL;
232 netpgp_setvar(netpgp, name, filename);
233 return keyring;
236 /* read keys from ssh key files */
237 static int
238 readsshkeys(netpgp_t *netpgp, char *homedir)
240 __ops_keyring_t *pubring;
241 __ops_keyring_t *secring;
242 char f[MAXPATHLEN];
243 char *filename;
245 if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) {
246 (void) snprintf(f, sizeof(f), "%s/.ssh/is_rsa.pub", homedir);
247 filename = f;
249 if ((pubring = calloc(1, sizeof(*pubring))) == NULL) {
250 (void) fprintf(stderr, "readsshkeys: bad alloc\n");
251 return 0;
253 if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL)) {
254 free(pubring);
255 (void) fprintf(stderr, "readsshkeys: can't read %s\n",
256 filename);
257 return 0;
259 netpgp->pubring = pubring;
260 netpgp_setvar(netpgp, "sshpubfile", filename);
261 /* try to take the ".pub" off the end */
262 if (filename == f) {
263 f[strlen(f) - 4] = 0x0;
264 } else {
265 (void) snprintf(f, sizeof(f), "%.*s",
266 (int)strlen(filename) - 4, filename);
267 filename = f;
269 if ((secring = calloc(1, sizeof(*secring))) == NULL) {
270 (void) fprintf(stderr, "readsshkeys: bad alloc\n");
271 return 0;
273 if (__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename)) {
274 netpgp->secring = secring;
275 netpgp_setvar(netpgp, "sshsecfile", filename);
276 } else {
277 (void) fprintf(stderr, "readsshkeys: can't read sec %s (%d)\n",
278 filename, errno);
280 return 1;
283 /* set ssh uid to first one in ring */
284 static void
285 set_ssh_userid(__ops_keyring_t *pubring, char *id, size_t len)
287 unsigned char *src;
288 int i;
289 int n;
291 (void) memset(id, 0x0, len);
292 src = pubring->keys[0].key_id;
293 for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) {
294 n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]);
296 id[n] = 0x0;
299 /***************************************************************************/
300 /* exported functions start here */
301 /***************************************************************************/
303 /* initialise a netpgp_t structure */
305 netpgp_init(netpgp_t *netpgp)
307 __ops_io_t *io;
308 char id[MAX_ID_LENGTH];
309 char *homedir;
310 char *userid;
311 char *stream;
312 char *passfd;
313 char *results;
314 int coredumps;
316 #ifdef HAVE_SYS_RESOURCE_H
317 struct rlimit limit;
319 coredumps = netpgp_getvar(netpgp, "coredumps") != NULL;
320 if (!coredumps) {
321 (void) memset(&limit, 0x0, sizeof(limit));
322 if (setrlimit(RLIMIT_CORE, &limit) != 0) {
323 (void) fprintf(stderr,
324 "netpgp_init: warning - can't turn off core dumps\n");
325 coredumps = 1;
328 #else
329 coredumps = 1;
330 #endif
331 if ((io = calloc(1, sizeof(*io))) == NULL) {
332 (void) fprintf(stderr, "netpgp_init: bad alloc\n");
333 return 0;
335 io->outs = stdout;
336 if ((stream = netpgp_getvar(netpgp, "stdout")) != NULL &&
337 strcmp(stream, "stderr") == 0) {
338 io->outs = stderr;
340 io->errs = stderr;
341 if ((stream = netpgp_getvar(netpgp, "stderr")) != NULL &&
342 strcmp(stream, "stdout") == 0) {
343 io->errs = stdout;
345 if ((results = netpgp_getvar(netpgp, "results")) == NULL) {
346 io->res = io->errs;
347 } else if ((io->res = fopen(results, "w")) == NULL) {
348 (void) fprintf(io->errs, "Can't open results %s for writing\n",
349 results);
350 return 0;
352 netpgp->io = io;
353 if (coredumps) {
354 (void) fprintf(io->errs,
355 "netpgp: warning: core dumps enabled\n");
357 if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) {
358 (void) fprintf(io->errs, "netpgp: bad homedir\n");
359 return 0;
361 /* read from either gpg files or ssh keys */
362 if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
363 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
364 (void) memset(id, 0x0, sizeof(id));
365 (void) conffile(netpgp, homedir, id, sizeof(id));
366 if (id[0] != 0x0) {
367 netpgp_setvar(netpgp, "userid", userid = id);
370 if (userid == NULL) {
371 if (netpgp_getvar(netpgp, "need userid") != NULL) {
372 (void) fprintf(io->errs,
373 "Cannot find user id\n");
374 return 0;
376 } else {
377 (void) netpgp_setvar(netpgp, "userid", userid);
379 netpgp->pubring = readkeyring(netpgp, "pubring");
380 if (netpgp->pubring == NULL) {
381 (void) fprintf(io->errs, "Can't read pub keyring\n");
382 return 0;
384 netpgp->secring = readkeyring(netpgp, "secring");
385 if (netpgp->secring == NULL) {
386 (void) fprintf(io->errs, "Can't read sec keyring\n");
387 return 0;
389 } else {
390 if (!readsshkeys(netpgp, homedir)) {
391 (void) fprintf(io->errs, "Can't read ssh pub key\n");
392 return 0;
394 if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
395 set_ssh_userid(netpgp->pubring, id, sizeof(id));
396 netpgp_setvar(netpgp, "userid", userid = id);
398 if (userid == NULL) {
399 if (netpgp_getvar(netpgp, "need userid") != NULL) {
400 (void) fprintf(io->errs,
401 "Cannot find user id\n");
402 return 0;
404 } else {
405 (void) netpgp_setvar(netpgp, "userid", userid);
408 if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL &&
409 (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) {
410 (void) fprintf(io->errs, "Can't open fd %s for reading\n",
411 passfd);
412 return 0;
414 return 1;
417 /* finish off with the netpgp_t struct */
419 netpgp_end(netpgp_t *netpgp)
421 unsigned i;
423 for (i = 0 ; i < netpgp->c ; i++) {
424 if (netpgp->name[i] != NULL) {
425 free(netpgp->name[i]);
427 if (netpgp->value[i] != NULL) {
428 free(netpgp->value[i]);
431 if (netpgp->name != NULL) {
432 free(netpgp->name);
434 if (netpgp->value != NULL) {
435 free(netpgp->value);
437 if (netpgp->pubring != NULL) {
438 __ops_keyring_free(netpgp->pubring);
440 if (netpgp->secring != NULL) {
441 __ops_keyring_free(netpgp->secring);
443 free(netpgp->io);
444 return 1;
447 /* list the keys in a keyring */
449 netpgp_list_keys(netpgp_t *netpgp)
451 return __ops_keyring_list(netpgp->io, netpgp->pubring);
454 /* find and list some keys in a keyring */
456 netpgp_match_list_keys(netpgp_t *netpgp, char *name)
458 const __ops_key_t *key;
459 unsigned found;
460 unsigned k;
461 char *data;
463 found = k = 0;
464 do {
465 key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
466 name, &k);
467 if (key != NULL) {
468 __ops_sprint_keydata(key, &data, "pub",
469 &key->key.pubkey);
470 printf("%s\n", data);
471 free(data);
472 found += 1;
473 k += 1;
475 } while (key != NULL);
476 printf("Found %u key%s\n", found, (found == 1) ? "" : "s");
477 return (found > 0);
480 /* find a key in a keyring */
482 netpgp_find_key(netpgp_t *netpgp, char *id)
484 __ops_io_t *io;
486 io = netpgp->io;
487 if (id == NULL) {
488 (void) fprintf(io->errs, "NULL id to search for\n");
489 return 0;
491 return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL;
494 /* get a key in a keyring */
495 char *
496 netpgp_get_key(netpgp_t *netpgp, const char *id)
498 const __ops_key_t *key;
499 __ops_io_t *io;
500 char *newkey;
502 io = netpgp->io;
503 if (id == NULL) {
504 (void) fprintf(io->errs, "NULL id to search for\n");
505 return NULL;
507 key = __ops_getkeybyname(netpgp->io, netpgp->pubring, id);
508 if (key == NULL) {
509 (void) fprintf(io->errs, "Can't find key '%s'\n", id);
510 return NULL;
512 return (__ops_sprint_keydata(key, &newkey, "pub",
513 &key->key.pubkey) > 0) ? newkey : NULL;
516 /* export a given key */
518 netpgp_export_key(netpgp_t *netpgp, char *userid)
520 const __ops_key_t *keypair;
521 __ops_io_t *io;
523 io = netpgp->io;
524 if (userid == NULL) {
525 userid = netpgp_getvar(netpgp, "userid");
527 keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
528 if (keypair == NULL) {
529 (void) fprintf(io->errs,
530 "Cannot find own key \"%s\" in keyring\n", userid);
531 return 0;
533 return __ops_export_key(keypair, NULL);
536 /* import a key into our keyring */
538 netpgp_import_key(netpgp_t *netpgp, char *f)
540 const unsigned noarmor = 0;
541 const unsigned armor = 1;
542 __ops_io_t *io;
543 int done;
545 io = netpgp->io;
546 if ((done = __ops_keyring_fileread(netpgp->pubring, noarmor, f)) == 0) {
547 done = __ops_keyring_fileread(netpgp->pubring, armor, f);
549 if (!done) {
550 (void) fprintf(io->errs, "Cannot import key from file %s\n",
552 return 0;
554 return __ops_keyring_list(io, netpgp->pubring);
557 /* generate a new key */
559 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits)
561 __ops_key_t *keypair;
562 __ops_userid_t uid;
563 __ops_output_t *create;
564 const unsigned noarmor = 0;
565 __ops_io_t *io;
566 char *ringfile;
567 int fd;
569 (void) memset(&uid, 0x0, sizeof(uid));
570 io = netpgp->io;
571 /* generate a new key for 'id' */
572 uid.userid = (unsigned char *) id;
573 keypair = __ops_rsa_new_selfsign_key(numbits, 65537UL, &uid);
574 if (keypair == NULL) {
575 (void) fprintf(io->errs, "Cannot generate key\n");
576 return 0;
578 /* write public key, and try to re-read it */
579 ringfile = netpgp_getvar(netpgp, "pubring");
580 fd = __ops_setup_file_append(&create, ringfile);
581 if (!__ops_write_xfer_pubkey(create, keypair, noarmor)) {
582 (void) fprintf(io->errs, "Cannot write pubkey\n");
583 return 0;
585 __ops_teardown_file_write(create, fd);
586 __ops_keyring_free(netpgp->pubring);
587 if (!__ops_keyring_fileread(netpgp->pubring, noarmor, ringfile)) {
588 (void) fprintf(io->errs, "Cannot read pubring %s\n", ringfile);
589 return 0;
591 /* write secret key, and try to re-read it */
592 ringfile = netpgp_getvar(netpgp, "sec ring file");
593 fd = __ops_setup_file_append(&create, ringfile);
594 if (!__ops_write_xfer_seckey(create, keypair, NULL, 0, noarmor)) {
595 (void) fprintf(io->errs, "Cannot write seckey\n");
596 return 0;
598 __ops_teardown_file_write(create, fd);
599 __ops_keyring_free(netpgp->secring);
600 if (!__ops_keyring_fileread(netpgp->secring, noarmor, ringfile)) {
601 (void) fprintf(io->errs, "Can't read secring %s\n", ringfile);
602 return 0;
604 __ops_keydata_free(keypair);
605 return 1;
608 /* encrypt a file */
610 netpgp_encrypt_file(netpgp_t *netpgp,
611 const char *userid,
612 const char *f,
613 char *out,
614 int armored)
616 const __ops_key_t *keypair;
617 const unsigned overwrite = 1;
618 const char *suffix;
619 __ops_io_t *io;
620 char outname[MAXPATHLEN];
622 io = netpgp->io;
623 if (f == NULL) {
624 (void) fprintf(io->errs,
625 "netpgp_encrypt_file: no filename specified\n");
626 return 0;
628 if (userid == NULL) {
629 userid = netpgp_getvar(netpgp, "userid");
631 suffix = (armored) ? ".asc" : ".gpg";
632 keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
633 if (keypair == NULL) {
634 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
635 userid);
636 return 0;
638 if (out == NULL) {
639 (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix);
640 out = outname;
642 return (int)__ops_encrypt_file(io, f, out, keypair, (unsigned)armored,
643 overwrite);
646 #define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----\r\n"
648 /* decrypt a file */
650 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored)
652 const unsigned overwrite = 1;
653 __ops_io_t *io;
654 unsigned realarmour;
655 FILE *fp;
656 char buf[BUFSIZ];
658 io = netpgp->io;
659 if (f == NULL) {
660 (void) fprintf(io->errs,
661 "netpgp_decrypt_file: no filename specified\n");
662 return 0;
664 realarmour = (unsigned)armored;
665 if ((fp = fopen(f, "r")) == NULL) {
666 (void) fprintf(io->errs,
667 "netpgp_decrypt_file: can't open '%s'\n", f);
668 return 0;
670 if (fgets(buf, sizeof(buf), fp) == NULL) {
671 realarmour = 0;
672 } else {
673 realarmour = (strcmp(buf, ARMOR_HEAD) == 0);
675 (void) fclose(fp);
676 return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring,
677 (unsigned)realarmour, overwrite,
678 netpgp->passfp, get_passphrase_cb);
681 /* sign a file */
683 netpgp_sign_file(netpgp_t *netpgp,
684 const char *userid,
685 const char *f,
686 char *out,
687 int armored,
688 int cleartext,
689 int detached)
691 const __ops_key_t *keypair;
692 __ops_seckey_t *seckey;
693 const unsigned overwrite = 1;
694 __ops_io_t *io;
695 char *hashalg;
696 int ret;
698 io = netpgp->io;
699 if (f == NULL) {
700 (void) fprintf(io->errs,
701 "netpgp_sign_file: no filename specified\n");
702 return 0;
704 if (userid == NULL) {
705 userid = netpgp_getvar(netpgp, "userid");
707 /* get key with which to sign */
708 keypair = __ops_getkeybyname(io, netpgp->secring, userid);
709 if (keypair == NULL) {
710 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
711 userid);
712 return 0;
714 ret = 1;
715 do {
716 /* print out the user id */
717 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey);
718 if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
719 /* now decrypt key */
720 seckey = __ops_decrypt_seckey(keypair);
721 if (seckey == NULL) {
722 (void) fprintf(io->errs, "Bad passphrase\n");
724 } else {
725 __ops_keyring_t *secring;
727 secring = netpgp->secring;
728 seckey = &secring->keys[0].key.seckey;
730 } while (seckey == NULL);
731 /* sign file */
732 hashalg = netpgp_getvar(netpgp, "hash");
733 if (detached) {
734 ret = __ops_sign_detached(io, f, out, seckey, hashalg);
735 } else {
736 ret = __ops_sign_file(io, f, out, seckey, hashalg,
737 (unsigned)armored, (unsigned)cleartext,
738 overwrite);
740 __ops_forget(seckey, sizeof(*seckey));
741 return ret;
744 /* verify a file */
746 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored)
748 __ops_validation_t result;
749 __ops_io_t *io;
751 (void) memset(&result, 0x0, sizeof(result));
752 io = netpgp->io;
753 if (in == NULL) {
754 (void) fprintf(io->errs,
755 "netpgp_verify_file: no filename specified\n");
756 return 0;
758 if (__ops_validate_file(io, &result, in, out, armored,
759 netpgp->pubring)) {
760 resultp(io, in, &result, netpgp->pubring);
761 return 1;
763 if (result.validc + result.invalidc + result.unknownc == 0) {
764 (void) fprintf(io->errs,
765 "\"%s\": No signatures found - is this a signed file?\n",
766 in);
767 } else {
768 (void) fprintf(io->errs,
769 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n",
770 in, result.invalidc, result.unknownc);
772 return 0;
775 /* sign some memory */
777 netpgp_sign_memory(netpgp_t *netpgp,
778 const char *userid,
779 char *mem,
780 size_t size,
781 char *out,
782 size_t outsize,
783 const unsigned armored,
784 const unsigned cleartext)
786 const __ops_key_t *keypair;
787 __ops_seckey_t *seckey;
788 __ops_memory_t *signedmem;
789 __ops_io_t *io;
790 char *hashalg;
791 int ret;
793 io = netpgp->io;
794 if (mem == NULL) {
795 (void) fprintf(io->errs,
796 "netpgp_sign_memory: no memory to sign\n");
797 return 0;
799 if (userid == NULL) {
800 userid = netpgp_getvar(netpgp, "userid");
802 /* get key with which to sign */
803 keypair = __ops_getkeybyname(io, netpgp->secring, userid);
804 if (keypair == NULL) {
805 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
806 userid);
807 return 0;
809 ret = 1;
810 do {
811 /* print out the user id */
812 __ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey);
813 /* now decrypt key */
814 seckey = __ops_decrypt_seckey(keypair);
815 if (seckey == NULL) {
816 (void) fprintf(io->errs, "Bad passphrase\n");
818 } while (seckey == NULL);
819 /* sign file */
820 hashalg = netpgp_getvar(netpgp, "hash");
821 signedmem = __ops_sign_buf(io, mem, size, seckey, hashalg,
822 armored, cleartext);
823 if (signedmem) {
824 size_t m;
826 m = MIN(__ops_mem_len(signedmem), outsize);
827 (void) memcpy(out, __ops_mem_data(signedmem), m);
828 __ops_memory_free(signedmem);
829 ret = (int)m;
830 } else {
831 ret = 0;
833 __ops_forget(seckey, sizeof(*seckey));
834 return ret;
837 /* verify memory */
839 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size,
840 void *out, size_t outsize, const int armored)
842 __ops_validation_t result;
843 __ops_memory_t *signedmem;
844 __ops_memory_t *cat;
845 __ops_io_t *io;
846 size_t m;
847 int ret;
849 (void) memset(&result, 0x0, sizeof(result));
850 io = netpgp->io;
851 if (in == NULL) {
852 (void) fprintf(io->errs,
853 "netpgp_verify_memory: no memory to verify\n");
854 return 0;
856 signedmem = __ops_memory_new();
857 __ops_memory_add(signedmem, in, size);
858 ret = __ops_validate_mem(io, &result, signedmem,
859 (out) ? &cat : NULL,
860 armored, netpgp->pubring);
861 __ops_memory_free(signedmem);
862 if (ret) {
863 resultp(io, "<stdin>", &result, netpgp->pubring);
864 if (out) {
865 m = MIN(__ops_mem_len(cat), outsize);
866 (void) memcpy(out, __ops_mem_data(cat), m);
867 __ops_memory_free(cat);
868 } else {
869 m = 1;
871 return (int)m;
873 if (result.validc + result.invalidc + result.unknownc == 0) {
874 (void) fprintf(io->errs,
875 "No signatures found - is this memory signed?\n");
876 } else {
877 (void) fprintf(io->errs,
878 "memory verification failure: %u invalid signatures, %u unknown signatures\n",
879 result.invalidc, result.unknownc);
881 return 0;
884 /* encrypt some memory */
886 netpgp_encrypt_memory(netpgp_t *netpgp,
887 const char *userid,
888 void *in,
889 const size_t insize,
890 char *out,
891 size_t outsize,
892 int armored)
894 const __ops_key_t *keypair;
895 __ops_memory_t *enc;
896 __ops_io_t *io;
897 size_t m;
899 io = netpgp->io;
900 if (in == NULL) {
901 (void) fprintf(io->errs,
902 "netpgp_encrypt_buf: no memory to encrypt\n");
903 return 0;
905 if (userid == NULL) {
906 userid = netpgp_getvar(netpgp, "userid");
908 keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
909 if (keypair == NULL) {
910 (void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
911 userid);
912 return 0;
914 if (in == out) {
915 (void) fprintf(io->errs,
916 "netpgp_encrypt_buf: input and output bufs need to be different\n");
917 return 0;
919 if (outsize < insize) {
920 (void) fprintf(io->errs,
921 "netpgp_encrypt_buf: input size is larger than output size\n");
922 return 0;
924 enc = __ops_encrypt_buf(io, in, insize, keypair, (unsigned)armored);
925 m = MIN(__ops_mem_len(enc), outsize);
926 (void) memcpy(out, __ops_mem_data(enc), m);
927 __ops_memory_free(enc);
928 return (int)m;
931 /* decrypt a chunk of memory */
933 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize,
934 char *out, size_t outsize, const int armored)
936 __ops_memory_t *mem;
937 __ops_io_t *io;
938 unsigned realarmour;
939 size_t m;
941 io = netpgp->io;
942 realarmour = (unsigned) armored;
943 if (input == NULL) {
944 (void) fprintf(io->errs,
945 "netpgp_decrypt_memory: no memory\n");
946 return 0;
948 realarmour = (strncmp(input, ARMOR_HEAD, sizeof(ARMOR_HEAD) - 1) == 0);
949 mem = __ops_decrypt_buf(netpgp->io, input, insize, netpgp->secring,
950 realarmour, netpgp->passfp,
951 get_passphrase_cb);
952 m = MIN(__ops_mem_len(mem), outsize);
953 (void) memcpy(out, __ops_mem_data(mem), m);
954 __ops_memory_free(mem);
955 return (int)m;
958 /* wrappers for the ops_debug_level functions we added to openpgpsdk */
960 /* set the debugging level per filename */
962 netpgp_set_debug(const char *f)
964 return __ops_set_debug_level(f);
967 /* get the debugging level per filename */
969 netpgp_get_debug(const char *f)
971 return __ops_get_debug_level(f);
974 /* return the version for the library */
975 const char *
976 netpgp_get_info(const char *type)
978 return __ops_get_info(type);
981 /* list all the packets in a file */
983 netpgp_list_packets(netpgp_t *netpgp, char *f, int armour, char *pubringname)
985 __ops_keyring_t *keyring;
986 const unsigned noarmor = 0;
987 __ops_io_t *io;
988 char ringname[MAXPATHLEN];
989 char *homedir;
990 int ret;
992 io = netpgp->io;
993 if (f == NULL) {
994 (void) fprintf(io->errs, "No file containing packets\n");
995 return 0;
997 homedir = netpgp_getvar(netpgp, "homedir");
998 if (pubringname == NULL) {
999 (void) snprintf(ringname, sizeof(ringname),
1000 "%s/pubring.gpg", homedir);
1001 pubringname = ringname;
1003 if ((keyring = calloc(1, sizeof(*keyring))) == NULL) {
1004 (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n");
1005 return 0;
1007 if (!__ops_keyring_fileread(keyring, noarmor, pubringname)) {
1008 free(keyring);
1009 (void) fprintf(io->errs, "Cannot read pub keyring %s\n",
1010 pubringname);
1011 return 0;
1013 netpgp->pubring = keyring;
1014 netpgp_setvar(netpgp, "pubring", pubringname);
1015 ret = __ops_list_packets(io, f, (unsigned)armour, keyring,
1016 netpgp->passfp,
1017 get_passphrase_cb);
1018 free(keyring);
1019 return ret;
1022 /* set a variable */
1024 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value)
1026 int i;
1028 if ((i = findvar(netpgp, name)) < 0) {
1029 /* add the element to the array */
1030 if (size_arrays(netpgp, netpgp->size + 15)) {
1031 netpgp->name[i = netpgp->c++] = strdup(name);
1033 } else {
1034 /* replace the element in the array */
1035 if (netpgp->value[i]) {
1036 free(netpgp->value[i]);
1037 netpgp->value[i] = NULL;
1040 /* sanity checks for range of values */
1041 if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) {
1042 if (__ops_str_to_hash_alg(value) == OPS_HASH_UNKNOWN) {
1043 return 0;
1046 netpgp->value[i] = strdup(value);
1047 return 1;
1050 /* get a variable's value (NULL if not set) */
1051 char *
1052 netpgp_getvar(netpgp_t *netpgp, const char *name)
1054 int i;
1056 return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i];
1059 /* increment a value */
1061 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta)
1063 char *cp;
1064 char num[16];
1065 int val;
1067 val = 0;
1068 if ((cp = netpgp_getvar(netpgp, name)) != NULL) {
1069 val = atoi(cp);
1071 (void) snprintf(num, sizeof(num), "%d", val + delta);
1072 netpgp_setvar(netpgp, name, num);
1073 return 1;
1076 /* set the home directory value to "home/subdir" */
1078 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet)
1080 struct stat st;
1081 char d[MAXPATHLEN];
1083 if (home == NULL) {
1084 if (!quiet) {
1085 (void) fprintf(stderr, "NULL HOME directory\n");
1087 return 0;
1089 (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : "");
1090 if (stat(d, &st) == 0) {
1091 if ((st.st_mode & S_IFMT) == S_IFDIR) {
1092 netpgp_setvar(netpgp, "homedir", d);
1093 return 1;
1095 (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n",
1097 return 0;
1099 if (!quiet) {
1100 (void) fprintf(stderr,
1101 "netpgp: warning homedir \"%s\" not found\n", d);
1103 return 1;