После некоторых исследований я решил ответить на свой вопрос. Макрос для X509_get_notAfter выглядит следующим образом:
#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
х - это X509 структура, которая содержит структуру X509_CINF, которая содержит структуру X509_VAL, которые содержат указатель на NotAfter :)
Так что мой план реализовать весь X509, X509_CINF и X509_VAL в коде python.
В C это выглядит следующим образом
struct x509_st
{
X509_CINF *cert_info;
X509_ALGOR *sig_alg;
ASN1_BIT_STRING *signature;
int valid;
int references;
char *name;
CRYPTO_EX_DATA ex_data;
/* These contain copies of various extension values */
long ex_pathlen;
long ex_pcpathlen;
unsigned long ex_flags;
unsigned long ex_kusage;
unsigned long ex_xkusage;
unsigned long ex_nscert;
ASN1_OCTET_STRING *skid;
AUTHORITY_KEYID *akid;
X509_POLICY_CACHE *policy_cache;
STACK_OF(DIST_POINT) *crldp;
STACK_OF(GENERAL_NAME) *altname;
NAME_CONSTRAINTS *nc;
#ifndef OPENSSL_NO_RFC3779
STACK_OF(IPAddressFamily) *rfc3779_addr;
struct ASIdentifiers_st *rfc3779_asid;
#endif
#ifndef OPENSSL_NO_SHA
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
#endif
X509_CERT_AUX *aux;
} /* X509 */;
И X509_CINF выглядит следующим образом:
typedef struct x509_cinf_st
{
ASN1_INTEGER *version; /* [ 0 ] default of v1 */
ASN1_INTEGER *serialNumber;
X509_ALGOR *signature;
X509_NAME *issuer;
X509_VAL *validity;
X509_NAME *subject;
X509_PUBKEY *key;
ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */
ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */
STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */
ASN1_ENCODING enc;
} X509_CINF;
А вот X509_VAL:
typedef struct X509_val_st
{
ASN1_TIME *notBefore;
ASN1_TIME *notAfter;
} X509_VAL;
Чтобы сделать всю задачу, я решил заменить все указатели на структуры, к которым я не хочу обращаться с помощью ctypes.c_void_p
Так что мой питон код теперь выглядит так:
class X509_val_st(ctypes.Structure):
_fields_ = [('notBefore', ctypes.c_void_p),
('notAfter', ctypes.c_void_p)]
class X509_cinf_st(ctypes.Structure):
_fields_ = [('version', ctypes.c_void_p),
('serialNumber', ctypes.c_void_p),
('signature', ctypes.c_void_p),
('issuer', ctypes.c_void_p),
('validity', X509_val_st),
('subject', ctypes.c_void_p),
('key', ctypes.c_void_p),
('issuerUID', ctypes.c_void_p),
('subjectUID', ctypes.c_void_p),
('extensions', ctypes.c_void_p),
('enc', ctypes.c_uint)]
class X509_st(ctypes.Structure):
_fields_ = [('cert_info', X509_cinf_st),
('sig_alg', ctypes.c_void_p),
('signature', ctypes.c_void_p),
('valid', ctypes.c_int),
('references', ctypes.c_int),
('name', ctypes.c_void_p),
('ex_data', ctypes.c_int),
('ex_pathlen', ctypes.c_long),
('ex_pcpathlen', ctypes.c_long),
('ex_flags', ctypes.c_ulong),
('ex_kusage', ctypes.c_ulong),
('ex_xkusage', ctypes.c_ulong),
('ex_nscert', ctypes.c_ulong),
('skid', ctypes.c_void_p),
('akid', ctypes.c_void_p),
('policy_cache', ctypes.c_void_p),
('crldp', ctypes.c_void_p),
('altname', ctypes.c_void_p),
('nc', ctypes.c_void_p),
('rfc3779_addr', ctypes.c_void_p),
('rfc3779_asid', ctypes.c_void_p),
('sha1_hash', ctypes.c_char),
('aux', ctypes.c_void_p)]
И последний шаг: назначить структуру указателя, полученного от функции X509_new():
self.X509_new = self._lib.X509_new
self.X509_new.restype = ctypes.POINTER(X509_st)
self.X509_new.argtypes = []
Так питон функции для OpenSSL macro X509_get_notBefore будет выглядеть так:
def X509_get_notBefore(self):
return self.X509[0].cert_info.validity.notBefore
Вы не можете импортировать «функции, определенные как макросы» beca они не существуют в библиотеке. – wRAR