修改实体证书检测
This commit is contained in:
240
src/x509.c
240
src/x509.c
@@ -4,7 +4,7 @@
|
||||
> Mail:
|
||||
> Created Time: Fri 01 Jun 2018 02:00:56 AM PDT
|
||||
************************************************************************/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -43,6 +43,7 @@ enum x509_input_file{
|
||||
INPUT_FILE_CRL,
|
||||
INPUT_FILE_LIST,
|
||||
INPUT_FILE_CHECK,
|
||||
INPUT_FILE_HOST,
|
||||
INPUT_FILE_CHAIN,
|
||||
};
|
||||
|
||||
@@ -64,11 +65,12 @@ static void help()
|
||||
printf("Welcome to x509 %s\n", "1.1.1");
|
||||
printf("x509 <-incert |-inkey | -incrl | -inlist> arg\n"
|
||||
"Usage:\n"
|
||||
" -incert | input certificate file [url]\n"
|
||||
" -incert | input certificate file\n"
|
||||
" -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");
|
||||
" -incheck | input certificate file and intpu key file\n"
|
||||
" -inhost | input san file and intpu fqdn file\n");
|
||||
}
|
||||
|
||||
static X509* base_load_pkcs12(BIO *in, EVP_PKEY **pkey, X509 **x, STACK_OF(X509) **ca)
|
||||
@@ -267,7 +269,7 @@ int x509_get_ValidDate(X509 *x509)
|
||||
BIO_free_all(STDout);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
|
||||
static char*
|
||||
x509_get_alt_name(X509 *x509)
|
||||
{
|
||||
@@ -279,11 +281,13 @@ x509_get_alt_name(X509 *x509)
|
||||
|
||||
if (cnt < 0)
|
||||
goto finish;
|
||||
|
||||
int gnnamelen = cnt * 64;
|
||||
|
||||
gnname = (char *)malloc(2048);
|
||||
gnname = (char *)malloc(gnnamelen);
|
||||
if (!gnname)
|
||||
goto finish;
|
||||
memset(gnname, 0, 2048);
|
||||
memset(gnname, 0, gnnamelen);
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
@@ -291,18 +295,15 @@ x509_get_alt_name(X509 *x509)
|
||||
ASN1_STRING *uri = GENERAL_NAME_get0_value(generalName, >ype);
|
||||
if (gtype == GEN_DNS)
|
||||
{
|
||||
size += snprintf(gnname + size, 2048, "%s, ", ASN1_STRING_data(uri));
|
||||
size += snprintf(gnname + size, gnnamelen, "%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)
|
||||
{
|
||||
@@ -511,7 +512,7 @@ int X509_check_valid_date(X509 *x509)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x509_parse_cert(char *certfile, char *input_url)
|
||||
int x509_parse_cert(char *certfile, char *host)
|
||||
{
|
||||
int xret = -1;
|
||||
int informat = 0;
|
||||
@@ -525,24 +526,7 @@ int x509_parse_cert(char *certfile, char *input_url)
|
||||
}
|
||||
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**/
|
||||
if ((constraints != NULL && STRSTR(constraints, "End Entity")) ||
|
||||
constraints == NULL)
|
||||
{
|
||||
char *cn = x509_get_cn(x509);
|
||||
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)
|
||||
{
|
||||
printf("Match host name: %s\n", "Matching failure");
|
||||
}
|
||||
kfree(cn);
|
||||
}
|
||||
printf("Match host name: %s\n", "Successful matching");
|
||||
if (constraints) kfree(constraints);
|
||||
printf("Ca Constraints : %s\n", (x509_get_ExtBasicConstraints(x509) != NULL)?x509_get_ExtBasicConstraints(x509): "NULL");
|
||||
if (informat == LOCAL_USER_P12 || informat == LOCAL_USER_PEN){
|
||||
if (stack_ca){
|
||||
printf("Chain Length : %d\n", sk_X509_num(stack_ca) + 1);
|
||||
@@ -559,11 +543,21 @@ int x509_parse_cert(char *certfile, char *input_url)
|
||||
printf("Ca SubjectName : ");
|
||||
x509_get_name(X509_get_subject_name(x509), 16);
|
||||
printf("\n");
|
||||
char *alt_name = x509_get_alt_name(x509);
|
||||
printf("Ca AltName : %s\n", (alt_name != NULL)?alt_name:"NULL");
|
||||
free(alt_name);
|
||||
printf("Ca Fingerprint : %s\n", x509_get_fingerprint(x509));
|
||||
x509_get_ValidDate(x509);
|
||||
if (X509_check_valid_date(x509) < 0)
|
||||
printf("Ca valid date : %s\n", (X509_check_valid_date(x509) == 0)?"valid":"expire");
|
||||
|
||||
/* self testing***/
|
||||
if (host != NULL)
|
||||
{
|
||||
printf("CA state : ERR_CERT_DATE_INVALID\n");
|
||||
if (X509_check_host(x509, host, strlen(host), 0, NULL) == 1)
|
||||
printf("Match host name: %s\n", "Successful matching");
|
||||
else
|
||||
printf("Match host name: %s\n", "Matching failure");
|
||||
|
||||
}
|
||||
xret = 0;
|
||||
finish:
|
||||
@@ -683,7 +677,6 @@ x509_parse_cert_list(char *certlist)
|
||||
perror(certlist);
|
||||
goto err;
|
||||
}
|
||||
|
||||
printf("Certificate List:\n");
|
||||
for (;;) {
|
||||
x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
|
||||
@@ -755,6 +748,14 @@ decoder_argv_parser(int argc, char **argv, char **infile, char **infile2)
|
||||
iformat = INPUT_FILE_CHECK;
|
||||
break;
|
||||
}
|
||||
if (STRCMP(argv[i], "-inhost") == 0){
|
||||
if (--argc < 1)
|
||||
goto help;
|
||||
*infile = argv[i+1];
|
||||
*infile2 = argv[i+2];
|
||||
iformat = INPUT_FILE_HOST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto finish;
|
||||
help:
|
||||
@@ -792,6 +793,178 @@ finish:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static X509 *make_cert()
|
||||
{
|
||||
X509 *x509 = X509_new();
|
||||
if (x509 == NULL)
|
||||
goto out;
|
||||
if (!X509_set_version(x509, 3))
|
||||
goto out;
|
||||
return x509;
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *execute_read_file(const char *filename)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
long length = 0;
|
||||
char *content = NULL;
|
||||
size_t read_chars = 0;
|
||||
|
||||
file = fopen(filename, "rb");
|
||||
if (file == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
if (fseek(file, 0, SEEK_END) != 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
length = ftell(file);
|
||||
if (length < 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
if (fseek(file, 0, SEEK_SET) != 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate content buffer */
|
||||
content = (char*)malloc((size_t)length + sizeof(""));
|
||||
if (content == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* read the file into memory */
|
||||
read_chars = fread(content, sizeof(char), (size_t)length, file);
|
||||
if ((long)read_chars != length)
|
||||
{
|
||||
free(content);
|
||||
content = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
content[read_chars] = '\0';
|
||||
cleanup:
|
||||
if (file != NULL)
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
char *str_trim(const char *str)
|
||||
{
|
||||
unsigned int uLen = strlen(str);
|
||||
|
||||
if(0 == uLen){
|
||||
return '\0';
|
||||
}
|
||||
char *strRet = (char *)malloc(uLen + 1);
|
||||
memset(strRet, 0, uLen+1);
|
||||
unsigned int i = 0, j = 0;
|
||||
for(i=0; i<uLen+1; i++)
|
||||
{
|
||||
if(str[i] != ' ')
|
||||
{
|
||||
strRet[j++] = str[i];
|
||||
}
|
||||
}
|
||||
strRet[j] = '\0';
|
||||
return strRet;
|
||||
}
|
||||
|
||||
static int set_altname(X509 *crt, int type, const char *sanfile)
|
||||
{
|
||||
int ret = 0;
|
||||
GENERAL_NAMES *gens = NULL;
|
||||
GENERAL_NAME *gen = NULL;
|
||||
ASN1_IA5STRING *ia5 = NULL;
|
||||
|
||||
gens = sk_GENERAL_NAME_new_null();
|
||||
if (gens == NULL)
|
||||
goto out;
|
||||
|
||||
char *buff = execute_read_file(sanfile);
|
||||
if (buff == NULL){
|
||||
goto finish;
|
||||
}
|
||||
char *sanline=NULL, *host = NULL;
|
||||
char seps[] = ";";
|
||||
sanline = strtok(buff, seps);
|
||||
while (sanline)
|
||||
{
|
||||
asprintf(&host, "%s", sanline);
|
||||
gen = GENERAL_NAME_new();
|
||||
if (gen == NULL)
|
||||
goto out;
|
||||
ia5 = ASN1_IA5STRING_new();
|
||||
if (ia5 == NULL)
|
||||
goto out;
|
||||
if (!ASN1_STRING_set(ia5, host, -1))
|
||||
goto out;
|
||||
switch (type) {
|
||||
case GEN_EMAIL:
|
||||
case GEN_DNS:
|
||||
GENERAL_NAME_set0_value(gen, type, ia5);
|
||||
ia5 = NULL;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
sk_GENERAL_NAME_push(gens, gen);
|
||||
gen = NULL;
|
||||
free(host);
|
||||
sanline = strtok(NULL, seps);
|
||||
if (sanline == NULL || strlen(sanline) == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
|
||||
goto out;
|
||||
ret = 1;
|
||||
out:
|
||||
ASN1_IA5STRING_free(ia5);
|
||||
GENERAL_NAME_free(gen);
|
||||
finish:
|
||||
GENERAL_NAMES_free(gens);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int x509_check_host(const char *sanfile, const char *urlfile)
|
||||
{
|
||||
#define LINE_SIZE (1024)
|
||||
|
||||
FILE *fp = NULL;
|
||||
char line[LINE_SIZE];
|
||||
|
||||
if (sanfile == NULL || urlfile == NULL){
|
||||
goto help;
|
||||
}
|
||||
X509 *x509 = make_cert();
|
||||
if (x509 == NULL)
|
||||
return -1;
|
||||
set_altname(x509, GEN_DNS, sanfile);
|
||||
fp = fopen(urlfile, "r");
|
||||
assert(fp != NULL);
|
||||
while(fgets(line, LINE_SIZE - 1, fp))
|
||||
{
|
||||
if (line[0] == '\0' || X509_check_host(x509, line, strlen(line) -1, 0, NULL) != 1)
|
||||
{
|
||||
printf("Fqdn :%.*s Status: %s\n", (int)(strlen(line)-1), line, "Matching failure");
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
goto finish;
|
||||
help:
|
||||
help();
|
||||
finish:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x509_check_format(int argc, char **argv)
|
||||
{
|
||||
int iformat = -1;
|
||||
@@ -817,6 +990,9 @@ int x509_check_format(int argc, char **argv)
|
||||
case INPUT_FILE_CHECK:
|
||||
x509_parse_check(infile, infile2);
|
||||
break;
|
||||
case INPUT_FILE_HOST:
|
||||
x509_check_host(infile, infile2);
|
||||
break;
|
||||
default:
|
||||
goto help;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user