pki: Properly clean up if output format for --pkcs12 is wrong
[strongswan.git] / src / pki / commands / pub.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <errno.h>
17
18 #include "pki.h"
19
20 #include <credentials/certificates/certificate.h>
21 #include <credentials/certificates/x509.h>
22
23 /**
24 * Extract a public key from a private key/certificate
25 */
26 static int pub()
27 {
28 cred_encoding_type_t form = PUBKEY_SPKI_ASN1_DER;
29 credential_type_t type = CRED_PRIVATE_KEY;
30 int subtype = KEY_RSA;
31 certificate_t *cert;
32 private_key_t *private;
33 public_key_t *public;
34 chunk_t encoding;
35 char *file = NULL, *keyid = NULL;
36 void *cred;
37 char *arg;
38
39 while (TRUE)
40 {
41 switch (command_getopt(&arg))
42 {
43 case 'h':
44 return command_usage(NULL);
45 case 't':
46 if (streq(arg, "rsa"))
47 {
48 type = CRED_PRIVATE_KEY;
49 subtype = KEY_RSA;
50 }
51 else if (streq(arg, "ecdsa"))
52 {
53 type = CRED_PRIVATE_KEY;
54 subtype = KEY_ECDSA;
55 }
56 else if (streq(arg, "bliss"))
57 {
58 type = CRED_PRIVATE_KEY;
59 subtype = KEY_BLISS;
60 }
61 else if (streq(arg, "pub"))
62 {
63 type = CRED_PUBLIC_KEY;
64 subtype = KEY_ANY;
65 }
66 else if (streq(arg, "pkcs10"))
67 {
68 type = CRED_CERTIFICATE;
69 subtype = CERT_PKCS10_REQUEST;
70 }
71 else if (streq(arg, "x509"))
72 {
73 type = CRED_CERTIFICATE;
74 subtype = CERT_X509;
75 }
76 else
77 {
78 return command_usage("invalid input type");
79 }
80 continue;
81 case 'f':
82 if (!get_form(arg, &form, CRED_PUBLIC_KEY))
83 {
84 return command_usage("invalid output format");
85 }
86 continue;
87 case 'i':
88 file = arg;
89 continue;
90 case 'x':
91 keyid = arg;
92 continue;
93 case EOF:
94 break;
95 default:
96 return command_usage("invalid --pub option");
97 }
98 break;
99 }
100 if (file)
101 {
102 cred = lib->creds->create(lib->creds, type, subtype,
103 BUILD_FROM_FILE, file, BUILD_END);
104 }
105 else if (keyid)
106 {
107 chunk_t chunk;
108
109 chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
110 cred = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
111 BUILD_PKCS11_KEYID, chunk, BUILD_END);
112 free(chunk.ptr);
113 }
114 else
115 {
116 chunk_t chunk;
117
118 set_file_mode(stdin, CERT_ASN1_DER);
119 if (!chunk_from_fd(0, &chunk))
120 {
121 fprintf(stderr, "reading input failed: %s\n", strerror(errno));
122 return 1;
123 }
124 cred = lib->creds->create(lib->creds, type, subtype,
125 BUILD_BLOB, chunk, BUILD_END);
126 free(chunk.ptr);
127 }
128
129 if (type == CRED_PRIVATE_KEY)
130 {
131 private = cred;
132 if (!private)
133 {
134 fprintf(stderr, "parsing private key failed\n");
135 return 1;
136 }
137 public = private->get_public_key(private);
138 private->destroy(private);
139 }
140 else if (type == CRED_PUBLIC_KEY)
141 {
142 public = cred;
143 if (!public)
144 {
145 fprintf(stderr, "parsing public key failed\n");
146 return 1;
147 }
148 }
149 else
150 {
151 cert = cred;
152 if (!cert)
153 {
154 fprintf(stderr, "parsing certificate failed\n");
155 return 1;
156 }
157 public = cert->get_public_key(cert);
158 cert->destroy(cert);
159 }
160 if (!public)
161 {
162 fprintf(stderr, "extracting public key failed\n");
163 return 1;
164 }
165 if (!public->get_encoding(public, form, &encoding))
166 {
167 fprintf(stderr, "public key encoding failed\n");
168 public->destroy(public);
169 return 1;
170 }
171 public->destroy(public);
172 set_file_mode(stdout, form);
173 if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
174 {
175 fprintf(stderr, "writing public key failed\n");
176 free(encoding.ptr);
177 return 1;
178 }
179 free(encoding.ptr);
180 return 0;
181 }
182
183 /**
184 * Register the command.
185 */
186 static void __attribute__ ((constructor))reg()
187 {
188 command_register((command_t) {
189 pub, 'p', "pub",
190 "extract the public key from a private key/certificate",
191 {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|pub|pkcs10|x509]",
192 "[--outform der|pem|dnskey|sshkey]"},
193 {
194 {"help", 'h', 0, "show usage information"},
195 {"in", 'i', 1, "input file, default: stdin"},
196 {"keyid", 'x', 1, "keyid on smartcard of private key"},
197 {"type", 't', 1, "type of credential, default: rsa"},
198 {"outform", 'f', 1, "encoding of extracted public key, default: der"},
199 }
200 });
201 }