1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* v3_ncons.c */
24969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin/*
34969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * project.
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ====================================================================
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright
144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin *    notice, this list of conditions and the following disclaimer.
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the documentation and/or other materials provided with the
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    distribution.
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    software must display the following acknowledgment:
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    endorse or promote products derived from this software without
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    prior written permission. For written permission, please contact
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    licensing@OpenSSL.org.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL"
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    nor may "OpenSSL" appear in their names without prior written
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    permission of the OpenSSL Project.
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    acknowledgment:
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h>
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1t.h>
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/conf.h>
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/obj.h>
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/x509v3.h>
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6869939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan#include "../internal.h"
6969939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan
7069939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                  X509V3_CTX *ctx,
734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                  STACK_OF(CONF_VALUE) *nval);
744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstatic int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                BIO *bp, int ind);
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                   STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp,
784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                   int ind, const char *name);
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen);
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_dn(X509_NAME *sub, X509_NAME *nm);
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns);
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyconst X509V3_EXT_METHOD v3_name_constraints = {
894969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    NID_name_constraints, 0,
904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    ASN1_ITEM_ref(NAME_CONSTRAINTS),
914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    0, 0, 0, 0,
924969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    0, 0,
934969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    0, v2i_NAME_CONSTRAINTS,
944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    i2r_NAME_CONSTRAINTS, 0,
954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    NULL
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
98d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyASN1_SEQUENCE(GENERAL_SUBTREE) = {
994969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
1004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
1014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
104d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyASN1_SEQUENCE(NAME_CONSTRAINTS) = {
1054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
1064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                                        GENERAL_SUBTREE, 0),
1074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
1084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                                        GENERAL_SUBTREE, 1),
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
1104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
112d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyIMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
113d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyIMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
1164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
1174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
1184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    size_t i;
1194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    CONF_VALUE tval, *val;
1204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
1214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    NAME_CONSTRAINTS *ncons = NULL;
1224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    GENERAL_SUBTREE *sub = NULL;
1234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    ncons = NAME_CONSTRAINTS_new();
1244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!ncons)
1254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        goto memerr;
1264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
1274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        val = sk_CONF_VALUE_value(nval, i);
1284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (!strncmp(val->name, "permitted", 9) && val->name[9]) {
1294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            ptree = &ncons->permittedSubtrees;
1304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            tval.name = val->name + 10;
1314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) {
1324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            ptree = &ncons->excludedSubtrees;
1334969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            tval.name = val->name + 9;
1344969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        } else {
1354969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
1364969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            goto err;
1374969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        }
1384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        tval.value = val->value;
1394969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        sub = GENERAL_SUBTREE_new();
1404969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
1414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            goto err;
1424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (!*ptree)
1434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            *ptree = sk_GENERAL_SUBTREE_new_null();
1444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
1454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            goto memerr;
1464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        sub = NULL;
1474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
1484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
1494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return ncons;
1504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
1514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin memerr:
1524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
1534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin err:
1544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (ncons)
1554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        NAME_CONSTRAINTS_free(ncons);
1564969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (sub)
1574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        GENERAL_SUBTREE_free(sub);
1584969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
1594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return NULL;
1604969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
1634969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                BIO *bp, int ind)
1644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
1654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    NAME_CONSTRAINTS *ncons = a;
1664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    do_i2r_name_constraints(method, ncons->permittedSubtrees,
1674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                            bp, ind, "Permitted");
1684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    do_i2r_name_constraints(method, ncons->excludedSubtrees,
1694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                            bp, ind, "Excluded");
1704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return 1;
1714969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
1744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                   STACK_OF(GENERAL_SUBTREE) *trees,
1754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                                   BIO *bp, int ind, const char *name)
1764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
1774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    GENERAL_SUBTREE *tree;
1784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    size_t i;
1794969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (sk_GENERAL_SUBTREE_num(trees) > 0)
1804969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        BIO_printf(bp, "%*s%s:\n", ind, "", name);
1814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
1824969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        tree = sk_GENERAL_SUBTREE_value(trees, i);
1834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        BIO_printf(bp, "%*s", ind + 2, "");
1844969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (tree->base->type == GEN_IPADD)
1854969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            print_nc_ipadd(bp, tree->base->d.ip);
1864969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        else
1874969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            GENERAL_NAME_print(bp, tree->base);
1884969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        BIO_puts(bp, "\n");
1894969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
1904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return 1;
1914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
1944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
1954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    int i, len;
1964969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    unsigned char *p;
1974969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    p = ip->data;
1984969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    len = ip->length;
1994969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    BIO_puts(bp, "IP:");
2004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (len == 8) {
2014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
2024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                   p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    } else if (len == 32) {
2044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        for (i = 0; i < 16; i++) {
2054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            BIO_printf(bp, "%X", p[0] << 8 | p[1]);
2064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            p += 2;
2074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (i == 7)
2084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                BIO_puts(bp, "/");
2094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            else if (i != 15)
2104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                BIO_puts(bp, ":");
2114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        }
2124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    } else
2134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        BIO_printf(bp, "IP Address:<invalid>");
2144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return 1;
2154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
2164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
2174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin/*
2184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * Check a certificate conforms to a specified set of constraints. Return
2194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * values: X509_V_OK: All constraints obeyed.
2204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
2214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
2224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
2234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
2244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint
2254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * syntax.  X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of
2264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * name
2274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin *
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc)
2314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
2324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    int r, i;
2334969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    size_t j;
2344969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    X509_NAME *nm;
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2364969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    nm = X509_get_subject_name(x);
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (X509_NAME_entry_count(nm) > 0) {
2394969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        GENERAL_NAME gntmp;
2404969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        gntmp.type = GEN_DIRNAME;
2414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        gntmp.d.directoryName = nm;
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        r = nc_match(&gntmp, nc);
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (r != X509_V_OK)
2464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return r;
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        gntmp.type = GEN_EMAIL;
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        /* Process any email address attributes in subject name */
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        for (i = -1;;) {
2534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            X509_NAME_ENTRY *ne;
2544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i);
2554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (i == -1)
2564969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                break;
2574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            ne = X509_NAME_get_entry(nm, i);
2584969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
2594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
2604969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2624969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            r = nc_match(&gntmp, nc);
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (r != X509_V_OK)
2654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                return r;
2664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        }
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++) {
2714969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j);
2724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        r = nc_match(gen, nc);
2734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (r != X509_V_OK)
2744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return r;
2754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return X509_V_OK;
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2794969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
2824969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
2834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    GENERAL_SUBTREE *sub;
2844969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    int r, match = 0;
2854969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    size_t i;
2864969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
2874969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /*
2884969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     * Permitted subtrees: if any subtrees exist of matching the type at
2894969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     * least one subtree must match.
2904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     */
2914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
2924969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
2934969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
2944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (gen->type != sub->base->type)
2954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            continue;
2964969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (sub->minimum || sub->maximum)
2974969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return X509_V_ERR_SUBTREE_MINMAX;
2984969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        /* If we already have a match don't bother trying any more */
2994969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (match == 2)
3004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            continue;
3014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (match == 0)
3024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            match = 1;
3034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        r = nc_match_single(gen, sub->base);
3044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (r == X509_V_OK)
3054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            match = 2;
3064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        else if (r != X509_V_ERR_PERMITTED_VIOLATION)
3074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return r;
3084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
3094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (match == 1)
3114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
3124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Excluded subtrees: must not match any of these */
3144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
3164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
3174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (gen->type != sub->base->type)
3184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            continue;
3194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (sub->minimum || sub->maximum)
3204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return X509_V_ERR_SUBTREE_MINMAX;
3214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        r = nc_match_single(gen, sub->base);
3234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (r == X509_V_OK)
3244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return X509_V_ERR_EXCLUDED_VIOLATION;
3254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        else if (r != X509_V_ERR_PERMITTED_VIOLATION)
3264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return r;
3274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
3294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return X509_V_OK;
3314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
334d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
3354969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
3364969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    switch (base->type) {
3374969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    case GEN_DIRNAME:
3384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return nc_dn(gen->d.directoryName, base->d.directoryName);
339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3404969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    case GEN_DNS:
3414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return nc_dns(gen->d.dNSName, base->d.dNSName);
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    case GEN_EMAIL:
3444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    case GEN_URI:
3474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return nc_uri(gen->d.uniformResourceIdentifier,
3484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                      base->d.uniformResourceIdentifier);
349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    default:
3514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
3524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3564969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin/*
3574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * directoryName name constraint matching. The canonical encoding of
3584969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * X509_NAME makes this comparison easy. It is matched if the subtree is a
3594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * subset of the name.
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
362d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_dn(X509_NAME *nm, X509_NAME *base)
3634969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
3644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Ensure canonical encodings are up to date.  */
3654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
3664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_OUT_OF_MEM;
3674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (base->modified && i2d_X509_NAME(base, NULL) < 0)
3684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_OUT_OF_MEM;
3694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (base->canon_enclen > nm->canon_enclen)
3704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
37169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan    if (OPENSSL_memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
3724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
3734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return X509_V_OK;
3744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
3774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
3784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    char *baseptr = (char *)base->data;
3794969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    char *dnsptr = (char *)dns->data;
3804969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Empty matches everything */
3814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!*baseptr)
3824969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_OK;
3834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /*
3844969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     * Otherwise can add zero or more components on the left so compare RHS
3854969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     * and if dns is longer and expect '.' as preceding character.
3864969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin     */
3874969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (dns->length > base->length) {
3884969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        dnsptr += dns->length - base->length;
3894969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (*baseptr != '.' && dnsptr[-1] != '.')
3904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            return X509_V_ERR_PERMITTED_VIOLATION;
3914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
3924969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3934969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (OPENSSL_strcasecmp(baseptr, dnsptr))
3944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
3954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3964969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return X509_V_OK;
3974969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
3984969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
4014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
4024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *baseptr = (char *)base->data;
4034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *emlptr = (char *)eml->data;
4044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *baseat = strchr(baseptr, '@');
4064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *emlat = strchr(emlptr, '@');
4074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!emlat)
4084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
4094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Special case: inital '.' is RHS match */
4104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!baseat && (*baseptr == '.')) {
4114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (eml->length > base->length) {
4124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            emlptr += eml->length - base->length;
4134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (!OPENSSL_strcasecmp(baseptr, emlptr))
4144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                return X509_V_OK;
4154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        }
4164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
4174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
4184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* If we have anything before '@' match local part */
4204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (baseat) {
4224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (baseat != baseptr) {
4234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if ((baseat - baseptr) != (emlat - emlptr))
4244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                return X509_V_ERR_PERMITTED_VIOLATION;
4254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            /* Case sensitive match of local part */
4264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (strncmp(baseptr, emlptr, emlat - emlptr))
4274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                return X509_V_ERR_PERMITTED_VIOLATION;
4284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        }
4294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        /* Position base after '@' */
4304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        baseptr = baseat + 1;
4314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
4324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    emlptr = emlat + 1;
4334969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Just have hostname left to match: case insensitive */
4344969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (OPENSSL_strcasecmp(baseptr, emlptr))
4354969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
4364969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4374969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return X509_V_OK;
4384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4394969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
4424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin{
4434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *baseptr = (char *)base->data;
4444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *hostptr = (char *)uri->data;
4454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    const char *p = strchr(hostptr, ':');
4464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    int hostlen;
4474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Check for foo:// and skip past it */
4484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!p || (p[1] != '/') || (p[2] != '/'))
4494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
4504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    hostptr = p + 3;
4514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Determine length of hostname part of URI */
4534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Look for a port indicator as end of hostname first */
4554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4564969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    p = strchr(hostptr, ':');
4574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Otherwise look for trailing slash */
4584969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!p)
4594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        p = strchr(hostptr, '/');
4604969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4614969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (!p)
4624969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        hostlen = strlen(hostptr);
4634969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    else
4644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        hostlen = p - hostptr;
4654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (hostlen == 0)
4674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
4684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    /* Special case: inital '.' is RHS match */
4704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (*baseptr == '.') {
4714969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        if (hostlen > base->length) {
4724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            p = hostptr + hostlen - base->length;
4734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin            if (!OPENSSL_strncasecmp(p, baseptr, base->length))
4744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                return X509_V_OK;
4754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        }
4764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
4774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    }
4784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4794969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if ((base->length != (int)hostlen)
4804969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        || OPENSSL_strncasecmp(hostptr, baseptr, hostlen))
4814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin        return X509_V_ERR_PERMITTED_VIOLATION;
4824969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return X509_V_OK;
4844969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
4854969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}
486