Bug Summary

File:src/sbin/isakmpd/x509.c
Warning:line 534, column 35
Array access results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name x509.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/isakmpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/isakmpd/x509.c
1/* $OpenBSD: x509.c,v 1.125 2022/01/16 14:30:11 naddy Exp $ */
2/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $ */
3
4/*
5 * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
6 * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved.
7 * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * This code was written under funding by Ericsson Radio Systems.
32 */
33
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <dirent.h>
37#include <errno(*__errno()).h>
38#include <fcntl.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43#include <limits.h>
44
45#include <regex.h>
46#include <keynote.h>
47
48#include "cert.h"
49#include "conf.h"
50#include "exchange.h"
51#include "hash.h"
52#include "ike_auth.h"
53#include "ipsec.h"
54#include "log.h"
55#include "dh.h"
56#include "monitor.h"
57#include "policy.h"
58#include "sa.h"
59#include "util.h"
60#include "x509.h"
61
62static u_int16_t x509_hash(u_int8_t *, size_t);
63static void x509_hash_init(void);
64static X509 *x509_hash_find(u_int8_t *, size_t);
65static int x509_hash_enter(X509 *);
66
67/*
68 * X509_STOREs do not support subjectAltNames, so we have to build
69 * our own hash table.
70 */
71
72/*
73 * XXX Actually this store is not really useful, we never use it as we have
74 * our own hash table. It also gets collisions if we have several certificates
75 * only differing in subjectAltName.
76 */
77static X509_STORE *x509_certs = 0;
78static X509_STORE *x509_cas = 0;
79
80static int n_x509_cas = 0;
81
82/* Initial number of bits used as hash. */
83#define INITIAL_BUCKET_BITS6 6
84
85struct x509_hash {
86 LIST_ENTRY(x509_hash)struct { struct x509_hash *le_next; struct x509_hash **le_prev
; }
link;
87
88 X509 *cert;
89};
90
91static LIST_HEAD(x509_list, x509_hash)struct x509_list { struct x509_hash *lh_first; } *x509_tab = 0;
92
93/* Works both as a maximum index and a mask. */
94static int bucket_mask;
95
96/*
97 * Given an X509 certificate, create a KeyNote assertion where
98 * Issuer/Subject -> Authorizer/Licensees.
99 * XXX RSA-specific.
100 */
101int
102x509_generate_kn(int id, X509 *cert)
103{
104 static const char fmt[] = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s"
105 "\"\nConditions: %s >= \"%s\" && %s <= \"%s\";\n";
106 char *ikey = NULL((void *)0), *skey = NULL((void *)0), *buf = NULL((void *)0);
107 char isname[256], subname[256];
108 static const char fmt2[] = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n"
109 "Conditions: %s >= \"%s\" && %s <= \"%s\";\n";
110 X509_NAME *issuer, *subject;
111 struct keynote_deckey dc;
112 X509_STORE_CTX *csc = NULL((void *)0);
113 X509_OBJECT *obj = NULL((void *)0);
114 X509 *icert;
115 RSA *key = NULL((void *)0);
116 time_t tt;
117 char before[15], after[15], *timecomp, *timecomp2;
118 ASN1_TIME *tm;
119 int i;
120
121 LOG_DBG((LOG_POLICY, 90,log_debug (LOG_POLICY, 90, "x509_generate_kn: generating KeyNote policy for certificate %p"
, cert)
122 "x509_generate_kn: generating KeyNote policy for certificate %p",log_debug (LOG_POLICY, 90, "x509_generate_kn: generating KeyNote policy for certificate %p"
, cert)
123 cert))log_debug (LOG_POLICY, 90, "x509_generate_kn: generating KeyNote policy for certificate %p"
, cert)
;
124
125 issuer = X509_get_issuer_name(cert);
126 subject = X509_get_subject_name(cert);
127
128 /* Missing or self-signed, ignore cert but don't report failure. */
129 if (!issuer || !subject || !X509_NAME_cmp(issuer, subject))
130 return 1;
131
132 if (!x509_cert_get_key(cert, &key)) {
133 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to get public key from cert"
)
134 "x509_generate_kn: failed to get public key from cert"))log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to get public key from cert"
)
;
135 return 0;
136 }
137 dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA6;
138 dc.dec_key = key;
139 ikey = kn_encode_key(&dc, INTERNAL_ENC_PKCS11, ENCODING_HEX1,
140 KEYNOTE_PUBLIC_KEY0);
141 if (keynote_errno == ERROR_MEMORY-1) {
142 log_print("x509_generate_kn: failed to get memory for "
143 "public key");
144 LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get "log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get " "subject key"
)
145 "subject key"))log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get " "subject key"
)
;
146 goto fail;
147 }
148 if (!ikey) {
149 LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get "log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get " "subject key"
)
150 "subject key"))log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get " "subject key"
)
;
151 goto fail;
152 }
153
154 RSA_free(key);
155 key = NULL((void *)0);
156
157 csc = X509_STORE_CTX_new();
158 if (csc == NULL((void *)0)) {
159 log_print("x509_generate_kn: failed to get memory for "
160 "certificate store");
161 goto fail;
162 }
163 obj = X509_OBJECT_new();
164 if (obj == NULL((void *)0)) {
165 log_print("x509_generate_kn: failed to get memory for "
166 "certificate object");
167 goto fail;
168 }
169
170 /* Now find issuer's certificate so we can get the public key. */
171 X509_STORE_CTX_init(csc, x509_cas, cert, NULL((void *)0));
172 if (X509_STORE_get_by_subjectX509_STORE_CTX_get_by_subject(csc, X509_LU_X509, issuer, obj) !=
173 X509_LU_X509) {
174 X509_STORE_CTX_cleanup(csc);
175 X509_STORE_CTX_init(csc, x509_certs, cert, NULL((void *)0));
176 if (X509_STORE_get_by_subjectX509_STORE_CTX_get_by_subject(csc, X509_LU_X509, issuer, obj)
177 != X509_LU_X509) {
178 X509_STORE_CTX_cleanup(csc);
179 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: no certificate found for "
"issuer")
180 "x509_generate_kn: no certificate found for "log_debug (LOG_POLICY, 30, "x509_generate_kn: no certificate found for "
"issuer")
181 "issuer"))log_debug (LOG_POLICY, 30, "x509_generate_kn: no certificate found for "
"issuer")
;
182 goto fail;
183 }
184 }
185 X509_STORE_CTX_free(csc);
186 csc = NULL((void *)0);
187
188 icert = X509_OBJECT_get0_X509(obj);
189 if (icert == NULL((void *)0)) {
190 LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: "log_debug (LOG_POLICY, 30, "x509_generate_kn: " "missing certificates, cannot construct X509 chain"
)
191 "missing certificates, cannot construct X509 chain"))log_debug (LOG_POLICY, 30, "x509_generate_kn: " "missing certificates, cannot construct X509 chain"
)
;
192 goto fail;
193 }
194 if (!x509_cert_get_key(icert, &key)) {
195 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to get public key from cert"
)
196 "x509_generate_kn: failed to get public key from cert"))log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to get public key from cert"
)
;
197 goto fail;
198 }
199 X509_OBJECT_free(obj);
200 obj = NULL((void *)0);
201
202 dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA6;
203 dc.dec_key = key;
204 skey = kn_encode_key(&dc, INTERNAL_ENC_PKCS11, ENCODING_HEX1,
205 KEYNOTE_PUBLIC_KEY0);
206 if (keynote_errno == ERROR_MEMORY-1) {
207 log_error("x509_generate_kn: failed to get memory for public "
208 "key");
209 LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
"key")
210 "key"))log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
"key")
;
211 goto fail;
212 }
213 if (!skey) {
214 LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
"key")
215 "key"))log_debug (LOG_POLICY, 30, "x509_generate_kn: cannot get issuer "
"key")
;
216 goto fail;
217 }
218
219 RSA_free(key);
220 key = NULL((void *)0);
221
222 if (((tm = X509_get_notBeforeX509_getm_notBefore(cert)) == NULL((void *)0)) ||
223 (tm->type != V_ASN1_UTCTIME23 &&
224 tm->type != V_ASN1_GENERALIZEDTIME24)) {
225 tt = time(0);
226 strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt));
227 timecomp = "LocalTimeOfDay";
228 } else {
229 if (tm->data[tm->length - 1] == 'Z') {
230 timecomp = "GMTTimeOfDay";
231 i = tm->length - 2;
232 } else {
233 timecomp = "LocalTimeOfDay";
234 i = tm->length - 1;
235 }
236
237 for (; i >= 0; i--) {
238 if (tm->data[i] < '0' || tm->data[i] > '9') {
239 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid data in "
"NotValidBefore time field")
240 "x509_generate_kn: invalid data in "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid data in "
"NotValidBefore time field")
241 "NotValidBefore time field"))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid data in "
"NotValidBefore time field")
;
242 goto fail;
243 }
244 }
245
246 if (tm->type == V_ASN1_UTCTIME23) {
247 if ((tm->length < 10) || (tm->length > 13)) {
248 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length "
"of NotValidBefore time field (%d)", tm->length)
249 "x509_generate_kn: invalid length "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length "
"of NotValidBefore time field (%d)", tm->length)
250 "of NotValidBefore time field (%d)",log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length "
"of NotValidBefore time field (%d)", tm->length)
251 tm->length))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length "
"of NotValidBefore time field (%d)", tm->length)
;
252 goto fail;
253 }
254 /* Validity checks. */
255 if ((tm->data[2] != '0' && tm->data[2] != '1') ||
256 (tm->data[2] == '0' && tm->data[3] == '0') ||
257 (tm->data[2] == '1' && tm->data[3] > '2') ||
258 (tm->data[4] > '3') ||
259 (tm->data[4] == '0' && tm->data[5] == '0') ||
260 (tm->data[4] == '3' && tm->data[5] > '1') ||
261 (tm->data[6] > '2') ||
262 (tm->data[6] == '2' && tm->data[7] > '3') ||
263 (tm->data[8] > '5')) {
264 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidBefore time field")
265 "x509_generate_kn: invalid value in "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidBefore time field")
266 "NotValidBefore time field"))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidBefore time field")
;
267 goto fail;
268 }
269 /* Stupid UTC tricks. */
270 if (tm->data[0] < '5')
271 snprintf(before, sizeof before, "20%s",
272 tm->data);
273 else
274 snprintf(before, sizeof before, "19%s",
275 tm->data);
276 } else { /* V_ASN1_GENERICTIME */
277 if ((tm->length < 12) || (tm->length > 15)) {
278 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidBefore time field (%d)", tm->length)
279 "x509_generate_kn: invalid length of "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidBefore time field (%d)", tm->length)
280 "NotValidBefore time field (%d)",log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidBefore time field (%d)", tm->length)
281 tm->length))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidBefore time field (%d)", tm->length)
;
282 goto fail;
283 }
284 /* Validity checks. */
285 if ((tm->data[4] != '0' && tm->data[4] != '1') ||
286 (tm->data[4] == '0' && tm->data[5] == '0') ||
287 (tm->data[4] == '1' && tm->data[5] > '2') ||
288 (tm->data[6] > '3') ||
289 (tm->data[6] == '0' && tm->data[7] == '0') ||
290 (tm->data[6] == '3' && tm->data[7] > '1') ||
291 (tm->data[8] > '2') ||
292 (tm->data[8] == '2' && tm->data[9] > '3') ||
293 (tm->data[10] > '5')) {
294 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidBefore time field")
295 "x509_generate_kn: invalid value in "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidBefore time field")
296 "NotValidBefore time field"))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidBefore time field")
;
297 goto fail;
298 }
299 snprintf(before, sizeof before, "%s", tm->data);
300 }
301
302 /* Fix missing seconds. */
303 if (tm->length < 12) {
304 before[12] = '0';
305 before[13] = '0';
306 }
307 /* This will overwrite trailing 'Z'. */
308 before[14] = '\0';
309 }
310
311 tm = X509_get_notAfterX509_getm_notAfter(cert);
312 if (tm == NULL((void *)0) ||
313 (tm->type != V_ASN1_UTCTIME23 &&
314 tm->type != V_ASN1_GENERALIZEDTIME24)) {
315 tt = time(0);
316 strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt));
317 timecomp2 = "LocalTimeOfDay";
318 } else {
319 if (tm->data[tm->length - 1] == 'Z') {
320 timecomp2 = "GMTTimeOfDay";
321 i = tm->length - 2;
322 } else {
323 timecomp2 = "LocalTimeOfDay";
324 i = tm->length - 1;
325 }
326
327 for (; i >= 0; i--) {
328 if (tm->data[i] < '0' || tm->data[i] > '9') {
329 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid data in "
"NotValidAfter time field")
330 "x509_generate_kn: invalid data in "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid data in "
"NotValidAfter time field")
331 "NotValidAfter time field"))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid data in "
"NotValidAfter time field")
;
332 goto fail;
333 }
334 }
335
336 if (tm->type == V_ASN1_UTCTIME23) {
337 if ((tm->length < 10) || (tm->length > 13)) {
338 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
339 "x509_generate_kn: invalid length of "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
340 "NotValidAfter time field (%d)",log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
341 tm->length))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
;
342 goto fail;
343 }
344 /* Validity checks. */
345 if ((tm->data[2] != '0' && tm->data[2] != '1') ||
346 (tm->data[2] == '0' && tm->data[3] == '0') ||
347 (tm->data[2] == '1' && tm->data[3] > '2') ||
348 (tm->data[4] > '3') ||
349 (tm->data[4] == '0' && tm->data[5] == '0') ||
350 (tm->data[4] == '3' && tm->data[5] > '1') ||
351 (tm->data[6] > '2') ||
352 (tm->data[6] == '2' && tm->data[7] > '3') ||
353 (tm->data[8] > '5')) {
354 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidAfter time field")
355 "x509_generate_kn: invalid value in "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidAfter time field")
356 "NotValidAfter time field"))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidAfter time field")
;
357 goto fail;
358 }
359 /* Stupid UTC tricks. */
360 if (tm->data[0] < '5')
361 snprintf(after, sizeof after, "20%s",
362 tm->data);
363 else
364 snprintf(after, sizeof after, "19%s",
365 tm->data);
366 } else { /* V_ASN1_GENERICTIME */
367 if ((tm->length < 12) || (tm->length > 15)) {
368 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
369 "x509_generate_kn: invalid length of "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
370 "NotValidAfter time field (%d)",log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
371 tm->length))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid length of "
"NotValidAfter time field (%d)", tm->length)
;
372 goto fail;
373 }
374 /* Validity checks. */
375 if ((tm->data[4] != '0' && tm->data[4] != '1') ||
376 (tm->data[4] == '0' && tm->data[5] == '0') ||
377 (tm->data[4] == '1' && tm->data[5] > '2') ||
378 (tm->data[6] > '3') ||
379 (tm->data[6] == '0' && tm->data[7] == '0') ||
380 (tm->data[6] == '3' && tm->data[7] > '1') ||
381 (tm->data[8] > '2') ||
382 (tm->data[8] == '2' && tm->data[9] > '3') ||
383 (tm->data[10] > '5')) {
384 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidAfter time field")
385 "x509_generate_kn: invalid value in "log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidAfter time field")
386 "NotValidAfter time field"))log_debug (LOG_POLICY, 30, "x509_generate_kn: invalid value in "
"NotValidAfter time field")
;
387 goto fail;
388 }
389 snprintf(after, sizeof after, "%s", tm->data);
390 }
391
392 /* Fix missing seconds. */
393 if (tm->length < 12) {
394 after[12] = '0';
395 after[13] = '0';
396 }
397 after[14] = '\0'; /* This will overwrite trailing 'Z' */
398 }
399
400 if (asprintf(&buf, fmt, skey, ikey, timecomp, before, timecomp2,
401 after) == -1) {
402 log_error("x509_generate_kn: "
403 "failed to allocate memory for KeyNote credential");
404 goto fail;
405 }
406
407 free(ikey);
408 ikey = NULL((void *)0);
409 free(skey);
410 skey = NULL((void *)0);
411
412 if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL0x0001) == -1) {
413 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to add new KeyNote credential"
)
414 "x509_generate_kn: failed to add new KeyNote credential"))log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to add new KeyNote credential"
)
;
415 goto fail;
416 }
417 /* We could print the assertion here, but log_print() truncates... */
418 LOG_DBG((LOG_POLICY, 60, "x509_generate_kn: added credential"))log_debug (LOG_POLICY, 60, "x509_generate_kn: added credential"
)
;
419
420 free(buf);
421 buf = NULL((void *)0);
422
423 if (!X509_NAME_oneline(issuer, isname, 256)) {
424 LOG_DBG((LOG_POLICY, 50,log_debug (LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (issuer, ...) failed"
)
425 "x509_generate_kn: "log_debug (LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (issuer, ...) failed"
)
426 "X509_NAME_oneline (issuer, ...) failed"))log_debug (LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (issuer, ...) failed"
)
;
427 goto fail;
428 }
429 if (!X509_NAME_oneline(subject, subname, 256)) {
430 LOG_DBG((LOG_POLICY, 50,log_debug (LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (subject, ...) failed"
)
431 "x509_generate_kn: "log_debug (LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (subject, ...) failed"
)
432 "X509_NAME_oneline (subject, ...) failed"))log_debug (LOG_POLICY, 50, "x509_generate_kn: " "X509_NAME_oneline (subject, ...) failed"
)
;
433 goto fail;
434 }
435 if (asprintf(&buf, fmt2, isname, subname, timecomp, before,
436 timecomp2, after) == -1) {
437 log_error("x509_generate_kn: malloc failed");
438 return 0;
439 }
440
441 if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL0x0001) == -1) {
442 LOG_DBG((LOG_POLICY, 30,log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to add new KeyNote credential"
)
443 "x509_generate_kn: failed to add new KeyNote credential"))log_debug (LOG_POLICY, 30, "x509_generate_kn: failed to add new KeyNote credential"
)
;
444 goto fail;
445 }
446 LOG_DBG((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s",log_debug (LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s"
, buf)
447 buf))log_debug (LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s"
, buf)
;
448
449 free(buf);
450 return 1;
451
452fail:
453 X509_STORE_CTX_free(csc);
454 X509_OBJECT_free(obj);
455 free(buf);
456 free(skey);
457 free(ikey);
458 if (key)
459 RSA_free(key);
460
461 return 0;
462}
463
464static u_int16_t
465x509_hash(u_int8_t *id, size_t len)
466{
467 u_int16_t bucket = 0;
468 size_t i;
469
470 /* XXX We might resize if we are crossing a certain threshold. */
471 for (i = 4; i < (len & ~1); i += 2) {
472 /* Doing it this way avoids alignment problems. */
473 bucket ^= (id[i] + 1) * (id[i + 1] + 257);
474 }
475 /* Hash in the last character of odd length IDs too. */
476 if (i < len)
477 bucket ^= (id[i] + 1) * (id[i] + 257);
478
479 bucket &= bucket_mask;
480 return bucket;
481}
482
483static void
484x509_hash_init(void)
485{
486 struct x509_hash *certh;
487 int i;
488
489 bucket_mask = (1 << INITIAL_BUCKET_BITS6) - 1;
490
491 /* If reinitializing, free existing entries. */
492 if (x509_tab) {
493 for (i = 0; i <= bucket_mask; i++)
494 for (certh = LIST_FIRST(&x509_tab[i])((&x509_tab[i])->lh_first); certh;
495 certh = LIST_FIRST(&x509_tab[i])((&x509_tab[i])->lh_first)) {
496 LIST_REMOVE(certh, link)do { if ((certh)->link.le_next != ((void *)0)) (certh)->
link.le_next->link.le_prev = (certh)->link.le_prev; *(certh
)->link.le_prev = (certh)->link.le_next; ; ; } while (0
)
;
497 free(certh);
498 }
499 free(x509_tab);
500 }
501 x509_tab = calloc(bucket_mask + 1, sizeof(struct x509_list));
502 if (!x509_tab)
503 log_fatal("x509_hash_init: malloc (%lu) failed",
504 (bucket_mask + 1) *
505 (unsigned long)sizeof(struct x509_list));
506 for (i = 0; i <= bucket_mask; i++) {
507 LIST_INIT(&x509_tab[i])do { ((&x509_tab[i])->lh_first) = ((void *)0); } while
(0)
;
508 }
509}
510
511/* Lookup a certificate by an ID blob. */
512static X509 *
513x509_hash_find(u_int8_t *id, size_t len)
514{
515 struct x509_hash *cert;
516 u_int8_t **cid;
517 u_int32_t *clen;
518 int n, i, id_found;
519
520 for (cert = LIST_FIRST(&x509_tab[x509_hash(id, len)])((&x509_tab[x509_hash(id, len)])->lh_first); cert;
6
Loop condition is true. Entering loop body
521 cert = LIST_NEXT(cert, link)((cert)->link.le_next)) {
522 if (!x509_cert_get_subjects(cert->cert, &n, &cid, &clen))
7
Calling 'x509_cert_get_subjects'
21
Returning from 'x509_cert_get_subjects'
22
Taking false branch
523 continue;
524
525 id_found = 0;
526 for (i = 0; i < n; i++) {
23
Loop condition is true. Entering loop body
25
The value 1 is assigned to 'i'
26
Loop condition is true. Entering loop body
527 LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", id, len))log_debug_buf (LOG_CRYPTO, 70, "cert_cmp", id, len);
528 LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", cid[i],log_debug_buf (LOG_CRYPTO, 70, "cert_cmp", cid[i], clen[i])
529 clen[i]))log_debug_buf (LOG_CRYPTO, 70, "cert_cmp", cid[i], clen[i]);
530 /*
531 * XXX This identity predicate needs to be
532 * understood.
533 */
534 if (clen[i] == len && id[0] == cid[i][0] &&
24
Assuming the condition is false
27
Assuming the condition is true
28
Array access results in a null pointer dereference
535 memcmp(id + 4, cid[i] + 4, len - 4) == 0) {
536 id_found++;
537 break;
538 }
539 }
540 cert_free_subjects(n, cid, clen);
541 if (!id_found)
542 continue;
543
544 LOG_DBG((LOG_CRYPTO, 70, "x509_hash_find: return X509 %p",log_debug (LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", cert
->cert)
545 cert->cert))log_debug (LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", cert
->cert)
;
546 return cert->cert;
547 }
548
549 LOG_DBG((LOG_CRYPTO, 70,log_debug (LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query"
)
550 "x509_hash_find: no certificate matched query"))log_debug (LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query"
)
;
551 return 0;
552}
553
554static int
555x509_hash_enter(X509 *cert)
556{
557 u_int16_t bucket = 0;
558 u_int8_t **id;
559 u_int32_t *len;
560 struct x509_hash *certh;
561 int n, i;
562
563 if (!x509_cert_get_subjects(cert, &n, &id, &len)) {
564 log_print("x509_hash_enter: cannot retrieve subjects");
565 return 0;
566 }
567 for (i = 0; i < n; i++) {
568 certh = calloc(1, sizeof *certh);
569 if (!certh) {
570 cert_free_subjects(n, id, len);
571 log_error("x509_hash_enter: calloc (1, %lu) failed",
572 (unsigned long)sizeof *certh);
573 return 0;
574 }
575 certh->cert = cert;
576
577 bucket = x509_hash(id[i], len[i]);
578
579 LIST_INSERT_HEAD(&x509_tab[bucket], certh, link)do { if (((certh)->link.le_next = (&x509_tab[bucket])->
lh_first) != ((void *)0)) (&x509_tab[bucket])->lh_first
->link.le_prev = &(certh)->link.le_next; (&x509_tab
[bucket])->lh_first = (certh); (certh)->link.le_prev = &
(&x509_tab[bucket])->lh_first; } while (0)
;
580 LOG_DBG((LOG_CRYPTO, 70,log_debug (LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d"
, cert, bucket)
581 "x509_hash_enter: cert %p added to bucket %d",log_debug (LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d"
, cert, bucket)
582 cert, bucket))log_debug (LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d"
, cert, bucket)
;
583 }
584 cert_free_subjects(n, id, len);
585
586 return 1;
587}
588
589/* X509 Certificate Handling functions. */
590
591int
592x509_read_from_dir(X509_STORE *ctx, char *name, int hash, int *pcount)
593{
594 FILE *certfp;
595 X509 *cert;
596 struct stat sb;
597 char fullname[PATH_MAX1024];
598 char file[PATH_MAX1024];
599 int fd;
600
601 if (strlen(name) >= sizeof fullname - 1) {
602 log_print("x509_read_from_dir: directory name too long");
603 return 0;
604 }
605 LOG_DBG((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s",log_debug (LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s"
, name)
606 name))log_debug (LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s"
, name)
;
607
608 if (monitor_req_readdir(name) == -1) {
609 LOG_DBG((LOG_CRYPTO, 10,log_debug (LOG_CRYPTO, 10, "x509_read_from_dir: opendir (\"%s\") failed: %s"
, name, strerror((*__errno())))
610 "x509_read_from_dir: opendir (\"%s\") failed: %s",log_debug (LOG_CRYPTO, 10, "x509_read_from_dir: opendir (\"%s\") failed: %s"
, name, strerror((*__errno())))
611 name, strerror(errno)))log_debug (LOG_CRYPTO, 10, "x509_read_from_dir: opendir (\"%s\") failed: %s"
, name, strerror((*__errno())))
;
612 return 0;
613 }
614
615 while ((fd = monitor_readdir(file, sizeof file)) != -1) {
616 LOG_DBG((LOG_CRYPTO, 60,log_debug (LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s"
, file)
617 "x509_read_from_dir: reading certificate %s",log_debug (LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s"
, file)
618 file))log_debug (LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s"
, file)
;
619
620 if (fstat(fd, &sb) == -1) {
621 log_error("x509_read_from_dir: fstat failed");
622 close(fd);
623 continue;
624 }
625
626 if (!S_ISREG(sb.st_mode)((sb.st_mode & 0170000) == 0100000)) {
627 close(fd);
628 continue;
629 }
630
631 if ((certfp = fdopen(fd, "r")) == NULL((void *)0)) {
632 log_error("x509_read_from_dir: fdopen failed");
633 close(fd);
634 continue;
635 }
636
637#if SSLEAY_VERSION_NUMBER0x20000000L >= 0x00904100L
638 cert = PEM_read_X509(certfp, NULL((void *)0), NULL((void *)0), NULL((void *)0));
639#else
640 cert = PEM_read_X509(certfp, NULL((void *)0), NULL((void *)0));
641#endif
642 fclose(certfp);
643
644 if (cert == NULL((void *)0)) {
645 log_print("x509_read_from_dir: PEM_read_X509 "
646 "failed for %s", file);
647 continue;
648 }
649
650 if (pcount != NULL((void *)0))
651 (*pcount)++;
652
653 if (!X509_STORE_add_cert(ctx, cert)) {
654 /*
655 * This is actually expected if we have several
656 * certificates only differing in subjectAltName,
657 * which is not an something that is strange.
658 * Consider multi-homed machines.
659 */
660 LOG_DBG((LOG_CRYPTO, 50,log_debug (LOG_CRYPTO, 50, "x509_read_from_dir: X509_STORE_add_cert failed "
"for %s", file)
661 "x509_read_from_dir: X509_STORE_add_cert failed "log_debug (LOG_CRYPTO, 50, "x509_read_from_dir: X509_STORE_add_cert failed "
"for %s", file)
662 "for %s", file))log_debug (LOG_CRYPTO, 50, "x509_read_from_dir: X509_STORE_add_cert failed "
"for %s", file)
;
663 }
664 if (hash)
665 if (!x509_hash_enter(cert))
666 log_print("x509_read_from_dir: "
667 "x509_hash_enter (%s) failed",
668 file);
669 }
670
671 return 1;
672}
673
674/* XXX share code with x509_read_from_dir() ? */
675int
676x509_read_crls_from_dir(X509_STORE *ctx, char *name)
677{
678 FILE *crlfp;
679 X509_CRL *crl;
680 struct stat sb;
681 char fullname[PATH_MAX1024];
682 char file[PATH_MAX1024];
683 int fd;
684
685 if (strlen(name) >= sizeof fullname - 1) {
686 log_print("x509_read_crls_from_dir: directory name too long");
687 return 0;
688 }
689 LOG_DBG((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs "log_debug (LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs "
"from %s", name)
690 "from %s", name))log_debug (LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs "
"from %s", name)
;
691
692 if (monitor_req_readdir(name) == -1) {
693 LOG_DBG((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir "log_debug (LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir "
"(\"%s\") failed: %s", name, strerror((*__errno())))
694 "(\"%s\") failed: %s", name, strerror(errno)))log_debug (LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir "
"(\"%s\") failed: %s", name, strerror((*__errno())))
;
695 return 0;
696 }
697 strlcpy(fullname, name, sizeof fullname);
698
699 while ((fd = monitor_readdir(file, sizeof file)) != -1) {
700 LOG_DBG((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading "log_debug (LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading "
"CRL %s", file)
701 "CRL %s", file))log_debug (LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading "
"CRL %s", file)
;
702
703 if (fstat(fd, &sb) == -1) {
704 log_error("x509_read_crls_from_dir: fstat failed");
705 close(fd);
706 continue;
707 }
708
709 if (!S_ISREG(sb.st_mode)((sb.st_mode & 0170000) == 0100000)) {
710 close(fd);
711 continue;
712 }
713
714 if ((crlfp = fdopen(fd, "r")) == NULL((void *)0)) {
715 log_error("x509_read_crls_from_dir: fdopen failed");
716 close(fd);
717 continue;
718 }
719
720 crl = PEM_read_X509_CRL(crlfp, NULL((void *)0), NULL((void *)0), NULL((void *)0));
721
722 fclose(crlfp);
723
724 if (crl == NULL((void *)0)) {
725 log_print("x509_read_crls_from_dir: "
726 "PEM_read_X509_CRL failed for %s",
727 file);
728 continue;
729 }
730 if (!X509_STORE_add_crl(ctx, crl)) {
731 LOG_DBG((LOG_CRYPTO, 50, "x509_read_crls_from_dir: "log_debug (LOG_CRYPTO, 50, "x509_read_crls_from_dir: " "X509_STORE_add_crl failed for %s"
, file)
732 "X509_STORE_add_crl failed for %s", file))log_debug (LOG_CRYPTO, 50, "x509_read_crls_from_dir: " "X509_STORE_add_crl failed for %s"
, file)
;
733 continue;
734 }
735 /*
736 * XXX This is to make x509_cert_validate set this (and
737 * XXX another) flag when validating certificates. Currently,
738 * XXX OpenSSL defaults to reject an otherwise valid
739 * XXX certificate (chain) if these flags are set but there
740 * XXX are no CRLs to check. The current workaround is to only
741 * XXX set the flags if we actually loaded some CRL data.
742 */
743 X509_STORE_set_flags(ctx, X509_V_FLAG_CRL_CHECK0x4);
744 }
745
746 return 1;
747}
748
749/* Initialize our databases and load our own certificates. */
750int
751x509_cert_init(void)
752{
753 char *dirname;
754
755 x509_hash_init();
756
757 /* Process CA certificates we will trust. */
758 dirname = conf_get_str("X509-certificates", "CA-directory");
759 if (!dirname) {
760 log_print("x509_cert_init: no CA-directory");
761 return 0;
762 }
763 /* Free if already initialized. */
764 if (x509_cas)
765 X509_STORE_free(x509_cas);
766
767 x509_cas = X509_STORE_new();
768 if (!x509_cas) {
769 log_print("x509_cert_init: creating new X509_STORE failed");
770 return 0;
771 }
772 if (!x509_read_from_dir(x509_cas, dirname, 0, &n_x509_cas)) {
773 log_print("x509_cert_init: x509_read_from_dir failed");
774 return 0;
775 }
776 /* Process client certificates we will accept. */
777 dirname = conf_get_str("X509-certificates", "Cert-directory");
778 if (!dirname) {
779 log_print("x509_cert_init: no Cert-directory");
780 return 0;
781 }
782 /* Free if already initialized. */
783 if (x509_certs)
784 X509_STORE_free(x509_certs);
785
786 x509_certs = X509_STORE_new();
787 if (!x509_certs) {
788 log_print("x509_cert_init: creating new X509_STORE failed");
789 return 0;
790 }
791 if (!x509_read_from_dir(x509_certs, dirname, 1, NULL((void *)0))) {
792 log_print("x509_cert_init: x509_read_from_dir failed");
793 return 0;
794 }
795 return 1;
796}
797
798int
799x509_crl_init(void)
800{
801 /*
802 * XXX I'm not sure if the method to use CRLs in certificate validation
803 * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not
804 * support it.
805 */
806 char *dirname;
807 dirname = conf_get_str("X509-certificates", "CRL-directory");
808 if (!dirname) {
809 log_print("x509_crl_init: no CRL-directory");
810 return 0;
811 }
812 if (!x509_read_crls_from_dir(x509_cas, dirname)) {
813 LOG_DBG((LOG_MISC, 10,log_debug (LOG_MISC, 10, "x509_crl_init: x509_read_crls_from_dir failed"
)
814 "x509_crl_init: x509_read_crls_from_dir failed"))log_debug (LOG_MISC, 10, "x509_crl_init: x509_read_crls_from_dir failed"
)
;
815 return 0;
816 }
817
818 return 1;
819}
820
821void *
822x509_cert_get(u_int8_t *asn, u_int32_t len)
823{
824 return x509_from_asn(asn, len);
825}
826
827int
828x509_cert_validate(void *scert)
829{
830 X509_STORE_CTX *csc;
831 X509_NAME *issuer, *subject;
832 X509 *cert = (X509 *) scert;
833 EVP_PKEY *key;
834 int res, err, flags;
835
836 /*
837 * Validate the peer certificate by checking with the CA certificates
838 * we trust.
839 */
840 csc = X509_STORE_CTX_new();
841 if (csc == NULL((void *)0)) {
842 log_print("x509_cert_validate: failed to get memory for "
843 "certificate store");
844 return 0;
845 }
846 X509_STORE_CTX_init(csc, x509_cas, cert, NULL((void *)0));
847 /* XXX See comment in x509_read_crls_from_dir. */
848 flags = X509_VERIFY_PARAM_get_flags(X509_STORE_get0_param(x509_cas));
849 if (flags & X509_V_FLAG_CRL_CHECK0x4) {
850 X509_STORE_CTX_set_flags(csc, X509_V_FLAG_CRL_CHECK0x4);
851 X509_STORE_CTX_set_flags(csc, X509_V_FLAG_CRL_CHECK_ALL0x8);
852 }
853 res = X509_verify_cert(csc);
854 err = X509_STORE_CTX_get_error(csc);
855 X509_STORE_CTX_free(csc);
856
857 /*
858 * Return if validation succeeded or self-signed certs are not
859 * accepted.
860 *
861 * XXX X509_verify_cert seems to return -1 if the validation should be
862 * retried somehow. We take this as an error and give up.
863 */
864 if (res > 0)
865 return 1;
866 else if (res < 0 ||
867 (res == 0 && err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT18)) {
868 if (err)
869 log_print("x509_cert_validate: %.100s",
870 X509_verify_cert_error_string(err));
871 return 0;
872 } else if (!conf_get_str("X509-certificates", "Accept-self-signed")) {
873 if (err)
874 log_print("x509_cert_validate: %.100s",
875 X509_verify_cert_error_string(err));
876 return 0;
877 }
878 issuer = X509_get_issuer_name(cert);
879 subject = X509_get_subject_name(cert);
880
881 if (!issuer || !subject || X509_NAME_cmp(issuer, subject))
882 return 0;
883
884 key = X509_get_pubkey(cert);
885 if (!key) {
886 log_print("x509_cert_validate: could not get public key from "
887 "self-signed cert");
888 return 0;
889 }
890 if (X509_verify(cert, key) == -1) {
891 log_print("x509_cert_validate: self-signed cert is bad");
892 return 0;
893 }
894 return 1;
895}
896
897int
898x509_cert_insert(int id, void *scert)
899{
900 X509 *cert;
901 int res;
902
903 cert = X509_dup((X509 *)scert);
904 if (!cert) {
905 log_print("x509_cert_insert: X509_dup failed");
906 return 0;
907 }
908 if (x509_generate_kn(id, cert) == 0) {
909 LOG_DBG((LOG_POLICY, 50,log_debug (LOG_POLICY, 50, "x509_cert_insert: x509_generate_kn failed"
)
910 "x509_cert_insert: x509_generate_kn failed"))log_debug (LOG_POLICY, 50, "x509_cert_insert: x509_generate_kn failed"
)
;
911 X509_free(cert);
912 return 0;
913 }
914
915 res = x509_hash_enter(cert);
916 if (!res)
917 X509_free(cert);
918
919 return res;
920}
921
922static struct x509_hash *
923x509_hash_lookup(X509 *cert)
924{
925 struct x509_hash *certh;
926 int i;
927
928 for (i = 0; i <= bucket_mask; i++)
929 for (certh = LIST_FIRST(&x509_tab[i])((&x509_tab[i])->lh_first); certh;
930 certh = LIST_NEXT(certh, link)((certh)->link.le_next))
931 if (certh->cert == cert)
932 return certh;
933 return 0;
934}
935
936void
937x509_cert_free(void *cert)
938{
939 struct x509_hash *certh = x509_hash_lookup((X509 *) cert);
940
941 if (certh)
942 LIST_REMOVE(certh, link)do { if ((certh)->link.le_next != ((void *)0)) (certh)->
link.le_next->link.le_prev = (certh)->link.le_prev; *(certh
)->link.le_prev = (certh)->link.le_next; ; ; } while (0
)
;
943 X509_free((X509 *) cert);
944}
945
946/* Validate the BER Encoding of a RDNSequence in the CERT_REQ payload. */
947int
948x509_certreq_validate(u_int8_t *asn, u_int32_t len)
949{
950 int res = 1;
951#if 0
952 struct norm_type name = SEQOF("issuer", RDNSequence);
953
954 if (!asn_template_clone(&name, 1) ||
955 (asn = asn_decode_sequence(asn, len, &name)) == 0) {
956 log_print("x509_certreq_validate: can not decode 'acceptable "
957 "CA' info");
958 res = 0;
959 }
960 asn_free(&name);
961#endif
962
963 /* XXX - not supported directly in SSL - later. */
964
965 return res;
966}
967
968/* Decode the BER Encoding of a RDNSequence in the CERT_REQ payload. */
969int
970x509_certreq_decode(void **pdata, u_int8_t *asn, u_int32_t len)
971{
972#if 0
973 /* XXX This needs to be done later. */
974 struct norm_type aca = SEQOF("aca", RDNSequence);
975 struct norm_type *tmp;
976 struct x509_aca naca, *ret;
977
978 if (!asn_template_clone(&aca, 1) ||
979 (asn = asn_decode_sequence(asn, len, &aca)) == 0) {
980 log_print("x509_certreq_decode: can not decode 'acceptable "
981 "CA' info");
982 goto fail;
983 }
984 bzero(&naca, sizeof(naca));
985
986 tmp = asn_decompose("aca.RelativeDistinguishedName."
987 "AttributeValueAssertion", &aca);
988 if (!tmp)
989 goto fail;
990 x509_get_attribval(tmp, &naca.name1);
991
992 tmp = asn_decompose("aca.RelativeDistinguishedName[1]"
993 ".AttributeValueAssertion", &aca);
994 if (tmp)
995 x509_get_attribval(tmp, &naca.name2);
996
997 asn_free(&aca);
998
999 ret = malloc(sizeof(struct x509_aca));
1000 if (ret)
1001 memcpy(ret, &naca, sizeof(struct x509_aca));
1002 else {
1003 log_error("x509_certreq_decode: malloc (%lu) failed",
1004 (unsigned long) sizeof(struct x509_aca));
1005 x509_free_aca(&aca);
1006 }
1007
1008 return ret;
1009
1010fail:
1011 asn_free(&aca);
1012#endif
1013 return 1;
1014}
1015
1016void
1017x509_free_aca(void *blob)
1018{
1019 struct x509_aca *aca = blob;
1020
1021 if (aca != NULL((void *)0)) {
1022 free(aca->name1.type);
1023 free(aca->name1.val);
1024
1025 free(aca->name2.type);
1026 free(aca->name2.val);
1027 }
1028}
1029
1030X509 *
1031x509_from_asn(u_char *asn, u_int len)
1032{
1033 BIO *certh;
1034 X509 *scert = 0;
1035
1036 certh = BIO_new(BIO_s_mem());
1037 if (!certh) {
1038 log_error("x509_from_asn: BIO_new (BIO_s_mem ()) failed");
1039 return 0;
1040 }
1041 if (BIO_write(certh, asn, len) == -1) {
1042 log_error("x509_from_asn: BIO_write failed\n");
1043 goto end;
1044 }
1045 scert = d2i_X509_bio(certh, NULL((void *)0));
1046 if (!scert) {
1047 log_print("x509_from_asn: d2i_X509_bio failed\n");
1048 goto end;
1049 }
1050end:
1051 BIO_free(certh);
1052 return scert;
1053}
1054
1055/*
1056 * Obtain a certificate from an acceptable CA.
1057 * XXX We don't check if the certificate we find is from an accepted CA.
1058 */
1059int
1060x509_cert_obtain(u_int8_t *id, size_t id_len, void *data, u_int8_t **cert,
1061 u_int32_t *certlen)
1062{
1063 struct x509_aca *aca = data;
1064 X509 *scert;
1065
1066 if (aca)
1
Assuming 'aca' is null
2
Taking false branch
1067 LOG_DBG((LOG_CRYPTO, 60, "x509_cert_obtain: "log_debug (LOG_CRYPTO, 60, "x509_cert_obtain: " "acceptable certificate authorities here"
)
1068 "acceptable certificate authorities here"))log_debug (LOG_CRYPTO, 60, "x509_cert_obtain: " "acceptable certificate authorities here"
)
;
1069
1070 /* We need our ID to find a certificate. */
1071 if (!id) {
3
Assuming 'id' is non-null
4
Taking false branch
1072 log_print("x509_cert_obtain: ID is missing");
1073 return 0;
1074 }
1075 scert = x509_hash_find(id, id_len);
5
Calling 'x509_hash_find'
1076 if (!scert)
1077 return 0;
1078
1079 x509_serialize(scert, cert, certlen);
1080 if (!*cert)
1081 return 0;
1082 return 1;
1083}
1084
1085/* Returns a pointer to the subjectAltName information of X509 certificate. */
1086int
1087x509_cert_subjectaltname(X509 *scert, u_int8_t **altname, u_int32_t *len)
1088{
1089 X509_EXTENSION *subjectaltname;
1090 ASN1_OCTET_STRING *sanasn1data;
1091 u_int8_t *sandata;
1092 int extpos, santype, sanlen;
1093
1094 extpos = X509_get_ext_by_NID(scert, NID_subject_alt_name85, -1);
1095 if (extpos == -1) {
1096 log_print("x509_cert_subjectaltname: "
1097 "certificate does not contain subjectAltName");
1098 return 0;
1099 }
1100 subjectaltname = X509_get_ext(scert, extpos);
1101 sanasn1data = X509_EXTENSION_get_data(subjectaltname);
1102
1103 if (!subjectaltname || !sanasn1data || !sanasn1data->data ||
1104 sanasn1data->length < 4) {
1105 log_print("x509_cert_subjectaltname: invalid "
1106 "subjectaltname extension");
1107 return 0;
1108 }
1109 /* SSL does not handle unknown ASN stuff well, do it by hand. */
1110 sandata = sanasn1data->data;
1111 santype = sandata[2] & 0x3f;
1112 sanlen = sandata[3];
1113 sandata += 4;
1114
1115 /*
1116 * The test here used to be !=, but some certificates can include
1117 * extra stuff in subjectAltName, so we will just take the first
1118 * salen bytes, and not worry about what follows.
1119 */
1120 if (sanlen + 4 > sanasn1data->length) {
1121 log_print("x509_cert_subjectaltname: subjectaltname invalid "
1122 "length");
1123 return 0;
1124 }
1125 *len = sanlen;
1126 *altname = sandata;
1127 return santype;
1128}
1129
1130int
1131x509_cert_get_subjects(void *scert, int *cnt, u_int8_t ***id,
1132 u_int32_t **id_len)
1133{
1134 X509 *cert = scert;
1135 X509_NAME *subject;
1136 int type;
1137 u_int8_t *altname;
1138 u_int32_t altlen;
1139 u_int8_t *buf = 0;
1140 unsigned char *ubuf;
1141 int i;
1142
1143 *id = 0;
1144 *id_len = 0;
1145
1146 /*
1147 * XXX There can be a collection of subjectAltNames, but for now I
1148 * only return the subjectName and a single subjectAltName, if
1149 * present.
1150 */
1151 type = x509_cert_subjectaltname(cert, &altname, &altlen);
1152 if (!type) {
8
Assuming 'type' is not equal to 0
9
Taking false branch
1153 *cnt = 1;
1154 altlen = 0;
1155 } else
1156 *cnt = 2;
1157
1158 *id = calloc(*cnt, sizeof **id);
10
Storing null pointer value
1159 if (!*id) {
11
Assuming the condition is false
12
Taking false branch
1160 log_print("x509_cert_get_subject: malloc (%lu) failed",
1161 *cnt * (unsigned long)sizeof **id);
1162 *cnt = 0;
1163 goto fail;
1164 }
1165 *id_len = calloc(*cnt, sizeof **id_len);
1166 if (!*id_len) {
13
Assuming the condition is false
14
Taking false branch
1167 log_print("x509_cert_get_subject: malloc (%lu) failed",
1168 *cnt * (unsigned long)sizeof **id_len);
1169 goto fail;
1170 }
1171 /* Stash the subjectName into the first slot. */
1172 subject = X509_get_subject_name(cert);
1173 if (!subject)
15
Assuming 'subject' is non-null
16
Taking false branch
1174 goto fail;
1175
1176 (*id_len)[0] =
1177 ISAKMP_ID_DATA_OFF8 + i2d_X509_NAME(subject, NULL((void *)0)) -
1178 ISAKMP_GEN_SZ4;
1179 (*id)[0] = malloc((*id_len)[0]);
1180 if (!(*id)[0]) {
17
Assuming the condition is false
18
Taking false branch
1181 log_print("x509_cert_get_subject: malloc (%d) failed",
1182 (*id_len)[0]);
1183 goto fail;
1184 }
1185 SET_ISAKMP_ID_TYPE((*id)[0] - ISAKMP_GEN_SZ, IPSEC_ID_DER_ASN1_DN)field_set_num (isakmp_id_fld + 0, (*id)[0] - 4, 9);
1186 ubuf = (*id)[0] + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4;
1187 i2d_X509_NAME(subject, &ubuf);
1188
1189 if (altlen) {
19
Assuming 'altlen' is 0
20
Taking false branch
1190 /* Stash the subjectAltName into the second slot. */
1191 buf = malloc(altlen + ISAKMP_ID_DATA_OFF8);
1192 if (!buf) {
1193 log_print("x509_cert_get_subject: malloc (%d) failed",
1194 altlen + ISAKMP_ID_DATA_OFF8);
1195 goto fail;
1196 }
1197 switch (type) {
1198 case X509v3_DNS_NAME2:
1199 SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_FQDN)field_set_num (isakmp_id_fld + 0, buf, 2);
1200 break;
1201
1202 case X509v3_RFC_NAME1:
1203 SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_USER_FQDN)field_set_num (isakmp_id_fld + 0, buf, 3);
1204 break;
1205
1206 case X509v3_IP_ADDR7:
1207 /*
1208 * XXX I dislike the numeric constants, but I don't
1209 * know what we should use otherwise.
1210 */
1211 switch (altlen) {
1212 case 4:
1213 SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV4_ADDR)field_set_num (isakmp_id_fld + 0, buf, 1);
1214 break;
1215
1216 case 16:
1217 SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV6_ADDR)field_set_num (isakmp_id_fld + 0, buf, 5);
1218 break;
1219
1220 default:
1221 log_print("x509_cert_get_subject: invalid "
1222 "subjectAltName IPaddress length %d ",
1223 altlen);
1224 goto fail;
1225 }
1226 break;
1227 }
1228
1229 SET_IPSEC_ID_PROTO(buf + ISAKMP_ID_DOI_DATA_OFF, 0)field_set_num (ipsec_id_fld + 0, buf + 5, 0);
1230 SET_IPSEC_ID_PORT(buf + ISAKMP_ID_DOI_DATA_OFF, 0)field_set_num (ipsec_id_fld + 1, buf + 5, 0);
1231 memcpy(buf + ISAKMP_ID_DATA_OFF8, altname, altlen);
1232
1233 (*id_len)[1] = ISAKMP_ID_DATA_OFF8 + altlen - ISAKMP_GEN_SZ4;
1234 (*id)[1] = malloc((*id_len)[1]);
1235 if (!(*id)[1]) {
1236 log_print("x509_cert_get_subject: malloc (%d) failed",
1237 (*id_len)[1]);
1238 goto fail;
1239 }
1240 memcpy((*id)[1], buf + ISAKMP_GEN_SZ4, (*id_len)[1]);
1241
1242 free(buf);
1243 buf = 0;
1244 }
1245 return 1;
1246
1247fail:
1248 for (i = 0; i < *cnt; i++)
1249 free((*id)[i]);
1250 free(*id);
1251 free(*id_len);
1252 free(buf);
1253 return 0;
1254}
1255
1256int
1257x509_cert_get_key(void *scert, void *keyp)
1258{
1259 X509 *cert = scert;
1260 EVP_PKEY *key;
1261
1262 key = X509_get_pubkey(cert);
1263
1264 /* Check if we got the right key type. */
1265 if (EVP_PKEY_id(key) != EVP_PKEY_RSA6) {
1266 log_print("x509_cert_get_key: public key is not a RSA key");
1267 X509_free(cert);
1268 return 0;
1269 }
1270 *(RSA **)keyp = RSAPublicKey_dup(EVP_PKEY_get0_RSA(key));
1271
1272 return *(RSA **)keyp == NULL((void *)0) ? 0 : 1;
1273}
1274
1275void *
1276x509_cert_dup(void *scert)
1277{
1278 return X509_dup(scert);
1279}
1280
1281void
1282x509_serialize(void *scert, u_int8_t **data, u_int32_t *datalen)
1283{
1284 u_int8_t *p;
1285
1286 *datalen = i2d_X509((X509 *)scert, NULL((void *)0));
1287 *data = p = malloc(*datalen);
1288 if (!p) {
1289 log_error("x509_serialize: malloc (%d) failed", *datalen);
1290 return;
1291 }
1292 *datalen = i2d_X509((X509 *)scert, &p);
1293}
1294
1295/* From cert to printable */
1296char *
1297x509_printable(void *cert)
1298{
1299 char *s;
1300 u_int8_t *data;
1301 u_int32_t datalen;
1302
1303 x509_serialize(cert, &data, &datalen);
1304 if (!data)
1305 return 0;
1306
1307 s = raw2hex(data, datalen);
1308 free(data);
1309 return s;
1310}
1311
1312/* From printable to cert */
1313void *
1314x509_from_printable(char *cert)
1315{
1316 u_int8_t *buf;
1317 int plen, ret;
1318 void *foo;
1319
1320 plen = (strlen(cert) + 1) / 2;
1321 buf = malloc(plen);
1322 if (!buf) {
1323 log_error("x509_from_printable: malloc (%d) failed", plen);
1324 return 0;
1325 }
1326 ret = hex2raw(cert, buf, plen);
1327 if (ret == -1) {
1328 free(buf);
1329 log_print("x509_from_printable: badly formatted cert");
1330 return 0;
1331 }
1332 foo = x509_cert_get(buf, plen);
1333 free(buf);
1334 if (!foo)
1335 log_print("x509_from_printable: "
1336 "could not retrieve certificate");
1337 return foo;
1338}
1339
1340char *
1341x509_DN_string(u_int8_t *asn1, size_t sz)
1342{
1343 X509_NAME *name;
1344 const u_int8_t *p = asn1;
1345 char buf[256]; /* XXX Just a guess at a maximum length. */
1346 long len = sz;
1347
1348 name = d2i_X509_NAME(NULL((void *)0), &p, len);
1349 if (!name) {
1350 log_print("x509_DN_string: d2i_X509_NAME failed");
1351 return 0;
1352 }
1353 if (!X509_NAME_oneline(name, buf, sizeof buf - 1)) {
1354 log_print("x509_DN_string: X509_NAME_oneline failed");
1355 X509_NAME_free(name);
1356 return 0;
1357 }
1358 X509_NAME_free(name);
1359 buf[sizeof buf - 1] = '\0';
1360 return strdup(buf);
1361}
1362
1363/* Number of CAs we trust (to decide whether we can send CERT_REQ) */
1364int
1365x509_ca_count(void)
1366{
1367 return n_x509_cas;
1368}