PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/crypto/external/bsd/netpgp/dist/src/netpgpkeys/netpgpkeys.c

https://gitlab.com/storedmirrors/minix
C | 483 lines | 408 code | 24 blank | 51 comment | 57 complexity | ce74f93a91dce3b8d58eea017933d875 MD5 | raw file
  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. /* Command line program to perform netpgp operations */
  30. #include <sys/types.h>
  31. #include <sys/param.h>
  32. #include <sys/stat.h>
  33. #include <getopt.h>
  34. #include <regex.h>
  35. #include <stdarg.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <unistd.h>
  40. #include <mj.h>
  41. #include <netpgp.h>
  42. /*
  43. * 2048 is the absolute minimum, really - we should really look at
  44. * bumping this to 4096 or even higher - agc, 20090522
  45. */
  46. #define DEFAULT_NUMBITS 2048
  47. #define DEFAULT_HASH_ALG "SHA256"
  48. static const char *usage =
  49. " --help OR\n"
  50. "\t--export-key [options] OR\n"
  51. "\t--find-key [options] OR\n"
  52. "\t--generate-key [options] OR\n"
  53. "\t--import-key [options] OR\n"
  54. "\t--list-keys [options] OR\n"
  55. "\t--list-sigs [options] OR\n"
  56. "\t--trusted-keys [options] OR\n"
  57. "\t--get-key keyid [options] OR\n"
  58. "\t--version\n"
  59. "where options are:\n"
  60. "\t[--cipher=<cipher name>] AND/OR\n"
  61. "\t[--coredumps] AND/OR\n"
  62. "\t[--hash=<hash alg>] AND/OR\n"
  63. "\t[--homedir=<homedir>] AND/OR\n"
  64. "\t[--keyring=<keyring>] AND/OR\n"
  65. "\t[--userid=<userid>] AND/OR\n"
  66. "\t[--verbose]\n";
  67. enum optdefs {
  68. /* commands */
  69. LIST_KEYS = 260,
  70. LIST_SIGS,
  71. FIND_KEY,
  72. EXPORT_KEY,
  73. IMPORT_KEY,
  74. GENERATE_KEY,
  75. VERSION_CMD,
  76. HELP_CMD,
  77. GET_KEY,
  78. TRUSTED_KEYS,
  79. /* options */
  80. SSHKEYS,
  81. KEYRING,
  82. USERID,
  83. HOMEDIR,
  84. NUMBITS,
  85. HASH_ALG,
  86. VERBOSE,
  87. COREDUMPS,
  88. PASSWDFD,
  89. RESULTS,
  90. SSHKEYFILE,
  91. CIPHER,
  92. FORMAT,
  93. /* debug */
  94. OPS_DEBUG
  95. };
  96. #define EXIT_ERROR 2
  97. static struct option options[] = {
  98. /* key-management commands */
  99. {"list-keys", no_argument, NULL, LIST_KEYS},
  100. {"list-sigs", no_argument, NULL, LIST_SIGS},
  101. {"find-key", optional_argument, NULL, FIND_KEY},
  102. {"export", no_argument, NULL, EXPORT_KEY},
  103. {"export-key", no_argument, NULL, EXPORT_KEY},
  104. {"import", no_argument, NULL, IMPORT_KEY},
  105. {"import-key", no_argument, NULL, IMPORT_KEY},
  106. {"gen", optional_argument, NULL, GENERATE_KEY},
  107. {"gen-key", optional_argument, NULL, GENERATE_KEY},
  108. {"generate", optional_argument, NULL, GENERATE_KEY},
  109. {"generate-key", optional_argument, NULL, GENERATE_KEY},
  110. {"get-key", no_argument, NULL, GET_KEY},
  111. {"trusted-keys",optional_argument, NULL, TRUSTED_KEYS},
  112. {"trusted", optional_argument, NULL, TRUSTED_KEYS},
  113. /* debugging commands */
  114. {"help", no_argument, NULL, HELP_CMD},
  115. {"version", no_argument, NULL, VERSION_CMD},
  116. {"debug", required_argument, NULL, OPS_DEBUG},
  117. /* options */
  118. {"coredumps", no_argument, NULL, COREDUMPS},
  119. {"keyring", required_argument, NULL, KEYRING},
  120. {"userid", required_argument, NULL, USERID},
  121. {"format", required_argument, NULL, FORMAT},
  122. {"hash-alg", required_argument, NULL, HASH_ALG},
  123. {"hash", required_argument, NULL, HASH_ALG},
  124. {"algorithm", required_argument, NULL, HASH_ALG},
  125. {"home", required_argument, NULL, HOMEDIR},
  126. {"homedir", required_argument, NULL, HOMEDIR},
  127. {"numbits", required_argument, NULL, NUMBITS},
  128. {"ssh", no_argument, NULL, SSHKEYS},
  129. {"ssh-keys", no_argument, NULL, SSHKEYS},
  130. {"sshkeyfile", required_argument, NULL, SSHKEYFILE},
  131. {"verbose", no_argument, NULL, VERBOSE},
  132. {"pass-fd", required_argument, NULL, PASSWDFD},
  133. {"results", required_argument, NULL, RESULTS},
  134. {"cipher", required_argument, NULL, CIPHER},
  135. { NULL, 0, NULL, 0},
  136. };
  137. /* gather up program variables into one struct */
  138. typedef struct prog_t {
  139. char keyring[MAXPATHLEN + 1]; /* name of keyring */
  140. char *progname; /* program name */
  141. int numbits; /* # of bits */
  142. int cmd; /* netpgpkeys command */
  143. } prog_t;
  144. /* print a usage message */
  145. static void
  146. print_usage(const char *usagemsg, char *progname)
  147. {
  148. (void) fprintf(stderr,
  149. "%s\nAll bug reports, praise and chocolate, please, to:\n%s\n",
  150. netpgp_get_info("version"),
  151. netpgp_get_info("maintainer"));
  152. (void) fprintf(stderr, "Usage: %s COMMAND OPTIONS:\n%s %s",
  153. progname, progname, usagemsg);
  154. }
  155. /* match keys, decoding from json if we do find any */
  156. static int
  157. match_keys(netpgp_t *netpgp, FILE *fp, char *f, const int psigs)
  158. {
  159. char *json;
  160. int idc;
  161. if (f == NULL) {
  162. if (!netpgp_list_keys_json(netpgp, &json, psigs)) {
  163. return 0;
  164. }
  165. } else {
  166. if (netpgp_match_keys_json(netpgp, &json, f,
  167. netpgp_getvar(netpgp, "format"), psigs) == 0) {
  168. return 0;
  169. }
  170. }
  171. idc = netpgp_format_json(fp, json, psigs);
  172. /* clean up */
  173. free(json);
  174. return idc;
  175. }
  176. /* do a command once for a specified file 'f' */
  177. static int
  178. netpgp_cmd(netpgp_t *netpgp, prog_t *p, char *f)
  179. {
  180. char *key;
  181. char *s;
  182. switch (p->cmd) {
  183. case LIST_KEYS:
  184. case LIST_SIGS:
  185. return match_keys(netpgp, stdout, f, (p->cmd == LIST_SIGS));
  186. case FIND_KEY:
  187. if ((key = f) == NULL) {
  188. key = netpgp_getvar(netpgp, "userid");
  189. }
  190. return netpgp_find_key(netpgp, key);
  191. case EXPORT_KEY:
  192. if ((key = f) == NULL) {
  193. key = netpgp_getvar(netpgp, "userid");
  194. }
  195. if (key) {
  196. if ((s = netpgp_export_key(netpgp, key)) != NULL) {
  197. printf("%s", s);
  198. return 1;
  199. }
  200. }
  201. (void) fprintf(stderr, "key '%s' not found\n", f);
  202. return 0;
  203. case IMPORT_KEY:
  204. return netpgp_import_key(netpgp, f);
  205. case GENERATE_KEY:
  206. return netpgp_generate_key(netpgp, f, p->numbits);
  207. case GET_KEY:
  208. key = netpgp_get_key(netpgp, f, netpgp_getvar(netpgp, "format"));
  209. if (key) {
  210. printf("%s", key);
  211. return 1;
  212. }
  213. (void) fprintf(stderr, "key '%s' not found\n", f);
  214. return 0;
  215. case TRUSTED_KEYS:
  216. return netpgp_match_pubkeys(netpgp, f, stdout);
  217. case HELP_CMD:
  218. default:
  219. print_usage(usage, p->progname);
  220. exit(EXIT_SUCCESS);
  221. }
  222. }
  223. /* set the option */
  224. static int
  225. setoption(netpgp_t *netpgp, prog_t *p, int val, char *arg, int *homeset)
  226. {
  227. switch (val) {
  228. case COREDUMPS:
  229. netpgp_setvar(netpgp, "coredumps", "allowed");
  230. break;
  231. case GENERATE_KEY:
  232. netpgp_setvar(netpgp, "userid checks", "skip");
  233. p->cmd = val;
  234. break;
  235. case LIST_KEYS:
  236. case LIST_SIGS:
  237. case FIND_KEY:
  238. case EXPORT_KEY:
  239. case IMPORT_KEY:
  240. case GET_KEY:
  241. case TRUSTED_KEYS:
  242. case HELP_CMD:
  243. p->cmd = val;
  244. break;
  245. case VERSION_CMD:
  246. printf(
  247. "%s\nAll bug reports, praise and chocolate, please, to:\n%s\n",
  248. netpgp_get_info("version"),
  249. netpgp_get_info("maintainer"));
  250. exit(EXIT_SUCCESS);
  251. /* options */
  252. case SSHKEYS:
  253. netpgp_setvar(netpgp, "ssh keys", "1");
  254. break;
  255. case KEYRING:
  256. if (arg == NULL) {
  257. (void) fprintf(stderr,
  258. "No keyring argument provided\n");
  259. exit(EXIT_ERROR);
  260. }
  261. snprintf(p->keyring, sizeof(p->keyring), "%s", arg);
  262. break;
  263. case USERID:
  264. if (optarg == NULL) {
  265. (void) fprintf(stderr,
  266. "no userid argument provided\n");
  267. exit(EXIT_ERROR);
  268. }
  269. netpgp_setvar(netpgp, "userid", arg);
  270. break;
  271. case VERBOSE:
  272. netpgp_incvar(netpgp, "verbose", 1);
  273. break;
  274. case HOMEDIR:
  275. if (arg == NULL) {
  276. (void) fprintf(stderr,
  277. "no home directory argument provided\n");
  278. exit(EXIT_ERROR);
  279. }
  280. netpgp_set_homedir(netpgp, arg, NULL, 0);
  281. *homeset = 1;
  282. break;
  283. case NUMBITS:
  284. if (arg == NULL) {
  285. (void) fprintf(stderr,
  286. "no number of bits argument provided\n");
  287. exit(EXIT_ERROR);
  288. }
  289. p->numbits = atoi(arg);
  290. break;
  291. case HASH_ALG:
  292. if (arg == NULL) {
  293. (void) fprintf(stderr,
  294. "No hash algorithm argument provided\n");
  295. exit(EXIT_ERROR);
  296. }
  297. netpgp_setvar(netpgp, "hash", arg);
  298. break;
  299. case PASSWDFD:
  300. if (arg == NULL) {
  301. (void) fprintf(stderr,
  302. "no pass-fd argument provided\n");
  303. exit(EXIT_ERROR);
  304. }
  305. netpgp_setvar(netpgp, "pass-fd", arg);
  306. break;
  307. case RESULTS:
  308. if (arg == NULL) {
  309. (void) fprintf(stderr,
  310. "No output filename argument provided\n");
  311. exit(EXIT_ERROR);
  312. }
  313. netpgp_setvar(netpgp, "res", arg);
  314. break;
  315. case SSHKEYFILE:
  316. netpgp_setvar(netpgp, "ssh keys", "1");
  317. netpgp_setvar(netpgp, "sshkeyfile", arg);
  318. break;
  319. case FORMAT:
  320. netpgp_setvar(netpgp, "format", arg);
  321. break;
  322. case CIPHER:
  323. netpgp_setvar(netpgp, "cipher", arg);
  324. break;
  325. case OPS_DEBUG:
  326. netpgp_set_debug(arg);
  327. break;
  328. default:
  329. p->cmd = HELP_CMD;
  330. break;
  331. }
  332. return 1;
  333. }
  334. /* we have -o option=value -- parse, and process */
  335. static int
  336. parse_option(netpgp_t *netpgp, prog_t *p, const char *s, int *homeset)
  337. {
  338. static regex_t opt;
  339. struct option *op;
  340. static int compiled;
  341. regmatch_t matches[10];
  342. char option[128];
  343. char value[128];
  344. if (!compiled) {
  345. compiled = 1;
  346. (void) regcomp(&opt, "([^=]{1,128})(=(.*))?", REG_EXTENDED);
  347. }
  348. if (regexec(&opt, s, 10, matches, 0) == 0) {
  349. (void) snprintf(option, sizeof(option), "%.*s",
  350. (int)(matches[1].rm_eo - matches[1].rm_so), &s[matches[1].rm_so]);
  351. if (matches[2].rm_so > 0) {
  352. (void) snprintf(value, sizeof(value), "%.*s",
  353. (int)(matches[3].rm_eo - matches[3].rm_so), &s[matches[3].rm_so]);
  354. } else {
  355. value[0] = 0x0;
  356. }
  357. for (op = options ; op->name ; op++) {
  358. if (strcmp(op->name, option) == 0) {
  359. return setoption(netpgp, p, op->val, value, homeset);
  360. }
  361. }
  362. }
  363. return 0;
  364. }
  365. int
  366. main(int argc, char **argv)
  367. {
  368. struct stat st;
  369. netpgp_t netpgp;
  370. prog_t p;
  371. int homeset;
  372. int optindex;
  373. int ret;
  374. int ch;
  375. int i;
  376. (void) memset(&p, 0x0, sizeof(p));
  377. (void) memset(&netpgp, 0x0, sizeof(netpgp));
  378. homeset = 0;
  379. p.progname = argv[0];
  380. p.numbits = DEFAULT_NUMBITS;
  381. if (argc < 2) {
  382. print_usage(usage, p.progname);
  383. exit(EXIT_ERROR);
  384. }
  385. /* set some defaults */
  386. netpgp_setvar(&netpgp, "sshkeydir", "/etc/ssh");
  387. netpgp_setvar(&netpgp, "res", "<stdout>");
  388. netpgp_setvar(&netpgp, "hash", DEFAULT_HASH_ALG);
  389. netpgp_setvar(&netpgp, "format", "human");
  390. optindex = 0;
  391. while ((ch = getopt_long(argc, argv, "S:Vglo:s", options, &optindex)) != -1) {
  392. if (ch >= LIST_KEYS) {
  393. /* getopt_long returns 0 for long options */
  394. if (!setoption(&netpgp, &p, options[optindex].val, optarg, &homeset)) {
  395. (void) fprintf(stderr, "Bad setoption result %d\n", ch);
  396. }
  397. } else {
  398. switch (ch) {
  399. case 'S':
  400. netpgp_setvar(&netpgp, "ssh keys", "1");
  401. netpgp_setvar(&netpgp, "sshkeyfile", optarg);
  402. break;
  403. case 'V':
  404. printf(
  405. "%s\nAll bug reports, praise and chocolate, please, to:\n%s\n",
  406. netpgp_get_info("version"),
  407. netpgp_get_info("maintainer"));
  408. exit(EXIT_SUCCESS);
  409. case 'g':
  410. p.cmd = GENERATE_KEY;
  411. break;
  412. case 'l':
  413. p.cmd = LIST_KEYS;
  414. break;
  415. case 'o':
  416. if (!parse_option(&netpgp, &p, optarg, &homeset)) {
  417. (void) fprintf(stderr, "Bad parse_option\n");
  418. }
  419. break;
  420. case 's':
  421. p.cmd = LIST_SIGS;
  422. break;
  423. default:
  424. p.cmd = HELP_CMD;
  425. break;
  426. }
  427. }
  428. }
  429. if (!homeset) {
  430. netpgp_set_homedir(&netpgp, getenv("HOME"),
  431. netpgp_getvar(&netpgp, "ssh keys") ? "/.ssh" : "/.gnupg", 1);
  432. }
  433. /* initialise, and read keys from file */
  434. if (!netpgp_init(&netpgp)) {
  435. if (stat(netpgp_getvar(&netpgp, "homedir"), &st) < 0) {
  436. (void) mkdir(netpgp_getvar(&netpgp, "homedir"), 0700);
  437. }
  438. if (stat(netpgp_getvar(&netpgp, "homedir"), &st) < 0) {
  439. (void) fprintf(stderr, "can't create home directory '%s'\n",
  440. netpgp_getvar(&netpgp, "homedir"));
  441. exit(EXIT_ERROR);
  442. }
  443. }
  444. /* now do the required action for each of the command line args */
  445. ret = EXIT_SUCCESS;
  446. if (optind == argc) {
  447. if (!netpgp_cmd(&netpgp, &p, NULL)) {
  448. ret = EXIT_FAILURE;
  449. }
  450. } else {
  451. for (i = optind; i < argc; i++) {
  452. if (!netpgp_cmd(&netpgp, &p, argv[i])) {
  453. ret = EXIT_FAILURE;
  454. }
  455. }
  456. }
  457. netpgp_end(&netpgp);
  458. exit(ret);
  459. }