1/* 2 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <stdio.h> 11#include "internal/cryptlib.h" 12#include <openssl/conf.h> 13#include <openssl/asn1.h> 14#include <openssl/asn1t.h> 15#include <openssl/x509v3.h> 16#include "ext_dat.h" 17 18/* Support for Thawte strong extranet extension */ 19 20#define SXNET_TEST 21 22static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, 23 int indent); 24#ifdef SXNET_TEST 25static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 26 STACK_OF(CONF_VALUE) *nval); 27#endif 28const X509V3_EXT_METHOD v3_sxnet = { 29 NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET), 30 0, 0, 0, 0, 31 0, 0, 32 0, 33#ifdef SXNET_TEST 34 (X509V3_EXT_V2I)sxnet_v2i, 35#else 36 0, 37#endif 38 (X509V3_EXT_I2R)sxnet_i2r, 39 0, 40 NULL 41}; 42 43ASN1_SEQUENCE(SXNETID) = { 44 ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER), 45 ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING) 46} ASN1_SEQUENCE_END(SXNETID) 47 48IMPLEMENT_ASN1_FUNCTIONS(SXNETID) 49 50ASN1_SEQUENCE(SXNET) = { 51 ASN1_SIMPLE(SXNET, version, ASN1_INTEGER), 52 ASN1_SEQUENCE_OF(SXNET, ids, SXNETID) 53} ASN1_SEQUENCE_END(SXNET) 54 55IMPLEMENT_ASN1_FUNCTIONS(SXNET) 56 57static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, 58 int indent) 59{ 60 long v; 61 char *tmp; 62 SXNETID *id; 63 int i; 64 v = ASN1_INTEGER_get(sx->version); 65 BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v); 66 for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { 67 id = sk_SXNETID_value(sx->ids, i); 68 tmp = i2s_ASN1_INTEGER(NULL, id->zone); 69 BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp); 70 OPENSSL_free(tmp); 71 ASN1_STRING_print(out, id->user); 72 } 73 return 1; 74} 75 76#ifdef SXNET_TEST 77 78/* 79 * NBB: this is used for testing only. It should *not* be used for anything 80 * else because it will just take static IDs from the configuration file and 81 * they should really be separate values for each user. 82 */ 83 84static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 85 STACK_OF(CONF_VALUE) *nval) 86{ 87 CONF_VALUE *cnf; 88 SXNET *sx = NULL; 89 int i; 90 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 91 cnf = sk_CONF_VALUE_value(nval, i); 92 if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1)) 93 return NULL; 94 } 95 return sx; 96} 97 98#endif 99 100/* Strong Extranet utility functions */ 101 102/* Add an id given the zone as an ASCII number */ 103 104int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen) 105{ 106 ASN1_INTEGER *izone; 107 108 if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) { 109 X509V3err(X509V3_F_SXNET_ADD_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE); 110 return 0; 111 } 112 return SXNET_add_id_INTEGER(psx, izone, user, userlen); 113} 114 115/* Add an id given the zone as an unsigned long */ 116 117int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user, 118 int userlen) 119{ 120 ASN1_INTEGER *izone; 121 122 if ((izone = ASN1_INTEGER_new()) == NULL 123 || !ASN1_INTEGER_set(izone, lzone)) { 124 X509V3err(X509V3_F_SXNET_ADD_ID_ULONG, ERR_R_MALLOC_FAILURE); 125 ASN1_INTEGER_free(izone); 126 return 0; 127 } 128 return SXNET_add_id_INTEGER(psx, izone, user, userlen); 129 130} 131 132/* 133 * Add an id given the zone as an ASN1_INTEGER. Note this version uses the 134 * passed integer and doesn't make a copy so don't free it up afterwards. 135 */ 136 137int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user, 138 int userlen) 139{ 140 SXNET *sx = NULL; 141 SXNETID *id = NULL; 142 if (!psx || !zone || !user) { 143 X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, 144 X509V3_R_INVALID_NULL_ARGUMENT); 145 return 0; 146 } 147 if (userlen == -1) 148 userlen = strlen(user); 149 if (userlen > 64) { 150 X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_USER_TOO_LONG); 151 return 0; 152 } 153 if (*psx == NULL) { 154 if ((sx = SXNET_new()) == NULL) 155 goto err; 156 if (!ASN1_INTEGER_set(sx->version, 0)) 157 goto err; 158 *psx = sx; 159 } else 160 sx = *psx; 161 if (SXNET_get_id_INTEGER(sx, zone)) { 162 X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_DUPLICATE_ZONE_ID); 163 return 0; 164 } 165 166 if ((id = SXNETID_new()) == NULL) 167 goto err; 168 if (userlen == -1) 169 userlen = strlen(user); 170 171 if (!ASN1_OCTET_STRING_set(id->user, (const unsigned char *)user, userlen)) 172 goto err; 173 if (!sk_SXNETID_push(sx->ids, id)) 174 goto err; 175 id->zone = zone; 176 return 1; 177 178 err: 179 X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, ERR_R_MALLOC_FAILURE); 180 SXNETID_free(id); 181 SXNET_free(sx); 182 *psx = NULL; 183 return 0; 184} 185 186ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone) 187{ 188 ASN1_INTEGER *izone; 189 ASN1_OCTET_STRING *oct; 190 191 if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) { 192 X509V3err(X509V3_F_SXNET_GET_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE); 193 return NULL; 194 } 195 oct = SXNET_get_id_INTEGER(sx, izone); 196 ASN1_INTEGER_free(izone); 197 return oct; 198} 199 200ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone) 201{ 202 ASN1_INTEGER *izone; 203 ASN1_OCTET_STRING *oct; 204 205 if ((izone = ASN1_INTEGER_new()) == NULL 206 || !ASN1_INTEGER_set(izone, lzone)) { 207 X509V3err(X509V3_F_SXNET_GET_ID_ULONG, ERR_R_MALLOC_FAILURE); 208 ASN1_INTEGER_free(izone); 209 return NULL; 210 } 211 oct = SXNET_get_id_INTEGER(sx, izone); 212 ASN1_INTEGER_free(izone); 213 return oct; 214} 215 216ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone) 217{ 218 SXNETID *id; 219 int i; 220 for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { 221 id = sk_SXNETID_value(sx->ids, i); 222 if (!ASN1_INTEGER_cmp(id->zone, zone)) 223 return id->user; 224 } 225 return NULL; 226} 227