diff --git a/src/internal.c b/src/internal.c index a0afd3d6b..f29dc5103 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2195,14 +2195,13 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) ctx->x509_store.objs = NULL; } #endif - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL) wolfSSL_X509_STORE_free(ctx->x509_store_pt); - while (ctx->ca_names != NULL) { - WOLFSSL_STACK *next = ctx->ca_names->next; - wolfSSL_X509_NAME_free(ctx->ca_names->data.name); - XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL); - ctx->ca_names = next; - } + #endif + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY) + wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL); + ctx->ca_names = NULL; #endif #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) if (ctx->x509Chain) { @@ -7075,6 +7074,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) wolfSSL_sk_X509_free(ssl->peerCertChain); wolfSSL_sk_X509_free(ssl->ourCertChain); #endif +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY) + wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL); + ssl->ca_names = NULL; +#endif } /* Free any handshake resources no longer needed */ @@ -10291,6 +10294,31 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain, #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +static void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType) +{ + if (nameType == SUBJECT) { + XSTRNCPY(name->name, dCert->subject, ASN_NAME_MAX); + name->name[ASN_NAME_MAX - 1] = '\0'; + name->sz = (int)XSTRLEN(name->name) + 1; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) + name->rawLen = min(dCert->subjectRawLen, ASN_NAME_MAX); + XMEMCPY(name->raw, dCert->subjectRaw, name->rawLen); +#endif + } + else { + XSTRNCPY(name->name, dCert->issuer, ASN_NAME_MAX); + name->name[ASN_NAME_MAX - 1] = '\0'; + name->sz = (int)XSTRLEN(name->name) + 1; +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) \ + && (defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)) + name->rawLen = min(dCert->issuerRawLen, ASN_NAME_MAX); + if (name->rawLen) { + XMEMCPY(name->raw, dCert->issuerRaw, name->rawLen); + } +#endif + } +} + /* Copy parts X509 needs from Decoded cert, 0 on success */ /* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the * altNames pointers could be free'd by second x509 still active by first */ @@ -10309,9 +10337,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->version = dCert->version + 1; - XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX); - x509->issuer.name[ASN_NAME_MAX - 1] = '\0'; - x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1; + CopyDecodedName(&x509->issuer, dCert, ISSUER); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (dCert->issuerName != NULL) { wolfSSL_X509_set_issuer_name(x509, @@ -10319,10 +10345,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->issuer.x509 = x509; } #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - - XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX); - x509->subject.name[ASN_NAME_MAX - 1] = '\0'; - x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1; + CopyDecodedName(&x509->subject, dCert, SUBJECT); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (dCert->subjectName != NULL) { wolfSSL_X509_set_subject_name(x509, @@ -10330,16 +10353,6 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->subject.x509 = x509; } #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) - x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw)); - XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen); -#ifdef WOLFSSL_CERT_EXT - x509->issuer.rawLen = min(dCert->issuerRawLen, sizeof(x509->issuer.raw)); - if (x509->issuer.rawLen) { - XMEMCPY(x509->issuer.raw, dCert->issuerRaw, x509->issuer.rawLen); - } -#endif -#endif XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); x509->serialSz = dCert->serialSz; @@ -18688,7 +18701,7 @@ int SendCertificateRequest(WOLFSSL* ssl) #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) /* Certificate Authorities */ - names = ssl->ctx->ca_names; + names = SSL_CA_NAMES(ssl); while (names != NULL) { byte seq[MAX_SEQ_SZ]; WOLFSSL_X509_NAME* name = names->data.name; @@ -18759,7 +18772,7 @@ int SendCertificateRequest(WOLFSSL* ssl) c16toa((word16)dnLen, &output[i]); /* auth's */ i += REQ_HEADER_SZ; #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) - names = ssl->ctx->ca_names; + names = SSL_CA_NAMES(ssl); while (names != NULL) { byte seq[MAX_SEQ_SZ]; WOLFSSL_X509_NAME* name = names->data.name; @@ -21105,7 +21118,7 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) } if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || - XSTRNCMP(next, "DEFAULT", 7) == 0) + XSTRNCMP(next, "DEFAULT", 7) == 0 || XSTRNCMP(next, "HIGH", 4) == 0) return 1; /* wolfSSL default */ do { @@ -22928,8 +22941,11 @@ exit_dpk: { word16 len; word32 begin = *inOutIdx; - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) int ret; + #endif + #ifdef OPENSSL_EXTRA WOLFSSL_X509* x509 = NULL; WOLFSSL_EVP_PKEY* pkey = NULL; #endif @@ -22991,12 +23007,22 @@ exit_dpk: if ((*inOutIdx - begin) + OPAQUE16_LEN > size) return BUFFER_ERROR; + /* DN seq length */ ato16(input + *inOutIdx, &len); *inOutIdx += OPAQUE16_LEN; if ((*inOutIdx - begin) + len > size) return BUFFER_ERROR; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) + if (ssl->ca_names != ssl->ctx->ca_names) + wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL); + ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ssl->ca_names == NULL) { + return MEMORY_ERROR; + } + #endif + while (len) { word16 dnSz; @@ -23009,6 +23035,38 @@ exit_dpk: if ((*inOutIdx - begin) + dnSz > size) return BUFFER_ERROR; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) + { + /* Use a DecodedCert struct to get access to GetName to + * parse DN name */ + DecodedCert cert; + WOLFSSL_X509_NAME* name; + + InitDecodedCert(&cert, input + *inOutIdx, dnSz, ssl->heap); + + if ((ret = GetName(&cert, SUBJECT, dnSz)) != 0) { + FreeDecodedCert(&cert); + return ret; + } + + if ((name = wolfSSL_X509_NAME_new()) == NULL) { + FreeDecodedCert(&cert); + return MEMORY_ERROR; + } + + CopyDecodedName(name, &cert, SUBJECT); + + if (wolfSSL_sk_X509_NAME_push(ssl->ca_names, name) + == WOLFSSL_FAILURE) { + FreeDecodedCert(&cert); + wolfSSL_X509_NAME_free(name); + return MEMORY_ERROR; + } + + FreeDecodedCert(&cert); + } + #endif + *inOutIdx += dnSz; len -= OPAQUE16_LEN + dnSz; } diff --git a/src/ssl.c b/src/ssl.c index d04b4eb35..7b612ffa1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -16032,70 +16032,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #endif /* !NO_BIO */ #endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_WEBSERVER) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) { WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list"); - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) - if (ctx != NULL) + if (ctx != NULL) { + wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL); ctx->ca_names = names; - #else - (void)ctx; - (void)names; - #endif + } } - - /* returns the CA's set on server side or the CA's sent from server when - * on client side */ -#if defined(SESSION_CERTS) && defined(OPENSSL_ALL) - WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( - const WOLFSSL* ssl) + void wolfSSL_set_client_CA_list(WOLFSSL* ssl, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) { - WOLFSSL_ENTER("wolfSSL_get_client_CA_list"); - - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); - return NULL; - } - - /* return list of CAs sent from the server */ - if (ssl->options.side == WOLFSSL_CLIENT_END) { - WOLF_STACK_OF(WOLFSSL_X509)* sk; - - sk = wolfSSL_get_peer_cert_chain(ssl); - if (sk != NULL) { - WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; - WOLFSSL_X509* x509; - - ret = wolfSSL_sk_X509_NAME_new(NULL); - do { - x509 = wolfSSL_sk_X509_pop(sk); - if (x509 != NULL) { - if (wolfSSL_X509_get_isCA(x509)) { - if (wolfSSL_sk_X509_NAME_push(ret, - wolfSSL_X509_get_subject_name(x509)) != 0) { - WOLFSSL_MSG("Error pushing X509 name to stack"); - /* continue on to try other certificates and - * do not fail out here */ - } - } - wolfSSL_X509_free(x509); - } - } while (x509 != NULL); - wolfSSL_sk_X509_free(sk); - return ret; - } - return NULL; - } - else { - /* currently only can be set in the CTX */ - return ssl->ctx->ca_names; + WOLFSSL_ENTER("wolfSSL_set_client_CA_list"); + if (ssl != NULL) { + if (ssl->ca_names != ssl->ctx->ca_names) + wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL); + ssl->ca_names = names; } } -#endif /* SESSION_CERTS */ - #ifdef OPENSSL_EXTRA /* registers client cert callback, called during handshake if server @@ -16155,144 +16112,160 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( - const WOLFSSL_CTX *s) + const WOLFSSL_CTX *ctx) { WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list"); - if (s == NULL) + if (ctx == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list"); return NULL; + } - return s->ca_names; + return ctx->ca_names; } -#endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) -#ifndef NO_BIO - #if !defined(NO_RSA) && !defined(NO_CERTS) - WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + /* returns the CA's set on server side or the CA's sent from server when + * on client side */ + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( + const WOLFSSL* ssl) { - /* The webserver build is using this to load a CA into the server - * for client authentication as an option. Have this return NULL in - * that case. If OPENSSL_EXTRA is enabled, go ahead and include - * the function. */ - #ifdef OPENSSL_EXTRA - WOLFSSL_STACK *list = NULL; - WOLFSSL_STACK *node; - WOLFSSL_BIO* bio; - WOLFSSL_X509 *cert = NULL; - WOLFSSL_X509_NAME *subjectName = NULL; - unsigned long err; + WOLFSSL_ENTER("wolfSSL_get_client_CA_list"); - WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); - - bio = wolfSSL_BIO_new_file(fname, "rb"); - if (bio == NULL) + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); return NULL; - - /* Read each certificate in the chain out of the file. */ - while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { - subjectName = wolfSSL_X509_get_subject_name(cert); - if (subjectName == NULL) - break; - - node = wolfSSL_sk_new_node(NULL); - if (node == NULL) - break; - node->type = STACK_TYPE_X509_NAME; - - /* Need a persistent copy of the subject name. */ - node->data.name = wolfSSL_X509_NAME_dup(subjectName); - if (node->data.name != NULL) { - /* - * Original cert will be freed so make sure not to try to access - * it in the future. - */ - node->data.name->x509 = NULL; - } - - /* Put node on the front of the list. */ - node->num = (list == NULL) ? 1 : list->num + 1; - node->next = list; - list = node; - - wolfSSL_X509_free(cert); - cert = NULL; } - err = wolfSSL_ERR_peek_last_error(); - - if (ERR_GET_LIB(err) == ERR_LIB_PEM && - ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { - /* - * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error - * to the error queue on file end. This should not be left - * for the caller to find so we clear the last error. - */ - wc_RemoveErrorNode(-1); - } - - wolfSSL_X509_free(cert); - wolfSSL_BIO_free(bio); - return list; - #else - (void)fname; - return NULL; - #endif + return SSL_CA_NAMES(ssl); } - #endif -#endif /* !NO_BIO */ -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ -#ifdef OPENSSL_EXTRA - #if !defined(NO_RSA) && !defined(NO_CERTS) + #if !defined(NO_CERTS) int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { - WOLFSSL_STACK *node = NULL; - WOLFSSL_X509_NAME *subjectName = NULL; + WOLFSSL_X509_NAME *nameCopy = NULL; WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); if (ctx == NULL || x509 == NULL){ WOLFSSL_MSG("Bad argument"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - subjectName = wolfSSL_X509_get_subject_name(x509); - if (subjectName == NULL){ - WOLFSSL_MSG("invalid x509 data"); - return SSL_FAILURE; + if (ctx->ca_names == NULL) { + ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ctx->ca_names == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + return WOLFSSL_FAILURE; + } } - /* Alloc stack struct */ - node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC( - sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)), - NULL, DYNAMIC_TYPE_OPENSSL); - if (node == NULL){ - WOLFSSL_MSG("memory allocation error"); - return SSL_FAILURE; + nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); + if (nameCopy == NULL) { + WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); + return WOLFSSL_FAILURE; } - XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME))); - /* Alloc and copy WOLFSSL_X509_NAME */ - node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( - sizeof(WOLFSSL_X509_NAME), - NULL, DYNAMIC_TYPE_OPENSSL); - if (node->data.name == NULL) { - XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); - WOLFSSL_MSG("memory allocation error"); - return SSL_FAILURE; + if (wolfSSL_sk_X509_NAME_push(ctx->ca_names, nameCopy) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); + wolfSSL_X509_NAME_free(nameCopy); + return WOLFSSL_FAILURE; } - XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); - XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); - /* push new node onto head of stack */ - node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1; - node->next = ctx->ca_names; - ctx->ca_names = node; return WOLFSSL_SUCCESS; } #endif + #ifndef NO_BIO + #if !defined(NO_RSA) && !defined(NO_CERTS) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + { + /* The webserver build is using this to load a CA into the server + * for client authentication as an option. Have this return NULL in + * that case. If OPENSSL_EXTRA is enabled, go ahead and include + * the function. */ + #ifdef OPENSSL_EXTRA + WOLFSSL_STACK *list = NULL; + WOLFSSL_BIO* bio = NULL; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *nameCopy = NULL; + unsigned long err = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "rb"); + if (bio == NULL) { + WOLFSSL_MSG("wolfSSL_BIO_new_file error"); + goto cleanup; + } + + list = wolfSSL_sk_X509_NAME_new(NULL); + if (list == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + goto cleanup; + } + + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + /* Need a persistent copy of the subject name. */ + nameCopy = wolfSSL_X509_NAME_dup( + wolfSSL_X509_get_subject_name(cert)); + if (nameCopy == NULL) { + WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); + goto cleanup; + } + /* + * Original cert will be freed so make sure not to try to access + * it in the future. + */ + nameCopy->x509 = NULL; + + if (wolfSSL_sk_X509_NAME_push(list, nameCopy) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); + /* Do free in loop because nameCopy is now responsibility + * of list to free and adding jumps to cleanup after this + * might result in a double free. */ + wolfSSL_X509_NAME_free(nameCopy); + goto cleanup; + } + + wolfSSL_X509_free(cert); + cert = NULL; + } + + err = wolfSSL_ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + /* + * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error + * to the error queue on file end. This should not be left + * for the caller to find so we clear the last error. + */ + wc_RemoveErrorNode(-1); + } + + err = WOLFSSL_SUCCESS; +cleanup: + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + if (err != WOLFSSL_SUCCESS) { + /* We failed so return NULL */ + wolfSSL_sk_X509_NAME_pop_free(list, NULL); + list = NULL; + } + return list; + #else + (void)fname; + return NULL; + #endif + } + #endif + #endif /* !NO_BIO */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */ + +#ifdef OPENSSL_EXTRA + #ifndef NO_WOLFSSL_STUB int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) { @@ -19037,7 +19010,9 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) if (ssl == NULL) return NULL; - if (ssl->peerCertChain == NULL) + /* Try to populate if NULL or empty */ + if (ssl->peerCertChain == NULL || + wolfSSL_sk_X509_num(ssl->peerCertChain) == 0) wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); return ssl->peerCertChain; } @@ -19142,6 +19117,8 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) wolfSSL_sk_X509_shift(sk); } #endif + if (ssl->peerCertChain != NULL) + wolfSSL_sk_X509_free(ssl->peerCertChain); /* This is Free'd when ssl is Free'd */ ssl->peerCertChain = sk; return sk; @@ -45081,6 +45058,204 @@ void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) } #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || FORTRESS */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB) + +WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(wolf_sk_compare_cb cb) +{ + WOLFSSL_STACK* sk; + (void)cb; + + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_new"); + + sk = wolfSSL_sk_new_node(NULL); + if (sk != NULL) { + sk->type = STACK_TYPE_X509_NAME; +#ifdef OPENSSL_ALL + sk->comp = cb; +#endif + } + + return sk; +} + +int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); + + if (sk == NULL) + return BAD_FUNC_ARG; + + return (int)sk->num; +} + +/* Getter function for WOLFSSL_X509_NAME pointer + * + * sk is the stack to retrieve pointer from + * i is the index value in stack + * + * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on + * fail + */ +WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, + int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); + + for (; sk != NULL && i > 0; i--) { + sk = sk->next; + } + + if (i != 0 || sk == NULL) + return NULL; + + return sk->data.name; +} + +WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_X509_NAME* name; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + name = sk->data.name; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.name = node->data.name; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + } + else { /* last x509 in stack */ + sk->data.name = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return name; +} + +void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + void (*f) (WOLFSSL_X509_NAME*)) +{ + WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); + + if (sk == NULL) + return; + + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + if (f) + f(tmp->data.name); + else + wolfSSL_X509_NAME_free(tmp->data.name); + tmp->data.name = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.name); + else + wolfSSL_X509_NAME_free(sk->data.name); + sk->data.name = NULL; + } + + XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL); +} + +/* Free only the sk structure, NOT X509_NAME members */ +void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_free"); + + if (sk == NULL) + return; + + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + WOLFSSL_X509_NAME* name) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_push"); + + if (sk == NULL || name == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.name == NULL) { + sk->data.name = name; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.name = sk->data.name; + node->next = sk->next; + sk->type = STACK_TYPE_X509_NAME; + sk->next = node; + sk->data.name = name; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +/* return index of found, or negative to indicate not found */ +int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk, + WOLFSSL_X509_NAME *name) +{ + int i; + + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_find"); + + if (sk == NULL) + return BAD_FUNC_ARG; + + for (i = 0; sk; i++, sk = sk->next) { + if (wolfSSL_X509_NAME_cmp(sk->data.name, name) == 0) { + return i; + } + } + return -1; +} + +#endif /* OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || + HAVE_LIGHTY || WOLFSSL_HAPROXY || + WOLFSSL_OPENSSH || HAVE_SBLIM_SFCB */ + /* Note: This is a huge section of API's - through * wolfSSL_X509_OBJECT_get0_X509_CRL */ #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ @@ -45453,21 +45628,6 @@ int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk, return WOLFSSL_SUCCESS; } -WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(wolf_sk_compare_cb cb) -{ - WOLFSSL_STACK* sk; - - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_new"); - - sk = wolfSSL_sk_new_node(NULL); - if (sk != NULL) { - sk->type = STACK_TYPE_X509_NAME; - sk->comp = cb; - } - - return sk; -} - /* Creates a duplicate of WOLF_STACK_OF(WOLFSSL_X509_NAME). * Returns a new WOLF_STACK_OF(WOLFSSL_X509_NAME) or NULL on failure */ WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( @@ -45480,7 +45640,7 @@ WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLFSSL_ENTER("wolfSSL_dup_CA_list"); - copy = wolfSSL_sk_X509_NAME_new(NULL); + copy = wolfSSL_sk_X509_NAME_new(sk->comp); if (copy == NULL) { WOLFSSL_MSG("Memory error"); return NULL; @@ -45498,63 +45658,6 @@ WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( return copy; } -int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, - WOLFSSL_X509_NAME* name) -{ - WOLFSSL_STACK* node; - - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_push"); - - if (sk == NULL || name == NULL) { - return WOLFSSL_FAILURE; - } - - /* no previous values in stack */ - if (sk->data.name == NULL) { - sk->data.name = name; - sk->num += 1; - return WOLFSSL_SUCCESS; - } - - /* stack already has value(s) create a new node and add more */ - node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, - DYNAMIC_TYPE_OPENSSL); - if (node == NULL) { - WOLFSSL_MSG("Memory error"); - return WOLFSSL_FAILURE; - } - XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); - - /* push new obj onto head of stack */ - node->data.name = sk->data.name; - node->next = sk->next; - sk->type = STACK_TYPE_X509_NAME; - sk->next = node; - sk->data.name = name; - sk->num += 1; - - return WOLFSSL_SUCCESS; -} - -/* return index of found, or negative to indicate not found */ -int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk, - WOLFSSL_X509_NAME *name) -{ - int i; - - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_find"); - - if (sk == NULL) - return BAD_FUNC_ARG; - - for (i = 0; sk; i++, sk = sk->next) { - if (wolfSSL_X509_NAME_cmp(sk->data.name, name) == 0) { - return i; - } - } - return -1; -} - void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i) { WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_value"); @@ -45589,121 +45692,6 @@ int wolfSSL_sk_X509_NAME_set_cmp_func(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, } #endif /* OPENSSL_ALL */ -int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk) -{ - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); - - if (sk == NULL) - return BAD_FUNC_ARG; - - return (int)sk->num; -} - -/* Getter function for WOLFSSL_X509_NAME pointer - * - * sk is the stack to retrieve pointer from - * i is the index value in stack - * - * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on - * fail - */ -WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, - int i) -{ - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); - - for (; sk != NULL && i > 0; i--) { - sk = sk->next; - } - - if (i != 0 || sk == NULL) - return NULL; - - return sk->data.name; -} - -WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) -{ - WOLFSSL_STACK* node; - WOLFSSL_X509_NAME* name; - - if (sk == NULL) { - return NULL; - } - - node = sk->next; - name = sk->data.name; - - if (node != NULL) { /* update sk and remove node from stack */ - sk->data.name = node->data.name; - sk->next = node->next; - XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); - } - else { /* last x509 in stack */ - sk->data.name = NULL; - } - - if (sk->num > 0) { - sk->num -= 1; - } - - return name; -} - -void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, - void (*f) (WOLFSSL_X509_NAME*)) -{ - WOLFSSL_STACK* node; - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); - - if (sk == NULL) - return; - - node = sk->next; - while (node && sk->num > 1) { - WOLFSSL_STACK* tmp = node; - node = node->next; - if (f) - f(tmp->data.name); - else - wolfSSL_X509_NAME_free(tmp->data.name); - tmp->data.name = NULL; - XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); - sk->num -= 1; - } - - /* free head of stack */ - if (sk->num == 1) { - if (f) - f(sk->data.name); - else - wolfSSL_X509_NAME_free(sk->data.name); - sk->data.name = NULL; - } - - XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL); -} - -/* Free only the sk structure, NOT X509_NAME members */ -void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) -{ - WOLFSSL_STACK* node; - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_free"); - - if (sk == NULL) - return; - - node = sk->next; - while (sk->num > 1) { - WOLFSSL_STACK* tmp = node; - node = node->next; - XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); - sk->num -= 1; - } - - XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL); -} - #ifndef NO_BIO #if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) @@ -58174,7 +58162,8 @@ int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, * START OF X509_STORE APIs ******************************************************************************/ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL) WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) { WOLFSSL_X509_STORE* store = NULL; @@ -58367,7 +58356,7 @@ int wolfSSL_X509_STORE_set_ex_data_with_cleanup( #endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER || WOLFSSL_WPAS_SMALL */ #ifdef OPENSSL_EXTRA diff --git a/tests/api.c b/tests/api.c index dd2e8d364..522cd4e65 100644 --- a/tests/api.c +++ b/tests/api.c @@ -30772,17 +30772,42 @@ static void test_wolfSSL_CTX_set_client_CA_list(void) #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_CERTS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_BIO) WOLFSSL_CTX* ctx; + WOLFSSL* ssl; X509_NAME* name = NULL; STACK_OF(X509_NAME)* names = NULL; STACK_OF(X509_NAME)* ca_list = NULL; int i, names_len; printf(testingFmt, "wolfSSL_CTX_set_client_CA_list()"); - AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + /* Send two X501 names in cert request */ names = SSL_load_client_CA_file(cliCertFile); AssertNotNull(names); - SSL_CTX_set_client_CA_list(ctx,names); + ca_list = SSL_load_client_CA_file(caCertFile); + AssertNotNull(ca_list); + AssertIntEQ(sk_X509_NAME_push(names, sk_X509_NAME_value(ca_list, 0)), 1); + SSL_CTX_set_client_CA_list(ctx, names); + /* This should only free the stack structure */ + sk_X509_NAME_free(ca_list); AssertNotNull(ca_list = SSL_CTX_get_client_CA_list(ctx)); + AssertIntEQ(sk_X509_NAME_num(ca_list), sk_X509_NAME_num(names)); + + AssertIntGT((names_len = sk_X509_NAME_num(names)), 0); + for (i=0; iport, 0, 0, NULL); + AssertNotNull(ctx_client = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx_client, caCertFile, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx_client, cliCertFile, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx_client, cliKeyFile, SSL_FILETYPE_PEM)); + + AssertNotNull(ssl_client = wolfSSL_new(ctx_client)); + AssertIntEQ(wolfSSL_set_fd(ssl_client, sockfd), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_connect(ssl_client), WOLFSSL_SUCCESS); + + AssertNotNull(ca_list = SSL_get_client_CA_list(ssl_client)); + /* We are expecting two cert names to be sent */ + AssertIntEQ(sk_X509_NAME_num(ca_list), 2); + + AssertNotNull(names = SSL_CTX_get_client_CA_list(ctx)); + for (i=0; i #include #endif @@ -6542,9 +6543,18 @@ int GetName(DecodedCert* cert, int nameType, int maxIdx) #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ !defined(WOLFCRYPT_ONLY) if (nameType == ISSUER) { +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) && \ + (defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)) + dName->rawLen = min(cert->issuerRawLen, ASN_NAME_MAX); + XMEMCPY(dName->raw, cert->issuerRaw, dName->rawLen); +#endif cert->issuerName = dName; } else { +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + dName->rawLen = min(cert->subjectRawLen, ASN_NAME_MAX); + XMEMCPY(dName->raw, cert->subjectRaw, dName->rawLen); +#endif cert->subjectName = dName; } #endif @@ -9694,7 +9704,9 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } -/* from SSL proper, for locking can't do find here anymore */ +#if !defined(OPENSSL_EXTRA) && !defined(OPENSSL_EXTRA_X509_SMALL) +/* from SSL proper, for locking can't do find here anymore. + * brought in from internal.h if built with compat layer */ #ifdef __cplusplus extern "C" { #endif @@ -9705,6 +9717,7 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) #ifdef __cplusplus } #endif +#endif #if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c0770b05b..7f3c08855 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4508,6 +4508,9 @@ struct WOLFSSL { byte clientFinished[TLS_FINISHED_SZ]; byte serverFinished[TLS_FINISHED_SZ]; #endif +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; +#endif }; /* @@ -4524,6 +4527,9 @@ struct WOLFSSL { #define SSL_CM(ssl) ssl->ctx->cm #endif +#define SSL_CA_NAMES(ssl) (ssl->ca_names != NULL ? ssl->ca_names : \ + ssl->ctx->ca_names) + WOLFSSL_LOCAL int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr); WOLFSSL_LOCAL int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int); WOLFSSL_LOCAL int InitSSL(WOLFSSL*, WOLFSSL_CTX*, int); diff --git a/wolfssl/openssl/objects.h b/wolfssl/openssl/objects.h index ba79c48b4..5d6b49ca9 100644 --- a/wolfssl/openssl/objects.h +++ b/wolfssl/openssl/objects.h @@ -24,7 +24,6 @@ #define WOLFSSL_OBJECTS_H_ #include -//#include #ifndef OPENSSL_EXTRA_SSL_GUARD #define OPENSSL_EXTRA_SSL_GUARD #include diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 97d4d5d7a..a02b11cd9 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -835,13 +835,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_set1_verify_cert_store wolfSSL_set1_verify_cert_store #define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) #define SSL_get_client_CA_list wolfSSL_get_client_CA_list +#define SSL_set_client_CA_list wolfSSL_set_client_CA_list #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx #define SSL_get_ex_data wolfSSL_get_ex_data -#ifndef WOLFSSL_NO_STUB -#define SSL_set_client_CA_list(...) -#endif /* WOLFSSL_NO_STUB */ - #define SSL_CTX_set_default_passwd_cb_userdata wolfSSL_CTX_set_default_passwd_cb_userdata #define SSL_CTX_set_default_passwd_cb wolfSSL_CTX_set_default_passwd_cb diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 4d546e432..8f48c64ee 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -561,7 +561,8 @@ struct WOLFSSL_X509_STORE { int cache; /* stunnel dereference */ WOLFSSL_CERT_MANAGER* cm; WOLFSSL_X509_LOOKUP lookup; -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL) int isDynamic; WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */ #endif @@ -574,7 +575,8 @@ struct WOLFSSL_X509_STORE { #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; #endif -#ifdef HAVE_CRL +#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL)) && defined(HAVE_CRL) WOLFSSL_X509_CRL *crl; /* points to cm->crl */ #endif #ifndef SINGLE_THREADED @@ -1807,11 +1809,13 @@ WOLFSSL_API void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t); WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( - const WOLFSSL_CTX *s); + const WOLFSSL_CTX *ctx); /* deprecated function name */ #define wolfSSL_SSL_CTX_get_client_CA_list wolfSSL_CTX_get_client_CA_list -WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, +WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, + WOLF_STACK_OF(WOLFSSL_X509_NAME)*); +WOLFSSL_API void wolfSSL_set_client_CA_list(WOLFSSL*, WOLF_STACK_OF(WOLFSSL_X509_NAME)*); WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( const WOLFSSL* ssl);