handle pluto specific certificates under CRED_CERTIFICATE, not as own credential...
[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 #include "credentials/certificates/certificate.h"
27
28 #include "constants.h"
29 #include "defs.h"
30 #include "log.h"
31 #include "id.h"
32 #include "certs.h"
33 #include "whack.h"
34 #include "builder.h"
35
36 /**
37 * used for initializatin of certs
38 */
39 const cert_t cert_empty = {CERT_NONE, {NULL}};
40
41 /**
42 * extracts the certificate to be sent to the peer
43 */
44 chunk_t cert_get_encoding(cert_t cert)
45 {
46 switch (cert.type)
47 {
48 case CERT_PGP:
49 return cert.u.pgp->certificate;
50 case CERT_X509_SIGNATURE:
51 return cert.u.x509->certificate;
52 default:
53 return chunk_empty;
54 }
55 }
56
57 public_key_t* cert_get_public_key(const cert_t cert)
58 {
59 switch (cert.type)
60 {
61 case CERT_PGP:
62 return cert.u.pgp->public_key;
63 break;
64 case CERT_X509_SIGNATURE:
65 return cert.u.x509->public_key;
66 break;
67 default:
68 return NULL;
69 }
70 }
71
72 /**
73 * Passphrase callback to read from whack fd
74 */
75 chunk_t whack_pass_cb(prompt_pass_t *pass, int try)
76 {
77 int n;
78
79 if (try > MAX_PROMPT_PASS_TRIALS)
80 {
81 whack_log(RC_LOG_SERIOUS, "invalid passphrase, too many trials");
82 return chunk_empty;
83 }
84 if (try == 1)
85 {
86 whack_log(RC_ENTERSECRET, "need passphrase for 'private key'");
87 }
88 else
89 {
90 whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
91 }
92
93 n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
94
95 if (n == -1)
96 {
97 whack_log(RC_LOG_SERIOUS, "read(whackfd) failed");
98 return chunk_empty;
99 }
100
101 pass->secret[n-1] = '\0';
102
103 if (strlen(pass->secret) == 0)
104 {
105 whack_log(RC_LOG_SERIOUS, "no passphrase entered, aborted");
106 return chunk_empty;
107 }
108 return chunk_create(pass->secret, strlen(pass->secret));
109 }
110
111 /**
112 * Loads a PKCS#1 or PGP privatekey file
113 */
114 private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
115 key_type_t type)
116 {
117 private_key_t *key = NULL;
118 char *path;
119
120 path = concatenate_paths(PRIVATE_KEY_PATH, filename);
121 if (pass && pass->prompt && pass->fd != NULL_FD)
122 { /* use passphrase callback */
123 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
124 BUILD_FROM_FILE, path,
125 BUILD_PASSPHRASE_CALLBACK, whack_pass_cb, pass,
126 BUILD_END);
127 if (key)
128 {
129 whack_log(RC_SUCCESS, "valid passphrase");
130 }
131 }
132 else if (pass)
133 { /* use a given passphrase */
134 chunk_t password = chunk_create(pass->secret, strlen(pass->secret));
135 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
136 BUILD_FROM_FILE, path,
137 BUILD_PASSPHRASE, password, BUILD_END);
138 }
139 else
140 { /* no passphrase */
141 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
142 BUILD_FROM_FILE, path, BUILD_END);
143
144 }
145 if (key == NULL)
146 {
147 plog(" syntax error in private key file");
148 }
149 return key;
150 }
151
152 /**
153 * Loads a X.509 or OpenPGP certificate
154 */
155 bool load_cert(char *filename, const char *label, cert_t *out)
156 {
157 cert_t *cert;
158
159 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
160 BUILD_FROM_FILE, filename, BUILD_END);
161 if (cert)
162 {
163 /* the API passes an empty cert_t, we move over and free the built one */
164 *out = *cert;
165 free(cert);
166 return TRUE;
167 }
168 return FALSE;
169 }
170
171 /**
172 * Loads a host certificate
173 */
174 bool load_host_cert(char *filename, cert_t *cert)
175 {
176 char *path = concatenate_paths(HOST_CERT_PATH, filename);
177
178 return load_cert(path, "host cert", cert);
179 }
180
181 /**
182 * Loads a CA certificate
183 */
184 bool load_ca_cert(char *filename, cert_t *cert)
185 {
186 char *path = concatenate_paths(CA_CERT_PATH, filename);
187
188 return load_cert(path, "CA cert", cert);
189 }
190
191 /**
192 * establish equality of two certificates
193 */
194 bool same_cert(const cert_t *a, const cert_t *b)
195 {
196 return a->type == b->type && a->u.x509 == b->u.x509;
197 }
198
199 /**
200 * for each link pointing to the certificate increase the count by one
201 */
202 void share_cert(cert_t cert)
203 {
204 switch (cert.type)
205 {
206 case CERT_PGP:
207 share_pgpcert(cert.u.pgp);
208 break;
209 case CERT_X509_SIGNATURE:
210 share_x509cert(cert.u.x509);
211 break;
212 default:
213 break;
214 }
215 }
216
217 /* release of a certificate decreases the count by one
218 " the certificate is freed when the counter reaches zero
219 */
220 void
221 release_cert(cert_t cert)
222 {
223 switch (cert.type)
224 {
225 case CERT_PGP:
226 release_pgpcert(cert.u.pgp);
227 break;
228 case CERT_X509_SIGNATURE:
229 release_x509cert(cert.u.x509);
230 break;
231 default:
232 break;
233 }
234 }
235
236 /*
237 * list all X.509 and OpenPGP end certificates
238 */
239 void
240 list_certs(bool utc)
241 {
242 list_x509_end_certs(utc);
243 list_pgp_end_certs(utc);
244 }
245