Index: c/sslinfo.c |
diff --git a/c/sslinfo.c b/c/sslinfo.c |
deleted file mode 100644 |
index 0ee3829710d52d2c750c4b66b7cc766d8df9a8d1..0000000000000000000000000000000000000000 |
--- a/c/sslinfo.c |
+++ /dev/null |
@@ -1,591 +0,0 @@ |
-/* Licensed to the Apache Software Foundation (ASF) under one or more |
- * contributor license agreements. See the NOTICE file distributed with |
- * this work for additional information regarding copyright ownership. |
- * The ASF licenses this file to You under the Apache License, Version 2.0 |
- * (the "License"); you may not use this file except in compliance with |
- * the License. You may obtain a copy of the License at |
- * |
- * http://www.apache.org/licenses/LICENSE-2.0 |
- * |
- * Unless required by applicable law or agreed to in writing, software |
- * distributed under the License is distributed on an "AS IS" BASIS, |
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
- * See the License for the specific language governing permissions and |
- * limitations under the License. |
- */ |
- |
-/** SSL info wrapper |
- * |
- * @author Mladen Turk |
- * @version $Id: sslinfo.c 1658603 2015-02-09 23:26:44Z kkolinko $ |
- */ |
- |
-#include "tcn.h" |
-#include "apr_file_io.h" |
-#include "apr_thread_mutex.h" |
-#include "apr_poll.h" |
- |
-#ifdef HAVE_OPENSSL |
-#include "ssl_private.h" |
- |
-static const char *hex_basis = "0123456789ABCDEF"; |
- |
-static char *convert_to_hex(const void *buf, size_t len) |
-{ |
- const unsigned char *p = ( const unsigned char *)buf; |
- char *str, *s; |
- size_t i; |
- |
- if ((len < 1) || ((str = malloc(len * 2 + 1)) == NULL)) |
- return NULL; |
- for (i = 0, s = str; i < len; i++) { |
- unsigned char c = *p++; |
- *s++ = hex_basis[c >> 4]; |
- *s++ = hex_basis[c & 0x0F]; |
- } |
- *s = '\0'; |
- return str; |
-} |
- |
-#define DIGIT2NUM(x) (((x)[0] - '0') * 10 + (x)[1] - '0') |
- |
-static int get_days_remaining(ASN1_UTCTIME *tm) |
-{ |
- apr_time_t then, now = apr_time_now(); |
- apr_time_exp_t exp = {0}; |
- int diff; |
- |
- /* Fail if the time isn't a valid ASN.1 UTCTIME; RFC3280 mandates |
- * that the seconds digits are present even though ASN.1 |
- * doesn't. */ |
- if (tm->length < 11 || !ASN1_UTCTIME_check(tm)) |
- return 0; |
- |
- exp.tm_year = DIGIT2NUM(tm->data); |
- exp.tm_mon = DIGIT2NUM(tm->data + 2) - 1; |
- exp.tm_mday = DIGIT2NUM(tm->data + 4) + 1; |
- exp.tm_hour = DIGIT2NUM(tm->data + 6); |
- exp.tm_min = DIGIT2NUM(tm->data + 8); |
- exp.tm_sec = DIGIT2NUM(tm->data + 10); |
- |
- if (exp.tm_year <= 50) |
- exp.tm_year += 100; |
- if (apr_time_exp_gmt_get(&then, &exp) != APR_SUCCESS) |
- return 0; |
- |
- diff = (int)((apr_time_sec(then) - apr_time_sec(now)) / (60*60*24)); |
- return diff > 0 ? diff : 0; |
-} |
- |
-static char *get_cert_valid(ASN1_UTCTIME *tm) |
-{ |
- char *result; |
- BIO* bio; |
- int n; |
- |
- if ((bio = BIO_new(BIO_s_mem())) == NULL) |
- return NULL; |
- ASN1_UTCTIME_print(bio, tm); |
- n = BIO_pending(bio); |
- result = malloc(n+1); |
- n = BIO_read(bio, result, n); |
- result[n] = '\0'; |
- BIO_free(bio); |
- return result; |
-} |
- |
-static char *get_cert_PEM(X509 *xs) |
-{ |
- char *result = NULL; |
- BIO *bio; |
- |
- if ((bio = BIO_new(BIO_s_mem())) == NULL) |
- return NULL; |
- if (PEM_write_bio_X509(bio, xs)) { |
- int n = BIO_pending(bio); |
- result = malloc(n+1); |
- n = BIO_read(bio, result, n); |
- result[n] = '\0'; |
- } |
- BIO_free(bio); |
- return result; |
-} |
- |
-static unsigned char *get_cert_ASN1(X509 *xs, int *len) |
-{ |
- unsigned char *result = NULL; |
- BIO *bio; |
- |
- *len = 0; |
- if ((bio = BIO_new(BIO_s_mem())) == NULL) |
- return NULL; |
- if (i2d_X509_bio(bio, xs)) { |
- int n = BIO_pending(bio); |
- result = malloc(n); |
- n = BIO_read(bio, result, n); |
- *len = n; |
- } |
- BIO_free(bio); |
- return result; |
-} |
- |
- |
-static char *get_cert_serial(X509 *xs) |
-{ |
- char *result; |
- BIO *bio; |
- int n; |
- |
- if ((bio = BIO_new(BIO_s_mem())) == NULL) |
- return NULL; |
- i2a_ASN1_INTEGER(bio, X509_get_serialNumber(xs)); |
- n = BIO_pending(bio); |
- result = malloc(n+1); |
- n = BIO_read(bio, result, n); |
- result[n] = '\0'; |
- BIO_free(bio); |
- return result; |
-} |
- |
-static const struct { |
- int fid; |
- int nid; |
-} info_cert_dn_rec[] = { |
- { SSL_INFO_DN_COUNTRYNAME, NID_countryName }, |
- { SSL_INFO_DN_STATEORPROVINCENAME, NID_stateOrProvinceName }, |
- { SSL_INFO_DN_LOCALITYNAME, NID_localityName }, |
- { SSL_INFO_DN_ORGANIZATIONNAME, NID_organizationName }, |
- { SSL_INFO_DN_ORGANIZATIONALUNITNAME, NID_organizationalUnitName }, |
- { SSL_INFO_DN_COMMONNAME, NID_commonName }, |
- { SSL_INFO_DN_TITLE, NID_title }, |
- { SSL_INFO_DN_INITIALS, NID_initials }, |
- { SSL_INFO_DN_GIVENNAME, NID_givenName }, |
- { SSL_INFO_DN_SURNAME, NID_surname }, |
- { SSL_INFO_DN_DESCRIPTION, NID_description }, |
- { SSL_INFO_DN_UNIQUEIDENTIFIER, NID_x500UniqueIdentifier }, |
- { SSL_INFO_DN_EMAILADDRESS, NID_pkcs9_emailAddress }, |
- { 0, 0 } |
-}; |
- |
-static char *lookup_ssl_cert_dn(X509_NAME *xsname, int dnidx) |
-{ |
- char *result; |
- X509_NAME_ENTRY *xsne; |
- int i, j, n, idx = 0; |
- |
- result = NULL; |
- |
- for (i = 0; info_cert_dn_rec[i].fid != 0; i++) { |
- if (info_cert_dn_rec[i].fid == dnidx) { |
- for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) |
- (xsname->entries)); j++) { |
- xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) |
- (xsname->entries), j); |
- |
- n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); |
- if (n == info_cert_dn_rec[i].nid && idx-- == 0) { |
- result = malloc(xsne->value->length + 1); |
- memcpy(result, xsne->value->data, |
- xsne->value->length); |
- result[xsne->value->length] = '\0'; |
- |
-#if APR_CHARSET_EBCDIC |
- ap_xlate_proto_from_ascii(result, xsne->value->length); |
-#endif /* APR_CHARSET_EBCDIC */ |
- break; |
- } |
- } |
- break; |
- } |
- } |
- return result; |
-} |
- |
-TCN_IMPLEMENT_CALL(jobject, SSLSocket, getInfoB)(TCN_STDARGS, jlong sock, |
- jint what) |
-{ |
- tcn_socket_t *a = J2P(sock, tcn_socket_t *); |
- tcn_ssl_conn_t *s; |
- jbyteArray array = NULL; |
- apr_status_t rv = APR_SUCCESS; |
- |
- UNREFERENCED(o); |
- TCN_ASSERT(sock != 0); |
- |
- s = (tcn_ssl_conn_t *)(a->opaque); |
- switch (what) { |
- case SSL_INFO_SESSION_ID: |
- { |
- SSL_SESSION *session = SSL_get_session(s->ssl); |
- if (session) { |
- unsigned int len; |
- const unsigned char *id = SSL_SESSION_get_id(session, &len); |
- array = tcn_new_arrayb(e, id, len); |
- } |
- } |
- break; |
- default: |
- rv = APR_EINVAL; |
- break; |
- } |
- if (what & SSL_INFO_CLIENT_MASK) { |
- X509 *xs; |
- unsigned char *result; |
- int len; |
- if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { |
- switch (what) { |
- case SSL_INFO_CLIENT_CERT: |
- if ((result = get_cert_ASN1(xs, &len))) { |
- array = tcn_new_arrayb(e, result, len); |
- free(result); |
- } |
- break; |
- } |
- X509_free(xs); |
- } |
- rv = APR_SUCCESS; |
- } |
- else if (what & SSL_INFO_SERVER_MASK) { |
- X509 *xs; |
- unsigned char *result; |
- int len; |
- if ((xs = SSL_get_certificate(s->ssl)) != NULL) { |
- switch (what) { |
- case SSL_INFO_SERVER_CERT: |
- if ((result = get_cert_ASN1(xs, &len))) { |
- array = tcn_new_arrayb(e, result, len); |
- free(result); |
- } |
- break; |
- } |
- /* XXX: No need to call the X509_free(xs); */ |
- } |
- rv = APR_SUCCESS; |
- } |
- else if (what & SSL_INFO_CLIENT_CERT_CHAIN) { |
- X509 *xs; |
- unsigned char *result; |
- STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s->ssl); |
- int len, n = what & 0x0F; |
- if (n < sk_X509_num(sk)) { |
- xs = sk_X509_value(sk, n); |
- if ((result = get_cert_ASN1(xs, &len))) { |
- array = tcn_new_arrayb(e, result, len); |
- free(result); |
- } |
- } |
- rv = APR_SUCCESS; |
- } |
- if (rv != APR_SUCCESS) |
- tcn_ThrowAPRException(e, rv); |
- |
- return array; |
-} |
- |
-TCN_IMPLEMENT_CALL(jstring, SSLSocket, getInfoS)(TCN_STDARGS, jlong sock, |
- jint what) |
-{ |
- tcn_socket_t *a = J2P(sock, tcn_socket_t *); |
- tcn_ssl_conn_t *s; |
- jstring value = NULL; |
- apr_status_t rv = APR_SUCCESS; |
- |
- UNREFERENCED(o); |
- TCN_ASSERT(sock != 0); |
- |
- s = (tcn_ssl_conn_t *)(a->opaque); |
- switch (what) { |
- case SSL_INFO_SESSION_ID: |
- { |
- SSL_SESSION *session = SSL_get_session(s->ssl); |
- if (session) { |
- unsigned int len; |
- const unsigned char *id = SSL_SESSION_get_id(session, &len); |
- char *hs = convert_to_hex(id, len); |
- if (hs) { |
- value = tcn_new_string(e, hs); |
- free(hs); |
- } |
- } |
- } |
- break; |
- case SSL_INFO_PROTOCOL: |
- value = tcn_new_string(e, SSL_get_version(s->ssl)); |
- break; |
- case SSL_INFO_CIPHER: |
- value = tcn_new_string(e, SSL_get_cipher_name(s->ssl)); |
- break; |
- case SSL_INFO_CIPHER_VERSION: |
- value = tcn_new_string(e, SSL_get_cipher_version(s->ssl)); |
- break; |
- case SSL_INFO_CIPHER_DESCRIPTION: |
- { |
- SSL_CIPHER *cipher = (SSL_CIPHER *)SSL_get_current_cipher(s->ssl); |
- if (cipher) { |
- char buf[256]; |
- const char *desc = SSL_CIPHER_description(cipher, buf, 256); |
- value = tcn_new_string(e, desc); |
- } |
- } |
- break; |
- default: |
- rv = APR_EINVAL; |
- break; |
- } |
- if (what & (SSL_INFO_CLIENT_S_DN | SSL_INFO_CLIENT_I_DN)) { |
- X509 *xs; |
- X509_NAME *xsname; |
- if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { |
- char *result; |
- int idx = what & 0x0F; |
- if (what & SSL_INFO_CLIENT_S_DN) |
- xsname = X509_get_subject_name(xs); |
- else |
- xsname = X509_get_issuer_name(xs); |
- if (idx) { |
- result = lookup_ssl_cert_dn(xsname, idx); |
- if (result) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- } |
- else |
- value = tcn_new_string(e, X509_NAME_oneline(xsname, NULL, 0)); |
- X509_free(xs); |
- } |
- rv = APR_SUCCESS; |
- } |
- else if (what & (SSL_INFO_SERVER_S_DN | SSL_INFO_SERVER_I_DN)) { |
- X509 *xs; |
- X509_NAME *xsname; |
- if ((xs = SSL_get_certificate(s->ssl)) != NULL) { |
- char *result; |
- int idx = what & 0x0F; |
- if (what & SSL_INFO_SERVER_S_DN) |
- xsname = X509_get_subject_name(xs); |
- else |
- xsname = X509_get_issuer_name(xs); |
- if (idx) { |
- result = lookup_ssl_cert_dn(xsname, what & 0x0F); |
- if (result) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- } |
- else |
- value = tcn_new_string(e, X509_NAME_oneline(xsname, NULL, 0)); |
- /* XXX: No need to call the X509_free(xs); */ |
- } |
- rv = APR_SUCCESS; |
- } |
- else if (what & SSL_INFO_CLIENT_MASK) { |
- X509 *xs; |
- char *result; |
- int nid; |
- if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { |
- switch (what) { |
- case SSL_INFO_CLIENT_V_START: |
- if ((result = get_cert_valid(X509_get_notBefore(xs)))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- case SSL_INFO_CLIENT_V_END: |
- if ((result = get_cert_valid(X509_get_notAfter(xs)))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- case SSL_INFO_CLIENT_A_SIG: |
- nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->signature->algorithm); |
- if (nid == NID_undef) |
- value = tcn_new_string(e, "UNKNOWN"); |
- else |
- value = tcn_new_string(e, OBJ_nid2ln(nid)); |
- break; |
- case SSL_INFO_CLIENT_A_KEY: |
- nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->key->algor->algorithm); |
- if (nid == NID_undef) |
- value = tcn_new_string(e, "UNKNOWN"); |
- else |
- value = tcn_new_string(e, OBJ_nid2ln(nid)); |
- break; |
- case SSL_INFO_CLIENT_CERT: |
- if ((result = get_cert_PEM(xs))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- case SSL_INFO_CLIENT_M_SERIAL: |
- if ((result = get_cert_serial(xs))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- } |
- X509_free(xs); |
- } |
- rv = APR_SUCCESS; |
- } |
- else if (what & SSL_INFO_SERVER_MASK) { |
- X509 *xs; |
- char *result; |
- int nid; |
- if ((xs = SSL_get_certificate(s->ssl)) != NULL) { |
- switch (what) { |
- case SSL_INFO_SERVER_V_START: |
- if ((result = get_cert_valid(X509_get_notBefore(xs)))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- case SSL_INFO_SERVER_V_END: |
- if ((result = get_cert_valid(X509_get_notAfter(xs)))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- case SSL_INFO_SERVER_A_SIG: |
- nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->signature->algorithm); |
- if (nid == NID_undef) |
- value = tcn_new_string(e, "UNKNOWN"); |
- else |
- value = tcn_new_string(e, OBJ_nid2ln(nid)); |
- break; |
- case SSL_INFO_SERVER_A_KEY: |
- nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->key->algor->algorithm); |
- if (nid == NID_undef) |
- value = tcn_new_string(e, "UNKNOWN"); |
- else |
- value = tcn_new_string(e, OBJ_nid2ln(nid)); |
- break; |
- case SSL_INFO_SERVER_CERT: |
- if ((result = get_cert_PEM(xs))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- case SSL_INFO_SERVER_M_SERIAL: |
- if ((result = get_cert_serial(xs))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- break; |
- } |
- /* XXX: No need to call the X509_free(xs); */ |
- } |
- rv = APR_SUCCESS; |
- } |
- else if (what & SSL_INFO_CLIENT_CERT_CHAIN) { |
- X509 *xs; |
- char *result; |
- STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s->ssl); |
- int n = what & 0x0F; |
- if (n < sk_X509_num(sk)) { |
- xs = sk_X509_value(sk, n); |
- if ((result = get_cert_PEM(xs))) { |
- value = tcn_new_string(e, result); |
- free(result); |
- } |
- } |
- rv = APR_SUCCESS; |
- } |
- if (rv != APR_SUCCESS) |
- tcn_ThrowAPRException(e, rv); |
- |
- return value; |
-} |
- |
-TCN_IMPLEMENT_CALL(jint, SSLSocket, getInfoI)(TCN_STDARGS, jlong sock, |
- jint what) |
-{ |
- tcn_socket_t *a = J2P(sock, tcn_socket_t *); |
- tcn_ssl_conn_t *s; |
- apr_status_t rv = APR_SUCCESS; |
- jint value = -1; |
- |
- UNREFERENCED(o); |
- TCN_ASSERT(sock != 0); |
- |
- s = (tcn_ssl_conn_t *)(a->opaque); |
- |
- switch (what) { |
- case SSL_INFO_CIPHER_USEKEYSIZE: |
- case SSL_INFO_CIPHER_ALGKEYSIZE: |
- { |
- int usekeysize = 0; |
- int algkeysize = 0; |
- const SSL_CIPHER *cipher = SSL_get_current_cipher(s->ssl); |
- if (cipher) { |
- usekeysize = SSL_CIPHER_get_bits(cipher, &algkeysize); |
- if (what == SSL_INFO_CIPHER_USEKEYSIZE) |
- value = usekeysize; |
- else |
- value = algkeysize; |
- } |
- } |
- break; |
- case SSL_INFO_CLIENT_CERT_CHAIN: |
- { |
- STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s->ssl); |
- value = sk_X509_num(sk); |
- } |
- break; |
- default: |
- rv = APR_EINVAL; |
- break; |
- } |
- if (what & SSL_INFO_CLIENT_MASK) { |
- X509 *xs; |
- if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { |
- switch (what) { |
- case SSL_INFO_CLIENT_V_REMAIN: |
- value = get_days_remaining(X509_get_notAfter(xs)); |
- rv = APR_SUCCESS; |
- break; |
- default: |
- rv = APR_EINVAL; |
- break; |
- } |
- X509_free(xs); |
- } |
- } |
- |
- if (rv != APR_SUCCESS) |
- tcn_ThrowAPRException(e, rv); |
- return value; |
-} |
- |
-#else |
-/* OpenSSL is not supported. |
- * Create empty stubs. |
- */ |
- |
-TCN_IMPLEMENT_CALL(jobject, SSLSocket, getInfoB)(TCN_STDARGS, jlong sock, |
- jint what) |
-{ |
- UNREFERENCED_STDARGS; |
- UNREFERENCED(sock); |
- UNREFERENCED(what); |
- return NULL; |
-} |
- |
-TCN_IMPLEMENT_CALL(jstring, SSLSocket, getInfoS)(TCN_STDARGS, jlong sock, |
- jint what) |
-{ |
- UNREFERENCED_STDARGS; |
- UNREFERENCED(sock); |
- UNREFERENCED(what); |
- return NULL; |
-} |
- |
-TCN_IMPLEMENT_CALL(jint, SSLSocket, getInfoI)(TCN_STDARGS, jlong sock, |
- jint what) |
-{ |
- UNREFERENCED_STDARGS; |
- UNREFERENCED(sock); |
- UNREFERENCED(what); |
- return 0; |
-} |
- |
-#endif |