2 Copyright (C) 2008 Ben Kibbey <bjk@luxsci.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
18 #include <gnutls/x509.h>
24 #include "pwmd-error.h"
26 #include "util-misc.h"
27 #include "util-string.h"
33 tls_fingerprint (gnutls_session_t ses
)
35 gnutls_x509_crt_t crt
;
36 const gnutls_datum_t
*cert_list
;
38 unsigned char buf
[20];
39 size_t len
= sizeof (buf
);
41 gnutls_x509_crt_init (&crt
);
44 log_write ("%s(%i): %s(): %s", __FILE__
, __LINE__
, __FUNCTION__
,
45 gnutls_strerror (GNUTLS_E_MEMORY_ERROR
));
49 cert_list
= gnutls_certificate_get_peers (ses
, &count
);
52 gnutls_x509_crt_import (crt
, &cert_list
[0], GNUTLS_X509_FMT_DER
);
53 gnutls_x509_crt_get_fingerprint (crt
, GNUTLS_DIG_SHA1
, buf
, &len
);
56 gnutls_x509_crt_deinit (crt
);
57 return bin2hex (buf
, len
);
61 verify_client_certificate (unsigned status
)
66 if (status
& GNUTLS_CERT_INVALID
)
67 log_write (_("client certificate is invalid"));
69 if (status
& GNUTLS_CERT_REVOKED
)
70 log_write (_("client certificate is revoked"));
72 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
73 log_write (_("client certificate has no signer"));
75 if (status
& GNUTLS_CERT_SIGNER_NOT_CA
)
76 log_write (_("client certificate signer is not from CA"));
78 if (status
& GNUTLS_CERT_INSECURE_ALGORITHM
)
79 log_write (_("client certificate has insecure algorithm"));
81 return GNUTLS_E_CERTIFICATE_ERROR
;
85 tls_init (int fd
, const char *prio
)
87 struct tls_s
*tls
= xcalloc (1, sizeof (struct tls_s
));
90 const char *prio_error
;
91 gnutls_kx_algorithm_t kx
;
95 log_write ("%s(%i): %s: %s", __FILE__
, __LINE__
, __FUNCTION__
,
100 ret
= gnutls_init (&tls
->ses
, GNUTLS_SERVER
);
101 if (ret
!= GNUTLS_E_SUCCESS
)
104 ret
= gnutls_priority_set_direct (tls
->ses
, prio
, &prio_error
);
105 if (ret
!= GNUTLS_E_SUCCESS
)
108 ret
= gnutls_credentials_set (tls
->ses
, GNUTLS_CRD_CERTIFICATE
, x509_cred
);
109 if (ret
!= GNUTLS_E_SUCCESS
)
112 gnutls_certificate_server_set_request (tls
->ses
, GNUTLS_CERT_REQUIRE
);
113 gnutls_transport_set_ptr (tls
->ses
, (gnutls_transport_ptr_t
) fd
);
114 ret
= gnutls_handshake (tls
->ses
);
115 if (ret
!= GNUTLS_E_SUCCESS
)
118 ret
= gnutls_certificate_verify_peers2 (tls
->ses
, &status
);
122 kx
= gnutls_kx_get (tls
->ses
);
123 tls
->fp
= tls_fingerprint (tls
->ses
);
124 log_write ("PROTO=%s CIPHER=%s MAC=%s KX=%s(%d) FP=%s",
125 gnutls_protocol_get_name (gnutls_protocol_get_version
127 gnutls_cipher_get_name (gnutls_cipher_get (tls
->ses
)),
128 gnutls_mac_get_name (gnutls_mac_get (tls
->ses
)),
129 gnutls_kx_get_name (kx
), gnutls_dh_get_prime_bits (tls
->ses
),
130 tls
->fp
? tls
->fp
: "N/A");
131 ret
= verify_client_certificate (status
);
138 log_write ("%s", gnutls_strerror (ret
));
139 gnutls_deinit (tls
->ses
);
145 /* From the documentation. */
147 tls_get_params (gnutls_session_t ses
, gnutls_params_type_t type
,
148 gnutls_params_st
* st
)
150 if (type
== GNUTLS_PARAMS_RSA_EXPORT
)
151 st
->params
.rsa_export
= rsa_params
;
152 else if (type
== GNUTLS_PARAMS_DH
)
153 st
->params
.dh
= dh_params
;
163 tls_log (int level
, const char *msg
)
165 log_write ("TLS: %i: %s", level
, msg
);
169 tls_read_hook (assuan_context_t ctx
, assuan_fd_t fd
, void *data
, size_t len
)
171 struct client_s
*client
= assuan_get_pointer (ctx
);
176 ret
= gnutls_record_recv (client
->thd
->tls
->ses
, data
, len
);
178 if (ret
== GNUTLS_E_REHANDSHAKE
)
180 ret
= gnutls_rehandshake (client
->thd
->tls
->ses
);
181 if (ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
||
182 ret
== GNUTLS_A_NO_RENEGOTIATION
)
184 log_write ("%s", gnutls_strerror (ret
));
188 if (ret
!= GNUTLS_E_SUCCESS
)
190 log_write ("%s", gnutls_strerror (ret
));
195 ret
= gnutls_handshake (client
->thd
->tls
->ses
);
196 if (ret
!= GNUTLS_E_SUCCESS
)
198 log_write ("%s", gnutls_strerror (ret
));
206 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
210 log_write ("%s", gnutls_strerror (ret
));
218 tls_write_hook (assuan_context_t ctx
, assuan_fd_t fd
, const void *data
,
221 struct client_s
*client
= assuan_get_pointer (ctx
);
226 struct timeval tv
= { 0, 50000 };
228 ret
= gnutls_record_send (client
->thd
->tls
->ses
, data
, len
);
229 if (ret
== GNUTLS_E_AGAIN
)
230 select (0, NULL
, NULL
, NULL
, &tv
);
232 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
);
242 gpg_error_t rc
= GPG_ERR_UNKNOWN_ERRNO
;
244 n
= gnutls_certificate_allocate_credentials (&x509_cred
);
245 if (n
!= GNUTLS_E_SUCCESS
)
247 log_write ("%s", gnutls_strerror (n
));
252 MUTEX_LOCK (&rcfile_mutex
);
254 if (config_get_boolean ("global", "tls_use_crl"))
256 MUTEX_UNLOCK (&rcfile_mutex
);
257 tmp
= str_asprintf ("%s/crl.pem", homedir
);
264 if (access (tmp
, R_OK
) == -1 && errno
== ENOENT
)
265 log_write ("%s: %s", tmp
, gnutls_strerror (n
));
268 n
= gnutls_certificate_set_x509_crl_file (x509_cred
, tmp
,
269 GNUTLS_X509_FMT_PEM
);
272 log_write ("%s: %s", tmp
, gnutls_strerror (n
));
281 MUTEX_UNLOCK (&rcfile_mutex
);
283 tmp
= str_asprintf ("%s/ca-cert.pem", homedir
);
290 n
= gnutls_certificate_set_x509_trust_file (x509_cred
, tmp
,
291 GNUTLS_X509_FMT_PEM
);
294 log_write ("%s: %s", tmp
, gnutls_strerror (n
));
300 tmp
= str_asprintf ("%s/server-cert.pem", homedir
);
307 tmp2
= str_asprintf ("%s/server-key.pem", homedir
);
311 log_write ("%s(%i): %s", __FILE__
, __LINE__
, strerror (ENOMEM
));
315 n
= gnutls_certificate_set_x509_key_file (x509_cred
, tmp
, tmp2
,
316 GNUTLS_X509_FMT_PEM
);
319 if (n
!= GNUTLS_E_SUCCESS
)
321 log_write ("%s", gnutls_strerror (n
));
325 log_write ("%s", _("Generating key exchange parameters..."));
326 n
= gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM
, 0);
329 log_write ("%s", pwmd_strerror (n
));
333 n
= gnutls_dh_params_init (&dh_params
);
334 if (n
!= GNUTLS_E_SUCCESS
)
336 log_write ("%s", gnutls_strerror (n
));
340 n
= gnutls_dh_params_generate2 (dh_params
, 1024);
341 if (n
!= GNUTLS_E_SUCCESS
)
343 log_write ("%s", gnutls_strerror (n
));
347 gnutls_certificate_set_dh_params (x509_cred
, dh_params
);
348 n
= gnutls_rsa_params_init (&rsa_params
);
349 if (n
!= GNUTLS_E_SUCCESS
)
351 log_write ("%s", gnutls_strerror (n
));
355 n
= gnutls_rsa_params_generate2 (rsa_params
, 512);
356 if (n
!= GNUTLS_E_SUCCESS
)
358 log_write ("%s", gnutls_strerror (n
));
362 gnutls_certificate_set_rsa_export_params (x509_cred
, rsa_params
);
363 gnutls_certificate_set_params_function (x509_cred
, tls_get_params
);
375 gnutls_dh_params_deinit (dh_params
);
381 gnutls_rsa_params_deinit (rsa_params
);
387 gnutls_certificate_free_credentials (x509_cred
);
393 tls_validate_access (struct client_s
*cl
, const char *filename
)
395 char **access
= config_get_list (filename
, "tls_access");
397 int allow
= 0, deny
= 0;
399 if (!access
|| !*access
)
400 return GPG_ERR_INV_USER_ID
;
402 for (p
= access
; p
&& *p
; p
++)
407 if (*fp
&& *fp
== '+' && *(fp
+ 1) == 0)
421 if (!strcasecmp (cl
->thd
->tls
->fp
, fp
))
436 return allow
&& !deny
? 0 : GPG_ERR_INV_USER_ID
;