static int authenticate_webid_user(request_rec *request) { int r = 0; authn_webid_config_rec *conf = ap_get_module_config(request->per_dir_config, &authn_webid_module); if (!conf->authoritative) r = DECLINED; else r = HTTP_UNAUTHORIZED; /* Check for AuthType WebID */ const char *current_auth = ap_auth_type(request); if (!current_auth || strcasecmp(current_auth, "WebID") != 0) { return DECLINED; } request->ap_auth_type = "WebID"; /* Check for WebID cached in SSL session */ const char *subjAltName = NULL; { void *data = NULL; if (apr_pool_userdata_get(&data, UD_WEBID_KEY, request->connection->pool) == APR_SUCCESS && data != NULL) { subjAltName = data; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: using cached URI <%s>", subjAltName); if (strlen(subjAltName)) { request->user = (char *)subjAltName; r = OK; } return r; } } #if AP_MODULE_MAGIC_AT_LEAST(20060101,0) apr_array_header_t *subjAltName_list = ssl_ext_list(request->pool, request->connection, 1, "2.5.29.17"); #else subjAltName = ssl_ext_lookup(request->pool, request->connection, 1, "2.5.29.17"); #endif /* Load X509 Public Key + Exponent */ char *pkey_n = NULL; char *pkey_e = NULL; unsigned int pkey_e_i = 0; #if AP_MODULE_MAGIC_AT_LEAST(20060101,0) if (subjAltName_list != NULL) { #else if (subjAltName != NULL) { #endif char *c_cert = NULL; BIO *bio_cert = NULL; X509 *x509 = NULL; EVP_PKEY *pkey = NULL; RSA *rsa = NULL; BIO *bio = NULL; BUF_MEM *bptr = NULL; if (NULL != (c_cert = ssl_var_lookup(request->pool, request->server, request->connection, request, "SSL_CLIENT_CERT")) && NULL != (bio_cert = BIO_new_mem_buf(c_cert, strlen(c_cert))) && NULL != (x509 = PEM_read_bio_X509(bio_cert, NULL, NULL, NULL)) && NULL != (pkey = X509_get_pubkey(x509)) && NULL != (rsa = EVP_PKEY_get1_RSA(pkey))) { // public key modulus bio = BIO_new(BIO_s_mem()); BN_print(bio, rsa->n); BIO_get_mem_ptr(bio, &bptr); pkey_n = apr_pstrndup(request->pool, bptr->data, bptr->length); BIO_free(bio); // public key exponent bio = BIO_new(BIO_s_mem()); BN_print(bio, rsa->e); BIO_get_mem_ptr(bio, &bptr); pkey_e = apr_pstrndup(request->pool, bptr->data, bptr->length); pkey_e_i = apr_strtoi64(pkey_e, NULL, 16); BIO_free(bio); } else { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, request, "WebID: invalid client SSL certificate"); } if (rsa) RSA_free(rsa); if (pkey) EVP_PKEY_free(pkey); if (x509) X509_free(x509); if (bio_cert) BIO_free(bio_cert); } if (pkey_n != NULL && pkey_e != NULL) { #if AP_MODULE_MAGIC_AT_LEAST(20060101,0) const char *san; char *tok; int i; for (i = 0; i < subjAltName_list->nelts; i++) { san = APR_ARRAY_IDX(subjAltName_list, i, const char*); while ((tok = get_list_item(request->pool, &san)) != NULL) { if (strncmp(tok, "URI:", 4) == 0) { if (validate_webid(request, tok+4, pkey_n, pkey_e_i) == OK) { subjAltName = tok+4; r = OK; break; } } } } #else ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: subjectAltName = %s", subjAltName); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: client pkey.n = %s", pkey_n); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: client pkey.e = %d (%s)", pkey_e_i, pkey_e); const char *san = subjAltName; char *tok; while ((tok = get_list_item(request->pool, &san)) != NULL) { if (strncmp(tok, "URI:", 4) == 0) { if (validate_webid(request, tok+4, pkey_n, pkey_e_i) == OK) { subjAltName = tok+4; r = OK; break; } } } #endif } if (r == OK) { ap_log_rerror(APLOG_MARK, APLOG_INFO | APLOG_TOCLIENT, 0, request, "WebID: authentication (%sauthoritative) succeeded for <%s> pubkey: \"%s\", URI: <%s>", conf->authoritative?"":"non-", subjAltName, pkey_n, request->uri); request->user = apr_psprintf(request->connection->pool, "%s", subjAltName); } else { ap_log_rerror(APLOG_MARK, (conf->authoritative?APLOG_WARNING:APLOG_INFO) | APLOG_TOCLIENT, 0, request, "WebID: authentication (%sauthoritative) failed for <%s> pubkey: \"%s\", URI: <%s>", conf->authoritative?"":"non-", subjAltName, pkey_n, request->uri); subjAltName = ""; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, request, "WebID: setting cached URI <%s>", subjAltName); apr_pool_userdata_set(apr_pstrdup(request->connection->pool, subjAltName), UD_WEBID_KEY, NULL, request->connection->pool); return r; } static void import_ssl_func() { ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); #if AP_MODULE_MAGIC_AT_LEAST(20060101,0) ssl_ext_list = APR_RETRIEVE_OPTIONAL_FN(ssl_ext_list); #else ssl_ext_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_ext_lookup); #endif }
static apr_array_header_t *expr_peer_ext_list_fn(ap_expr_eval_ctx_t *ctx, const void *dummy, const char *arg) { return ssl_ext_list(ctx->p, ctx->c, 1, arg); }