/[cvs]/eggdrop1.8/src/tls.c
ViewVC logotype

Annotation of /eggdrop1.8/src/tls.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2.2.2 - (hide annotations) (download) (as text)
Tue Feb 8 22:06:01 2011 UTC (8 years, 3 months ago) by thommey
Branch: gettext
Changes since 1.2.2.1: +4 -3 lines
File MIME type: text/x-chdr
merge changes from master into gettext

1 pseudo 1.1 /*
2     * tls.c -- handles:
3     * TLS support functions
4     * Certificate handling
5     * OpenSSL initialization and shutdown
6     *
7 thommey 1.2.2.2 * $Id: tls.c,v 1.2.2.1 2010/11/08 10:02:32 pseudo Exp $
8 pseudo 1.1 */
9     /*
10     * Written by Rumen Stoyanov <pseudo@egg6.net>
11     *
12     * Copyright (C) 2010 Eggheads Development Team
13     *
14     * This program is free software; you can redistribute it and/or
15     * modify it under the terms of the GNU General Public License
16     * as published by the Free Software Foundation; either version 2
17     * of the License, or (at your option) any later version.
18     *
19     * This program is distributed in the hope that it will be useful,
20     * but WITHOUT ANY WARRANTY; without even the implied warranty of
21     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22     * GNU General Public License for more details.
23     *
24     * You should have received a copy of the GNU General Public License
25     * along with this program; if not, write to the Free Software
26     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27     */
28    
29     #include "main.h"
30    
31     #ifdef TLS
32    
33     #include <openssl/err.h>
34     #include <openssl/rand.h>
35     #include <openssl/x509v3.h>
36    
37     extern int tls_vfydcc;
38     extern struct dcc_t *dcc;
39    
40     int tls_maxdepth = 9; /* Max certificate chain verification depth */
41     SSL_CTX *ssl_ctx = NULL; /* SSL context object */
42     char *tls_randfile = NULL; /* Random seed file for SSL */
43     char tls_capath[121] = ""; /* Path to trusted CA certificates */
44     char tls_cafile[121] = ""; /* File containing trusted CA certificates */
45     char tls_certfile[121] = ""; /* Our own digital certificate ;) */
46     char tls_keyfile[121] = ""; /* Private key for use with eggdrop */
47     char tls_ciphers[121] = ""; /* A list of ciphers for SSL to use */
48    
49    
50     /* Count allocated memory for SSL. This excludes memory allocated by OpenSSL's
51     * family of malloc functions.
52     */
53     int expmem_tls()
54     {
55     int i, tot;
56     struct threaddata *td = threaddata();
57    
58     /* currently it's only the appdata structs allocated by ssl_handshake() */
59     for (i = 0, tot = 0; i < td->MAXSOCKS; i++)
60     if (!(td->socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)))
61     if (td->socklist[i].ssl && SSL_get_app_data(td->socklist[i].ssl))
62     tot += sizeof(ssl_appdata);
63     return tot;
64     }
65    
66     /* Seeds the PRNG
67     *
68     * Only does something if the system doesn't have enough entropy.
69     * If there is no random file, one will be created either at
70     * $RANDFILE if set or at $HOME/.rnd
71     *
72     * Return value: 0 on success, !=0 on failure.
73     */
74     static int ssl_seed(void)
75     {
76     char stackdata[1024];
77     static char rand_file[120];
78     FILE *fh;
79    
80 pseudo 1.2 #ifdef HAVE_RAND_STATUS
81 pseudo 1.1 if (RAND_status())
82     return 0; /* Status OK */
83     #endif
84     /* If '/dev/urandom' is present, OpenSSL will use it by default.
85     * Otherwise we'll have to generate pseudorandom data ourselves,
86     * using system time, our process ID and some unitialized static
87     * storage.
88     */
89     if ((fh = fopen("/dev/urandom", "r"))) {
90     fclose(fh);
91     return 0;
92     }
93     if (RAND_file_name(rand_file, sizeof(rand_file)))
94     tls_randfile = rand_file;
95     else
96     return 1;
97     if (!RAND_load_file(rand_file, -1)) {
98     /* generate some pseudo random data */
99     unsigned int c;
100     c = time(NULL);
101     RAND_seed(&c, sizeof(c));
102     c = getpid();
103     RAND_seed(&c, sizeof(c));
104     RAND_seed(stackdata, sizeof(stackdata));
105     }
106 pseudo 1.2 #ifdef HAVE_RAND_STATUS
107 pseudo 1.1 if (!RAND_status())
108     return 2; /* pseudo random data still not ehough */
109     #endif
110     return 0;
111     }
112    
113     /* Prepares and initializes SSL stuff
114     *
115     * Creates a context object, supporting SSLv2/v3 & TLSv1 protocols;
116     * Seeds the Pseudo Random Number Generator;
117     * Optionally loads a SSL certifate and a private key.
118     * Tell OpenSSL the location of certificate authority certs
119     *
120     * Return value: 0 on successful initialization, !=0 on failure
121     */
122     int ssl_init()
123     {
124     /* Load SSL and crypto error strings; register SSL algorithms */
125     SSL_load_error_strings();
126     SSL_library_init();
127    
128     if (ssl_seed()) {
129 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("TLS: unable to seed PRNG. Disabling SSL"));
130 pseudo 1.1 ERR_free_strings();
131     return -2;
132     }
133     /* A TLS/SSL connection established with this method will understand all
134     supported protocols (SSLv2, SSLv3, and TLSv1) */
135     if (!(ssl_ctx = SSL_CTX_new(SSLv23_method()))) {
136     debug0(ERR_error_string(ERR_get_error(), NULL));
137 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("TLS: unable to create context. Disabling SSL."));
138 pseudo 1.1 ERR_free_strings();
139     return -1;
140     }
141     /* Load our own certificate and private key. Mandatory for acting as
142     server, because we don't support anonymous ciphers by default. */
143     if (SSL_CTX_use_certificate_chain_file(ssl_ctx, tls_certfile) != 1)
144 pseudo 1.2.2.1 debug1(_("TLS: unable to load own certificate: %s"),
145 pseudo 1.1 ERR_error_string(ERR_get_error(), NULL));
146     if (SSL_CTX_use_PrivateKey_file(ssl_ctx, tls_keyfile,
147     SSL_FILETYPE_PEM) != 1)
148 pseudo 1.2.2.1 debug1(_("TLS: unable to load private key: %s"),
149 pseudo 1.1 ERR_error_string(ERR_get_error(), NULL));
150     if ((tls_capath[0] || tls_cafile[0]) &&
151     !SSL_CTX_load_verify_locations(ssl_ctx, tls_cafile[0] ? tls_cafile : NULL,
152     tls_capath[0] ? tls_capath : NULL))
153 pseudo 1.2.2.1 debug1(_("TLS: unable to set CA certificates location: %s"),
154 pseudo 1.1 ERR_error_string(ERR_get_error(), NULL));
155     /* Let advanced users specify the list of allowed ssl ciphers */
156     if (tls_ciphers[0])
157     if (!SSL_CTX_set_cipher_list(ssl_ctx, tls_ciphers)) {
158     /* this replaces any preset ciphers so an invalid list is fatal */
159 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("TLS: no valid ciphers found. Disabling SSL."));
160 pseudo 1.1 ERR_free_strings();
161     SSL_CTX_free(ssl_ctx);
162     ssl_ctx = NULL;
163     return -3;
164     }
165    
166     return 0;
167     }
168    
169     /* Free the SSL CTX, clean up the mess */
170     void ssl_cleanup()
171     {
172     if (ssl_ctx) {
173     SSL_CTX_free(ssl_ctx);
174     ssl_ctx = NULL;
175     }
176     if (tls_randfile)
177     RAND_write_file(tls_randfile);
178     ERR_free_strings();
179     }
180    
181     char *ssl_fpconv(char *in, char *out)
182     {
183     long len;
184     char *fp;
185     unsigned char *md5;
186    
187     if (!in)
188     return NULL;
189    
190     if ((md5 = string_to_hex(in, &len))) {
191     fp = hex_to_string(md5, len);
192     if (fp) {
193     out = user_realloc(out, strlen(fp) + 1);
194     strcpy(out, fp);
195     OPENSSL_free(md5);
196     OPENSSL_free(fp);
197     return out;
198     }
199     OPENSSL_free(md5);
200     }
201     return NULL;
202     }
203    
204     /* Get the certificate, corresponding to the connection
205     * identified by sock.
206     *
207     * Return value: pointer to a X509 certificate or NULL if we couldn't
208     * look up the certificate.
209     */
210     static X509 *ssl_getcert(int sock)
211     {
212     int i;
213     struct threaddata *td = threaddata();
214    
215     i = findsock(sock);
216     if (i == -1 || !td->socklist[i].ssl)
217     return NULL;
218     return SSL_get_peer_certificate(td->socklist[i].ssl);
219     }
220    
221     /* Get the certificate fingerprint of the connection corresponding
222     * to the socket.
223     *
224     * Return value: ptr to the hexadecimal representation of the fingerprint
225     * or NULL if there's no certificate associated with the connection.
226     */
227     char *ssl_getfp(int sock)
228     {
229     char *p;
230     unsigned i;
231     X509 *cert;
232     static char fp[64];
233     unsigned char md[EVP_MAX_MD_SIZE];
234    
235     if (!(cert = ssl_getcert(sock)))
236     return NULL;
237     if (!X509_digest(cert, EVP_sha1(), md, &i))
238     return NULL;
239     if (!(p = hex_to_string(md, i)))
240     return NULL;
241     strncpyz(fp, p, sizeof fp);
242     OPENSSL_free(p);
243     return fp;
244     }
245    
246     /* Get the UID field from the certificate subject name.
247     * The certificate is looked up using the socket of the connection.
248     *
249     * Return value: Pointer to the uid string or NULL if not found
250     */
251     char *ssl_getuid(int sock)
252     {
253     int idx;
254     X509 *cert;
255     X509_NAME *subj;
256     ASN1_STRING *name;
257    
258     if (!(cert = ssl_getcert(sock)))
259     return NULL;
260     /* Get the subject name */
261     if (!(subj = X509_get_subject_name(cert)))
262     return NULL;
263    
264     /* Get the first UID */
265     idx = X509_NAME_get_index_by_NID(subj, NID_userId, -1);
266     if (idx == -1)
267     return NULL;
268     name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, idx));
269     /* Extract the contents, assuming null-terminated ASCII string */
270     return (char *) ASN1_STRING_data(name);
271     }
272    
273     /* Compare the peer's host with their Common Name or dnsName found in
274     * it's certificate. Only the first domain component of cn is allowed to
275     * be a wildcard '*'. The non-wildcard characters are compared ignoring
276     * case.
277     *
278     * Return value: 1 if cn matches host, 0 otherwise.
279     */
280     static int ssl_hostmatch(char *cn, char *host)
281     {
282     char *p, *q, *r;
283    
284     if ((r = strchr(cn + 1, '.')) && r[-1] == '*' && strchr(r, '.')) {
285     for (p = cn, q = host; *p != '*'; p++, q++)
286     if (toupper(*p) != toupper(*q))
287     return 0;
288    
289     if (!(p = strchr(host, '.')) || strcasecmp(p, r))
290     return 0;
291     return 1;
292     }
293    
294     /* First domain component is not a wildcard and they aren't allowed
295     elsewhere, so just compare the strings. */
296     return strcasecmp(cn, host) ? 0 : 1;
297     }
298    
299     /* Confirm the peer identity, by checking if the certificate subject
300     * matches the peer's DNS name or IP address. Matching is performed in
301     * accordance with RFC 2818:
302     *
303     * If the certificate has a subjectAltName extension, all names of type
304     * IPAddress or dnsName present there, will be compared to data->host,
305     * depending on it's contents.
306     * In case there's no subjectAltName extension, commonName (CN) parts
307     * of the certificate subject field will be used instead of IPAddress
308     * and dnsName entries. For IP addresses, common names must contain IPs
309     * in presentation format (1.2.3.4 or 2001:DB8:15:dead::)
310     * Finally, if no subjectAltName or common names are present, the
311     * certificate is considered to not match the peer.
312     *
313     * The structure of X509 certificates and all fields referenced above
314     * are described in RFC 5280.
315     *
316     * The certificate must be pointed by cert and the peer's host must be
317     * placed in data->host. The format is a regular DNS name or an IP in
318     * presentation format (see above).
319     *
320     * Return value: 1 if the certificate matches the peer, 0 otherwise.
321     */
322     static int ssl_verifycn(X509 *cert, ssl_appdata *data)
323     {
324     char *cn;
325     int crit = 0, match = 0;
326     ASN1_OCTET_STRING *ip;
327     GENERAL_NAMES *altname; /* SubjectAltName ::= GeneralNames */
328    
329     ip = a2i_IPADDRESS(data->host); /* check if it's an IP or a hostname */
330     if ((altname = X509_get_ext_d2i(cert, NID_subject_alt_name, &crit, NULL))) {
331     GENERAL_NAME *gn;
332    
333     /* Loop through the general names in altname and pick these
334     of type ip address or dns name */
335     while (!match && (gn = sk_GENERAL_NAME_pop(altname))) {
336     /* if the peer's host is an IP, we're only interested in
337     matching against iPAddress general names, otherwise
338     we'll only look for dnsName's */
339     if (ip) {
340     if (gn->type == GEN_IPADD)
341     match = !ASN1_STRING_cmp(gn->d.ip, ip);
342     } else if (gn->type == GEN_DNS) {
343     /* IA5string holds ASCII data */
344     cn = (char *) ASN1_STRING_data(gn->d.ia5);
345     match = ssl_hostmatch(cn, data->host);
346     }
347     }
348     sk_GENERAL_NAME_free(altname);
349     } else { /* no subjectAltName, try to match against the subject CNs */
350     X509_NAME *subj; /* certificate subject */
351    
352     /* the following is just for information */
353     switch (crit) {
354     case 0:
355 pseudo 1.2.2.1 debug0(_("TLS: X509 subjectAltName cannot be decoded"));
356 pseudo 1.1 break;
357     case -1:
358 pseudo 1.2.2.1 debug0(_("TLS: X509 has no subjectAltName extension"));
359 pseudo 1.1 break;
360     case -2:
361 pseudo 1.2.2.1 debug0(_("TLS: X509 has multiple subjectAltName extensions"));
362 pseudo 1.1 }
363     /* no subject name either? A completely broken certificate :) */
364     if (!(subj = X509_get_subject_name(cert))) {
365 pseudo 1.2.2.1 putlog(data->loglevel, "*", _("TLS: peer certificate has no subject: %s"),
366 pseudo 1.1 data->host);
367     match = 0;
368     } else { /* we have a subject name, look at it */
369     int pos = -1;
370     ASN1_STRING *name;
371    
372     /* Look for commonName attributes in the subject name */
373     pos = X509_NAME_get_index_by_NID(subj, NID_commonName, pos);
374     if (pos == -1) /* sorry */
375 pseudo 1.2.2.1 putlog(data->loglevel, "*", _("TLS: Peer has no common names and "
376     "no subjectAltName extension. Verification failed."));
377 pseudo 1.1 /* Loop through all common names which may be present in the subject
378     name until we find a match. */
379     while (!match && pos != -1) {
380     name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, pos));
381     cn = (char *) ASN1_STRING_data(name);
382     if (ip)
383 pseudo 1.2.2.1 match = a2i_IPADDRESS(cn) ? (ASN1_STRING_cmp(ip, a2i_IPADDRESS(cn)) ?
384     0 : 1) : 0;
385 pseudo 1.1 else
386     match = ssl_hostmatch(cn, data->host);
387     pos = X509_NAME_get_index_by_NID(subj, NID_commonName, pos);
388     }
389     }
390     }
391    
392     if (ip)
393     ASN1_OCTET_STRING_free(ip);
394     return match;
395     }
396    
397     /* Extract a human readable version of a X509_NAME and put the result
398     * into a nmalloc'd buffer.
399     * The X509_NAME structure is used for example in certificate subject
400     * and issuer names.
401     *
402     * You need to nfree() the returned pointer.
403     */
404     static char *ssl_printname(X509_NAME *name)
405     {
406     int len;
407     char *data, *buf;
408     BIO *bio = BIO_new(BIO_s_mem());
409    
410     /* X509_NAME_oneline() is easier and shorter, but is deprecated and
411     the manual discourages it's usage, so let's not be lazy ;) */
412     X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE & ~XN_FLAG_SPC_EQ);
413     len = BIO_get_mem_data(bio, &data) + 1;
414     buf = nmalloc(len);
415     strncpyz(buf, data, len);
416     BIO_free(bio);
417     return buf;
418     }
419    
420     /* Print the time from a ASN1_UTCTIME object in standard format i.e.
421     * Nov 21 23:59:00 1996 GMT and store it in a nmalloc'd buffer.
422     * The ASN1_UTCTIME structure is what's used for example with
423     * certificate validity dates.
424     *
425     * You need to nfree() the returned pointer.
426     */
427     static char *ssl_printtime(ASN1_UTCTIME *t)
428     {
429     int len;
430     char *data, *buf;
431     BIO *bio = BIO_new(BIO_s_mem());
432    
433     ASN1_UTCTIME_print(bio, t);
434     len = BIO_get_mem_data(bio, &data) + 1;
435     buf = nmalloc(len);
436     strncpyz(buf, data, len);
437     BIO_free(bio);
438     return buf;
439     }
440    
441     /* Print the value of an ASN1_INTEGER in hexadecimal format.
442     * A typical use for this is to display certificate serial numbers.
443     * As usual, we use a memory BIO.
444     *
445     * You need to nfree() the returned pointer.
446     */
447     static char *ssl_printnum(ASN1_INTEGER *i)
448     {
449     int len;
450     char *data, *buf;
451     BIO *bio = BIO_new(BIO_s_mem());
452    
453     i2a_ASN1_INTEGER(bio, i);
454     len = BIO_get_mem_data(bio, &data) + 1;
455     buf = nmalloc(len);
456     strncpyz(buf, data, len);
457     BIO_free(bio);
458     return buf;
459     }
460    
461     /* Show the user all relevant information about a certificate: subject,
462     * issuer, validity dates and fingerprints.
463     */
464     static void ssl_showcert(X509 *cert, int loglev)
465     {
466     char *buf, *from, *to;
467     X509_NAME *name;
468     unsigned int len;
469     unsigned char md[EVP_MAX_MD_SIZE];
470    
471     /* Subject and issuer names */
472     if ((name = X509_get_subject_name(cert))) {
473     buf = ssl_printname(name);
474 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: certificate subject: %s"), buf);
475 pseudo 1.1 nfree(buf);
476     } else
477 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: cannot get subject name from certificate!"));
478 pseudo 1.1 if ((name = X509_get_issuer_name(cert))) {
479     buf = ssl_printname(name);
480 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: certificate issuer: %s"), buf);
481 pseudo 1.1 nfree(buf);
482     } else
483 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: cannot get issuer name from certificate!"));
484 pseudo 1.1
485     /* Fingerprints */
486     X509_digest(cert, EVP_md5(), md, &len); /* MD5 hash */
487     if (len <= sizeof(md)) {
488     buf = hex_to_string(md, len);
489 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: certificate MD5 Fingerprint: %s"), buf);
490 pseudo 1.1 OPENSSL_free(buf);
491     }
492     X509_digest(cert, EVP_sha1(), md, &len); /* SHA-1 hash */
493     if (len <= sizeof(md)) {
494     buf = hex_to_string(md, len);
495 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: certificate SHA1 Fingerprint: %s"), buf);
496 pseudo 1.1 OPENSSL_free(buf);
497     }
498    
499     /* Validity time */
500     from = ssl_printtime(X509_get_notBefore(cert));
501     to = ssl_printtime(X509_get_notAfter(cert));
502 pseudo 1.2.2.1 putlog(loglev, "*", _("TLS: certificate valid from %s to %s"), from, to);
503 pseudo 1.1 nfree(from);
504 pseudo 1.2.2.1 nfree(to);
505 pseudo 1.1 }
506    
507     /* Certificate validation callback
508     *
509     * Check if the certificate given is valid with respect to the
510     * ssl-verify config variable. This makes it possible to allow
511     * self-signed certificates and is also a convenient place to
512     * extract a certificate summary.
513     *
514     * Return value: 1 - validation passed, 0 - invalid cert
515     */
516     int ssl_verify(int ok, X509_STORE_CTX *ctx)
517     {
518     SSL *ssl;
519     X509 *cert;
520     ssl_appdata *data;
521     int err, depth;
522    
523     /* get cert, callbacks, error codes, etc. */
524     depth = X509_STORE_CTX_get_error_depth(ctx);
525     cert = X509_STORE_CTX_get_current_cert(ctx);
526     ssl = X509_STORE_CTX_get_ex_data(ctx,
527     SSL_get_ex_data_X509_STORE_CTX_idx());
528     data = (ssl_appdata *) SSL_get_app_data(ssl);
529     err = X509_STORE_CTX_get_error(ctx);
530    
531     /* OpenSSL won't explicitly generate this error; instead it will
532     * report missing certificates. Refer to SSL_CTX_set_verify(3)
533     * manual for details
534     */
535     if (depth > tls_maxdepth) {
536     ok = 0;
537     err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
538    
539     /* depth 0 is actually the peer certificate. We do all custom
540     * verification here and leave the rest of the certificate chain
541     * to OpenSSL's built in procedures.
542     */
543     } else if (!depth) {
544     /* OpenSSL doesn't perform subject name verification. We need to do
545     * it ourselves. We check here for validity even if it's not requested
546     * in order to be able to warn the user.
547     */
548     if (!(data->flags & TLS_DEPTH0) && !ssl_verifycn(cert, data) &&
549     (data->verify & TLS_VERIFYCN)) {
550 pseudo 1.2.2.1 putlog(data->loglevel, "*", _("TLS: certificate validation failed. "
551     "Certificate subject does not match peer."));
552 pseudo 1.1 return 0;
553     }
554     data->flags |= TLS_DEPTH0;
555     /* Allow exceptions for certain common verification errors, if the
556     * caller requested so. A lot of servers provide completely invalid
557     * certificates unuseful for any authentication.
558     */
559     if (!ok || data->verify)
560     if (((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) &&
561     (data->verify & TLS_VERIFYISSUER)) ||
562     ((err == X509_V_ERR_CERT_REVOKED) &&
563     (data->verify & TLS_VERIFYREV)) ||
564     ((err == X509_V_ERR_CERT_NOT_YET_VALID) &&
565     (data->verify & TLS_VERIFYFROM)) ||
566     ((err == X509_V_ERR_CERT_HAS_EXPIRED) &&
567     (data->verify & TLS_VERIFYTO))) {
568 pseudo 1.2.2.1 debug1(_("TLS: peer certificate warning: %s"),
569 pseudo 1.1 X509_verify_cert_error_string(err));
570     ok = 1;
571     }
572     }
573     if (ok || !data->verify)
574     return 1;
575     putlog(data->loglevel, "*",
576 pseudo 1.2.2.1 _("TLS: certificate validation failed at depth %d: %s"),
577 pseudo 1.1 depth, X509_verify_cert_error_string(err));
578     return 0;
579     }
580    
581     /* SSL info callback, this is used to trace engine state changes
582     * and to check when the handshake is finished, so we can display
583     * some cipher and session information and process callbacks.
584     */
585     void ssl_info(SSL *ssl, int where, int ret)
586     {
587     int sock;
588     X509 *cert;
589     char buf[256];
590     ssl_appdata *data;
591     SSL_CIPHER *cipher;
592     int secret, processed;
593    
594     /* We're doing non-blocking IO, so we check here if the handshake has
595     finished */
596     if (where & SSL_CB_HANDSHAKE_DONE) {
597     if (!(data = (ssl_appdata *) SSL_get_app_data(ssl)))
598     return;
599     /* Callback for completed handshake. Cheaper and more convenient than
600     using H_tls */
601     sock = SSL_get_fd(ssl);
602     if (data->cb)
603     data->cb(sock);
604     /* Call TLS binds. We allow scripts to take over or disable displaying of
605     certificate information. */
606     if (check_tcl_tls(sock))
607     return;
608    
609 pseudo 1.2.2.1 putlog(data->loglevel, "*", _("TLS: handshake successful. "
610     "Secure connection established."));
611 pseudo 1.1
612     if ((cert = SSL_get_peer_certificate(ssl)))
613     ssl_showcert(cert, data->loglevel);
614     else
615 pseudo 1.2.2.1 putlog(data->loglevel, "*", _("TLS: peer did not present a certificate"));
616 pseudo 1.1
617     /* Display cipher information */
618     cipher = SSL_get_current_cipher(ssl);
619     processed = SSL_CIPHER_get_bits(cipher, &secret);
620 pseudo 1.2.2.1 putlog(data->loglevel, "*", _("TLS: cipher used: %s %s; "
621     "%d bits (%d secret)"), SSL_CIPHER_get_name(cipher),
622     SSL_CIPHER_get_version(cipher), processed, secret);
623 pseudo 1.1 /* secret are the actually secret bits. If processed and secret differ,
624     the rest of the bits are fixed, i.e. for limited export ciphers */
625    
626     /* More verbose information, for debugging only */
627     SSL_CIPHER_description(cipher, buf, sizeof buf);
628 pseudo 1.2.2.1 debug1(_("TLS: cipher details: %s"), buf);
629 pseudo 1.1 }
630    
631     /* Display the state of the engine for debugging purposes */
632 thommey 1.2.2.2 debug1("TLS: state change: %s", SSL_state_string_long(ssl));
633 pseudo 1.1 }
634    
635     /* Switch a socket to SSL communication
636     *
637     * Creates a SSL data structure for the connection;
638     * Sets up callbacks and initiates a SSL handshake with the peer;
639     * Reports error conditions and performs cleanup upon failure.
640     *
641     * flags: ssl flags, i.e connect or listen
642     * verify: peer certificate verification flags
643     * loglevel: is the level to output information about the connection
644     * and certificates.
645     * host: contains the dns name or ip address of the peer. Used for
646     * verification.
647     * cb: optional callback, this function will be called after the
648     * handshake completes.
649     *
650     * Return value: 0 on success, !=0 on failure.
651     */
652     int ssl_handshake(int sock, int flags, int verify, int loglevel, char *host,
653     IntFunc cb)
654     {
655     int i, err, ret;
656     ssl_appdata *data;
657     struct threaddata *td = threaddata();
658    
659 pseudo 1.2.2.1 debug0(_("TLS: attempting SSL negotiation..."));
660 pseudo 1.1 if (!ssl_ctx && ssl_init()) {
661 pseudo 1.2.2.1 debug0(_("TLS: Failed. OpenSSL not initialized properly."));
662 pseudo 1.1 return -1;
663     }
664     /* find the socket in the list */
665     i = findsock(sock);
666     if (i == -1) {
667 pseudo 1.2.2.1 debug0(_("TLS: socket not in socklist"));
668 pseudo 1.1 return -2;
669     }
670     if (td->socklist[i].ssl) {
671 pseudo 1.2.2.1 debug0(_("TLS: handshake not required - SSL session already established"));
672 pseudo 1.1 return 0;
673     }
674     td->socklist[i].ssl = SSL_new(ssl_ctx);
675     if (!td->socklist[i].ssl ||
676     !SSL_set_fd(td->socklist[i].ssl, td->socklist[i].sock)) {
677 pseudo 1.2.2.1 debug1(_("TLS: cannot initiate SSL session - %s"),
678 pseudo 1.1 ERR_error_string(ERR_get_error(), 0));
679     return -3;
680     }
681    
682     /* Prepare a ssl appdata struct for the verify callback */
683     data = nmalloc(sizeof(ssl_appdata));
684     egg_bzero(data, sizeof(ssl_appdata));
685     data->flags = flags & (TLS_LISTEN | TLS_CONNECT);
686     data->verify = flags & ~(TLS_LISTEN | TLS_CONNECT);
687     data->loglevel = loglevel;
688     data->cb = cb;
689     strncpyz(data->host, host ? host : "", sizeof(data->host));
690     SSL_set_app_data(td->socklist[i].ssl, data);
691     SSL_set_info_callback(td->socklist[i].ssl, (void *) ssl_info);
692     /* We set this +1 to be able to report extra long chains properly.
693     * Otherwise, OpenSSL will break the verification reporting about
694     * missing certificates instead. The rest of the fix is in
695     * ssl_verify()
696     */
697     SSL_set_verify_depth(td->socklist[i].ssl, tls_maxdepth + 1);
698    
699 thommey 1.2.2.2 SSL_set_mode(td->socklist[i].ssl, SSL_MODE_ENABLE_PARTIAL_WRITE |
700     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
701 pseudo 1.1 if (data->flags & TLS_CONNECT) {
702     SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER, ssl_verify);
703     ret = SSL_connect(td->socklist[i].ssl);
704     if (!ret)
705 pseudo 1.2.2.1 debug0(_("TLS: connect handshake failed."));
706 pseudo 1.1 } else {
707     if (data->flags & TLS_VERIFYPEER)
708     SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER |
709     SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify);
710     else
711     SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER, ssl_verify);
712     ret = SSL_accept(td->socklist[i].ssl);
713     if (!ret)
714 pseudo 1.2.2.1 debug0(_("TLS: accept handshake failed"));
715 pseudo 1.1 }
716    
717     err = SSL_get_error(td->socklist[i].ssl, ret);
718     /* Normal condition for async I/O, similar to EAGAIN */
719     if (ret > 0 || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
720 pseudo 1.2.2.1 debug0(_("TLS: handshake in progress"));
721 pseudo 1.1 return 0;
722     }
723     if (ERR_peek_error())
724 pseudo 1.2.2.1 debug0(_("TLS: handshake failed due to the following errors: "));
725 pseudo 1.1 while ((err = ERR_get_error()))
726 pseudo 1.2.2.1 debug1(_("TLS: %s"), ERR_error_string(err, NULL));
727 pseudo 1.1
728     /* Attempt failed, cleanup and abort */
729     SSL_shutdown(td->socklist[i].ssl);
730     SSL_free(td->socklist[i].ssl);
731     td->socklist[i].ssl = NULL;
732     nfree(data);
733     return -4;
734     }
735    
736     /* Tcl functions */
737    
738     /* Is the connection secure? */
739     static int tcl_istls STDVAR
740     {
741     int j;
742    
743     BADARGS(2, 2, " idx");
744    
745     j = findidx(atoi(argv[1]));
746     if (j < 0) {
747     Tcl_AppendResult(irp, "invalid idx", NULL);
748     return TCL_ERROR;
749     }
750     if (dcc[j].ssl)
751     Tcl_AppendResult(irp, "1", NULL);
752     else
753     Tcl_AppendResult(irp, "0", NULL);
754     return TCL_OK;
755     }
756    
757     /* Perform a SSL handshake over an existing plain text
758     * connection.
759     */
760     static int tcl_starttls STDVAR
761     {
762     int j;
763     struct threaddata *td = threaddata();
764    
765     BADARGS(2, 2, " idx");
766    
767     j = findidx(atoi(argv[1]));
768     if (j < 0 || (dcc[j].type != &DCC_SCRIPT)) {
769     Tcl_AppendResult(irp, "invalid idx", NULL);
770     return TCL_ERROR;
771     }
772     if (dcc[j].ssl) {
773     Tcl_AppendResult(irp, "already started", NULL);
774     return TCL_ERROR;
775     }
776     /* Determine if we're playing a client or a server */
777     j = findsock(dcc[j].sock);
778     if (ssl_handshake(dcc[j].sock, (td->socklist[j].flags & SOCK_CONNECT) ?
779     TLS_CONNECT : TLS_LISTEN, tls_vfydcc, LOG_MISC, NULL, NULL))
780     Tcl_AppendResult(irp, "0", NULL);
781     else
782     Tcl_AppendResult(irp, "1", NULL);
783     return TCL_OK;
784     }
785    
786     /* Get all relevant information about an established ssl connection.
787     * This includes certificate subject and issuer, serial number,
788     * expiry date, protocol version and cipher information.
789     * All data is presented as a flat list consisting of name-value pairs.
790     */
791     static int tcl_tlsstatus STDVAR
792     {
793     char *p;
794     int i, j;
795     X509 *cert;
796     SSL_CIPHER *cipher;
797     struct threaddata *td = threaddata();
798     Tcl_DString ds;
799    
800     BADARGS(2, 2, " idx");
801    
802     /* Allow it to be used for any connection, not just scripted
803     * ones. This makes it possible for a script to display the
804     * server certificate.
805     */
806     i = findanyidx(atoi(argv[1]));
807     if (i < 0) {
808     Tcl_AppendResult(irp, "invalid idx", NULL);
809     return TCL_ERROR;
810     }
811     j = findsock(dcc[i].sock);
812     if (!j || !dcc[i].ssl || !td->socklist[j].ssl) {
813     Tcl_AppendResult(irp, "not a TLS connection", NULL);
814     return TCL_ERROR;
815     }
816    
817     Tcl_DStringInit(&ds);
818     /* Try to get a cert, clients aren't required to send a
819     * certificate, so this is optional
820     */
821     cert = SSL_get_peer_certificate(td->socklist[j].ssl);
822     /* The following information is certificate dependent */
823     if (cert) {
824     p = ssl_printname(X509_get_subject_name(cert));
825     Tcl_DStringAppendElement(&ds, "subject");
826     Tcl_DStringAppendElement(&ds, p);
827     nfree(p);
828     p = ssl_printname(X509_get_issuer_name(cert));
829     Tcl_DStringAppendElement(&ds, "issuer");
830     Tcl_DStringAppendElement(&ds, p);
831     nfree(p);
832     p = ssl_printtime(X509_get_notBefore(cert));
833     Tcl_DStringAppendElement(&ds, "notBefore");
834     Tcl_DStringAppendElement(&ds, p);
835     nfree(p);
836     p = ssl_printtime(X509_get_notAfter(cert));
837     Tcl_DStringAppendElement(&ds, "notAfter");
838     Tcl_DStringAppendElement(&ds, p);
839     nfree(p);
840     p = ssl_printnum(X509_get_serialNumber(cert));
841     Tcl_DStringAppendElement(&ds, "serial");
842     Tcl_DStringAppendElement(&ds, p);
843     nfree(p);
844     }
845     /* We should always have a cipher, but who knows? */
846     cipher = SSL_get_current_cipher(td->socklist[j].ssl);
847     if (cipher) { /* don't bother if there's none */
848     Tcl_DStringAppendElement(&ds, "protocol");
849     Tcl_DStringAppendElement(&ds, SSL_CIPHER_get_version(cipher));
850     Tcl_DStringAppendElement(&ds, "cipher");
851     Tcl_DStringAppendElement(&ds, SSL_CIPHER_get_name(cipher));
852     }
853    
854     /* Done, get a Tcl list from this and return it to the caller */
855     Tcl_AppendResult(irp, Tcl_DStringValue(&ds), NULL);
856     Tcl_DStringFree(&ds);
857     return TCL_OK;
858     }
859    
860     /* These will be added by tcl.c which is the established practice */
861     tcl_cmds tcltls_cmds[] = {
862     {"istls", tcl_istls},
863     {"starttls", tcl_starttls},
864     {"tlsstatus", tcl_tlsstatus},
865     {NULL, NULL}
866     };
867    
868     #endif /* TLS */

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23