The starttls_xxx() functions in libfun.c now support async use of TLS Pool
[tlspool] / src / starttls.c
1 /* tlspool/starttls.c -- Setup and validation handler for TLS session */
2
3
4 #include <config.h>
5
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <memory.h>
10 #include <pthread.h>
11
12 #include <unistd.h>
13 #include <syslog.h>
14 #include <errno.h>
15 #include <poll.h>
16
17 #include <sys/types.h>
18 #include <sys/socket.h>
19
20 #include <gnutls/gnutls.h>
21 #include <gnutls/pkcs11.h>
22 #include <gnutls/abstract.h>
23
24 #include <tlspool/internal.h>
25
26
27 #include "manage.h"
28 #include "donai.h"
29
30
31 #if EXPECTED_LID_TYPE_COUNT != LID_TYPE_CNT
32 #error "Set EXPECTED_LID_TYPE_COUNT in <tlspool/internal.h> to match LID_TYPE_CNT"
33 #endif
34
35
36 /* This module hosts TLS handlers which treat an individual connection.
37  *
38  * Initially, the TLS setup is processed, which means validating the
39  * connection.  If and when this succeeds, a continued process is needed
40  * to encrypt and decrypt traffic while it is in transit.
41  *
42  * Every TLS connection (including the attempt to set it up) is hosted in
43  * its own thread.  This means that it can abide time to wait for PINENTRY
44  * or LOCALID responses.  It also means a very clear flow when the time
45  * comes to destroy a connection.
46  *
47  * While encrypting and decrypting traffic passing through, the thread
48  * will use its own poll() call, and thus offload the potentially large
49  * one of the main thread, which is supposed to be a low-traffic task.
50  * The set of file descriptors used by the session-handler threads are
51  * in contrast very small and can easily be started for every single
52  * packet passing through.
53  *
54  * Might the user terminate a process while this one is waiting for a
55  * callback command request, then the main TLS pool thread will take
56  * care of taking down this thread.  To that end, it sets the followup
57  * pointer that normally holds a callback response to NULL, and then
58  * permits this thread to run again.  This will lead to a shutdown of
59  * this process, and proper closing of all connections.  The remote peer
60  * will therefore see the result of a local kill as a connection reset.
61  *
62  * In case one of the end points of the connection is terminated, a
63  * similar thing will happen; the thread will terminate itself after
64  * a cleanup of any outstanding resources.  This, once again, leads
65  * to passing on the reset of a connection between the encrypted and
66  * side of the connection.
67  */
68
69
70
71 /*
72  * GnuTLS infrastructure setup.
73  * Session-shared DH-keys, credentials structures, and so on.
74  */
75 static gnutls_dh_params_t dh_params;
76
77 struct credinfo {
78         gnutls_credentials_type_t credtp;
79         void *cred;
80 };
81
82 #define EXPECTED_SRV_CREDCOUNT 3
83 #define EXPECTED_CLI_CREDCOUNT 2
84 static struct credinfo srv_creds [EXPECTED_SRV_CREDCOUNT];
85 static struct credinfo cli_creds [EXPECTED_CLI_CREDCOUNT];
86 static int srv_credcount = 0;
87 static int cli_credcount = 0;
88
89
90 /* Map a GnuTLS call (usually a function call) to a POSIX errno,
91  * optionally reporting an errstr to avoid loosing information.
92  * Retain errno if it already exists.
93  * Continue if errno differs from 0, GnuTLS may "damage" it even when OK. */
94 #define E_g2e(errstr,gtlscall) { \
95         if (gtls_errno == GNUTLS_E_SUCCESS) { \
96                 int gtls_errno = (gtlscall); \
97                 if (gtls_errno != GNUTLS_E_SUCCESS) { \
98                         error_gnutls2posix (gtls_errno, errstr); \
99                 } \
100         } \
101 }
102
103 /* Cleanup when GnuTLS leaves errno damaged but returns no gtls_errno */
104 #define E_gnutls_clear_errno() { \
105         if (gtls_errno == GNUTLS_E_SUCCESS) { \
106                 errno = 0; \
107         } \
108 }
109
110 /* Error number translation, including error string setup.  See E_g2e(). */
111 void error_gnutls2posix (int gtls_errno, char *new_errstr) {
112         char *errstr;
113         register int newerrno;
114         //
115         // Sanity checks
116         if (gtls_errno == GNUTLS_E_SUCCESS) {
117                 return;
118         }
119         errstr =  error_getstring ();
120         if (errstr != NULL) {
121                 return;
122         }
123         //
124         // Report the textual error
125         if (new_errstr == NULL) {
126                 new_errstr = "GnuTLS error";
127         }
128         tlog (TLOG_TLS, LOG_ERR, "%s: %s",
129                 new_errstr,
130                 gnutls_strerror (gtls_errno));
131         error_setstring (new_errstr);
132         //
133         // Translate error to a POSIX errno value
134         switch (gtls_errno) {
135         case GNUTLS_E_SUCCESS:
136                 return;
137         case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
138         case GNUTLS_E_UNKNOWN_CIPHER_TYPE:
139         case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
140         case GNUTLS_E_UNWANTED_ALGORITHM:
141         case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
142         case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
143         case GNUTLS_E_X509_UNKNOWN_SAN:
144         case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
145         case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
146         case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
147         case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
148         case GNUTLS_E_NO_CIPHER_SUITES:
149         case GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED:
150         case GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE:
151         case GNUTLS_E_UNKNOWN_HASH_ALGORITHM:
152         case GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE:
153         case GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE:
154         case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
155         case GNUTLS_E_UNKNOWN_ALGORITHM:
156         case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
157         case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
158         case GNUTLS_E_X509_UNSUPPORTED_OID:
159         case GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE:
160         case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
161         case GNUTLS_E_ECC_NO_SUPPORTED_CURVES:
162         case GNUTLS_E_ECC_UNSUPPORTED_CURVE:
163         case GNUTLS_E_X509_UNSUPPORTED_EXTENSION:
164         case GNUTLS_E_NO_CERTIFICATE_STATUS:
165         case GNUTLS_E_NO_APPLICATION_PROTOCOL:
166 #ifdef GNUTLS_E_NO_SELF_TEST
167         case GNUTLS_E_NO_SELF_TEST:
168 #endif
169                 newerrno = EOPNOTSUPP;
170                 break;
171         case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
172         case GNUTLS_E_INVALID_REQUEST:
173                 newerrno = EINVAL;
174                 break;
175         case GNUTLS_E_INVALID_SESSION:
176         case GNUTLS_E_REHANDSHAKE:
177         case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
178                 newerrno = ENOTCONN;
179                 break;
180         case GNUTLS_E_PUSH_ERROR:
181         case GNUTLS_E_PULL_ERROR:
182         case GNUTLS_E_PREMATURE_TERMINATION:
183         case GNUTLS_E_SESSION_EOF:
184                 newerrno = ECONNRESET;
185                 break;
186         case GNUTLS_E_UNEXPECTED_PACKET:
187         case GNUTLS_E_WARNING_ALERT_RECEIVED:
188         case GNUTLS_E_FATAL_ALERT_RECEIVED:
189         case GNUTLS_E_LARGE_PACKET:
190         case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
191         case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
192         case GNUTLS_E_MPI_SCAN_FAILED:
193         case GNUTLS_E_DECRYPTION_FAILED:
194         case GNUTLS_E_DECOMPRESSION_FAILED:
195         case GNUTLS_E_COMPRESSION_FAILED:
196         case GNUTLS_E_BASE64_DECODING_ERROR:
197         case GNUTLS_E_MPI_PRINT_FAILED:
198         case GNUTLS_E_GOT_APPLICATION_DATA:
199         case GNUTLS_E_RECORD_LIMIT_REACHED:
200         case GNUTLS_E_ENCRYPTION_FAILED:
201         case GNUTLS_E_PK_ENCRYPTION_FAILED:
202         case GNUTLS_E_PK_DECRYPTION_FAILED:
203         case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
204         case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
205         case GNUTLS_E_PKCS1_WRONG_PAD:
206         case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
207         case GNUTLS_E_FILE_ERROR:
208         case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
209         case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
210         case GNUTLS_E_ASN1_DER_ERROR:
211         case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
212         case GNUTLS_E_ASN1_GENERIC_ERROR:
213         case GNUTLS_E_ASN1_VALUE_NOT_VALID:
214         case GNUTLS_E_ASN1_TAG_ERROR:
215         case GNUTLS_E_ASN1_TAG_IMPLICIT:
216         case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
217         case GNUTLS_E_ASN1_SYNTAX_ERROR:
218         case GNUTLS_E_ASN1_DER_OVERFLOW:
219         case GNUTLS_E_TOO_MANY_EMPTY_PACKETS:
220         case GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS:
221         case GNUTLS_E_SRP_PWD_PARSING_ERROR:
222         case GNUTLS_E_BASE64_ENCODING_ERROR:
223         case GNUTLS_E_OPENPGP_KEYRING_ERROR:
224         case GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR:
225         case GNUTLS_E_OPENPGP_SUBKEY_ERROR:
226         case GNUTLS_E_CRYPTO_ALREADY_REGISTERED:
227         case GNUTLS_E_HANDSHAKE_TOO_LARGE:
228         case GNUTLS_E_BAD_COOKIE:
229         case GNUTLS_E_PARSING_ERROR:
230         case GNUTLS_E_CERTIFICATE_LIST_UNSORTED:
231         case GNUTLS_E_NO_PRIORITIES_WERE_SET:
232 #ifdef GNUTLS_E_PK_GENERATION_ERROR
233         case GNUTLS_E_PK_GENERATION_ERROR:
234 #endif
235 #ifdef GNUTLS_E_SELF_TEST_ERROR
236         case GNUTLS_E_SELF_TEST_ERROR:
237 #endif
238 #ifdef GNUTLS_E_SOCKETS_INIT_ERROR
239         case GNUTLS_E_SOCKETS_INIT_ERROR:
240 #endif
241                 newerrno = EIO;
242                 break;
243         case GNUTLS_E_MEMORY_ERROR:
244         case GNUTLS_E_SHORT_MEMORY_BUFFER:
245                 newerrno = ENOMEM;
246                 break;
247         case GNUTLS_E_AGAIN:
248                 newerrno = EAGAIN;
249                 break;
250         case GNUTLS_E_EXPIRED:
251         case GNUTLS_E_TIMEDOUT:
252                 newerrno = ETIMEDOUT;
253                 break;
254         case GNUTLS_E_DB_ERROR:
255 #ifdef ENODATA
256                 newerrno = ENODATA;
257 #else
258                 newerrno = ENOENT;
259 #endif
260                 break;
261         case GNUTLS_E_SRP_PWD_ERROR:
262         case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
263         case GNUTLS_E_HASH_FAILED:
264         case GNUTLS_E_PK_SIGN_FAILED:
265         case GNUTLS_E_CERTIFICATE_ERROR:
266         case GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION:
267         case GNUTLS_E_KEY_USAGE_VIOLATION:
268         case GNUTLS_E_NO_CERTIFICATE_FOUND:
269         case GNUTLS_E_OPENPGP_UID_REVOKED:
270         case GNUTLS_E_OPENPGP_GETKEY_FAILED:
271         case GNUTLS_E_PK_SIG_VERIFY_FAILED:
272         case GNUTLS_E_ILLEGAL_SRP_USERNAME:
273         case GNUTLS_E_INVALID_PASSWORD:
274         case GNUTLS_E_MAC_VERIFY_FAILED:
275         case GNUTLS_E_IA_VERIFY_FAILED:
276         case GNUTLS_E_UNKNOWN_SRP_USERNAME:
277         case GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR:
278         case GNUTLS_E_USER_ERROR:
279         case GNUTLS_E_AUTH_ERROR:
280                 newerrno = EACCES;
281                 break;
282         case GNUTLS_E_INTERRUPTED:
283                 newerrno = EINTR;
284                 break;
285         case GNUTLS_E_INTERNAL_ERROR:
286         case GNUTLS_E_CONSTRAINT_ERROR:
287         case GNUTLS_E_ILLEGAL_PARAMETER:
288                 newerrno = EINVAL;
289                 break;
290         case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
291                 newerrno = ECONNREFUSED;
292                 break;
293         case GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY:
294         case GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY:
295 #ifdef GNUTLS_E_LIB_IN_ERROR_STATE
296         case GNUTLS_E_LIB_IN_ERROR_STATE:
297 #endif
298                 newerrno = ENOEXEC;
299                 break;
300         case GNUTLS_E_RANDOM_FAILED:
301                 newerrno = EBADF;
302                 break;
303         case GNUTLS_E_CRYPTODEV_IOCTL_ERROR:
304         case GNUTLS_E_CRYPTODEV_DEVICE_ERROR:
305         case GNUTLS_E_HEARTBEAT_PONG_RECEIVED:
306         case GNUTLS_E_HEARTBEAT_PING_RECEIVED:
307         case GNUTLS_E_PKCS11_ERROR:
308         case GNUTLS_E_PKCS11_LOAD_ERROR:
309         case GNUTLS_E_PKCS11_PIN_ERROR:
310         case GNUTLS_E_PKCS11_SLOT_ERROR:
311         case GNUTLS_E_LOCKING_ERROR:
312         case GNUTLS_E_PKCS11_ATTRIBUTE_ERROR:
313         case GNUTLS_E_PKCS11_DEVICE_ERROR:
314         case GNUTLS_E_PKCS11_DATA_ERROR:
315         case GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR:
316         case GNUTLS_E_PKCS11_KEY_ERROR:
317         case GNUTLS_E_PKCS11_PIN_EXPIRED:
318         case GNUTLS_E_PKCS11_PIN_LOCKED:
319         case GNUTLS_E_PKCS11_SESSION_ERROR:
320         case GNUTLS_E_PKCS11_SIGNATURE_ERROR:
321         case GNUTLS_E_PKCS11_TOKEN_ERROR:
322         case GNUTLS_E_PKCS11_USER_ERROR:
323         case GNUTLS_E_CRYPTO_INIT_FAILED:
324         case GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE:
325         case GNUTLS_E_TPM_ERROR:
326         case GNUTLS_E_TPM_KEY_PASSWORD_ERROR:
327         case GNUTLS_E_TPM_SRK_PASSWORD_ERROR:
328         case GNUTLS_E_TPM_SESSION_ERROR:
329         case GNUTLS_E_TPM_KEY_NOT_FOUND:
330         case GNUTLS_E_TPM_UNINITIALIZED:
331         case GNUTLS_E_OCSP_RESPONSE_ERROR:
332         case GNUTLS_E_RANDOM_DEVICE_ERROR:
333 #ifdef EREMOTEIO
334                 newerrno = EREMOTEIO;
335 #else
336                 newerrno = EIO;
337 #endif
338                 break;
339         default:
340                 newerrno = EIO;
341                 break;
342         }
343         errno = newerrno;
344         return;
345 }
346
347 /* Generate Diffie-Hellman parameters - for use with DHE
348  * kx algorithms. TODO: These should be discarded and regenerated
349  * once a day, once a week or once a month. Depending on the
350  * security requirements.
351  */
352 static gtls_error generate_dh_params (void) {
353         unsigned int bits;
354         int gtls_errno = GNUTLS_E_SUCCESS;
355         bits = gnutls_sec_param_to_pk_bits (
356                 GNUTLS_PK_DH,
357                 GNUTLS_SEC_PARAM_LEGACY);
358         //TODO// Acquire DH-params lock
359         E_g2e ("Failed to initialise DH params",
360                 gnutls_dh_params_init (
361                         &dh_params));
362         E_g2e ("Failed to generate DH params",
363                 gnutls_dh_params_generate2 (
364                         dh_params,
365                         bits));
366         //TODO// Release DH-params lock
367         return gtls_errno;
368 }
369
370 /* Load Diffie-Hellman parameters from file - or generate them when load fails.
371  */
372 static gtls_error load_dh_params (void) {
373         gnutls_dh_params_t dhp;
374         gnutls_datum_t pkcs3;
375         char *filename = cfg_tls_dhparamfile ();
376         int gtls_errno = GNUTLS_E_SUCCESS;
377         bzero (&pkcs3, sizeof (pkcs3));
378         if (filename) {
379                 E_g2e ("No PKCS #3 PEM file with DH params",
380                         gnutls_load_file (
381                                 filename,
382                                 &pkcs3));
383                 E_gnutls_clear_errno ();
384                 E_g2e ("Failed to initialise DH params",
385                         gnutls_dh_params_init (
386                                 &dhp));
387                 E_g2e ("Failed to import DH params from PKCS #3 PEM",
388                         gnutls_dh_params_import_pkcs3 (
389                                 dhp,
390                                 &pkcs3,
391                                 GNUTLS_X509_FMT_PEM));
392                 E_gnutls_clear_errno ();
393         }
394         if (pkcs3.data != NULL) {
395                 free (pkcs3.data);
396         }
397         if (gtls_errno != GNUTLS_E_SUCCESS) {
398                 //
399                 // File failed to load, so try to generate fresh DH params
400                 int gtls_errno_stack0;
401                 gtls_errno = GNUTLS_E_SUCCESS;
402                 tlog (TLOG_CRYPTO, LOG_DEBUG, "Failed to load DH params from %s; generating fresh parameters", filename);
403                 E_g2e ("Failed to generate DH params",
404                         generate_dh_params ());
405                 gtls_errno_stack0 = gtls_errno;
406                 //TODO// Acquire DH-params lock
407                 E_g2e ("Failed to format DH params as PKCS #3 PEM",
408                         gnutls_dh_params_export2_pkcs3 (
409                                 dh_params,
410                                 GNUTLS_X509_FMT_PEM,
411                                 &pkcs3));
412                 //TODO// Release DH-params lock
413                 if ((gtls_errno == GNUTLS_E_SUCCESS) && (filename != NULL)) {
414                         FILE *pemf;
415                         //
416                         // Best effor file save -- readback will parse
417                         pemf = fopen (filename, "w");
418                         if (pemf != NULL) {
419                                 fwrite (pkcs3.data, 1, pkcs3.size, pemf);
420                                 fclose (pemf);
421                                 tlog (TLOG_FILES, LOG_DEBUG, "Saved DH params to %s (best-effort)", filename);
422                         }
423                         E_gnutls_clear_errno ();
424                 }
425                 gtls_errno = gtls_errno_stack0;
426         } else {
427                 gnutls_dh_params_t old_dh;
428                 //TODO// Acquire DH-params lock
429                 old_dh = dh_params;
430                 dh_params = dhp;
431                 //TODO// Release DH-params lock
432                 if (old_dh) {
433                         gnutls_dh_params_deinit (old_dh);
434                 }
435         }
436         return gtls_errno;
437 }
438
439 /* Remove DH parameters, to be used during program cleanup. */
440 static void remove_dh_params (void) {
441         if (dh_params) {
442                 gnutls_dh_params_deinit (dh_params);
443                 dh_params = NULL;
444         }
445 }
446
447
448 /* A log printing function
449  */
450 void log_gnutls (int level, const char *msg) {
451         tlog (TLOG_TLS, level, "GnuTLS: %s", msg);
452 }
453
454
455 /* Implement the GnuTLS function for token insertion callback.  This function
456  * refers back to the generic callback for token insertion.
457  */
458 int gnutls_token_callback (void *const userdata,
459                                 const char *const label,
460                                 unsigned retry) {
461         if (token_callback (label, retry)) {
462                 return GNUTLS_E_SUCCESS;
463         } else {
464                 return GNUTLS_E_PKCS11_TOKEN_ERROR;
465         }
466 }
467  
468
469 /*
470  * Implement the GnuTLS function for PIN callback.  This function calls
471  * the generic PIN callback operation.
472  */
473 int gnutls_pin_callback (void *userdata,
474                                 int attempt,
475                                 const char *token_url,
476                                 const char *token_label,
477                                 unsigned int flags,
478                                 char *pin,
479                                 size_t pin_max) {
480         if (flags & GNUTLS_PIN_SO) {
481                 return GNUTLS_E_USER_ERROR;
482         }
483         if (pin_callback (attempt, token_url, token_label, pin, pin_max)) {
484                 return 0;
485         } else {
486                 return GNUTLS_E_PKCS11_PIN_ERROR;
487         }
488 }
489
490
491 /* Register a PKCS #11 provider with the GnuTLS environment. */
492 void starttls_pkcs11_provider (char *p11path) {
493         unsigned int token_seq = 0;
494         char *p11uri;
495         if (gnutls_pkcs11_add_provider (p11path, NULL) != 0) {
496                 fprintf (stderr, "Failed to register PKCS #11 library %s with GnuTLS\n", p11path);
497                 exit (1);
498         }
499         while (gnutls_pkcs11_token_get_url (token_seq, 0, &p11uri) == 0) {
500 #ifdef DEBUG
501                 printf ("DEBUG: Found token URI %s\n", p11uri);
502 #endif
503                 //TODO// if (gnutls_pkcs11_token_get_info (p11uri, GNUTLS_PKCS11_TOKEN_LABEL-of-SERIAL-of-MANUFACTURER-of-MODEL, output, utput_size) == 0) { ... }
504                 gnutls_free (p11uri);
505                 token_seq++;
506         }
507         //TODO// Select token by name (value)
508         //TODO// if PIN available then set it up
509         //TODO:WHY?// free_p11pin ();
510 }
511
512
513 /* The global and static setup function for the starttls functions.
514  */
515 void setup_starttls (void) {
516         int setup_starttls_credentials (void);  /* Defined below */
517         const char *curver;
518         int gtls_errno = GNUTLS_E_SUCCESS;
519         //
520         // Basic library actions
521         tlog (TLOG_TLS, LOG_DEBUG, "Compiled against GnuTLS version %s", GNUTLS_VERSION);
522         curver = gnutls_check_version (GNUTLS_VERSION);
523         tlog (TLOG_TLS, LOG_DEBUG, "Running against %s GnuTLS version %s", curver? "acceptable": "OLDER", curver? curver: gnutls_check_version (NULL));
524         E_g2e ("GnuTLS global initialisation failed",
525                 gnutls_global_init ());
526         E_gnutls_clear_errno ();
527         E_g2e ("GnuTLS PKCS #11 initialisation failed",
528                 gnutls_pkcs11_init (
529                         GNUTLS_PKCS11_FLAG_MANUAL, NULL));
530         //
531         // Setup logging / debugging
532         if (cfg_log_level () == LOG_DEBUG) {
533                 gnutls_global_set_log_function (log_gnutls);
534                 gnutls_global_set_log_level (2);
535         }
536         //
537         // Setup callbacks for user communication
538         gnutls_pkcs11_set_token_function (gnutls_token_callback, NULL);
539         gnutls_pkcs11_set_pin_function (gnutls_pin_callback, NULL);
540         //
541         // Setup DH parameters
542         E_g2e ("Loading DH params failed",
543                 load_dh_params ());
544         //
545         // Setup shared credentials for all client server processes
546         E_g2e ("Failed to setup GnuTLS callback credentials",
547                 setup_starttls_credentials ());
548         if (gtls_errno != GNUTLS_E_SUCCESS) {
549                 tlog (TLOG_TLS, LOG_CRIT, "FATAL: GnuTLS setup failed: %s", gnutls_strerror (gtls_errno));
550                 exit (1);
551         }
552         //MOVED// //
553         //MOVED// // Setup the management databases
554         //MOVED// tlog (TLOG_DB, LOG_DEBUG, "Setting up management databases");
555         //MOVED// E_e2e ("Failed to setup management databases",
556         //MOVED//       setup_management ());
557         //MOVED// if (errno != 0) {
558         //MOVED//       tlog (TLOG_DB, LOG_CRIT, "FATAL: Management databases setup failed: %s", strerror (errno));
559         //MOVED//       exit (1);
560         //MOVED// }
561 }
562
563 /* Cleanup the structures and resources that were setup for handling TLS.
564  */
565 void cleanup_starttls (void) {
566         void cleanup_starttls_credentials (void);       /* Defined below */
567         //MOVED// cleanup_management ();
568         cleanup_starttls_credentials ();
569         remove_dh_params ();
570         gnutls_pkcs11_set_pin_function (NULL, NULL);
571         gnutls_pkcs11_set_token_function (NULL, NULL);
572         gnutls_pkcs11_deinit ();
573         gnutls_global_deinit ();
574 }
575
576
577 /*
578  * The copycat function is a bidirectional transport between the given
579  * remote and local sockets, but it will encrypt traffic from local to
580  * remote, and decrypt traffic from remote to local.  It will do this
581  * until one of the end points is shut down, at which time it will
582  * return and assume the context will close down both pre-existing
583  * sockets.
584  *
585  * This copycat actually has a few sharp claws to watch for -- shutdown
586  * of sockets may drop the last bit of information sent.  First, the
587  * signal POLLHUP is best ignored because it travels asynchronously.
588  * Second, reading 0 is a good indicator of end-of-file and may be
589  * followed by an shutdown of reading from that stream.  But, more
590  * importantly, the other side must have this information forwarded
591  * so it can shutdown.  This means that a shutdown for writing to that
592  * stream is to be sent.  Even when *both* sides have agreed to not send
593  * anything, they may still not have received all they were offered for
594  * reading, so we should SO_LINGER on the sockets so they can acknowledge,
595  * and after a timeout we can establish that shutdown failed and log and
596  * return an error for it.
597  * Will you believe that I had looked up if close() would suffice?  The man
598  * page clearly stated yes.  However, these articles offer much more detail:
599  * http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable
600  * http://www.greenend.org.uk/rjk/tech/poll.html
601  */
602 static void copycat (int local, int remote, gnutls_session_t wrapped, int master) {
603         char buf [1024];
604         struct pollfd inout [3];
605         ssize_t sz;
606         struct linger linger = { 1, 10 };
607
608         inout [0].fd = local;
609         inout [1].fd = remote;
610         inout [2].fd = master;
611         inout [0].events = inout [1].events = POLLIN;
612         inout [2].events = 0;   // error events only
613         tlog (TLOG_COPYCAT, LOG_DEBUG, "Starting copycat cycle for local=%d, remote=%d", local, remote);
614         while (((inout [0].events | inout [1].events) & POLLIN) != 0) {
615                 if (poll (inout, 3, -1) == -1) {
616                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat polling returned an error");
617                         break;  // Polling sees an error
618                 }
619                 if (inout [0].revents & POLLIN) {
620                         // Read local and encrypt to remote
621                         sz = recv (local, buf, sizeof (buf), MSG_DONTWAIT);
622                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d local bytes (or error<0) from %d", (int) sz, local);
623                         if (sz == -1) {
624                                 tlog (TLOG_COPYCAT, LOG_ERR, "Error while receiving: %s", strerror (errno));
625                                 break;  // stream error
626                         } else if (sz == 0) {
627                                 inout [0].events &= ~POLLIN;
628                                 shutdown (local, SHUT_RD);
629                                 setsockopt (remote, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
630                                 gnutls_bye (wrapped, GNUTLS_SHUT_WR);
631                         } else if (gnutls_record_send (wrapped, buf, sz) != sz) {
632                                 tlog (TLOG_COPYCAT, LOG_ERR, "gnutls_record_send() failed to pass on the requested bytes");
633                                 break;  // communication error
634                         } else {
635                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to remote %d", (int) sz, remote);
636                         }
637                 }
638                 if (inout [1].revents & POLLIN) {
639                         // Read remote and decrypt to local
640                         sz = gnutls_record_recv (wrapped, buf, sizeof (buf));
641                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d remote bytes from %d (or error if <0)", (int) sz, remote);
642                         if (sz < 0) {
643                                 if (gnutls_error_is_fatal (sz)) {
644                                         tlog (TLOG_TLS, LOG_ERR, "GnuTLS fatal error: %s", gnutls_strerror (sz));
645                                         break;  // stream error
646                                 } else {
647                                         tlog (TLOG_TLS, LOG_INFO, "GnuTLS recoverable error: %s", gnutls_strerror (sz));
648                                 }
649                         } else if (sz == 0) {
650                                 inout [1].events &= ~POLLIN;
651                                 shutdown (remote, SHUT_RD);
652                                 setsockopt (local, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
653                                 shutdown (local, SHUT_WR);
654                         } else if (send (local, buf, sz, MSG_DONTWAIT) != sz) {
655                                 break;  // communication error
656                         } else {
657                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to local %d", (int) sz, local);
658                         }
659                 }
660                 inout [0].revents &= ~(POLLIN | POLLHUP); // Thy copying cat?
661                 inout [1].revents &= ~(POLLIN | POLLHUP); // Retract thee claws!
662                 if ((inout [0].revents | inout [1].revents | inout [2].revents) & ~POLLIN) {
663                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat polling returned a special condition");
664                         break;  // Apparently, one of POLLERR, POLLHUP, POLLNVAL
665                 }
666         }
667         tlog (TLOG_COPYCAT, LOG_DEBUG, "Ending copycat cycle for local=%d, remote=%d", local, remote);
668         close (local);
669         close (remote);
670         gnutls_deinit (wrapped);
671 }
672
673
674 /* The callback function that retrieves certification information from either
675  * the client or the server in the course of the handshake procedure.
676  */
677 gtls_error clisrv_cert_retrieve (gnutls_session_t session,
678                                 const gnutls_datum_t* req_ca_dn,
679                                 int nreqs,
680                                 const gnutls_pk_algorithm_t* pk_algos,
681                                 int pk_algos_length,
682                                 gnutls_pcert_st** pcert,
683                                 unsigned int *pcert_length,
684                                 gnutls_privkey_t *pkey) {
685         gnutls_certificate_type_t certtp;
686         gnutls_pcert_st *pc = NULL;
687         struct command *cmd;
688         char *lid, *rid;
689         gnutls_datum_t privdatum = { NULL, 0 };
690         gnutls_datum_t certdatum = { NULL, 0 };
691         gnutls_openpgp_crt_t pgpcert = NULL;
692         gnutls_openpgp_privkey_t pgppriv = NULL;
693         gnutls_x509_crt_t x509cert = NULL;
694         gnutls_x509_privkey_t x509priv = NULL;
695         int gtls_errno = GNUTLS_E_SUCCESS;
696         int lidtype;
697         int lidrole = 0;
698         char *rolestr;
699         char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.localid)];
700         size_t snilen = sizeof (sni);
701         int snitype;
702         int ok;
703         uint32_t flags;
704         char *p11priv;
705         uint8_t *pubdata;
706         int pubdatalen;
707         gtls_error fetch_local_credentials (struct command *cmd);
708         gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum);
709
710         //
711         // Setup a number of common references and structures
712         *pcert = NULL;
713         cmd = (struct command *) gnutls_session_get_ptr (session);
714         if (cmd == NULL) {
715                 E_g2e ("No data pointer with session",
716                         GNUTLS_E_INVALID_SESSION);
717                 return gtls_errno;
718         }
719         if (cmd->cmd.pio_cmd == PIOC_STARTTLS_SERVER_V2) {
720                 lidrole = LID_ROLE_SERVER;
721                 rolestr = "server";
722         } else if (cmd->cmd.pio_cmd == PIOC_STARTTLS_CLIENT_V2) {
723                 lidrole = LID_ROLE_CLIENT;
724                 rolestr = "client";
725         } else {
726                 E_g2e ("TLS Pool command is not _STARTTLS_",
727                         GNUTLS_E_INVALID_SESSION);
728                 return gtls_errno;
729         }
730         lid = cmd->cmd.pio_data.pioc_starttls.localid;
731         rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
732
733         //
734         // On a server, lookup the server name and match it against lid.
735         // TODO: For now assume a single server name in SNI (as that is normal).
736         if (lidrole == LID_ROLE_SERVER) {
737                 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) || (snitype != GNUTLS_NAME_DNS)) {
738                         E_g2e ("Requested SNI error or not a DNS name",
739                                 GNUTLS_E_NO_CERTIFICATE_FOUND);
740                         return gtls_errno;
741                 }
742                 if (*lid != '\0') {
743                         if (strncmp (sni, lid, snilen) != 0) {
744                                 tlog (TLOG_TLS, LOG_ERR, "SNI %s does not match preset local identity %s", sni, lid);
745                                 E_g2e ("Requested SNI does not match local identity",
746                                         GNUTLS_E_NO_CERTIFICATE_FOUND);
747                                 return gtls_errno;
748                         }
749                 } else {
750                         // TODO: Should ask for permission before accepting SNI
751                         memcpy (lid, sni, sizeof (sni));
752                 }
753         }
754
755         //
756         // Setup the lidtype parameter for responding
757         certtp = gnutls_certificate_type_get (session);
758         if (certtp == GNUTLS_CRT_OPENPGP) {
759                 tlog (TLOG_TLS, LOG_INFO, "Serving OpenPGP certificate request as a %s", rolestr);
760                 lidtype = LID_TYPE_PGP;
761         } else if (certtp == GNUTLS_CRT_X509) {
762                 tlog (TLOG_TLS, LOG_INFO, "Serving X.509 certificate request as a %s", rolestr);
763                 lidtype = LID_TYPE_X509;
764         } else {
765                 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
766                 tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate retrieval attempted as a %s", rolestr);
767                 E_g2e ("Requested certtype is neither X.509 nor OpenPGP",
768                         GNUTLS_E_CERTIFICATE_ERROR);
769                 return gtls_errno;
770         }
771
772         //
773         // Find the prefetched local identity to use towards this remote
774         // Send a callback to the user if none is available and accessible
775         //TODO// This callback will be redirected to the identity watchdog
776         //TODO// Define a flag to enforce this callback (to set plainfd)
777         if (cmd->lids [lidtype - LID_TYPE_MIN].data == NULL) {
778                 uint32_t oldcmd = cmd->cmd.pio_cmd;
779                 cmd->cmd.pio_cmd = PIOC_STARTTLS_LOCALID_V1;
780                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_STARTTLS_LOCALID_V1");
781                 cmd = send_callback_and_await_response (cmd);
782                 if (cmd->cmd.pio_cmd != PIOC_STARTTLS_LOCALID_V1) {
783                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
784                         cmd->cmd.pio_cmd = oldcmd;
785                         return GNUTLS_E_CERTIFICATE_ERROR;
786                 }
787                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that sets plainfd:=%d and lid:=\"%s\" for rid==\"%s\"", cmd->passfd, lid, rid);
788                 cmd->cmd.pio_cmd = oldcmd;
789                 //
790                 // Check that new rid is a generalisation of original rid
791                 // Note: This is only of interest for client operation
792                 if (oldcmd == PIOC_STARTTLS_CLIENT_V2) {
793                         selector_t newrid = donai_from_stable_string (rid, strlen (rid));
794                         donai_t oldrid = donai_from_stable_string (cmd->orig_piocdata->remoteid, strlen (cmd->orig_piocdata->remoteid));
795                         if (!donai_matches_selector (&oldrid, &newrid)) {
796                                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
797                         }
798                 }
799                 //
800                 // Add (rid,lid) to db_disclose for acceptance.
801                 // Note that this is done within the STARTTLS transaction.
802                 // Upon secure setup failure this change will roll back.
803                 //TODO// Client => add (rid,lid) to db_disclose within cmd->txn
804                 //TODO// Decide how to deal with lower-level overrides
805                 //
806                 // Now reiterate to lookup lid credentials in db_localid
807                 E_g2e ("Missing local credentials",
808                         fetch_local_credentials (cmd));
809         }
810         if (cmd->lids [lidtype - LID_TYPE_MIN].data == NULL) {
811                 E_g2e ("Missing certificate for local ID",
812                         GNUTLS_E_NO_CERTIFICATE_FOUND);
813                 return gtls_errno;
814         }
815
816         //
817         // Split the credential into its various aspects
818         ok = dbcred_interpret (
819                 &cmd->lids [lidtype - LID_TYPE_MIN],
820                 &flags,
821                 &p11priv,
822                 &certdatum.data,
823                 &certdatum.size);
824         tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, p11priv=\"%s\", cert.size=%d", flags, p11priv, certdatum.size);
825         //TODO// ok = ok && verify_cert_... (...); -- keyidlookup
826         if (!ok) {
827                 gtls_errno = GNUTLS_E_CERTIFICATE_ERROR;
828         }
829
830         //
831         // Allocate response structures
832         *pcert_length = 0;
833         *pcert = load_certificate_chain (flags, pcert_length, &certdatum);
834         if (*pcert == NULL) {
835                 E_g2e ("Failed to load certificate chain",
836                         GNUTLS_E_CERTIFICATE_ERROR);
837                 return gtls_errno;
838         }
839         cmd->session_certificate = (intptr_t) (void *) *pcert;  //TODO// Used for session cleanup
840
841         //
842         // Setup private key
843         E_g2e ("Failed to initialise private key",
844                 gnutls_privkey_init (
845                         pkey));
846         if (gtls_errno == GNUTLS_E_SUCCESS) {
847                 cmd->session_privatekey = (intptr_t) (void *) *pkey;    //TODO// Used for session cleanup
848         }
849         E_g2e ("Failed to import PKCS #11 private key URL",
850                 gnutls_privkey_import_pkcs11_url (
851                         *pkey,
852                         p11priv));
853         E_gnutls_clear_errno ();
854
855 //TODO// Moved out (start)
856
857         //
858         // Setup public key certificate
859         switch (lidtype) {
860         case LID_TYPE_X509:
861                 E_g2e ("Failed to import X.509 certificate into chain",
862                         gnutls_pcert_import_x509_raw (
863                                 *pcert,
864                                 &certdatum,
865                                 GNUTLS_X509_FMT_DER,
866                                 0));
867                 break;
868         case LID_TYPE_PGP:
869                 E_g2e ("Failed to import OpenPGP certificate",
870                         gnutls_pcert_import_openpgp_raw (
871                                 *pcert,
872                                 &certdatum,
873                                 GNUTLS_OPENPGP_FMT_RAW,
874                                 NULL,   /* use master key */
875                                 0));
876                 break;
877         default:
878                 /* Should not happen */
879                 break;
880         }
881
882 //TODO// Moved out (end)
883
884         //
885         // Lap up any overseen POSIX error codes in errno
886         if (errno) {
887                 tlog (TLOG_TLS, LOG_DEBUG, "Failing TLS on errno=%d / %s", errno, strerror (errno));
888                 cmd->session_errno = errno;
889                 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
890         }
891
892         //
893         // Return the overral error code, hopefully GNUTLS_E_SUCCESS
894         tlog (TLOG_TLS, LOG_DEBUG, "Returning %d / %s from clisrv_cert_retrieve()", gtls_errno, gnutls_strerror (gtls_errno));
895         return gtls_errno;
896 }
897
898 /* Load a single certificate in the given gnutls_pcert_st from the given
899  * gnutls_datum_t.  Use the lidtype to determine how to do this.
900  */
901 gtls_error load_certificate (int lidtype, gnutls_pcert_st *pcert, gnutls_datum_t *certdatum) {
902         int gtls_errno = GNUTLS_E_SUCCESS;
903         //
904         // Setup public key certificate
905         switch (lidtype) {
906         case LID_TYPE_X509:
907                 E_g2e ("Failed to import X.509 certificate into chain",
908                         gnutls_pcert_import_x509_raw (
909                                 pcert,
910                                 certdatum,
911                                 GNUTLS_X509_FMT_DER,
912                                 0));
913                 break;
914         case LID_TYPE_PGP:
915                 E_g2e ("Failed to import OpenPGP certificate",
916                         gnutls_pcert_import_openpgp_raw (
917                                 pcert,
918                                 certdatum,
919                                 GNUTLS_OPENPGP_FMT_RAW,
920                                 NULL,   /* use master key */
921                                 0));
922                 break;
923         default:
924                 /* Should not happen */
925                 break;
926         }
927         return gtls_errno;
928 }
929
930
931 /* Load a certificate chain.  This returns a value for a retrieval function's
932  * pcert, and also modifies the chainlen.  The latter starts at 0, and is
933  * incremented in a nested procedure that unrolls until all certificates are
934  * loaded.
935  */
936 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum) {
937         gnutls_pcert_st *chain;
938         unsigned int mypos = *chainlen;
939         int gtls_errno = GNUTLS_E_SUCCESS;
940
941         //
942         // Quick and easy: No chaining required, just add the literal data.
943         // Note however, this may be the end of a chain, so allocate all
944         // structures and load the single one at the end.
945         if ((flags & (LID_CHAINED | LID_NEEDS_CHAIN)) == 0) {
946                 (*chainlen)++;
947                 chain = (gnutls_pcert_st *) calloc (*chainlen, sizeof (gnutls_pcert_st));
948                 if (chain != NULL) {
949                         bzero (chain, (*chainlen) * sizeof (gnutls_pcert_st));
950                 } else {
951                         gtls_errno = GNUTLS_E_MEMORY_ERROR;
952                 }
953                 E_g2e ("Failed to load certificate into chain",
954                         load_certificate (
955                                 flags & LID_TYPE_MASK,
956                                 &chain [mypos],
957                                 certdatum));
958                 if (gtls_errno != GNUTLS_E_SUCCESS) {
959                         if (chain) {
960                                 free (chain);
961                         }
962                         *chainlen = 0;
963                         chain = NULL;
964                 }
965                 return chain;
966         }
967
968         //
969         // First extended case.  Chain certs in response to LID_CHAINED.
970         // Recursive calls are depth-first, so we only add our first cert
971         // after a recursive call succeeds.  Any LID_NEEDS_CHAIN work is
972         // added after LID_CHAINED, so is higher up in the hierarchy, but
973         // it is loaded as part of the recursion.  To support that, a
974         // recursive call with certdatum.size==0 is possible when the
975         // LID_NEEDS_CHAIN flag is set, and this section then skips.
976         // Note that this code is also used to load the certificate chain
977         // provided by LID_NEEDS_CHAIN, but by then the flag in a recursive
978         // call is replaced with LID_CHAINED and no more LID_NEEDS_CHAIN.
979         if (((flags & LID_CHAINED) != 0) && (certdatum->size > 0)) {
980                 long certlen;
981                 int lenlen;
982                 gnutls_datum_t nextdatum;
983                 long nextlen;
984                 // Note: Accept BER because the outside SEQUENCE is not signed
985                 certlen = asn1_get_length_ber (
986                         ((char *) certdatum->data) + 1,
987                         certdatum->size,
988                         &lenlen);
989                 certlen += 1 + lenlen;
990                 tlog (TLOG_CERT, LOG_DEBUG, "Found LID_CHAINED certificate size %d", certlen);
991                 if (certlen > certdatum->size) {
992                         tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate beyond data size %d", certdatum->size);
993                         *chainlen = 0;
994                         return NULL;
995                 } else if (certlen <= 0) {
996                         tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate of too-modest data size %d", certlen);
997                         *chainlen = 0;
998                         return NULL;
999                 }
1000                 nextdatum.data = ((char *) certdatum->data) + certlen;
1001                 nextdatum.size =           certdatum->size  - certlen;
1002                 certdatum->size = certlen;
1003                 nextlen = asn1_get_length_ber (
1004                         ((char *) nextdatum.data) + 1,
1005                         nextdatum.size,
1006                         &lenlen);
1007                 nextlen += 1 + lenlen;
1008                 if (nextlen == nextdatum.size) {
1009                         // The last cert is loaded thinking it is not CHAINED,
1010                         // but NEEDS_CHAIN can still be present for expansion.
1011                         flags &= ~LID_CHAINED;
1012                 }
1013                 (*chainlen)++;
1014                 chain = load_certificate_chain (flags, chainlen, &nextdatum);
1015                 if (chain != NULL) {
1016                         E_g2e ("Failed to add chained certificate",
1017                                 load_certificate (
1018                                         flags & LID_TYPE_MASK,
1019                                         &chain [mypos],
1020                                         certdatum));
1021                         if (gtls_errno != GNUTLS_E_SUCCESS) {
1022                                 free (chain);
1023                                 chain = NULL;
1024                                 *chainlen = 0;
1025                         }
1026                 }
1027                 return chain;
1028         }
1029
1030         //
1031         // Second extended case.  Chain certs in response to LID_NEEDS_CHAIN.
1032         // These are the highest-up in the hierarchy, above any LID_CHAINED
1033         // certificates.  The procedure for adding them is looking them up
1034         // in a central database by their authority key identifier.  What is
1035         // found is assumed to be a chain, and will be unrolled by replacing
1036         // the LID_NEEDS_CHAIN flag with LID_CHAINED and calling recursively.
1037         if (((flags & LID_NEEDS_CHAIN) != 0) && (certdatum->size == 0)) {
1038                 //TODO//CODE// lookup new certdatum
1039                 flags &= ~LID_NEEDS_CHAIN;
1040                 flags |=  LID_CHAINED;
1041                 //TODO//CODE// recursive call
1042                 //TODO//CODE// no structures to fill here
1043                 //TODO//CODE// cleanup new certdatum
1044         }
1045
1046         //
1047         // Final judgement.  Nothing worked.  Return failure.
1048         *chainlen = 0;
1049         return NULL;
1050 }
1051
1052
1053 /* Fetch local credentials.  This can be done before TLS is started, to find
1054  * the possible authentication forms that can be offered.  The function
1055  * can additionally be used after interaction with the client to establish
1056  * a local identity that was not initially provided, or that was not
1057  * considered public at the time.
1058  */
1059 gtls_error fetch_local_credentials (struct command *cmd) {
1060         int lidrole;
1061         char *lid, *rid;
1062         DBC *crs_disclose = NULL;
1063         DBC *crs_localid = NULL;
1064         DBT discpatn;
1065         DBT keydata;
1066         DBT creddata;
1067         selector_t remote_selector;
1068         int gtls_errno = 0;
1069         int db_errno = 0;
1070         int found = 0;
1071
1072         //
1073         // Setup a number of common references and structures
1074         if (cmd->cmd.pio_cmd == PIOC_STARTTLS_SERVER_V2) {
1075                 lidrole = LID_ROLE_SERVER;
1076         } else if (cmd->cmd.pio_cmd == PIOC_STARTTLS_CLIENT_V2) {
1077                 lidrole = LID_ROLE_CLIENT;
1078         } else {
1079                 E_g2e ("TLS Pool command is not _STARTTLS_",
1080                         GNUTLS_E_INVALID_SESSION);
1081                 return gtls_errno;
1082         }
1083         lid = cmd->cmd.pio_data.pioc_starttls.localid;
1084         rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1085
1086         //
1087         // Refuse to disclose client credentials when the server name is unset;
1088         // note that server-claimed identities are unproven during handshake.
1089         if ((lidrole == LID_ROLE_CLIENT) && (*rid == '\0')) {
1090                 tlog (TLOG_USER, LOG_ERR, "No remote identity (server name) set, so no client credential disclosure");
1091                 E_g2e ("Missing remote ID",
1092                         GNUTLS_E_NO_CERTIFICATE_FOUND);
1093                 return gtls_errno;
1094         }
1095         //
1096         // Setup database iterators to map identities to credentials
1097         if (lidrole == LID_ROLE_CLIENT) {
1098                 E_d2e ("Failed to create db_disclse cursor",
1099                         dbh_disclose->cursor (
1100                                 dbh_disclose,
1101                                 cmd->txn,
1102                                 &crs_disclose,
1103                                 0));
1104         }
1105         E_d2e ("Failed to create db_localid cursor",
1106                 dbh_localid->cursor (
1107                         dbh_localid,
1108                         cmd->txn,
1109                         &crs_localid,
1110                         0));
1111         //
1112         // Prepare for iteration over possible local identities / credentials
1113         char mid [128];
1114         char cid [128];
1115         if (gtls_errno != 0) {
1116                 ; // Skip setup
1117         } else if (lidrole == LID_ROLE_CLIENT) {
1118                 memcpy (cid, rid, sizeof (cid));
1119                 dbt_init_fixbuf (&discpatn, cid, strlen (cid));
1120                 dbt_init_fixbuf (&keydata,  mid, sizeof (mid)-1);
1121                 dbt_init_malloc (&creddata);
1122                 selector_t ridsel;
1123                 donai_t remote_donai = donai_from_stable_string (rid, strlen (rid));
1124                 if (!selector_iterate_init (&remote_selector, &remote_donai)) {
1125                         E_g2e ("Syntax of remote ID unsuitable for selector",
1126                                 GNUTLS_E_INVALID_REQUEST);
1127                 } else {
1128                         E_d2e ("Failed to start iterator on remote ID selector",
1129                                 dbcred_iterate_from_remoteid_selector (
1130                                         crs_disclose,
1131                                         crs_localid,
1132                                         &remote_selector,
1133                                         &discpatn,
1134                                         &keydata,
1135                                         &creddata));
1136                 }
1137         } else {
1138                 dbt_init_fixbuf (&discpatn, "", 0);     // Unused but good style
1139                 dbt_init_fixbuf (&keydata,  lid, strlen (lid));
1140                 dbt_init_malloc (&creddata);
1141                 E_d2e ("Failed to start iterator on local ID",
1142                         dbcred_iterate_from_localid (
1143                         crs_localid,
1144                         &keydata,
1145                         &creddata));
1146         }
1147         if (db_errno != 0) {
1148                 gtls_errno = GNUTLS_E_DB_ERROR;
1149         }
1150
1151         //
1152         // Now store the local identities inasfar as they are usable
1153         db_errno = 0;
1154         while ((gtls_errno == GNUTLS_E_SUCCESS) && (db_errno == 0)) {
1155                 int ok;
1156                 uint32_t flags;
1157                 int lidtype;
1158
1159                 tlog (TLOG_DB, LOG_DEBUG, "Found BDB entry %s disclosed to %s", creddata.data + 4, (lidrole == LID_ROLE_CLIENT)? rid: "all clients");
1160                 ok = dbcred_flags (
1161                         &creddata,
1162                         &flags);
1163                 lidtype = flags & LID_TYPE_MASK;
1164                 ok = ok && ((flags & lidrole) != 0);
1165                 ok = ok && ((flags & LID_NO_PKCS11) == 0);
1166                 ok = ok && (lidtype >= LID_TYPE_MIN);
1167                 ok = ok && (lidtype <= LID_TYPE_MAX);
1168                 tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, so we (%04x/%04x) %s it", flags, lidrole, LID_ROLE_MASK, ok? "store": "skip ");
1169                 if (ok) {
1170                         // Move the credential into the command structure
1171                         dbt_store (&creddata,
1172                                 &cmd->lids [lidtype - LID_TYPE_MIN]);
1173                         found = 1;
1174                 } else {
1175                         // Skip the credential by freeing its data structure
1176                         dbt_free (&creddata);
1177                 }
1178                 db_errno = dbcred_iterate_next (crs_disclose, crs_localid, &discpatn, &keydata, &creddata);
1179         }
1180
1181         if (db_errno == DB_NOTFOUND) {
1182                 if (!found) {
1183                         gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1184                 }
1185         }
1186         if (crs_localid != NULL) {
1187                 crs_localid->close (crs_localid);
1188                 crs_localid = NULL;
1189         }
1190         if (crs_disclose != NULL) {
1191                 crs_disclose->close (crs_disclose);
1192                 crs_disclose = NULL;
1193         }
1194         return gtls_errno;
1195 }
1196
1197
1198 /* The callback functions retrieve various bits of information for the client
1199  * or server in the course of the handshake procedure.
1200  *
1201  * The logic here is based on client-sent information, such as:
1202  *  - TLS hints -- X.509 or alternatives like OpenPGP, SRP, PSK
1203  *  - TLS hints -- Server Name Indication
1204  *  - User hints -- local and remote identities provided
1205  */
1206 int srv_clienthello (gnutls_session_t session) {
1207         struct command *cmd;
1208         char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)]; // static
1209         size_t snilen = sizeof (sni);
1210         int snitype;
1211         int gtls_errno = GNUTLS_E_SUCCESS;
1212         char *lid;
1213
1214         //
1215         // Setup a number of common references
1216         cmd = (struct command *) gnutls_session_get_ptr (session);
1217         if (cmd == NULL) {
1218                 return GNUTLS_E_INVALID_SESSION;
1219         }
1220         lid = cmd->cmd.pio_data.pioc_starttls.localid;
1221
1222         //
1223         // Find the client-helloed ServerNameIndication, or the service name
1224         sni [0] = '\0';
1225         if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) == 0) {
1226                 switch (snitype) {
1227                 case GNUTLS_NAME_DNS:
1228                         break;
1229                 // Note: In theory, other name types could be sent, and it would
1230                 // be useful to access indexes beyond 0.  In practice, nobody
1231                 // uses other name types than exactly one GNUTLS_NAME_DNS.
1232                 default:
1233                         sni [0] = '\0';
1234                         tlog (TLOG_TLS, LOG_ERR, "Received an unexpected SNI type; that is possible but uncommon; skipping SNI");
1235                         break;
1236                 }
1237         }
1238         if (sni [0] != '\0') {
1239                 if (*lid != '\0') {
1240                         if (strncmp (sni, lid, sizeof (sni)) != 0) {
1241                                 tlog (TLOG_USER | TLOG_TLS, LOG_ERR, "Mismatch between client-sent SNI %s and local identity %s", sni, lid);
1242                                 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
1243                         }
1244                 } else {
1245                         memcpy (lid, sni, sizeof (sni));
1246                 }
1247         } else {
1248                 memcpy (sni, lid, sizeof (sni)-1);
1249                 sni [sizeof (sni) - 1] = '\0';
1250         }
1251
1252         //
1253         // Lap up any unnoticed POSIX error messages
1254         if (errno != 0) {
1255                 cmd->session_errno = errno;
1256                 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
1257         }
1258
1259         //
1260         // Round off with an overal judgement
1261         return gtls_errno;
1262 }
1263
1264
1265 int cli_srpcreds_retrieve (gnutls_session_t session,
1266                                 char **username,
1267                                 char **password) {
1268         //TODO:FIXED//
1269         tlog (TLOG_CRYPTO, LOG_DEBUG, "DEBUG: Picking up SRP credentials");
1270         *username = strdup ("tester");
1271         *password = strdup ("test");
1272         return GNUTLS_E_SUCCESS;
1273 }
1274
1275
1276 /* Setup credentials to be shared by all clients and servers.
1277  * Credentials are generally implemented through callback functions.
1278  * This should be called after setting up DH parameters.
1279  */
1280 int setup_starttls_credentials (void) {
1281         gnutls_anon_server_credentials_t srv_anoncred = NULL;
1282         gnutls_anon_client_credentials_t cli_anoncred = NULL;
1283         gnutls_certificate_credentials_t clisrv_certcred = NULL;
1284         //TODO:NOTHERE// int srpbits;
1285         gnutls_srp_server_credentials_t srv_srpcred = NULL;
1286         gnutls_srp_client_credentials_t cli_srpcred = NULL;
1287         //TODO// gnutls_kdh_server_credentials_t srv_kdhcred = NULL;
1288         //TODO// gnutls_kdh_server_credentials_t cli_kdhcred = NULL;
1289         int gtls_errno = GNUTLS_E_SUCCESS;
1290         int gtls_errno_stack0;
1291
1292         //
1293         // Construct certificate credentials for X.509 and OpenPGP cli/srv
1294         E_g2e ("Failed to allocate certificate credentials",
1295                 gnutls_certificate_allocate_credentials (
1296                         &clisrv_certcred));
1297         //TODO// What to do here when we add locking on DH params?
1298         gnutls_certificate_set_dh_params (
1299                 clisrv_certcred,
1300                 dh_params);
1301         gtls_errno_stack0 = gtls_errno;
1302         /* TODO: Bad code.  GnuTLS 3.2.1 ignores retrieve_function2 when
1303          * checking if it can handle the OpenPGP certificate type in
1304          * _gnutls_session_cert_type_supported (gnutls_status.c:175) but
1305          * it does see the "1" version field.  It does not callback the
1306          * "1" version if "2" is present though.
1307          */
1308         if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function (
1309                 clisrv_certcred,
1310                 (void *) exit);
1311         if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function2 (
1312                 clisrv_certcred,
1313                 clisrv_cert_retrieve);
1314         if (gtls_errno == GNUTLS_E_SUCCESS) {
1315                 // Setup for certificates
1316                 tlog (TLOG_CERT, LOG_INFO, "Setting client and server certificate credentials");
1317                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
1318                 cli_creds [cli_credcount].cred   = (void *) clisrv_certcred;
1319                 cli_credcount++;
1320                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
1321                 srv_creds [srv_credcount].cred   = (void *) clisrv_certcred;
1322                 srv_credcount++;
1323         } else if (clisrv_certcred != NULL) {
1324                 gnutls_certificate_free_credentials (clisrv_certcred);
1325                 clisrv_certcred = NULL;
1326         }
1327
1328         //
1329         // Construct anonymous server credentials
1330         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1331         E_g2e ("Failed to allocate ANON-DH server credentials",
1332                 gnutls_anon_allocate_server_credentials (
1333                         &srv_anoncred));
1334         if (!have_error_codes ()) /* E_g2e (...) */ gnutls_anon_set_server_dh_params (
1335                 srv_anoncred,
1336                 dh_params);
1337         if (gtls_errno == GNUTLS_E_SUCCESS) {
1338                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server anonymous credentials");
1339                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_ANON;
1340                 srv_creds [srv_credcount].cred   = (void *) srv_anoncred;
1341                 srv_credcount++;
1342         } else if (srv_anoncred != NULL) {
1343                 gnutls_anon_free_server_credentials (srv_anoncred);
1344                 srv_anoncred = NULL;
1345         }
1346
1347 #ifdef MIRROR_IMAGE_OF_SERVER_ANONYMOUS_CREDENTIALS
1348         //
1349         // Construct anonymous client credentials
1350         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1351         E_g2e ("Failed to allocate ANON-DH client credentials",
1352                 gnutls_anon_allocate_client_credentials (
1353                         &cli_anoncred));
1354         if (!have_error_codes ()) gnutls_anon_set_client_dh_params (
1355                 cli_anoncred,
1356                 dh_params);
1357         if (gtls_errno == GNUTLS_E_SUCCESS) {
1358                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client anonymous credentials");
1359                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_ANON;
1360                 cli_creds [cli_credcount].cred   = (void *) cli_anoncred;
1361                 cli_credcount++;
1362         } else if (cli_anoncred != NULL) {
1363                 gnutls_anon_free_client_credentials (cli_anoncred);
1364                 cli_anoncred = NULL;
1365         }
1366 #endif
1367
1368         //
1369         // Construct server credentials for SRP authentication
1370         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1371         E_g2e ("Failed to allocate SRP server credentials",
1372                 gnutls_srp_allocate_server_credentials (
1373                         &srv_srpcred));
1374         E_g2e ("Failed to set SRP server credentials",
1375                 gnutls_srp_set_server_credentials_file (
1376                         srv_srpcred,
1377                         "../testdata/tlspool-test-srp.passwd",
1378                         "../testdata/tlspool-test-srp.conf"));
1379         if (gtls_errno == GNUTLS_E_SUCCESS) {
1380                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server SRP credentials");
1381                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_SRP;
1382                 srv_creds [srv_credcount].cred   = (void *) srv_srpcred;
1383                 srv_credcount++;
1384         } else if (srv_srpcred != NULL) {
1385                 gnutls_srp_free_server_credentials (srv_srpcred);
1386                 srv_srpcred = NULL;
1387         }
1388
1389         //
1390         // Construct client credentials for SRP authentication
1391         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1392         E_g2e ("Failed to allocate SRP client credentials",
1393                 gnutls_srp_allocate_client_credentials (
1394                         &cli_srpcred));
1395         if (!have_error_codes ()) gnutls_srp_set_client_credentials_function (
1396                 cli_srpcred,
1397                 cli_srpcreds_retrieve);
1398         if (gtls_errno == GNUTLS_E_SUCCESS) {
1399                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client SRP credentials");
1400                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_SRP;
1401                 cli_creds [cli_credcount].cred   = (void *) cli_srpcred;
1402                 cli_credcount++;
1403         } else if (cli_srpcred != NULL) {
1404                 gnutls_srp_free_client_credentials (cli_srpcred);
1405                 cli_srpcred = NULL;
1406         }
1407
1408         //
1409         // Construct server credentials for KDH authentication
1410         //TODO// gtls_errno = gtls_errno_stack0;        // Don't pop, just forget last failures
1411         //TODO// E_g2e ("Failed to allocate KDH server credentials",
1412         //TODO//        gnutls_kdh_allocate_server_credentials (
1413         //TODO//                &srv_kdhcred));
1414         //TODO// E_g2e ("Failed to set KDH server DH params",
1415         //TODO//        gnutls_kdh_set_server_dh_params (
1416         //TODO//                srv_kdhcred,
1417         //TODO//                dh_params));
1418         //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
1419         //TODO//        tlog (TLOG_CRYPTO, LOG_INFO, "Setting server KDH credentials");
1420         //TODO//        srv_creds [srv_credcount].credtp = GNUTLS_CRD_KDH;
1421         //TODO//        srv_creds [srv_credcount].cred   = (void *) srv_kdhcred;
1422         //TODO//        srv_credcount++;
1423         //TODO// } else if (srv_kdhcred != NULL) {
1424         //TODO//        gnutls_kdh_free_server_credentials (srv_kdhcred);
1425         //TODO//        srv_kdhcred = NULL;
1426         //TODO// }
1427
1428         //
1429         // Construct client credentials for KDH
1430         //TODO// gtls_errno = gtls_errno_stack0;        // Don't pop, just forget last failures
1431         //TODO// E_g2e ("Failed to allocate KDH client credentials",
1432         //TODO//        gnutls_kdh_allocate_client_credentials (
1433         //TODO//                &cli_kdhcred));
1434         //TODO// E_g2e ("Failed to set KDH client credentials",
1435         //TODO//        gnutls_kdh_set_client_credentials_function (
1436         //TODO//                cli_kdhcred,
1437         //TODO//                cli_kdh_retrieve));
1438         //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
1439         //TODO//        tlog (TLOG_CRYPTO, LOG_INFO, "Setting client KDH credentials");
1440         //TODO//        cli_creds [cli_credcount].credtp = GNUTLS_CRD_KDH;
1441         //TODO//        cli_creds [cli_credcount].cred   = (void *) cli_kdhcred;
1442         //TODO//        cli_credcount++;
1443         //TODO// } else if (cli_kdhcred != NULL) {
1444         //TODO//        gnutls_kdh_free_client_credentials (cli_kdhcred);
1445         //TODO//        cli_kdhcred = NULL;
1446         //TODO// }
1447
1448         //
1449         // Ensure that at least one credential has been set
1450         // TODO: Look at the counters; but at boot, we can require all okay
1451         if ((gtls_errno == GNUTLS_E_SUCCESS) &&
1452                         ( (cli_credcount != EXPECTED_CLI_CREDCOUNT) ||
1453                           (srv_credcount != EXPECTED_SRV_CREDCOUNT) ) ) {
1454                 tlog (TLOG_CRYPTO, LOG_ERR, "Not all credential types could be setup (cli %d/%d, srv %d/%d, gtls_errno %d)", cli_credcount, EXPECTED_CLI_CREDCOUNT, srv_credcount, EXPECTED_SRV_CREDCOUNT, gtls_errno);
1455                 E_g2e ("Not all credentials could be setup",
1456                         GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1457         }
1458
1459         //
1460         // Report overall error or success
1461         return gtls_errno;
1462 }
1463
1464
1465 /* Cleanup all credentials created, just before exiting the daemon.
1466  */
1467 void cleanup_starttls_credentials (void) {
1468         while (srv_credcount-- > 0) {
1469                 struct credinfo *crd = &srv_creds [srv_credcount];
1470                 switch (crd->credtp) {
1471                 case GNUTLS_CRD_CERTIFICATE:
1472                         // Shared with client; skipped in server and removed in client
1473                         // gnutls_certificate_free_credentials (crd->cred);
1474                         break;
1475                 case GNUTLS_CRD_ANON:
1476                         gnutls_anon_free_server_credentials (crd->cred);
1477                         break;
1478                 case GNUTLS_CRD_SRP:
1479                         gnutls_srp_free_server_credentials (crd->cred);
1480                         break;
1481                 //TODO// case GNUTLS_CRD_KDH:
1482                 //TODO//        gnutls_kdh_free_server_credentials (crd->cred);
1483                 //TODO//        break;
1484                 }
1485         }
1486         while (cli_credcount-- > 0) {
1487                 struct credinfo *crd = &cli_creds [cli_credcount];
1488                 switch (crd->credtp) {
1489                 case GNUTLS_CRD_CERTIFICATE:
1490                         // Shared with client; skipped in server and removed in client
1491                         gnutls_certificate_free_credentials (crd->cred);
1492                         break;
1493                 case GNUTLS_CRD_ANON:
1494                         gnutls_anon_free_client_credentials (crd->cred);
1495                         break;
1496                 case GNUTLS_CRD_SRP:
1497                         gnutls_srp_free_client_credentials (crd->cred);
1498                         break;
1499                 //TODO// case GNUTLS_CRD_KDH:
1500                 //TODO//        gnutls_kdh_free_client_credentials (crd->cred);
1501                 //TODO//        break;
1502                 }
1503         }
1504 }
1505
1506
1507 /*
1508  * Check if a given cmd has the given LID_TYPE setup.
1509  * Return 1 for yes or 0 for no; this is used in priority strings.
1510  */
1511 static inline int lidtpsup (struct command *cmd, int lidtp) {
1512         return cmd->lids [lidtp - LID_TYPE_MIN].data != NULL;
1513 }
1514
1515 /*
1516  * The starttls_thread is a main program for the setup of a TLS connection,
1517  * either in client mode or server mode.  Note that the distinction between
1518  * client and server mode is only a TLS concern, but not of interest to the
1519  * application or the records exchanged.
1520  *
1521  * If the STARTTLS operation succeeds, this will be reported back to the
1522  * application, but the TLS pool will continue to be active in a copycat
1523  * procedure: encrypting outgoing traffic and decrypting incoming traffic.
1524  * TODO: Are client and server routines different?
1525  */
1526 static void *starttls_thread (void *cmd_void) {
1527         struct command *cmd;
1528         struct pioc_starttls orig_piocdata;
1529         uint32_t orig_cmd;
1530         int plainfd = -1;
1531         int cryptfd = -1;
1532         int clientfd;
1533         gnutls_session_t session;
1534         int gtls_errno = GNUTLS_E_SUCCESS;
1535         int i;
1536         struct credinfo *clisrv_creds;
1537         int clisrv_credcount;
1538
1539         //
1540         // General thread setup
1541         cmd = (struct command *) cmd_void;
1542         if (cmd == NULL) {
1543                 send_error (cmd, EINVAL, "Command structure not received");
1544                 return;
1545         }
1546         cmd->session_errno = 0;
1547         orig_cmd = cmd->cmd.pio_cmd;
1548         memcpy (&orig_piocdata, &cmd->cmd.pio_data.pioc_starttls, sizeof (orig_piocdata));
1549         cmd->orig_piocdata = &orig_piocdata;
1550         cryptfd = cmd->passfd;
1551         cmd->passfd = -1;
1552         if (cryptfd < 0) {
1553                 tlog (TLOG_UNIXSOCK, LOG_ERR, "No ciphertext file descriptor supplied to TLS Pool");
1554                 send_error (cmd, EINVAL, "No ciphertext file descriptor supplied to TLS Pool");
1555                 return;
1556         }
1557         clientfd = cmd->clientfd;
1558         cmd->session_certificate = (intptr_t) (void *) NULL;
1559         cmd->session_privatekey = (intptr_t) (void *) NULL;
1560
1561         //
1562         // Setup BDB transactions and reset credential datum fields
1563         bzero (&cmd->lids, sizeof (cmd->lids)); //TODO: Probably double work?
1564         manage_txn_begin (&cmd->txn);
1565
1566         //
1567         // Permit cancellation of this thread -- TODO: Cleanup?
1568         errno = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
1569         if (errno != 0) {
1570                 send_error (cmd, ESRCH, "STARTTLS handler thread cancellability refused");
1571                 return;
1572         }
1573         //
1574         // Check and setup the plaintext file handle
1575         if (cryptfd == -1) {
1576                 send_error (cmd, EPROTO, "You must supply a TLS-protected socket");
1577                 return;
1578         }
1579
1580         //
1581         // Negotiate TLS; split client/server mode setup
1582         if (orig_cmd == PIOC_STARTTLS_SERVER_V2) {
1583                 //
1584                 // Setup as a TLS server
1585                 //
1586                 E_g2e ("Failed to initialise GnuTLS server session",
1587                         gnutls_init (
1588                                 &session,
1589                                 GNUTLS_SERVER));
1590                 if (gtls_errno == GNUTLS_E_SUCCESS) {
1591                         gnutls_session_set_ptr (session, cmd);
1592                         gnutls_handshake_set_post_client_hello_function (
1593                                 session,
1594                                 srv_clienthello);
1595                 }
1596                 //
1597                 // Setup for server credential installation in this session
1598                 clisrv_creds     = srv_creds;
1599                 clisrv_credcount = srv_credcount;
1600
1601         } else if (orig_cmd == PIOC_STARTTLS_CLIENT_V2) {
1602                 //
1603                 // Setup as a TLS client
1604                 //
1605                 int srpbits;
1606                 //
1607                 // Require a minimum security level for SRP
1608                 srpbits = 3072;
1609                 //TODO:CRASH// if (gtls_errno == GNUTLS_E_SUCCESS) gnutls_srp_set_prime_bits (
1610                         //TODO:CRASH// session,
1611                         //TODO:CRASH// srpbits);
1612                 //
1613                 // Setup as a TLS client
1614                 E_g2e ("Failed to initialise GnuTLS client session",
1615                         gnutls_init (
1616                                 &session,
1617                                 GNUTLS_CLIENT));
1618                 if (gtls_errno == GNUTLS_E_SUCCESS) {
1619                         gnutls_session_set_ptr (
1620                                 session,
1621                                 cmd);
1622                 }
1623                 //
1624                 // Setup for potential sending of SNI
1625                 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_SEND_SNI) {
1626                         char *str = cmd->cmd.pio_data.pioc_starttls.remoteid;
1627                         int len = 0;
1628                         while (str [len] && (len < 128)) {
1629                                 len++;
1630                         }
1631                         if (len == 128) {
1632                                 send_error (cmd, EINVAL, "Remote ID is not set");
1633                                 close (cryptfd);
1634                                 return;
1635                         }
1636                         cmd->cmd.pio_data.pioc_starttls.remoteid [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)-1] = '\0';
1637                         E_g2e ("Client failed to setup SNI",
1638                                 gnutls_server_name_set (
1639                                         session,
1640                                         GNUTLS_NAME_DNS,
1641                                         str,
1642                                         len));
1643                 }
1644                 //
1645                 // Setup for client credential installation in this session
1646                 clisrv_creds     = cli_creds;
1647                 clisrv_credcount = cli_credcount;
1648
1649         } else {
1650                 //
1651                 // Neither a TLS client nor a TLS server
1652                 //
1653                 send_error (cmd, ENOTSUP, "Command not supported");
1654                 close (cryptfd);
1655                 return;
1656         }
1657
1658         //
1659         // Install the shared credentials for the client or server role
1660         for (i=0; i<clisrv_credcount; i++) {
1661                 E_g2e ("Failed to install credentials into TLS session",
1662                         gnutls_credentials_set (
1663                                 session,
1664                                 clisrv_creds [i].credtp,
1665                                 clisrv_creds [i].cred  ));
1666         }
1667
1668         //
1669         // Prefetch local identities that might be used in this session
1670         E_g2e ("Failed to fetch local credentials",
1671                 fetch_local_credentials (cmd));
1672
1673         //
1674         // Setup the priority string for this session; this avoids future
1675         // credential callbacks that ask for something impossible or
1676         // undesired.
1677         //
1678         // Variation factors:
1679         //  - starting configuration (can it be empty?)
1680         //  - Configured security parameters (database? variable?)
1681         //  - CTYPEs, SRP, ANON-or-not --> fill in as + or - characters
1682         //TODO// Support for ANON-DH where appropriate
1683         if (gtls_errno == GNUTLS_E_SUCCESS) {
1684                 char priostr [256];
1685                 snprintf (priostr, sizeof (priostr)-1,
1686                         "NORMAL:"
1687                         "%cCTYPE-X.509:"
1688                         "%cCTYPE-OPENPGP:"
1689                         "%cSRP:%cSRP-RSA:%cSRP-DSS:"
1690                         "%cANON-ECDH:%cANON-DH",
1691                         lidtpsup (cmd, LID_TYPE_X509)           ?'+':'-',
1692                         lidtpsup (cmd, LID_TYPE_PGP)            ?'+':'-',
1693                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
1694                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
1695                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
1696                         0 /* TODO: ANON-DH */                   ?'+':'-',
1697                         0 /* TODO: ANON-DH */                   ?'+':'-');
1698                 tlog (TLOG_TLS, LOG_DEBUG, "Constructed priority string %s for local ID %s",
1699                         priostr, cmd->cmd.pio_data.pioc_starttls.localid);
1700                 E_g2e ("Failed to set GnuTLS priority string",
1701                         gnutls_priority_set_direct (
1702                         session,
1703                         // "NORMAL:-KX-ALL:+SRP:+SRP-RSA:+SRP-DSS",
1704                         // "NORMAL:+CTYPE-X.509:-CTYPE-OPENPGP:+CTYPE-X.509",
1705                         // "NORMAL:-CTYPE-X.509:+CTYPE-OPENPGP:-CTYPE-X.509",
1706                         // "NORMAL:+ANON-ECDH:+ANON-DH",
1707                         priostr,
1708                         NULL));
1709         }
1710
1711         //
1712         // Check if past code stored an error code through POSIX
1713         if (cmd->session_errno) {
1714                 gtls_errno = GNUTLS_E_USER_ERROR;
1715         }
1716
1717         //
1718         // Now setup for the GnuTLS handshake
1719         //
1720         if (gtls_errno == GNUTLS_E_SUCCESS) {
1721                 gnutls_transport_set_int (session, cryptfd);
1722                 gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
1723         }
1724         if (gtls_errno != GNUTLS_E_SUCCESS) {
1725                 tlog (TLOG_TLS, LOG_ERR, "Failed to prepare for TLS: %s", gnutls_strerror (gtls_errno));
1726                 if (cmd->session_errno) {
1727                         send_error (cmd, cmd->session_errno, error_getstring ());
1728                 } else {
1729                         send_error (cmd, EIO, "Failed to prepare for TLS");
1730                 }
1731                 close (cryptfd);
1732                 return;
1733         }
1734         do {
1735                 gtls_errno = gnutls_handshake (session);
1736         } while ((gtls_errno < 0) && (gnutls_error_is_fatal (gtls_errno) == 0));
1737         if ((gtls_errno == GNUTLS_E_SUCCESS) && cmd->session_errno) {
1738                 gtls_errno = GNUTLS_E_USER_ERROR;
1739         }
1740
1741         //
1742         // Cleanup any prefetched identities
1743         for (i=LID_TYPE_MIN; i<=LID_TYPE_MAX; i++) {
1744                 if (cmd->lids [i - LID_TYPE_MIN].data != NULL) {
1745                         free (cmd->lids [i - LID_TYPE_MIN].data);
1746                 }
1747         }
1748         bzero (cmd->lids, sizeof (cmd->lids));
1749         if (NULL != (void *) cmd->session_privatekey) {
1750                 gnutls_privkey_deinit ((void *) cmd->session_privatekey);
1751                 cmd->session_privatekey = (intptr_t) (void *) NULL;
1752         }
1753         if (NULL != (void *) cmd->session_certificate) {
1754                 gnutls_pcert_deinit ((void *) cmd->session_certificate);
1755                 free ((void *) cmd->session_certificate);
1756                 cmd->session_certificate = (intptr_t) (void *) NULL;
1757         }
1758
1759         //
1760         // From here, assume nothing about the cmd structure; as part of the
1761         // handshake, it may have passed through the client's control, as
1762         // part of a callback.  So, reinitialise the entire return structure.
1763         //TODO// Or backup the (struct pioc_starttls) before handshaking
1764         cmd->cmd.pio_cmd = orig_cmd;
1765         cmd->cmd.pio_data.pioc_starttls.localid  [0] =
1766         cmd->cmd.pio_data.pioc_starttls.remoteid [0] = 0;
1767
1768         //
1769         // Respond to positive or negative outcome of the handshake
1770         if (gtls_errno != GNUTLS_E_SUCCESS) {
1771                 gnutls_deinit (session);
1772                 tlog (TLOG_TLS, LOG_ERR, "TLS handshake failed: %s", gnutls_strerror (gtls_errno));
1773                 if (cmd->session_errno) {
1774                         tlog (TLOG_TLS, LOG_ERR, "Underlying cause may be: %s", strerror (cmd->session_errno));
1775                         send_error (cmd, cmd->session_errno, error_getstring ());
1776                 } else {
1777                         send_error (cmd, EPERM, "TLS handshake failed");
1778                 }
1779                 manage_txn_rollback (&cmd->txn);
1780                 close (cryptfd);
1781                 return;
1782         } else {
1783                 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_INFO, "TLS handshake succeeded over %d", cryptfd);
1784                 //TODO// extract_authenticated_remote_identity (cmd);
1785         }
1786
1787         //
1788         // Request the plaintext file descriptor with a callback
1789         uint32_t oldcmd = cmd->cmd.pio_cmd;
1790         cmd->cmd.pio_cmd = PIOC_PLAINTEXT_CONNECT_V2;
1791         tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_PLAINTEXT_CONNECT_V2");
1792         cmd = send_callback_and_await_response (cmd);
1793                 if (cmd->cmd.pio_cmd != PIOC_PLAINTEXT_CONNECT_V2) {
1794                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
1795                         if (cmd->cmd.pio_cmd == PIOC_ERROR_V1) {
1796                                 send_command (cmd, -1); // Bounce error back
1797                         } else {
1798                                 send_error (cmd, EPROTO, "Unexpected response to plaintext connection callback");
1799                         }
1800                         return;
1801                 }
1802         tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that set plainfd:=%d for lid==\"%s\" and rid==\"%s\"", cmd->passfd, cmd->cmd.pio_data.pioc_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid);
1803         plainfd = cmd->passfd;
1804         cmd->passfd = -1;
1805         if (plainfd < 0) {
1806                 tlog (TLOG_UNIXSOCK, LOG_ERR, "No plaintext file descriptor supplied to TLS Pool");
1807                 send_error (cmd, EINVAL, "No plaintext file descriptor supplied to TLS Pool");
1808                 manage_txn_rollback (&cmd->txn);
1809                 close (cryptfd);
1810                 return;
1811         }
1812         if (cmd->cmd.pio_cmd != PIOC_PLAINTEXT_CONNECT_V2) {
1813                 tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has bad command code");
1814                 send_error (cmd, EINVAL, "Callback response has bad command code");
1815                 manage_txn_rollback (&cmd->txn);
1816                 close (cryptfd);
1817                 close (plainfd);
1818                 return;
1819         }
1820         cmd->cmd.pio_cmd = oldcmd;
1821         send_command (cmd, -1);         // app sent plainfd to us
1822
1823         //
1824         // Copy TLS records until the connection is closed
1825         manage_txn_commit (&cmd->txn);
1826         copycat (plainfd, cryptfd, session, clientfd);
1827 }
1828
1829
1830 /*
1831  * The starttls_client function responds to an application's request to 
1832  * setup TLS for a given file descriptor, and return a file descriptor
1833  * with the unencrypted view when done.  The main thing done here is to
1834  * spark off a new thread that handles the operations.
1835  * TODO: Are client and server routines different?
1836  */
1837 void starttls_client (struct command *cmd) {
1838         /* Create a thread and, if successful, wait for it to unlock cmd */
1839         errno = pthread_create (&cmd->handler, NULL, starttls_thread, (void *) cmd);
1840         if (errno != 0) {
1841                 send_error (cmd, ESRCH, "STARTTLS_CLIENT thread refused");
1842                 return;
1843         }
1844         errno = pthread_detach (cmd->handler);
1845         if (errno != 0) {
1846                 pthread_cancel (cmd->handler);
1847                 send_error (cmd, ESRCH, "STARTTLS_CLIENT thread detachment refused");
1848                 return;
1849         }
1850 }
1851
1852 /*
1853  * The starttls_server function responds to an application's request to 
1854  * setup TLS for a given file descriptor, and return a file descriptor
1855  * with the unencrypted view when done.  The main thing done here is to
1856  * spark off a new thread that handles the operations.
1857  */
1858 void starttls_server (struct command *cmd) {
1859         /* Create a thread and, if successful, wait for it to unlock cmd */
1860         errno = pthread_create (&cmd->handler, NULL, starttls_thread, (void *) cmd);
1861         if (errno != 0) {
1862                 send_error (cmd, ESRCH, "STARTTLS_SERVER thread refused");
1863                 return;
1864         }
1865         errno = pthread_detach (cmd->handler);
1866         if (errno != 0) {
1867                 //TODO// Kill the thread... somehow
1868                 send_error (cmd, ESRCH, "STARTTLS_CLIENT thread detachment refused");
1869                 return;
1870         }
1871 }
1872