1 /* $Id$ */
2 
3 /*
4  *
5  * Copyright (C) 2005 David Mazieres (dm@uun.org)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2, or (at
10  * your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20  * USA
21  *
22  */
23 
24 #include "asmtpd.h"
25 #include "async_ssl.h"
26 
27 static bool ssl_initialized;
28 static u_int64_t ssl_initno;
29 static SSL_CTX *ctx;
30 static bssstr ssl_randfile;
31 
32 static void
ssl_shutdown()33 ssl_shutdown ()
34 {
35   if (ssl_randfile) {
36     RAND_write_file (ssl_randfile);
37     ssl_randfile = NULL;
38   }
39 }
40 
41 static u_int64_t ssl_tmpkey_initno;
42 static RSA *ssl_tmpkey_key;
43 timecb_t *ssl_tmpkey_tmo;
44 static void
45 ssl_tmpkey_erase (bool timedout = false)
46 {
47   if (!timedout && ssl_tmpkey_tmo)
48     timecb_remove (ssl_tmpkey_tmo);
49   ssl_tmpkey_tmo = NULL;
50   RSA_free (ssl_tmpkey_key);
51   ssl_tmpkey_key = NULL;
52 }
53 static RSA *
ssl_tmpkey(SSL * ssl,int exp,int keylen)54 ssl_tmpkey (SSL *ssl, int exp, int keylen)
55 {
56   if (ssl_tmpkey_initno != opt->configno)
57     ssl_tmpkey_erase ();
58 
59   if (ssl_tmpkey_key)
60     return ssl_tmpkey_key;
61 
62   BIGNUM *bne = BN_new ();
63   BN_set_word (bne, 17);
64   RSA_generate_key_ex (ssl_tmpkey_key, keylen, bne, NULL);
65   BN_free (bne);
66 
67   if (!ssl_tmpkey_tmo)
68     ssl_tmpkey_tmo = delaycb (3600, wrap (ssl_tmpkey_erase, true));
69   return ssl_tmpkey_key;
70 }
71 
72 static DH *
ssl_dhparm(SSL *,int exp,int len)73 ssl_dhparm (SSL *, int exp, int len)
74 {
75   static qhash<int, DH *> parmtab;
76   if (DH **dhp = parmtab[len])
77     return *dhp;
78 
79   DH *dh = NULL;
80   str cachefile = strbuf ("%s/dh%d.pem", opt->etcdir.cstr (), len);
81   if (FILE *fp = fopen (cachefile, "r")) {
82     dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
83     fclose (fp);
84   }
85 
86   if (!dh) {
87     warn << "Generating " << len << "-bit DH parameters... ";
88     err_flush ();
89     dh = DH_new ();
90     DH_generate_parameters_ex (dh, len, 2, NULL);
91     if (!dh) {
92       warn << "failed: " << ssl_err () << "\n";
93       DH_free (dh);
94       return NULL;
95     }
96     warnx << "done\n";
97 
98     int fd = open (cachefile, O_CREAT|O_EXCL|O_WRONLY, 0644);
99     if (fd >= 0) {
100       if (FILE *fp = fdopen (fd, "w")) {
101 	PEM_write_DHparams (fp, dh);
102 	fclose (fp);
103       }
104       else
105 	close (fd);
106     }
107   }
108 
109   parmtab.insert (len, dh);
110   return dh;
111 }
112 
113 static int
verify_cb(int,X509_STORE_CTX *)114 verify_cb (int, X509_STORE_CTX *)
115 {
116   return 1;
117 }
118 
119 bool
ssl_init()120 ssl_init ()
121 {
122   if (ssl_initno == opt->configno)
123     return opt->ssl_status > 0;
124   opt->ssl_status = -1;
125   ssl_initno = opt->configno;
126 
127   ssl_tmpkey_erase ();
128 
129   if (!opt->ssl)
130     return false;
131 
132   struct stat sb;
133   if (stat (opt->ssl_key, &sb) < 0) {
134     if (errno == ENOENT)
135       warn << "STARTTLS disabled (no file " << opt->ssl_key << ")\n";
136     else
137       warn << opt->ssl_key << ":  " << strerror (errno) << "\n";
138     return false;
139   }
140   if (sb.st_mode & 044)
141     warn << "DANGER: " << opt->ssl_key << " should be read-protected\n";
142 
143   if (!ssl_initialized) {
144     ssl_initialized = true;
145     SSL_load_error_strings ();
146     SSL_library_init ();
147 #ifdef SFS_DEV_RANDOM
148     if (RAND_load_file (SFS_DEV_RANDOM, 1024) <= 0)
149       warn << "DANGER: " << SFS_DEV_RANDOM ": " << ssl_err () << "\n";
150 #else /* !SFS_DEV_RANDOM */
151     ssl_randfile = opt->etcdir << "/.rnd";
152     if (RAND_load_file (ssl_randfile, 1024) <= 0)
153       warn << "DANGER: " << ssl_randfile << ": " << ssl_err () << "\n";
154 #endif /* !SFS_DEV_RANDOM */
155     atexit (ssl_shutdown);
156   }
157   else if (ssl_randfile)
158     RAND_write_file (ssl_randfile);
159 
160   if (ctx)
161     SSL_CTX_free (ctx);
162   ctx = SSL_CTX_new (SSLv23_server_method ());
163   if (!ctx) {
164     warn << "SSL_CTX_new: " << ssl_err () << "\n";
165     return false;
166   }
167 
168   bool verify = true;
169   if (SSL_CTX_load_verify_locations (ctx, opt->ssl_ca, NULL) <= 0) {
170     warn << opt->ssl_ca << ": " << ssl_err () << "\n";
171     verify = false;
172   }
173   if (verify)
174     SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, verify_cb);
175 
176   if (!access (opt->ssl_crl, 0)) {
177     X509_STORE *store = SSL_CTX_get_cert_store (ctx);
178     X509_LOOKUP *lookup;
179     if ((lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file ()))
180 	&& (X509_load_crl_file(lookup, opt->ssl_crl, X509_FILETYPE_PEM) == 1))
181       X509_STORE_set_flags(store, (X509_V_FLAG_CRL_CHECK |
182 				   X509_V_FLAG_CRL_CHECK_ALL));
183   }
184 
185   if (SSL_CTX_use_certificate_file (ctx, opt->ssl_cert,
186 				    SSL_FILETYPE_PEM) <= 0) {
187     warn << opt->ssl_cert << ": " << ssl_err () << "\n";
188     return false;
189   }
190 
191   if (SSL_CTX_use_PrivateKey_file (ctx, opt->ssl_key, SSL_FILETYPE_PEM) <= 0) {
192     warn << opt->ssl_key << ": " << ssl_err () << "\n";
193     return false;
194   }
195 
196   if (SSL_CTX_check_private_key (ctx) <= 0) {
197     warn << opt->ssl_key << ": " << ssl_err () << "\n";
198     return false;
199   }
200 
201   SSL_CTX_set_options (ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
202   if (opt->ssl_ciphers
203       && SSL_CTX_set_cipher_list (ctx, opt->ssl_ciphers) <= 0) {
204     warn << "Cipher list " << opt->ssl_ciphers << ": " << ssl_err () << "\n";
205     return false;
206   }
207 
208   SSL_CTX_set_tmp_rsa_callback (ctx, ssl_tmpkey);
209   SSL_CTX_set_tmp_dh_callback (ctx, ssl_dhparm);
210 
211   u_char sessid[SSL_MAX_SSL_SESSION_ID_LENGTH];
212   if (RAND_bytes (sessid, sizeof (sessid)) >= 0)
213     SSL_CTX_set_session_id_context (ctx, sessid, sizeof (sessid));
214 
215   opt->ssl_status = 1;
216   return true;
217 }
218 
219 
220 str
helo_starttls()221 smtpd::helo_starttls ()
222 {
223   if (!encrypted && !auth_user && opt->ssl_status > 0)
224     return "250-STARTTLS\r\n";
225   return "";
226 }
227 
228 void
cmd_starttls(str cmd,str arg)229 smtpd::cmd_starttls (str cmd, str arg)
230 {
231   aiossl *ssl;
232   if (encrypted || auth_user || opt->ssl_status <= 0
233       || !(ssl = dynamic_cast<aiossl *> (aio.get ()))) {
234     respond ("502 command not implemented\r\n");
235     return;
236   }
237 
238   reset ();
239   aio << "220 Starting TLS\r\n";
240   ssl->startssl (ctx, true);
241   encrypted = true;
242 
243   ssl->verify_cb (wrap (this, &smtpd::set_quota_user));
244 
245   cmdwait = true;
246   aio->readline (wrap (this, &smtpd::getcmd));
247 }
248 
249 void
set_quota_user()250 smtpd::set_quota_user ()
251 {
252   if (!encrypted)
253     return;
254   aiossl *ssl = dynamic_cast<aiossl *> (aio.get ());
255   if (ssl && ssl->subject) {
256     quota_user = ssl->subject;
257     if (opt->ssl >= 2 && trust < TRUST_AUTH)
258       trust = TRUST_AUTH;
259   }
260 }
261 
262 void
received_starttls(strbuf r)263 smtpd::received_starttls (strbuf r) const
264 {
265   if (!encrypted)
266     return;
267   aiossl *ssl = dynamic_cast<aiossl *> (aio.get ());
268   if (!ssl || !ssl->cipher)
269     return;
270 
271   r << "    (";
272   if (const char *vers = SSL_get_cipher_version (ssl->get_ssl ()))
273     r << vers;
274   else
275     r << "SSL";
276   int cipher_bits, alg_bits = 0;
277   cipher_bits = SSL_get_cipher_bits (ssl->get_ssl (), &alg_bits);
278   r << " " << ssl->cipher << " " << cipher_bits << "/" << alg_bits;
279 
280   if (ssl->subject) {
281     r << ",\n    ";
282     if (ssl->issuer)
283       r << " issuer=" << ssl->issuer << ",";
284     r << " subject=" << ssl->subject << ")\n";
285   }
286   else
287     r << ")\n";
288 
289 }
290 
291 void
env_starttls(vec<str> * envp)292 smtpd::env_starttls (vec<str> *envp) const
293 {
294   if (!encrypted)
295     return;
296   aiossl *ssl = dynamic_cast<aiossl *> (aio.get ());
297   if (!ssl || !ssl->cipher)
298     return;
299 
300   envp->push_back (strbuf () << "SSL_CIPHER=" << ssl->cipher);
301 
302   int cipher_bits, alg_bits = 0;
303   cipher_bits = SSL_get_cipher_bits (ssl->get_ssl (), &alg_bits);
304   envp->push_back (strbuf ("SSL_CIPHER_BITS=%d", cipher_bits));
305   envp->push_back (strbuf ("SSL_ALG_BITS=%d", alg_bits));
306 
307   if (const char *vers = SSL_get_cipher_version (ssl->get_ssl ()))
308       envp->push_back (strbuf () << "SSL_VERSION=" << vers);
309 
310   if (ssl->issuer)
311     envp->push_back (strbuf () << "SSL_ISSUER=" << ssl->issuer);
312   if (ssl->issuer_dn)
313     envp->push_back (strbuf () << "SSL_ISSUER_DN=" << ssl->issuer_dn);
314   if (ssl->subject)
315     envp->push_back (strbuf () << "SSL_SUBJECT=" << ssl->subject);
316   if (ssl->subject_dn)
317     envp->push_back (strbuf () << "SSL_SUBJECT_DN=" << ssl->subject_dn);
318 }
319