1 /*
2 * Written by Dr Stephen N Henson ([email protected]) for the OpenSSL project
3 * 2004.
4 */
5 /* ====================================================================
6 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * [email protected].
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * ([email protected]). This product includes software written by Tim
55 * Hudson ([email protected]). */
56
57 #include <string.h>
58
59 #include <openssl/mem.h>
60 #include <openssl/obj.h>
61 #include <openssl/stack.h>
62 #include <openssl/x509.h>
63
64 #include "../internal.h"
65 #include "internal.h"
66
67
68 // X509_VERIFY_PARAM functions
69
70 #define SET_HOST 0
71 #define ADD_HOST 1
72
str_free(char * s)73 static void str_free(char *s) { OPENSSL_free(s); }
74
int_x509_param_set_hosts(X509_VERIFY_PARAM * param,int mode,const char * name,size_t namelen)75 static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode,
76 const char *name, size_t namelen) {
77 char *copy;
78
79 if (name == NULL || namelen == 0) {
80 // Unlike OpenSSL, we reject trying to set or add an empty name.
81 return 0;
82 }
83
84 // Refuse names with embedded NUL bytes.
85 // XXX: Do we need to push an error onto the error stack?
86 if (name && OPENSSL_memchr(name, '\0', namelen)) {
87 return 0;
88 }
89
90 if (mode == SET_HOST && param->hosts) {
91 sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
92 param->hosts = NULL;
93 }
94
95 copy = OPENSSL_strndup(name, namelen);
96 if (copy == NULL) {
97 return 0;
98 }
99
100 if (param->hosts == NULL &&
101 (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
102 OPENSSL_free(copy);
103 return 0;
104 }
105
106 if (!sk_OPENSSL_STRING_push(param->hosts, copy)) {
107 OPENSSL_free(copy);
108 if (sk_OPENSSL_STRING_num(param->hosts) == 0) {
109 sk_OPENSSL_STRING_free(param->hosts);
110 param->hosts = NULL;
111 }
112 return 0;
113 }
114
115 return 1;
116 }
117
X509_VERIFY_PARAM_new(void)118 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) {
119 X509_VERIFY_PARAM *param = OPENSSL_zalloc(sizeof(X509_VERIFY_PARAM));
120 if (!param) {
121 return NULL;
122 }
123 param->depth = -1;
124 return param;
125 }
126
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM * param)127 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) {
128 if (param == NULL) {
129 return;
130 }
131 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
132 sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
133 OPENSSL_free(param->email);
134 OPENSSL_free(param->ip);
135 OPENSSL_free(param);
136 }
137
should_copy(int dest_is_set,int src_is_set,int prefer_src)138 static int should_copy(int dest_is_set, int src_is_set, int prefer_src) {
139 if (prefer_src) {
140 // We prefer the source, so as long as there is a value to copy, copy it.
141 return src_is_set;
142 }
143
144 // We prefer the destination, so only copy if the destination is unset.
145 return src_is_set && !dest_is_set;
146 }
147
copy_int_param(int * dest,const int * src,int default_val,int prefer_src)148 static void copy_int_param(int *dest, const int *src, int default_val,
149 int prefer_src) {
150 if (should_copy(*dest != default_val, *src != default_val, prefer_src)) {
151 *dest = *src;
152 }
153 }
154
155 // x509_verify_param_copy copies fields from |src| to |dest|. If both |src| and
156 // |dest| have some field set, |prefer_src| determines whether |src| or |dest|'s
157 // version is used.
x509_verify_param_copy(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src,int prefer_src)158 static int x509_verify_param_copy(X509_VERIFY_PARAM *dest,
159 const X509_VERIFY_PARAM *src,
160 int prefer_src) {
161 if (src == NULL) {
162 return 1;
163 }
164
165 copy_int_param(&dest->purpose, &src->purpose, /*default_val=*/0, prefer_src);
166 copy_int_param(&dest->trust, &src->trust, /*default_val=*/0, prefer_src);
167 copy_int_param(&dest->depth, &src->depth, /*default_val=*/-1, prefer_src);
168
169 // |check_time|, unlike all other parameters, does not honor |prefer_src|.
170 // This means |X509_VERIFY_PARAM_set1| will not overwrite it. This behavior
171 // comes from OpenSSL but may have been a bug.
172 if (!(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
173 dest->check_time = src->check_time;
174 // The source |X509_V_FLAG_USE_CHECK_TIME| flag, if set, is copied below.
175 }
176
177 dest->flags |= src->flags;
178
179 if (should_copy(dest->policies != NULL, src->policies != NULL, prefer_src)) {
180 if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) {
181 return 0;
182 }
183 }
184
185 if (should_copy(dest->hosts != NULL, src->hosts != NULL, prefer_src)) {
186 sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
187 dest->hosts = NULL;
188 if (src->hosts) {
189 dest->hosts =
190 sk_OPENSSL_STRING_deep_copy(src->hosts, OPENSSL_strdup, str_free);
191 if (dest->hosts == NULL) {
192 return 0;
193 }
194 // Copy the host flags if and only if we're copying the host list. Note
195 // this means mechanisms like |X509_STORE_CTX_set_default| cannot be used
196 // to set host flags. E.g. we cannot change the defaults using
197 // |kDefaultParam| below.
198 dest->hostflags = src->hostflags;
199 }
200 }
201
202 if (should_copy(dest->email != NULL, src->email != NULL, prefer_src)) {
203 if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) {
204 return 0;
205 }
206 }
207
208 if (should_copy(dest->ip != NULL, src->ip != NULL, prefer_src)) {
209 if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) {
210 return 0;
211 }
212 }
213
214 dest->poison = src->poison;
215 return 1;
216 }
217
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src)218 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
219 const X509_VERIFY_PARAM *src) {
220 // Prefer the destination. That is, this function only changes unset
221 // parameters in |dest|.
222 return x509_verify_param_copy(dest, src, /*prefer_src=*/0);
223 }
224
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM * to,const X509_VERIFY_PARAM * from)225 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
226 const X509_VERIFY_PARAM *from) {
227 // Prefer the source. That is, values in |to| are only preserved if they were
228 // unset in |from|.
229 return x509_verify_param_copy(to, from, /*prefer_src=*/1);
230 }
231
int_x509_param_set1(char ** pdest,size_t * pdestlen,const char * src,size_t srclen)232 static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src,
233 size_t srclen) {
234 void *tmp;
235 if (src == NULL || srclen == 0) {
236 // Unlike OpenSSL, we do not allow an empty string to disable previously
237 // configured checks.
238 return 0;
239 }
240
241 tmp = OPENSSL_memdup(src, srclen);
242 if (!tmp) {
243 return 0;
244 }
245
246 if (*pdest) {
247 OPENSSL_free(*pdest);
248 }
249 *pdest = tmp;
250 if (pdestlen) {
251 *pdestlen = srclen;
252 }
253 return 1;
254 }
255
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM * param,unsigned long flags)256 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) {
257 param->flags |= flags;
258 return 1;
259 }
260
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM * param,unsigned long flags)261 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
262 unsigned long flags) {
263 param->flags &= ~flags;
264 return 1;
265 }
266
X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM * param)267 unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param) {
268 return param->flags;
269 }
270
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM * param,int purpose)271 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) {
272 if (X509_PURPOSE_get0(purpose) == NULL) {
273 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
274 return 0;
275 }
276 param->purpose = purpose;
277 return 1;
278 }
279
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM * param,int trust)280 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) {
281 if (!X509_is_valid_trust_id(trust)) {
282 OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
283 return 0;
284 }
285
286 param->trust = trust;
287 return 1;
288 }
289
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM * param,int depth)290 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) {
291 param->depth = depth;
292 }
293
X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM * param,int64_t t)294 void X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM *param, int64_t t) {
295 param->check_time = t;
296 param->flags |= X509_V_FLAG_USE_CHECK_TIME;
297 }
298
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM * param,time_t t)299 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) {
300 X509_VERIFY_PARAM_set_time_posix(param, t);
301 }
302
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM * param,ASN1_OBJECT * policy)303 int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
304 ASN1_OBJECT *policy) {
305 if (!param->policies) {
306 param->policies = sk_ASN1_OBJECT_new_null();
307 if (!param->policies) {
308 return 0;
309 }
310 }
311 if (!sk_ASN1_OBJECT_push(param->policies, policy)) {
312 return 0;
313 }
314 return 1;
315 }
316
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM * param,const STACK_OF (ASN1_OBJECT)* policies)317 int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
318 const STACK_OF(ASN1_OBJECT) *policies) {
319 if (!param) {
320 return 0;
321 }
322
323 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
324 if (!policies) {
325 param->policies = NULL;
326 return 1;
327 }
328
329 param->policies =
330 sk_ASN1_OBJECT_deep_copy(policies, OBJ_dup, ASN1_OBJECT_free);
331 if (!param->policies) {
332 return 0;
333 }
334
335 return 1;
336 }
337
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)338 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name,
339 size_t namelen) {
340 if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) {
341 param->poison = 1;
342 return 0;
343 }
344 return 1;
345 }
346
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)347 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name,
348 size_t namelen) {
349 if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) {
350 param->poison = 1;
351 return 0;
352 }
353 return 1;
354 }
355
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM * param,unsigned int flags)356 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
357 unsigned int flags) {
358 param->hostflags = flags;
359 }
360
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM * param,const char * email,size_t emaillen)361 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
362 size_t emaillen) {
363 if (OPENSSL_memchr(email, '\0', emaillen) != NULL ||
364 !int_x509_param_set1(¶m->email, ¶m->emaillen, email, emaillen)) {
365 param->poison = 1;
366 return 0;
367 }
368
369 return 1;
370 }
371
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM * param,const unsigned char * ip,size_t iplen)372 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
373 size_t iplen) {
374 if ((iplen != 4 && iplen != 16) ||
375 !int_x509_param_set1((char **)¶m->ip, ¶m->iplen, (char *)ip,
376 iplen)) {
377 param->poison = 1;
378 return 0;
379 }
380
381 return 1;
382 }
383
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM * param,const char * ipasc)384 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) {
385 unsigned char ipout[16];
386 size_t iplen;
387
388 iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc);
389 if (iplen == 0) {
390 return 0;
391 }
392 return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
393 }
394
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM * param)395 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) {
396 return param->depth;
397 }
398
399 static const X509_VERIFY_PARAM kDefaultParam = {
400 .flags = X509_V_FLAG_TRUSTED_FIRST,
401 .depth = 100,
402 };
403
404 static const X509_VERIFY_PARAM kSMIMESignParam = {
405 .purpose = X509_PURPOSE_SMIME_SIGN,
406 .trust = X509_TRUST_EMAIL,
407 .depth = -1,
408 };
409
410 static const X509_VERIFY_PARAM kSSLClientParam = {
411 .purpose = X509_PURPOSE_SSL_CLIENT,
412 .trust = X509_TRUST_SSL_CLIENT,
413 .depth = -1,
414 };
415
416 static const X509_VERIFY_PARAM kSSLServerParam = {
417 .purpose = X509_PURPOSE_SSL_SERVER,
418 .trust = X509_TRUST_SSL_SERVER,
419 .depth = -1,
420 };
421
X509_VERIFY_PARAM_lookup(const char * name)422 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) {
423 if (strcmp(name, "default") == 0) {
424 return &kDefaultParam;
425 }
426 if (strcmp(name, "pkcs7") == 0) {
427 // PKCS#7 and S/MIME signing use the same defaults.
428 return &kSMIMESignParam;
429 }
430 if (strcmp(name, "smime_sign") == 0) {
431 return &kSMIMESignParam;
432 }
433 if (strcmp(name, "ssl_client") == 0) {
434 return &kSSLClientParam;
435 }
436 if (strcmp(name, "ssl_server") == 0) {
437 return &kSSLServerParam;
438 }
439 return NULL;
440 }
441