MSC_VER <= 1200 isn't supported; remove dead code
[openssl.git] / apps / storeutl.c
1 /*
2  * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <openssl/opensslconf.h>
11
12 #include "apps.h"
13 #include <openssl/err.h>
14 #include <openssl/pem.h>
15 #include <openssl/store.h>
16
17 typedef enum OPTION_choice {
18     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
19     OPT_NOOUT, OPT_TEXT
20 } OPTION_CHOICE;
21
22 const OPTIONS storeutl_options[] = {
23     {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"},
24     {"help", OPT_HELP, '-', "Display this summary"},
25     {"out", OPT_OUT, '>', "Output file - default stdout"},
26     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
27     {"text", OPT_TEXT, '-', "Print a text form of the objects"},
28     {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
29 #ifndef OPENSSL_NO_ENGINE
30     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
31 #endif
32     {NULL}
33 };
34
35 int storeutl_main(int argc, char *argv[])
36 {
37     OSSL_STORE_CTX *store_ctx = NULL;
38     int ret = 1, noout = 0, text = 0, items = 0;
39     char *outfile = NULL, *passin = NULL, *passinarg = NULL;
40     BIO *out = NULL;
41     ENGINE *e = NULL;
42     OPTION_CHOICE o;
43     char *prog = opt_init(argc, argv, storeutl_options);
44     PW_CB_DATA pw_cb_data;
45
46     while ((o = opt_next()) != OPT_EOF) {
47         switch (o) {
48         case OPT_EOF:
49         case OPT_ERR:
50  opthelp:
51             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
52             goto end;
53         case OPT_HELP:
54             opt_help(storeutl_options);
55             ret = 0;
56             goto end;
57         case OPT_OUT:
58             outfile = opt_arg();
59             break;
60         case OPT_PASSIN:
61             passinarg = opt_arg();
62             break;
63         case OPT_NOOUT:
64             noout = 1;
65             break;
66         case OPT_TEXT:
67             text = 1;
68             break;
69         case OPT_ENGINE:
70             e = setup_engine(opt_arg(), 0);
71             break;
72         }
73     }
74     argc = opt_num_rest();
75     argv = opt_rest();
76
77     if (argc == 0) {
78         BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog);
79         goto opthelp;
80     }
81     if (argc > 1) {
82         BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog);
83         goto opthelp;
84     }
85
86     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
87         BIO_printf(bio_err, "Error getting passwords\n");
88         goto end;
89     }
90     pw_cb_data.password = passin;
91     pw_cb_data.prompt_info = argv[0];
92
93     out = bio_open_default(outfile, 'w', FORMAT_TEXT);
94     if (out == NULL)
95         goto end;
96
97     if ((store_ctx = OSSL_STORE_open(argv[0], get_ui_method(), &pw_cb_data,
98                                      NULL, NULL)) == NULL) {
99         BIO_printf(bio_err, "Couldn't open file or uri %s\n", argv[0]);
100         ERR_print_errors(bio_err);
101         goto end;
102     }
103
104     /* From here on, we count errors, and we'll return the count at the end */
105     ret = 0;
106
107     for (;;) {
108         OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx);
109         int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
110         const char *infostr =
111             info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
112
113         if (info == NULL) {
114             if (OSSL_STORE_eof(store_ctx))
115                 break;
116
117             if (OSSL_STORE_error(store_ctx)) {
118                 ERR_print_errors(bio_err);
119                 ret++;
120                 continue;
121             }
122
123             BIO_printf(bio_err,
124                        "ERROR: OSSL_STORE_load() returned NULL without "
125                        "eof or error indications\n");
126             BIO_printf(bio_err, "       This is an error in the loader\n");
127             ERR_print_errors(bio_err);
128             ret++;
129             break;
130         }
131
132         if (type == OSSL_STORE_INFO_NAME) {
133             const char *name = OSSL_STORE_INFO_get0_NAME(info);
134             const char *desc = OSSL_STORE_INFO_get0_NAME_description(info);
135             BIO_printf(bio_out, "%d: %s: %s\n", items, infostr, name);
136             if (desc != NULL)
137                 BIO_printf(bio_out, "%s\n", desc);
138         } else {
139             BIO_printf(bio_out, "%d: %s\n", items, infostr);
140         }
141
142         /*
143          * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in
144          * functionality, so we must figure out how exactly to write things
145          * ourselves...
146          */
147         switch (type) {
148         case OSSL_STORE_INFO_NAME:
149             break;
150         case OSSL_STORE_INFO_PARAMS:
151             if (text)
152                 EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info),
153                                       0, NULL);
154             if (!noout)
155                 PEM_write_bio_Parameters(out,
156                                          OSSL_STORE_INFO_get0_PARAMS(info));
157             break;
158         case OSSL_STORE_INFO_PKEY:
159             if (text)
160                 EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
161                                        0, NULL);
162             if (!noout)
163                 PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info),
164                                          NULL, NULL, 0, NULL, NULL);
165             break;
166         case OSSL_STORE_INFO_CERT:
167             if (text)
168                 X509_print(out, OSSL_STORE_INFO_get0_CERT(info));
169             if (!noout)
170                 PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info));
171             break;
172         case OSSL_STORE_INFO_CRL:
173             if (text)
174                 X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info));
175             if (!noout)
176                 PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info));
177             break;
178         default:
179             BIO_printf(bio_err, "!!! Unknown code\n");
180             ret++;
181             break;
182         }
183         items++;
184         OSSL_STORE_INFO_free(info);
185     }
186     BIO_printf(out, "Total found: %d\n", items);
187
188     if (!OSSL_STORE_close(store_ctx)) {
189         ERR_print_errors(bio_err);
190         ret++;
191         goto end;
192     }
193
194  end:
195     BIO_free_all(out);
196     OPENSSL_free(passin);
197     release_engine(e);
198     return ret;
199 }