-/* $OpenBSD: spkac.c,v 1.2 2014/08/28 14:23:52 jsing Exp $ */
+/* $OpenBSD: spkac.c,v 1.3 2015/01/08 11:08:50 doug Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999. Based on an original idea by Massimiliano Pala
* (madwolf@openca.org).
#include <openssl/pem.h>
#include <openssl/x509.h>
-/* -in arg - input file - default stdin
- * -out arg - output file - default stdout
- */
+static struct {
+ char *challenge;
+#ifndef OPENSSL_NO_ENGINE
+ char *engine;
+#endif
+ char *infile;
+ char *keyfile;
+ int noout;
+ char *outfile;
+ char *passargin;
+ int pubkey;
+ char *spkac;
+ char *spksect;
+ int verify;
+} spkac_config;
+
+static struct option spkac_options[] = {
+ {
+ .name = "challenge",
+ .argname = "string",
+ .desc = "Specify challenge string if SPKAC is generated",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.challenge,
+ },
+#ifndef OPENSSL_NO_ENGINE
+ {
+ .name = "engine",
+ .argname = "id",
+ .desc = "Use the engine specified by the given identifier",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.engine,
+ },
+#endif
+ {
+ .name = "in",
+ .argname = "file",
+ .desc = "Input file (default stdin)",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.infile,
+ },
+ {
+ .name = "key",
+ .argname = "file",
+ .desc = "Create SPKAC using private key file",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.keyfile,
+ },
+ {
+ .name = "noout",
+ .desc = "Do not print text version of SPKAC",
+ .type = OPTION_FLAG,
+ .opt.flag = &spkac_config.noout,
+ },
+ {
+ .name = "out",
+ .argname = "file",
+ .desc = "Output file (default stdout)",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.outfile,
+ },
+ {
+ .name = "passin",
+ .argname = "src",
+ .desc = "Input file passphrase source",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.passargin,
+ },
+ {
+ .name = "pubkey",
+ .desc = "Output public key of an SPKAC (not used if creating)",
+ .type = OPTION_FLAG,
+ .opt.flag = &spkac_config.pubkey,
+ },
+ {
+ .name = "spkac",
+ .argname = "name",
+ .desc = "SPKAC name (default \"SPKAC\")",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.spkac,
+ },
+ {
+ .name = "spksect",
+ .argname = "name",
+ .desc = "Name of the section containing SPKAC (default"
+ " \"default\")",
+ .type = OPTION_ARG,
+ .opt.arg = &spkac_config.spksect,
+ },
+ {
+ .name = "verify",
+ .desc = "Verify digital signature on supplied SPKAC",
+ .type = OPTION_FLAG,
+ .opt.flag = &spkac_config.verify,
+ },
+ { NULL }
+};
-int spkac_main(int, char **);
+static void
+spkac_usage(void)
+{
+ fprintf(stderr,
+ "usage: spkac [-challenge string] [-engine id] [-in file] "
+ "[-key file] [-noout]\n"
+ " [-out file] [-passin src] [-pubkey] [-spkac name] "
+ "[-spksect section]\n"
+ " [-verify]\n\n");
+ options_usage(spkac_options);
+}
int
spkac_main(int argc, char **argv)
{
ENGINE *e = NULL;
- int i, badops = 0, ret = 1;
+ int i, ret = 1;
BIO *in = NULL, *out = NULL;
- int verify = 0, noout = 0, pubkey = 0;
- char *infile = NULL, *outfile = NULL, *prog;
- char *passargin = NULL, *passin = NULL;
- const char *spkac = "SPKAC", *spksect = "default";
+ char *passin = NULL;
char *spkstr = NULL;
- char *challenge = NULL, *keyfile = NULL;
CONF *conf = NULL;
NETSCAPE_SPKI *spki = NULL;
EVP_PKEY *pkey = NULL;
-#ifndef OPENSSL_NO_ENGINE
- char *engine = NULL;
-#endif
- prog = argv[0];
- argc--;
- argv++;
- while (argc >= 1) {
- if (strcmp(*argv, "-in") == 0) {
- if (--argc < 1)
- goto bad;
- infile = *(++argv);
- } else if (strcmp(*argv, "-out") == 0) {
- if (--argc < 1)
- goto bad;
- outfile = *(++argv);
- } else if (strcmp(*argv, "-passin") == 0) {
- if (--argc < 1)
- goto bad;
- passargin = *(++argv);
- } else if (strcmp(*argv, "-key") == 0) {
- if (--argc < 1)
- goto bad;
- keyfile = *(++argv);
- } else if (strcmp(*argv, "-challenge") == 0) {
- if (--argc < 1)
- goto bad;
- challenge = *(++argv);
- } else if (strcmp(*argv, "-spkac") == 0) {
- if (--argc < 1)
- goto bad;
- spkac = *(++argv);
- } else if (strcmp(*argv, "-spksect") == 0) {
- if (--argc < 1)
- goto bad;
- spksect = *(++argv);
- }
-#ifndef OPENSSL_NO_ENGINE
- else if (strcmp(*argv, "-engine") == 0) {
- if (--argc < 1)
- goto bad;
- engine = *(++argv);
- }
-#endif
- else if (strcmp(*argv, "-noout") == 0)
- noout = 1;
- else if (strcmp(*argv, "-pubkey") == 0)
- pubkey = 1;
- else if (strcmp(*argv, "-verify") == 0)
- verify = 1;
- else
- badops = 1;
- argc--;
- argv++;
- }
+ memset(&spkac_config, 0, sizeof(spkac_config));
+ spkac_config.spkac = "SPKAC";
+ spkac_config.spksect = "default";
- if (badops) {
-bad:
- BIO_printf(bio_err, "%s [options]\n", prog);
- BIO_printf(bio_err, "where options are\n");
- BIO_printf(bio_err, " -in arg input file\n");
- BIO_printf(bio_err, " -out arg output file\n");
- BIO_printf(bio_err, " -key arg create SPKAC using private key\n");
- BIO_printf(bio_err, " -passin arg input file pass phrase source\n");
- BIO_printf(bio_err, " -challenge arg challenge string\n");
- BIO_printf(bio_err, " -spkac arg alternative SPKAC name\n");
- BIO_printf(bio_err, " -noout don't print SPKAC\n");
- BIO_printf(bio_err, " -pubkey output public key\n");
- BIO_printf(bio_err, " -verify verify SPKAC signature\n");
-#ifndef OPENSSL_NO_ENGINE
- BIO_printf(bio_err, " -engine e use engine e, possibly a hardware device.\n");
-#endif
- goto end;
+ if (options_parse(argc, argv, spkac_options, NULL, NULL) != 0) {
+ spkac_usage();
+ return (1);
}
- if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
+ if (!app_passwd(bio_err, spkac_config.passargin, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
#ifndef OPENSSL_NO_ENGINE
- e = setup_engine(bio_err, engine, 0);
+ e = setup_engine(bio_err, spkac_config.engine, 0);
#endif
- if (keyfile) {
+ if (spkac_config.keyfile) {
pkey = load_key(bio_err,
- strcmp(keyfile, "-") ? keyfile : NULL,
- FORMAT_PEM, 1, passin, e, "private key");
+ strcmp(spkac_config.keyfile, "-") ? spkac_config.keyfile
+ : NULL, FORMAT_PEM, 1, passin, e, "private key");
if (!pkey) {
goto end;
}
spki = NETSCAPE_SPKI_new();
- if (challenge)
+ if (spkac_config.challenge)
ASN1_STRING_set(spki->spkac->challenge,
- challenge, (int) strlen(challenge));
+ spkac_config.challenge,
+ (int) strlen(spkac_config.challenge));
NETSCAPE_SPKI_set_pubkey(spki, pkey);
NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
spkstr = NETSCAPE_SPKI_b64_encode(spki);
goto end;
}
- if (outfile)
- out = BIO_new_file(outfile, "w");
+ if (spkac_config.outfile)
+ out = BIO_new_file(spkac_config.outfile, "w");
else
out = BIO_new_fp(stdout, BIO_NOCLOSE);
free(spkstr);
goto end;
}
- if (infile)
- in = BIO_new_file(infile, "r");
+ if (spkac_config.infile)
+ in = BIO_new_file(spkac_config.infile, "r");
else
in = BIO_new_fp(stdin, BIO_NOCLOSE);
ERR_print_errors(bio_err);
goto end;
}
- spkstr = NCONF_get_string(conf, spksect, spkac);
+ spkstr = NCONF_get_string(conf, spkac_config.spksect,
+ spkac_config.spkac);
if (!spkstr) {
- BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n", spkac);
+ BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n",
+ spkac_config.spkac);
ERR_print_errors(bio_err);
goto end;
}
ERR_print_errors(bio_err);
goto end;
}
- if (outfile)
- out = BIO_new_file(outfile, "w");
+ if (spkac_config.outfile)
+ out = BIO_new_file(spkac_config.outfile, "w");
else {
out = BIO_new_fp(stdout, BIO_NOCLOSE);
}
ERR_print_errors(bio_err);
goto end;
}
- if (!noout)
+ if (!spkac_config.noout)
NETSCAPE_SPKI_print(out, spki);
pkey = NETSCAPE_SPKI_get_pubkey(spki);
- if (verify) {
+ if (spkac_config.verify) {
i = NETSCAPE_SPKI_verify(spki, pkey);
if (i > 0)
BIO_printf(bio_err, "Signature OK\n");
goto end;
}
}
- if (pubkey)
+ if (spkac_config.pubkey)
PEM_write_bio_PUBKEY(out, pkey);
ret = 0;