21#include <openssl/err.h> 
   22#include <openssl/ssl.h> 
   23#include <openssl/evp.h> 
   24#include <openssl/md5.h> 
   25#include <openssl/sha.h> 
   26#include <openssl/bio.h> 
   27#include <openssl/obj_mac.h> 
   28#include <openssl/x509.h> 
   29#include <openssl/x509v3.h> 
   30#include <openssl/x509_vfy.h> 
   44void __attribute__((format(printf, 5, 6)))
 
   54    fp = open_memstream(&buffer, &length);
 
   61        size_t fmt_len = strlen(fmt);
 
   62        if (fmt[fmt_len - 1] == 
'\n') {
 
   64            tmp_fmt[fmt_len - 1] = 
'\0';
 
   68    vfprintf(fp, fmt, ap);
 
   70    ERR_print_errors_fp(fp);
 
   74        ast_log(level, file, line, function, 
"%s\n", buffer);
 
 
   81    const char *long_name)
 
   87        ast_log(
LOG_ERROR, 
"One or more of oid, short_name or long_name are NULL or empty\n");
 
   91    nid = OBJ_sn2nid(short_name);
 
   92    if (nid != NID_undef) {
 
   97    nid = OBJ_create(oid, short_name, long_name);
 
   98    if (nid == NID_undef) {
 
 
  108    int nid, 
const char *short_name)
 
  114        nid = OBJ_sn2nid(short_name);
 
  115        if (nid == NID_undef) {
 
  120        const char *tmp = OBJ_nid2sn(nid);
 
  127    ex_idx = X509_get_ext_by_NID(cert, nid, -1);
 
  132    ex = X509_get_ext(cert, ex_idx);
 
  138    return X509_EXTENSION_get_data(ex);
 
 
  143    EVP_PKEY *key = 
NULL;
 
  151    fp = fopen(filename, 
"r");
 
 
  168    X509_CRL *crl = 
NULL;
 
  175    fp = fopen(filename, 
"r");
 
  181    crl = PEM_read_X509_CRL(fp, &crl, 
NULL, 
NULL);
 
 
  189#define debug_cert_chain(level, cert_chain) \ 
  193    if (cert_chain && sk_X509_num(cert_chain) > 0) { \ 
  194        for (i = 0; i < sk_X509_num(cert_chain); i++) { \ 
  195            X509 *cert = sk_X509_value(cert_chain, i); \ 
  197            X509_NAME_oneline(X509_get_subject_name(cert), subj, 1024); \ 
  198            ast_debug(level, "Chain cert %d: '%s'\n", i, subj); \ 
 
  206    X509 *end_cert = 
NULL;
 
  213    fp = fopen(filename, 
"r");
 
  219    end_cert = PEM_read_X509(fp, &end_cert, 
NULL, 
NULL);
 
  231        X509 *chain_cert = 
NULL;
 
  233        *cert_chain = sk_X509_new_null();
 
  234        while ((chain_cert = PEM_read_X509(fp, &chain_cert, 
NULL, 
NULL)) != 
NULL) {
 
  235            if (sk_X509_push(*cert_chain, chain_cert) <= 0) {
 
  240                sk_X509_pop_free(*cert_chain, X509_free);
 
  251        X509_NAME_oneline(X509_get_subject_name(end_cert), subj, 1024);
 
  252        ast_debug(4, 
"Opened end cert '%s' from '%s'\n", subj, filename);
 
  254        if (cert_chain && *cert_chain) {
 
  257            ast_debug(4, 
"No chain certs found in '%s'\n", filename);
 
 
  267    STACK_OF(X509) **cert_chain)
 
  270    X509 *end_cert = 
NULL;
 
  277    bio = BIO_new_mem_buf(buffer, size);
 
  294        X509 *chain_cert = 
NULL;
 
  296        *cert_chain = sk_X509_new_null();
 
  297        while ((chain_cert = PEM_read_bio_X509(bio, &chain_cert, 
NULL, 
NULL)) != 
NULL) {
 
  298            if (sk_X509_push(*cert_chain, chain_cert) <= 0) {
 
  301                sk_X509_pop_free(*cert_chain, X509_free);
 
  312        X509_NAME_oneline(X509_get_subject_name(end_cert), subj, 1024);
 
  313        ast_debug(4, 
"Opened end cert '%s' from BIO\n", subj);
 
  315        if (cert_chain && *cert_chain) {
 
  318            ast_debug(4, 
"No chain certs found in BIO\n");
 
 
  328    EVP_PKEY *key = 
NULL;
 
  335    bio = BIO_new_mem_buf(buffer, size);
 
 
  367    raw_key_len = BIO_get_mem_data(bio, &temp_ptr);
 
  368    if (raw_key_len <= 0) {
 
  377    memcpy(*buffer, temp_ptr, raw_key_len);
 
 
  386    bio = BIO_new(BIO_s_mem());
 
  388    if (!bio || (PEM_write_bio_PUBKEY(bio, key) <= 0)) {
 
 
  397    unsigned char **buffer)
 
  399    RAII_VAR(EVP_PKEY *, public_key, X509_get_pubkey(cert), EVP_PKEY_free);
 
 
  413    bio = BIO_new(BIO_s_mem());
 
  415    if (!bio || (PEM_write_bio_PrivateKey(bio, key, 
NULL, 
NULL, 0, 
NULL, 
NULL) <= 0)) {
 
 
  463        X509_STORE_free(store->
certs);
 
  468    if (store->untrusted_stack) {
 
  469        sk_X509_free(store->untrusted_stack);
 
  472        X509_STORE_free(store->
crls);
 
  474    if (store->crl_stack) {
 
  475        sk_X509_CRL_free(store->crl_stack);
 
 
  487    store->
certs = X509_STORE_new();
 
  500    store->untrusted_stack = sk_X509_new_null();
 
  501    if (!store->untrusted_stack) {
 
  507    store->
crls = X509_STORE_new();
 
  513    store->crl_stack = sk_X509_CRL_new_null();
 
  514    if (!store->crl_stack) {
 
 
  537    rc = X509_STORE_add_cert(store, cert);
 
 
  561    rc = X509_STORE_add_crl(store, crl);
 
 
  576static int pem_file_cb(
const char *dir_name, 
const char *filename, 
void *obj)
 
  579    char *filename_merged = 
NULL;
 
  583    if (
ast_asprintf(&filename_merged, 
"%s/%s", dir_name, filename) < 0) {
 
  587    if (lstat(filename_merged, &statbuf)) {
 
  588        printf(
"Error reading path stats - %s: %s\n",
 
  589                    filename_merged, strerror(
errno));
 
  595    if (!S_ISLNK(statbuf.st_mode)) {
 
 
  672    STACK_OF(X509_OBJECT) *objs = 
NULL;
 
  698    objs = X509_STORE_get0_objects(
store->untrusted);
 
  699    count = sk_X509_OBJECT_num(objs);
 
  700    for (i = 0; i < count ; i++) {
 
  701        X509_OBJECT *o = sk_X509_OBJECT_value(objs, i);
 
  702        if (X509_OBJECT_get_type(o) == X509_LU_X509) {
 
  703            X509 *
c = X509_OBJECT_get0_X509(o);
 
  704            sk_X509_push(
store->untrusted_stack, 
c);
 
 
  715    STACK_OF(X509_OBJECT) *objs = 
NULL;
 
  741    objs = X509_STORE_get0_objects(
store->crls);
 
  742    count = sk_X509_OBJECT_num(objs);
 
  743    for (i = 0; i < count ; i++) {
 
  744        X509_OBJECT *o = sk_X509_OBJECT_value(objs, i);
 
  745        if (X509_OBJECT_get_type(o) == X509_LU_CRL) {
 
  746            X509_CRL *
c = X509_OBJECT_get0_X509_CRL(o);
 
  747            sk_X509_CRL_push(
store->crl_stack, 
c);
 
 
  756#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) 
  757    STACK_OF(X509_OBJECT) *objs = 
NULL;
 
  759    int untrusted_count = 0;
 
  767    objs = X509_STORE_get0_objects(
store->certs);
 
  768    count = sk_X509_OBJECT_num(objs);
 
  770    for (i = 0; i < count ; i++) {
 
  771        X509_OBJECT *o = sk_X509_OBJECT_value(objs, i);
 
  772        if (X509_OBJECT_get_type(o) == X509_LU_X509) {
 
  773            X509 *
c = X509_OBJECT_get0_X509(o);
 
  774            X509_NAME_oneline(X509_get_subject_name(
c), subj, 1024);
 
  775            ast_cli(fd, 
"Cert: %s\n", subj);
 
  786    untrusted_count = sk_X509_num(
store->untrusted_stack);
 
  787    for (i = 0; i < untrusted_count ; i++) {
 
  788        X509 *
c = sk_X509_value(
store->untrusted_stack, i);
 
  789        X509_NAME_oneline(X509_get_subject_name(
c), subj, 1024);
 
  790        ast_cli(fd, 
"Untrusted: %s\n", subj);
 
  796    crl_count = sk_X509_CRL_num(
store->crl_stack);
 
  797    for (i = 0; i < crl_count ; i++) {
 
  798        X509_CRL *crl = sk_X509_CRL_value(
store->crl_stack, i);
 
  799        X509_NAME_oneline(X509_CRL_get_issuer(crl), subj, 1024);
 
  800        ast_cli(fd, 
"CRL: %s\n", subj);
 
  803    return count + untrusted_count + crl_count;
 
  805    ast_cli(fd, 
"This command is not supported until OpenSSL 1.1.0\n");
 
 
  812    ASN1_STRING *notbefore;
 
  813    ASN1_STRING *notafter;
 
  816        reftime = time(
NULL);
 
  818    notbefore = X509_get_notBefore(cert);
 
  819    notafter = X509_get_notAfter(cert);
 
  820    if (!notbefore || !notafter) {
 
  821        ast_log(
LOG_ERROR, 
"Either notbefore or notafter were not present in the cert\n");
 
  825    return (X509_cmp_time(notbefore, &reftime) < 0 &&
 
  826        X509_cmp_time(notafter, &reftime) > 0);
 
 
  830    STACK_OF(X509) *cert_chain, 
const char **err_msg)
 
  832    X509_STORE_CTX *verify_ctx = 
NULL;
 
  833    RAII_VAR(STACK_OF(X509) *, untrusted_stack, 
NULL, sk_X509_free);
 
  836    if (!(verify_ctx = X509_STORE_CTX_new())) {
 
  841    if (cert_chain && sk_X509_num(cert_chain) > 0) {
 
  842        int untrusted_count = 
store->untrusted_stack ? sk_X509_num(
store->untrusted_stack) : 0;
 
  845        untrusted_stack = sk_X509_dup(cert_chain);
 
  846        if (!untrusted_stack) {
 
  848            X509_STORE_CTX_free(verify_ctx);
 
  855        for (i = 0; i < untrusted_count; i++) {
 
  856            X509 *
c = sk_X509_value(
store->untrusted_stack, i);
 
  857            if (sk_X509_push(untrusted_stack, 
c) <= 0) {
 
  859                sk_X509_free(untrusted_stack);
 
  860                X509_STORE_CTX_free(verify_ctx);
 
  868    } 
else if (
store->untrusted_stack){
 
  870        ast_debug(4, 
"cert_chain had no certs\n");
 
  871        untrusted_stack = sk_X509_dup(
store->untrusted_stack);
 
  872        if (!untrusted_stack) {
 
  874            X509_STORE_CTX_free(verify_ctx);
 
  879    if (X509_STORE_CTX_init(verify_ctx, 
store->certs, cert, untrusted_stack) != 1) {
 
  880        X509_STORE_CTX_cleanup(verify_ctx);
 
  881        X509_STORE_CTX_free(verify_ctx);
 
  885    X509_STORE_CTX_set0_crls(verify_ctx, 
store->crl_stack);
 
  887    rc = X509_verify_cert(verify_ctx);
 
  888    if (rc != 1 && err_msg != 
NULL) {
 
  889        int err = X509_STORE_CTX_get_error(verify_ctx);
 
  890        *err_msg = X509_verify_cert_error_string(err);
 
  893    X509_STORE_CTX_cleanup(verify_ctx);
 
  894    X509_STORE_CTX_free(verify_ctx);
 
 
  899#define SECS_PER_DAY 86400 
  904    time_t rt = time(
NULL);
 
  906    if (!ASN1_TIME_diff(&pday, &psec, 
NULL, at)) {
 
 
  921    char *search_buff = 
NULL;
 
  923    size_t search_len = 0;
 
  932    unsigned long flags =
 
  933        short_name ? XN_FLAG_FN_SN | XN_FLAG_SEP_MULTILINE : XN_FLAG_ONELINE;
 
  934    FILE *fp = open_memstream(&buffer, &
len);
 
  935    BIO *bio = fp ? BIO_new_fp(fp, BIO_CLOSE) : 
NULL;
 
  936    X509_NAME *subject = X509_get_subject_name(cert);
 
  939    if (!fp || !bio || !subject) {
 
  943    rc = X509_NAME_print_ex(bio, subject, 0, flags);
 
  957    search_len = strlen(short_name) + 1;
 
  959    if (rc != search_len) {
 
  963    search_buff = buffer;
 
  966            rtn = 
ast_malloc(strlen(line) - search_len + 1);
 
  968                strcpy(rtn, line + search_len); 
 
 
Asterisk main include file. File version handling, generic pbx functions.
void ast_std_free(void *ptr)
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc(data_size, destructor_fn)
Standard Command Line Interface.
void ast_cli(int fd, const char *fmt,...)
static EVP_PKEY * load_private_key_from_memory(const char *buffer, size_t size)
int crypto_load_crl_store(struct crypto_cert_store *store, const char *file, const char *path)
Load an X509 Store with certificate revocation lists.
static void crypto_cert_store_destructor(void *obj)
X509 * crypto_load_cert_chain_from_memory(const char *buffer, size_t size, STACK_OF(X509) **cert_chain)
Load an X509 Cert and any chained certs from a NULL terminated buffer.
#define debug_cert_chain(level, cert_chain)
static int pem_file_cb(const char *dir_name, const char *filename, void *obj)
static int _crypto_load_cert_store(X509_STORE *store, const char *file, const char *path)
static int crypto_load_store_from_crl_file(X509_STORE *store, const char *file)
void crypto_log_openssl(int level, char *file, int line, const char *function, const char *fmt,...)
Print a log message with any OpenSSL errors appended.
int crypto_get_raw_pubkey_from_cert(X509 *cert, unsigned char **buffer)
Retrieve RAW public key from cert.
int crypto_extract_raw_pubkey(EVP_PKEY *key, unsigned char **buffer)
Extract raw public key from EVP_PKEY.
time_t crypto_asn_time_as_time_t(ASN1_TIME *at)
Return a time_t for an ASN1_TIME.
X509 * crypto_load_cert_chain_from_file(const char *filename, STACK_OF(X509) **cert_chain)
Load an X509 Cert and any chained certs from a file.
X509_CRL * crypto_load_crl_from_file(const char *filename)
Load an X509 CRL from a PEM file.
EVP_PKEY * crypto_load_privkey_from_file(const char *filename)
Load a private key from a file.
int crypto_register_x509_extension(const char *oid, const char *short_name, const char *long_name)
Register a certificate extension to openssl.
int crypto_load_untrusted_cert_store(struct crypto_cert_store *store, const char *file, const char *path)
Load an X509 Store with untrusted certificates.
int crypto_extract_raw_privkey(EVP_PKEY *key, unsigned char **buffer)
Extract raw private key from EVP_PKEY.
int crypto_load(void)
Initialize the crypto utils.
char * crypto_get_cert_subject(X509 *cert, const char *short_name)
Returns the Subject (or component of Subject) from a certificate.
int crypto_is_cert_time_valid(X509 *cert, time_t reftime)
Check if the reftime is within the cert's valid dates.
static int crypto_load_store_from_cert_file(X509_STORE *store, const char *file)
struct crypto_cert_store * crypto_create_cert_store(void)
Create an empty X509 store.
static int dump_mem_bio(BIO *bio, unsigned char **buffer)
int crypto_has_private_key_from_memory(const char *buffer, size_t size)
Check if the supplied buffer has a private key.
int crypto_unload(void)
Clean up the crypto utils.
static int _crypto_load_crl_store(X509_STORE *store, const char *file, const char *path)
int crypto_is_cert_trusted(struct crypto_cert_store *store, X509 *cert, STACK_OF(X509) *cert_chain, const char **err_msg)
Check if the cert is trusted.
EVP_PKEY * crypto_load_private_key_from_memory(const char *buffer, size_t size)
Load a private key from memory.
int crypto_show_cli_store(struct crypto_cert_store *store, int fd)
Dump a cert store to the asterisk CLI.
ASN1_OCTET_STRING * crypto_get_cert_extension_data(X509 *cert, int nid, const char *short_name)
Return the data from a specific extension in a cert.
int crypto_load_cert_store(struct crypto_cert_store *store, const char *file, const char *path)
Load an X509 Store with either certificates or CRLs.
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Support for logging to various files, console and syslog Configuration in file logger....
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk module definitions.
@ AST_MODULE_LOAD_SUCCESS
static force_inline int attribute_pure ast_strlen_zero(const char *s)
char * ast_read_line_from_buffer(char **buffer)
Read lines from a string buffer.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
ao2 object wrapper for X509_STORE that provides locking and refcounting
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Vector container support.