1 // Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string.h>
16
17 #include <openssl/mem.h>
18 #include <openssl/obj.h>
19 #include <openssl/stack.h>
20 #include <openssl/x509.h>
21
22 #include "../internal.h"
23 #include "internal.h"
24
25
26 // X509_VERIFY_PARAM functions
27
28 #define SET_HOST 0
29 #define ADD_HOST 1
30
str_free(char * s)31 static void str_free(char *s) { OPENSSL_free(s); }
32
int_x509_param_set_hosts(X509_VERIFY_PARAM * param,int mode,const char * name,size_t namelen)33 static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode,
34 const char *name, size_t namelen) {
35 char *copy;
36
37 if (name == NULL || namelen == 0) {
38 // Unlike OpenSSL, we reject trying to set or add an empty name.
39 return 0;
40 }
41
42 // Refuse names with embedded NUL bytes.
43 // XXX: Do we need to push an error onto the error stack?
44 if (name && OPENSSL_memchr(name, '\0', namelen)) {
45 return 0;
46 }
47
48 if (mode == SET_HOST && param->hosts) {
49 sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
50 param->hosts = NULL;
51 }
52
53 copy = OPENSSL_strndup(name, namelen);
54 if (copy == NULL) {
55 return 0;
56 }
57
58 if (param->hosts == NULL &&
59 (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
60 OPENSSL_free(copy);
61 return 0;
62 }
63
64 if (!sk_OPENSSL_STRING_push(param->hosts, copy)) {
65 OPENSSL_free(copy);
66 if (sk_OPENSSL_STRING_num(param->hosts) == 0) {
67 sk_OPENSSL_STRING_free(param->hosts);
68 param->hosts = NULL;
69 }
70 return 0;
71 }
72
73 return 1;
74 }
75
X509_VERIFY_PARAM_new(void)76 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) {
77 X509_VERIFY_PARAM *param = reinterpret_cast<X509_VERIFY_PARAM *>(
78 OPENSSL_zalloc(sizeof(X509_VERIFY_PARAM)));
79 if (!param) {
80 return NULL;
81 }
82 param->depth = -1;
83 return param;
84 }
85
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM * param)86 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) {
87 if (param == NULL) {
88 return;
89 }
90 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
91 sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
92 OPENSSL_free(param->email);
93 OPENSSL_free(param->ip);
94 OPENSSL_free(param);
95 }
96
should_copy(int dest_is_set,int src_is_set,int prefer_src)97 static int should_copy(int dest_is_set, int src_is_set, int prefer_src) {
98 if (prefer_src) {
99 // We prefer the source, so as long as there is a value to copy, copy it.
100 return src_is_set;
101 }
102
103 // We prefer the destination, so only copy if the destination is unset.
104 return src_is_set && !dest_is_set;
105 }
106
copy_int_param(int * dest,const int * src,int default_val,int prefer_src)107 static void copy_int_param(int *dest, const int *src, int default_val,
108 int prefer_src) {
109 if (should_copy(*dest != default_val, *src != default_val, prefer_src)) {
110 *dest = *src;
111 }
112 }
113
114 // x509_verify_param_copy copies fields from |src| to |dest|. If both |src| and
115 // |dest| have some field set, |prefer_src| determines whether |src| or |dest|'s
116 // version is used.
x509_verify_param_copy(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src,int prefer_src)117 static int x509_verify_param_copy(X509_VERIFY_PARAM *dest,
118 const X509_VERIFY_PARAM *src,
119 int prefer_src) {
120 if (src == NULL) {
121 return 1;
122 }
123
124 copy_int_param(&dest->purpose, &src->purpose, /*default_val=*/0, prefer_src);
125 copy_int_param(&dest->trust, &src->trust, /*default_val=*/0, prefer_src);
126 copy_int_param(&dest->depth, &src->depth, /*default_val=*/-1, prefer_src);
127
128 // |check_time|, unlike all other parameters, does not honor |prefer_src|.
129 // This means |X509_VERIFY_PARAM_set1| will not overwrite it. This behavior
130 // comes from OpenSSL but may have been a bug.
131 if (!(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
132 dest->check_time = src->check_time;
133 // The source |X509_V_FLAG_USE_CHECK_TIME| flag, if set, is copied below.
134 }
135
136 dest->flags |= src->flags;
137
138 if (should_copy(dest->policies != NULL, src->policies != NULL, prefer_src)) {
139 if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) {
140 return 0;
141 }
142 }
143
144 if (should_copy(dest->hosts != NULL, src->hosts != NULL, prefer_src)) {
145 sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
146 dest->hosts = NULL;
147 if (src->hosts) {
148 dest->hosts =
149 sk_OPENSSL_STRING_deep_copy(src->hosts, OPENSSL_strdup, str_free);
150 if (dest->hosts == NULL) {
151 return 0;
152 }
153 // Copy the host flags if and only if we're copying the host list. Note
154 // this means mechanisms like |X509_STORE_CTX_set_default| cannot be used
155 // to set host flags. E.g. we cannot change the defaults using
156 // |kDefaultParam| below.
157 dest->hostflags = src->hostflags;
158 }
159 }
160
161 if (should_copy(dest->email != NULL, src->email != NULL, prefer_src)) {
162 if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) {
163 return 0;
164 }
165 }
166
167 if (should_copy(dest->ip != NULL, src->ip != NULL, prefer_src)) {
168 if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) {
169 return 0;
170 }
171 }
172
173 dest->poison = src->poison;
174 return 1;
175 }
176
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src)177 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
178 const X509_VERIFY_PARAM *src) {
179 // Prefer the destination. That is, this function only changes unset
180 // parameters in |dest|.
181 return x509_verify_param_copy(dest, src, /*prefer_src=*/0);
182 }
183
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM * to,const X509_VERIFY_PARAM * from)184 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
185 const X509_VERIFY_PARAM *from) {
186 // Prefer the source. That is, values in |to| are only preserved if they were
187 // unset in |from|.
188 return x509_verify_param_copy(to, from, /*prefer_src=*/1);
189 }
190
int_x509_param_set1(char ** pdest,size_t * pdestlen,const char * src,size_t srclen)191 static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src,
192 size_t srclen) {
193 void *tmp;
194 if (src == NULL || srclen == 0) {
195 // Unlike OpenSSL, we do not allow an empty string to disable previously
196 // configured checks.
197 return 0;
198 }
199
200 tmp = OPENSSL_memdup(src, srclen);
201 if (!tmp) {
202 return 0;
203 }
204
205 if (*pdest) {
206 OPENSSL_free(*pdest);
207 }
208 *pdest = reinterpret_cast<char *>(tmp);
209 if (pdestlen) {
210 *pdestlen = srclen;
211 }
212 return 1;
213 }
214
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM * param,unsigned long flags)215 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) {
216 param->flags |= flags;
217 return 1;
218 }
219
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM * param,unsigned long flags)220 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
221 unsigned long flags) {
222 param->flags &= ~flags;
223 return 1;
224 }
225
X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM * param)226 unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param) {
227 return param->flags;
228 }
229
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM * param,int purpose)230 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) {
231 if (X509_PURPOSE_get0(purpose) == NULL) {
232 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
233 return 0;
234 }
235 param->purpose = purpose;
236 return 1;
237 }
238
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM * param,int trust)239 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) {
240 if (!X509_is_valid_trust_id(trust)) {
241 OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
242 return 0;
243 }
244
245 param->trust = trust;
246 return 1;
247 }
248
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM * param,int depth)249 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) {
250 param->depth = depth;
251 }
252
X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM * param,int64_t t)253 void X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM *param, int64_t t) {
254 param->check_time = t;
255 param->flags |= X509_V_FLAG_USE_CHECK_TIME;
256 }
257
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM * param,time_t t)258 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) {
259 X509_VERIFY_PARAM_set_time_posix(param, t);
260 }
261
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM * param,ASN1_OBJECT * policy)262 int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
263 ASN1_OBJECT *policy) {
264 if (!param->policies) {
265 param->policies = sk_ASN1_OBJECT_new_null();
266 if (!param->policies) {
267 return 0;
268 }
269 }
270 if (!sk_ASN1_OBJECT_push(param->policies, policy)) {
271 return 0;
272 }
273 return 1;
274 }
275
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM * param,const STACK_OF (ASN1_OBJECT)* policies)276 int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
277 const STACK_OF(ASN1_OBJECT) *policies) {
278 if (!param) {
279 return 0;
280 }
281
282 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
283 if (!policies) {
284 param->policies = NULL;
285 return 1;
286 }
287
288 param->policies =
289 sk_ASN1_OBJECT_deep_copy(policies, OBJ_dup, ASN1_OBJECT_free);
290 if (!param->policies) {
291 return 0;
292 }
293
294 return 1;
295 }
296
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)297 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name,
298 size_t namelen) {
299 if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) {
300 param->poison = 1;
301 return 0;
302 }
303 return 1;
304 }
305
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)306 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name,
307 size_t namelen) {
308 if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) {
309 param->poison = 1;
310 return 0;
311 }
312 return 1;
313 }
314
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM * param,unsigned int flags)315 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
316 unsigned int flags) {
317 param->hostflags = flags;
318 }
319
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM * param,const char * email,size_t emaillen)320 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
321 size_t emaillen) {
322 if (OPENSSL_memchr(email, '\0', emaillen) != NULL ||
323 !int_x509_param_set1(¶m->email, ¶m->emaillen, email, emaillen)) {
324 param->poison = 1;
325 return 0;
326 }
327
328 return 1;
329 }
330
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM * param,const unsigned char * ip,size_t iplen)331 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
332 size_t iplen) {
333 if ((iplen != 4 && iplen != 16) ||
334 !int_x509_param_set1((char **)¶m->ip, ¶m->iplen, (char *)ip,
335 iplen)) {
336 param->poison = 1;
337 return 0;
338 }
339
340 return 1;
341 }
342
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM * param,const char * ipasc)343 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) {
344 unsigned char ipout[16];
345 size_t iplen;
346
347 iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc);
348 if (iplen == 0) {
349 return 0;
350 }
351 return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
352 }
353
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM * param)354 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) {
355 return param->depth;
356 }
357
358 static const X509_VERIFY_PARAM kDefaultParam = {
359 /*check_time=*/0,
360 /*flags=*/X509_V_FLAG_TRUSTED_FIRST,
361 /*purpose=*/0,
362 /*trust=*/0,
363 /*depth=*/100,
364 /*policies=*/nullptr,
365 /*hosts=*/nullptr,
366 /*hostflags=*/0,
367 /*email=*/nullptr,
368 /*emaillen=*/0,
369 /*ip=*/nullptr,
370 /*iplen=*/0,
371 /*poison=*/0,
372 };
373
374 static const X509_VERIFY_PARAM kSMIMESignParam = {
375 /*check_time=*/0,
376 /*flags=*/0,
377 /*purpose=*/X509_PURPOSE_SMIME_SIGN,
378 /*trust=*/X509_TRUST_EMAIL,
379 /*depth=*/-1,
380 /*policies=*/nullptr,
381 /*hosts=*/nullptr,
382 /*hostflags=*/0,
383 /*email=*/nullptr,
384 /*emaillen=*/0,
385 /*ip=*/nullptr,
386 /*iplen=*/0,
387 /*poison=*/0,
388 };
389
390 static const X509_VERIFY_PARAM kSSLClientParam = {
391 /*check_time=*/0,
392 /*flags=*/0,
393 /*purpose=*/X509_PURPOSE_SSL_CLIENT,
394 /*trust=*/X509_TRUST_SSL_CLIENT,
395 /*depth=*/-1,
396 /*policies=*/nullptr,
397 /*hosts=*/nullptr,
398 /*hostflags=*/0,
399 /*email=*/nullptr,
400 /*emaillen=*/0,
401 /*ip=*/nullptr,
402 /*iplen=*/0,
403 /*poison=*/0,
404 };
405
406 static const X509_VERIFY_PARAM kSSLServerParam = {
407 /*check_time=*/0,
408 /*flags=*/0,
409 /*purpose=*/X509_PURPOSE_SSL_SERVER,
410 /*trust=*/X509_TRUST_SSL_SERVER,
411 /*depth=*/-1,
412 /*policies=*/nullptr,
413 /*hosts=*/nullptr,
414 /*hostflags=*/0,
415 /*email=*/nullptr,
416 /*emaillen=*/0,
417 /*ip=*/nullptr,
418 /*iplen=*/0,
419 /*poison=*/0,
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