xref: /minix3/crypto/external/bsd/netpgp/dist/src/netpgpkeys/netpgpkeys.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1ebfedea0SLionel Sambuc /*-
2ebfedea0SLionel Sambuc  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3ebfedea0SLionel Sambuc  * All rights reserved.
4ebfedea0SLionel Sambuc  *
5ebfedea0SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
6ebfedea0SLionel Sambuc  * by Alistair Crooks (agc@NetBSD.org)
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
12ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
13ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
14ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
15ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
16ebfedea0SLionel Sambuc  *
17ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18ebfedea0SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19ebfedea0SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21ebfedea0SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22ebfedea0SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23ebfedea0SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24ebfedea0SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25ebfedea0SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27ebfedea0SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
28ebfedea0SLionel Sambuc  */
29ebfedea0SLionel Sambuc 
30ebfedea0SLionel Sambuc /* Command line program to perform netpgp operations */
31ebfedea0SLionel Sambuc #include <sys/types.h>
32ebfedea0SLionel Sambuc #include <sys/param.h>
33ebfedea0SLionel Sambuc #include <sys/stat.h>
34ebfedea0SLionel Sambuc 
35ebfedea0SLionel Sambuc #include <getopt.h>
36ebfedea0SLionel Sambuc #include <regex.h>
37ebfedea0SLionel Sambuc #include <stdarg.h>
38ebfedea0SLionel Sambuc #include <stdio.h>
39ebfedea0SLionel Sambuc #include <stdlib.h>
40ebfedea0SLionel Sambuc #include <string.h>
41ebfedea0SLionel Sambuc #include <unistd.h>
42ebfedea0SLionel Sambuc 
43ebfedea0SLionel Sambuc #include <mj.h>
44ebfedea0SLionel Sambuc #include <netpgp.h>
45ebfedea0SLionel Sambuc 
46ebfedea0SLionel Sambuc /*
47ebfedea0SLionel Sambuc  * 2048 is the absolute minimum, really - we should really look at
48ebfedea0SLionel Sambuc  * bumping this to 4096 or even higher - agc, 20090522
49ebfedea0SLionel Sambuc  */
50ebfedea0SLionel Sambuc #define DEFAULT_NUMBITS 2048
51ebfedea0SLionel Sambuc 
52ebfedea0SLionel Sambuc #define DEFAULT_HASH_ALG "SHA256"
53ebfedea0SLionel Sambuc 
54ebfedea0SLionel Sambuc static const char *usage =
55ebfedea0SLionel Sambuc 	" --help OR\n"
56ebfedea0SLionel Sambuc 	"\t--export-key [options] OR\n"
57ebfedea0SLionel Sambuc 	"\t--find-key [options] OR\n"
58ebfedea0SLionel Sambuc 	"\t--generate-key [options] OR\n"
59ebfedea0SLionel Sambuc 	"\t--import-key [options] OR\n"
60ebfedea0SLionel Sambuc 	"\t--list-keys [options] OR\n"
61ebfedea0SLionel Sambuc 	"\t--list-sigs [options] OR\n"
62ebfedea0SLionel Sambuc 	"\t--trusted-keys [options] OR\n"
63ebfedea0SLionel Sambuc 	"\t--get-key keyid [options] OR\n"
64ebfedea0SLionel Sambuc 	"\t--version\n"
65ebfedea0SLionel Sambuc 	"where options are:\n"
66ebfedea0SLionel Sambuc 	"\t[--cipher=<cipher name>] AND/OR\n"
67ebfedea0SLionel Sambuc 	"\t[--coredumps] AND/OR\n"
68ebfedea0SLionel Sambuc 	"\t[--hash=<hash alg>] AND/OR\n"
69ebfedea0SLionel Sambuc 	"\t[--homedir=<homedir>] AND/OR\n"
70ebfedea0SLionel Sambuc 	"\t[--keyring=<keyring>] AND/OR\n"
71ebfedea0SLionel Sambuc 	"\t[--userid=<userid>] AND/OR\n"
72ebfedea0SLionel Sambuc 	"\t[--verbose]\n";
73ebfedea0SLionel Sambuc 
74ebfedea0SLionel Sambuc enum optdefs {
75ebfedea0SLionel Sambuc 	/* commands */
76ebfedea0SLionel Sambuc 	LIST_KEYS = 260,
77ebfedea0SLionel Sambuc 	LIST_SIGS,
78ebfedea0SLionel Sambuc 	FIND_KEY,
79ebfedea0SLionel Sambuc 	EXPORT_KEY,
80ebfedea0SLionel Sambuc 	IMPORT_KEY,
81ebfedea0SLionel Sambuc 	GENERATE_KEY,
82ebfedea0SLionel Sambuc 	VERSION_CMD,
83ebfedea0SLionel Sambuc 	HELP_CMD,
84ebfedea0SLionel Sambuc 	GET_KEY,
85ebfedea0SLionel Sambuc 	TRUSTED_KEYS,
86ebfedea0SLionel Sambuc 
87ebfedea0SLionel Sambuc 	/* options */
88ebfedea0SLionel Sambuc 	SSHKEYS,
89ebfedea0SLionel Sambuc 	KEYRING,
90ebfedea0SLionel Sambuc 	USERID,
91ebfedea0SLionel Sambuc 	HOMEDIR,
92ebfedea0SLionel Sambuc 	NUMBITS,
93ebfedea0SLionel Sambuc 	HASH_ALG,
94ebfedea0SLionel Sambuc 	VERBOSE,
95ebfedea0SLionel Sambuc 	COREDUMPS,
96ebfedea0SLionel Sambuc 	PASSWDFD,
97ebfedea0SLionel Sambuc 	RESULTS,
98ebfedea0SLionel Sambuc 	SSHKEYFILE,
99ebfedea0SLionel Sambuc 	CIPHER,
100ebfedea0SLionel Sambuc 	FORMAT,
101ebfedea0SLionel Sambuc 
102ebfedea0SLionel Sambuc 	/* debug */
103ebfedea0SLionel Sambuc 	OPS_DEBUG
104ebfedea0SLionel Sambuc 
105ebfedea0SLionel Sambuc };
106ebfedea0SLionel Sambuc 
107ebfedea0SLionel Sambuc #define EXIT_ERROR	2
108ebfedea0SLionel Sambuc 
109ebfedea0SLionel Sambuc static struct option options[] = {
110ebfedea0SLionel Sambuc 	/* key-management commands */
111ebfedea0SLionel Sambuc 	{"list-keys",	no_argument,		NULL,	LIST_KEYS},
112ebfedea0SLionel Sambuc 	{"list-sigs",	no_argument,		NULL,	LIST_SIGS},
113ebfedea0SLionel Sambuc 	{"find-key",	optional_argument,	NULL,	FIND_KEY},
114ebfedea0SLionel Sambuc 	{"export",	no_argument,		NULL,	EXPORT_KEY},
115ebfedea0SLionel Sambuc 	{"export-key",	no_argument,		NULL,	EXPORT_KEY},
116ebfedea0SLionel Sambuc 	{"import",	no_argument,		NULL,	IMPORT_KEY},
117ebfedea0SLionel Sambuc 	{"import-key",	no_argument,		NULL,	IMPORT_KEY},
118ebfedea0SLionel Sambuc 	{"gen",		optional_argument,	NULL,	GENERATE_KEY},
119ebfedea0SLionel Sambuc 	{"gen-key",	optional_argument,	NULL,	GENERATE_KEY},
120ebfedea0SLionel Sambuc 	{"generate",	optional_argument,	NULL,	GENERATE_KEY},
121ebfedea0SLionel Sambuc 	{"generate-key", optional_argument,	NULL,	GENERATE_KEY},
122ebfedea0SLionel Sambuc 	{"get-key", 	no_argument,		NULL,	GET_KEY},
123ebfedea0SLionel Sambuc 	{"trusted-keys",optional_argument,	NULL,	TRUSTED_KEYS},
124ebfedea0SLionel Sambuc 	{"trusted",	optional_argument,	NULL,	TRUSTED_KEYS},
125ebfedea0SLionel Sambuc 	/* debugging commands */
126ebfedea0SLionel Sambuc 	{"help",	no_argument,		NULL,	HELP_CMD},
127ebfedea0SLionel Sambuc 	{"version",	no_argument,		NULL,	VERSION_CMD},
128ebfedea0SLionel Sambuc 	{"debug",	required_argument, 	NULL,	OPS_DEBUG},
129ebfedea0SLionel Sambuc 	/* options */
130ebfedea0SLionel Sambuc 	{"coredumps",	no_argument, 		NULL,	COREDUMPS},
131ebfedea0SLionel Sambuc 	{"keyring",	required_argument, 	NULL,	KEYRING},
132ebfedea0SLionel Sambuc 	{"userid",	required_argument, 	NULL,	USERID},
133ebfedea0SLionel Sambuc 	{"format",	required_argument, 	NULL,	FORMAT},
134ebfedea0SLionel Sambuc 	{"hash-alg",	required_argument, 	NULL,	HASH_ALG},
135ebfedea0SLionel Sambuc 	{"hash",	required_argument, 	NULL,	HASH_ALG},
136ebfedea0SLionel Sambuc 	{"algorithm",	required_argument, 	NULL,	HASH_ALG},
137ebfedea0SLionel Sambuc 	{"home",	required_argument, 	NULL,	HOMEDIR},
138ebfedea0SLionel Sambuc 	{"homedir",	required_argument, 	NULL,	HOMEDIR},
139ebfedea0SLionel Sambuc 	{"numbits",	required_argument, 	NULL,	NUMBITS},
140ebfedea0SLionel Sambuc 	{"ssh",		no_argument, 		NULL,	SSHKEYS},
141ebfedea0SLionel Sambuc 	{"ssh-keys",	no_argument, 		NULL,	SSHKEYS},
142ebfedea0SLionel Sambuc 	{"sshkeyfile",	required_argument, 	NULL,	SSHKEYFILE},
143ebfedea0SLionel Sambuc 	{"verbose",	no_argument, 		NULL,	VERBOSE},
144ebfedea0SLionel Sambuc 	{"pass-fd",	required_argument, 	NULL,	PASSWDFD},
145ebfedea0SLionel Sambuc 	{"results",	required_argument, 	NULL,	RESULTS},
146ebfedea0SLionel Sambuc 	{"cipher",	required_argument, 	NULL,	CIPHER},
147ebfedea0SLionel Sambuc 	{ NULL,		0,			NULL,	0},
148ebfedea0SLionel Sambuc };
149ebfedea0SLionel Sambuc 
150ebfedea0SLionel Sambuc /* gather up program variables into one struct */
151ebfedea0SLionel Sambuc typedef struct prog_t {
152ebfedea0SLionel Sambuc 	char	 keyring[MAXPATHLEN + 1];	/* name of keyring */
153ebfedea0SLionel Sambuc 	char	*progname;			/* program name */
154ebfedea0SLionel Sambuc 	int	 numbits;			/* # of bits */
155ebfedea0SLionel Sambuc 	int	 cmd;				/* netpgpkeys command */
156ebfedea0SLionel Sambuc } prog_t;
157ebfedea0SLionel Sambuc 
158ebfedea0SLionel Sambuc 
159ebfedea0SLionel Sambuc /* print a usage message */
160ebfedea0SLionel Sambuc static void
print_usage(const char * usagemsg,char * progname)161ebfedea0SLionel Sambuc print_usage(const char *usagemsg, char *progname)
162ebfedea0SLionel Sambuc {
163ebfedea0SLionel Sambuc 	(void) fprintf(stderr,
164ebfedea0SLionel Sambuc 	"%s\nAll bug reports, praise and chocolate, please, to:\n%s\n",
165ebfedea0SLionel Sambuc 				netpgp_get_info("version"),
166ebfedea0SLionel Sambuc 				netpgp_get_info("maintainer"));
167ebfedea0SLionel Sambuc 	(void) fprintf(stderr, "Usage: %s COMMAND OPTIONS:\n%s %s",
168ebfedea0SLionel Sambuc 		progname, progname, usagemsg);
169ebfedea0SLionel Sambuc }
170ebfedea0SLionel Sambuc 
171ebfedea0SLionel Sambuc /* match keys, decoding from json if we do find any */
172ebfedea0SLionel Sambuc static int
match_keys(netpgp_t * netpgp,FILE * fp,char * f,const int psigs)173ebfedea0SLionel Sambuc match_keys(netpgp_t *netpgp, FILE *fp, char *f, const int psigs)
174ebfedea0SLionel Sambuc {
175ebfedea0SLionel Sambuc 	char	*json;
176ebfedea0SLionel Sambuc 	int	 idc;
177ebfedea0SLionel Sambuc 
178ebfedea0SLionel Sambuc 	if (f == NULL) {
179ebfedea0SLionel Sambuc 		if (!netpgp_list_keys_json(netpgp, &json, psigs)) {
180ebfedea0SLionel Sambuc 			return 0;
181ebfedea0SLionel Sambuc 		}
182ebfedea0SLionel Sambuc 	} else {
183ebfedea0SLionel Sambuc 		if (netpgp_match_keys_json(netpgp, &json, f,
184ebfedea0SLionel Sambuc 				netpgp_getvar(netpgp, "format"), psigs) == 0) {
185ebfedea0SLionel Sambuc 			return 0;
186ebfedea0SLionel Sambuc 		}
187ebfedea0SLionel Sambuc 	}
188ebfedea0SLionel Sambuc 	idc = netpgp_format_json(fp, json, psigs);
189ebfedea0SLionel Sambuc 	/* clean up */
190ebfedea0SLionel Sambuc 	free(json);
191ebfedea0SLionel Sambuc 	return idc;
192ebfedea0SLionel Sambuc }
193ebfedea0SLionel Sambuc 
194ebfedea0SLionel Sambuc /* do a command once for a specified file 'f' */
195ebfedea0SLionel Sambuc static int
netpgp_cmd(netpgp_t * netpgp,prog_t * p,char * f)196ebfedea0SLionel Sambuc netpgp_cmd(netpgp_t *netpgp, prog_t *p, char *f)
197ebfedea0SLionel Sambuc {
198ebfedea0SLionel Sambuc 	char	*key;
199*0a6a1f1dSLionel Sambuc 	char	*s;
200ebfedea0SLionel Sambuc 
201ebfedea0SLionel Sambuc 	switch (p->cmd) {
202ebfedea0SLionel Sambuc 	case LIST_KEYS:
203ebfedea0SLionel Sambuc 	case LIST_SIGS:
204ebfedea0SLionel Sambuc 		return match_keys(netpgp, stdout, f, (p->cmd == LIST_SIGS));
205ebfedea0SLionel Sambuc 	case FIND_KEY:
206ebfedea0SLionel Sambuc 		if ((key = f) == NULL) {
207ebfedea0SLionel Sambuc 			key = netpgp_getvar(netpgp, "userid");
208ebfedea0SLionel Sambuc 		}
209ebfedea0SLionel Sambuc 		return netpgp_find_key(netpgp, key);
210ebfedea0SLionel Sambuc 	case EXPORT_KEY:
211ebfedea0SLionel Sambuc 		if ((key = f) == NULL) {
212ebfedea0SLionel Sambuc 			key = netpgp_getvar(netpgp, "userid");
213ebfedea0SLionel Sambuc 		}
214ebfedea0SLionel Sambuc 		if (key) {
215*0a6a1f1dSLionel Sambuc 			if ((s = netpgp_export_key(netpgp, key)) != NULL) {
216*0a6a1f1dSLionel Sambuc 				printf("%s", s);
217ebfedea0SLionel Sambuc 				return 1;
218ebfedea0SLionel Sambuc 			}
219*0a6a1f1dSLionel Sambuc 		}
220ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "key '%s' not found\n", f);
221ebfedea0SLionel Sambuc 		return 0;
222ebfedea0SLionel Sambuc 	case IMPORT_KEY:
223ebfedea0SLionel Sambuc 		return netpgp_import_key(netpgp, f);
224ebfedea0SLionel Sambuc 	case GENERATE_KEY:
225ebfedea0SLionel Sambuc 		return netpgp_generate_key(netpgp, f, p->numbits);
226ebfedea0SLionel Sambuc 	case GET_KEY:
227ebfedea0SLionel Sambuc 		key = netpgp_get_key(netpgp, f, netpgp_getvar(netpgp, "format"));
228ebfedea0SLionel Sambuc 		if (key) {
229ebfedea0SLionel Sambuc 			printf("%s", key);
230ebfedea0SLionel Sambuc 			return 1;
231ebfedea0SLionel Sambuc 		}
232ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "key '%s' not found\n", f);
233ebfedea0SLionel Sambuc 		return 0;
234ebfedea0SLionel Sambuc 	case TRUSTED_KEYS:
235ebfedea0SLionel Sambuc 		return netpgp_match_pubkeys(netpgp, f, stdout);
236ebfedea0SLionel Sambuc 	case HELP_CMD:
237ebfedea0SLionel Sambuc 	default:
238ebfedea0SLionel Sambuc 		print_usage(usage, p->progname);
239ebfedea0SLionel Sambuc 		exit(EXIT_SUCCESS);
240ebfedea0SLionel Sambuc 	}
241ebfedea0SLionel Sambuc }
242ebfedea0SLionel Sambuc 
243ebfedea0SLionel Sambuc /* set the option */
244ebfedea0SLionel Sambuc static int
setoption(netpgp_t * netpgp,prog_t * p,int val,char * arg,int * homeset)245ebfedea0SLionel Sambuc setoption(netpgp_t *netpgp, prog_t *p, int val, char *arg, int *homeset)
246ebfedea0SLionel Sambuc {
247ebfedea0SLionel Sambuc 	switch (val) {
248ebfedea0SLionel Sambuc 	case COREDUMPS:
249ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "coredumps", "allowed");
250ebfedea0SLionel Sambuc 		break;
251ebfedea0SLionel Sambuc 	case GENERATE_KEY:
252ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "userid checks", "skip");
253ebfedea0SLionel Sambuc 		p->cmd = val;
254ebfedea0SLionel Sambuc 		break;
255ebfedea0SLionel Sambuc 	case LIST_KEYS:
256ebfedea0SLionel Sambuc 	case LIST_SIGS:
257ebfedea0SLionel Sambuc 	case FIND_KEY:
258ebfedea0SLionel Sambuc 	case EXPORT_KEY:
259ebfedea0SLionel Sambuc 	case IMPORT_KEY:
260ebfedea0SLionel Sambuc 	case GET_KEY:
261ebfedea0SLionel Sambuc 	case TRUSTED_KEYS:
262ebfedea0SLionel Sambuc 	case HELP_CMD:
263ebfedea0SLionel Sambuc 		p->cmd = val;
264ebfedea0SLionel Sambuc 		break;
265ebfedea0SLionel Sambuc 	case VERSION_CMD:
266ebfedea0SLionel Sambuc 		printf(
267ebfedea0SLionel Sambuc "%s\nAll bug reports, praise and chocolate, please, to:\n%s\n",
268ebfedea0SLionel Sambuc 			netpgp_get_info("version"),
269ebfedea0SLionel Sambuc 			netpgp_get_info("maintainer"));
270ebfedea0SLionel Sambuc 		exit(EXIT_SUCCESS);
271ebfedea0SLionel Sambuc 		/* options */
272ebfedea0SLionel Sambuc 	case SSHKEYS:
273ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "ssh keys", "1");
274ebfedea0SLionel Sambuc 		break;
275ebfedea0SLionel Sambuc 	case KEYRING:
276ebfedea0SLionel Sambuc 		if (arg == NULL) {
277ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
278ebfedea0SLionel Sambuc 				"No keyring argument provided\n");
279ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
280ebfedea0SLionel Sambuc 		}
281ebfedea0SLionel Sambuc 		snprintf(p->keyring, sizeof(p->keyring), "%s", arg);
282ebfedea0SLionel Sambuc 		break;
283ebfedea0SLionel Sambuc 	case USERID:
284ebfedea0SLionel Sambuc 		if (optarg == NULL) {
285ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
286ebfedea0SLionel Sambuc 				"no userid argument provided\n");
287ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
288ebfedea0SLionel Sambuc 		}
289ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "userid", arg);
290ebfedea0SLionel Sambuc 		break;
291ebfedea0SLionel Sambuc 	case VERBOSE:
292ebfedea0SLionel Sambuc 		netpgp_incvar(netpgp, "verbose", 1);
293ebfedea0SLionel Sambuc 		break;
294ebfedea0SLionel Sambuc 	case HOMEDIR:
295ebfedea0SLionel Sambuc 		if (arg == NULL) {
296ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
297ebfedea0SLionel Sambuc 			"no home directory argument provided\n");
298ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
299ebfedea0SLionel Sambuc 		}
300ebfedea0SLionel Sambuc 		netpgp_set_homedir(netpgp, arg, NULL, 0);
301ebfedea0SLionel Sambuc 		*homeset = 1;
302ebfedea0SLionel Sambuc 		break;
303ebfedea0SLionel Sambuc 	case NUMBITS:
304ebfedea0SLionel Sambuc 		if (arg == NULL) {
305ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
306ebfedea0SLionel Sambuc 			"no number of bits argument provided\n");
307ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
308ebfedea0SLionel Sambuc 		}
309ebfedea0SLionel Sambuc 		p->numbits = atoi(arg);
310ebfedea0SLionel Sambuc 		break;
311ebfedea0SLionel Sambuc 	case HASH_ALG:
312ebfedea0SLionel Sambuc 		if (arg == NULL) {
313ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
314ebfedea0SLionel Sambuc 			"No hash algorithm argument provided\n");
315ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
316ebfedea0SLionel Sambuc 		}
317ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "hash", arg);
318ebfedea0SLionel Sambuc 		break;
319ebfedea0SLionel Sambuc 	case PASSWDFD:
320ebfedea0SLionel Sambuc 		if (arg == NULL) {
321ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
322ebfedea0SLionel Sambuc 			"no pass-fd argument provided\n");
323ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
324ebfedea0SLionel Sambuc 		}
325ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "pass-fd", arg);
326ebfedea0SLionel Sambuc 		break;
327ebfedea0SLionel Sambuc 	case RESULTS:
328ebfedea0SLionel Sambuc 		if (arg == NULL) {
329ebfedea0SLionel Sambuc 			(void) fprintf(stderr,
330ebfedea0SLionel Sambuc 			"No output filename argument provided\n");
331ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
332ebfedea0SLionel Sambuc 		}
333ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "res", arg);
334ebfedea0SLionel Sambuc 		break;
335ebfedea0SLionel Sambuc 	case SSHKEYFILE:
336ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "ssh keys", "1");
337ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "sshkeyfile", arg);
338ebfedea0SLionel Sambuc 		break;
339ebfedea0SLionel Sambuc 	case FORMAT:
340ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "format", arg);
341ebfedea0SLionel Sambuc 		break;
342ebfedea0SLionel Sambuc 	case CIPHER:
343ebfedea0SLionel Sambuc 		netpgp_setvar(netpgp, "cipher", arg);
344ebfedea0SLionel Sambuc 		break;
345ebfedea0SLionel Sambuc 	case OPS_DEBUG:
346ebfedea0SLionel Sambuc 		netpgp_set_debug(arg);
347ebfedea0SLionel Sambuc 		break;
348ebfedea0SLionel Sambuc 	default:
349ebfedea0SLionel Sambuc 		p->cmd = HELP_CMD;
350ebfedea0SLionel Sambuc 		break;
351ebfedea0SLionel Sambuc 	}
352ebfedea0SLionel Sambuc 	return 1;
353ebfedea0SLionel Sambuc }
354ebfedea0SLionel Sambuc 
355ebfedea0SLionel Sambuc /* we have -o option=value -- parse, and process */
356ebfedea0SLionel Sambuc static int
parse_option(netpgp_t * netpgp,prog_t * p,const char * s,int * homeset)357ebfedea0SLionel Sambuc parse_option(netpgp_t *netpgp, prog_t *p, const char *s, int *homeset)
358ebfedea0SLionel Sambuc {
359ebfedea0SLionel Sambuc 	static regex_t	 opt;
360ebfedea0SLionel Sambuc 	struct option	*op;
361ebfedea0SLionel Sambuc 	static int	 compiled;
362ebfedea0SLionel Sambuc 	regmatch_t	 matches[10];
363ebfedea0SLionel Sambuc 	char		 option[128];
364ebfedea0SLionel Sambuc 	char		 value[128];
365ebfedea0SLionel Sambuc 
366ebfedea0SLionel Sambuc 	if (!compiled) {
367ebfedea0SLionel Sambuc 		compiled = 1;
368ebfedea0SLionel Sambuc 		(void) regcomp(&opt, "([^=]{1,128})(=(.*))?", REG_EXTENDED);
369ebfedea0SLionel Sambuc 	}
370ebfedea0SLionel Sambuc 	if (regexec(&opt, s, 10, matches, 0) == 0) {
371ebfedea0SLionel Sambuc 		(void) snprintf(option, sizeof(option), "%.*s",
372ebfedea0SLionel Sambuc 			(int)(matches[1].rm_eo - matches[1].rm_so), &s[matches[1].rm_so]);
373ebfedea0SLionel Sambuc 		if (matches[2].rm_so > 0) {
374ebfedea0SLionel Sambuc 			(void) snprintf(value, sizeof(value), "%.*s",
375ebfedea0SLionel Sambuc 				(int)(matches[3].rm_eo - matches[3].rm_so), &s[matches[3].rm_so]);
376ebfedea0SLionel Sambuc 		} else {
377ebfedea0SLionel Sambuc 			value[0] = 0x0;
378ebfedea0SLionel Sambuc 		}
379ebfedea0SLionel Sambuc 		for (op = options ; op->name ; op++) {
380ebfedea0SLionel Sambuc 			if (strcmp(op->name, option) == 0) {
381ebfedea0SLionel Sambuc 				return setoption(netpgp, p, op->val, value, homeset);
382ebfedea0SLionel Sambuc 			}
383ebfedea0SLionel Sambuc 		}
384ebfedea0SLionel Sambuc 	}
385ebfedea0SLionel Sambuc 	return 0;
386ebfedea0SLionel Sambuc }
387ebfedea0SLionel Sambuc 
388ebfedea0SLionel Sambuc int
main(int argc,char ** argv)389ebfedea0SLionel Sambuc main(int argc, char **argv)
390ebfedea0SLionel Sambuc {
391ebfedea0SLionel Sambuc 	struct stat	st;
392ebfedea0SLionel Sambuc 	netpgp_t	netpgp;
393ebfedea0SLionel Sambuc 	prog_t          p;
394ebfedea0SLionel Sambuc 	int             homeset;
395ebfedea0SLionel Sambuc 	int             optindex;
396ebfedea0SLionel Sambuc 	int             ret;
397ebfedea0SLionel Sambuc 	int             ch;
398ebfedea0SLionel Sambuc 	int             i;
399ebfedea0SLionel Sambuc 
400ebfedea0SLionel Sambuc 	(void) memset(&p, 0x0, sizeof(p));
401ebfedea0SLionel Sambuc 	(void) memset(&netpgp, 0x0, sizeof(netpgp));
402ebfedea0SLionel Sambuc 	homeset = 0;
403ebfedea0SLionel Sambuc 	p.progname = argv[0];
404ebfedea0SLionel Sambuc 	p.numbits = DEFAULT_NUMBITS;
405ebfedea0SLionel Sambuc 	if (argc < 2) {
406ebfedea0SLionel Sambuc 		print_usage(usage, p.progname);
407ebfedea0SLionel Sambuc 		exit(EXIT_ERROR);
408ebfedea0SLionel Sambuc 	}
409ebfedea0SLionel Sambuc 	/* set some defaults */
410ebfedea0SLionel Sambuc 	netpgp_setvar(&netpgp, "sshkeydir", "/etc/ssh");
411ebfedea0SLionel Sambuc 	netpgp_setvar(&netpgp, "res", "<stdout>");
412ebfedea0SLionel Sambuc 	netpgp_setvar(&netpgp, "hash", DEFAULT_HASH_ALG);
413ebfedea0SLionel Sambuc 	netpgp_setvar(&netpgp, "format", "human");
414ebfedea0SLionel Sambuc 	optindex = 0;
415ebfedea0SLionel Sambuc 	while ((ch = getopt_long(argc, argv, "S:Vglo:s", options, &optindex)) != -1) {
416ebfedea0SLionel Sambuc 		if (ch >= LIST_KEYS) {
417ebfedea0SLionel Sambuc 			/* getopt_long returns 0 for long options */
418ebfedea0SLionel Sambuc 			if (!setoption(&netpgp, &p, options[optindex].val, optarg, &homeset)) {
419ebfedea0SLionel Sambuc 				(void) fprintf(stderr, "Bad setoption result %d\n", ch);
420ebfedea0SLionel Sambuc 			}
421ebfedea0SLionel Sambuc 		} else {
422ebfedea0SLionel Sambuc 			switch (ch) {
423ebfedea0SLionel Sambuc 			case 'S':
424ebfedea0SLionel Sambuc 				netpgp_setvar(&netpgp, "ssh keys", "1");
425ebfedea0SLionel Sambuc 				netpgp_setvar(&netpgp, "sshkeyfile", optarg);
426ebfedea0SLionel Sambuc 				break;
427ebfedea0SLionel Sambuc 			case 'V':
428ebfedea0SLionel Sambuc 				printf(
429ebfedea0SLionel Sambuc 	"%s\nAll bug reports, praise and chocolate, please, to:\n%s\n",
430ebfedea0SLionel Sambuc 					netpgp_get_info("version"),
431ebfedea0SLionel Sambuc 					netpgp_get_info("maintainer"));
432ebfedea0SLionel Sambuc 				exit(EXIT_SUCCESS);
433ebfedea0SLionel Sambuc 			case 'g':
434ebfedea0SLionel Sambuc 				p.cmd = GENERATE_KEY;
435ebfedea0SLionel Sambuc 				break;
436ebfedea0SLionel Sambuc 			case 'l':
437ebfedea0SLionel Sambuc 				p.cmd = LIST_KEYS;
438ebfedea0SLionel Sambuc 				break;
439ebfedea0SLionel Sambuc 			case 'o':
440ebfedea0SLionel Sambuc 				if (!parse_option(&netpgp, &p, optarg, &homeset)) {
441ebfedea0SLionel Sambuc 					(void) fprintf(stderr, "Bad parse_option\n");
442ebfedea0SLionel Sambuc 				}
443ebfedea0SLionel Sambuc 				break;
444ebfedea0SLionel Sambuc 			case 's':
445ebfedea0SLionel Sambuc 				p.cmd = LIST_SIGS;
446ebfedea0SLionel Sambuc 				break;
447ebfedea0SLionel Sambuc 			default:
448ebfedea0SLionel Sambuc 				p.cmd = HELP_CMD;
449ebfedea0SLionel Sambuc 				break;
450ebfedea0SLionel Sambuc 			}
451ebfedea0SLionel Sambuc 		}
452ebfedea0SLionel Sambuc 	}
453ebfedea0SLionel Sambuc 	if (!homeset) {
454ebfedea0SLionel Sambuc 		netpgp_set_homedir(&netpgp, getenv("HOME"),
455ebfedea0SLionel Sambuc 			netpgp_getvar(&netpgp, "ssh keys") ? "/.ssh" : "/.gnupg", 1);
456ebfedea0SLionel Sambuc 	}
457ebfedea0SLionel Sambuc 	/* initialise, and read keys from file */
458ebfedea0SLionel Sambuc 	if (!netpgp_init(&netpgp)) {
459ebfedea0SLionel Sambuc 		if (stat(netpgp_getvar(&netpgp, "homedir"), &st) < 0) {
460ebfedea0SLionel Sambuc 			(void) mkdir(netpgp_getvar(&netpgp, "homedir"), 0700);
461ebfedea0SLionel Sambuc 		}
462ebfedea0SLionel Sambuc 		if (stat(netpgp_getvar(&netpgp, "homedir"), &st) < 0) {
463ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "can't create home directory '%s'\n",
464ebfedea0SLionel Sambuc 				netpgp_getvar(&netpgp, "homedir"));
465ebfedea0SLionel Sambuc 			exit(EXIT_ERROR);
466ebfedea0SLionel Sambuc 		}
467ebfedea0SLionel Sambuc 	}
468ebfedea0SLionel Sambuc 	/* now do the required action for each of the command line args */
469ebfedea0SLionel Sambuc 	ret = EXIT_SUCCESS;
470ebfedea0SLionel Sambuc 	if (optind == argc) {
471ebfedea0SLionel Sambuc 		if (!netpgp_cmd(&netpgp, &p, NULL)) {
472ebfedea0SLionel Sambuc 			ret = EXIT_FAILURE;
473ebfedea0SLionel Sambuc 		}
474ebfedea0SLionel Sambuc 	} else {
475ebfedea0SLionel Sambuc 		for (i = optind; i < argc; i++) {
476ebfedea0SLionel Sambuc 			if (!netpgp_cmd(&netpgp, &p, argv[i])) {
477ebfedea0SLionel Sambuc 				ret = EXIT_FAILURE;
478ebfedea0SLionel Sambuc 			}
479ebfedea0SLionel Sambuc 		}
480ebfedea0SLionel Sambuc 	}
481ebfedea0SLionel Sambuc 	netpgp_end(&netpgp);
482ebfedea0SLionel Sambuc 	exit(ret);
483ebfedea0SLionel Sambuc }
484