diff options
-rw-r--r-- | lib/auth_cert.c | 73 |
1 files changed, 45 insertions, 28 deletions
diff --git a/lib/auth_cert.c b/lib/auth_cert.c index 5841839cd9..c349afa9dc 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -289,7 +289,6 @@ static int _gnutls_find_acceptable_client_cert(GNUTLS_STATE state, return GNUTLS_E_INSUFICIENT_CRED; } - if (state->gnutls_internals.client_cert_callback != NULL) { /* if try>=0 then the client wants automatic * choose of certificate, otherwise (-1), he @@ -332,6 +331,35 @@ static int _gnutls_find_acceptable_client_cert(GNUTLS_STATE state, gnutls_datum *my_certs = NULL; gnutls_datum *issuers_dn = NULL; int count; + int issuers_dn_len = 0; + opaque* dataptr = data; + int dataptr_size = data_size; + + /* Count the number of the given issuers; + * This is used to allocate the issuers_dn without + * using realloc(). + */ + do { + dataptr_size -= 2; + if (dataptr_size <= 0) + goto clear; + size = READuint16(data); + + dataptr_size -= size; + if (dataptr_size < 0) + goto clear; + + dataptr += 2; + + issuers_dn_len++; + + dataptr += size; + + if (dataptr_size == 0) + break; + + } while (1); + my_certs = gnutls_alloca(cred->ncerts * sizeof(gnutls_datum)); @@ -344,41 +372,29 @@ static int _gnutls_find_acceptable_client_cert(GNUTLS_STATE state, if (gnutls_cert_type_get(state) == GNUTLS_CRT_X509) { data = _data; data_size = _data_size; - count = 0; /* holds the number of given CA's DN */ - do { - data_size -= 2; - if (data_size <= 0) - goto clear; - size = READuint16(data); - data_size -= size; - if (data_size < 0) - goto clear; + issuers_dn = gnutls_alloca( issuers_dn_len * sizeof(gnutls_datum)); - data += 2; + for (i=0;i<issuers_dn_len;i++) { + /* The checks here for the buffer boundaries + * are not needed since the buffer has been + * parsed above. + */ + data_size -= 2; - issuers_dn = - gnutls_realloc_fast(issuers_dn, - (count + - 1) * - sizeof - (gnutls_datum)); - if (issuers_dn == NULL) - goto clear; + size = READuint16(data); - issuers_dn->data = data; - issuers_dn->size = size; + data += 2; - count++; /* otherwise we have failed */ + issuers_dn[count].data = data; + issuers_dn[count].size = size; data += size; - if (data_size == 0) - break; + } - } while (1); } else { /* Other certificate types */ - count = 0; + issuers_dn_len = 0; issuers_dn = NULL; } @@ -407,12 +423,13 @@ static int _gnutls_find_acceptable_client_cert(GNUTLS_STATE state, my_certs[j++] = cred->cert_list[i][0].raw; } } + indx = state->gnutls_internals.client_cert_callback(state, my_certs, j, issuers_dn, - count); + issuers_dn_len); /* the indx returned by the user is relative * to the certificates we provided him. @@ -424,7 +441,7 @@ static int _gnutls_find_acceptable_client_cert(GNUTLS_STATE state, clear: gnutls_afree(my_certs); gnutls_afree(ij_map); - gnutls_free(issuers_dn); + gnutls_afree(issuers_dn); } *ind = indx; |