2019-08-07 19:24:13 +08:00
|
|
|
/*************************************************************************
|
|
|
|
|
> File Name: cert_session.c
|
|
|
|
|
> Author:
|
|
|
|
|
> Mail:
|
|
|
|
|
> Created Time: Fri 01 Jun 2018 02:00:56 AM PDT
|
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
/* openssl**/
|
|
|
|
|
#include <opensslv.h>
|
|
|
|
|
#include <ssl.h>
|
|
|
|
|
#include <err.h>
|
|
|
|
|
#include <rand.h>
|
|
|
|
|
#include <x509.h>
|
|
|
|
|
#include <x509v3.h>
|
|
|
|
|
#include <crypto.h>
|
|
|
|
|
#include <engine.h>
|
|
|
|
|
#include <pkcs12.h>
|
|
|
|
|
|
|
|
|
|
#include "rt_string.h"
|
|
|
|
|
#include "rt_common.h"
|
|
|
|
|
#include "rt_stdlib.h"
|
|
|
|
|
#include "rt_file.h"
|
|
|
|
|
#include "rt_time.h"
|
|
|
|
|
#include "rt_tmr.h"
|
|
|
|
|
|
|
|
|
|
#include "bufferevent.h"
|
|
|
|
|
#include "listener.h"
|
|
|
|
|
#include "event_compat.h"
|
|
|
|
|
#include "http.h"
|
|
|
|
|
#include "buffer.h"
|
|
|
|
|
#include "util-internal.h"
|
|
|
|
|
|
|
|
|
|
enum x509_input_file{
|
|
|
|
|
INPUT_FILE_CERT,
|
|
|
|
|
INPUT_FILE_KEY,
|
|
|
|
|
INPUT_FILE_CRL,
|
|
|
|
|
INPUT_FILE_LIST,
|
|
|
|
|
INPUT_FILE_CHECK,
|
|
|
|
|
INPUT_FILE_CHAIN,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define LOCAL_USER_PEN 1
|
|
|
|
|
#define LOCAL_USER_DER 2
|
|
|
|
|
#define LOCAL_USER_P12 3
|
|
|
|
|
|
|
|
|
|
BIO *bio_err = NULL;
|
|
|
|
|
|
|
|
|
|
static const struct value_string format_vals[] =
|
|
|
|
|
{
|
|
|
|
|
{LOCAL_USER_PEN, "PEM TEXT FILE"},
|
|
|
|
|
{LOCAL_USER_DER, "DER BINARY FILE"},
|
|
|
|
|
{LOCAL_USER_P12, "P12 BINARY FILE"},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void help()
|
|
|
|
|
{
|
|
|
|
|
printf("Welcome to x509 %s\n", "1.1.1");
|
|
|
|
|
printf("x509 <-incert |-inkey | -incrl | -inlist> arg\n"
|
|
|
|
|
"Usage:\n"
|
2019-08-26 17:03:04 +08:00
|
|
|
" -incert | input certificate file [url]\n"
|
2019-08-07 19:24:13 +08:00
|
|
|
" -inkey | input private key file\n"
|
|
|
|
|
" -incrl | input certificate revocation list\n"
|
|
|
|
|
" -inlist | input certificate list file,format = pem\n"
|
|
|
|
|
" -incheck | input certificate file and intpu key file\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static X509* base_load_pkcs12(BIO *in, EVP_PKEY **pkey, X509 **x, STACK_OF(X509) **ca)
|
|
|
|
|
{
|
|
|
|
|
PKCS12 *p12;
|
|
|
|
|
const char *pass = "";
|
|
|
|
|
|
|
|
|
|
X509 *_x = NULL;
|
|
|
|
|
EVP_PKEY *_pkey;
|
|
|
|
|
STACK_OF(X509) *_ca = NULL;
|
|
|
|
|
|
|
|
|
|
OpenSSL_add_all_algorithms();
|
|
|
|
|
ERR_load_crypto_strings();
|
|
|
|
|
|
|
|
|
|
p12 = d2i_PKCS12_bio(in, NULL);
|
|
|
|
|
if (p12 == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
if (!PKCS12_parse(p12, pass, &_pkey, &_x, &_ca)) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (x)
|
|
|
|
|
*x = _x;
|
|
|
|
|
if (pkey)
|
|
|
|
|
*pkey = _pkey;
|
|
|
|
|
if (ca)
|
|
|
|
|
*ca = _ca;
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
if (p12)
|
|
|
|
|
PKCS12_free(p12);
|
|
|
|
|
return _x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cert_base_load_stack_info(BIO * in_bio, STACK_OF(X509) **stack_ca)
|
|
|
|
|
{
|
|
|
|
|
int x509_cnt = 0;
|
|
|
|
|
X509_INFO *x509_info;
|
|
|
|
|
STACK_OF(X509) *stack_x509 = NULL;
|
|
|
|
|
STACK_OF(X509_INFO) *stack_x509_info = NULL;
|
|
|
|
|
|
|
|
|
|
if ((stack_x509 = sk_X509_new_null()) == NULL)
|
|
|
|
|
{
|
|
|
|
|
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stack_x509_info = PEM_X509_INFO_read_bio(in_bio, NULL, NULL, NULL);
|
|
|
|
|
if (stack_x509_info == NULL)
|
|
|
|
|
{
|
|
|
|
|
X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (sk_X509_INFO_num(stack_x509_info)) {
|
|
|
|
|
x509_info = sk_X509_INFO_shift(stack_x509_info);
|
|
|
|
|
if (x509_info->x509 != NULL) {
|
|
|
|
|
sk_X509_push(stack_x509, x509_info->x509);
|
|
|
|
|
x509_info->x509 = NULL;
|
|
|
|
|
x509_cnt++;
|
|
|
|
|
}
|
|
|
|
|
X509_INFO_free(x509_info);
|
|
|
|
|
}
|
|
|
|
|
if (x509_cnt >= 1)
|
|
|
|
|
*stack_ca = stack_x509;
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
if (stack_x509_info != NULL)
|
|
|
|
|
sk_X509_INFO_free(stack_x509_info);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static X509 *
|
|
|
|
|
cert_base_load_x509 (BIO * in_bio, STACK_OF(X509) **stack_ca, int iFormat)
|
|
|
|
|
{
|
|
|
|
|
X509 *x = NULL;
|
|
|
|
|
|
|
|
|
|
switch (iFormat)
|
|
|
|
|
{
|
|
|
|
|
case LOCAL_USER_DER:
|
|
|
|
|
x = d2i_X509_bio (in_bio, NULL);
|
|
|
|
|
break;
|
|
|
|
|
case LOCAL_USER_PEN:
|
|
|
|
|
x = PEM_read_bio_X509 (in_bio, NULL, NULL, NULL);
|
|
|
|
|
cert_base_load_stack_info(in_bio, stack_ca);
|
|
|
|
|
break;
|
|
|
|
|
case LOCAL_USER_P12:
|
|
|
|
|
x = base_load_pkcs12(in_bio, NULL, &x, stack_ca);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static X509 *
|
|
|
|
|
cert_load_x509(char *file, int *informat, STACK_OF(X509) **stack_ca)
|
|
|
|
|
{
|
|
|
|
|
BIO *in = NULL;
|
|
|
|
|
X509 *x509 = NULL;
|
|
|
|
|
|
|
|
|
|
if(!file){
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((in = BIO_new(BIO_s_file())) == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
if (BIO_read_filename(in, file) <= 0) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**try pem */
|
|
|
|
|
if ((x509 = cert_base_load_x509(in, stack_ca, LOCAL_USER_PEN)) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_PEN;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
(void)BIO_reset (in);
|
|
|
|
|
if ((x509 = cert_base_load_x509(in, stack_ca, LOCAL_USER_P12)) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_P12;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
(void)BIO_reset (in);
|
|
|
|
|
if ((x509 = cert_base_load_x509(in, stack_ca, LOCAL_USER_DER)) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_DER;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
end:
|
|
|
|
|
BIO_free (in);
|
|
|
|
|
in = NULL;
|
|
|
|
|
finish:
|
|
|
|
|
return x509;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EVP_PKEY * cert_base_key_x509 (BIO * bio, int iFormat, char *strPwd)
|
|
|
|
|
{
|
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
|
|
|
|
|
switch (iFormat){
|
|
|
|
|
case LOCAL_USER_PEN:
|
|
|
|
|
pkey = PEM_read_bio_PrivateKey (bio, NULL, NULL, strPwd);
|
|
|
|
|
break;
|
|
|
|
|
case LOCAL_USER_P12:
|
|
|
|
|
base_load_pkcs12(bio, &pkey, NULL, NULL);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pkey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EVP_PKEY * cert_load_key(char *keyfile, int *informat)
|
|
|
|
|
{
|
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
BIO *in = NULL;
|
|
|
|
|
|
|
|
|
|
if(!keyfile){
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
if ((in = BIO_new(BIO_s_file())) == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
if (BIO_read_filename(in, keyfile) <= 0) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((pkey = cert_base_key_x509 (in, LOCAL_USER_PEN, "")) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_PEN;
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
(void)BIO_reset (in);
|
|
|
|
|
if ((pkey = cert_base_key_x509 (in, LOCAL_USER_P12, "")) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_P12;
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
finish:
|
|
|
|
|
if (in != NULL)
|
|
|
|
|
BIO_free (in);
|
|
|
|
|
return pkey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int x509_get_ValidDate(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
BIO *STDout = NULL;
|
|
|
|
|
|
|
|
|
|
STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
|
|
|
|
|
|
|
|
|
|
printf("CA notBefore : ");
|
|
|
|
|
ASN1_TIME_print(STDout, X509_get_notBefore(x509));
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("CA notAfter : ");
|
|
|
|
|
ASN1_TIME_print(STDout, X509_get_notAfter(x509));
|
|
|
|
|
printf("\n");
|
|
|
|
|
BIO_free_all(STDout);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
static char*
|
|
|
|
|
x509_get_alt_name(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
int i, size = 0, gtype = 0;
|
|
|
|
|
char *gnname = NULL;
|
|
|
|
|
|
|
|
|
|
GENERAL_NAMES* subjectAltNames = (GENERAL_NAMES*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
|
|
|
|
|
int cnt = sk_GENERAL_NAME_num(subjectAltNames);
|
|
|
|
|
|
|
|
|
|
if (cnt < 0)
|
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
|
|
gnname = (char *)malloc(2048);
|
|
|
|
|
if (!gnname)
|
|
|
|
|
goto finish;
|
|
|
|
|
memset(gnname, 0, 2048);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cnt; i++)
|
|
|
|
|
{
|
|
|
|
|
GENERAL_NAME* generalName = sk_GENERAL_NAME_value(subjectAltNames, i);
|
|
|
|
|
ASN1_STRING *uri = GENERAL_NAME_get0_value(generalName, >ype);
|
|
|
|
|
if (gtype == GEN_DNS)
|
|
|
|
|
{
|
|
|
|
|
size += snprintf(gnname + size, 2048, "%s, ", ASN1_STRING_data(uri));
|
|
|
|
|
if (size < 0)
|
|
|
|
|
continue;
|
|
|
|
|
if (size >= 2048)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
return gnname;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void x509_get_name(X509_NAME *name, int obase)
|
|
|
|
|
{
|
|
|
|
|
BIO *out = NULL;
|
|
|
|
|
|
|
|
|
|
out = BIO_new(BIO_s_file());
|
|
|
|
|
if (out == NULL) {
|
|
|
|
|
ERR_print_errors(bio_err);
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
BIO_set_fp(out, stdout, BIO_NOCLOSE);
|
|
|
|
|
X509_NAME_print(out, name, obase);
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
if (out != NULL)
|
|
|
|
|
BIO_free_all(out);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *x509_get_cn(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
char *CName = NULL;
|
|
|
|
|
int iLen = 0, CNlen = 256;
|
|
|
|
|
X509_NAME *pSubName = NULL;
|
|
|
|
|
|
|
|
|
|
pSubName = X509_get_subject_name(x509);
|
|
|
|
|
if (!pSubName){
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
CName = kmalloc(CNlen, MPF_CLR, -1);
|
|
|
|
|
if (!CName){
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
iLen = X509_NAME_get_text_by_NID(pSubName, NID_commonName, CName, CNlen-1);
|
|
|
|
|
if (iLen > 0){
|
|
|
|
|
return CName;
|
|
|
|
|
}
|
|
|
|
|
finish:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *x509_get_SubjectName(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
int iLen = 0;
|
|
|
|
|
char *csSubName = NULL;
|
|
|
|
|
char csBuf[256] = {0};
|
|
|
|
|
X509_NAME *pSubName = NULL;
|
|
|
|
|
|
|
|
|
|
csSubName = (char *)malloc(1024);
|
|
|
|
|
if (!csSubName)
|
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
|
|
pSubName = X509_get_subject_name(x509);
|
|
|
|
|
if (!pSubName){
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
memset(csBuf, 0, 256);
|
|
|
|
|
memset(csSubName, 0, 1024);
|
|
|
|
|
iLen = X509_NAME_get_text_by_NID(pSubName, NID_countryName, csBuf, 255);
|
|
|
|
|
if (iLen > 0){
|
|
|
|
|
strcat(csSubName, "C=");
|
|
|
|
|
strcat(csSubName, csBuf);
|
|
|
|
|
strcat(csSubName, ", ");
|
|
|
|
|
}
|
|
|
|
|
memset(csBuf, 0, 256);
|
|
|
|
|
iLen = X509_NAME_get_text_by_NID(pSubName, NID_organizationName, csBuf, 255);
|
|
|
|
|
if (iLen > 0){
|
|
|
|
|
strcat(csSubName, "O=");
|
|
|
|
|
strcat(csSubName, csBuf);
|
|
|
|
|
strcat(csSubName, ", ");
|
|
|
|
|
}
|
|
|
|
|
memset(csBuf, 0, 256);
|
|
|
|
|
iLen = X509_NAME_get_text_by_NID(pSubName, NID_organizationalUnitName, csBuf, 255);
|
|
|
|
|
if (iLen > 0) {
|
|
|
|
|
strcat(csSubName, "OU=");
|
|
|
|
|
strcat(csSubName, csBuf);
|
|
|
|
|
strcat(csSubName, ", ");
|
|
|
|
|
}
|
|
|
|
|
memset(csBuf, 0, 256);
|
|
|
|
|
iLen = X509_NAME_get_text_by_NID(pSubName, NID_commonName, csBuf, 255);
|
|
|
|
|
if (iLen > 0){
|
|
|
|
|
strcat(csSubName, "CN=");
|
|
|
|
|
strcat(csSubName, csBuf);
|
|
|
|
|
}
|
|
|
|
|
finish:
|
|
|
|
|
return csSubName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* x509_get_ExtBasicConstraints(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
int crit = 0;
|
|
|
|
|
char value[512] = {0};
|
|
|
|
|
BASIC_CONSTRAINTS *bcons = NULL;
|
|
|
|
|
|
|
|
|
|
if (!x509)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
bcons = (BASIC_CONSTRAINTS*)X509_get_ext_d2i(x509, NID_basic_constraints, &crit, NULL);
|
|
|
|
|
if (!bcons)
|
|
|
|
|
return NULL;
|
|
|
|
|
if (!bcons->ca)
|
|
|
|
|
{
|
|
|
|
|
strcat(value, "Subject Type=End Entity; ");
|
|
|
|
|
strcat(value, "Path Length Constraint=None");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char temp[128] = {0};
|
|
|
|
|
if (bcons->pathlen != NULL)
|
|
|
|
|
snprintf(temp, 128, "Path Length Constraint=%d", bcons->pathlen->type);
|
|
|
|
|
else
|
|
|
|
|
snprintf(temp, 128, "Path Length Constraint=None");
|
|
|
|
|
strcat(value, "Subject Type=CA; ");
|
|
|
|
|
strcat(value, temp);
|
|
|
|
|
}
|
|
|
|
|
BASIC_CONSTRAINTS_free(bcons);
|
|
|
|
|
|
|
|
|
|
char *base_cons = NULL;
|
|
|
|
|
int base_cons_len = strlen(value) + 1;
|
|
|
|
|
|
|
|
|
|
base_cons = (char *)malloc(base_cons_len);
|
|
|
|
|
if (!base_cons)
|
|
|
|
|
return NULL;
|
|
|
|
|
strncpy(base_cons, value, base_cons_len);
|
|
|
|
|
return base_cons;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char*
|
|
|
|
|
x509_get_fingerprint(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
char *rkey = NULL;
|
|
|
|
|
unsigned int len = 0, i = 0;
|
|
|
|
|
char hex[EVP_MAX_MD_SIZE] = {0};
|
|
|
|
|
unsigned char fdig[EVP_MAX_MD_SIZE] = {0};
|
|
|
|
|
|
|
|
|
|
rkey = (char *)malloc(512);
|
|
|
|
|
if (!rkey)
|
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
|
|
X509_digest(x509, EVP_sha1(), fdig, &len);
|
|
|
|
|
for (i = 0; i < len ; ++i){
|
|
|
|
|
sprintf(hex + i * sizeof(unsigned char) * 2, "%02x", fdig[i]);
|
|
|
|
|
}
|
|
|
|
|
snprintf(rkey, 511, "%s", hex);
|
|
|
|
|
finish:
|
|
|
|
|
return rkey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *x509_get_sn(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
ASN1_INTEGER *asn1_i = NULL;
|
|
|
|
|
BIGNUM *bignum = NULL;
|
|
|
|
|
char *serial = NULL;
|
|
|
|
|
|
|
|
|
|
asn1_i = X509_get_serialNumber(x509);
|
|
|
|
|
bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
|
|
|
|
|
if (bignum == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
serial = BN_bn2hex(bignum);
|
|
|
|
|
if (serial == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
BN_free(bignum);
|
|
|
|
|
finish:
|
|
|
|
|
return serial;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *x509_get_version(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
unsigned int v = 0;
|
|
|
|
|
|
|
|
|
|
v = X509_get_version(x509);
|
|
|
|
|
switch(v){
|
|
|
|
|
case 0:
|
|
|
|
|
return "V1";
|
|
|
|
|
case 1:
|
|
|
|
|
return "V2";
|
|
|
|
|
case 2:
|
|
|
|
|
return "V3";
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int X509_check_valid_date(X509 *x509)
|
|
|
|
|
{
|
|
|
|
|
int day, sec;
|
|
|
|
|
|
|
|
|
|
/*Certificate is issued earlier than the current time*/
|
|
|
|
|
if (ASN1_TIME_diff(&day, &sec, X509_get_notBefore(x509), NULL) == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
if (day <= 0 && sec <= 0)
|
|
|
|
|
return -1;
|
|
|
|
|
/*Certificate expiration is less than the current time*/
|
|
|
|
|
if (ASN1_TIME_diff(&day, &sec, NULL, X509_get_notAfter(x509)) == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
if (day <= 0 && sec <= 0)
|
|
|
|
|
return -1;
|
|
|
|
|
/*Certificate expires less than the date of issue*/
|
|
|
|
|
if (ASN1_TIME_diff(&day, &sec, X509_get_notBefore(x509), X509_get_notAfter(x509)) == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
if (day <= 0 && sec <= 0)
|
|
|
|
|
return -1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-26 17:03:04 +08:00
|
|
|
int x509_parse_cert(char *certfile, char *input_url)
|
2019-08-07 19:24:13 +08:00
|
|
|
{
|
|
|
|
|
int xret = -1;
|
|
|
|
|
int informat = 0;
|
|
|
|
|
X509 *x509 = NULL;
|
|
|
|
|
STACK_OF(X509) *stack_ca = NULL;
|
|
|
|
|
|
|
|
|
|
x509 = cert_load_x509(certfile, &informat, &stack_ca);
|
|
|
|
|
if (!x509){
|
|
|
|
|
printf("unable to load certificate\n");
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
printf("Successful certificate conversion\n");
|
|
|
|
|
printf("Ca Format : %s\n", val_to_str(informat, format_vals));
|
|
|
|
|
|
|
|
|
|
char *constraints = NULL;
|
|
|
|
|
constraints = x509_get_ExtBasicConstraints(x509);
|
|
|
|
|
printf("Ca Constraints : %s\n", (constraints != NULL)?constraints: "NULL");
|
|
|
|
|
/*end-entity certificate san**/
|
2019-08-26 17:03:04 +08:00
|
|
|
if ((constraints != NULL && STRSTR(constraints, "End Entity")) ||
|
|
|
|
|
constraints == NULL)
|
2019-08-07 19:24:13 +08:00
|
|
|
{
|
|
|
|
|
char *cn = x509_get_cn(x509);
|
2019-08-26 17:03:04 +08:00
|
|
|
if (!cn || X509_check_host(x509, cn, strlen(cn), 0, NULL) != 1 ||
|
|
|
|
|
input_url == NULL || X509_check_host(x509, input_url, strlen(input_url), 0, NULL) != 1)
|
2019-08-07 19:24:13 +08:00
|
|
|
{
|
2019-08-26 17:03:04 +08:00
|
|
|
printf("Match host name: %s\n", "Matching failure");
|
2019-08-07 19:24:13 +08:00
|
|
|
}
|
|
|
|
|
kfree(cn);
|
|
|
|
|
}
|
2019-08-26 17:03:04 +08:00
|
|
|
printf("Match host name: %s\n", "Successful matching");
|
|
|
|
|
if (constraints) kfree(constraints);
|
2019-08-07 19:24:13 +08:00
|
|
|
if (informat == LOCAL_USER_P12 || informat == LOCAL_USER_PEN){
|
|
|
|
|
if (stack_ca){
|
|
|
|
|
printf("Chain Length : %d\n", sk_X509_num(stack_ca) + 1);
|
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
printf("Chain Length : %d\n", 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("Ca Version : %s\n", (x509_get_version(x509) != NULL)?x509_get_version(x509) : "NULL");
|
|
|
|
|
printf("Ca Serial : %s\n", (x509_get_sn(x509) != NULL)?x509_get_sn(x509) : "NULL");
|
|
|
|
|
printf("Ca Issuer : ");
|
|
|
|
|
x509_get_name(X509_get_issuer_name(x509), 16);
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("Ca SubjectName : ");
|
|
|
|
|
x509_get_name(X509_get_subject_name(x509), 16);
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("Ca Fingerprint : %s\n", x509_get_fingerprint(x509));
|
|
|
|
|
x509_get_ValidDate(x509);
|
|
|
|
|
if (X509_check_valid_date(x509) < 0)
|
|
|
|
|
{
|
|
|
|
|
printf("CA state : ERR_CERT_DATE_INVALID\n");
|
|
|
|
|
}
|
|
|
|
|
xret = 0;
|
|
|
|
|
finish:
|
|
|
|
|
return xret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int x509_parse_key(char *keyfile)
|
|
|
|
|
{
|
|
|
|
|
int xret = -1;
|
|
|
|
|
int informat = 0;
|
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
|
|
|
|
|
pkey = cert_load_key(keyfile, &informat);
|
|
|
|
|
if (!pkey){
|
|
|
|
|
printf("unable to load private key\n");
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
printf("Successful private key conversion\n");
|
|
|
|
|
printf("Key Format : %s\n", val_to_str(informat, format_vals));
|
|
|
|
|
xret = 0;
|
|
|
|
|
finish:
|
|
|
|
|
return xret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static X509_CRL *
|
|
|
|
|
x509_load_crl(char *crlfile, int *informat)
|
|
|
|
|
{
|
|
|
|
|
BIO *in = NULL;
|
|
|
|
|
X509_CRL *x = NULL;
|
|
|
|
|
|
|
|
|
|
in = BIO_new(BIO_s_file());
|
|
|
|
|
if (in == NULL) {
|
|
|
|
|
ERR_print_errors(bio_err);
|
|
|
|
|
goto free;
|
|
|
|
|
}
|
|
|
|
|
if (BIO_read_filename(in, crlfile) <= 0) {
|
|
|
|
|
perror(crlfile);
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL)) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_PEN;
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((x = d2i_X509_CRL_bio(in, NULL)) != NULL){
|
|
|
|
|
*informat = LOCAL_USER_DER;
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free:
|
|
|
|
|
BIO_free(in);
|
|
|
|
|
finish:
|
|
|
|
|
return x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *x509_get_crlNumber(X509_CRL *crl)
|
|
|
|
|
{
|
|
|
|
|
ASN1_INTEGER *crlnum;
|
|
|
|
|
BIGNUM *bignum = NULL;
|
|
|
|
|
char *crl_number = NULL;
|
|
|
|
|
|
|
|
|
|
crlnum = X509_CRL_get_ext_d2i(crl, NID_crl_number, NULL, NULL);
|
|
|
|
|
bignum = ASN1_INTEGER_to_BN(crlnum, NULL);
|
|
|
|
|
if (bignum == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
crl_number = BN_bn2dec(bignum);
|
|
|
|
|
if (crl_number == NULL) {
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
BN_free(bignum);
|
|
|
|
|
finish:
|
|
|
|
|
return crl_number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int x509_parse_crl(char *crlfile)
|
|
|
|
|
{
|
|
|
|
|
X509_CRL *crl = NULL;
|
|
|
|
|
int informat = 0;
|
|
|
|
|
int xret = -1;
|
|
|
|
|
|
|
|
|
|
crl = x509_load_crl(crlfile, &informat);
|
|
|
|
|
if (!crl){
|
|
|
|
|
printf("unable to load Certificate Revocation List\n");
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("Successful certificate revocation list conversion\n");
|
|
|
|
|
long l = 0;
|
|
|
|
|
l = X509_CRL_get_version(crl);
|
|
|
|
|
printf("CRL Format : %s\n", val_to_str(informat, format_vals));
|
|
|
|
|
printf("CRL Version : %lu\n", l + 1);
|
|
|
|
|
printf("CRL Issuer : ");
|
|
|
|
|
x509_get_name(X509_CRL_get_issuer(crl), 16);
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("CRL Number : %s\n", x509_get_crlNumber(crl));
|
|
|
|
|
|
|
|
|
|
finish:
|
|
|
|
|
return xret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
x509_parse_cert_list(char *certlist)
|
|
|
|
|
{
|
|
|
|
|
int xret = 0;
|
|
|
|
|
BIO *in = NULL;
|
|
|
|
|
X509* x = NULL;
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
in = BIO_new(BIO_s_file());
|
|
|
|
|
if (in == NULL) {
|
|
|
|
|
ERR_print_errors(bio_err);
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
if (BIO_read_filename(in, certlist) <= 0) {
|
|
|
|
|
perror(certlist);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("Certificate List:\n");
|
|
|
|
|
for (;;) {
|
|
|
|
|
x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
|
|
|
|
|
if (x == NULL) {
|
|
|
|
|
if (count == 0)
|
|
|
|
|
printf("bad input format specified for input cert list\n");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("Cert list Issuer : ");
|
|
|
|
|
x509_get_name(X509_get_issuer_name(x), 16);
|
|
|
|
|
printf("\n");
|
|
|
|
|
count++;
|
|
|
|
|
X509_free(x);
|
|
|
|
|
x = NULL;
|
|
|
|
|
}
|
|
|
|
|
err:
|
|
|
|
|
if (x != NULL)
|
|
|
|
|
X509_free(x);
|
|
|
|
|
if (in != NULL)
|
|
|
|
|
BIO_free(in);
|
|
|
|
|
printf("Certificate List Number : %d\n", count);
|
|
|
|
|
finish:
|
|
|
|
|
return xret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
decoder_argv_parser(int argc, char **argv, char **infile, char **infile2)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
int iformat = -1;
|
|
|
|
|
|
|
|
|
|
for (i = 0; argv[i] != NULL; i++){
|
|
|
|
|
/** run version parser */
|
|
|
|
|
if (STRCMP (argv[i], "-inkey") == 0){
|
|
|
|
|
if (--argc < 1)
|
|
|
|
|
goto help;
|
|
|
|
|
*infile = argv[i+1];
|
|
|
|
|
iformat = INPUT_FILE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (STRCMP(argv[i], "-incert") == 0){
|
|
|
|
|
if (--argc < 1)
|
|
|
|
|
goto help;
|
|
|
|
|
*infile = argv[i+1];
|
2019-08-26 17:03:04 +08:00
|
|
|
*infile2 = argv[i+2];
|
2019-08-07 19:24:13 +08:00
|
|
|
iformat = INPUT_FILE_CERT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (STRCMP(argv[i], "-incrl") == 0){
|
|
|
|
|
if (--argc < 1)
|
|
|
|
|
goto help;
|
|
|
|
|
*infile = argv[i+1];
|
|
|
|
|
iformat = INPUT_FILE_CRL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (STRCMP(argv[i], "-inlist")== 0){
|
|
|
|
|
if (--argc < 1)
|
|
|
|
|
goto help;
|
2019-08-26 17:03:04 +08:00
|
|
|
*infile = argv[i+1];
|
2019-08-07 19:24:13 +08:00
|
|
|
iformat = INPUT_FILE_LIST;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (STRCMP(argv[i], "-incheck") == 0){
|
|
|
|
|
if (--argc < 1)
|
|
|
|
|
goto help;
|
|
|
|
|
*infile = argv[i+1];
|
|
|
|
|
*infile2 = argv[i+2];
|
|
|
|
|
iformat = INPUT_FILE_CHECK;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
goto finish;
|
|
|
|
|
help:
|
|
|
|
|
help();
|
|
|
|
|
finish:
|
|
|
|
|
return iformat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
x509_parse_check(char *cafile, char *keyfile)
|
|
|
|
|
{
|
|
|
|
|
int informat = 0;
|
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
|
|
|
|
|
pkey = cert_load_key(keyfile, &informat);
|
|
|
|
|
if (!pkey){
|
|
|
|
|
printf("unable to load private key\n");
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
X509 *x509 = NULL;
|
|
|
|
|
STACK_OF(X509) *stack_ca = NULL;
|
|
|
|
|
|
|
|
|
|
x509 = cert_load_x509(cafile, &informat, &stack_ca);
|
|
|
|
|
if (!x509){
|
|
|
|
|
printf("unable to load certificate\n");
|
|
|
|
|
goto finish;
|
|
|
|
|
}
|
|
|
|
|
if (!X509_check_private_key(x509, pkey)) {
|
|
|
|
|
printf("Matching failure\n");
|
|
|
|
|
}else{
|
|
|
|
|
printf("Successful matching\n");
|
|
|
|
|
}
|
|
|
|
|
finish:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int x509_check_format(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
int iformat = -1;
|
|
|
|
|
char *infile = NULL, *infile2 = NULL;
|
|
|
|
|
|
|
|
|
|
iformat = decoder_argv_parser(argc, argv, &infile, &infile2);
|
|
|
|
|
if (!infile && iformat < 0)
|
|
|
|
|
goto help;
|
|
|
|
|
|
|
|
|
|
switch(iformat){
|
|
|
|
|
case INPUT_FILE_KEY:
|
|
|
|
|
x509_parse_key(infile);
|
|
|
|
|
break;
|
|
|
|
|
case INPUT_FILE_CERT:
|
2019-08-26 17:03:04 +08:00
|
|
|
x509_parse_cert(infile, infile2);
|
2019-08-07 19:24:13 +08:00
|
|
|
break;
|
|
|
|
|
case INPUT_FILE_CRL:
|
|
|
|
|
x509_parse_crl(infile);
|
|
|
|
|
break;
|
|
|
|
|
case INPUT_FILE_LIST:
|
|
|
|
|
x509_parse_cert_list(infile);
|
|
|
|
|
break;
|
|
|
|
|
case INPUT_FILE_CHECK:
|
|
|
|
|
x509_parse_check(infile, infile2);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
goto help;
|
|
|
|
|
}
|
|
|
|
|
goto finish;
|
|
|
|
|
help:
|
|
|
|
|
help();
|
|
|
|
|
finish:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
x509_check_format(argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|