This is an automated email from the ASF dual-hosted git repository.
kichan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new fcd0827045 Add support for retrieving cert info in lua plugin (#12683)
fcd0827045 is described below
commit fcd0827045dd3da6a2342715bb7e94d5c8322955
Author: Kit Chan <[email protected]>
AuthorDate: Tue Dec 16 18:41:05 2025 +0100
Add support for retrieving cert info in lua plugin (#12683)
* Add support for retrieving cert info in lua plugin
* fix format error
* fix format error
* fix compile error
* Update plugins/lua/ts_lua_client_cert_helpers.h
Co-authored-by: Copilot <[email protected]>
* fix error checking
* fix error checking
* fix error checking
* fix error checking
* fix error checking
* Update plugins/lua/ts_lua_client_cert_helpers.h
Co-authored-by: Copilot <[email protected]>
* fix error checking
* fix error checking
* fix compile error
---------
Co-authored-by: Copilot <[email protected]>
---
doc/admin-guide/plugins/lua.en.rst | 347 +++++++++++
plugins/lua/ts_lua_client_cert_helpers.h | 243 ++++++++
plugins/lua/ts_lua_client_request.cc | 955 +++++++++++++++++++++++++++++++
3 files changed, 1545 insertions(+)
diff --git a/doc/admin-guide/plugins/lua.en.rst
b/doc/admin-guide/plugins/lua.en.rst
index b00999633e..08970e340e 100644
--- a/doc/admin-guide/plugins/lua.en.rst
+++ b/doc/admin-guide/plugins/lua.en.rst
@@ -1340,6 +1340,353 @@ Here is an example:
end
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_pem
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_pem()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the PEM-encoded client certificate (for mTLS connections).
+
+Returns the client certificate in PEM format, or nil if no client certificate
is present.
+
+Here is an example:
+
+::
+
+ function do_global_read_request()
+ pem = ts.client_request.client_cert_get_pem()
+ if pem then
+ ts.debug('Client cert PEM: ' .. pem)
+ end
+ end
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_subject
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_subject()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the subject DN from the client certificate.
+
+Returns the subject distinguished name in RFC2253 format, or nil if not
available.
+
+Here is an example:
+
+::
+
+ function do_global_read_request()
+ subject = ts.client_request.client_cert_get_subject()
+ if subject then
+ ts.debug('Client cert subject: ' .. subject)
+ end
+ end
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_issuer
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_issuer()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the issuer DN from the client certificate.
+
+Returns the issuer distinguished name in RFC2253 format, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_serial
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_serial()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the serial number from the client certificate.
+
+Returns the certificate serial number as a string, or nil if not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_signature
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_signature()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the signature from the client certificate.
+
+Returns the certificate signature as a colon-separated hex string, or nil if
not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_not_before
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_not_before()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the "not before" timestamp from the client certificate.
+
+Returns the certificate validity start date/time as a string, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_not_after
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_not_after()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the "not after" timestamp from the client certificate.
+
+Returns the certificate validity end date/time as a string, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_version
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_version()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the X.509 version from the client certificate.
+
+Returns the certificate version as an integer (typically 2 for v3
certificates), or nil if not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_san_dns
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_san_dns()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get DNS Subject Alternative Names from the client certificate.
+
+Returns a Lua table (array) of DNS names, or nil if none are present.
+
+Here is an example:
+
+::
+
+ function do_global_read_request()
+ dns_names = ts.client_request.client_cert_get_san_dns()
+ if dns_names then
+ for i, name in ipairs(dns_names) do
+ ts.debug('DNS SAN: ' .. name)
+ end
+ end
+ end
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_san_ip
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_san_ip()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get IP address Subject Alternative Names from the client
certificate.
+
+Returns a Lua table (array) of IP addresses, or nil if none are present.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_san_email
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_san_email()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get email Subject Alternative Names from the client
certificate.
+
+Returns a Lua table (array) of email addresses, or nil if none are present.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.client_cert_get_san_uri
+-----------------------------------------------
+**syntax:** *ts.client_request.client_cert_get_san_uri()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get URI Subject Alternative Names from the client certificate.
+
+Returns a Lua table (array) of URIs, or nil if none are present.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_pem
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_pem()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the PEM-encoded server certificate (the certificate ATS
presented to the client).
+
+Returns the server certificate in PEM format, or nil if not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_subject
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_subject()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the subject DN from the server certificate.
+
+Returns the subject distinguished name in RFC2253 format, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_issuer
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_issuer()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the issuer DN from the server certificate.
+
+Returns the issuer distinguished name in RFC2253 format, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_serial
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_serial()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the serial number from the server certificate.
+
+Returns the certificate serial number as a string, or nil if not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_signature
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_signature()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the signature from the server certificate.
+
+Returns the certificate signature as a colon-separated hex string, or nil if
not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_not_before
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_not_before()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the "not before" timestamp from the server certificate.
+
+Returns the certificate validity start date/time as a string, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_not_after
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_not_after()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the "not after" timestamp from the server certificate.
+
+Returns the certificate validity end date/time as a string, or nil if not
available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_version
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_version()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get the X.509 version from the server certificate.
+
+Returns the certificate version as an integer (typically 2 for v3
certificates), or nil if not available.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_san_dns
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_san_dns()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get DNS Subject Alternative Names from the server certificate.
+
+Returns a Lua table (array) of DNS names, or nil if none are present.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_san_ip
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_san_ip()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get IP address Subject Alternative Names from the server
certificate.
+
+Returns a Lua table (array) of IP addresses, or nil if none are present.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_san_email
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_san_email()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get email Subject Alternative Names from the server
certificate.
+
+Returns a Lua table (array) of email addresses, or nil if none are present.
+
+
+:ref:`TOP <admin-plugins-ts-lua>`
+
+ts.client_request.server_cert_get_san_uri
+-----------------------------------------------
+**syntax:** *ts.client_request.server_cert_get_san_uri()*
+
+**context:** do_remap/do_os_response or do_global_* or later
+
+**description**: Get URI Subject Alternative Names from the server certificate.
+
+Returns a Lua table (array) of URIs, or nil if none are present.
+
+
:ref:`TOP <admin-plugins-ts-lua>`
ts.client_request.get_pp_info
diff --git a/plugins/lua/ts_lua_client_cert_helpers.h
b/plugins/lua/ts_lua_client_cert_helpers.h
new file mode 100644
index 0000000000..c7f20b50eb
--- /dev/null
+++ b/plugins/lua/ts_lua_client_cert_helpers.h
@@ -0,0 +1,243 @@
+/*
+ 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.
+*/
+
+// Helper functions for certificate data extraction
+static std::string
+get_x509_name_string(X509_NAME *name)
+{
+ if (!name) {
+ return "";
+ }
+
+ BIO *bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ return "";
+ }
+
+ if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) <= 0) {
+ BIO_free(bio);
+ return "";
+ }
+
+ char *data = nullptr;
+ long length = BIO_get_mem_data(bio, &data);
+ std::string result;
+
+ if (data && length > 0) {
+ result.assign(data, length);
+ }
+
+ BIO_free(bio);
+ return result;
+}
+
+static std::string
+get_x509_serial_string(X509 *cert)
+{
+ if (!cert) {
+ return "";
+ }
+
+ ASN1_INTEGER *serial = X509_get_serialNumber(cert);
+ if (!serial) {
+ return "";
+ }
+
+ BIO *bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ return "";
+ }
+
+ if (i2a_ASN1_INTEGER(bio, serial) <= 0) {
+ BIO_free(bio);
+ return "";
+ }
+
+ char *data = nullptr;
+ long length = BIO_get_mem_data(bio, &data);
+ std::string result;
+
+ if (data && length > 0) {
+ result.assign(data, length);
+ }
+
+ BIO_free(bio);
+ return result;
+}
+
+static std::string
+get_x509_time_string(ASN1_TIME *time)
+{
+ if (!time) {
+ return "";
+ }
+
+ BIO *bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ return "";
+ }
+
+ if (ASN1_TIME_print(bio, time) <= 0) {
+ BIO_free(bio);
+ return "";
+ }
+
+ char *data = nullptr;
+ long length = BIO_get_mem_data(bio, &data);
+ std::string result;
+
+ if (data && length > 0) {
+ result.assign(data, length);
+ }
+
+ BIO_free(bio);
+ return result;
+}
+
+static std::string
+get_x509_pem_string(X509 *cert)
+{
+ if (!cert) {
+ return "";
+ }
+
+ BIO *bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ return "";
+ }
+
+ if (PEM_write_bio_X509(bio, cert) <= 0) {
+ BIO_free(bio);
+ return "";
+ }
+
+ char *data = nullptr;
+ long length = BIO_get_mem_data(bio, &data);
+ std::string result;
+
+ if (data && length > 0) {
+ result.assign(data, length);
+ }
+
+ BIO_free(bio);
+ return result;
+}
+
+static std::string
+get_x509_signature_string(X509 *cert)
+{
+ if (!cert) {
+ return "";
+ }
+
+ const ASN1_BIT_STRING *sig = nullptr;
+ X509_get0_signature(&sig, nullptr, cert);
+
+ if (!sig) {
+ return "";
+ }
+
+ BIO *bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ return "";
+ }
+
+ for (int i = 0; i < sig->length; i++) {
+ if (BIO_printf(bio, "%02x", sig->data[i]) <= 0) {
+ BIO_free(bio);
+ return "";
+ }
+ if (i < sig->length - 1) {
+ if (BIO_printf(bio, ":") <= 0) {
+ BIO_free(bio);
+ return "";
+ }
+ }
+ }
+
+ char *data = nullptr;
+ long length = BIO_get_mem_data(bio, &data);
+ std::string result;
+
+ if (data && length > 0) {
+ result.assign(data, length);
+ }
+
+ BIO_free(bio);
+ return result;
+}
+
+static std::vector<std::string>
+get_x509_san_strings(X509 *cert, int san_type)
+{
+ std::vector<std::string> results;
+
+ if (!cert) {
+ return results;
+ }
+
+ GENERAL_NAMES *names = static_cast<GENERAL_NAMES *>(X509_get_ext_d2i(cert,
NID_subject_alt_name, nullptr, nullptr));
+ if (!names) {
+ return results;
+ }
+
+ int num_names = sk_GENERAL_NAME_num(names);
+ for (int i = 0; i < num_names; i++) {
+ GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
+ if (!name || name->type != san_type) {
+ continue;
+ }
+
+ switch (san_type) {
+ case GEN_DNS:
+ case GEN_EMAIL:
+ case GEN_URI: {
+ ASN1_STRING *str = name->d.ia5;
+ if (str) {
+ const unsigned char *data = ASN1_STRING_get0_data(str);
+ int len = ASN1_STRING_length(str);
+ if (data && len > 0) {
+ results.emplace_back(reinterpret_cast<const char *>(data), len);
+ }
+ }
+ break;
+ }
+ case GEN_IPADD: {
+ ASN1_OCTET_STRING *ip = name->d.iPAddress;
+ if (ip) {
+ const unsigned char *data = ASN1_STRING_get0_data(ip);
+ int len = ASN1_STRING_length(ip);
+ char ip_str[INET6_ADDRSTRLEN];
+
+ if (len == 4) { // IPv4
+ if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) != nullptr) {
+ results.emplace_back(ip_str);
+ }
+ } else if (len == 16) { // IPv6
+ if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) != nullptr) {
+ results.emplace_back(ip_str);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ GENERAL_NAMES_free(names);
+ return results;
+}
diff --git a/plugins/lua/ts_lua_client_request.cc
b/plugins/lua/ts_lua_client_request.cc
index a6beea92ab..4e675ffafa 100644
--- a/plugins/lua/ts_lua_client_request.cc
+++ b/plugins/lua/ts_lua_client_request.cc
@@ -18,7 +18,14 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/bio.h>
+#include <vector>
+#include <string>
#include "ts_lua_util.h"
+#include "ts_lua_client_cert_helpers.h"
typedef enum {
TS_LUA_PP_INFO_VERSION = TS_PP_INFO_VERSION,
@@ -94,6 +101,32 @@ static int
ts_lua_client_request_get_ssl_protocol(lua_State *L);
static void ts_lua_inject_client_request_ssl_curve_api(lua_State *L);
static int ts_lua_client_request_get_ssl_curve(lua_State *L);
+static void ts_lua_inject_client_request_cert_api(lua_State *L);
+static int ts_lua_client_request_client_cert_get_pem(lua_State *L);
+static int ts_lua_client_request_client_cert_get_subject(lua_State *L);
+static int ts_lua_client_request_client_cert_get_issuer(lua_State *L);
+static int ts_lua_client_request_client_cert_get_serial(lua_State *L);
+static int ts_lua_client_request_client_cert_get_signature(lua_State *L);
+static int ts_lua_client_request_client_cert_get_not_before(lua_State *L);
+static int ts_lua_client_request_client_cert_get_not_after(lua_State *L);
+static int ts_lua_client_request_client_cert_get_version(lua_State *L);
+static int ts_lua_client_request_client_cert_get_san_dns(lua_State *L);
+static int ts_lua_client_request_client_cert_get_san_ip(lua_State *L);
+static int ts_lua_client_request_client_cert_get_san_email(lua_State *L);
+static int ts_lua_client_request_client_cert_get_san_uri(lua_State *L);
+static int ts_lua_client_request_server_cert_get_pem(lua_State *L);
+static int ts_lua_client_request_server_cert_get_subject(lua_State *L);
+static int ts_lua_client_request_server_cert_get_issuer(lua_State *L);
+static int ts_lua_client_request_server_cert_get_serial(lua_State *L);
+static int ts_lua_client_request_server_cert_get_signature(lua_State *L);
+static int ts_lua_client_request_server_cert_get_not_before(lua_State *L);
+static int ts_lua_client_request_server_cert_get_not_after(lua_State *L);
+static int ts_lua_client_request_server_cert_get_version(lua_State *L);
+static int ts_lua_client_request_server_cert_get_san_dns(lua_State *L);
+static int ts_lua_client_request_server_cert_get_san_ip(lua_State *L);
+static int ts_lua_client_request_server_cert_get_san_email(lua_State *L);
+static int ts_lua_client_request_server_cert_get_san_uri(lua_State *L);
+
static void ts_lua_inject_client_request_pp_info_api(lua_State *L);
static int ts_lua_client_request_get_pp_info(lua_State *L);
static int ts_lua_client_request_get_pp_info_int(lua_State *L);
@@ -118,6 +151,7 @@ ts_lua_inject_client_request_api(lua_State *L)
ts_lua_inject_client_request_ssl_cipher_api(L);
ts_lua_inject_client_request_ssl_protocol_api(L);
ts_lua_inject_client_request_ssl_curve_api(L);
+ ts_lua_inject_client_request_cert_api(L);
ts_lua_inject_client_request_pp_info_api(L);
lua_setfield(L, -2, "client_request");
@@ -1169,6 +1203,927 @@ ts_lua_client_request_get_ssl_curve(lua_State *L)
return 1;
}
+// Certificate API Functions
+static void
+ts_lua_inject_client_request_cert_api(lua_State *L)
+{
+ // Client certificate functions
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_pem);
+ lua_setfield(L, -2, "client_cert_get_pem");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_subject);
+ lua_setfield(L, -2, "client_cert_get_subject");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_issuer);
+ lua_setfield(L, -2, "client_cert_get_issuer");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_serial);
+ lua_setfield(L, -2, "client_cert_get_serial");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_signature);
+ lua_setfield(L, -2, "client_cert_get_signature");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_not_before);
+ lua_setfield(L, -2, "client_cert_get_not_before");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_not_after);
+ lua_setfield(L, -2, "client_cert_get_not_after");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_version);
+ lua_setfield(L, -2, "client_cert_get_version");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_san_dns);
+ lua_setfield(L, -2, "client_cert_get_san_dns");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_san_ip);
+ lua_setfield(L, -2, "client_cert_get_san_ip");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_san_email);
+ lua_setfield(L, -2, "client_cert_get_san_email");
+
+ lua_pushcfunction(L, ts_lua_client_request_client_cert_get_san_uri);
+ lua_setfield(L, -2, "client_cert_get_san_uri");
+
+ // Server certificate functions
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_pem);
+ lua_setfield(L, -2, "server_cert_get_pem");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_subject);
+ lua_setfield(L, -2, "server_cert_get_subject");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_issuer);
+ lua_setfield(L, -2, "server_cert_get_issuer");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_serial);
+ lua_setfield(L, -2, "server_cert_get_serial");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_signature);
+ lua_setfield(L, -2, "server_cert_get_signature");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_not_before);
+ lua_setfield(L, -2, "server_cert_get_not_before");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_not_after);
+ lua_setfield(L, -2, "server_cert_get_not_after");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_version);
+ lua_setfield(L, -2, "server_cert_get_version");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_san_dns);
+ lua_setfield(L, -2, "server_cert_get_san_dns");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_san_ip);
+ lua_setfield(L, -2, "server_cert_get_san_ip");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_san_email);
+ lua_setfield(L, -2, "server_cert_get_san_email");
+
+ lua_pushcfunction(L, ts_lua_client_request_server_cert_get_san_uri);
+ lua_setfield(L, -2, "server_cert_get_san_uri");
+}
+
+// Client Certificate Functions
+static int
+ts_lua_client_request_client_cert_get_pem(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string pem = get_x509_pem_string(cert);
+ X509_free(cert);
+ if (!pem.empty()) {
+ lua_pushlstring(L, pem.c_str(), pem.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_subject(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string subject =
get_x509_name_string(X509_get_subject_name(cert));
+ X509_free(cert);
+ if (!subject.empty()) {
+ lua_pushlstring(L, subject.c_str(), subject.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_issuer(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string issuer = get_x509_name_string(X509_get_issuer_name(cert));
+ X509_free(cert);
+ if (!issuer.empty()) {
+ lua_pushlstring(L, issuer.c_str(), issuer.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_serial(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string serial = get_x509_serial_string(cert);
+ X509_free(cert);
+ if (!serial.empty()) {
+ lua_pushlstring(L, serial.c_str(), serial.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_signature(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string sig = get_x509_signature_string(cert);
+ X509_free(cert);
+ if (!sig.empty()) {
+ lua_pushlstring(L, sig.c_str(), sig.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_not_before(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string not_before =
get_x509_time_string(X509_get_notBefore(cert));
+ X509_free(cert);
+ if (!not_before.empty()) {
+ lua_pushlstring(L, not_before.c_str(), not_before.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_not_after(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::string not_after = get_x509_time_string(X509_get_notAfter(cert));
+ X509_free(cert);
+ if (!not_after.empty()) {
+ lua_pushlstring(L, not_after.c_str(), not_after.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_version(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ long version = X509_get_version(cert);
+ X509_free(cert);
+ lua_pushinteger(L, version);
+ return 1;
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_san_dns(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::vector<std::string> dns_names = get_x509_san_strings(cert,
GEN_DNS);
+ X509_free(cert);
+
+ if (!dns_names.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < dns_names.size(); i++) {
+ lua_pushlstring(L, dns_names[i].c_str(), dns_names[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_san_ip(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::vector<std::string> ip_addrs = get_x509_san_strings(cert,
GEN_IPADD);
+ X509_free(cert);
+
+ if (!ip_addrs.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < ip_addrs.size(); i++) {
+ lua_pushlstring(L, ip_addrs[i].c_str(), ip_addrs[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_san_email(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::vector<std::string> emails = get_x509_san_strings(cert,
GEN_EMAIL);
+ X509_free(cert);
+
+ if (!emails.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < emails.size(); i++) {
+ lua_pushlstring(L, emails[i].c_str(), emails[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_client_cert_get_san_uri(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+#ifdef OPENSSL_IS_OPENSSL3
+ X509 *cert = SSL_get1_peer_certificate(ssl);
+#else
+ X509 *cert = SSL_get_peer_certificate(ssl);
+#endif
+ if (cert) {
+ std::vector<std::string> uris = get_x509_san_strings(cert, GEN_URI);
+ X509_free(cert);
+
+ if (!uris.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < uris.size(); i++) {
+ lua_pushlstring(L, uris[i].c_str(), uris[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+// Server Certificate Functions
+static int
+ts_lua_client_request_server_cert_get_pem(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string pem = get_x509_pem_string(cert);
+ if (!pem.empty()) {
+ lua_pushlstring(L, pem.c_str(), pem.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_subject(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string subject =
get_x509_name_string(X509_get_subject_name(cert));
+ if (!subject.empty()) {
+ lua_pushlstring(L, subject.c_str(), subject.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_issuer(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string issuer = get_x509_name_string(X509_get_issuer_name(cert));
+ if (!issuer.empty()) {
+ lua_pushlstring(L, issuer.c_str(), issuer.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_serial(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string serial = get_x509_serial_string(cert);
+ if (!serial.empty()) {
+ lua_pushlstring(L, serial.c_str(), serial.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_signature(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string sig = get_x509_signature_string(cert);
+ if (!sig.empty()) {
+ lua_pushlstring(L, sig.c_str(), sig.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_not_before(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string not_before =
get_x509_time_string(X509_get_notBefore(cert));
+ if (!not_before.empty()) {
+ lua_pushlstring(L, not_before.c_str(), not_before.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_not_after(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::string not_after = get_x509_time_string(X509_get_notAfter(cert));
+ if (!not_after.empty()) {
+ lua_pushlstring(L, not_after.c_str(), not_after.length());
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_version(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ long version = X509_get_version(cert);
+ lua_pushinteger(L, version);
+ return 1;
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_san_dns(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::vector<std::string> dns_names = get_x509_san_strings(cert,
GEN_DNS);
+
+ if (!dns_names.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < dns_names.size(); i++) {
+ lua_pushlstring(L, dns_names[i].c_str(), dns_names[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_san_ip(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::vector<std::string> ip_addrs = get_x509_san_strings(cert,
GEN_IPADD);
+
+ if (!ip_addrs.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < ip_addrs.size(); i++) {
+ lua_pushlstring(L, ip_addrs[i].c_str(), ip_addrs[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_san_email(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::vector<std::string> emails = get_x509_san_strings(cert,
GEN_EMAIL);
+
+ if (!emails.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < emails.size(); i++) {
+ lua_pushlstring(L, emails[i].c_str(), emails[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+static int
+ts_lua_client_request_server_cert_get_san_uri(lua_State *L)
+{
+ ts_lua_http_ctx *http_ctx;
+ TSHttpSsn ssnp;
+ TSVConn client_conn;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ ssnp = TSHttpTxnSsnGet(http_ctx->txnp);
+ client_conn = TSHttpSsnClientVConnGet(ssnp);
+
+ if (TSVConnIsSsl(client_conn)) {
+ TSSslConnection ssl_conn = TSVConnSslConnectionGet(client_conn);
+ if (ssl_conn) {
+ SSL *ssl = reinterpret_cast<SSL *>(ssl_conn);
+ X509 *cert = SSL_get_certificate(ssl);
+ if (cert) {
+ std::vector<std::string> uris = get_x509_san_strings(cert, GEN_URI);
+
+ if (!uris.empty()) {
+ lua_newtable(L);
+ for (size_t i = 0; i < uris.size(); i++) {
+ lua_pushlstring(L, uris[i].c_str(), uris[i].length());
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
static void
ts_lua_inject_client_request_pp_info_api(lua_State *L)
{