LCOV - code coverage report
Current view: top level - src/client - ca.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 123 0.0 %
Date: 2022-08-30 22:36:43 Functions: 0 4 0.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../asfd.h"
       3             : #include "../async.h"
       4             : #include "../cmd.h"
       5             : #include "../conf.h"
       6             : #include "../conffile.h"
       7             : #include "../fsops.h"
       8             : #include "../handy.h"
       9             : #include "../iobuf.h"
      10             : #include "../log.h"
      11             : #include "../run_script.h"
      12             : #include "cvss.h"
      13             : #include "ca.h"
      14             : 
      15             : #ifdef HAVE_WIN32
      16             : // Want to avoid giving standard users access to the conf files, otherwise
      17             : // they can get access to all the backed up files, which may include files
      18             : // they shouldn't be able to get.
      19             : static void hack_windows_perms(const char *path)
      20             : {
      21             :         char cmd[512]="";
      22             :         snprintf(cmd, sizeof(cmd), "icacls.exe \"%s\" /inheritance:r /grant:r Administrators:F SYSTEM:F", path);
      23             :         system(cmd);
      24             : }
      25             : #endif
      26             : 
      27           0 : static int generate_key_and_csr(struct asfd *asfd,
      28             :         struct conf **confs, const char *csr_path)
      29             : {
      30           0 :         int a=0;
      31             :         const char *args[12];
      32           0 :         const char *ca_burp_ca=get_string(confs[OPT_CA_BURP_CA]);
      33           0 :         const char *cname=get_string(confs[OPT_CNAME]);
      34           0 :         const char *ssl_key=get_string(confs[OPT_SSL_KEY]);
      35             : 
      36           0 :         logp("Generating SSL key and certificate signing request\n");
      37           0 :         logp("Running '%s --key --keypath %s --request --requestpath %s --name %s'\n", ca_burp_ca, ssl_key, csr_path, cname);
      38             : #ifdef HAVE_WIN32
      39             :         win32_enable_backup_privileges();
      40             : #else
      41             :         // FIX THIS
      42           0 :         signal(SIGPIPE, SIG_IGN);
      43             : #endif
      44           0 :         args[a++]=ca_burp_ca;
      45           0 :         args[a++]="--key";
      46           0 :         args[a++]="--keypath";
      47           0 :         args[a++]=ssl_key;
      48           0 :         args[a++]="--request";
      49           0 :         args[a++]="--requestpath";
      50           0 :         args[a++]=csr_path;
      51           0 :         args[a++]="--name";
      52           0 :         args[a++]=cname;
      53           0 :         args[a++]=NULL;
      54           0 :         if(run_script(asfd, args, NULL, confs, 1 /* wait */,
      55             :                 0, 0 /* do not use logp - stupid openssl prints lots of dots
      56             :                         one at a time with no way to turn it off */))
      57             :         {
      58           0 :                 logp("error when running '%s --key --keypath %s --request --requestpath %s --name %s'\n",
      59             :                         ca_burp_ca, ssl_key, csr_path, cname);
      60           0 :                 return -1;
      61             :         }
      62             : 
      63             : #ifdef HAVE_WIN32
      64             :         hack_windows_perms(ssl_key);
      65             :         hack_windows_perms(csr_path);
      66             : #endif
      67             : 
      68             :         return 0;
      69             : }
      70             : 
      71             : /* Rewrite the conf file with the ssl_peer_cn value changed to what the
      72             :    server told us it should be. */
      73           0 : static int rewrite_client_conf(struct conf **confs)
      74             : {
      75           0 :         int ret=-1;
      76           0 :         char p[32]="";
      77           0 :         struct fzp *dp=NULL;
      78           0 :         struct fzp *sp=NULL;
      79           0 :         char *tmp=NULL;
      80           0 :         char buf[4096]="";
      81           0 :         const char *conffile=get_string(confs[OPT_CONFFILE]);
      82           0 :         const char *ssl_peer_cn=get_string(confs[OPT_SSL_PEER_CN]);
      83             : 
      84           0 :         snprintf(p, sizeof(p), ".%d", getpid());
      85           0 :         if(!(tmp=prepend(conffile, p)))
      86             :                 goto end;
      87           0 :         if(!(sp=fzp_open(conffile, "rb"))
      88           0 :           || !(dp=fzp_open(tmp, "wb")))
      89             :                 goto end;
      90             : 
      91           0 :         while(fzp_gets(sp, buf, sizeof(buf)))
      92             :         {
      93           0 :                 char *copy=NULL;
      94           0 :                 char *field=NULL;
      95           0 :                 char *value=NULL;
      96           0 :                 int r=0;
      97             : 
      98           0 :                 if(!(copy=strdup_w(buf, __func__)))
      99             :                         goto end;
     100           0 :                 if(conf_get_pair(buf, &field, &value, &r)
     101           0 :                   || !field || !value
     102           0 :                   || strcmp(field, "ssl_peer_cn"))
     103             :                 {
     104           0 :                         fzp_printf(dp, "%s", copy);
     105           0 :                         free_w(&copy);
     106           0 :                         continue;
     107             :                 }
     108           0 :                 free_w(&copy);
     109             : #ifdef HAVE_WIN32
     110             :                 fzp_printf(dp, "ssl_peer_cn = %s\r\n", ssl_peer_cn);
     111             : #else
     112           0 :                 fzp_printf(dp, "ssl_peer_cn = %s\n", ssl_peer_cn);
     113             : #endif
     114             :         }
     115           0 :         fzp_close(&sp);
     116           0 :         if(fzp_close(&dp))
     117             :         {
     118           0 :                 logp("error closing %s in %s\n", tmp, __func__);
     119           0 :                 goto end;
     120             :         }
     121             : 
     122           0 :         if(files_equal(conffile, tmp, 0/*compressed*/))
     123             :         {
     124             :                 // No need to overwrite if there were no differences.
     125           0 :                 ret=0;
     126           0 :                 unlink(tmp);
     127           0 :                 goto end;
     128             :         }
     129             : 
     130           0 :         logp("Rewriting conf file: %s\n", conffile);
     131             : 
     132             :         // Nasty race conditions going on here. However, the new config
     133             :         // file will get left behind, so at worse you will have to move
     134             :         // the new file into the correct place by hand. Or delete everything
     135             :         // and start again.
     136             : #ifdef HAVE_WIN32
     137             :         // Need to delete the destination, or Windows gets upset.
     138             :         unlink(conffile);
     139             : #endif
     140           0 :         if(do_rename(tmp, conffile)) goto end;
     141             : 
     142           0 :         ret=0;
     143             : end:
     144           0 :         fzp_close(&sp);
     145           0 :         fzp_close(&dp);
     146           0 :         if(ret)
     147             :         {
     148           0 :                 logp("%s with %s failed\n", __func__, conffile);
     149           0 :                 unlink(tmp);
     150             :         }
     151           0 :         free_w(&tmp);
     152           0 :         return ret;
     153             : }
     154             : 
     155           0 : static enum asl_ret csr_client_func(struct asfd *asfd,
     156             :         struct conf **confs, __attribute__((unused)) void *param)
     157             : {
     158           0 :         if(strncmp_w(asfd->rbuf->buf, "csr ok:"))
     159             :         {
     160           0 :                 iobuf_log_unexpected(asfd->rbuf, __func__);
     161           0 :                 return ASL_END_ERROR;
     162             :         }
     163             :         // The server appends its name after 'csr ok:'
     164           0 :         if(set_string(confs[OPT_SSL_PEER_CN], 
     165           0 :                 asfd->rbuf->buf+strlen("csr ok:")))
     166             :                         return ASL_END_ERROR;
     167           0 :         return ASL_END_OK;
     168             : }
     169             : 
     170             : /* Return 1 for everything OK, signed and returned, -1 for error, 0 for
     171             :    nothing done. */
     172           0 : int ca_client_setup(struct asfd *asfd, struct conf **confs)
     173             : {
     174           0 :         int ret=-1;
     175             :         struct stat statp;
     176           0 :         char csr_path[256]="";
     177           0 :         char ssl_cert_tmp[512]="";
     178           0 :         char ssl_cert_ca_tmp[512]="";
     179           0 :         const char *ca_burp_ca=get_string(confs[OPT_CA_BURP_CA]);
     180           0 :         const char *ca_csr_dir=get_string(confs[OPT_CA_CSR_DIR]);
     181           0 :         const char *cname=get_string(confs[OPT_CNAME]);
     182           0 :         const char *ssl_key=get_string(confs[OPT_SSL_KEY]);
     183           0 :         const char *ssl_cert=get_string(confs[OPT_SSL_CERT]);
     184           0 :         const char *ssl_cert_ca=get_string(confs[OPT_SSL_CERT_CA]);
     185           0 :         struct cntr *cntr=get_cntr(confs);
     186             : 
     187             :         /* Store setting, compared later to decide whether to rewrite the config */
     188           0 :         char *ssl_peer_cn_old=strdup_w(get_string(confs[OPT_SSL_PEER_CN]), __func__);
     189           0 :         if(!ssl_peer_cn_old) goto end;
     190             : 
     191             :         // Do not continue if we have one of the following things not set.
     192           0 :         if(  !ca_burp_ca
     193           0 :           || !ca_csr_dir
     194           0 :           || !ssl_cert_ca
     195           0 :           || !ssl_cert
     196           0 :           || !ssl_key
     197             :         // Do not try to get a new certificate if we already have a key.
     198           0 :           || !lstat(ssl_key, &statp))
     199             :         {
     200           0 :                 if(asfd->write_str(asfd, CMD_GEN, "nocsr")
     201           0 :                   || asfd_read_expect(asfd, CMD_GEN, "nocsr ok"))
     202             :                 {
     203           0 :                         logp("problem reading from server nocsr\n");
     204           0 :                         goto end;
     205             :                 }
     206           0 :                 logp("nocsr ok\n");
     207           0 :                 ret=0;
     208           0 :                 goto end;
     209             :         }
     210             : 
     211             :         // Tell the server we want to do a signing request and store the servers name in ssl_peer_cn.
     212           0 :         if(asfd->write_str(asfd, CMD_GEN, "csr")
     213           0 :           || asfd->simple_loop(asfd, confs, NULL, __func__, csr_client_func))
     214             :                 goto end;
     215             : 
     216           0 :         logp("Server will sign a certificate request\n");
     217             : 
     218             :         // First need to generate a client key and a certificate signing
     219             :         // request.
     220           0 :         snprintf(csr_path, sizeof(csr_path), "%s/%s.csr", ca_csr_dir, cname);
     221           0 :         if(generate_key_and_csr(asfd, confs, csr_path)) goto end_cleanup;
     222             : 
     223             :         // Then copy the csr to the server.
     224           0 :         if(send_a_file(asfd, csr_path, cntr)) goto end_cleanup;
     225             : 
     226           0 :         snprintf(ssl_cert_tmp, sizeof(ssl_cert_tmp), "%s.%d",
     227             :                 ssl_cert, getpid());
     228           0 :         snprintf(ssl_cert_ca_tmp, sizeof(ssl_cert_ca_tmp), "%s.%d",
     229             :                 ssl_cert_ca, getpid());
     230             : 
     231             :         // The server will then sign it, and give it back.
     232           0 :         if(receive_a_file(asfd, ssl_cert_tmp, cntr)) goto end_cleanup;
     233             :         // The server will also send the CA certificate.
     234           0 :         if(receive_a_file(asfd, ssl_cert_ca_tmp, cntr)) goto end_cleanup;
     235             : 
     236             :         // Possible race condition - the rename can delete the destination
     237             :         // and then fail. Worse case, the user has to rename them by hand.
     238           0 :         if(do_rename(ssl_cert_tmp, ssl_cert)
     239           0 :           || do_rename(ssl_cert_ca_tmp, ssl_cert_ca))
     240             :                 goto end_cleanup;
     241             : 
     242             : #ifdef HAVE_WIN32
     243             :         hack_windows_perms(ssl_cert);
     244             :         hack_windows_perms(ssl_cert_ca);
     245             : #endif
     246             : 
     247             :         // Need to rewrite our configuration file to contain the server
     248             :         // name (ssl_peer_cn) if the name differs from the config file.
     249           0 :         if(strncmp_w(ssl_peer_cn_old, get_string(confs[OPT_SSL_PEER_CN])))
     250             :         {
     251           0 :             if(rewrite_client_conf(confs)) goto end_cleanup;
     252             :         }
     253             : 
     254             :         // My goodness, everything seems to have gone OK. Stand back!
     255             :         ret=1;
     256             : end_cleanup:
     257           0 :         if(ret<0)
     258             :         {
     259             :                 // On error, remove any possibly newly created files, so that
     260             :                 // this function might run again on another go.
     261           0 :                 unlink(csr_path);
     262           0 :                 unlink(ssl_key);
     263           0 :                 unlink(ssl_cert);
     264           0 :                 unlink(ssl_cert_ca);
     265           0 :                 unlink(ssl_cert_tmp);
     266           0 :                 unlink(ssl_cert_ca_tmp);
     267             :         }
     268             : end:
     269           0 :         if(ssl_peer_cn_old) free_w(&ssl_peer_cn_old);
     270           0 :         return ret;
     271             : }

Generated by: LCOV version 1.13