unified pluto builder implementations
[strongswan.git] / src / pluto / certs.c
1 /* Certificate support for IKE authentication
2 * Copyright (C) 2002-2009 Andreas Steffen
3 *
4 * HSR - Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #include <freeswan.h>
23
24 #include "library.h"
25 #include "asn1/asn1.h"
26
27 #include "constants.h"
28 #include "defs.h"
29 #include "log.h"
30 #include "id.h"
31 #include "certs.h"
32 #include "whack.h"
33 #include "builder.h"
34
35 /**
36 * used for initializatin of certs
37 */
38 const cert_t cert_empty = {CERT_NONE, {NULL}};
39
40 /**
41 * extracts the certificate to be sent to the peer
42 */
43 chunk_t cert_get_encoding(cert_t cert)
44 {
45 switch (cert.type)
46 {
47 case CERT_PGP:
48 return cert.u.pgp->certificate;
49 case CERT_X509_SIGNATURE:
50 return cert.u.x509->certificate;
51 default:
52 return chunk_empty;
53 }
54 }
55
56 public_key_t* cert_get_public_key(const cert_t cert)
57 {
58 switch (cert.type)
59 {
60 case CERT_PGP:
61 return cert.u.pgp->public_key;
62 break;
63 case CERT_X509_SIGNATURE:
64 return cert.u.x509->public_key;
65 break;
66 default:
67 return NULL;
68 }
69 }
70
71 /**
72 * Passphrase callback to read from whack fd
73 */
74 chunk_t whack_pass_cb(prompt_pass_t *pass, int try)
75 {
76 int n;
77
78 if (try > MAX_PROMPT_PASS_TRIALS)
79 {
80 whack_log(RC_LOG_SERIOUS, "invalid passphrase, too many trials");
81 return chunk_empty;
82 }
83 if (try == 1)
84 {
85 whack_log(RC_ENTERSECRET, "need passphrase for 'private key'");
86 }
87 else
88 {
89 whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
90 }
91
92 n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
93
94 if (n == -1)
95 {
96 whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
97 return chunk_empty;
98 }
99
100 pass->secret[n-1] = '\0';
101
102 if (strlen(pass->secret) == 0)
103 {
104 whack_log(RC_LOG_SERIOUS, "no passphrase entered, aborted");
105 return chunk_empty;
106 }
107 return chunk_create(pass->secret, strlen(pass->secret));
108 }
109
110 /**
111 * Loads a PKCS#1 or PGP privatekey file
112 */
113 private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
114 key_type_t type)
115 {
116 private_key_t *key = NULL;
117 char *path;
118
119 path = concatenate_paths(PRIVATE_KEY_PATH, filename);
120 if (pass && pass->prompt && pass->fd != NULL_FD)
121 { /* use passphrase callback */
122 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
123 BUILD_FROM_FILE, path,
124 BUILD_PASSPHRASE_CALLBACK, whack_pass_cb, pass,
125 BUILD_END);
126 if (key)
127 {
128 whack_log(RC_SUCCESS, "valid passphrase");
129 }
130 }
131 else if (pass)
132 { /* use a given passphrase */
133 chunk_t password = chunk_create(pass->secret, strlen(pass->secret));
134 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
135 BUILD_FROM_FILE, path,
136 BUILD_PASSPHRASE, password, BUILD_END);
137 }
138 else
139 { /* no passphrase */
140 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
141 BUILD_FROM_FILE, path, BUILD_END);
142
143 }
144 if (key == NULL)
145 {
146 plog(" syntax error in private key file");
147 }
148 return key;
149 }
150
151 /**
152 * Loads a X.509 or OpenPGP certificate
153 */
154 bool load_cert(char *filename, const char *label, cert_t *out)
155 {
156 cert_t *cert;
157
158 cert = lib->creds->create(lib->creds, CRED_PLUTO_CERT, CRED_TYPE_CERTIFICATE,
159 BUILD_FROM_FILE, filename, BUILD_END);
160 if (cert)
161 {
162 /* the API passes an empty cert_t, we move over and free the built one */
163 *out = *cert;
164 free(cert);
165 return TRUE;
166 }
167 return FALSE;
168 }
169
170 /**
171 * Loads a host certificate
172 */
173 bool load_host_cert(char *filename, cert_t *cert)
174 {
175 char *path = concatenate_paths(HOST_CERT_PATH, filename);
176
177 return load_cert(path, "host cert", cert);
178 }
179
180 /**
181 * Loads a CA certificate
182 */
183 bool load_ca_cert(char *filename, cert_t *cert)
184 {
185 char *path = concatenate_paths(CA_CERT_PATH, filename);
186
187 return load_cert(path, "CA cert", cert);
188 }
189
190 /**
191 * establish equality of two certificates
192 */
193 bool same_cert(const cert_t *a, const cert_t *b)
194 {
195 return a->type == b->type && a->u.x509 == b->u.x509;
196 }
197
198 /**
199 * for each link pointing to the certificate increase the count by one
200 */
201 void share_cert(cert_t cert)
202 {
203 switch (cert.type)
204 {
205 case CERT_PGP:
206 share_pgpcert(cert.u.pgp);
207 break;
208 case CERT_X509_SIGNATURE:
209 share_x509cert(cert.u.x509);
210 break;
211 default:
212 break;
213 }
214 }
215
216 /* release of a certificate decreases the count by one
217 " the certificate is freed when the counter reaches zero
218 */
219 void
220 release_cert(cert_t cert)
221 {
222 switch (cert.type)
223 {
224 case CERT_PGP:
225 release_pgpcert(cert.u.pgp);
226 break;
227 case CERT_X509_SIGNATURE:
228 release_x509cert(cert.u.x509);
229 break;
230 default:
231 break;
232 }
233 }
234
235 /*
236 * list all X.509 and OpenPGP end certificates
237 */
238 void
239 list_certs(bool utc)
240 {
241 list_x509_end_certs(utc);
242 list_pgp_end_certs(utc);
243 }
244