xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/netpgp.c (revision 7f21db1c0118155e0dd40b75182e30c589d9f63e)
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.37 2010/02/06 02:24:33 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 unsigned char *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 unsigned char *) res->valid_sigs[i].signer_id,
165 			&from);
166 		__ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey);
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 	unsigned char	*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 /* get expiration in seconds */
314 static uint64_t
315 get_duration(char *s)
316 {
317 	struct tm	 tm;
318 	uint64_t	 now;
319 	char		*mult;
320 
321 	if (s == NULL) {
322 		return 0;
323 	}
324 	now = strtoull(s, NULL, 10);
325 	if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) {
326 		switch(*mult) {
327 		case 'h':
328 			return now * 60 * 60;
329 		case 'd':
330 			return now * 60 * 60 * 24;
331 		case 'w':
332 			return now * 60 * 60 * 24 * 7;
333 		case 'm':
334 			return now * 60 * 60 * 24 * 31;
335 		case 'y':
336 			return now * 60 * 60 * 24 * 365;
337 		}
338 	}
339 	if (strptime(s, "%Y-%m-%d", &tm) != NULL) {
340 		return mktime(&tm);
341 	}
342 	if (strptime(s, "%Y/%m/%d", &tm) != NULL) {
343 		return mktime(&tm);
344 	}
345 	return (uint64_t)strtoll(s, NULL, 10);
346 }
347 
348 /* get birthtime in seconds */
349 static int64_t
350 get_birthtime(char *s)
351 {
352 	struct tm	 tm;
353 
354 	if (s == NULL) {
355 		return time(NULL);
356 	}
357 	if (strptime(s, "%Y-%m-%d", &tm) != NULL) {
358 		return mktime(&tm);
359 	}
360 	if (strptime(s, "%Y/%m/%d", &tm) != NULL) {
361 		return mktime(&tm);
362 	}
363 	return (uint64_t)strtoll(s, NULL, 10);
364 }
365 
366 /***************************************************************************/
367 /* exported functions start here */
368 /***************************************************************************/
369 
370 /* initialise a netpgp_t structure */
371 int
372 netpgp_init(netpgp_t *netpgp)
373 {
374 	__ops_io_t	*io;
375 	char		 id[MAX_ID_LENGTH];
376 	char		*homedir;
377 	char		*userid;
378 	char		*stream;
379 	char		*passfd;
380 	char		*results;
381 	int		 coredumps;
382 	int		 last;
383 
384 #ifdef HAVE_SYS_RESOURCE_H
385 	struct rlimit	limit;
386 
387 	coredumps = netpgp_getvar(netpgp, "coredumps") != NULL;
388 	if (!coredumps) {
389 		(void) memset(&limit, 0x0, sizeof(limit));
390 		if (setrlimit(RLIMIT_CORE, &limit) != 0) {
391 			(void) fprintf(stderr,
392 			"netpgp_init: warning - can't turn off core dumps\n");
393 			coredumps = 1;
394 		}
395 	}
396 #else
397 	coredumps = 1;
398 #endif
399 	if ((io = calloc(1, sizeof(*io))) == NULL) {
400 		(void) fprintf(stderr, "netpgp_init: bad alloc\n");
401 		return 0;
402 	}
403 	io->outs = stdout;
404 	if ((stream = netpgp_getvar(netpgp, "stdout")) != NULL &&
405 	    strcmp(stream, "stderr") == 0) {
406 		io->outs = stderr;
407 	}
408 	io->errs = stderr;
409 	if ((stream = netpgp_getvar(netpgp, "stderr")) != NULL &&
410 	    strcmp(stream, "stdout") == 0) {
411 		io->errs = stdout;
412 	}
413 	if ((results = netpgp_getvar(netpgp, "results")) == NULL) {
414 		io->res = io->errs;
415 	} else if ((io->res = fopen(results, "w")) == NULL) {
416 		(void) fprintf(io->errs, "Can't open results %s for writing\n",
417 			results);
418 		return 0;
419 	}
420 	netpgp->io = io;
421 	if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL &&
422 	    (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) {
423 		(void) fprintf(io->errs, "Can't open fd %s for reading\n",
424 			passfd);
425 		return 0;
426 	}
427 	if (coredumps) {
428 		(void) fprintf(io->errs,
429 			"netpgp: warning: core dumps enabled\n");
430 	}
431 	if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) {
432 		(void) fprintf(io->errs, "netpgp: bad homedir\n");
433 		return 0;
434 	}
435 	/* read from either gpg files or ssh keys */
436 	if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
437 		if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
438 			(void) memset(id, 0x0, sizeof(id));
439 			(void) conffile(netpgp, homedir, id, sizeof(id));
440 			if (id[0] != 0x0) {
441 				netpgp_setvar(netpgp, "userid", userid = id);
442 			}
443 		}
444 		if (userid == NULL) {
445 			if (netpgp_getvar(netpgp, "need userid") != NULL) {
446 				(void) fprintf(io->errs,
447 						"Cannot find user id\n");
448 				return 0;
449 			}
450 		} else {
451 			(void) netpgp_setvar(netpgp, "userid", userid);
452 		}
453 		netpgp->pubring = readkeyring(netpgp, "pubring");
454 		if (netpgp->pubring == NULL) {
455 			(void) fprintf(io->errs, "Can't read pub keyring\n");
456 			return 0;
457 		}
458 		netpgp->secring = readkeyring(netpgp, "secring");
459 		if (netpgp->secring == NULL) {
460 			(void) fprintf(io->errs, "Can't read sec keyring\n");
461 			return 0;
462 		}
463 	} else {
464 		last = (netpgp->pubring != NULL);
465 		if (!readsshkeys(netpgp, homedir)) {
466 			(void) fprintf(io->errs, "Can't read ssh pub key\n");
467 			return 0;
468 		}
469 		if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
470 			set_ssh_userid(netpgp->pubring, id, sizeof(id), last);
471 			netpgp_setvar(netpgp, "userid", userid = id);
472 		}
473 		if (userid == NULL) {
474 			if (netpgp_getvar(netpgp, "need userid") != NULL) {
475 				(void) fprintf(io->errs,
476 						"Cannot find user id\n");
477 				return 0;
478 			}
479 		} else {
480 			(void) netpgp_setvar(netpgp, "userid", userid);
481 		}
482 	}
483 	return 1;
484 }
485 
486 /* finish off with the netpgp_t struct */
487 int
488 netpgp_end(netpgp_t *netpgp)
489 {
490 	unsigned	i;
491 
492 	for (i = 0 ; i < netpgp->c ; i++) {
493 		if (netpgp->name[i] != NULL) {
494 			free(netpgp->name[i]);
495 		}
496 		if (netpgp->value[i] != NULL) {
497 			free(netpgp->value[i]);
498 		}
499 	}
500 	if (netpgp->name != NULL) {
501 		free(netpgp->name);
502 	}
503 	if (netpgp->value != NULL) {
504 		free(netpgp->value);
505 	}
506 	if (netpgp->pubring != NULL) {
507 		__ops_keyring_free(netpgp->pubring);
508 	}
509 	if (netpgp->secring != NULL) {
510 		__ops_keyring_free(netpgp->secring);
511 	}
512 	free(netpgp->io);
513 	return 1;
514 }
515 
516 /* list the keys in a keyring */
517 int
518 netpgp_list_keys(netpgp_t *netpgp)
519 {
520 	return __ops_keyring_list(netpgp->io, netpgp->pubring);
521 }
522 
523 DEFINE_ARRAY(strings_t, char *);
524 
525 #ifndef HKP_VERSION
526 #define HKP_VERSION	1
527 #endif
528 
529 /* find and list some keys in a keyring */
530 int
531 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp)
532 {
533 	const __ops_key_t	*key;
534 	unsigned		 k;
535 	strings_t		 pubs;
536 	FILE			*fp = (FILE *)vp;
537 
538 	(void) memset(&pubs, 0x0, sizeof(pubs));
539 	k = 0;
540 	do {
541 		key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
542 						name, &k);
543 		if (key != NULL) {
544 			ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10,
545 					"netpgp_match_keys", return 0);
546 			if (strcmp(fmt, "mr") == 0) {
547 				__ops_hkp_sprint_keydata(
548 						key, &pubs.v[pubs.c],
549 						&key->key.pubkey);
550 			} else {
551 				__ops_sprint_keydata(
552 						key, &pubs.v[pubs.c],
553 						"pub",
554 						&key->key.pubkey);
555 			}
556 			pubs.c += 1;
557 			k += 1;
558 		}
559 	} while (key != NULL);
560 	if (strcmp(fmt, "mr") == 0) {
561 		(void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c);
562 	} else {
563 		(void) fprintf(fp, "%d keys found\n", pubs.c);
564 	}
565 	for (k = 0 ; k < pubs.c ; k++) {
566 		(void) fprintf(fp, "%s", pubs.v[k]);
567 		free(pubs.v[k]);
568 	}
569 	free(pubs.v);
570 	return pubs.c;
571 }
572 
573 /* find and list some public keys in a keyring */
574 int
575 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp)
576 {
577 	const __ops_key_t	*key;
578 	unsigned		 k;
579 	strings_t		 pubs;
580 	FILE			*fp = (FILE *)vp;
581 
582 	(void) memset(&pubs, 0x0, sizeof(pubs));
583 	do {
584 		key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
585 						name, &k);
586 		if (key != NULL) {
587 			char	out[1024 * 64];
588 
589 			ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10,
590 					"netpgp_match_pubkeys", return 0);
591 			(void) __ops_sprint_pubkey(key, out, sizeof(out));
592 			pubs.v[pubs.c++] = strdup(out);
593 			k += 1;
594 		}
595 	} while (key != NULL);
596 	(void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c);
597 	for (k = 0 ; k < pubs.c ; k++) {
598 		(void) fprintf(fp, "%s", pubs.v[k]);
599 		free(pubs.v[k]);
600 	}
601 	free(pubs.v);
602 	return pubs.c;
603 }
604 
605 /* find a key in a keyring */
606 int
607 netpgp_find_key(netpgp_t *netpgp, char *id)
608 {
609 	__ops_io_t	*io;
610 
611 	io = netpgp->io;
612 	if (id == NULL) {
613 		(void) fprintf(io->errs, "NULL id to search for\n");
614 		return 0;
615 	}
616 	return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL;
617 }
618 
619 /* get a key in a keyring */
620 char *
621 netpgp_get_key(netpgp_t *netpgp, const char *id)
622 {
623 	const __ops_key_t	*key;
624 	__ops_io_t		*io;
625 	char			*newkey;
626 
627 	io = netpgp->io;
628 	if (id == NULL) {
629 		/* just get the default userid */
630 		id = netpgp_getvar(netpgp, "userid");
631 	}
632 	key = __ops_getkeybyname(netpgp->io, netpgp->pubring, id);
633 	if (key == NULL) {
634 		(void) fprintf(io->errs, "Can't find key '%s'\n", id);
635 		return NULL;
636 	}
637 	return (__ops_sprint_keydata(key, &newkey, "pub",
638 				&key->key.pubkey) > 0) ? newkey : NULL;
639 }
640 
641 /* export a given key */
642 int
643 netpgp_export_key(netpgp_t *netpgp, char *userid)
644 {
645 	const __ops_key_t	*keypair;
646 	__ops_io_t		*io;
647 
648 	io = netpgp->io;
649 	if (userid == NULL) {
650 		userid = netpgp_getvar(netpgp, "userid");
651 	}
652 	keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
653 	if (keypair == NULL) {
654 		(void) fprintf(io->errs,
655 			"Cannot find own key \"%s\" in keyring\n", userid);
656 		return 0;
657 	}
658 	return __ops_export_key(keypair, NULL);
659 }
660 
661 /* import a key into our keyring */
662 int
663 netpgp_import_key(netpgp_t *netpgp, char *f)
664 {
665 	const unsigned	noarmor = 0;
666 	const unsigned	armor = 1;
667 	__ops_io_t	*io;
668 	int		done;
669 
670 	io = netpgp->io;
671 	if ((done = __ops_keyring_fileread(netpgp->pubring, noarmor, f)) == 0) {
672 		done = __ops_keyring_fileread(netpgp->pubring, armor, f);
673 	}
674 	if (!done) {
675 		(void) fprintf(io->errs, "Cannot import key from file %s\n",
676 				f);
677 		return 0;
678 	}
679 	return __ops_keyring_list(io, netpgp->pubring);
680 }
681 
682 /* generate a new key */
683 int
684 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits)
685 {
686 	__ops_key_t		*keypair;
687 	__ops_userid_t		 uid;
688 	__ops_output_t		*create;
689 	const unsigned		 noarmor = 0;
690 	__ops_io_t		*io;
691 	char			*ringfile;
692 	int             	 fd;
693 
694 	(void) memset(&uid, 0x0, sizeof(uid));
695 	io = netpgp->io;
696 	/* generate a new key for 'id' */
697 	uid.userid = (unsigned char *) id;
698 	keypair = __ops_rsa_new_selfsign_key(numbits, 65537UL, &uid);
699 	if (keypair == NULL) {
700 		(void) fprintf(io->errs, "Cannot generate key\n");
701 		return 0;
702 	}
703 	/* write public key, and try to re-read it */
704 	ringfile = netpgp_getvar(netpgp, "pubring");
705 	fd = __ops_setup_file_append(&create, ringfile);
706 	if (!__ops_write_xfer_pubkey(create, keypair, noarmor)) {
707 		(void) fprintf(io->errs, "Cannot write pubkey\n");
708 		return 0;
709 	}
710 	__ops_teardown_file_write(create, fd);
711 	__ops_keyring_free(netpgp->pubring);
712 	if (!__ops_keyring_fileread(netpgp->pubring, noarmor, ringfile)) {
713 		(void) fprintf(io->errs, "Cannot read pubring %s\n", ringfile);
714 		return 0;
715 	}
716 	/* write secret key, and try to re-read it */
717 	ringfile = netpgp_getvar(netpgp, "sec ring file");
718 	fd = __ops_setup_file_append(&create, ringfile);
719 	if (!__ops_write_xfer_seckey(create, keypair, NULL, 0, noarmor)) {
720 		(void) fprintf(io->errs, "Cannot write seckey\n");
721 		return 0;
722 	}
723 	__ops_teardown_file_write(create, fd);
724 	__ops_keyring_free(netpgp->secring);
725 	if (!__ops_keyring_fileread(netpgp->secring, noarmor, ringfile)) {
726 		(void) fprintf(io->errs, "Can't read secring %s\n", ringfile);
727 		return 0;
728 	}
729 	__ops_keydata_free(keypair);
730 	return 1;
731 }
732 
733 /* encrypt a file */
734 int
735 netpgp_encrypt_file(netpgp_t *netpgp,
736 			const char *userid,
737 			const char *f,
738 			char *out,
739 			int armored)
740 {
741 	const __ops_key_t	*keypair;
742 	const unsigned		 overwrite = 1;
743 	const char		*suffix;
744 	__ops_io_t		*io;
745 	char			 outname[MAXPATHLEN];
746 
747 	io = netpgp->io;
748 	if (f == NULL) {
749 		(void) fprintf(io->errs,
750 			"netpgp_encrypt_file: no filename specified\n");
751 		return 0;
752 	}
753 	if (userid == NULL) {
754 		userid = netpgp_getvar(netpgp, "userid");
755 	}
756 	suffix = (armored) ? ".asc" : ".gpg";
757 	keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
758 	if (keypair == NULL) {
759 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
760 					userid);
761 		return 0;
762 	}
763 	if (out == NULL) {
764 		(void) snprintf(outname, sizeof(outname), "%s%s", f, suffix);
765 		out = outname;
766 	}
767 	return (int)__ops_encrypt_file(io, f, out, keypair, (unsigned)armored,
768 					overwrite);
769 }
770 
771 #define ARMOR_HEAD	"-----BEGIN PGP MESSAGE-----\r\n"
772 
773 /* decrypt a file */
774 int
775 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored)
776 {
777 	const unsigned	 overwrite = 1;
778 	__ops_io_t	*io;
779 	unsigned	 realarmour;
780 	FILE		*fp;
781 	char		 buf[BUFSIZ];
782 
783 	io = netpgp->io;
784 	if (f == NULL) {
785 		(void) fprintf(io->errs,
786 			"netpgp_decrypt_file: no filename specified\n");
787 		return 0;
788 	}
789 	realarmour = (unsigned)armored;
790 	if ((fp = fopen(f, "r")) == NULL) {
791 		(void) fprintf(io->errs,
792 			"netpgp_decrypt_file: can't open '%s'\n", f);
793 		return 0;
794 	}
795 	if (fgets(buf, sizeof(buf), fp) == NULL) {
796 		realarmour = 0;
797 	} else {
798 		realarmour = (strcmp(buf, ARMOR_HEAD) == 0);
799 	}
800 	(void) fclose(fp);
801 	return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring,
802 				(unsigned)realarmour, overwrite,
803 				netpgp->passfp, get_passphrase_cb);
804 }
805 
806 /* sign a file */
807 int
808 netpgp_sign_file(netpgp_t *netpgp,
809 		const char *userid,
810 		const char *f,
811 		char *out,
812 		int armored,
813 		int cleartext,
814 		int detached)
815 {
816 	const __ops_key_t	*keypair;
817 	__ops_seckey_t		*seckey;
818 	const unsigned		 overwrite = 1;
819 	__ops_io_t		*io;
820 	char			*hashalg;
821 	int			 ret;
822 
823 	io = netpgp->io;
824 	if (f == NULL) {
825 		(void) fprintf(io->errs,
826 			"netpgp_sign_file: no filename specified\n");
827 		return 0;
828 	}
829 	if (userid == NULL) {
830 		userid = netpgp_getvar(netpgp, "userid");
831 	}
832 	/* get key with which to sign */
833 	keypair = __ops_getkeybyname(io, netpgp->secring, userid);
834 	if (keypair == NULL) {
835 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
836 				userid);
837 		return 0;
838 	}
839 	ret = 1;
840 	do {
841 		if (netpgp->passfp == NULL) {
842 			/* print out the user id */
843 			__ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey);
844 		}
845 		if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
846 			/* now decrypt key */
847 			seckey = __ops_decrypt_seckey(keypair, netpgp->passfp);
848 			if (seckey == NULL) {
849 				(void) fprintf(io->errs, "Bad passphrase\n");
850 			}
851 		} else {
852 			__ops_keyring_t	*secring;
853 
854 			secring = netpgp->secring;
855 			seckey = &secring->keys[0].key.seckey;
856 		}
857 	} while (seckey == NULL);
858 	/* sign file */
859 	hashalg = netpgp_getvar(netpgp, "hash");
860 	if (detached) {
861 		ret = __ops_sign_detached(io, f, out, seckey, hashalg,
862 				get_birthtime(netpgp_getvar(netpgp, "birthtime")),
863 				get_duration(netpgp_getvar(netpgp, "duration")));
864 	} else {
865 		ret = __ops_sign_file(io, f, out, seckey, hashalg,
866 				get_birthtime(netpgp_getvar(netpgp, "birthtime")),
867 				get_duration(netpgp_getvar(netpgp, "duration")),
868 				(unsigned)armored, (unsigned)cleartext,
869 				overwrite);
870 	}
871 	__ops_forget(seckey, sizeof(*seckey));
872 	return ret;
873 }
874 
875 /* verify a file */
876 int
877 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored)
878 {
879 	__ops_validation_t	 result;
880 	__ops_io_t		*io;
881 
882 	(void) memset(&result, 0x0, sizeof(result));
883 	io = netpgp->io;
884 	if (in == NULL) {
885 		(void) fprintf(io->errs,
886 			"netpgp_verify_file: no filename specified\n");
887 		return 0;
888 	}
889 	if (__ops_validate_file(io, &result, in, out, armored,
890 						netpgp->pubring)) {
891 		resultp(io, in, &result, netpgp->pubring);
892 		return 1;
893 	}
894 	if (result.validc + result.invalidc + result.unknownc == 0) {
895 		(void) fprintf(io->errs,
896 		"\"%s\": No signatures found - is this a signed file?\n",
897 			in);
898 	} else if (result.invalidc == 0 && result.unknownc == 0) {
899 		(void) fprintf(io->errs,
900 			"\"%s\": file verification failure: invalid signature time\n", in);
901 	} else {
902 		(void) fprintf(io->errs,
903 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n",
904 			in, result.invalidc, result.unknownc);
905 	}
906 	return 0;
907 }
908 
909 /* sign some memory */
910 int
911 netpgp_sign_memory(netpgp_t *netpgp,
912 		const char *userid,
913 		char *mem,
914 		size_t size,
915 		char *out,
916 		size_t outsize,
917 		const unsigned armored,
918 		const unsigned cleartext)
919 {
920 	const __ops_key_t	*keypair;
921 	__ops_seckey_t		*seckey;
922 	__ops_memory_t		*signedmem;
923 	__ops_io_t		*io;
924 	char			*hashalg;
925 	int			 ret;
926 
927 	io = netpgp->io;
928 	if (mem == NULL) {
929 		(void) fprintf(io->errs,
930 			"netpgp_sign_memory: no memory to sign\n");
931 		return 0;
932 	}
933 	if (userid == NULL) {
934 		userid = netpgp_getvar(netpgp, "userid");
935 	}
936 	/* get key with which to sign */
937 	keypair = __ops_getkeybyname(io, netpgp->secring, userid);
938 	if (keypair == NULL) {
939 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
940 				userid);
941 		return 0;
942 	}
943 	ret = 1;
944 	do {
945 		if (netpgp->passfp == NULL) {
946 			/* print out the user id */
947 			__ops_print_keydata(io, keypair, "pub", &keypair->key.pubkey);
948 		}
949 		/* now decrypt key */
950 		seckey = __ops_decrypt_seckey(keypair, netpgp->passfp);
951 		if (seckey == NULL) {
952 			(void) fprintf(io->errs, "Bad passphrase\n");
953 		}
954 	} while (seckey == NULL);
955 	/* sign file */
956 	(void) memset(out, 0x0, outsize);
957 	hashalg = netpgp_getvar(netpgp, "hash");
958 	signedmem = __ops_sign_buf(io, mem, size, seckey,
959 				get_birthtime(netpgp_getvar(netpgp, "birthtime")),
960 				get_duration(netpgp_getvar(netpgp, "duration")),
961 				hashalg, armored, cleartext);
962 	if (signedmem) {
963 		size_t	m;
964 
965 		m = MIN(__ops_mem_len(signedmem), outsize);
966 		(void) memcpy(out, __ops_mem_data(signedmem), m);
967 		__ops_memory_free(signedmem);
968 		ret = (int)m;
969 	} else {
970 		ret = 0;
971 	}
972 	__ops_forget(seckey, sizeof(*seckey));
973 	return ret;
974 }
975 
976 /* verify memory */
977 int
978 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size,
979 			void *out, size_t outsize, const int armored)
980 {
981 	__ops_validation_t	 result;
982 	__ops_memory_t		*signedmem;
983 	__ops_memory_t		*cat;
984 	__ops_io_t		*io;
985 	size_t			 m;
986 	int			 ret;
987 
988 	(void) memset(&result, 0x0, sizeof(result));
989 	io = netpgp->io;
990 	if (in == NULL) {
991 		(void) fprintf(io->errs,
992 			"netpgp_verify_memory: no memory to verify\n");
993 		return 0;
994 	}
995 	signedmem = __ops_memory_new();
996 	__ops_memory_add(signedmem, in, size);
997 	ret = __ops_validate_mem(io, &result, signedmem,
998 				(out) ? &cat : NULL,
999 				armored, netpgp->pubring);
1000 	__ops_memory_free(signedmem);
1001 	if (ret) {
1002 		resultp(io, "<stdin>", &result, netpgp->pubring);
1003 		if (out) {
1004 			m = MIN(__ops_mem_len(cat), outsize);
1005 			(void) memcpy(out, __ops_mem_data(cat), m);
1006 			__ops_memory_free(cat);
1007 		} else {
1008 			m = 1;
1009 		}
1010 		return (int)m;
1011 	}
1012 	if (result.validc + result.invalidc + result.unknownc == 0) {
1013 		(void) fprintf(io->errs,
1014 		"No signatures found - is this memory signed?\n");
1015 	} else if (result.invalidc == 0 && result.unknownc == 0) {
1016 		(void) fprintf(io->errs,
1017 			"memory verification failure: invalid signature time\n");
1018 	} else {
1019 		(void) fprintf(io->errs,
1020 "memory verification failure: %u invalid signatures, %u unknown signatures\n",
1021 			result.invalidc, result.unknownc);
1022 	}
1023 	return 0;
1024 }
1025 
1026 /* encrypt some memory */
1027 int
1028 netpgp_encrypt_memory(netpgp_t *netpgp,
1029 			const char *userid,
1030 			void *in,
1031 			const size_t insize,
1032 			char *out,
1033 			size_t outsize,
1034 			int armored)
1035 {
1036 	const __ops_key_t	*keypair;
1037 	__ops_memory_t		*enc;
1038 	__ops_io_t		*io;
1039 	size_t			 m;
1040 
1041 	io = netpgp->io;
1042 	if (in == NULL) {
1043 		(void) fprintf(io->errs,
1044 			"netpgp_encrypt_buf: no memory to encrypt\n");
1045 		return 0;
1046 	}
1047 	if (userid == NULL) {
1048 		userid = netpgp_getvar(netpgp, "userid");
1049 	}
1050 	keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
1051 	if (keypair == NULL) {
1052 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
1053 					userid);
1054 		return 0;
1055 	}
1056 	if (in == out) {
1057 		(void) fprintf(io->errs,
1058 			"netpgp_encrypt_buf: input and output bufs need to be different\n");
1059 		return 0;
1060 	}
1061 	if (outsize < insize) {
1062 		(void) fprintf(io->errs,
1063 			"netpgp_encrypt_buf: input size is larger than output size\n");
1064 		return 0;
1065 	}
1066 	enc = __ops_encrypt_buf(io, in, insize, keypair, (unsigned)armored);
1067 	m = MIN(__ops_mem_len(enc), outsize);
1068 	(void) memcpy(out, __ops_mem_data(enc), m);
1069 	__ops_memory_free(enc);
1070 	return (int)m;
1071 }
1072 
1073 /* decrypt a chunk of memory */
1074 int
1075 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize,
1076 			char *out, size_t outsize, const int armored)
1077 {
1078 	__ops_memory_t	*mem;
1079 	__ops_io_t	*io;
1080 	unsigned	 realarmour;
1081 	size_t		 m;
1082 
1083 	io = netpgp->io;
1084 	realarmour = (unsigned) armored;
1085 	if (input == NULL) {
1086 		(void) fprintf(io->errs,
1087 			"netpgp_decrypt_memory: no memory\n");
1088 		return 0;
1089 	}
1090 	realarmour = (strncmp(input, ARMOR_HEAD, sizeof(ARMOR_HEAD) - 1) == 0);
1091 	mem = __ops_decrypt_buf(netpgp->io, input, insize, netpgp->secring,
1092 				realarmour, netpgp->passfp,
1093 				get_passphrase_cb);
1094 	m = MIN(__ops_mem_len(mem), outsize);
1095 	(void) memcpy(out, __ops_mem_data(mem), m);
1096 	__ops_memory_free(mem);
1097 	return (int)m;
1098 }
1099 
1100 /* wrappers for the ops_debug_level functions we added to openpgpsdk */
1101 
1102 /* set the debugging level per filename */
1103 int
1104 netpgp_set_debug(const char *f)
1105 {
1106 	return __ops_set_debug_level(f);
1107 }
1108 
1109 /* get the debugging level per filename */
1110 int
1111 netpgp_get_debug(const char *f)
1112 {
1113 	return __ops_get_debug_level(f);
1114 }
1115 
1116 /* return the version for the library */
1117 const char *
1118 netpgp_get_info(const char *type)
1119 {
1120 	return __ops_get_info(type);
1121 }
1122 
1123 /* list all the packets in a file */
1124 int
1125 netpgp_list_packets(netpgp_t *netpgp, char *f, int armour, char *pubringname)
1126 {
1127 	__ops_keyring_t	*keyring;
1128 	const unsigned	 noarmor = 0;
1129 	struct stat	 st;
1130 	__ops_io_t	*io;
1131 	char		 ringname[MAXPATHLEN];
1132 	char		*homedir;
1133 	int		 ret;
1134 
1135 	io = netpgp->io;
1136 	if (f == NULL) {
1137 		(void) fprintf(io->errs, "No file containing packets\n");
1138 		return 0;
1139 	}
1140 	if (stat(f, &st) < 0) {
1141 		(void) fprintf(io->errs, "No such file '%s'\n", f);
1142 		return 0;
1143 	}
1144 	homedir = netpgp_getvar(netpgp, "homedir");
1145 	if (pubringname == NULL) {
1146 		(void) snprintf(ringname, sizeof(ringname),
1147 				"%s/pubring.gpg", homedir);
1148 		pubringname = ringname;
1149 	}
1150 	if ((keyring = calloc(1, sizeof(*keyring))) == NULL) {
1151 		(void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n");
1152 		return 0;
1153 	}
1154 	if (!__ops_keyring_fileread(keyring, noarmor, pubringname)) {
1155 		free(keyring);
1156 		(void) fprintf(io->errs, "Cannot read pub keyring %s\n",
1157 			pubringname);
1158 		return 0;
1159 	}
1160 	netpgp->pubring = keyring;
1161 	netpgp_setvar(netpgp, "pubring", pubringname);
1162 	ret = __ops_list_packets(io, f, (unsigned)armour, keyring,
1163 					netpgp->passfp,
1164 					get_passphrase_cb);
1165 	free(keyring);
1166 	return ret;
1167 }
1168 
1169 /* set a variable */
1170 int
1171 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value)
1172 {
1173 	int	i;
1174 
1175 	if ((i = findvar(netpgp, name)) < 0) {
1176 		/* add the element to the array */
1177 		if (size_arrays(netpgp, netpgp->size + 15)) {
1178 			netpgp->name[i = netpgp->c++] = strdup(name);
1179 		}
1180 	} else {
1181 		/* replace the element in the array */
1182 		if (netpgp->value[i]) {
1183 			free(netpgp->value[i]);
1184 			netpgp->value[i] = NULL;
1185 		}
1186 	}
1187 	/* sanity checks for range of values */
1188 	if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) {
1189 		if (__ops_str_to_hash_alg(value) == OPS_HASH_UNKNOWN) {
1190 			return 0;
1191 		}
1192 	}
1193 	netpgp->value[i] = strdup(value);
1194 	return 1;
1195 }
1196 
1197 /* get a variable's value (NULL if not set) */
1198 char *
1199 netpgp_getvar(netpgp_t *netpgp, const char *name)
1200 {
1201 	int	i;
1202 
1203 	return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i];
1204 }
1205 
1206 /* increment a value */
1207 int
1208 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta)
1209 {
1210 	char	*cp;
1211 	char	 num[16];
1212 	int	 val;
1213 
1214 	val = 0;
1215 	if ((cp = netpgp_getvar(netpgp, name)) != NULL) {
1216 		val = atoi(cp);
1217 	}
1218 	(void) snprintf(num, sizeof(num), "%d", val + delta);
1219 	netpgp_setvar(netpgp, name, num);
1220 	return 1;
1221 }
1222 
1223 /* set the home directory value to "home/subdir" */
1224 int
1225 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet)
1226 {
1227 	struct stat	st;
1228 	char		d[MAXPATHLEN];
1229 
1230 	if (home == NULL) {
1231 		if (!quiet) {
1232 			(void) fprintf(stderr, "NULL HOME directory\n");
1233 		}
1234 		return 0;
1235 	}
1236 	(void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : "");
1237 	if (stat(d, &st) == 0) {
1238 		if ((st.st_mode & S_IFMT) == S_IFDIR) {
1239 			netpgp_setvar(netpgp, "homedir", d);
1240 			return 1;
1241 		}
1242 		(void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n",
1243 					d);
1244 		return 0;
1245 	}
1246 	if (!quiet) {
1247 		(void) fprintf(stderr,
1248 			"netpgp: warning homedir \"%s\" not found\n", d);
1249 	}
1250 	return 1;
1251 }
1252 
1253 /* validate all sigs in the pub keyring */
1254 int
1255 netpgp_validate_sigs(netpgp_t *netpgp)
1256 {
1257 	__ops_validation_t	result;
1258 
1259 	return (int)__ops_validate_all_sigs(&result, netpgp->pubring, NULL);
1260 }
1261 
1262 #if 0
1263 #include "sshkey.h"
1264 
1265 int
1266 netpgp_pgpkey_to_sshkey(netpgp_t *netpgp, char *name, SSHKey *sshkey)
1267 {
1268 	const __ops_key_t	*pgpkey;
1269 	unsigned		 k;
1270 
1271 	k = 0;
1272 	pgpkey = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, name, &k);
1273 	if (pgpkey == NULL) {
1274 		pgpkey = __ops_getkeybyname(io, netpgp->pubring, userid);
1275 	}
1276 	if (pgpkey == NULL) {
1277 		(void) fprintf(stderr, "No key matching '%s'\n", name);
1278 		return 0;
1279 	}
1280 	switch(pgpkey->key.pubkey.alg) {
1281 	case OPS_PKA_RSA:
1282 		sshkey->type = KEY_RSA;
1283 		sshkey->rsa = calloc(1, sizeof(*sshkey->rsa);
1284 		if (sshkey->rsa == NULL) {
1285 			(void) fprintf(stderr, "RSA memory problems\n");
1286 			return 0;
1287 		}
1288 		sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n;
1289 		sshkey->rsa->e = pgpkey->key.pubkey.key.rsa.e;
1290 		sshkey->rsa->d = pgpkey->key.seckey.key.rsa.d;
1291 		sshkey->rsa->p = pgpkey->key.seckey.key.rsa.p;
1292 		sshkey->rsa->q = pgpkey->key.seckey.key.rsa.q;
1293 		sshkey->rsa->iqmp = pgpkey->key.seckey.key.rsa.u;
1294 		break;
1295 	case OPS_PKA_DSA:
1296 		sshkey->type = KEY_DSA;
1297 		sshkey->dsa = calloc(1, sizeof(*sshkey->dsa);
1298 		if (sshkey->dsa == NULL) {
1299 			(void) fprintf(stderr, "DSA memory problems\n");
1300 			return 0;
1301 		}
1302 		sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n;
1303 		key->dsa->p = pgpkey->key.pubkey.key.dsa.p;
1304 		key->dsa->q = pgpkey->key.pubkey.key.dsa.q;
1305 		key->dsa->g = pgpkey->key.pubkey.key.dsa.g;
1306 		key->dsa->pub_key = pgpkey->key.pubkey.key.dsa.y;
1307 		key->dsa->priv_key = pgpkey->key.seckey.key.dsa.x;
1308 		break;
1309 	default:
1310 		(void) fprintf(stderr, "weird type\n");
1311 		return 0;
1312 	}
1313 	return 1;
1314 }
1315 #endif
1316