From 62cab15c648c1d618c658332bc59276e7baa6eb6 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 29 Jul 2021 15:12:58 +0200 Subject: [PATCH] Reorganize wolfSSL_sk_X509_NAME_* Make the `wolfSSL_sk_X509_NAME_*` API's available in OPENSSL_EXTRA for use with `client_CA_list` API's. --- src/ssl.c | 572 +++++++++++++++++++++++++++++------------------------- 1 file changed, 310 insertions(+), 262 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 48e82bf93..ebc4f5a3e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -16190,91 +16190,30 @@ int wolfSSL_set_compression(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list"); - if (ctx == NULL) + if (ctx == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list"); return NULL; + } 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) int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { @@ -16324,6 +16263,99 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } #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_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + unsigned long err; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "rb"); + if (bio == NULL) + 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 + } + #endif + #endif /* !NO_BIO */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ + + +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + /* registers client cert callback, called during handshake if server + requests client auth but user has not loaded client cert/key */ + void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb"); + + if (ctx != NULL) { + ctx->CBClientCert = cb; + } + } +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#ifdef OPENSSL_EXTRA + #ifndef NO_WOLFSSL_STUB int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) { @@ -45117,9 +45149,210 @@ 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_EXTRA) +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ + (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, CRYPTO_free_func* cb3) { @@ -45486,21 +45719,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( @@ -45531,63 +45749,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"); @@ -45622,121 +45783,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) @@ -46121,7 +46167,9 @@ WOLFSSL_X509_CRL *wolfSSL_X509_OBJECT_get0_X509_CRL(WOLFSSL_X509_OBJECT *obj) return NULL; } -#endif /* OPENSSL_EXTRA */ +#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || + * HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH || + * HAVE_SBLIM_SFCB)) */ #if defined(OPENSSL_EXTRA)