diff --git a/src/ngx_http_voms_module.cpp b/src/ngx_http_voms_module.cpp index 2cd9b1db2e852cf5c9a5e86e3eadfb19d1811461..042bd634b07284689d750194b97077f1de0b3b32 100644 --- a/src/ngx_http_voms_module.cpp +++ b/src/ngx_http_voms_module.cpp @@ -74,6 +74,11 @@ static ngx_int_t get_ssl_client_ee_dn( // ngx_http_variable_value_t* v, uintptr_t data); +static ngx_int_t get_ssl_client_ee_cert( // + ngx_http_request_t* r, + ngx_http_variable_value_t* v, + uintptr_t data); + using getter_t = std::string(VomsAc const& voms); static getter_t get_voms_user; static getter_t get_voms_user_ca; @@ -192,6 +197,14 @@ static ngx_http_variable_t variables[] = { NGX_HTTP_VAR_NOCACHEABLE, 0 // }, + { + ngx_string("ssl_client_ee_cert"), + NULL, + get_ssl_client_ee_cert, + 0, + NGX_HTTP_VAR_NOCACHEABLE, + 0 // + }, ngx_http_null_variable // }; @@ -228,20 +241,14 @@ static bool is_proxy(X509* cert) return X509_get_extension_flags(cert) & EXFLAG_PROXY; } -static ngx_int_t get_ssl_client_ee_dn(ngx_http_request_t* r, - ngx_http_variable_value_t* v, - uintptr_t data) -{ - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "%s", __func__); - v->not_found = 1; - v->valid = 0; +static X509* get_ee_cert(ngx_http_request_t* r){ auto chain = SSL_get_peer_cert_chain(r->connection->ssl->connection); if (!chain) { ngx_log_error( NGX_LOG_ERR, r->connection->log, 0, "SSL_get_peer_cert_chain() failed"); - return NGX_OK; + return nullptr; } X509* ee_cert = nullptr; @@ -259,6 +266,123 @@ static ngx_int_t get_ssl_client_ee_dn(ngx_http_request_t* r, } } + return ee_cert; +} + +static ngx_int_t get_ssl_client_ee_cert_raw(ngx_http_request_t* r, + ngx_str_t *s) +{ + + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "%s", __func__); + s->len = 0; + + auto ee_cert = get_ee_cert(r); + + if (!ee_cert) { + ngx_log_error(NGX_LOG_DEBUG, + r->connection->log, + 0, + "cannot identify end-entity certificate"); + return NGX_OK; + } + + + BioPtr bio(BIO_new(BIO_s_mem()), &BIO_free); + if (!bio) { + ngx_log_error(NGX_LOG_ERR, + r->connection->log, + 0, + "cannot create OpenSSL BIO"); + return NGX_ERROR; + } + + if (PEM_write_bio_X509(bio.get(), ee_cert) == 0) { + ngx_log_error(NGX_LOG_ERR, + r->connection->log, + 0, + "cannot write EEC to OpenSSL bio"); + return NGX_ERROR; + } + + size_t len = BIO_pending(bio.get()); + + s->len = len; + s->data = static_cast<u_char*>(ngx_pnalloc(r->pool, len)); + + if (s->data == nullptr) { + return NGX_ERROR; + } + + BIO_read(bio.get(),s->data,len); + + return NGX_OK; +} + +static ngx_int_t get_ssl_client_ee_cert(ngx_http_request_t* r, + ngx_http_variable_value_t* v, + uintptr_t data) +{ + + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "%s", __func__); + + v->not_found = 1; + v->valid = 0; + + ngx_str_t cert; + + if (get_ssl_client_ee_cert_raw(r, &cert) != NGX_OK) { + return NGX_ERROR; + } + + if (cert.len == 0) { + v->len = 0; + return NGX_OK; + } + + size_t len = cert.len -1; + + for (int i=0; i < cert.len - 1; i++) { + if (cert.data[i] == '\n') { + len++; + } + } + + auto buffer = static_cast<u_char*>(ngx_pnalloc(r->pool, len)); + + if (!buffer) { + return NGX_OK; + } + + u_char* p = buffer; + + for (int i=0; i < cert.len - 1; i++) { + *p++ = cert.data[i]; + if (cert.data[i] == '\n') { + *p++ = '\t'; + } + } + + v->data = buffer; + v->len = len; + v->valid = 1; + v->not_found = 0; + v->no_cacheable = 0; + return NGX_OK; + +} + + +static ngx_int_t get_ssl_client_ee_dn(ngx_http_request_t* r, + ngx_http_variable_value_t* v, + uintptr_t data) +{ + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "%s", __func__); + + v->not_found = 1; + v->valid = 0; + + auto ee_cert = get_ee_cert(r); + if (!ee_cert) { ngx_log_error(NGX_LOG_DEBUG, r->connection->log, diff --git a/t/certs/0.eec.cert.pem b/t/certs/0.eec.cert.pem new file mode 100644 index 0000000000000000000000000000000000000000..dc05d435adc71d5a471cbee53f234a5687ed1345 --- /dev/null +++ b/t/certs/0.eec.cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- + MIIDnjCCAoagAwIBAgIBCTANBgkqhkiG9w0BAQUFADAtMQswCQYDVQQGEwJJVDEM + MAoGA1UECgwDSUdJMRAwDgYDVQQDDAdUZXN0IENBMB4XDTEyMDkyNjE1MzkzNFoX + DTIyMDkyNDE1MzkzNFowKzELMAkGA1UEBhMCSVQxDDAKBgNVBAoTA0lHSTEOMAwG + A1UEAxMFdGVzdDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKxtrw + hoZ27SxxISjlRqWmBWB6U+N/xW2kS1uUfrQRav6auVtmtEW45J44VTi3WW6Y113R + BwmS6oW+3lzyBBZVPqnhV9/VkTxLp83gGVVvHATgGgkjeTxIsOE+TkPKAoZJ/QFc + CfPh3WdZ3ANI14WYkAM9VXsSbh2okCsWGa4o6pzt3Pt1zKkyO4PW0cBkletDImJK + 2vufuDVNm7Iz/y3/8pY8p3MoiwbF/PdSba7XQAxBWUJMoaleh8xy8HSROn7tF2al + xoDLH4QWhp6UDn2rvOWseBqUMPXFjsUi1/rkw1oHAjMroTk5lL15GI0LGd5dTVop + kKXFbTTYxSkPz1MLAgMBAAGjgcowgccwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU + fLdB5+jO9LyWN2/VCNYgMa0jvHEwDgYDVR0PAQH/BAQDAgXgMD4GA1UdJQQ3MDUG + CCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBBggrBgEF + BQcDBDAfBgNVHSMEGDAWgBSRdzZ7LrRp8yfqt/YIi0ojohFJxjAnBgNVHREEIDAe + gRxhbmRyZWEuY2VjY2FudGlAY25hZi5pbmZuLml0MA0GCSqGSIb3DQEBBQUAA4IB + AQANYtWXetheSeVpCfnId9TkKyKTAp8RahNZl4XFrWWn2S9We7ACK/G7u1DebJYx + d8POo8ClscoXyTO2BzHHZLxauEKIzUv7g2GehI+SckfZdjFyRXjD0+wMGwzX7MDu + SL3CG2aWsYpkBnj6BMlr0P3kZEMqV5t2+2Tj0+aXppBPVwzJwRhnrSJiO5WIZAZf + 49YhMn61sQIrepvhrKEUR4XVorH2Bj8ek1/iLlgcmFMBOds+PrehSRR8Gn0IjlEg + C68EY6KPE+FKySuS7Ur7lTAjNdddfdAgKV6hJyST6/dx8ymIkb8nxCPnxCcT2I2N + vDxcPMc/wmnMa+smNal0sJ6m + -----END CERTIFICATE----- diff --git a/t/eec_cert.t b/t/eec_cert.t new file mode 100644 index 0000000000000000000000000000000000000000..63684913afff154c87939d4c7b1291523471f290 --- /dev/null +++ b/t/eec_cert.t @@ -0,0 +1,58 @@ +use Test::Nginx::Socket 'no_plan'; + +run_tests(); + +__DATA__ + +=== TEST 1: rfc proxy certificate, no AC +--- main_config + env OPENSSL_ALLOW_PROXY_CERTS=1; + env X509_VOMS_DIR=t/vomsdir; + env X509_CERT_DIR=t/trust-anchors; +--- http_config + server { + error_log logs/error.log debug; + listen 8443 ssl; + ssl_certificate ../../certs/nginx_voms_example.cert.pem; + ssl_certificate_key ../../certs/nginx_voms_example.key.pem; + ssl_client_certificate ../../trust-anchors/igi-test-ca.pem; + ssl_verify_depth 10; + ssl_verify_client on; + location = / { + default_type text/plain; + echo $ssl_client_ee_cert; + } + } +--- config + location = / { + error_log logs/error-proxy.log debug; + proxy_pass https://localhost:8443/; + proxy_ssl_certificate ../../certs/0.cert.pem; + proxy_ssl_certificate_key ../../certs/0.key.pem; + } +--- request +GET / +--- response_body +-----BEGIN CERTIFICATE----- + MIIDnjCCAoagAwIBAgIBCTANBgkqhkiG9w0BAQUFADAtMQswCQYDVQQGEwJJVDEM + MAoGA1UECgwDSUdJMRAwDgYDVQQDDAdUZXN0IENBMB4XDTEyMDkyNjE1MzkzNFoX + DTIyMDkyNDE1MzkzNFowKzELMAkGA1UEBhMCSVQxDDAKBgNVBAoTA0lHSTEOMAwG + A1UEAxMFdGVzdDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKxtrw + hoZ27SxxISjlRqWmBWB6U+N/xW2kS1uUfrQRav6auVtmtEW45J44VTi3WW6Y113R + BwmS6oW+3lzyBBZVPqnhV9/VkTxLp83gGVVvHATgGgkjeTxIsOE+TkPKAoZJ/QFc + CfPh3WdZ3ANI14WYkAM9VXsSbh2okCsWGa4o6pzt3Pt1zKkyO4PW0cBkletDImJK + 2vufuDVNm7Iz/y3/8pY8p3MoiwbF/PdSba7XQAxBWUJMoaleh8xy8HSROn7tF2al + xoDLH4QWhp6UDn2rvOWseBqUMPXFjsUi1/rkw1oHAjMroTk5lL15GI0LGd5dTVop + kKXFbTTYxSkPz1MLAgMBAAGjgcowgccwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU + fLdB5+jO9LyWN2/VCNYgMa0jvHEwDgYDVR0PAQH/BAQDAgXgMD4GA1UdJQQ3MDUG + CCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBBggrBgEF + BQcDBDAfBgNVHSMEGDAWgBSRdzZ7LrRp8yfqt/YIi0ojohFJxjAnBgNVHREEIDAe + gRxhbmRyZWEuY2VjY2FudGlAY25hZi5pbmZuLml0MA0GCSqGSIb3DQEBBQUAA4IB + AQANYtWXetheSeVpCfnId9TkKyKTAp8RahNZl4XFrWWn2S9We7ACK/G7u1DebJYx + d8POo8ClscoXyTO2BzHHZLxauEKIzUv7g2GehI+SckfZdjFyRXjD0+wMGwzX7MDu + SL3CG2aWsYpkBnj6BMlr0P3kZEMqV5t2+2Tj0+aXppBPVwzJwRhnrSJiO5WIZAZf + 49YhMn61sQIrepvhrKEUR4XVorH2Bj8ek1/iLlgcmFMBOds+PrehSRR8Gn0IjlEg + C68EY6KPE+FKySuS7Ur7lTAjNdddfdAgKV6hJyST6/dx8ymIkb8nxCPnxCcT2I2N + vDxcPMc/wmnMa+smNal0sJ6m + -----END CERTIFICATE----- +--- error_code: 200