Home | History | Annotate | Download | only in ocsp
      1 /* ocsp_ext.c */
      2 /* Written by Tom Titchener <Tom_Titchener (at) groove.net> for the OpenSSL
      3  * project. */
      4 
      5 /* History:
      6    This file was transfered to Richard Levitte from CertCo by Kathy
      7    Weinhold in mid-spring 2000 to be included in OpenSSL or released
      8    as a patch kit. */
      9 
     10 /* ====================================================================
     11  * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  *
     17  * 1. Redistributions of source code must retain the above copyright
     18  *    notice, this list of conditions and the following disclaimer.
     19  *
     20  * 2. Redistributions in binary form must reproduce the above copyright
     21  *    notice, this list of conditions and the following disclaimer in
     22  *    the documentation and/or other materials provided with the
     23  *    distribution.
     24  *
     25  * 3. All advertising materials mentioning features or use of this
     26  *    software must display the following acknowledgment:
     27  *    "This product includes software developed by the OpenSSL Project
     28  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
     29  *
     30  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     31  *    endorse or promote products derived from this software without
     32  *    prior written permission. For written permission, please contact
     33  *    openssl-core (at) openssl.org.
     34  *
     35  * 5. Products derived from this software may not be called "OpenSSL"
     36  *    nor may "OpenSSL" appear in their names without prior written
     37  *    permission of the OpenSSL Project.
     38  *
     39  * 6. Redistributions of any form whatsoever must retain the following
     40  *    acknowledgment:
     41  *    "This product includes software developed by the OpenSSL Project
     42  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
     43  *
     44  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     45  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     47  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     48  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     49  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     50  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     51  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     53  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     54  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     55  * OF THE POSSIBILITY OF SUCH DAMAGE.
     56  * ====================================================================
     57  *
     58  * This product includes cryptographic software written by Eric Young
     59  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     60  * Hudson (tjh (at) cryptsoft.com).
     61  *
     62  */
     63 
     64 #include <stdio.h>
     65 #include <cryptlib.h>
     66 #include <openssl/objects.h>
     67 #include <openssl/x509.h>
     68 #include <openssl/ocsp.h>
     69 #include <openssl/rand.h>
     70 #include <openssl/x509v3.h>
     71 
     72 /* Standard wrapper functions for extensions */
     73 
     74 /* OCSP request extensions */
     75 
     76 int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x)
     77 	{
     78 	return(X509v3_get_ext_count(x->tbsRequest->requestExtensions));
     79 	}
     80 
     81 int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
     82 	{
     83 	return(X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions,nid,lastpos));
     84 	}
     85 
     86 int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos)
     87 	{
     88 	return(X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions,obj,lastpos));
     89 	}
     90 
     91 int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
     92 	{
     93 	return(X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions,crit,lastpos));
     94 	}
     95 
     96 X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc)
     97 	{
     98 	return(X509v3_get_ext(x->tbsRequest->requestExtensions,loc));
     99 	}
    100 
    101 X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc)
    102 	{
    103 	return(X509v3_delete_ext(x->tbsRequest->requestExtensions,loc));
    104 	}
    105 
    106 void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
    107 	{
    108 	return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx);
    109 	}
    110 
    111 int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
    112 							unsigned long flags)
    113 	{
    114 	return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, crit, flags);
    115 	}
    116 
    117 int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc)
    118 	{
    119 	return(X509v3_add_ext(&(x->tbsRequest->requestExtensions),ex,loc) != NULL);
    120 	}
    121 
    122 /* Single extensions */
    123 
    124 int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x)
    125 	{
    126 	return(X509v3_get_ext_count(x->singleRequestExtensions));
    127 	}
    128 
    129 int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
    130 	{
    131 	return(X509v3_get_ext_by_NID(x->singleRequestExtensions,nid,lastpos));
    132 	}
    133 
    134 int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos)
    135 	{
    136 	return(X509v3_get_ext_by_OBJ(x->singleRequestExtensions,obj,lastpos));
    137 	}
    138 
    139 int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
    140 	{
    141 	return(X509v3_get_ext_by_critical(x->singleRequestExtensions,crit,lastpos));
    142 	}
    143 
    144 X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc)
    145 	{
    146 	return(X509v3_get_ext(x->singleRequestExtensions,loc));
    147 	}
    148 
    149 X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc)
    150 	{
    151 	return(X509v3_delete_ext(x->singleRequestExtensions,loc));
    152 	}
    153 
    154 void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
    155 	{
    156 	return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
    157 	}
    158 
    159 int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
    160 							unsigned long flags)
    161 	{
    162 	return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, flags);
    163 	}
    164 
    165 int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc)
    166 	{
    167 	return(X509v3_add_ext(&(x->singleRequestExtensions),ex,loc) != NULL);
    168 	}
    169 
    170 /* OCSP Basic response */
    171 
    172 int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x)
    173 	{
    174 	return(X509v3_get_ext_count(x->tbsResponseData->responseExtensions));
    175 	}
    176 
    177 int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos)
    178 	{
    179 	return(X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions,nid,lastpos));
    180 	}
    181 
    182 int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos)
    183 	{
    184 	return(X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions,obj,lastpos));
    185 	}
    186 
    187 int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos)
    188 	{
    189 	return(X509v3_get_ext_by_critical(x->tbsResponseData->responseExtensions,crit,lastpos));
    190 	}
    191 
    192 X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc)
    193 	{
    194 	return(X509v3_get_ext(x->tbsResponseData->responseExtensions,loc));
    195 	}
    196 
    197 X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc)
    198 	{
    199 	return(X509v3_delete_ext(x->tbsResponseData->responseExtensions,loc));
    200 	}
    201 
    202 void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx)
    203 	{
    204 	return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, crit, idx);
    205 	}
    206 
    207 int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
    208 							unsigned long flags)
    209 	{
    210 	return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, value, crit, flags);
    211 	}
    212 
    213 int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc)
    214 	{
    215 	return(X509v3_add_ext(&(x->tbsResponseData->responseExtensions),ex,loc) != NULL);
    216 	}
    217 
    218 /* OCSP single response extensions */
    219 
    220 int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x)
    221 	{
    222 	return(X509v3_get_ext_count(x->singleExtensions));
    223 	}
    224 
    225 int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos)
    226 	{
    227 	return(X509v3_get_ext_by_NID(x->singleExtensions,nid,lastpos));
    228 	}
    229 
    230 int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos)
    231 	{
    232 	return(X509v3_get_ext_by_OBJ(x->singleExtensions,obj,lastpos));
    233 	}
    234 
    235 int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos)
    236 	{
    237 	return(X509v3_get_ext_by_critical(x->singleExtensions,crit,lastpos));
    238 	}
    239 
    240 X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc)
    241 	{
    242 	return(X509v3_get_ext(x->singleExtensions,loc));
    243 	}
    244 
    245 X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc)
    246 	{
    247 	return(X509v3_delete_ext(x->singleExtensions,loc));
    248 	}
    249 
    250 void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx)
    251 	{
    252 	return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
    253 	}
    254 
    255 int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
    256 							unsigned long flags)
    257 	{
    258 	return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
    259 	}
    260 
    261 int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc)
    262 	{
    263 	return(X509v3_add_ext(&(x->singleExtensions),ex,loc) != NULL);
    264 	}
    265 
    266 /* also CRL Entry Extensions */
    267 #if 0
    268 ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
    269 				void *data, STACK_OF(ASN1_OBJECT) *sk)
    270         {
    271 	int i;
    272 	unsigned char *p, *b = NULL;
    273 
    274 	if (data)
    275 	        {
    276 		if ((i=i2d(data,NULL)) <= 0) goto err;
    277 		if (!(b=p=OPENSSL_malloc((unsigned int)i)))
    278 			goto err;
    279 	        if (i2d(data, &p) <= 0) goto err;
    280 		}
    281 	else if (sk)
    282 	        {
    283 		if ((i=i2d_ASN1_SET_OF_ASN1_OBJECT(sk,NULL,
    284 						   (I2D_OF(ASN1_OBJECT))i2d,
    285 						   V_ASN1_SEQUENCE,
    286 						   V_ASN1_UNIVERSAL,
    287 						   IS_SEQUENCE))<=0) goto err;
    288 		if (!(b=p=OPENSSL_malloc((unsigned int)i)))
    289 			goto err;
    290 		if (i2d_ASN1_SET_OF_ASN1_OBJECT(sk,&p,(I2D_OF(ASN1_OBJECT))i2d,
    291 						V_ASN1_SEQUENCE,
    292 						V_ASN1_UNIVERSAL,
    293 						IS_SEQUENCE)<=0) goto err;
    294 		}
    295 	else
    296 		{
    297 		OCSPerr(OCSP_F_ASN1_STRING_ENCODE,OCSP_R_BAD_DATA);
    298 		goto err;
    299 		}
    300 	if (!s && !(s = ASN1_STRING_new())) goto err;
    301 	if (!(ASN1_STRING_set(s, b, i))) goto err;
    302 	OPENSSL_free(b);
    303 	return s;
    304 err:
    305 	if (b) OPENSSL_free(b);
    306 	return NULL;
    307 	}
    308 #endif
    309 
    310 /* Nonce handling functions */
    311 
    312 /* Add a nonce to an extension stack. A nonce can be specificed or if NULL
    313  * a random nonce will be generated.
    314  * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the
    315  * nonce, previous versions used the raw nonce.
    316  */
    317 
    318 static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len)
    319 	{
    320 	unsigned char *tmpval;
    321 	ASN1_OCTET_STRING os;
    322 	int ret = 0;
    323 	if (len <= 0) len = OCSP_DEFAULT_NONCE_LENGTH;
    324 	/* Create the OCTET STRING manually by writing out the header and
    325 	 * appending the content octets. This avoids an extra memory allocation
    326 	 * operation in some cases. Applications should *NOT* do this because
    327          * it relies on library internals.
    328 	 */
    329 	os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING);
    330 	os.data = OPENSSL_malloc(os.length);
    331 	if (os.data == NULL)
    332 		goto err;
    333 	tmpval = os.data;
    334 	ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL);
    335 	if (val)
    336 		memcpy(tmpval, val, len);
    337 	else
    338 		RAND_pseudo_bytes(tmpval, len);
    339 	if(!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
    340 			&os, 0, X509V3_ADD_REPLACE))
    341 				goto err;
    342 	ret = 1;
    343 	err:
    344 	if (os.data)
    345 		OPENSSL_free(os.data);
    346 	return ret;
    347 	}
    348 
    349 
    350 /* Add nonce to an OCSP request */
    351 
    352 int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
    353 	{
    354 	return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len);
    355 	}
    356 
    357 /* Same as above but for a response */
    358 
    359 int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
    360 	{
    361 	return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, len);
    362 	}
    363 
    364 /* Check nonce validity in a request and response.
    365  * Return value reflects result:
    366  *  1: nonces present and equal.
    367  *  2: nonces both absent.
    368  *  3: nonce present in response only.
    369  *  0: nonces both present and not equal.
    370  * -1: nonce in request only.
    371  *
    372  *  For most responders clients can check return > 0.
    373  *  If responder doesn't handle nonces return != 0 may be
    374  *  necessary. return == 0 is always an error.
    375  */
    376 
    377 int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
    378 	{
    379 	/*
    380 	 * Since we are only interested in the presence or absence of
    381 	 * the nonce and comparing its value there is no need to use
    382 	 * the X509V3 routines: this way we can avoid them allocating an
    383 	 * ASN1_OCTET_STRING structure for the value which would be
    384 	 * freed immediately anyway.
    385 	 */
    386 
    387 	int req_idx, resp_idx;
    388 	X509_EXTENSION *req_ext, *resp_ext;
    389 	req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
    390 	resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1);
    391 	/* Check both absent */
    392 	if((req_idx < 0) && (resp_idx < 0))
    393 		return 2;
    394 	/* Check in request only */
    395 	if((req_idx >= 0) && (resp_idx < 0))
    396 		return -1;
    397 	/* Check in response but not request */
    398 	if((req_idx < 0) && (resp_idx >= 0))
    399 		return 3;
    400 	/* Otherwise nonce in request and response so retrieve the extensions */
    401 	req_ext = OCSP_REQUEST_get_ext(req, req_idx);
    402 	resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
    403 	if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value))
    404 		return 0;
    405 	return 1;
    406 	}
    407 
    408 /* Copy the nonce value (if any) from an OCSP request to
    409  * a response.
    410  */
    411 
    412 int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req)
    413 	{
    414 	X509_EXTENSION *req_ext;
    415 	int req_idx;
    416 	/* Check for nonce in request */
    417 	req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
    418 	/* If no nonce that's OK */
    419 	if (req_idx < 0) return 2;
    420 	req_ext = OCSP_REQUEST_get_ext(req, req_idx);
    421 	return OCSP_BASICRESP_add_ext(resp, req_ext, -1);
    422 	}
    423 
    424 X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim)
    425         {
    426 	X509_EXTENSION *x = NULL;
    427 	OCSP_CRLID *cid = NULL;
    428 
    429 	if (!(cid = OCSP_CRLID_new())) goto err;
    430 	if (url)
    431 	        {
    432 		if (!(cid->crlUrl = ASN1_IA5STRING_new())) goto err;
    433 		if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) goto err;
    434 		}
    435 	if (n)
    436 	        {
    437 		if (!(cid->crlNum = ASN1_INTEGER_new())) goto err;
    438 		if (!(ASN1_INTEGER_set(cid->crlNum, *n))) goto err;
    439 		}
    440 	if (tim)
    441 	        {
    442 		if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) goto err;
    443 		if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim)))
    444 		        goto err;
    445 		}
    446 	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid);
    447 err:
    448 	if (cid) OCSP_CRLID_free(cid);
    449 	return x;
    450 	}
    451 
    452 /*   AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
    453 X509_EXTENSION *OCSP_accept_responses_new(char **oids)
    454         {
    455 	int nid;
    456 	STACK_OF(ASN1_OBJECT) *sk = NULL;
    457 	ASN1_OBJECT *o = NULL;
    458         X509_EXTENSION *x = NULL;
    459 
    460 	if (!(sk = sk_ASN1_OBJECT_new_null())) goto err;
    461 	while (oids && *oids)
    462 	        {
    463 		if ((nid=OBJ_txt2nid(*oids))!=NID_undef&&(o=OBJ_nid2obj(nid)))
    464 		        sk_ASN1_OBJECT_push(sk, o);
    465 		oids++;
    466 		}
    467 	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk);
    468 err:
    469 	if (sk) sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
    470 	return x;
    471         }
    472 
    473 /*  ArchiveCutoff ::= GeneralizedTime */
    474 X509_EXTENSION *OCSP_archive_cutoff_new(char* tim)
    475         {
    476 	X509_EXTENSION *x=NULL;
    477 	ASN1_GENERALIZEDTIME *gt = NULL;
    478 
    479 	if (!(gt = ASN1_GENERALIZEDTIME_new())) goto err;
    480 	if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) goto err;
    481 	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt);
    482 err:
    483 	if (gt) ASN1_GENERALIZEDTIME_free(gt);
    484 	return x;
    485 	}
    486 
    487 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently
    488  * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value.  This
    489  * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
    490  */
    491 X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls)
    492         {
    493 	X509_EXTENSION *x = NULL;
    494 	ASN1_IA5STRING *ia5 = NULL;
    495 	OCSP_SERVICELOC *sloc = NULL;
    496 	ACCESS_DESCRIPTION *ad = NULL;
    497 
    498 	if (!(sloc = OCSP_SERVICELOC_new())) goto err;
    499 	if (!(sloc->issuer = X509_NAME_dup(issuer))) goto err;
    500 	if (urls && *urls && !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) goto err;
    501 	while (urls && *urls)
    502 	        {
    503 		if (!(ad = ACCESS_DESCRIPTION_new())) goto err;
    504 		if (!(ad->method=OBJ_nid2obj(NID_ad_OCSP))) goto err;
    505 		if (!(ad->location = GENERAL_NAME_new())) goto err;
    506 	        if (!(ia5 = ASN1_IA5STRING_new())) goto err;
    507 		if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) goto err;
    508 		ad->location->type = GEN_URI;
    509 		ad->location->d.ia5 = ia5;
    510 		if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) goto err;
    511 		urls++;
    512 		}
    513 	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc);
    514 err:
    515 	if (sloc) OCSP_SERVICELOC_free(sloc);
    516 	return x;
    517 	}
    518 
    519