• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
2 /*
3  * Contributed to the OpenSSL Project 2004 by Richard Levitte
4  * (richard@levitte.org)
5  */
6 /* Copyright (c) 2004 Kungliga Tekniska Högskolan
7  * (Royal Institute of Technology, Stockholm, Sweden).
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * 3. Neither the name of the Institute nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include <string.h>
39 
40 #include <openssl/conf.h>
41 #include <openssl/err.h>
42 #include <openssl/mem.h>
43 #include <openssl/obj.h>
44 #include <openssl/x509v3.h>
45 
46 #include "../internal.h"
47 #include "internal.h"
48 
49 
50 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
51                    BIO *out, int indent);
52 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
53                                           X509V3_CTX *ctx, char *str);
54 
55 const X509V3_EXT_METHOD v3_pci =
56     { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
57     0, 0, 0, 0,
58     0, 0,
59     NULL, NULL,
60     (X509V3_EXT_I2R)i2r_pci,
61     (X509V3_EXT_R2I)r2i_pci,
62     NULL,
63 };
64 
i2r_pci(X509V3_EXT_METHOD * method,PROXY_CERT_INFO_EXTENSION * pci,BIO * out,int indent)65 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
66                    BIO *out, int indent)
67 {
68     BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
69     if (pci->pcPathLengthConstraint)
70         i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
71     else
72         BIO_printf(out, "infinite");
73     BIO_puts(out, "\n");
74     BIO_printf(out, "%*sPolicy Language: ", indent, "");
75     i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
76     BIO_puts(out, "\n");
77     if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
78         BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
79                    pci->proxyPolicy->policy->data);
80     return 1;
81 }
82 
process_pci_value(CONF_VALUE * val,ASN1_OBJECT ** language,ASN1_INTEGER ** pathlen,ASN1_OCTET_STRING ** policy)83 static int process_pci_value(CONF_VALUE *val,
84                              ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
85                              ASN1_OCTET_STRING **policy)
86 {
87     int free_policy = 0;
88 
89     if (strcmp(val->name, "language") == 0) {
90         if (*language) {
91             OPENSSL_PUT_ERROR(X509V3,
92                               X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
93             X509V3_conf_err(val);
94             return 0;
95         }
96         if (!(*language = OBJ_txt2obj(val->value, 0))) {
97             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
98             X509V3_conf_err(val);
99             return 0;
100         }
101     } else if (strcmp(val->name, "pathlen") == 0) {
102         if (*pathlen) {
103             OPENSSL_PUT_ERROR(X509V3,
104                               X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
105             X509V3_conf_err(val);
106             return 0;
107         }
108         if (!X509V3_get_value_int(val, pathlen)) {
109             OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
110             X509V3_conf_err(val);
111             return 0;
112         }
113     } else if (strcmp(val->name, "policy") == 0) {
114         unsigned char *tmp_data = NULL;
115         long val_len;
116         if (!*policy) {
117             *policy = ASN1_OCTET_STRING_new();
118             if (!*policy) {
119                 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
120                 X509V3_conf_err(val);
121                 return 0;
122             }
123             free_policy = 1;
124         }
125         if (strncmp(val->value, "hex:", 4) == 0) {
126             unsigned char *tmp_data2 =
127                 x509v3_hex_to_bytes(val->value + 4, &val_len);
128 
129             if (!tmp_data2) {
130                 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
131                 X509V3_conf_err(val);
132                 goto err;
133             }
134 
135             tmp_data = OPENSSL_realloc((*policy)->data,
136                                        (*policy)->length + val_len + 1);
137             if (tmp_data) {
138                 (*policy)->data = tmp_data;
139                 OPENSSL_memcpy(&(*policy)->data[(*policy)->length],
140                        tmp_data2, val_len);
141                 (*policy)->length += val_len;
142                 (*policy)->data[(*policy)->length] = '\0';
143             } else {
144                 OPENSSL_free(tmp_data2);
145                 /*
146                  * realloc failure implies the original data space is b0rked
147                  * too!
148                  */
149                 (*policy)->data = NULL;
150                 (*policy)->length = 0;
151                 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
152                 X509V3_conf_err(val);
153                 goto err;
154             }
155             OPENSSL_free(tmp_data2);
156         } else if (strncmp(val->value, "text:", 5) == 0) {
157             val_len = strlen(val->value + 5);
158             tmp_data = OPENSSL_realloc((*policy)->data,
159                                        (*policy)->length + val_len + 1);
160             if (tmp_data) {
161                 (*policy)->data = tmp_data;
162                 OPENSSL_memcpy(&(*policy)->data[(*policy)->length],
163                        val->value + 5, val_len);
164                 (*policy)->length += val_len;
165                 (*policy)->data[(*policy)->length] = '\0';
166             } else {
167                 /*
168                  * realloc failure implies the original data space is b0rked
169                  * too!
170                  */
171                 (*policy)->data = NULL;
172                 (*policy)->length = 0;
173                 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
174                 X509V3_conf_err(val);
175                 goto err;
176             }
177         } else {
178             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
179             X509V3_conf_err(val);
180             goto err;
181         }
182         if (!tmp_data) {
183             OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
184             X509V3_conf_err(val);
185             goto err;
186         }
187     }
188     return 1;
189  err:
190     if (free_policy) {
191         ASN1_OCTET_STRING_free(*policy);
192         *policy = NULL;
193     }
194     return 0;
195 }
196 
r2i_pci(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,char * value)197 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
198                                           X509V3_CTX *ctx, char *value)
199 {
200     PROXY_CERT_INFO_EXTENSION *pci = NULL;
201     STACK_OF(CONF_VALUE) *vals;
202     ASN1_OBJECT *language = NULL;
203     ASN1_INTEGER *pathlen = NULL;
204     ASN1_OCTET_STRING *policy = NULL;
205     size_t i, j;
206     int nid;
207 
208     vals = X509V3_parse_list(value);
209     for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
210         CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
211         if (!cnf->name || (*cnf->name != '@' && !cnf->value)) {
212             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
213             X509V3_conf_err(cnf);
214             goto err;
215         }
216         if (*cnf->name == '@') {
217             STACK_OF(CONF_VALUE) *sect;
218             int success_p = 1;
219 
220             sect = X509V3_get_section(ctx, cnf->name + 1);
221             if (!sect) {
222                 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
223                 X509V3_conf_err(cnf);
224                 goto err;
225             }
226             for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) {
227                 success_p =
228                     process_pci_value(sk_CONF_VALUE_value(sect, j),
229                                       &language, &pathlen, &policy);
230             }
231             X509V3_section_free(ctx, sect);
232             if (!success_p)
233                 goto err;
234         } else {
235             if (!process_pci_value(cnf, &language, &pathlen, &policy)) {
236                 X509V3_conf_err(cnf);
237                 goto err;
238             }
239         }
240     }
241 
242     /* Language is mandatory */
243     if (!language) {
244         OPENSSL_PUT_ERROR(X509V3,
245                           X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
246         goto err;
247     }
248     nid = OBJ_obj2nid(language);
249     if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) {
250         OPENSSL_PUT_ERROR(X509V3,
251                           X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
252         goto err;
253     }
254 
255     pci = PROXY_CERT_INFO_EXTENSION_new();
256     if (!pci) {
257         OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
258         goto err;
259     }
260 
261     pci->proxyPolicy->policyLanguage = language;
262     language = NULL;
263     pci->proxyPolicy->policy = policy;
264     policy = NULL;
265     pci->pcPathLengthConstraint = pathlen;
266     pathlen = NULL;
267     goto end;
268  err:
269     if (language) {
270         ASN1_OBJECT_free(language);
271         language = NULL;
272     }
273     if (pathlen) {
274         ASN1_INTEGER_free(pathlen);
275         pathlen = NULL;
276     }
277     if (policy) {
278         ASN1_OCTET_STRING_free(policy);
279         policy = NULL;
280     }
281     if (pci) {
282         PROXY_CERT_INFO_EXTENSION_free(pci);
283         pci = NULL;
284     }
285  end:
286     sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
287     return pci;
288 }
289