Navigation


Changeset 542:0b6cee362f5d in freeDiameter


Ignore:
Timestamp:
Sep 13, 2010, 6:39:22 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Enforce validation of local certificate upon daemon start.

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/cnxctx.c

    r455 r542  
    11761176                CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
    11771177               
     1178                /* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function */
     1179               
    11781180                GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) );
    11791181                if ((deadline != (time_t)-1) && (deadline < now)) {
     
    12531255        {
    12541256                int ret;
     1257               
     1258                /* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function */
     1259               
    12551260                CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session),
    12561261                        {
  • freeDiameter/config.c

    r447 r542  
    269269        }
    270270       
     271       
     272        /* Verify that our certificate is valid -- otherwise remote peers will reject it */
     273        {
     274                int ret = 0, i;
     275               
     276                gnutls_datum_t certfile;
     277                size_t alloc = 0;
     278               
     279                gnutls_x509_crt_t * certs = NULL;
     280                unsigned int cert_max = 0;
     281               
     282                gnutls_x509_crt_t * CA_list;
     283                int CA_list_length;
     284               
     285                gnutls_x509_crl_t * CRL_list;
     286                int CRL_list_length;
     287               
     288                unsigned int verify;
     289                time_t now;
     290               
     291                memset(&certfile, 0, sizeof(certfile));
     292               
     293                /* Read the certificate file */
     294                FILE *stream = fopen (fd_g_config->cnf_sec_data.cert_file, "rb");
     295                if (!stream) {
     296                        int err = errno;
     297                        TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s\n", fd_g_config->cnf_sec_data.cert_file, strerror(err));
     298                        return err;
     299                }
     300                do {
     301                        uint8_t * realloced = NULL;
     302                        size_t read = 0;
     303                       
     304                        if (alloc < certfile.size + BUFSIZ + 1) {
     305                                alloc += alloc / 2 + BUFSIZ + 1;
     306                                CHECK_MALLOC_DO( realloced = realloc(certfile.data, alloc),
     307                                        {
     308                                                free(certfile.data);
     309                                                return ENOMEM;
     310                                        } )
     311                                certfile.data = realloced;
     312                        }
     313                       
     314                        read = fread( certfile.data + certfile.size, 1, alloc - certfile.size - 1, stream );
     315                        certfile.size += read;
     316                       
     317                        if (ferror(stream)) {
     318                                int err = errno;
     319                                TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s\n", fd_g_config->cnf_sec_data.cert_file, strerror(err));
     320                                return err;
     321                        }
     322                } while (!feof(stream));
     323                certfile.data[certfile.size] = '\0';
     324                fclose(stream);
     325               
     326                /* Import the certificate(s) */
     327                GNUTLS_TRACE( ret = gnutls_x509_crt_list_import(NULL, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) );
     328                if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
     329                        CHECK_GNUTLS_DO(ret, return EINVAL);
     330                }
     331               
     332                CHECK_MALLOC( certs = calloc(cert_max, sizeof(gnutls_x509_crt_t)) );
     333                CHECK_GNUTLS_DO( gnutls_x509_crt_list_import(certs, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, 0),
     334                        {
     335                                TRACE_DEBUG(INFO, "Failed to import the data from file '%s'", fd_g_config->cnf_sec_data.cert_file);
     336                                free(certfile.data);
     337                                return EINVAL;
     338                        } );
     339                free(certfile.data);
     340               
     341                ASSERT(cert_max >= 1);
     342               
     343                /* Now, verify the list against the local CA and CRL */
     344                GNUTLS_TRACE( gnutls_certificate_get_x509_cas (fd_g_config->cnf_sec_data.credentials, &CA_list, (unsigned int *) &CA_list_length) );
     345                GNUTLS_TRACE( gnutls_certificate_get_x509_crls (fd_g_config->cnf_sec_data.credentials, &CRL_list, (unsigned int *) &CRL_list_length) );
     346                CHECK_GNUTLS_DO( gnutls_x509_crt_list_verify(certs, cert_max, CA_list, CA_list_length, CRL_list, CRL_list_length, 0, &verify),
     347                        {
     348                                TRACE_DEBUG(INFO, "Failed to verify the local certificate '%s' against local credentials. Please check your certificate is valid.", fd_g_config->cnf_sec_data.cert_file);
     349                                return EINVAL;
     350                        } );
     351                if (verify) {
     352                        fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
     353                        if (verify & GNUTLS_CERT_INVALID)
     354                                fd_log_debug(" - The certificate is not trusted (unknown CA? expired?)\n");
     355                        if (verify & GNUTLS_CERT_REVOKED)
     356                                fd_log_debug(" - The certificate has been revoked.\n");
     357                        if (verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
     358                                fd_log_debug(" - The certificate hasn't got a known issuer.\n");
     359                        if (verify & GNUTLS_CERT_SIGNER_NOT_CA)
     360                                fd_log_debug(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.\n");
     361                        if (verify & GNUTLS_CERT_INSECURE_ALGORITHM)
     362                                fd_log_debug(" - The certificate signature uses a weak algorithm.\n");
     363                        return EINVAL;
     364                }
     365       
     366                /* Check the local Identity is valid with the certificate */
     367                if (!gnutls_x509_crt_check_hostname (certs[0], fd_g_config->cnf_diamid)) {
     368                        fd_log_debug("TLS: Local certificate '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
     369                        fd_log_debug(" - The certificate hostname does not match '%s'\n", fd_g_config->cnf_diamid);
     370                        return EINVAL;
     371                }
     372               
     373                /* Check validity of all the certificates in the chain */
     374                now = time(NULL);
     375                for (i = 0; i < cert_max; i++)
     376                {
     377                        time_t deadline;
     378
     379                        GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(certs[i]) );
     380                        if ((deadline != (time_t)-1) && (deadline < now)) {
     381                                fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
     382                                fd_log_debug(" - The certificate %d in the chain is expired\n", i);
     383                                return EINVAL;
     384                        }
     385
     386                        GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(certs[i]) );
     387                        if ((deadline != (time_t)-1) && (deadline > now)) {
     388                                fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file);
     389                                fd_log_debug(" - The certificate %d in the chain is not yet activated\n", i);
     390                                return EINVAL;
     391                        }
     392                }
     393               
     394                /* Everything checked OK, free the certificate list */
     395                for (i = 0; i < cert_max; i++)
     396                {
     397                        GNUTLS_TRACE( gnutls_x509_crt_deinit (certs[i]) );
     398                }
     399                free(certs);
     400        }
     401       
     402       
     403        /* gnutls_certificate_set_verify_limits -- so far the default values are fine... */
     404       
    271405        return 0;
    272406}
  • include/freeDiameter/freeDiameter.h

    r454 r542  
    7070
    7171
    72 
    7372/* Structure to hold the configuration of the freeDiameter daemon */
    7473struct fd_config {
  • include/freeDiameter/libfreeDiameter.h

    r512 r542  
    538538          || (((ts1)->tv_sec  == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) ))
    539539
     540/* This gives a good size for buffered reads */
     541#ifndef BUFSIZ
     542#define BUFSIZ 96
     543#endif /* BUFSIZ */
     544
    540545
    541546
Note: See TracChangeset for help on using the changeset viewer.