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