X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=blobdiff_plain;f=src%2Fos_auth%2Fssl.c;fp=src%2Fos_auth%2Fssl.c;h=c9b017cc37b6d2b68f1c677297264fc335072a11;hp=9841861dba2a57821ccf00dcae0670dd13ce4ad2;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hpb=927951d1c1ad45ba9e7325f07d996154a91c911b diff --git a/src/os_auth/ssl.c b/src/os_auth/ssl.c old mode 100755 new mode 100644 index 9841861..c9b017c --- a/src/os_auth/ssl.c +++ b/src/os_auth/ssl.c @@ -1,6 +1,3 @@ -/* @(#) $Id: ./src/os_auth/ssl.c, 2011/09/08 dcid Exp $ - */ - /* Copyright (C) 2010 Trend Micro Inc. * All rights reserved. * @@ -25,84 +22,182 @@ * */ - -#ifdef USE_OPENSSL +#ifdef LIBOPENSSL_ENABLED #include "shared.h" #include "auth.h" +/* Global variables */ +BIO *bio_err; + + +/* Create an SSL context. If certificate verification is requested + * then load the file containing the CA chain and verify the certificate + * sent by the peer. + */ +SSL_CTX *os_ssl_keys(int is_server, const char *os_dir, const char *ciphers, const char *cert, const char *key, const char *ca_cert) +{ + SSL_CTX *ctx = NULL; + + if (!(ctx = get_ssl_context(ciphers))) { + goto SSL_ERROR; + } + + /* If a CA certificate has been specified then load it and verify the peer */ + if (ca_cert) { + debug1("%s: DEBUG: Peer verification requested.", ARGV0); + + if (!load_ca_cert(ctx, ca_cert)) { + goto SSL_ERROR; + } + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); + } + + /* Loading a certificate and key is mandatory for the server and optional for clients */ + if (is_server) { + char default_cert[PATH_MAX + 1]; + char default_key[PATH_MAX + 1]; + + if (!cert) { + snprintf(default_cert, PATH_MAX + 1, "%s%s", os_dir, CERTFILE); + cert = default_cert; + } + + if (!key) { + snprintf(default_key, PATH_MAX + 1, "%s%s", os_dir, KEYFILE); + key = default_key; + } + + if (!load_cert_and_key(ctx, cert, key)) { + goto SSL_ERROR; + } + + debug1("%s: DEBUG: Returning CTX for server.", ARGV0); + } else { + if (cert && key) { + if (!load_cert_and_key(ctx, cert, key)) { + goto SSL_ERROR; + } + } + + debug1("%s: DEBUG: Returning CTX for client.", ARGV0); + } -void *os_ssl_keys(int isclient, char *dir) + return ctx; + +SSL_ERROR: + if (ctx) { + SSL_CTX_free(ctx); + } + + return (SSL_CTX *)NULL; +} + +SSL_CTX *get_ssl_context(const char *ciphers) { - SSL_METHOD *sslmeth; - SSL_CTX *ctx; - char certf[1024 +1]; - char keyf[1024 +1]; + const SSL_METHOD *sslmeth = NULL; + SSL_CTX *ctx = NULL; SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); - bio_err = BIO_new_fp(stderr,BIO_NOCLOSE); - /* Create our context */ - sslmeth = (SSL_METHOD *)SSLv23_method(); - ctx = SSL_CTX_new(sslmeth); - - if(isclient) - { - debug1("%s: DEBUG: Returning CTX for client.", ARGV0); - return(ctx); + sslmeth = TLSv1_2_method(); + if (!(ctx = SSL_CTX_new(sslmeth))) { + goto CONTEXT_ERR; } - if(!dir) - { - return(NULL); + /* Explicitly set options and cipher list */ + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + if (!(SSL_CTX_set_cipher_list(ctx, ciphers))) { + goto CONTEXT_ERR; } + return ctx; - /* Setting final cert/key files */ - certf[1024] = '\0'; - keyf[1024] = '\0'; - snprintf(certf, 1023, "%s%s", dir, CERTFILE); - snprintf(keyf, 1023, "%s%s", dir, KEYFILE); +CONTEXT_ERR: + if (ctx) { + SSL_CTX_free(ctx); + } + return (SSL_CTX *)NULL; +} - if(File_DateofChange(certf) <= 0) - { - merror("%s: ERROR: Unable to read certificate file (not found): %s", ARGV0, certf); - return(NULL); +int load_cert_and_key(SSL_CTX *ctx, const char *cert, const char *key) +{ + if (File_DateofChange(cert) <= 0) { + merror("%s: ERROR: Unable to read certificate file (not found): %s", ARGV0, cert); + return 0; } - /* Load our keys and certificates*/ - if(!(SSL_CTX_use_certificate_chain_file(ctx, certf))) - { - merror("%s: ERROR: Unable to read certificate file: %s", ARGV0, certf); + if (!(SSL_CTX_use_certificate_chain_file(ctx, cert))) { + merror("%s: ERROR: Unable to read certificate file: %s", ARGV0, cert); ERR_print_errors_fp(stderr); - return(NULL); + return 0; } - if(!(SSL_CTX_use_PrivateKey_file(ctx, keyf, SSL_FILETYPE_PEM))) - { - merror("%s: ERROR: Unable to read private key file: %s", ARGV0, keyf); - return(NULL); + if (!(SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM))) { + merror("%s: ERROR: Unable to read private key file: %s", ARGV0, key); + ERR_print_errors_fp(stderr); + return 0; } - if (!SSL_CTX_check_private_key(ctx)) - { + if (!SSL_CTX_check_private_key(ctx)) { merror("%s: ERROR: Unable to verify private key file", ARGV0); - return(NULL); + ERR_print_errors_fp(stderr); + return 0; } +#if(OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(ctx, 1); +#endif - #if(OPENSSL_VERSION_NUMBER < 0x00905100L) - SSL_CTX_set_verify_depth(ctx,1); - #endif + return 1; +} - return ctx; +int load_ca_cert(SSL_CTX *ctx, const char *ca_cert) +{ + if (!ca_cert) { + merror("%s: ERROR: Verification requested but no CA certificate file specified", ARGV0); + return 0; + } + + if (SSL_CTX_load_verify_locations(ctx, ca_cert, NULL) != 1) { + merror("%s: ERROR: Unable to read CA certificate file \"%s\"", ARGV0, ca_cert); + return 0; + } + + return 1; } +/* No extra verification is done here. This function provides more + * information in the case that certificate verification fails + * for any reason. + */ +int verify_callback(int ok, X509_STORE_CTX *store) +{ + char data[256]; + + if (!ok) { + X509 *cert = X509_STORE_CTX_get_current_cert(store); + int depth = X509_STORE_CTX_get_error_depth(store); + int err = X509_STORE_CTX_get_error(store); -#endif + merror("%s: ERROR: Problem with certificate at depth %i", ARGV0, depth); + + X509_NAME_oneline(X509_get_issuer_name(cert), data, 256); + merror("%s: ERROR: issuer = %s", ARGV0, data); + + X509_NAME_oneline(X509_get_subject_name(cert), data, 256); + merror("%s: ERROR: subject = %s", ARGV0, data); + + merror("%s: ERROR: %i:%s", ARGV0, err, X509_verify_cert_error_string(err)); + } + + return ok; +} + +#endif /* LIBOPENSSL_ENABLED */ -/* EOF */