v3_ncons.c revision 296465
1/* v3_ncons.c */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 2003 The OpenSSL Project.  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 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com).  This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59
60#include <stdio.h>
61#include "cryptlib.h"
62#include <openssl/asn1t.h>
63#include <openssl/conf.h>
64#include <openssl/x509v3.h>
65
66static void *v2i_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method,
67                                  X509V3_CTX *ctx,
68                                  STACK_OF(CONF_VALUE) *nval);
69static int i2r_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method, void *a, BIO *bp,
70                                int ind);
71static int do_i2r_name_constraints(X509V3_EXT_METHOD *method,
72                                   STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp,
73                                   int ind, char *name);
74static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
75
76const X509V3_EXT_METHOD v3_name_constraints = {
77    NID_name_constraints, 0,
78    ASN1_ITEM_ref(NAME_CONSTRAINTS),
79    0, 0, 0, 0,
80    0, 0,
81    0, v2i_NAME_CONSTRAINTS,
82    i2r_NAME_CONSTRAINTS, 0,
83    NULL
84};
85
86ASN1_SEQUENCE(GENERAL_SUBTREE) = {
87        ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
88        ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
89        ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
90} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
91
92ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
93        ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
94                                                        GENERAL_SUBTREE, 0),
95        ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
96                                                        GENERAL_SUBTREE, 1),
97} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
98
99
100IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
101IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
102
103static void *v2i_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method,
104                                  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
105{
106    int i;
107    CONF_VALUE tval, *val;
108    STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
109    NAME_CONSTRAINTS *ncons = NULL;
110    GENERAL_SUBTREE *sub = NULL;
111    ncons = NAME_CONSTRAINTS_new();
112    if (!ncons)
113        goto memerr;
114    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
115        val = sk_CONF_VALUE_value(nval, i);
116        if (!strncmp(val->name, "permitted", 9) && val->name[9]) {
117            ptree = &ncons->permittedSubtrees;
118            tval.name = val->name + 10;
119        } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) {
120            ptree = &ncons->excludedSubtrees;
121            tval.name = val->name + 9;
122        } else {
123            X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, X509V3_R_INVALID_SYNTAX);
124            goto err;
125        }
126        tval.value = val->value;
127        sub = GENERAL_SUBTREE_new();
128        if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
129            goto err;
130        if (!*ptree)
131            *ptree = sk_GENERAL_SUBTREE_new_null();
132        if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
133            goto memerr;
134        sub = NULL;
135    }
136
137    return ncons;
138
139 memerr:
140    X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
141 err:
142    if (ncons)
143        NAME_CONSTRAINTS_free(ncons);
144    if (sub)
145        GENERAL_SUBTREE_free(sub);
146
147    return NULL;
148}
149
150static int i2r_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method,
151                                void *a, BIO *bp, int ind)
152{
153    NAME_CONSTRAINTS *ncons = a;
154    do_i2r_name_constraints(method, ncons->permittedSubtrees,
155                            bp, ind, "Permitted");
156    do_i2r_name_constraints(method, ncons->excludedSubtrees,
157                            bp, ind, "Excluded");
158    return 1;
159}
160
161static int do_i2r_name_constraints(X509V3_EXT_METHOD *method,
162                                   STACK_OF(GENERAL_SUBTREE) *trees,
163                                   BIO *bp, int ind, char *name)
164{
165    GENERAL_SUBTREE *tree;
166    int i;
167    if (sk_GENERAL_SUBTREE_num(trees) > 0)
168        BIO_printf(bp, "%*s%s:\n", ind, "", name);
169    for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
170        tree = sk_GENERAL_SUBTREE_value(trees, i);
171        BIO_printf(bp, "%*s", ind + 2, "");
172        if (tree->base->type == GEN_IPADD)
173            print_nc_ipadd(bp, tree->base->d.ip);
174        else
175            GENERAL_NAME_print(bp, tree->base);
176        BIO_puts(bp, "\n");
177    }
178    return 1;
179}
180
181static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
182{
183    int i, len;
184    unsigned char *p;
185    p = ip->data;
186    len = ip->length;
187    BIO_puts(bp, "IP:");
188    if (len == 8) {
189        BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
190                   p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
191    } else if (len == 32) {
192        for (i = 0; i < 16; i++) {
193            BIO_printf(bp, "%X", p[0] << 8 | p[1]);
194            p += 2;
195            if (i == 7)
196                BIO_puts(bp, "/");
197            else if (i != 15)
198                BIO_puts(bp, ":");
199        }
200    } else
201        BIO_printf(bp, "IP Address:<invalid>");
202    return 1;
203}
204