Android: Support multiple CA certs when connecting to EAP network
In the Android-specific case, make ca_cert directive parse a space-separated list of hex-encoded CA certificate aliases following the "keystores://" prefix. Server certificate validation should succeed as long as the chain ends with one of them. Signed-off-by: Rubin Xu <rubinxu@google.com>
This commit is contained in:
parent
561536205a
commit
a8ef133f1d
1 changed files with 89 additions and 19 deletions
|
@ -105,6 +105,66 @@ static BIO * BIO_from_keystore(const char *key)
|
||||||
free(value);
|
free(value);
|
||||||
return bio;
|
return bio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
|
||||||
|
{
|
||||||
|
BIO *bio = BIO_from_keystore(key_alias);
|
||||||
|
STACK_OF(X509_INFO) *stack = NULL;
|
||||||
|
stack_index_t i;
|
||||||
|
|
||||||
|
if (bio) {
|
||||||
|
stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
|
||||||
|
BIO_free(bio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stack) {
|
||||||
|
wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
|
||||||
|
key_alias);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
|
||||||
|
X509_INFO *info = sk_X509_INFO_value(stack, i);
|
||||||
|
|
||||||
|
if (info->x509)
|
||||||
|
X509_STORE_add_cert(ctx, info->x509);
|
||||||
|
if (info->crl)
|
||||||
|
X509_STORE_add_crl(ctx, info->crl);
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_X509_INFO_pop_free(stack, X509_INFO_free);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx,
|
||||||
|
const char *encoded_key_alias)
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
int len = os_strlen(encoded_key_alias);
|
||||||
|
unsigned char *decoded_alias;
|
||||||
|
|
||||||
|
if (len & 1) {
|
||||||
|
wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s",
|
||||||
|
encoded_key_alias);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded_alias = os_malloc(len / 2 + 1);
|
||||||
|
if (decoded_alias) {
|
||||||
|
if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
|
||||||
|
decoded_alias[len / 2] = '\0';
|
||||||
|
rc = tls_add_ca_from_keystore(
|
||||||
|
ctx, (const char *) decoded_alias);
|
||||||
|
}
|
||||||
|
os_free(decoded_alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
|
|
||||||
static int tls_openssl_ref_count = 0;
|
static int tls_openssl_ref_count = 0;
|
||||||
|
@ -1989,30 +2049,40 @@ static int tls_connection_ca_cert(struct tls_data *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
/* Single alias */
|
||||||
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
|
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
|
||||||
BIO *bio = BIO_from_keystore(&ca_cert[11]);
|
if (tls_add_ca_from_keystore(ssl_ctx->cert_store,
|
||||||
STACK_OF(X509_INFO) *stack = NULL;
|
&ca_cert[11]) < 0)
|
||||||
stack_index_t i;
|
|
||||||
|
|
||||||
if (bio) {
|
|
||||||
stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
|
|
||||||
BIO_free(bio);
|
|
||||||
}
|
|
||||||
if (!stack)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
|
/* Multiple aliases separated by space */
|
||||||
X509_INFO *info = sk_X509_INFO_value(stack, i);
|
if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
|
||||||
if (info->x509) {
|
char *aliases = os_strdup(&ca_cert[12]);
|
||||||
X509_STORE_add_cert(ssl_ctx->cert_store,
|
const char *delim = " ";
|
||||||
info->x509);
|
int rc = 0;
|
||||||
}
|
char *savedptr;
|
||||||
if (info->crl) {
|
char *alias;
|
||||||
X509_STORE_add_crl(ssl_ctx->cert_store,
|
|
||||||
info->crl);
|
if (!aliases)
|
||||||
|
return -1;
|
||||||
|
alias = strtok_r(aliases, delim, &savedptr);
|
||||||
|
for (; alias; alias = strtok_r(NULL, delim, &savedptr)) {
|
||||||
|
if (tls_add_ca_from_keystore_encoded(
|
||||||
|
ssl_ctx->cert_store, alias)) {
|
||||||
|
wpa_printf(MSG_WARNING,
|
||||||
|
"OpenSSL: %s - Failed to add ca_cert %s from keystore",
|
||||||
|
__func__, alias);
|
||||||
|
rc = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sk_X509_INFO_pop_free(stack, X509_INFO_free);
|
os_free(aliases);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
|
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue