1 /* starttls.c --- Handle extended TCP connections (for TLS).
2 * Copyright (C) 2002, 2003, 2006 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 /* Note: only use syslog to report errors in this file. */
24 /* Get Shishid stuff. */
27 /* This function will print information about this session's peer
30 logcertinfo (gnutls_session session
)
32 time_t now
= time (NULL
);
33 const gnutls_datum
*cert_list
;
34 unsigned cert_list_size
= 0;
39 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
43 rc
= gnutls_x509_crt_init (&cert
);
46 syslog (LOG_ERR
, "TLS xci failed (%d): %s", rc
, gnutls_strerror (rc
));
50 if (gnutls_certificate_type_get (session
) == GNUTLS_CRT_X509
)
51 for (i
= 0; i
< cert_list_size
; i
++)
53 time_t expiration_time
, activation_time
;
54 char *expiration_time_str
= NULL
, *activation_time_str
= NULL
;
55 unsigned char *serial
= NULL
, *serialhex
= NULL
;
56 char *issuer
= NULL
, *subject
= NULL
;
57 size_t seriallen
, issuerlen
, subjectlen
;
58 unsigned char md5fingerprint
[16], md5fingerprinthex
[3 * 16 + 1];
59 size_t md5fingerprintlen
;
62 const char *keytype
, *validity
;
64 rc
= gnutls_x509_crt_import (cert
, &cert_list
[i
],
68 syslog (LOG_ERR
, "TLS xci[%d] failed (%d): %s", i
,
69 rc
, gnutls_strerror (rc
));
73 md5fingerprintlen
= sizeof (md5fingerprint
);
74 rc
= gnutls_fingerprint (GNUTLS_DIG_MD5
, &cert_list
[i
],
75 md5fingerprint
, &md5fingerprintlen
);
76 if (rc
!= GNUTLS_E_SUCCESS
)
78 syslog (LOG_ERR
, "TLS f[%d] failed (%d): %s", i
,
79 rc
, gnutls_strerror (rc
));
83 for (i
= 0; i
< md5fingerprintlen
; i
++)
84 sprintf (&md5fingerprinthex
[3 * i
], "%.2x:", md5fingerprint
[i
]);
86 expiration_time
= gnutls_x509_crt_get_expiration_time (cert
);
87 if (expiration_time
== (time_t) - 1)
89 syslog (LOG_ERR
, "TLS xcget[%d] failed (%d): %s", i
,
90 rc
, gnutls_strerror (rc
));
94 activation_time
= gnutls_x509_crt_get_activation_time (cert
);
95 if (expiration_time
== (time_t) - 1)
97 syslog (LOG_ERR
, "TLS xcgat[%d] failed (%d): %s", i
,
98 rc
, gnutls_strerror (rc
));
102 expiration_time_str
= xstrdup (ctime (&expiration_time
));
103 if (expiration_time_str
[strlen (expiration_time_str
) - 1] == '\n')
104 expiration_time_str
[strlen (expiration_time_str
) - 1] = '\0';
106 activation_time_str
= xstrdup (ctime (&activation_time
));
107 if (activation_time_str
[strlen (activation_time_str
) - 1] == '\n')
108 activation_time_str
[strlen (activation_time_str
) - 1] = '\0';
110 rc
= gnutls_x509_crt_get_dn (cert
, NULL
, &subjectlen
);
111 if (rc
!= GNUTLS_E_SUCCESS
&& rc
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
113 syslog (LOG_ERR
, "TLS xcgd[%d] failed (%d): %s", i
,
114 rc
, gnutls_strerror (rc
));
117 subject
= xmalloc (++subjectlen
);
118 rc
= gnutls_x509_crt_get_dn (cert
, subject
, &subjectlen
);
119 if (rc
!= GNUTLS_E_SUCCESS
)
121 syslog (LOG_ERR
, "TLS xcgd2[%d] failed (%d): %s", i
,
122 rc
, gnutls_strerror (rc
));
126 rc
= gnutls_x509_crt_get_issuer_dn (cert
, NULL
, &issuerlen
);
127 if (rc
!= GNUTLS_E_SUCCESS
&& rc
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
129 syslog (LOG_ERR
, "TLS xcgid[%d] failed (%d): %s", i
,
130 rc
, gnutls_strerror (rc
));
133 issuer
= xmalloc (++issuerlen
);
134 rc
= gnutls_x509_crt_get_issuer_dn (cert
, issuer
, &issuerlen
);
135 if (rc
!= GNUTLS_E_SUCCESS
)
137 syslog (LOG_ERR
, "TLS xcgid2[%d] failed (%d): %s", i
,
138 rc
, gnutls_strerror (rc
));
143 rc
= gnutls_x509_crt_get_serial (cert
, NULL
, &seriallen
);
144 if (rc
!= GNUTLS_E_SUCCESS
&& rc
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
146 syslog (LOG_ERR
, "TLS xcgs[%d] failed (%d): %s", i
,
147 rc
, gnutls_strerror (rc
));
150 serial
= xmalloc (seriallen
);
151 rc
= gnutls_x509_crt_get_serial (cert
, serial
, &seriallen
);
152 if (rc
!= GNUTLS_E_SUCCESS
)
154 syslog (LOG_ERR
, "TLS xcgs2[%d] failed (%d): %s", i
,
155 rc
, gnutls_strerror (rc
));
159 serialhex
= xmalloc (2 * seriallen
+ 1);
160 for (i
= 0; i
< seriallen
; i
++)
161 sprintf (&serialhex
[2 * i
], "%.2x", serial
[i
]);
164 algo
= gnutls_x509_crt_get_pk_algorithm (cert
, &bits
);
165 if (algo
== GNUTLS_PK_RSA
)
166 keytype
= "RSA modulus";
167 else if (algo
== GNUTLS_PK_DSA
)
168 keytype
= "DSA exponent";
172 if (expiration_time
< now
)
173 validity
= "EXPIRED";
174 else if (activation_time
> now
)
175 validity
= "NOT YET ACTIVATED";
179 syslog (LOG_INFO
, "TLS client certificate `%s', issued by `%s', "
180 "serial number `%s', MD5 fingerprint `%s', activated `%s', "
181 "expires `%s', version #%d, key %s %d bits, currently %s",
182 subject
, issuer
, serialhex
, md5fingerprinthex
,
183 activation_time_str
, expiration_time_str
,
184 gnutls_x509_crt_get_version (cert
), keytype
, bits
, validity
);
191 if (expiration_time_str
)
192 free (expiration_time_str
);
193 if (activation_time_str
)
194 free (activation_time_str
);
201 gnutls_x509_crt_deinit (cert
);
203 rc
= gnutls_certificate_verify_peers (session
);
204 if (rc
!= GNUTLS_E_SUCCESS
)
205 syslog (LOG_ERR
, "TLS client certificate verify failed (%d): %s",
206 rc
, gnutls_strerror (rc
));
209 /* This function will log some details of the given session. */
211 logtlsinfo (gnutls_session session
)
213 gnutls_credentials_type cred
;
214 const char *protocol
=
215 gnutls_protocol_get_name (gnutls_protocol_get_version (session
));
216 gnutls_kx_algorithm kx
= gnutls_kx_get (session
);
217 const char *keyexchange
= gnutls_kx_get_name (kx
);
218 const char *certtype
=
219 gnutls_certificate_type_get_name (gnutls_certificate_type_get (session
));
220 const char *cipher
= gnutls_cipher_get_name (gnutls_cipher_get (session
));
221 const char *mac
= gnutls_mac_get_name (gnutls_mac_get (session
));
222 const char *compression
=
223 gnutls_compression_get_name (gnutls_compression_get (session
));
224 int resumedp
= gnutls_session_is_resumed (session
);
226 syslog (LOG_INFO
, "TLS handshake negotiated protocol `%s', "
227 "key exchange `%s', certficate type `%s', cipher `%s', "
228 "mac `%s', compression `%s', %s",
229 protocol
? protocol
: "N/A",
230 keyexchange
? keyexchange
: "N/A",
231 certtype
? certtype
: "N/A",
232 cipher
? cipher
: "N/A",
233 mac
? mac
: "N/A", compression
? compression
: "N/A",
234 resumedp
? "resumed session" : "session not resumed");
236 cred
= gnutls_auth_get_type (session
);
239 case GNUTLS_CRD_ANON
:
241 "TLS anonymous authentication with %d bit Diffie-Hellman",
242 gnutls_dh_get_prime_bits (session
));
245 case GNUTLS_CRD_CERTIFICATE
:
246 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
)
247 syslog (LOG_INFO
, "TLS certificate authentication with %d bit "
248 "ephemeral Diffie-Hellman",
249 gnutls_dh_get_prime_bits (session
));
250 logcertinfo (session
);
254 syslog (LOG_ERR
, "Unknown TLS authentication (%d)", cred
);
259 #define STARTTLS_CLIENT_REQUEST "\x70\x00\x00\x01"
260 #define STARTTLS_SERVER_ACCEPT "\x00\x00\x00\x00"
261 #define STARTTLS_LEN 4
263 /* Handle the high TCP length bit, currently only used for STARTTLS. */
265 kdc_extension (struct listenspec
*ls
)
269 if (!ls
->usetls
&& ls
->type
== SOCK_STREAM
&& ls
->bufpos
== 4 &&
270 memcmp (ls
->buf
, STARTTLS_CLIENT_REQUEST
, STARTTLS_LEN
) == 0)
272 const int kx_prio
[] = { GNUTLS_KX_RSA
, GNUTLS_KX_DHE_DSS
,
273 GNUTLS_KX_DHE_RSA
, GNUTLS_KX_ANON_DH
, 0
276 syslog (LOG_INFO
, "Trying STARTTLS");
278 memcpy (ls
->buf
, STARTTLS_SERVER_ACCEPT
, STARTTLS_LEN
);
279 ls
->bufpos
= STARTTLS_LEN
;
283 rc
= gnutls_init (&ls
->session
, GNUTLS_SERVER
);
284 if (rc
!= GNUTLS_E_SUCCESS
)
286 syslog (LOG_ERR
, "TLS initialization failed (%d): %s", rc
,
287 gnutls_strerror (rc
));
291 rc
= gnutls_set_default_priority (ls
->session
);
292 if (rc
!= GNUTLS_E_SUCCESS
)
294 syslog (LOG_ERR
, "TLS failed, gnutls_sdp %d: %s", rc
,
295 gnutls_strerror (rc
));
299 rc
= gnutls_kx_set_priority (ls
->session
, kx_prio
);
300 if (rc
!= GNUTLS_E_SUCCESS
)
302 syslog (LOG_ERR
, "TLS failed, gnutls_ksp %d: %s", rc
,
303 gnutls_strerror (rc
));
307 rc
= gnutls_credentials_set (ls
->session
, GNUTLS_CRD_ANON
, anoncred
);
308 if (rc
!= GNUTLS_E_SUCCESS
)
310 syslog (LOG_ERR
, "TLS failed, gnutls_cs %d: %s", rc
,
311 gnutls_strerror (rc
));
315 rc
= gnutls_credentials_set (ls
->session
, GNUTLS_CRD_CERTIFICATE
,
317 if (rc
!= GNUTLS_E_SUCCESS
)
319 syslog (LOG_ERR
, "TLS failed, gnutls_cs X.509 %d: %s", rc
,
320 gnutls_strerror (rc
));
324 gnutls_certificate_server_set_request (ls
->session
,
325 GNUTLS_CERT_REQUEST
);
327 gnutls_dh_set_prime_bits (ls
->session
, DH_BITS
);
328 gnutls_transport_set_ptr (ls
->session
,
329 (gnutls_transport_ptr
) ls
->sockfd
);
331 gnutls_db_set_retrieve_function (ls
->session
, resume_db_fetch
);
332 gnutls_db_set_store_function (ls
->session
, resume_db_store
);
333 gnutls_db_set_remove_function (ls
->session
, resume_db_delete
);
335 rc
= gnutls_handshake (ls
->session
);
338 syslog (LOG_ERR
, "TLS handshake failed (%d): %s\n",
339 rc
, gnutls_strerror (rc
));
343 logtlsinfo (ls
->session
);