Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
comp30023-2018-project-2
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Sebastian Baker
comp30023-2018-project-2
Commits
b09a93f7
Commit
b09a93f7
authored
May 24, 2018
by
Ubuntu
Browse files
Options
Downloads
Patches
Plain Diff
done
parent
d834930f
No related branches found
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
certexample.c
+0
-91
0 additions, 91 deletions
certexample.c
fixpath.sh
+0
-1
0 additions, 1 deletion
fixpath.sh
makefile
+11
-8
11 additions, 8 deletions
makefile
src/main.c
+370
-7
370 additions, 7 deletions
src/main.c
with
381 additions
and
107 deletions
certexample.c
deleted
100644 → 0
+
0
−
91
View file @
d834930f
/**
Example certifcate code
gcc -o certexample certexample.c -lssl -lcrypto
gcc certexample.c -I /usr/local/opt/openssl/include -L /usr/local/opt/openssl/lib -o certexample
*/
#include
<openssl/x509.h>
#include
<openssl/x509v3.h>
#include
<openssl/bio.h>
#include
<openssl/pem.h>
#include
<openssl/err.h>
#include
<stdio.h>
#include
<string.h>
int
main
()
{
const
char
test_cert_example
[]
=
"./cert-file2.pem"
;
BIO
*
certificate_bio
=
NULL
;
X509
*
cert
=
NULL
;
X509_NAME
*
cert_issuer
=
NULL
;
X509_CINF
*
cert_inf
=
NULL
;
STACK_OF
(
X509_EXTENSION
)
*
ext_list
;
//initialise openSSL
OpenSSL_add_all_algorithms
();
ERR_load_BIO_strings
();
ERR_load_crypto_strings
();
//create BIO object to read certificate
certificate_bio
=
BIO_new
(
BIO_s_file
());
//Read certificate into BIO
if
(
!
(
BIO_read_filename
(
certificate_bio
,
test_cert_example
)))
{
fprintf
(
stderr
,
"Error in reading cert BIO filename"
);
exit
(
EXIT_FAILURE
);
}
if
(
!
(
cert
=
PEM_read_bio_X509
(
certificate_bio
,
NULL
,
0
,
NULL
)))
{
fprintf
(
stderr
,
"Error in loading certificate"
);
exit
(
EXIT_FAILURE
);
}
//cert contains the x509 certificate and can be used to analyse the certificate
//*********************
// Example code of accessing certificate values
//*********************
cert_issuer
=
X509_get_issuer_name
(
cert
);
char
issuer_cn
[
256
]
=
"Issuer CN NOT FOUND"
;
X509_NAME_get_text_by_NID
(
cert_issuer
,
NID_commonName
,
issuer_cn
,
256
);
printf
(
"Issuer CommonName:%s
\n
"
,
issuer_cn
);
//List of extensions available at https://www.openssl.org/docs/man1.1.0/crypto/X509_REVOKED_get0_extensions.html
//Need to check extension exists and is not null
X509_EXTENSION
*
ex
=
X509_get_ext
(
cert
,
X509_get_ext_by_NID
(
cert
,
NID_subject_key_identifier
,
-
1
));
ASN1_OBJECT
*
obj
=
X509_EXTENSION_get_object
(
ex
);
char
buff
[
1024
];
OBJ_obj2txt
(
buff
,
1024
,
obj
,
0
);
printf
(
"Extension:%s
\n
"
,
buff
);
BUF_MEM
*
bptr
=
NULL
;
char
*
buf
=
NULL
;
BIO
*
bio
=
BIO_new
(
BIO_s_mem
());
if
(
!
X509V3_EXT_print
(
bio
,
ex
,
0
,
0
))
{
fprintf
(
stderr
,
"Error in reading extensions"
);
}
BIO_flush
(
bio
);
BIO_get_mem_ptr
(
bio
,
&
bptr
);
//bptr->data is not NULL terminated - add null character
buf
=
(
char
*
)
malloc
((
bptr
->
length
+
1
)
*
sizeof
(
char
));
memcpy
(
buf
,
bptr
->
data
,
bptr
->
length
);
buf
[
bptr
->
length
]
=
'\0'
;
//Can print or parse value
printf
(
"%s
\n
"
,
buf
);
//*********************
// End of Example code
//*********************
X509_free
(
cert
);
BIO_free_all
(
certificate_bio
);
BIO_free_all
(
bio
);
free
(
buf
);
exit
(
0
);
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
fixpath.sh
deleted
100644 → 0
+
0
−
1
View file @
d834930f
export
PATH
=
"/usr/local/opt/openssl/bin:"
$PATH
\ No newline at end of file
This diff is collapsed.
Click to expand it.
makefile
+
11
−
8
View file @
b09a93f7
...
...
@@ -6,22 +6,25 @@
#
#***************************************************************************
CC
=
gcc
FLAGS
=
-Wall
-lssl
-lcrypto
MAC_FLAGS
=
-Wall
-I
/usr/local/opt/openssl/include
-L
/usr/local/opt/openssl/lib
OUT
=
certcheck
TESTS
=
sample_certs
SRC
=
src/main.c
EXAMPLE_SRC
=
./certexample.c
CSVOUT
=
output.csv
compile
:
$(
CC
)
$(
SRC
)
$(
FLAGS
)
-o
$(
OUT
);
mac
:
$(
CC
)
$(
SRC
)
$(
MAC_FLAGS
)
-o
$(
OUT
);
clean
:
rm
$(
OUT
);
rm
$(
CSVOUT
);
clean_tests
:
rm
$(
TESTS
)
/
$(
OUT
);
rm
$(
TESTS
)
/
$(
CSVOUT
);
exa
mple
:
$(
CC
)
$(
EXAMPLE_
SRC
)
$(
MAC_
FLAGS
)
-o
certexample
;
co
mp
i
le
_tests
:
$(
CC
)
$(
SRC
)
$(
FLAGS
)
-o
$(
TESTS
)
/
$(
OUT
)
;
clean
:
rm
-f
src/
*
.o
;
rm
$(
OUT
)
;
test
:
cd
sample_certs/
;
./testscript.sh
;
cd
..
;
This diff is collapsed.
Click to expand it.
src/main.c
+
370
−
7
View file @
b09a93f7
/***************************************************************************
*
* File : main.c
* Student Id : 757931
* Name : Sebastian Baker
*
**************************************************************************/
#include
<openssl/x509.h>
#include
<openssl/x509v3.h>
...
...
@@ -5,14 +12,370 @@
#include
<openssl/pem.h>
#include
<openssl/err.h>
#include
<stdio.h>
#include
<assert.h>
#include
<string.h>
#include
<time.h>
#include
<math.h>
#include
<string.h>
#define EXAMPLE_USAGE "USAGE: ./certcheck test_file.csv\n"
#define NUM_ARGS 2
#define FILENAME_ARG 1
#define OUT_FILENAME "output.csv"
#define REWRITE "w"
#define READONLY "r"
#define DELIMITER ','
#define NEWLINE '\n'
#define NULL_C '\0'
#define BITS_TO_BYTES(bits) bits/8
#define START_STR_SIZE 2
#define DEFAULT_STRLEN 2048
#define VALID 1
#define ASN1_TIME_BEFORE -1
#define ASN1_TIME_AFTER 1
#define MIN_RSA_BYTES BITS_TO_BYTES(2048)
#define EXT_STARTPOS -1
#define NOT_CA_STR "CA:FALSE"
#define IS_CA_STR "CA:TRUE"
#define TLS_STR "TLS Web Server Authentication"
#define NO_CN "CN NOT FOUND"
#define SAN_DELIM ", "
#define SAN_ENTRY ":"
#define WILDCARD '*'
// Checks the validity of the positioning of the wildcard
// Wildcards must be located at the beginning of the name, followed by a '.'
#define WILDCARD_VALID(name, i) ((name[0] == WILDCARD) \
&& (i == 0) \
&& (name[1] == '.'))
// Print the name of an X509 extension in plaintext
void
print_ext_name
(
X509_EXTENSION
*
ex
)
{
int
len
=
DEFAULT_STRLEN
;
ASN1_OBJECT
*
obj
=
X509_EXTENSION_get_object
(
ex
);
char
buff
[
len
];
OBJ_obj2txt
(
buff
,
len
,
obj
,
0
);
//printf("Extension:%s\n", buff);
}
// Get the value from an X509 extension in plaintext
char
*
get_ext_value
(
X509
*
cert
,
int
nid
)
{
// Get extension object
int
loc
=
X509_get_ext_by_NID
(
cert
,
nid
,
EXT_STARTPOS
);
X509_EXTENSION
*
ex
=
X509_get_ext
(
cert
,
loc
);
if
(
!
ex
)
{
return
NULL
;}
//print_ext_name(ex);
// Wrap the extension in a BIO
BUF_MEM
*
bptr
=
NULL
;
BIO
*
bio
=
BIO_new
(
BIO_s_mem
());
assert
(
X509V3_EXT_print
(
bio
,
ex
,
0
,
0
));
BIO_flush
(
bio
);
BIO_get_mem_ptr
(
bio
,
&
bptr
);
// Load extension into a string
char
*
str
=
(
char
*
)
malloc
((
bptr
->
length
+
1
)
*
sizeof
(
char
));
memcpy
(
str
,
bptr
->
data
,
bptr
->
length
);
str
[
bptr
->
length
]
=
NULL_C
;
BIO_free_all
(
bio
);
//printf("%s\n", str);
return
str
;
}
// My version of X509_cmp_current_time
int
my_X509_cmp_current_time
(
ASN1_TIME
*
t
)
{
int
daydiff
=
0
;
int
secdiff
=
0
;
assert
(
ASN1_TIME_diff
(
&
daydiff
,
&
secdiff
,
t
,
NULL
));
assert
(
daydiff
/
abs
(
daydiff
)
==
secdiff
/
abs
(
secdiff
));
if
(
secdiff
<
0
||
daydiff
<
0
)
{
return
ASN1_TIME_BEFORE
;
}
else
{
return
ASN1_TIME_AFTER
;
}
}
// Verify the not before and not after dates of the certificate
int
validate_date
(
X509
*
cert
)
{
ASN1_TIME
*
not_before
=
X509_get_notBefore
(
cert
);
ASN1_TIME
*
not_after
=
X509_get_notAfter
(
cert
);
if
(
(
my_X509_cmp_current_time
(
not_after
)
==
ASN1_TIME_BEFORE
)
&&
(
my_X509_cmp_current_time
(
not_before
)
==
ASN1_TIME_AFTER
)
)
{
return
VALID
;
}
return
!
VALID
;
}
// Validate the minimum length of the public rsa key is a secure length
int
validate_RSA_min_len
(
X509
*
cert
)
{
// Check that key type is rsa
int
key_type
=
OBJ_obj2nid
(
cert
->
cert_info
->
key
->
algor
->
algorithm
);
assert
(
key_type
);
assert
(
key_type
==
NID_rsaEncryption
);
// Get the key
EVP_PKEY
*
key
=
X509_get_pubkey
(
cert
);
assert
(
key
);
RSA
*
rsa_key
=
key
->
pkey
.
rsa
;
assert
(
rsa_key
);
// Check the length of the key
int
rsa_bytes
=
RSA_size
(
rsa_key
);
assert
(
rsa_bytes
);
if
(
rsa_bytes
>=
MIN_RSA_BYTES
)
{
return
VALID
;
}
return
!
VALID
;
}
// Checks that BasicConstraints extension exists and contains "CA:FALSE"
int
validate_BasicConstraints
(
X509
*
cert
)
{
char
*
constraints
=
get_ext_value
(
cert
,
NID_basic_constraints
);
if
(
constraints
)
{
int
not_ca
=
(
strstr
(
constraints
,
NOT_CA_STR
)
!=
NULL
)
&&
(
strstr
(
constraints
,
IS_CA_STR
)
==
NULL
);
free
(
constraints
);
return
not_ca
?
VALID
:
!
VALID
;
}
return
!
VALID
;
}
// Checks that ExtendedKeyUsage extension exists
// and contains "TLS Web Server Authentication"
int
validate_ExtendedKeyUsage
(
X509
*
cert
)
{
char
*
ext_key_usage
=
get_ext_value
(
cert
,
NID_ext_key_usage
);
if
(
ext_key_usage
)
{
int
for_tls
=
(
strstr
(
ext_key_usage
,
TLS_STR
)
!=
NULL
);
free
(
ext_key_usage
);
return
for_tls
?
VALID
:
!
VALID
;
}
return
!
VALID
;
}
// Checks if a certificate name matches the url given
int
match_url_to_name
(
char
*
url
,
char
*
name
)
{
int
u_i
=
strlen
(
url
);
int
n_i
=
strlen
(
name
);
while
(
u_i
>=
0
&&
n_i
>=
0
)
{
// Wildcard case
if
(
name
[
n_i
]
==
WILDCARD
)
{
return
WILDCARD_VALID
(
name
,
n_i
)
?
VALID
:
!
VALID
;
}
// Check if characters match
if
(
url
[
u_i
]
!=
name
[
n_i
])
{
return
!
VALID
;
}
else
if
(
u_i
==
0
&&
n_i
==
0
)
{
return
VALID
;
}
u_i
--
;
n_i
--
;
}
return
!
VALID
;
}
// Check if the url matches the CN on the certificate
int
check_cn
(
X509
*
cert
,
char
*
url
)
{
int
len
=
DEFAULT_STRLEN
;
char
*
cn
=
(
char
*
)
calloc
(
len
,
sizeof
(
char
));
assert
(
cn
);
assert
(
strcpy
(
cn
,
NO_CN
));
X509_NAME
*
cert_subject
=
X509_get_subject_name
(
cert
);
X509_NAME_get_text_by_NID
(
cert_subject
,
NID_commonName
,
cn
,
len
);
int
validity
=
match_url_to_name
(
url
,
cn
);
//printf("CN: %s\n", cn);
free
(
cn
);
return
validity
;
}
int
main
(
int
argv
,
char
**
argc
)
{
printf
(
"Hello, World
\n
"
);
BIO
*
certificate_bio
=
NULL
;
// Check if the url matches the SAN on the certificate
int
check_san
(
X509
*
cert
,
char
*
url
)
{
char
*
sans
=
get_ext_value
(
cert
,
NID_subject_alt_name
);
if
(
sans
==
NULL
)
{
return
!
VALID
;
}
char
*
stptr
=
sans
;
char
*
endptr
=
sans
;
char
*
name
=
(
char
*
)
calloc
(
DEFAULT_STRLEN
,
sizeof
(
char
));
assert
(
name
);
for
(;;)
{
name
=
memset
(
name
,
NULL_C
,
DEFAULT_STRLEN
);
// Clear name
stptr
=
strstr
(
endptr
,
SAN_ENTRY
)
+
1
;
// get ptr to start of name
endptr
=
strstr
(
stptr
,
SAN_DELIM
);
// get ptr to end of name
// copy name to name str
if
(
endptr
==
NULL
)
{
name
=
strcpy
(
name
,
stptr
);
}
else
{
int
n
=
endptr
-
stptr
;
name
=
memcpy
(
name
,
stptr
,
n
);
}
//printf("SAN: %s\n",name);
// match name against url
if
(
match_url_to_name
(
url
,
name
)
==
VALID
)
{
free
(
name
);
return
VALID
;
}
// Give up search when at end of list
if
(
endptr
==
NULL
)
{
free
(
name
);
return
!
VALID
;
}
}
}
// Verify the domain name in the url matches the
// CN or SAN of the certificate
int
validate_domain
(
X509
*
cert
,
char
*
url
)
{
int
cn
=
check_cn
(
cert
,
url
)
==
VALID
;
int
san
=
check_san
(
cert
,
url
)
==
VALID
;
return
cn
||
san
?
VALID
:
!
VALID
;
}
// Validate a certificate
int
validate_cert
(
X509
*
cert
,
char
*
url
)
{
int
date
=
(
validate_date
(
cert
)
==
VALID
);
int
minkey
=
(
validate_RSA_min_len
(
cert
)
==
VALID
);
int
basic
=
(
validate_BasicConstraints
(
cert
)
==
VALID
);
int
exten
=
(
validate_ExtendedKeyUsage
(
cert
)
==
VALID
);
int
dom
=
(
validate_domain
(
cert
,
url
)
==
VALID
);
int
valid
=
date
&&
minkey
&&
basic
&&
exten
&&
dom
;
if
(
valid
)
{
return
VALID
;
}
return
!
VALID
;
}
// Reads X509 certificate into X509 struct
// Returned value can be used to analyse the certificate
X509
*
open_cert
(
const
char
*
filename
)
{
//create BIO object to read certificate
BIO
*
certificate_bio
=
BIO_new
(
BIO_s_file
());
//Read certificate into BIO
int
read_success
=
BIO_read_filename
(
certificate_bio
,
filename
);
assert
(
read_success
);
// Read BIO into certificate
X509
*
cert
=
PEM_read_bio_X509
(
certificate_bio
,
NULL
,
0
,
NULL
);
assert
(
cert
);
BIO_free_all
(
certificate_bio
);
return
cert
;
}
// Reads a portion of the input csv file into an array, delimited by delim
char
*
ftostr
(
FILE
*
fp
,
char
delim
)
{
int
size
=
START_STR_SIZE
;
char
*
arr
=
(
char
*
)
calloc
(
size
,
sizeof
(
char
));
assert
(
arr
);
char
tmpc
;
int
i
=
0
;
for
(
i
=
0
;;
i
++
)
{
tmpc
=
fgetc
(
fp
);
if
(
tmpc
==
delim
||
tmpc
==
EOF
)
{
// stop if reached delimiter
break
;
}
else
if
(
tmpc
==
NULL_C
)
{
// Skip null chars
continue
;
}
else
if
((
i
+
1
)
>=
size
)
{
// Extend array if necessary
size
+=
size
;
arr
=
(
char
*
)
realloc
(
arr
,
size
*
sizeof
(
char
*
));
assert
(
arr
);
}
// Put char from stream into array output
assert
(
tmpc
);
arr
[
i
]
=
tmpc
;
arr
[
i
+
1
]
=
NULL_C
;
}
return
arr
;
}
// Process a line in the csv
char
process_line
(
FILE
*
in_fp
,
FILE
*
out_fp
)
{
// Read path until a comma is found
char
*
path
=
ftostr
(
in_fp
,
DELIMITER
);
if
(
!
strlen
(
path
))
{
free
(
path
);
return
EOF
;
}
// Read url until a \n is found
char
*
url
=
ftostr
(
in_fp
,
NEWLINE
);
assert
(
strlen
(
url
));
// Validate the certificate and print to output
X509
*
cert
=
open_cert
(
path
);
int
valid
=
validate_cert
(
cert
,
url
);
fprintf
(
out_fp
,
"%s,%s,%d
\n
"
,
path
,
url
,
valid
);
X509_free
(
cert
);
free
(
url
);
free
(
path
);
return
!
EOF
;
}
// Processes a csv in accordance with assignment specs
void
process_csv
(
char
*
filename
)
{
FILE
*
in_fp
=
fopen
(
filename
,
READONLY
);
FILE
*
out_fp
=
fopen
(
OUT_FILENAME
,
REWRITE
);
assert
(
out_fp
);
assert
(
in_fp
);
while
(
process_line
(
in_fp
,
out_fp
)
!=
EOF
)
{
}
fclose
(
out_fp
);
fclose
(
in_fp
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
//initialise openSSL
OpenSSL_add_all_algorithms
();
ERR_load_BIO_strings
();
ERR_load_crypto_strings
();
if
(
argc
!=
NUM_ARGS
)
{
printf
(
EXAMPLE_USAGE
);
exit
(
EXIT_FAILURE
);
}
process_csv
(
argv
[
FILENAME_ARG
]);
exit
(
EXIT_SUCCESS
);
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment