LCOV - code coverage report
Current view: top level - src - ssl.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 7 175 4.0 %
Date: 2026-05-30 05:21:37 Functions: 2 13 15.4 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "alloc.h"
       3             : #include "conf.h"
       4             : #include "log.h"
       5             : #include "server/ca.h"
       6             : #include "ssl.h"
       7             : 
       8             : static const char *pass=NULL;
       9             : 
      10           0 : int ssl_do_accept(SSL *ssl)
      11             : {
      12           0 :         while(1)
      13           0 :         {
      14           0 :                 int r=0;
      15           0 :                 int ssl_err;
      16           0 :                 ERR_clear_error();
      17           0 :                 switch((r=SSL_accept(ssl)))
      18             :                 {
      19             :                         case 1:
      20             :                                 return 0;
      21           0 :                         case 0:
      22             :                         default:
      23           0 :                                 ssl_err=SSL_get_error(ssl, r);
      24           0 :                                 switch(ssl_err)
      25             :                                 {
      26           0 :                                         case SSL_ERROR_WANT_READ:
      27           0 :                                                 continue;
      28           0 :                                         default:
      29           0 :                                                 logp_ssl_err("SSL_accept error: %d\n", ssl_err);
      30           0 :                                                 return -1;
      31             :                                 }
      32           0 :                                 break;
      33             :                 }
      34             :         }
      35             : }
      36             : 
      37             : #if OPENSSL_VERSION_NUMBER < 0x30000000L
      38             : int ssl_load_dh_params(SSL_CTX *ctx, struct conf **confs)
      39             : {
      40             :         DH *ret=0;
      41             :         BIO *bio=NULL;
      42             :         const char *ssl_dhfile=get_string(confs[OPT_SSL_DHFILE]);
      43             : 
      44             :         if(!(bio=BIO_new_file(ssl_dhfile, "r")))
      45             :         {
      46             :                 logp_ssl_err("Couldn't open ssl_dhfile: %s\n", ssl_dhfile);
      47             :                 return -1;
      48             :         }
      49             : 
      50             :         ret=PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
      51             :         BIO_free(bio);
      52             :         if(SSL_CTX_set_tmp_dh(ctx, ret)<0)
      53             :         {
      54             :                 logp_ssl_err("Couldn't set DH parameters");
      55             :                 return -1;
      56             :         }
      57             :         return 0;
      58             : }
      59             : #else
      60             : #include <openssl/decoder.h>
      61           0 : int ssl_load_dh_params(SSL_CTX *ctx, struct conf **confs)
      62             : {
      63           0 :         BIO *bio=NULL;
      64           0 :         EVP_PKEY *pkey=NULL;
      65           0 :         const char *ssl_dhfile=get_string(confs[OPT_SSL_DHFILE]);
      66             : 
      67           0 :         if(!(bio=BIO_new_file(ssl_dhfile, "r")))
      68             :         {
      69           0 :                 logp_ssl_err("Couldn't open ssl_dhfile: %s\n", ssl_dhfile);
      70           0 :                 return -1;
      71             :         }
      72             : 
      73             :         // Modern way - read as EVP_PKEY directly (preferred in 3.x).
      74           0 :         pkey=PEM_read_bio_Parameters(bio, NULL);
      75           0 :         BIO_free(bio);
      76           0 :         if(!pkey)
      77             :         {
      78           0 :                 logp_ssl_err("Couldn't read DH parameters from %s\n",
      79             :                         ssl_dhfile);
      80           0 :                 return -1;
      81             :         }
      82             : 
      83             :         // Transfer ownership to OpenSSL.
      84           0 :         if(SSL_CTX_set0_tmp_dh_pkey(ctx, pkey)<=0)
      85             :         {
      86           0 :                 logp_ssl_err("Couldn't set DH parameters from %s\n",
      87             :                         ssl_dhfile);
      88           0 :                 EVP_PKEY_free(pkey);
      89           0 :                 return -1;
      90             :         }
      91             : 
      92             :         // Success, openssl now owns pkey, do not free it here.
      93             :         return 0;
      94             : }
      95             : #endif
      96             : 
      97           0 : static int password_cb(char *buf, int num,
      98             :         __attribute__ ((unused)) int rwflag,
      99             :         __attribute__ ((unused)) void *userdata)
     100             : {
     101           0 :         if(num<(int)strlen(pass)+1) return 0;
     102           0 :         strcpy(buf, pass);
     103           0 :         return strlen(pass);
     104             : }
     105             : 
     106           1 : void ssl_load_globals(void)
     107             : {
     108             :         // Global system initialization.
     109           1 :         SSL_library_init();
     110           1 :         SSL_load_error_strings();
     111           1 : }
     112             : 
     113           0 : static int check_path(const char *path, const char *what)
     114             : {
     115           0 :         struct stat statp;
     116           0 :         if(!path) return -1;
     117           0 :         if(stat(path, &statp))
     118             :         {
     119           0 :                 logp("Could not find %s %s: %s\n",
     120           0 :                         what, path, strerror(errno));
     121           0 :                 return -1;
     122             :         }
     123             :         return 0;
     124             : }
     125             : 
     126           0 : static int ssl_load_keys_and_certs(SSL_CTX *ctx, struct conf **confs)
     127             : {
     128           0 :         char *ssl_key=NULL;
     129           0 :         const char *ssl_cert=get_string(confs[OPT_SSL_CERT]);
     130           0 :         const char *ssl_cert_ca=get_string(confs[OPT_SSL_CERT_CA]);
     131             : 
     132             :         // Load our keys and certificates if the path exists.
     133           0 :         if(!check_path(ssl_cert, "ssl_cert")
     134           0 :           && !SSL_CTX_use_certificate_chain_file(ctx, ssl_cert))
     135             :         {
     136           0 :                 logp_ssl_err("Can't read ssl_cert: %s\n", ssl_cert);
     137           0 :                 return -1;
     138             :         }
     139             : 
     140           0 :         pass=get_string(confs[OPT_SSL_KEY_PASSWORD]);
     141           0 :         SSL_CTX_set_default_passwd_cb(ctx, password_cb);
     142             : 
     143           0 :         ssl_key=get_string(confs[OPT_SSL_KEY]);
     144           0 :         if(!ssl_key) ssl_key=get_string(confs[OPT_SSL_CERT]);
     145             : 
     146             :         // Load the key file, if the path exists.
     147           0 :         if(!check_path(ssl_key, "ssl_key")
     148           0 :           && !SSL_CTX_use_PrivateKey_file(ctx, ssl_key, SSL_FILETYPE_PEM))
     149             :         {
     150           0 :                 logp_ssl_err("Can't read ssl_key file: %s\n", ssl_key);
     151           0 :                 return -1;
     152             :         }
     153             : 
     154             :         // Load the CAs we trust, if the path exists.
     155           0 :         if(!check_path(ssl_cert_ca, "ssl_cert_ca")
     156           0 :           && !SSL_CTX_load_verify_locations(ctx, ssl_cert_ca, 0))
     157             :         {
     158           0 :                 logp_ssl_err("Can't read ssl_cert_ca file: %s\n", ssl_cert_ca);
     159           0 :                 return -1;
     160             :         }
     161             : 
     162             :         return 0;
     163             : }
     164             : 
     165           0 : SSL_CTX *ssl_initialise_ctx(struct conf **confs)
     166             : {
     167           0 :         SSL_CTX *ctx=NULL;
     168           0 :         SSL_METHOD *meth=NULL;
     169           0 :         const char *ssl_ciphers=get_string(confs[OPT_SSL_CIPHERS]);
     170             : 
     171             :         // Create our context.
     172           0 :         meth=(SSL_METHOD *)SSLv23_method();
     173           0 :         ctx=(SSL_CTX *)SSL_CTX_new(meth);
     174             : 
     175           0 :         if(ssl_load_keys_and_certs(ctx, confs)) return NULL;
     176             : 
     177           0 :         if(ssl_ciphers)
     178           0 :                 SSL_CTX_set_cipher_list(ctx, ssl_ciphers);
     179             : 
     180             :         // Unclear what is negotiated, so keep quiet until I figure that out.
     181           0 :         if(!get_int(confs[OPT_SSL_COMPRESSION]))
     182             :         {
     183             : #ifdef SSL_OP_NO_COMPRESSION
     184           0 :                 SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
     185             : #else
     186             :                 logp("This version of openssl has no SSL_OP_NO_COMPRESSION option, so turning off config option '%s' will not work. You should probably upgrade openssl.\n", confs[OPT_SSL_COMPRESSION]->field);
     187             : #endif
     188             :         }
     189             :         // Default is zlib5, which needs no option set.
     190             : 
     191           0 :         SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
     192             : 
     193           0 :         return ctx;
     194             : }
     195             : 
     196           1 : void ssl_destroy_ctx(SSL_CTX *ctx)
     197             : {
     198           1 :         SSL_CTX_free(ctx);
     199           1 : }
     200             : 
     201             : #ifndef HAVE_WIN32
     202           0 : static void sanitise(char *buf)
     203             : {
     204           0 :         char *cp=NULL;
     205           0 :         for(cp=buf; *cp; cp++)
     206             :         {
     207           0 :                 if(!isalnum(*cp)
     208             :                   && !isblank(*cp)
     209             :                   && *cp!='_'
     210             :                   && *cp!='-'
     211             :                   && *cp!='.'
     212             :                   && *cp!=':'
     213             :                   && *cp!='@')
     214           0 :                         *cp='_';
     215             :         }
     216           0 : }
     217             : 
     218             : // This function taken from openvpn-2.2.1 and tidied up a bit.
     219           0 : static int setenv_x509(X509_NAME *x509, const char *type)
     220             : {
     221           0 :         int i, n;
     222           0 :         int fn_nid;
     223           0 :         ASN1_OBJECT *fn;
     224           0 :         ASN1_STRING *val;
     225           0 :         X509_NAME_ENTRY *ent;
     226           0 :         const char *objbuf;
     227           0 :         uint8_t *buf;
     228           0 :         char *name_expand;
     229           0 :         size_t name_expand_size;
     230             : 
     231           0 :         n=X509_NAME_entry_count (x509);
     232           0 :         for(i=0; i<n; ++i)
     233             :         {
     234           0 :                 if(!(ent=X509_NAME_get_entry (x509, i))
     235           0 :                   || !(fn=X509_NAME_ENTRY_get_object(ent))
     236           0 :                   || !(val=X509_NAME_ENTRY_get_data(ent))
     237           0 :                   || (fn_nid=OBJ_obj2nid(fn))==NID_undef
     238           0 :                   || !(objbuf=OBJ_nid2sn(fn_nid)))
     239           0 :                         continue;
     240           0 :                 buf=(uint8_t *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
     241           0 :                 if(ASN1_STRING_to_UTF8(&buf, val)<=0) continue;
     242           0 :                 name_expand_size=64+strlen(objbuf);
     243           0 :                 if(!(name_expand=(char *)malloc_w(name_expand_size, __func__)))
     244             :                         return -1;
     245           0 :                 snprintf(name_expand, name_expand_size,
     246             :                         "X509_%s_%s", type, objbuf);
     247           0 :                 sanitise(name_expand);
     248           0 :                 sanitise((char*)buf);
     249           0 :                 setenv(name_expand, (char*)buf, 1);
     250           0 :                 free_w(&name_expand);
     251           0 :                 OPENSSL_free(buf);
     252             :         }
     253             :         return 0;
     254             : }
     255             : 
     256           0 : static int setenv_x509_date(ASN1_TIME *tm, const char *env)
     257             : {
     258           0 :         BIO *bio_out=NULL;
     259           0 :         BUF_MEM *bptr=NULL;
     260           0 :         char tmpbuf[256]="";
     261           0 :         if(!(bio_out=BIO_new(BIO_s_mem())))
     262             :         {
     263           0 :                 log_out_of_memory(__func__);
     264           0 :                 return -1;
     265             :         }
     266           0 :         ASN1_TIME_print(bio_out, tm);
     267           0 :         BIO_get_mem_ptr(bio_out, &bptr);
     268           0 :         BIO_gets(bio_out, tmpbuf, sizeof(tmpbuf)-1);
     269           0 :         BIO_free_all(bio_out);
     270           0 :         sanitise(tmpbuf);
     271           0 :         setenv(env, (char*)tmpbuf, 1);
     272           0 :         return 0;
     273             : }
     274             : 
     275           0 : static int setenv_x509_serialnumber(ASN1_INTEGER *i, const char *env)
     276             : {
     277           0 :         BIO *bio_out=NULL;
     278           0 :         BUF_MEM *bptr=NULL;
     279           0 :         char tmpbuf[256]="";
     280           0 :         if(!(bio_out=BIO_new(BIO_s_mem())))
     281             :         {
     282           0 :                 log_out_of_memory(__func__);
     283           0 :                 return -1;
     284             :         }
     285           0 :         i2a_ASN1_INTEGER(bio_out, i);
     286           0 :         BIO_get_mem_ptr(bio_out, &bptr);
     287           0 :         BIO_gets(bio_out, tmpbuf, sizeof(tmpbuf)-1);
     288           0 :         BIO_free_all(bio_out);
     289           0 :         sanitise(tmpbuf);
     290           0 :         setenv(env, (char*)tmpbuf, 1);
     291           0 :         return 0;
     292             : }
     293             : #endif
     294             : 
     295           0 : int ssl_check_cert(SSL *ssl, struct conf **confs, struct conf **cconfs)
     296             : {
     297           0 :         X509 *peer;
     298           0 :         int result;
     299           0 :         char tmpbuf[256]="";
     300           0 :         const char *ssl_peer_cn=get_string(cconfs[OPT_SSL_PEER_CN]);
     301             : 
     302           0 :         if(!ssl_peer_cn)
     303             :         {
     304           0 :                 logp("ssl_peer_cn not set.\n");
     305           0 :                 return -1;
     306             :         }
     307             : 
     308           0 :         SSL_CIPHER_description(SSL_get_current_cipher(ssl),
     309             :                 tmpbuf, sizeof(tmpbuf));
     310           0 :         logp("SSL is using cipher: %s\n", tmpbuf);
     311           0 :         if(!(peer=SSL_get_peer_certificate(ssl)))
     312             :         {
     313           0 :                 logp("Could not get peer certificate.\n");
     314           0 :                 return -1;
     315             :         }
     316           0 :         result=SSL_get_verify_result(ssl);
     317           0 :         if(result!=X509_V_OK)
     318             :         {
     319           0 :                 logp_ssl_err("Certificate doesn't verify (%d).\n", result);
     320           0 :                 return -1;
     321             :         }
     322             : 
     323           0 :         X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
     324             :                 NID_commonName, tmpbuf, sizeof(tmpbuf));
     325           0 :         if(strcasecmp(tmpbuf, ssl_peer_cn))
     326             :         {
     327           0 :                 logp("cert common name doesn't match configured ssl_peer_cn\n");
     328           0 :                 logp("'%s'!='%s'\n", tmpbuf, ssl_peer_cn);
     329           0 :                 return -1;
     330             :         }
     331             : 
     332             : #ifndef HAVE_WIN32
     333             :         // Check the peer certificate against the CRL list only if set
     334             :         // in the configuration file. Thus if not set it is not
     335             :         // breaking the 'ssl_extra_checks_script' configuration.
     336           0 :         if(confs && ca_x509_verify_crl(confs, peer, ssl_peer_cn))
     337             :                 return -1;
     338             : 
     339           0 :         if(setenv_x509(X509_get_subject_name(peer), "PEER")
     340           0 :           || setenv_x509(X509_get_issuer_name(peer), "ISSUER"))
     341           0 :                 return -1;
     342             : 
     343           0 :         if(setenv_x509_date(X509_get_notBefore(peer), "X509_PEER_NOT_BEFORE")
     344           0 :           || setenv_x509_date(X509_get_notAfter(peer), "X509_PEER_NOT_AFTER"))
     345           0 :                 return -1;
     346             : 
     347           0 :         if(setenv_x509_serialnumber(X509_get_serialNumber(peer),
     348             :                 "X509_PEER_SERIALNUMBER"))
     349             :                         return -1;
     350             : #endif
     351             :         //if((comp=SSL_get_current_compression(ssl)))
     352             :         //      logp("SSL is using compression: %s\n", comp->name);
     353             : 
     354             :         return 0;
     355             : }

Generated by: LCOV version 1.16