📄 ssl_engine_vars.c
字号:
{ "UID", NID_x500UniqueIdentifier },#else /* old name, OpenSSL < 0.9.7 */ { "UID", NID_uniqueIdentifier },#endif { "Email", NID_pkcs9_emailAddress }, { NULL, 0 }};static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var){ char *result, *ptr; X509_NAME_ENTRY *xsne; int i, j, n, idx = 0; apr_size_t varlen; /* if an _N suffix is used, find the Nth attribute of given name */ ptr = strchr(var, '_'); if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) { idx = atoi(ptr + 1); varlen = ptr - var; } else { varlen = strlen(var); } result = NULL; for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) { if (strEQn(var, ssl_var_lookup_ssl_cert_dn_rec[i].name, varlen) && strlen(ssl_var_lookup_ssl_cert_dn_rec[i].name) == varlen) { for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) X509_NAME_get_entries(xsname)); j++) { xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) X509_NAME_get_entries(xsname), j); n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) { unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne); /* cast needed from unsigned char to char */ result = apr_pstrmemdup(p, (char *)data, X509_NAME_ENTRY_get_data_len(xsne));#if APR_CHARSET_EBCDIC ap_xlate_proto_from_ascii(result, X509_NAME_ENTRY_get_data_len(xsne));#endif /* APR_CHARSET_EBCDIC */ break; } } break; } } return result;}static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, 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 = apr_pcalloc(p, n+1); n = BIO_read(bio, result, n); result[n] = NUL; BIO_free(bio); return result;}#define DIGIT2NUM(x) (((x)[0] - '0') * 10 + (x)[1] - '0')/* Return a string giving the number of days remaining until 'tm', or * "0" if this can't be determined. */static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_UTCTIME *tm){ apr_time_t then, now = apr_time_now(); apr_time_exp_t exp = {0}; long 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 apr_pstrdup(p, "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 apr_pstrdup(p, "0"); } diff = (long)((apr_time_sec(then) - apr_time_sec(now)) / (60*60*24)); return diff > 0 ? apr_ltoa(p, diff) : apr_pstrdup(p, "0");}static char *ssl_var_lookup_ssl_cert_serial(apr_pool_t *p, 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 = apr_pcalloc(p, n+1); n = BIO_read(bio, result, n); result[n] = NUL; BIO_free(bio); return result;}static char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, STACK_OF(X509) *sk, char *var){ char *result; X509 *xs; int n; result = NULL; if (strspn(var, "0123456789") == strlen(var)) { n = atoi(var); if (n < sk_X509_num(sk)) { xs = sk_X509_value(sk, n); result = ssl_var_lookup_ssl_cert_PEM(p, xs); } } return result;}static char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, X509 *xs){ char *result; BIO *bio; int n; if ((bio = BIO_new(BIO_s_mem())) == NULL) return NULL; PEM_write_bio_X509(bio, xs); n = BIO_pending(bio); result = apr_pcalloc(p, n+1); n = BIO_read(bio, result, n); result[n] = NUL; BIO_free(bio); return result;}static char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c){ SSLConnRec *sslconn = myConnConfig(c); char *result; long vrc; const char *verr; const char *vinfo; SSL *ssl; X509 *xs; result = NULL; ssl = sslconn->ssl; verr = sslconn->verify_error; vinfo = sslconn->verify_info; vrc = SSL_get_verify_result(ssl); xs = SSL_get_peer_certificate(ssl); if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs == NULL) /* no client verification done at all */ result = "NONE"; else if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs != NULL) /* client verification done successful */ result = "SUCCESS"; else if (vrc == X509_V_OK && vinfo != NULL && strEQ(vinfo, "GENEROUS")) /* client verification done in generous way */ result = "GENEROUS"; else /* client verification failed */ result = apr_psprintf(p, "FAILED:%s", verr); if (xs) X509_free(xs); return result;}static char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, conn_rec *c, char *var){ SSLConnRec *sslconn = myConnConfig(c); char *result; BOOL resdup; int usekeysize, algkeysize; SSL *ssl; result = NULL; resdup = TRUE; ssl = sslconn->ssl; ssl_var_lookup_ssl_cipher_bits(ssl, &usekeysize, &algkeysize); if (ssl && strEQ(var, "")) { SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); result = (cipher != NULL ? (char *)SSL_CIPHER_get_name(cipher) : NULL); } else if (strcEQ(var, "_EXPORT")) result = (usekeysize < 56 ? "true" : "false"); else if (strcEQ(var, "_USEKEYSIZE")) { result = apr_itoa(p, usekeysize); resdup = FALSE; } else if (strcEQ(var, "_ALGKEYSIZE")) { result = apr_itoa(p, algkeysize); resdup = FALSE; } if (result != NULL && resdup) result = apr_pstrdup(p, result); return result;}static void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize){ SSL_CIPHER *cipher; *usekeysize = 0; *algkeysize = 0; if (ssl != NULL) if ((cipher = SSL_get_current_cipher(ssl)) != NULL) *usekeysize = SSL_CIPHER_get_bits(cipher, algkeysize); return;}static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var){ if (strEQ(var, "INTERFACE")) { return apr_pstrdup(p, var_interface); } else if (strEQ(var, "LIBRARY_INTERFACE")) { return apr_pstrdup(p, var_library_interface); } else if (strEQ(var, "LIBRARY")) { return apr_pstrdup(p, var_library); } return NULL;}const char *ssl_ext_lookup(apr_pool_t *p, conn_rec *c, int peer, const char *oidnum){ SSLConnRec *sslconn = myConnConfig(c); SSL *ssl; X509 *xs = NULL; ASN1_OBJECT *oid; int count = 0, j; char *result = NULL; if (!sslconn || !sslconn->ssl) { return NULL; } ssl = sslconn->ssl; oid = OBJ_txt2obj(oidnum, 1); if (!oid) { ERR_clear_error(); return NULL; } xs = peer ? SSL_get_peer_certificate(ssl) : SSL_get_certificate(ssl); if (xs == NULL) { return NULL; } count = X509_get_ext_count(xs); for (j = 0; j < count; j++) { X509_EXTENSION *ext = X509_get_ext(xs, j); if (OBJ_cmp(ext->object, oid) == 0) { BIO *bio = BIO_new(BIO_s_mem()); if (X509V3_EXT_print(bio, ext, 0, 0) == 1) { BUF_MEM *buf; BIO_get_mem_ptr(bio, &buf); result = apr_pstrmemdup(p, buf->data, buf->length); } BIO_vfree(bio); break; } } if (peer) { /* only SSL_get_peer_certificate raises the refcount */ X509_free(xs); } ERR_clear_error(); return result;}static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl){ char *result = "NULL";#ifdef OPENSSL_VERSION_NUMBER#if (OPENSSL_VERSION_NUMBER >= 0x00908000) SSL_SESSION *pSession = SSL_get_session(ssl); if (pSession) { switch (pSession->compress_meth) { case 0: /* default "NULL" already set */ break; /* Defined by RFC 3749, deflate is coded by "1" */ case 1: result = "DEFLATE"; break; /* IANA assigned compression number for LZS */ case 0x40: result = "LZS"; break; default: result = "UNKNOWN"; break; } }#endif#endif return result;}/* _________________________________________________________________**** SSL Extension to mod_log_config** _________________________________________________________________*/#include "../../modules/loggers/mod_log_config.h"static const char *ssl_var_log_handler_c(request_rec *r, char *a);static const char *ssl_var_log_handler_x(request_rec *r, char *a);/* * register us for the mod_log_config function registering phase * to establish %{...}c and to be able to expand %{...}x variables. */void ssl_var_log_config_register(apr_pool_t *p){ static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register; log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler); if (log_pfn_register) { log_pfn_register(p, "c", ssl_var_log_handler_c, 0); log_pfn_register(p, "x", ssl_var_log_handler_x, 0); } return;}/* * implement the %{..}c log function * (we are the only function) */static const char *ssl_var_log_handler_c(request_rec *r, char *a){ SSLConnRec *sslconn = myConnConfig(r->connection); char *result; if (sslconn == NULL || sslconn->ssl == NULL) return NULL; result = NULL; if (strEQ(a, "version")) result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_PROTOCOL"); else if (strEQ(a, "cipher")) result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER"); else if (strEQ(a, "subjectdn") || strEQ(a, "clientcert")) result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_S_DN"); else if (strEQ(a, "issuerdn") || strEQ(a, "cacert")) result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_I_DN"); else if (strEQ(a, "errcode")) result = "-"; else if (strEQ(a, "errstr")) result = (char *)sslconn->verify_error; if (result != NULL && result[0] == NUL) result = NULL; return result;}/* * extend the implementation of the %{..}x log function * (there can be more functions) */static const char *ssl_var_log_handler_x(request_rec *r, char *a){ char *result; result = ssl_var_lookup(r->pool, r->server, r->connection, r, a); if (result != NULL && result[0] == NUL) result = NULL; return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -