pki: Add pki --req man page
[strongswan.git] / src / pki / commands / req.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2009 Andreas Steffen
4 *
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <time.h>
19
20 #include "pki.h"
21
22 #include <collections/linked_list.h>
23 #include <credentials/certificates/certificate.h>
24
25 /**
26 * Create a self-signed PKCS#10 certificate requesst.
27 */
28 static int req()
29 {
30 cred_encoding_type_t form = CERT_ASN1_DER;
31 key_type_t type = KEY_RSA;
32 hash_algorithm_t digest = HASH_SHA1;
33 certificate_t *cert = NULL;
34 private_key_t *private = NULL;
35 char *file = NULL, *dn = NULL, *error = NULL;
36 identification_t *id = NULL;
37 linked_list_t *san;
38 chunk_t encoding = chunk_empty;
39 chunk_t challenge_password = chunk_empty;
40 char *arg;
41
42 san = linked_list_create();
43
44 while (TRUE)
45 {
46 switch (command_getopt(&arg))
47 {
48 case 'h':
49 goto usage;
50 case 't':
51 if (streq(arg, "rsa"))
52 {
53 type = KEY_RSA;
54 }
55 else if (streq(arg, "ecdsa"))
56 {
57 type = KEY_ECDSA;
58 }
59 else
60 {
61 error = "invalid input type";
62 goto usage;
63 }
64 continue;
65 case 'g':
66 digest = enum_from_name(hash_algorithm_short_names, arg);
67 if (digest == -1)
68 {
69 error = "invalid --digest type";
70 goto usage;
71 }
72 continue;
73 case 'i':
74 file = arg;
75 continue;
76 case 'd':
77 dn = arg;
78 continue;
79 case 'a':
80 san->insert_last(san, identification_create_from_string(arg));
81 continue;
82 case 'p':
83 challenge_password = chunk_create(arg, strlen(arg));
84 continue;
85 case 'f':
86 if (!get_form(arg, &form, CRED_CERTIFICATE))
87 {
88 error = "invalid output format";
89 goto usage;
90 }
91 continue;
92 case EOF:
93 break;
94 default:
95 error = "invalid --req option";
96 goto usage;
97 }
98 break;
99 }
100
101 if (!dn)
102 {
103 error = "--dn is required";
104 goto usage;
105 }
106 id = identification_create_from_string(dn);
107 if (id->get_type(id) != ID_DER_ASN1_DN)
108 {
109 error = "supplied --dn is not a distinguished name";
110 goto end;
111 }
112 if (file)
113 {
114 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
115 BUILD_FROM_FILE, file, BUILD_END);
116 }
117 else
118 {
119 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
120 BUILD_FROM_FD, 0, BUILD_END);
121 }
122 if (!private)
123 {
124 error = "parsing private key failed";
125 goto end;
126 }
127 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PKCS10_REQUEST,
128 BUILD_SIGNING_KEY, private,
129 BUILD_SUBJECT, id,
130 BUILD_SUBJECT_ALTNAMES, san,
131 BUILD_CHALLENGE_PWD, challenge_password,
132 BUILD_DIGEST_ALG, digest,
133 BUILD_END);
134 if (!cert)
135 {
136 error = "generating certificate request failed";
137 goto end;
138 }
139 if (!cert->get_encoding(cert, form, &encoding))
140 {
141 error = "encoding certificate request failed";
142 goto end;
143 }
144 if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
145 {
146 error = "writing certificate request failed";
147 goto end;
148 }
149
150 end:
151 DESTROY_IF(id);
152 DESTROY_IF(cert);
153 DESTROY_IF(private);
154 san->destroy_offset(san, offsetof(identification_t, destroy));
155 free(encoding.ptr);
156
157 if (error)
158 {
159 fprintf(stderr, "%s\n", error);
160 return 1;
161 }
162 return 0;
163
164 usage:
165 san->destroy_offset(san, offsetof(identification_t, destroy));
166 return command_usage(error);
167 }
168
169 /**
170 * Register the command.
171 */
172 static void __attribute__ ((constructor))reg()
173 {
174 command_register((command_t) {
175 req, 'r', "req",
176 "create a PKCS#10 certificate request",
177 {" [--in file] [--type rsa|ecdsa] --dn distinguished-name",
178 "[--san subjectAltName]+ [--password challengePassword]",
179 "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"},
180 {
181 {"help", 'h', 0, "show usage information"},
182 {"in", 'i', 1, "private key input file, default: stdin"},
183 {"type", 't', 1, "type of input key, default: rsa"},
184 {"dn", 'd', 1, "subject distinguished name"},
185 {"san", 'a', 1, "subjectAltName to include in cert request"},
186 {"password",'p', 1, "challengePassword to include in cert request"},
187 {"digest", 'g', 1, "digest for signature creation, default: sha1"},
188 {"outform", 'f', 1, "encoding of generated request, default: der"},
189 }
190 });
191 }