First attempt at making TLS-KDH work with the TLS Pool
[tlspool] / src / starttls.c
1 /* tlspool/starttls.c -- Setup and validation handler for TLS session */
2
3
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <memory.h>
8 #include <string.h>
9 #include <pthread.h>
10 #include <assert.h>
11
12 #include <ctype.h>
13
14 #include <unistd.h>
15 #include <syslog.h>
16 #include <errno.h>
17 #include <poll.h>
18
19 #include <sys/types.h>
20 #include <sys/socket.h>
21
22 #include <arpa/inet.h>
23 #include <netinet/in.h>
24
25 #include <gnutls/gnutls.h>
26 #include <gnutls/pkcs11.h>
27 #include <gnutls/abstract.h>
28 #include <gnutls/dane.h>
29
30 #include <libtasn1.h>
31
32 #include <krb5.h>
33
34 #include <tlspool/internal.h>
35
36
37 #include "manage.h"
38 #include "donai.h"
39
40
41 #if EXPECTED_LID_TYPE_COUNT != LID_TYPE_CNT
42 #error "Set EXPECTED_LID_TYPE_COUNT in <tlspool/internal.h> to match LID_TYPE_CNT"
43 #endif
44
45
46 /* This module hosts TLS handlers which treat an individual connection.
47  *
48  * Initially, the TLS setup is processed, which means validating the
49  * connection.  If and when this succeeds, a continued process is needed
50  * to encrypt and decrypt traffic while it is in transit.
51  *
52  * Every TLS connection (including the attempt to set it up) is hosted in
53  * its own thread.  This means that it can abide time to wait for PINENTRY,
54  * LOCALID or LIDENTRY responses.  It also means a very clear flow when the
55  * time comes to destroy a connection.
56  *
57  * While encrypting and decrypting traffic passing through, the thread
58  * will use its own poll() call, and thus offload the potentially large
59  * one of the main thread, which is supposed to be a low-traffic task.
60  * The set of file descriptors used by the session-handler threads are
61  * in contrast very small and can easily be started for every single
62  * packet passing through.
63  *
64  * Might the user terminate a process while this one is waiting for a
65  * callback command request, then the main TLS pool thread will take
66  * care of taking down this thread.  To that end, it sets the followup
67  * pointer that normally holds a callback response to NULL, and then
68  * permits this thread to run again.  This will lead to a shutdown of
69  * this process, and proper closing of all connections.  The remote peer
70  * will therefore see the result of a local kill as a connection reset.
71  *
72  * In case one of the end points of the connection is terminated, a
73  * similar thing will happen; the thread will terminate itself after
74  * a cleanup of any outstanding resources.  This, once again, leads
75  * to passing on the reset of a connection between the encrypted and
76  * side of the connection.
77  */
78
79
80
81 /*
82  * GnuTLS infrastructure setup.
83  * Session-shared DH-keys, credentials structures, and so on.
84  */
85 static gnutls_dh_params_t dh_params;
86
87 struct credinfo {
88         gnutls_credentials_type_t credtp;
89         void *cred;
90 };
91
92 #define EXPECTED_SRV_CREDCOUNT 3
93 #define EXPECTED_CLI_CREDCOUNT 3
94 static struct credinfo srv_creds [EXPECTED_SRV_CREDCOUNT];
95 static struct credinfo cli_creds [EXPECTED_CLI_CREDCOUNT];
96 static int srv_credcount = 0;
97 static int cli_credcount = 0;
98 static const char const *onthefly_p11uri = "pkcs11:manufacturer=ARPA2.net;token=TLS+Pool+internal;object=on-the-fly+signer;type=private;serial=1";
99 static unsigned long long onthefly_serial;  //TODO: Fill with now * 1000
100 static gnutls_x509_crt_t onthefly_issuercrt = NULL;
101 static gnutls_privkey_t onthefly_issuerkey = NULL;
102 static gnutls_x509_privkey_t onthefly_subjectkey = NULL;
103 static pthread_mutex_t onthefly_signer_lock = PTHREAD_MUTEX_INITIALIZER;
104
105 static krb5_context kerberos_context;
106 static krb5_error_code have_credcache (krb5_principal sought, krb5_ccache *found);
107
108 /* The local variation on the ctlkeynode structure, with TLS-specific fields
109  */
110 struct ctlkeynode_tls {
111         struct ctlkeynode regent;       // Structure for ctlkey_register()
112         gnutls_session_t session;       // Additional data specifically for TLS
113         pthread_t owner;                // For interruption of copycat()
114         int plainfd;                    // Plain-side connection
115         int cryptfd;                    // Crypt-side connection
116 };
117
118 /* The list of accepted Exporter Label Prefixes for starttls_prng()
119  */
120 char *tlsprng_label_prefixes [] = {
121         // Forbidden by RFC 5705: "client finished",
122         // Forbidden by RFC 5705: "server finished",
123         // Forbidden by RFC 5705: "master secret",
124         // Forbidden by RFC 5705: "key expansion",
125         "client EAP encryption",                // not suited for DTLS
126         "ttls keying material",                 // not suited for DTLS
127         "ttls challenge",                       // not suited for DTLS
128         "EXTRACTOR-dtls_srtp",
129         "EXPORTER_DTLS_OVER_SCTP",
130         "EXPORTER-ETSI-TC-M2M-Bootstrap",
131         "EXPORTER-ETSI-TC-M2M-Connection",
132         "TLS_MK_Extr",
133         "EXPORTER_GBA_Digest",
134         "EXPORTER: teap session key seed",      // not suited for DTLS
135         "EXPORTER-oneM2M-Bootstrap",
136         "EXPORTER-oneM2M-Connection",
137         NULL
138 };
139
140 /* The registry with the service names that are deemed safe for an
141  * anonymous precursor phase; that is, the service names that may offer
142  * ANON-DH initially, and immediately renegotiate an authenticated
143  * connection.  See doc/anonymising-precursor.* for more information.
144  *
145  * The registry is ordered by case-independent service name, so it can
146  * be searched in 2log time.  Service names are as defined by IANA in the
147  * "Service Name and Transport Protocol Port Number Registry".
148  *
149  * The entries in the registry depend on the role played; either as a
150  * client or as a server.  This refers to the local node, and depends on
151  * uncertainty of the remote party's TLS implementation and whether or
152  * not the protocol could lead to the remote sending information that
153  * requires authentication before the secure renogiation into an
154  * authenticated connection has been completed by this side.  This is
155  * a protocol-dependent matter and the registry provided here serves to
156  * encapsulate this knowledge inside the TLS Pool instead of bothering
157  * application designers with it.  Entries that are not found in the
158  * registry are interpreted as not allowing an anonymising precursor.
159  *
160  * Note that ANONPRE_EXTEND_MASTER_SECRET cannot be verified before
161  * GnuTLS version 3.4.0; see "imap" below for the resulting impact.  This
162  * also impacts dynamic linking, because 3.4.0 introduces the new function
163  * gnutls_ext_get_data() that is used for this requirement.
164  */
165 #define ANONPRE_FORBID 0x00
166 #define ANONPRE_CLIENT 0x01
167 #define ANONPRE_SERVER 0x02
168 #define ANONPRE_EITHER (ANONPRE_CLIENT | ANONPRE_SERVER)
169 #define ANONPRE_EXTEND_MASTER_SECRET 0x10
170 struct anonpre_regentry {
171         char *service;
172         uint8_t flags;
173 };
174 struct anonpre_regentry anonpre_registry [] = {
175 /* This registry is commented out for now, although the code to use it seems
176  * to work fine.  GnuTLS however, does not seem to support making the switch
177  * from ANON-ECDH to an authenticated handshake.  Details:
178  * http://lists.gnutls.org/pipermail/gnutls-help/2015-November/003998.html
179  *
180         { "generic_anonpre", ANONPRE_EITHER },  // Name invalid as per RFC 6335
181         { "http", ANONPRE_CLIENT },     // Server also if it ignores client ID
182 #if GNUTLS_VERSION_NUMBER < 0x030400
183         { "imap", ANONPRE_SERVER },
184 #else
185         { "imap", ANONPRE_EITHER | ANONPRE_EXTEND_MASTER_SECRET },
186 #endif
187         { "pop3", ANONPRE_EITHER },
188         { "smtp", ANONPRE_EITHER },
189  *
190  * End of commenting out the registry
191  */
192 };
193 const int anonpre_registry_size = sizeof (anonpre_registry) / sizeof (struct anonpre_regentry);
194
195
196 /* The registry of Key Usage and Extended Key Usage for any given service name.
197  */
198 static const char *http_noncrit [] = { GNUTLS_KP_TLS_WWW_SERVER, GNUTLS_KP_TLS_WWW_CLIENT, NULL };
199 struct svcusage_regentry {
200         char *service;
201         unsigned int usage;
202         const char **oids_non_critical;
203         const char **oids_critical;
204 };
205 struct svcusage_regentry svcusage_registry [] = {
206         { "generic_anonpre",
207                 GNUTLS_KEY_KEY_ENCIPHERMENT |
208                 GNUTLS_KEY_KEY_AGREEMENT,
209                 NULL,
210                 NULL
211         },
212         { "http",
213                 GNUTLS_KEY_DIGITAL_SIGNATURE |
214                 GNUTLS_KEY_KEY_ENCIPHERMENT |
215                 GNUTLS_KEY_KEY_AGREEMENT,
216                 http_noncrit,
217                 NULL
218         },
219 };
220 const int svcusage_registry_size = sizeof (svcusage_registry) / sizeof (struct svcusage_regentry);
221
222
223 /* The maximum number of bytes that can be passed over a TLS connection before
224  * the authentication is complete in case of a anonymous precursor within a
225  * protocol that ensures that this cannot be a problem.
226  */
227 int maxpreauth;
228
229 /* The priorities cache for "NORMAL" -- used to preconfigure the server,
230  * actually to overcome its unwillingness to perform the handshake, and
231  * leave it to srv_clienthello() to setup the priority string.
232  */
233 gnutls_priority_t priority_normal;
234
235
236 /* Map a GnuTLS call (usually a function call) to a POSIX errno,
237  * optionally reporting an errstr to avoid loosing information.
238  * Retain errno if it already exists.
239  * Continue if errno differs from 0, GnuTLS may "damage" it even when OK. */
240 #define E_g2e(errstr,gtlscall) { \
241         if (gtls_errno == GNUTLS_E_SUCCESS) { \
242                 gtls_errno = (gtlscall); \
243                 if (gtls_errno != GNUTLS_E_SUCCESS) { \
244                         error_gnutls2posix (gtls_errno, errstr); \
245                 } \
246         } \
247 }
248
249 /* Cleanup when GnuTLS leaves errno damaged but returns no gtls_errno */
250 #define E_gnutls_clear_errno() { \
251         if (gtls_errno == GNUTLS_E_SUCCESS) { \
252                 errno = 0; \
253         } \
254 }
255
256 /* Error number translation, including error string setup.  See E_g2e(). */
257 void error_gnutls2posix (int gtls_errno, char *new_errstr) {
258         char *errstr;
259         register int newerrno;
260         //
261         // Sanity checks
262         if (gtls_errno == GNUTLS_E_SUCCESS) {
263                 return;
264         }
265         errstr =  error_getstring ();
266         if (errstr != NULL) {
267                 return;
268         }
269         //
270         // Report the textual error
271         if (new_errstr == NULL) {
272                 new_errstr = "GnuTLS error";
273         }
274         tlog (TLOG_TLS, LOG_ERR, "%s: %s",
275                 new_errstr,
276                 gnutls_strerror (gtls_errno));
277         error_setstring (new_errstr);
278         //
279         // Translate error to a POSIX errno value
280         switch (gtls_errno) {
281         case GNUTLS_E_SUCCESS:
282                 return;
283         case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
284         case GNUTLS_E_UNKNOWN_CIPHER_TYPE:
285         case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
286         case GNUTLS_E_UNWANTED_ALGORITHM:
287         case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
288         case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
289         case GNUTLS_E_X509_UNKNOWN_SAN:
290         case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
291         case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
292         case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
293         case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
294         case GNUTLS_E_NO_CIPHER_SUITES:
295         case GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED:
296         case GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE:
297         case GNUTLS_E_UNKNOWN_HASH_ALGORITHM:
298         case GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE:
299         case GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE:
300         case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
301         case GNUTLS_E_UNKNOWN_ALGORITHM:
302         case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
303         case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
304         case GNUTLS_E_X509_UNSUPPORTED_OID:
305         case GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE:
306         case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
307         case GNUTLS_E_ECC_NO_SUPPORTED_CURVES:
308         case GNUTLS_E_ECC_UNSUPPORTED_CURVE:
309         case GNUTLS_E_X509_UNSUPPORTED_EXTENSION:
310         case GNUTLS_E_NO_CERTIFICATE_STATUS:
311         case GNUTLS_E_NO_APPLICATION_PROTOCOL:
312 #ifdef GNUTLS_E_NO_SELF_TEST
313         case GNUTLS_E_NO_SELF_TEST:
314 #endif
315                 newerrno = EOPNOTSUPP;
316                 break;
317         case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
318         case GNUTLS_E_INVALID_REQUEST:
319                 newerrno = EINVAL;
320                 break;
321         case GNUTLS_E_INVALID_SESSION:
322         case GNUTLS_E_REHANDSHAKE:
323         case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
324                 newerrno = ENOTCONN;
325                 break;
326         case GNUTLS_E_PUSH_ERROR:
327         case GNUTLS_E_PULL_ERROR:
328         case GNUTLS_E_PREMATURE_TERMINATION:
329         case GNUTLS_E_SESSION_EOF:
330                 newerrno = ECONNRESET;
331                 break;
332         case GNUTLS_E_UNEXPECTED_PACKET:
333         case GNUTLS_E_WARNING_ALERT_RECEIVED:
334         case GNUTLS_E_FATAL_ALERT_RECEIVED:
335         case GNUTLS_E_LARGE_PACKET:
336         case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
337         case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
338         case GNUTLS_E_MPI_SCAN_FAILED:
339         case GNUTLS_E_DECRYPTION_FAILED:
340         case GNUTLS_E_DECOMPRESSION_FAILED:
341         case GNUTLS_E_COMPRESSION_FAILED:
342         case GNUTLS_E_BASE64_DECODING_ERROR:
343         case GNUTLS_E_MPI_PRINT_FAILED:
344         case GNUTLS_E_GOT_APPLICATION_DATA:
345         case GNUTLS_E_RECORD_LIMIT_REACHED:
346         case GNUTLS_E_ENCRYPTION_FAILED:
347         case GNUTLS_E_PK_ENCRYPTION_FAILED:
348         case GNUTLS_E_PK_DECRYPTION_FAILED:
349         case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
350         case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
351         case GNUTLS_E_PKCS1_WRONG_PAD:
352         case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
353         case GNUTLS_E_FILE_ERROR:
354         case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
355         case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
356         case GNUTLS_E_ASN1_DER_ERROR:
357         case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
358         case GNUTLS_E_ASN1_GENERIC_ERROR:
359         case GNUTLS_E_ASN1_VALUE_NOT_VALID:
360         case GNUTLS_E_ASN1_TAG_ERROR:
361         case GNUTLS_E_ASN1_TAG_IMPLICIT:
362         case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
363         case GNUTLS_E_ASN1_SYNTAX_ERROR:
364         case GNUTLS_E_ASN1_DER_OVERFLOW:
365         case GNUTLS_E_TOO_MANY_EMPTY_PACKETS:
366         case GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS:
367         case GNUTLS_E_SRP_PWD_PARSING_ERROR:
368         case GNUTLS_E_BASE64_ENCODING_ERROR:
369         case GNUTLS_E_OPENPGP_KEYRING_ERROR:
370         case GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR:
371         case GNUTLS_E_OPENPGP_SUBKEY_ERROR:
372         case GNUTLS_E_CRYPTO_ALREADY_REGISTERED:
373         case GNUTLS_E_HANDSHAKE_TOO_LARGE:
374         case GNUTLS_E_BAD_COOKIE:
375         case GNUTLS_E_PARSING_ERROR:
376         case GNUTLS_E_CERTIFICATE_LIST_UNSORTED:
377         case GNUTLS_E_NO_PRIORITIES_WERE_SET:
378 #ifdef GNUTLS_E_PK_GENERATION_ERROR
379         case GNUTLS_E_PK_GENERATION_ERROR:
380 #endif
381 #ifdef GNUTLS_E_SELF_TEST_ERROR
382         case GNUTLS_E_SELF_TEST_ERROR:
383 #endif
384 #ifdef GNUTLS_E_SOCKETS_INIT_ERROR
385         case GNUTLS_E_SOCKETS_INIT_ERROR:
386 #endif
387                 newerrno = EIO;
388                 break;
389         case GNUTLS_E_MEMORY_ERROR:
390         case GNUTLS_E_SHORT_MEMORY_BUFFER:
391                 newerrno = ENOMEM;
392                 break;
393         case GNUTLS_E_AGAIN:
394                 newerrno = EAGAIN;
395                 break;
396         case GNUTLS_E_EXPIRED:
397         case GNUTLS_E_TIMEDOUT:
398                 newerrno = ETIMEDOUT;
399                 break;
400         case GNUTLS_E_DB_ERROR:
401 #ifdef ENODATA
402                 newerrno = ENODATA;
403 #else
404                 newerrno = ENOENT;
405 #endif
406                 break;
407         case GNUTLS_E_SRP_PWD_ERROR:
408         case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
409         case GNUTLS_E_HASH_FAILED:
410         case GNUTLS_E_PK_SIGN_FAILED:
411         case GNUTLS_E_CERTIFICATE_ERROR:
412         case GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION:
413         case GNUTLS_E_KEY_USAGE_VIOLATION:
414         case GNUTLS_E_NO_CERTIFICATE_FOUND:
415         case GNUTLS_E_OPENPGP_UID_REVOKED:
416         case GNUTLS_E_OPENPGP_GETKEY_FAILED:
417         case GNUTLS_E_PK_SIG_VERIFY_FAILED:
418         case GNUTLS_E_ILLEGAL_SRP_USERNAME:
419         case GNUTLS_E_INVALID_PASSWORD:
420         case GNUTLS_E_MAC_VERIFY_FAILED:
421         case GNUTLS_E_IA_VERIFY_FAILED:
422         case GNUTLS_E_UNKNOWN_SRP_USERNAME:
423         case GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR:
424         case GNUTLS_E_USER_ERROR:
425         case GNUTLS_E_AUTH_ERROR:
426                 newerrno = EACCES;
427                 break;
428         case GNUTLS_E_INTERRUPTED:
429                 newerrno = EINTR;
430                 break;
431         case GNUTLS_E_INTERNAL_ERROR:
432         case GNUTLS_E_CONSTRAINT_ERROR:
433         case GNUTLS_E_ILLEGAL_PARAMETER:
434                 newerrno = EINVAL;
435                 break;
436         case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
437                 newerrno = ECONNREFUSED;
438                 break;
439         case GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY:
440         case GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY:
441 #ifdef GNUTLS_E_LIB_IN_ERROR_STATE
442         case GNUTLS_E_LIB_IN_ERROR_STATE:
443 #endif
444                 newerrno = ENOEXEC;
445                 break;
446         case GNUTLS_E_RANDOM_FAILED:
447                 newerrno = EBADF;
448                 break;
449         case GNUTLS_E_CRYPTODEV_IOCTL_ERROR:
450         case GNUTLS_E_CRYPTODEV_DEVICE_ERROR:
451         case GNUTLS_E_HEARTBEAT_PONG_RECEIVED:
452         case GNUTLS_E_HEARTBEAT_PING_RECEIVED:
453         case GNUTLS_E_PKCS11_ERROR:
454         case GNUTLS_E_PKCS11_LOAD_ERROR:
455         case GNUTLS_E_PKCS11_PIN_ERROR:
456         case GNUTLS_E_PKCS11_SLOT_ERROR:
457         case GNUTLS_E_LOCKING_ERROR:
458         case GNUTLS_E_PKCS11_ATTRIBUTE_ERROR:
459         case GNUTLS_E_PKCS11_DEVICE_ERROR:
460         case GNUTLS_E_PKCS11_DATA_ERROR:
461         case GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR:
462         case GNUTLS_E_PKCS11_KEY_ERROR:
463         case GNUTLS_E_PKCS11_PIN_EXPIRED:
464         case GNUTLS_E_PKCS11_PIN_LOCKED:
465         case GNUTLS_E_PKCS11_SESSION_ERROR:
466         case GNUTLS_E_PKCS11_SIGNATURE_ERROR:
467         case GNUTLS_E_PKCS11_TOKEN_ERROR:
468         case GNUTLS_E_PKCS11_USER_ERROR:
469         case GNUTLS_E_CRYPTO_INIT_FAILED:
470         case GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE:
471         case GNUTLS_E_TPM_ERROR:
472         case GNUTLS_E_TPM_KEY_PASSWORD_ERROR:
473         case GNUTLS_E_TPM_SRK_PASSWORD_ERROR:
474         case GNUTLS_E_TPM_SESSION_ERROR:
475         case GNUTLS_E_TPM_KEY_NOT_FOUND:
476         case GNUTLS_E_TPM_UNINITIALIZED:
477         case GNUTLS_E_OCSP_RESPONSE_ERROR:
478         case GNUTLS_E_RANDOM_DEVICE_ERROR:
479 #ifdef EREMOTEIO
480                 newerrno = EREMOTEIO;
481 #else
482                 newerrno = EIO;
483 #endif
484                 break;
485         default:
486                 newerrno = EIO;
487                 break;
488         }
489         errno = newerrno;
490         return;
491 }
492
493 /* Generate Diffie-Hellman parameters - for use with DHE
494  * kx algorithms. TODO: These should be discarded and regenerated
495  * once a day, once a week or once a month. Depending on the
496  * security requirements.
497  */
498 static gtls_error generate_dh_params (void) {
499         unsigned int bits;
500         int gtls_errno = GNUTLS_E_SUCCESS;
501         bits = gnutls_sec_param_to_pk_bits (
502                 GNUTLS_PK_DH,
503                 GNUTLS_SEC_PARAM_LEGACY);
504         //TODO// Acquire DH-params lock
505         E_g2e ("Failed to initialise DH params",
506                 gnutls_dh_params_init (
507                         &dh_params));
508         E_g2e ("Failed to generate DH params",
509                 gnutls_dh_params_generate2 (
510                         dh_params,
511                         bits));
512         //TODO// Release DH-params lock
513         return gtls_errno;
514 }
515
516 /* Load Diffie-Hellman parameters from file - or generate them when load fails.
517  */
518 static gtls_error load_dh_params (void) {
519         gnutls_dh_params_t dhp;
520         gnutls_datum_t pkcs3;
521         char *filename = cfg_tls_dhparamfile ();
522         int gtls_errno = GNUTLS_E_SUCCESS;
523         bzero (&pkcs3, sizeof (pkcs3));
524         if (filename) {
525                 E_g2e ("No PKCS #3 PEM file with DH params",
526                         gnutls_load_file (
527                                 filename,
528                                 &pkcs3));
529                 E_gnutls_clear_errno ();
530                 E_g2e ("Failed to initialise DH params",
531                         gnutls_dh_params_init (
532                                 &dhp));
533                 E_g2e ("Failed to import DH params from PKCS #3 PEM",
534                         gnutls_dh_params_import_pkcs3 (
535                                 dhp,
536                                 &pkcs3,
537                                 GNUTLS_X509_FMT_PEM));
538                 E_gnutls_clear_errno ();
539         }
540         if (pkcs3.data != NULL) {
541                 free (pkcs3.data);
542         }
543         if (gtls_errno != GNUTLS_E_SUCCESS) {
544                 //
545                 // File failed to load, so try to generate fresh DH params
546                 int gtls_errno_stack0;
547                 gtls_errno = GNUTLS_E_SUCCESS;
548                 tlog (TLOG_CRYPTO, LOG_DEBUG, "Failed to load DH params from %s; generating fresh parameters", filename);
549                 E_g2e ("Failed to generate DH params",
550                         generate_dh_params ());
551                 gtls_errno_stack0 = gtls_errno;
552                 //TODO// Acquire DH-params lock
553                 E_g2e ("Failed to format DH params as PKCS #3 PEM",
554                         gnutls_dh_params_export2_pkcs3 (
555                                 dh_params,
556                                 GNUTLS_X509_FMT_PEM,
557                                 &pkcs3));
558                 //TODO// Release DH-params lock
559                 if ((gtls_errno == GNUTLS_E_SUCCESS) && (filename != NULL)) {
560                         FILE *pemf;
561                         //
562                         // Best effor file save -- readback will parse
563                         pemf = fopen (filename, "w");
564                         if (pemf != NULL) {
565                                 fwrite (pkcs3.data, 1, pkcs3.size, pemf);
566                                 fclose (pemf);
567                                 tlog (TLOG_FILES, LOG_DEBUG, "Saved DH params to %s (best-effort)", filename);
568                         }
569                         E_gnutls_clear_errno ();
570                 }
571                 gtls_errno = gtls_errno_stack0;
572         } else {
573                 gnutls_dh_params_t old_dh;
574                 //TODO// Acquire DH-params lock
575                 old_dh = dh_params;
576                 dh_params = dhp;
577                 //TODO// Release DH-params lock
578                 if (old_dh) {
579                         gnutls_dh_params_deinit (old_dh);
580                 }
581         }
582         return gtls_errno;
583 }
584
585 /* Remove DH parameters, to be used during program cleanup. */
586 static void remove_dh_params (void) {
587         if (dh_params) {
588                 gnutls_dh_params_deinit (dh_params);
589                 dh_params = NULL;
590         }
591 }
592
593
594 /* A log printing function
595  */
596 void log_gnutls (int level, const char *msg) {
597         tlog (TLOG_TLS, level, "GnuTLS: %s", msg);
598 }
599
600
601 /* Implement the GnuTLS function for token insertion callback.  This function
602  * refers back to the generic callback for token insertion.
603  */
604 int gnutls_token_callback (void *const userdata,
605                                 const char *const label,
606                                 unsigned retry) {
607         if (token_callback (label, retry)) {
608                 return GNUTLS_E_SUCCESS;
609         } else {
610                 return GNUTLS_E_PKCS11_TOKEN_ERROR;
611         }
612 }
613  
614
615 /*
616  * Implement the GnuTLS function for PIN callback.  This function calls
617  * the generic PIN callback operation.
618  */
619 int gnutls_pin_callback (void *userdata,
620                                 int attempt,
621                                 const char *token_url,
622                                 const char *token_label,
623                                 unsigned int flags,
624                                 char *pin,
625                                 size_t pin_max) {
626         if (flags & GNUTLS_PIN_SO) {
627                 return GNUTLS_E_USER_ERROR;
628         }
629         if (pin_callback (attempt, token_url, token_label, pin, pin_max)) {
630                 return 0;
631         } else {
632                 return GNUTLS_E_PKCS11_PIN_ERROR;
633         }
634 }
635
636
637 /* Register a PKCS #11 provider with the GnuTLS environment. */
638 void starttls_pkcs11_provider (char *p11path) {
639         unsigned int token_seq = 0;
640         char *p11uri;
641         if (gnutls_pkcs11_add_provider (p11path, NULL) != 0) {
642                 fprintf (stderr, "Failed to register PKCS #11 library %s with GnuTLS\n", p11path);
643                 exit (1);
644         }
645         while (gnutls_pkcs11_token_get_url (token_seq, 0, &p11uri) == 0) {
646 #ifdef DEBUG
647                 fprintf (stderr, "DEBUG: Found token URI %s\n", p11uri);
648 #endif
649                 //TODO// if (gnutls_pkcs11_token_get_info (p11uri, GNUTLS_PKCS11_TOKEN_LABEL-of-SERIAL-of-MANUFACTURER-of-MODEL, output, utput_size) == 0) { ... }
650                 gnutls_free (p11uri);
651                 token_seq++;
652         }
653         //TODO// Select token by name (value)
654         //TODO// if PIN available then set it up
655         //TODO:WHY?// free_p11pin ();
656 }
657
658
659 /* The global and static setup function for the starttls functions.
660  */
661 void setup_starttls (void) {
662         int setup_starttls_credentials (void);  /* Defined below */
663         const char *curver;
664         int gtls_errno = GNUTLS_E_SUCCESS;
665         char *otfsigcrt, *otfsigkey;
666         //
667         // Setup configuration variables
668         maxpreauth = cfg_tls_maxpreauth ();
669         //
670         // Basic library actions
671         tlog (TLOG_TLS, LOG_DEBUG, "Compiled against GnuTLS version %s", GNUTLS_VERSION);
672         curver = gnutls_check_version (GNUTLS_VERSION);
673         tlog (TLOG_TLS, LOG_DEBUG, "Running against %s GnuTLS version %s", curver? "acceptable": "OLDER", curver? curver: gnutls_check_version (NULL));
674         E_g2e ("GnuTLS global initialisation failed",
675                 gnutls_global_init ());
676         E_gnutls_clear_errno ();
677         E_g2e ("GnuTLS PKCS #11 initialisation failed",
678                 gnutls_pkcs11_init (
679                         GNUTLS_PKCS11_FLAG_MANUAL, NULL));
680         //
681         // Setup logging / debugging
682         if (cfg_log_level () == LOG_DEBUG) {
683                 gnutls_global_set_log_function (log_gnutls);
684                 gnutls_global_set_log_level (9);
685         }
686         //
687         // Setup callbacks for user communication
688         gnutls_pkcs11_set_token_function (gnutls_token_callback, NULL);
689         gnutls_pkcs11_set_pin_function (gnutls_pin_callback, NULL);
690         //
691         // Setup DH parameters
692         E_g2e ("Loading DH params failed",
693                 load_dh_params ());
694         //
695         // Setup shared credentials for all client server processes
696         E_g2e ("Failed to setup GnuTLS callback credentials",
697                 setup_starttls_credentials ());
698         //
699         // Parse the default priority string
700         E_g2e ("Failed to setup NORMAL priority cache",
701                 gnutls_priority_init (&priority_normal, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+COMP-NULL:"
702 #ifdef HAVE_TLS_KDH
703                 "%GNUTLS_ASYM_CERT_TYPES:"
704 #endif
705                 "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:+ANON-ECDH:+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
706                 // gnutls_priority_init (&priority_normal, "NORMAL:-RSA:+ANON-ECDH:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
707         //
708         // Try to setup on-the-fly signing key / certificate and gen a certkey
709         otfsigcrt = cfg_tls_onthefly_signcert ();
710         otfsigkey = cfg_tls_onthefly_signkey ();
711 fprintf (stderr, "DEBUG: gtls_errno = %d, otfsigcrt == %s, otfsigkey == %s\n", gtls_errno, otfsigcrt? otfsigcrt: "NULL", otfsigkey? otfsigkey: "NULL");
712         if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigcrt != NULL)) {
713                 FILE *crtfile = NULL;
714 fprintf (stderr, "DEBUG: gtls_errno==%d when initialising onthefly_issuercrt\n", gtls_errno);
715                 E_g2e ("Failed to initialise on-the-fly issuer certificate structure",
716                         gnutls_x509_crt_init (&onthefly_issuercrt));
717                 if (strncmp (otfsigcrt, "file:", 5) == 0) {
718                         // Provisionary support for the "file:" prefix
719                         otfsigcrt += 5;
720                 }
721                 crtfile = fopen (otfsigcrt, "r");
722                 if (crtfile == NULL) {
723                         E_g2e ("Failed to open on-the-fly issuer certificate file",
724                                 GNUTLS_E_FILE_ERROR);
725 fprintf (stderr, "DEBUG: gtls_errno==%d after failing to open file for onthefly_issuercrt\n", gtls_errno);
726                 } else {
727                         char crt [5001];
728                         size_t len = fread (crt, 1, sizeof (crt), crtfile);
729                         if (ferror (crtfile)) {
730                                 E_g2e ("Failed to read on-the-fly issuer certificate from file",
731                                         GNUTLS_E_FILE_ERROR);
732                         } else if ((len >= sizeof (crt)) || !feof (crtfile)) {
733                                 E_g2e ("Unexpectedly long on-the-fly issuer certificate file",
734                                         GNUTLS_E_FILE_ERROR);
735                         } else {
736                                 gnutls_datum_t cd = {
737                                         .data = crt,
738                                         .size = len
739                                 };
740 fprintf (stderr, "DEBUG: gtls_errno==%d before importing onthefly_issuercrt\n", gtls_errno);
741                                 E_g2e ("Failed to import on-the-fly certificate from file",
742                                         gnutls_x509_crt_import (onthefly_issuercrt, &cd, GNUTLS_X509_FMT_DER));
743 fprintf (stderr, "DEBUG: gtls_errno==%d after  importing onthefly_issuercrt\n", gtls_errno);
744                         }
745                         fclose (crtfile);
746                 }
747         }
748         if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigkey != NULL)) {
749                 E_g2e ("Failed to initialise on-the-fly issuer private key structure",
750                         gnutls_privkey_init (&onthefly_issuerkey));
751 fprintf (stderr, "DEBUG: before onthefly p11 import, gtlserrno = %d\n", gtls_errno);
752                 E_g2e ("Failed to import pkcs11: URI into on-the-fly issuer private key",
753                         gnutls_privkey_import_pkcs11_url (onthefly_issuerkey, otfsigkey));
754 fprintf (stderr, "DEBUG: after  onthefly p11 import, gtlserrno = %d\n", gtls_errno);
755         }
756 fprintf (stderr, "DEBUG: When it matters, gtls_errno = %d, onthefly_issuercrt %s NULL, onthefly_issuerkey %s NULL\n", gtls_errno, onthefly_issuercrt?"!=":"==", onthefly_issuerkey?"!=":"==");
757         if ((gtls_errno == GNUTLS_E_SUCCESS) && (onthefly_issuercrt != NULL) && (onthefly_issuerkey != NULL)) {
758                 E_g2e ("Failed to initialise on-the-fly certificate session key",
759                         gnutls_x509_privkey_init (&onthefly_subjectkey));
760                 E_g2e ("Failed to generate on-the-fly certificate session key",
761                         gnutls_x509_privkey_generate (onthefly_subjectkey, GNUTLS_PK_RSA, 2048 /*TODO:FIXED*/, 0));
762                 if (gtls_errno == GNUTLS_E_SUCCESS) {
763                         tlog (TLOG_TLS, LOG_INFO, "Setup for on-the-fly signing with the TLS Pool");
764                 } else {
765                         tlog (TLOG_TLS, LOG_ERR, "Failed to setup on-the-fly signing (shall continue without it)");
766                         gnutls_x509_privkey_deinit (onthefly_subjectkey);
767                         onthefly_subjectkey = NULL;
768                 }
769         } else {
770                 gtls_errno = GNUTLS_E_SUCCESS;
771                 E_gnutls_clear_errno ();
772         }
773         if (onthefly_subjectkey == NULL) {
774                 if (onthefly_issuercrt != NULL) {
775                         gnutls_x509_crt_deinit (onthefly_issuercrt);
776                         onthefly_issuercrt = NULL;
777                 }
778                 if (onthefly_issuerkey != NULL) {
779                         gnutls_privkey_deinit (onthefly_issuerkey);
780                         onthefly_issuerkey = NULL;
781                 }
782         }
783         //
784         // Finally, check whether there was any error setting up GnuTLS
785         if (gtls_errno != GNUTLS_E_SUCCESS) {
786                 tlog (TLOG_TLS, LOG_CRIT, "FATAL: GnuTLS setup failed: %s", gnutls_strerror (gtls_errno));
787                 exit (1);
788         }
789         //MOVED// //
790         //MOVED// // Setup the management databases
791         //MOVED// tlog (TLOG_DB, LOG_DEBUG, "Setting up management databases");
792         //MOVED// E_e2e ("Failed to setup management databases",
793         //MOVED//       setup_management ());
794         //MOVED// if (errno != 0) {
795         //MOVED//       tlog (TLOG_DB, LOG_CRIT, "FATAL: Management databases setup failed: %s", strerror (errno));
796         //MOVED//       exit (1);
797         //MOVED// }
798 }
799
800 /* Cleanup the structures and resources that were setup for handling TLS.
801  */
802 void cleanup_starttls (void) {
803         void cleanup_starttls_credentials (void);       /* Defined below */
804         //MOVED// cleanup_management ();
805         if (onthefly_subjectkey != NULL) {
806                 gnutls_x509_privkey_deinit (onthefly_subjectkey);
807                 onthefly_subjectkey = NULL;
808         }
809         if (onthefly_issuercrt != NULL) {
810                 gnutls_x509_crt_deinit (onthefly_issuercrt);
811                 onthefly_issuercrt = NULL;
812         }
813         if (onthefly_issuerkey != NULL) {
814                 gnutls_privkey_deinit (onthefly_issuerkey);
815                 onthefly_issuerkey = NULL;
816         }
817         if (kerberos_context != NULL) {
818                 krb5_free_context (kerberos_context);
819                 kerberos_context = NULL;
820         }
821         cleanup_starttls_credentials ();
822         remove_dh_params ();
823         gnutls_pkcs11_set_pin_function (NULL, NULL);
824         gnutls_pkcs11_set_token_function (NULL, NULL);
825         gnutls_pkcs11_deinit ();
826         gnutls_priority_deinit (priority_normal);
827         gnutls_global_deinit ();
828 }
829
830
831 /*
832  * The copycat function is a bidirectional transport between the given
833  * remote and local sockets, but it will encrypt traffic from local to
834  * remote, and decrypt traffic from remote to local.  It will do this
835  * until one of the end points is shut down, at which time it will
836  * return and assume the context will close down both pre-existing
837  * sockets.
838  *
839  * This copycat actually has a few sharp claws to watch for -- shutdown
840  * of sockets may drop the last bit of information sent.  First, the
841  * signal POLLHUP is best ignored because it travels asynchronously.
842  * Second, reading 0 is a good indicator of end-of-file and may be
843  * followed by an shutdown of reading from that stream.  But, more
844  * importantly, the other side must have this information forwarded
845  * so it can shutdown.  This means that a shutdown for writing to that
846  * stream is to be sent.  Even when *both* sides have agreed to not send
847  * anything, they may still not have received all they were offered for
848  * reading, so we should SO_LINGER on the sockets so they can acknowledge,
849  * and after a timeout we can establish that shutdown failed and log and
850  * return an error for it.
851  * Will you believe that I had looked up if close() would suffice?  The man
852  * page clearly stated yes.  However, these articles offer much more detail:
853  * http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable
854  * http://www.greenend.org.uk/rjk/tech/poll.html
855  *
856  * This function blocks during its call to poll(), in a state that can easily
857  * be restarted.  This is when thread cancellation is temporarily enabled.
858  * Other threads may use this to cancel the thread and have it joined with that
859  * thread which will subsume its tasks and restart the handshake.  We might
860  * later make this more advanced, by using a cancel stack push/pull mechanisms
861  * to ensure that recv() always results in send() in spite of cancellation.
862  *
863  * The return value of copycat is a GNUTLS_E_ code, usually GNUTLS_E_SUCCESS.
864  * For the moment, only one special value is of concern, namely
865  * GNUTLS_E_REHANDSHAKE which client or server side may receive when an
866  * attempt is made to renegotiate the security of the connection.
867  */
868 static int copycat (int local, int remote, gnutls_session_t wrapped, int client) {
869         char buf [1024];
870         struct pollfd inout [3];
871         ssize_t sz;
872         struct linger linger = { 1, 10 };
873         int have_client;
874         int retval = GNUTLS_E_SUCCESS;
875
876         inout [0].fd = local;
877         inout [1].fd = remote;
878         inout [2].fd = client;
879         have_client = inout [2].fd >= 0;
880         if (!have_client) {
881                 inout [2].revents = 0;  // Will not be written by poll
882                 //FORK!=DETACH// inout [2].fd = ctlkey_signalling_fd;
883         }
884         inout [0].events = POLLIN;
885         inout [1].events = POLLIN;
886         inout [2].events = 0;   // error events only
887         tlog (TLOG_COPYCAT, LOG_DEBUG, "Starting copycat cycle for local=%d, remote=%d, control=%d", local, remote, client);
888         while (((inout [0].events | inout [1].events) & POLLIN) != 0) {
889                 int polled;
890                 assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE,  NULL) == 0);
891                 pthread_testcancel ();  // Efficiency & Certainty
892                 polled = poll (inout, have_client? 3: 2, -1);
893                 assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
894                 if (polled == -1) {
895                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat polling returned an error");
896                         break;  // Polling sees an error
897                 }
898                 if (inout [0].revents & POLLIN) {
899                         // Read local and encrypt to remote
900                         sz = recv (local, buf, sizeof (buf), MSG_DONTWAIT | MSG_NOSIGNAL);
901                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d local bytes (or error<0) from %d", (int) sz, local);
902                         if (sz == -1) {
903                                 tlog (TLOG_COPYCAT, LOG_ERR, "Error while receiving: %s", strerror (errno));
904                                 break;  // stream error
905                         } else if (sz == 0) {
906                                 inout [0].events &= ~POLLIN;
907                                 shutdown (local, SHUT_RD);
908                                 setsockopt (remote, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
909                                 gnutls_bye (wrapped, GNUTLS_SHUT_WR);
910                         } else if (gnutls_record_send (wrapped, buf, sz) != sz) {
911                                 tlog (TLOG_COPYCAT, LOG_ERR, "gnutls_record_send() failed to pass on the requested bytes");
912                                 break;  // communication error
913                         } else {
914                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to remote %d", (int) sz, remote);
915                         }
916                 }
917                 if (inout [1].revents & POLLIN) {
918                         // Read remote and decrypt to local
919                         sz = gnutls_record_recv (wrapped, buf, sizeof (buf));
920                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d remote bytes from %d (or error if <0)", (int) sz, remote);
921                         if (sz < 0) {
922                                 //TODO// Process GNUTLS_E_REHANDSHAKE
923                                 if (sz == GNUTLS_E_REHANDSHAKE) {
924                                         tlog (TLOG_TLS, LOG_INFO, "Received renegotiation request over TLS handle %d", remote);
925                                         retval = GNUTLS_E_REHANDSHAKE;
926                                         break;
927                                 } else if (gnutls_error_is_fatal (sz)) {
928                                         tlog (TLOG_TLS, LOG_ERR, "GnuTLS fatal error: %s", gnutls_strerror (sz));
929                                         break;  // stream error
930                                 } else {
931                                         tlog (TLOG_TLS, LOG_INFO, "GnuTLS recoverable error: %s", gnutls_strerror (sz));
932                                 }
933                         } else if (sz == 0) {
934                                 inout [1].events &= ~POLLIN;
935                                 shutdown (remote, SHUT_RD);
936                                 setsockopt (local, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
937                                 shutdown (local, SHUT_WR);
938                         } else if (send (local, buf, sz, MSG_DONTWAIT | MSG_NOSIGNAL) != sz) {
939                                 break;  // communication error
940                         } else {
941                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to local %d", (int) sz, local);
942                         }
943                 }
944                 inout [0].revents &= ~(POLLIN | POLLHUP); // Thy copying cat?
945                 inout [1].revents &= ~(POLLIN | POLLHUP); // Retract thee claws!
946                 if ((inout [0].revents | inout [1].revents) & ~POLLIN) {
947                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat data connection polling returned a special condition");
948                         break;  // Apparently, one of POLLERR, POLLHUP, POLLNVAL
949                 }
950                 if (inout [2].revents & ~POLLIN) {
951                         if (have_client) {
952                                 // This case is currently not ever triggered
953                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat control connection polling returned a special condition");
954                                 break;  // Apparently, one of POLLERR, POLLHUP, POLLNVAL
955                         } else {
956                                 inout [2].fd = client;
957                                 have_client = inout [2].fd >= 0;
958                                 if (have_client) {
959                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal to set control fd to %d", inout [2].fd);
960                                 } else {
961                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal that could be ignored");
962                                 }
963                                 continue;
964                         }
965                 }
966         }
967         tlog (TLOG_COPYCAT, LOG_DEBUG, "Ending copycat cycle for local=%d, remote=%d", local, remote);
968         return retval;
969 }
970
971
972 /* The callback function that retrieves certification information from either
973  * the client or the server in the course of the handshake procedure.
974  */
975 gtls_error clisrv_cert_retrieve (gnutls_session_t session,
976                                 const gnutls_datum_t* req_ca_dn,
977                                 int nreqs,
978                                 const gnutls_pk_algorithm_t* pk_algos,
979                                 int pk_algos_length,
980                                 gnutls_pcert_st** pcert,
981                                 unsigned int *pcert_length,
982                                 gnutls_privkey_t *pkey) {
983         gnutls_certificate_type_t certtp;
984         gnutls_pcert_st *pc = NULL;
985         struct command *cmd;
986         char *lid, *rid;
987         gnutls_datum_t privdatum = { NULL, 0 };
988         gnutls_datum_t certdatum = { NULL, 0 };
989         gnutls_openpgp_crt_t pgpcert = NULL;
990         gnutls_openpgp_privkey_t pgppriv = NULL;
991         int gtls_errno = GNUTLS_E_SUCCESS;
992         int lidtype;
993         int lidrole = 0;
994         char *rolestr;
995         char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.localid)];
996         size_t snilen = sizeof (sni);
997         int snitype;
998         int ok;
999         uint32_t flags;
1000         char *p11priv;
1001         uint8_t *pubdata;
1002         int pubdatalen;
1003         gtls_error fetch_local_credentials (struct command *cmd);
1004         gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum);
1005
1006         //
1007         // Setup a number of common references and structures
1008         *pcert = NULL;
1009         cmd = (struct command *) gnutls_session_get_ptr (session);
1010         if (cmd == NULL) {
1011                 E_g2e ("No data pointer with session",
1012                         GNUTLS_E_INVALID_SESSION);
1013                 return gtls_errno;
1014         }
1015         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
1016                 lidrole = LID_ROLE_CLIENT;
1017                 rolestr = "client";
1018         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
1019                 lidrole = LID_ROLE_SERVER;
1020                 rolestr = "server";
1021         } else {
1022                 E_g2e ("TLS Pool command supports neither local client nor local server role",
1023                         GNUTLS_E_INVALID_SESSION);
1024                 return gtls_errno;
1025         }
1026         lid = cmd->cmd.pio_data.pioc_starttls.localid;
1027         rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1028
1029         //
1030         // On a server, lookup the server name and match it against lid.
1031         // TODO: For now assume a single server name in SNI (as that is normal).
1032         if (lidrole == LID_ROLE_SERVER) {
1033                 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) || (snitype != GNUTLS_NAME_DNS)) {
1034                         E_g2e ("Requested SNI error or not a DNS name",
1035                                 GNUTLS_E_NO_CERTIFICATE_FOUND);
1036                         return gtls_errno;
1037                 }
1038                 if (*lid != '\0') {
1039                         int atidx;
1040                         for (atidx=128; atidx > 0; atidx--) {
1041                                 if (lid [atidx-1] == '@') {
1042                                         break;
1043                                 }
1044                         }
1045                         if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
1046                                 tlog (TLOG_TLS, LOG_ERR, "SNI %s does not match preset local identity %s", sni, lid);
1047                                 E_g2e ("Requested SNI does not match local identity",
1048                                         GNUTLS_E_NO_CERTIFICATE_FOUND);
1049                                 return gtls_errno;
1050                         }
1051                 } else {
1052                         // TODO: Should ask for permission before accepting SNI
1053                         memcpy (lid, sni, sizeof (sni));
1054                 }
1055         }
1056
1057         //
1058         // Setup the lidtype parameter for responding
1059         certtp = gnutls_certificate_type_get_peers (session);
1060         if (certtp == GNUTLS_CRT_OPENPGP) {
1061                 tlog (TLOG_TLS, LOG_INFO, "Serving OpenPGP certificate request as a %s", rolestr);
1062                 lidtype = LID_TYPE_PGP;
1063         } else if (certtp == GNUTLS_CRT_X509) {
1064                 tlog (TLOG_TLS, LOG_INFO, "Serving X.509 certificate request as a %s", rolestr);
1065                 lidtype = LID_TYPE_X509;
1066 #ifdef HAVE_TLS_KDH
1067         } else if (certtp == GNUTLS_CRT_KRB) {
1068                 tlog (TLOG_TLS, LOG_INFO, "Serving X.509 certificate request as a %s", rolestr);
1069                 lidtype = LID_TYPE_KRB5;
1070 #endif
1071         } else {
1072                 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1073                 tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate retrieval attempted as a %s", rolestr);
1074                 E_g2e ("Requested certtype is neither X.509 nor OpenPGP",
1075                         GNUTLS_E_CERTIFICATE_ERROR);
1076                 return gtls_errno;
1077         }
1078
1079         //
1080         // Find the prefetched local identity to use towards this remote
1081         // Send a callback to the user if none is available and accessible
1082         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_CHECK) {
1083                 uint32_t oldcmd = cmd->cmd.pio_cmd;
1084                 struct command *resp;
1085                 cmd->cmd.pio_cmd = PIOC_STARTTLS_LOCALID_V2;
1086                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_STARTTLS_LOCALID_V2");
1087                 resp = send_callback_and_await_response (cmd, 0);
1088                 assert (resp != NULL);  // No timeout, should be non-NULL
1089                 if (resp->cmd.pio_cmd != PIOC_STARTTLS_LOCALID_V2) {
1090                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
1091                         cmd->cmd.pio_cmd = oldcmd;
1092                         return GNUTLS_E_CERTIFICATE_ERROR;
1093                 }
1094                 assert (resp == cmd);  // No ERROR, so should be the same
1095                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that sets plainfd:=%d and lid:=\"%s\" for rid==\"%s\"", cmd->passfd, lid, rid);
1096                 cmd->cmd.pio_cmd = oldcmd;
1097                 //
1098                 // Check that new rid is a generalisation of original rid
1099                 // Note: This is only of interest for client operation
1100                 if (lidrole == LID_ROLE_CLIENT) {
1101                         selector_t newrid = donai_from_stable_string (rid, strlen (rid));
1102                         donai_t oldrid = donai_from_stable_string (cmd->orig_starttls->remoteid, strlen (cmd->orig_starttls->remoteid));
1103                         if (!donai_matches_selector (&oldrid, &newrid)) {
1104                                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
1105                         }
1106                 }
1107                 //
1108                 // Now reiterate to lookup lid credentials in db_localid
1109                 E_g2e ("Missing local credentials",
1110                         fetch_local_credentials (cmd));
1111         }
1112         if (cmd->lids [lidtype - LID_TYPE_MIN].data == NULL) {
1113 fprintf (stderr, "DEBUG: Missing certificate for local ID %s and remote ID %s\n", lid, rid);
1114                 E_g2e ("Missing certificate for local ID",
1115                         GNUTLS_E_NO_CERTIFICATE_FOUND);
1116                 return gtls_errno;
1117         }
1118
1119         //
1120         // Split the credential into its various aspects
1121         ok = dbcred_interpret (
1122                 &cmd->lids [lidtype - LID_TYPE_MIN],
1123                 &flags,
1124                 &p11priv,
1125                 &certdatum.data,
1126                 &certdatum.size);
1127         tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, p11priv=\"%s\", cert.size=%d", flags, p11priv, certdatum.size);
1128         //TODO// ok = ok && verify_cert_... (...); -- keyidlookup
1129         if (!ok) {
1130                 gtls_errno = GNUTLS_E_CERTIFICATE_ERROR;
1131         }
1132
1133         //
1134         // Allocate response structures
1135         *pcert_length = 0;
1136         *pcert = load_certificate_chain (flags, pcert_length, &certdatum);
1137         if (*pcert == NULL) {
1138                 E_g2e ("Failed to load certificate chain",
1139                         GNUTLS_E_CERTIFICATE_ERROR);
1140                 return gtls_errno;
1141         }
1142         cmd->session_certificate = (intptr_t) (void *) *pcert;  //TODO// Used for session cleanup
1143
1144         //
1145         // Setup private key
1146         E_g2e ("Failed to initialise private key",
1147                 gnutls_privkey_init (
1148                         pkey));
1149         if ((onthefly_subjectkey != NULL) && (strcmp (p11priv, onthefly_p11uri) == 0)) {
1150                 // Setup the on-the-fly certification key as private key
1151                 E_g2e ("Failed to import on-the-fly subject private key",
1152                         gnutls_privkey_import_x509 (
1153                                 *pkey,
1154                                 onthefly_subjectkey,
1155                                 GNUTLS_PRIVKEY_IMPORT_COPY));
1156 #ifdef HAVE_TLS_KDH
1157         } else if (lidtype == LID_TYPE_KRB5) {
1158                 // Fake a private key for Kerberos (we sign it out here, not GnuTLS)
1159                 E_g2e ("Failed to generate a private-key placeholder for Kerberos",
1160                         gnutls_privkey_generate_krb (
1161                                 *pkey,
1162                                 0));
1163 #endif
1164         } else {
1165                 // Import the PKCS #11 key as the private key for use by GnuTLS
1166                 if (gtls_errno == GNUTLS_E_SUCCESS) {
1167                         cmd->session_privatekey = (intptr_t) (void *) *pkey;    //TODO// Used for session cleanup
1168                 }
1169                 E_g2e ("Failed to import PKCS #11 private key URI",
1170                         gnutls_privkey_import_pkcs11_url (
1171                                 *pkey,
1172                                 p11priv));
1173         }
1174         E_gnutls_clear_errno ();
1175
1176 //TODO// Moved out (start)
1177
1178         //
1179         // Setup public key certificate
1180         switch (lidtype) {
1181         case LID_TYPE_X509:
1182                 E_g2e ("MOVED: Failed to import X.509 certificate into chain",
1183                         gnutls_pcert_import_x509_raw (
1184                                 *pcert,
1185                                 &certdatum,
1186                                 GNUTLS_X509_FMT_DER,
1187                                 0));
1188                 break;
1189         case LID_TYPE_PGP:
1190                 E_g2e ("MOVED: Failed to import OpenPGP key",
1191                         gnutls_pcert_import_openpgp_raw (
1192                                 *pcert,
1193                                 &certdatum,
1194                                 GNUTLS_OPENPGP_FMT_RAW,
1195                                 NULL,   /* use master key */
1196                                 0));
1197                 break;
1198 #ifdef HAVE_TLS_KDH
1199         case LID_TYPE_KRB5:
1200                 if (lidrole == LID_ROLE_CLIENT) {
1201                         // KDH-Only or KDH-Enhanced; fetch ticket for localid
1202                         // and a TGT based on it for service/remoteid@REALM
1203                         char *svc = cmd->cmd.pio_data.pioc_starttls.service;
1204                         const gnutls_datum_t *server_tgt = NULL;
1205                         // If the server provides a TGT, employ ENC-TKT-IN-SKEY
1206                         if (gnutls_certificate_type_get_peers (cmd->session) == GNUTLS_CRT_KRB) {
1207                                 // Try to get the server's TGT; it returns NULL
1208                                 // if it wasn't found.  We will not try this
1209                                 // unless we know what we'd find would be KRB.
1210                                 server_tgt = gnutls_certificate_get_peers (cmd->session, NULL);
1211                         }
1212                         // The servicename may need mapping to another form
1213                         if (strcmp (svc, "http")) {
1214                                 svc = "HTTP";
1215                         }
1216                         //TODO: Have a client ticket matching the found localid
1217                         //TODO: From the client ticket, obtain a service ticket
1218                         //TODO: Export the service ticket
1219                         krb5_ccache mycache;
1220                         krb5_creds prep_creds;
1221                         krb5_creds *gotten_creds = NULL;
1222                         char klid [128 + 1];
1223                         char krid [128 + 1];
1224                         krb5_data klidprincipal [1];
1225                         krb5_data kridprincipal [2];
1226                         char *klidrealm;
1227                         char *kridrealm;
1228                         char *realmtmp;
1229                         // Fill the credentials request
1230                         memset (&prep_creds, 0, sizeof (prep_creds));
1231                         memcpy (klid, cmd->cmd.pio_data.pioc_starttls.localid,  128);
1232                         memcpy (krid, cmd->cmd.pio_data.pioc_starttls.remoteid, 128);
1233                         klid [128] = krid [128] = '\0';
1234                         realmtmp = strrchr (klid, '@');
1235                         if (realmtmp != NULL) {
1236                                 *realmtmp++ = '\0';
1237                                 prep_creds.client->realm.data = realmtmp;
1238                                 prep_creds.client->realm.length = strlen (realmtmp);
1239                                 while (*realmtmp) {
1240                                         *realmtmp++ = toupper (*realmtmp);
1241                                 }
1242                         }
1243                         klidprincipal [0].data = klid;
1244                         klidprincipal [0].length = strlen (klid);
1245                         prep_creds.client->data = klidprincipal;
1246                         prep_creds.client->length = 1;
1247                         prep_creds.client->type = KRB5_NT_PRINCIPAL;
1248                         realmtmp = strrchr (krid, '@');
1249                         if (realmtmp != NULL) {
1250                                 *realmtmp++ = '\0';
1251                                 prep_creds.server->realm.data = realmtmp;
1252                                 prep_creds.server->realm.length = strlen (realmtmp);
1253                                 while (*realmtmp) {
1254                                         *realmtmp++ = toupper (*realmtmp);
1255                                 }
1256                         }
1257                         kridprincipal [0].data = svc;
1258                         kridprincipal [0].length = strnlen (svc, TLSPOOL_SERVICELEN);
1259                         kridprincipal [1].data = krid;
1260                         kridprincipal [1].length = strlen (krid);
1261                         prep_creds.server->data = kridprincipal;
1262                         prep_creds.server->length = 1;
1263                         prep_creds.server->type = KRB5_NT_SRV_HST;
1264                         // KDH-Only with server-side TGT
1265                         //TODO//  1. setup flag KRB5_GC_USER_USER
1266                         //TODO//  2. fill the .second_ticket value
1267                         ok = ok && (0 == have_credcache (prep_creds.client, &mycache));
1268                         ok = ok && (mycache != NULL);
1269                         ok = ok && (0 == krb5_get_credentials (
1270                                         kerberos_context,
1271                                         0,
1272                                         mycache,
1273                                         &prep_creds,
1274                                         &gotten_creds));
1275                         ok = ok && (gotten_creds != NULL);
1276                         if (!ok) {
1277                                 gtls_errno = GNUTLS_E_AUTH_ERROR;
1278                         } else {
1279                                 certdatum.data = gotten_creds->ticket.data;
1280                                 certdatum.size = gotten_creds->ticket.length;
1281                         }
1282                         E_g2e ("MOVED: Failed to import Kerberos ticket",
1283                                 gnutls_pcert_import_krb_raw (
1284                                         *pcert,
1285                                         &certdatum,
1286                                         0));
1287                         if (gotten_creds != NULL) {
1288                                 krb5_free_creds (kerberos_context, gotten_creds);
1289                                 gotten_creds = NULL;
1290                         }
1291                 } else {
1292                         // For KDH-Only, servers can send a TGT if they want to
1293                         //TODO// E_g2e ("MOVED: Failed to import Kerberos ticket",
1294                         //TODO//        gnutls_pcert_import_krb_raw (
1295                         //TODO//                *pcert,
1296                         //TODO//                &certdatum,     //TODO:WHATSFOUND//
1297                         //TODO//                0));
1298                 }
1299 #endif
1300         default:
1301                 /* Should not happen */
1302                 break;
1303         }
1304
1305 //TODO// Moved out (end)
1306
1307         //
1308         // Lap up any overseen POSIX error codes in errno
1309         if (errno) {
1310                 tlog (TLOG_TLS, LOG_DEBUG, "Failing TLS on errno=%d / %s", errno, strerror (errno));
1311                 cmd->session_errno = errno;
1312                 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
1313         }
1314
1315         //
1316         // Return the overral error code, hopefully GNUTLS_E_SUCCESS
1317         tlog (TLOG_TLS, LOG_DEBUG, "Returning %d / %s from clisrv_cert_retrieve()", gtls_errno, gnutls_strerror (gtls_errno));
1318 printf ("DEBUG: clisrv_cert_retrieve() sets *pcert to 0x%xl (length %d)... {pubkey = 0x%lx, cert= {data = 0x%lx, size=%ld}, type=%ld}\n", (long) *pcert, *pcert_length, (long) (*pcert)->pubkey, (long) (*pcert)->cert.data, (long) (*pcert)->cert.size, (long) (*pcert)->type);
1319         return gtls_errno;
1320 }
1321
1322 /* Load a single certificate in the given gnutls_pcert_st from the given
1323  * gnutls_datum_t.  Use the lidtype to determine how to do this.
1324  */
1325 gtls_error load_certificate (int lidtype, gnutls_pcert_st *pcert, gnutls_datum_t *certdatum) {
1326         int gtls_errno = GNUTLS_E_SUCCESS;
1327         //
1328         // Setup public key certificate
1329         switch (lidtype) {
1330         case LID_TYPE_X509:
1331 fprintf (stderr, "DEBUG: About to import %d bytes worth of X.509 certificate into chain: %02x %02x %02x %02x...\n", certdatum->size, certdatum->data[0], certdatum->data[1], certdatum->data[2], certdatum->data[3]);
1332                 E_g2e ("Failed to import X.509 certificate into chain",
1333                         gnutls_pcert_import_x509_raw (
1334                                 pcert,
1335                                 certdatum,
1336                                 GNUTLS_X509_FMT_DER,
1337                                 0));
1338                 break;
1339         case LID_TYPE_PGP:
1340                 E_g2e ("Failed to import OpenPGP certificate",
1341                         gnutls_pcert_import_openpgp_raw (
1342                                 pcert,
1343                                 certdatum,
1344                                 GNUTLS_OPENPGP_FMT_RAW,
1345                                 NULL,   /* use master key */
1346                                 0));
1347                 break;
1348         default:
1349                 /* Should not happen */
1350                 break;
1351         }
1352         return gtls_errno;
1353 }
1354
1355
1356 /* Load a certificate chain.  This returns a value for a retrieval function's
1357  * pcert, and also modifies the chainlen.  The latter starts at 0, and is
1358  * incremented in a nested procedure that unrolls until all certificates are
1359  * loaded.
1360  */
1361 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum) {
1362         gnutls_pcert_st *chain;
1363         unsigned int mypos = *chainlen;
1364         int gtls_errno = GNUTLS_E_SUCCESS;
1365
1366         //
1367         // Quick and easy: No chaining required, just add the literal data.
1368         // Note however, this may be the end of a chain, so allocate all
1369         // structures and load the single one at the end.
1370         if ((flags & (LID_CHAINED | LID_NEEDS_CHAIN)) == 0) {
1371                 (*chainlen)++;
1372                 chain = (gnutls_pcert_st *) calloc (*chainlen, sizeof (gnutls_pcert_st));
1373                 if (chain != NULL) {
1374                         bzero (chain, (*chainlen) * sizeof (gnutls_pcert_st));
1375                 } else {
1376                         gtls_errno = GNUTLS_E_MEMORY_ERROR;
1377                 }
1378                 E_g2e ("Failed to load certificate into chain",
1379                         load_certificate (
1380                                 flags & LID_TYPE_MASK,
1381                                 &chain [mypos],
1382                                 certdatum));
1383                 if (gtls_errno != GNUTLS_E_SUCCESS) {
1384                         if (chain) {
1385                                 free (chain);
1386                         }
1387                         *chainlen = 0;
1388                         chain = NULL;
1389                 }
1390                 return chain;
1391         }
1392
1393         //
1394         // First extended case.  Chain certs in response to LID_CHAINED.
1395         // Recursive calls are depth-first, so we only add our first cert
1396         // after a recursive call succeeds.  Any LID_NEEDS_CHAIN work is
1397         // added after LID_CHAINED, so is higher up in the hierarchy, but
1398         // it is loaded as part of the recursion.  To support that, a
1399         // recursive call with certdatum.size==0 is possible when the
1400         // LID_NEEDS_CHAIN flag is set, and this section then skips.
1401         // Note that this code is also used to load the certificate chain
1402         // provided by LID_NEEDS_CHAIN, but by then the flag in a recursive
1403         // call is replaced with LID_CHAINED and no more LID_NEEDS_CHAIN.
1404         if (((flags & LID_CHAINED) != 0) && (certdatum->size > 0)) {
1405                 long certlen;
1406                 int lenlen;
1407                 gnutls_datum_t nextdatum;
1408                 long nextlen;
1409                 // Note: Accept BER because the outside SEQUENCE is not signed
1410                 certlen = asn1_get_length_ber (
1411                         ((char *) certdatum->data) + 1,
1412                         certdatum->size,
1413                         &lenlen);
1414                 certlen += 1 + lenlen;
1415                 tlog (TLOG_CERT, LOG_DEBUG, "Found LID_CHAINED certificate size %d", certlen);
1416                 if (certlen > certdatum->size) {
1417                         tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate beyond data size %d", certdatum->size);
1418                         *chainlen = 0;
1419                         return NULL;
1420                 } else if (certlen <= 0) {
1421                         tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate of too-modest data size %d", certlen);
1422                         *chainlen = 0;
1423                         return NULL;
1424                 }
1425                 nextdatum.data = ((char *) certdatum->data) + certlen;
1426                 nextdatum.size =           certdatum->size  - certlen;
1427                 certdatum->size = certlen;
1428                 nextlen = asn1_get_length_ber (
1429                         ((char *) nextdatum.data) + 1,
1430                         nextdatum.size,
1431                         &lenlen);
1432                 nextlen += 1 + lenlen;
1433                 if (nextlen == nextdatum.size) {
1434                         // The last cert is loaded thinking it is not CHAINED,
1435                         // but NEEDS_CHAIN can still be present for expansion.
1436                         flags &= ~LID_CHAINED;
1437                 }
1438                 (*chainlen)++;
1439                 chain = load_certificate_chain (flags, chainlen, &nextdatum);
1440                 if (chain != NULL) {
1441                         E_g2e ("Failed to add chained certificate",
1442                                 load_certificate (
1443                                         flags & LID_TYPE_MASK,
1444                                         &chain [mypos],
1445                                         certdatum));
1446                         if (gtls_errno != GNUTLS_E_SUCCESS) {
1447                                 free (chain);
1448                                 chain = NULL;
1449                                 *chainlen = 0;
1450                         }
1451                 }
1452                 return chain;
1453         }
1454
1455         //
1456         // Second extended case.  Chain certs in response to LID_NEEDS_CHAIN.
1457         // These are the highest-up in the hierarchy, above any LID_CHAINED
1458         // certificates.  The procedure for adding them is looking them up
1459         // in a central database by their authority key identifier.  What is
1460         // found is assumed to be a chain, and will be unrolled by replacing
1461         // the LID_NEEDS_CHAIN flag with LID_CHAINED and calling recursively.
1462         if (((flags & LID_NEEDS_CHAIN) != 0) && (certdatum->size == 0)) {
1463                 //TODO//CODE// lookup new certdatum
1464                 flags &= ~LID_NEEDS_CHAIN;
1465                 flags |=  LID_CHAINED;
1466                 //TODO//CODE// recursive call
1467                 //TODO//CODE// no structures to fill here
1468                 //TODO//CODE// cleanup new certdatum
1469         }
1470
1471         //
1472         // Final judgement.  Nothing worked.  Return failure.
1473         *chainlen = 0;
1474         return NULL;
1475 }
1476
1477
1478 /* Iterate over a credential cache collection, looking for the one that
1479  * has the desired principal name and realm.  If it does not exist yet,
1480  * create it.  This works with collections such as DIR:/var/tlspool/creds
1481  * or, only on Linux, KEYRING:process:name to store creds in the kernel.
1482  * The function returns 0 when ok, or otherwise nonzero.
1483  */
1484 #ifdef HAVE_TLS_KDH
1485 static krb5_error_code have_credcache (krb5_principal sought, krb5_ccache *found) {
1486         krb5_cccol_cursor crs;
1487         krb5_ccache tmp;
1488         krb5_principal princ;
1489         *found = NULL;
1490         crs = NULL;
1491         int hit;
1492         if (0 == krb5_cccol_cursor_new (kerberos_context, &crs)) {
1493                 while (0 != krb5_cccol_cursor_next (kerberos_context, crs, &tmp)) {
1494                         if (tmp == NULL) {
1495                                 // No more ccache in directory
1496                                 break;
1497                         }
1498                         if (0 != krb5_cc_get_principal (kerberos_context, tmp, &princ)) {
1499                                 break;
1500                         }
1501                         hit = krb5_principal_compare (kerberos_context, princ, sought);
1502                         krb5_free_principal (kerberos_context, princ);
1503                         if (hit) {
1504                                 *found = tmp;
1505                                 // Avoid cleaning up the context
1506                                 break;
1507                         }
1508                         krb5_cc_close (kerberos_context, tmp);
1509                 }
1510         }
1511         if (crs != NULL) {
1512                 krb5_cccol_cursor_free (kerberos_context, &crs);
1513                 crs = NULL;
1514         }
1515         // If need be, create a new credential cache
1516         if (NULL == *found) {
1517                 //TODO// Param "type" set to "DIR" but that's pretty fixed.
1518                 //TODO// Is "hint" really not interpreted?!?
1519                 if (0 == krb5_cc_new_unique (kerberos_context, "DIR", NULL, &tmp)) {
1520                         if (0 == krb5_cc_initialize (kerberos_context, tmp, sought)) {
1521                                 *found = tmp;
1522                         }
1523                 }
1524         }
1525         return (NULL != *found)? 0: KRB5_CC_NOTFOUND;
1526 }
1527 #endif
1528
1529
1530 /* valexp_valflag_set -- set a validation flag bit for an uppercase predicate.
1531  */
1532 static void valexp_valflag_set (struct command *cmd, char pred) {
1533         int len = strlen (cmd->valflags);
1534         cmd->valflags [len++] = pred;
1535         cmd->valflags [len  ] = '\0';
1536 }
1537
1538 /* valexp_valflag_start -- get a prior set bit with validation information.
1539  * Where cmd->valflags is a string of uppercase letters that were ensured.
1540  */
1541 static void valexp_valflag_start (void *vcmd, struct valexp *ve, char pred) {
1542         struct command *cmd = (struct command *) vcmd;
1543         pred &= 0xdf;   // lowercase->uppercase
1544         valexp_setpredicate (ve, pred, NULL != strchr (cmd->valflags, pred));
1545 }
1546
1547 /* valexp_0_start -- validation function for the GnuTLS backend.
1548  * This function immediately sends failure on something impossible.
1549  */
1550 static void valexp_0_start (void *vcmd, struct valexp *ve, char pred) {
1551         valexp_setpredicate (ve, pred, 0);
1552 }
1553
1554 /* valexp_1_start -- validation function for the GnuTLS backend.
1555  * This function immediately sends success on something trivial.
1556  */
1557 static void valexp_1_start (void *vcmd, struct valexp *ve, char pred) {
1558         valexp_setpredicate (ve, pred, 1);
1559 }
1560
1561 //TODO// valexp_L_start, valexp_l_start
1562
1563 /* valexp_I_start -- validation function for the GnuTLS backend.
1564  * This function ensures that the remote peer provides an identity.
1565  * TODO: We should compare the hostname as well, or compare if in remoteid
1566  * TODO: We may need to support more than just X509/PGP certificates 
1567  */
1568 static void valexp_I_start (void *vcmd, struct valexp *ve, char pred) {
1569         struct command *cmd = (struct command *) vcmd;
1570         unsigned int num_certs = 0;
1571         // peer-returned "certs" points into GnuTLS' internal data structures
1572         valexp_setpredicate (ve, pred,
1573                 (gnutls_certificate_get_peers (cmd->session, &num_certs) != NULL)
1574                 && (num_certs > 0));
1575 }
1576
1577 /* valexp_i_start -- is opportunistic and will always succeed
1578  */
1579 #define valexp_i_start valexp_1_start
1580
1581 /* valexp_Ff_start -- validation function for the GnuTLS backend.
1582  * This functin ensures that forward secrecy is applied.
1583  * While _F_ only accepts DHE, _f_ will also accept DH.
1584  * Note: GnuTLS does not seem to show DH that is not also DHE.
1585  */
1586 static void valexp_Ff_start (void *vcmd, struct valexp *ve, char pred) {
1587         struct command *cmd = (struct command *) vcmd;
1588         gnutls_kx_algorithm_t kx = gnutls_kx_get (cmd->session);
1589         switch (kx) {
1590         case GNUTLS_KX_UNKNOWN:
1591         case GNUTLS_KX_RSA:
1592         case GNUTLS_KX_RSA_EXPORT:
1593         case GNUTLS_KX_PSK:
1594         default:
1595                 valexp_setpredicate (ve, pred, 0);
1596                 break;
1597         case GNUTLS_KX_DHE_DSS:
1598         case GNUTLS_KX_DHE_RSA:
1599         case GNUTLS_KX_SRP:
1600         case GNUTLS_KX_SRP_RSA:
1601         case GNUTLS_KX_SRP_DSS:
1602         case GNUTLS_KX_DHE_PSK:
1603         case GNUTLS_KX_ECDHE_RSA:
1604         case GNUTLS_KX_ECDHE_ECDSA:
1605         case GNUTLS_KX_ECDHE_PSK:
1606         case GNUTLS_KX_ANON_ECDH:       // Assume DHE is in fact implemented
1607         case GNUTLS_KX_ANON_DH:         // Assume DHE is in fact implemented
1608                 valexp_setpredicate (ve, pred, 1);
1609                 break;
1610         // case GNUTLS_KX_xxx_DH:
1611         //      valexp_setpredicate (ve, pred, pred != 'F');
1612         //      break;
1613         }
1614 }
1615
1616 /* valexp_A_start -- validation function for the GnuTLS backend.
1617  * This function ensures that an anonymising precursor is used.
1618  */
1619 #define valexp_A_start valexp_valflag_start
1620
1621 /* valexp_a_start -- is opportunistic and will always succeed */
1622 #define valexp_a_start valexp_1_start
1623
1624 /* valexp_Tt_start -- validation function for the GnuTLS backend.
1625  * This function ensures trust based on a trusted certificate/key list.
1626  * In the _t_ case, self-signed certificates are also accepted.
1627  */
1628 static void valexp_Tt_start (void *vcmd, struct valexp *ve, char pred) {
1629         struct command *cmd = (struct command *) vcmd;
1630         int flagval = 0;
1631         gnutls_credentials_type_t authtp;
1632         const gnutls_datum_t *certs;
1633         unsigned int num_certs;
1634         if (cmd->vfystatus == 0) {
1635                 goto setflagval;
1636         }
1637         authtp = gnutls_auth_get_type (cmd->session);
1638         if (authtp != GNUTLS_CRD_CERTIFICATE) {
1639                 goto setflagval;
1640         }
1641         certs = gnutls_certificate_get_peers (cmd->session, &num_certs);
1642         // "certs" points into GnuTLS' internal data structures
1643         if (num_certs < 1) {
1644                 goto setflagval;
1645         }
1646         if ((num_certs == 1) && (pred == 't')) {
1647                 //TODO// if (self-signature-correct) {
1648                 //TODO//        flagval = 1;
1649                 //TODO//        goto setflagval;
1650                 //TODO// }
1651         }
1652         //TODO// Look in trust.db for H(cert[num_certs-1])
1653         //TODO// flagval = 1;
1654 setflagval:
1655         valexp_setpredicate (ve, pred, flagval);
1656 }
1657
1658 /* valexp_Dd_start -- validation function for the GnuTLS backend.
1659  * This function validates through DNSSEC.
1660  * While _D_ enforces DNSSEC, _d_ also accepts opted-out security.
1661  */
1662 static void valexp_Dd_start (void *vcmd, struct valexp *ve, char pred) {
1663         struct command *cmd = (struct command *) vcmd;
1664         int flagval = 0;
1665         dane_state_t stat;
1666         unsigned int vfystat;
1667         char *host;
1668         char *proto;
1669         int sox;
1670         struct sockaddr peername;
1671         socklen_t peernamesz = sizeof (peername);
1672         uint16_t port;
1673         host = strchr (cmd->cmd.pio_data.pioc_starttls.remoteid, '@');
1674         if (host == NULL) {
1675                 host = cmd->cmd.pio_data.pioc_starttls.remoteid;
1676         }
1677         switch (cmd->cmd.pio_data.pioc_starttls.ipproto) {
1678         case IPPROTO_TCP:
1679                 proto = "tcp";
1680                 break;
1681         case IPPROTO_UDP:
1682                 proto = "udp";
1683                 break;
1684         case IPPROTO_SCTP:
1685                 proto = "sctp";
1686                 break;
1687         default:
1688                 goto setflagval;
1689         }
1690         sox = gnutls_transport_get_int (cmd->session);
1691         if (sox < 0) {
1692                 goto setflagval;
1693         }
1694         if (getpeername (sox, &peername, &peernamesz) != 0) {
1695                 goto setflagval;
1696         }
1697         if ((peername.sa_family == AF_INET) &&
1698                                 (peernamesz == sizeof (struct sockaddr_in))) {
1699                 port = ntohs (((struct sockaddr_in *) &peername)->sin_port);
1700         } else if ((peername.sa_family == AF_INET6) &&
1701                                 (peernamesz == sizeof (struct sockaddr_in6))) {
1702         } else {
1703                 port = ntohs (((struct sockaddr_in6 *) &peername)->sin6_port);
1704                 goto setflagval;
1705         }
1706         if (dane_state_init (&stat, /*TODO:*/ 0) != GNUTLS_E_SUCCESS) {
1707                 goto setflagval;
1708         }
1709         if (dane_verify_session_crt (stat,
1710                                 cmd->session,
1711                                 host,
1712                                 proto,
1713                                 port,
1714                                 0,
1715                                 DANE_VFLAG_FAIL_IF_NOT_CHECKED,
1716                                 &vfystat) == DANE_E_SUCCESS) {
1717                 if ((pred == 'D') && (vfystat & DANE_VERIFY_UNKNOWN_DANE_INFO)) {
1718                         dane_state_deinit (stat);
1719                         goto setflagval;
1720                 }
1721                 flagval = ((vfystat & ~DANE_VERIFY_UNKNOWN_DANE_INFO) == 0);
1722         }
1723         dane_state_deinit (stat);
1724 setflagval:
1725         valexp_setpredicate (ve, pred, flagval);
1726 }
1727
1728 /* valexp_Rr_start -- validation function for the GnuTLS backend.
1729  * This function validates through a CRL.
1730  * While _R_ requires the CRL to be present, _r_ accepts confirmed absense.
1731  * TODO: This is not implemented yet.
1732  */
1733 static void valexp_Rr_start (void *vcmd, struct valexp *ve, char pred) {
1734         //TODO//;
1735         valexp_setpredicate (ve, pred, 0);
1736 }
1737
1738 /* valexp_Ee_start -- validation function for the GnuTLS backend.
1739  * This function validates certificate extensions for the named service.
1740  * While _E_ required OIDs to be marked critical, _e_ also accepts non-crit.
1741  */
1742 static void valexp_Ee_start (void *vcmd, struct valexp *ve, char pred) {
1743         //TODO//;
1744         valexp_setpredicate (ve, pred, 0);
1745 }
1746
1747 /* valexp_Oo_start -- validation function for the GnuTLS backend.
1748  * This function validates with online/live information.
1749  * While _O_ required positive confirmation, _o_ also accepts unknown.
1750  *  -> For X.509,    look in OCSP
1751  *  -> For OpenPGP,  redirect O->G, o->g
1752  *  -> For Kerberos, accept anything as sufficiently live / online
1753  */
1754 static void valexp_Oo_start (void *vcmd, struct valexp *ve, char pred) {
1755         struct command *cmd = (struct command *) vcmd;
1756         int valflag = 0;
1757         char *atnam = NULL;
1758         char *atoid = NULL;
1759         gnutls_credentials_type_t authtp;
1760         gnutls_certificate_type_t certtp;
1761         online2success_t o2vf;
1762         char *rid;
1763         const gnutls_datum_t *crt;
1764         unsigned int crtcount;
1765         authtp = gnutls_auth_get_type (cmd->session);
1766         if (authtp != GNUTLS_CRD_CERTIFICATE) {
1767                 // No authentication types other than certificates yet
1768                 goto setvalflag;
1769         } else {
1770                 if ((pred >= 'a') && (pred <= 'z')) {
1771                         o2vf = online2success_optional;
1772                 } else {
1773                         o2vf = online2success_enforced;
1774                 }
1775                 certtp = gnutls_certificate_type_get (cmd->session);
1776                 crt = gnutls_certificate_get_peers (cmd->session, &crtcount);
1777                 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1778                 if (certtp == GNUTLS_CRT_OPENPGP) {
1779                         valflag = o2vf (online_globaldir_pgp (
1780                                         rid, crt->data, crt->size));
1781                 } else if (certtp == GNUTLS_CRT_X509) {
1782                         //TODO// OCSP inquiry or globaldir
1783                         valflag = o2vf (online_globaldir_x509 (
1784                                         rid, crt->data, crt->size));
1785 #ifdef HAVE_TLS_KDH
1786                 } else if (certtp == GNUTLS_CRT_KRB) {
1787                         // Kerberos is sufficiently "live" to be pass O
1788                         valflag = 1;
1789                         goto setvalflag;
1790 #endif
1791                 } else {
1792                         // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1793                         goto setvalflag;
1794                 }
1795         }
1796 setvalflag:
1797         valexp_setpredicate (ve, pred, valflag);
1798 }
1799
1800 /* valexp_Gg_start -- validation function for the GnuTLS backend.
1801  * This function validates through the LDAP global directory.
1802  * While _G_ requires information to be present, _g_ also accepts absense.
1803  *  -> For X.509,   lookup userCertificate
1804  *  -> For OpenPGP, lookup pgpKey
1805  *  -> For KDH,     lookup krbPrincipalName
1806  *  -> For SRP,     nothing is defined
1807  *  -> For OpenSSH, no TLS support
1808  */
1809 static void valexp_Gg_start (void *vcmd, struct valexp *ve, char pred) {
1810         struct command *cmd = (struct command *) vcmd;
1811         int valflag = 0;
1812         char *atnam = NULL;
1813         char *atoid = NULL;
1814         gnutls_credentials_type_t authtp;
1815         gnutls_certificate_type_t certtp;
1816         online2success_t o2vf;
1817         char *rid;
1818         const gnutls_datum_t *crt;
1819         unsigned int crtcount;
1820         authtp = gnutls_auth_get_type (cmd->session);
1821         if (authtp != GNUTLS_CRD_CERTIFICATE) {
1822                 // No authentication types other than certificates yet
1823                 goto setvalflag;
1824         } else {
1825                 if ((pred >= 'a') && (pred <= 'z')) {
1826                         o2vf = online2success_optional;
1827                 } else {
1828                         o2vf = online2success_enforced;
1829                 }
1830                 certtp = gnutls_certificate_type_get (cmd->session);
1831                 crt = gnutls_certificate_get_peers (cmd->session, &crtcount);
1832                 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1833                 if (certtp == GNUTLS_CRT_OPENPGP) {
1834                         valflag = o2vf (online_globaldir_pgp (
1835                                         rid, crt->data, crt->size));
1836                 } else if (certtp == GNUTLS_CRT_X509) {
1837                         //TODO// OCSP inquiry or globaldir
1838                         valflag = o2vf (online_globaldir_x509 (
1839                                         rid, crt->data, crt->size));
1840 #ifdef HAVE_TLS_KDH
1841                 } else if (certtp == GNUTLS_CRT_KRB) {
1842                         valflag = 0;
1843                         //TODO// valflag = o2vf (online_globaldir_kerberos (
1844                         //TODO//                rid, crt->data, crt->size));
1845 #endif
1846                 } else {
1847                         // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1848                         goto setvalflag;
1849                 }
1850         }
1851 setvalflag:
1852         valexp_setpredicate (ve, pred, valflag);
1853 }
1854
1855 /* valexp_Pp_start -- validation function for the GnuTLS backend.
1856  * This function validates through pinning information.
1857  * While _P_ requires pinning to be present, _p_ will Trust On First Use.
1858  */
1859 static void valexp_Pp_start (void *vcmd, struct valexp *ve, char pred) {
1860         //TODO//;
1861         valexp_setpredicate (ve, pred, 0);
1862 }
1863
1864 /* valexp_U_start -- validation function for the GnuTLS backend.
1865  * This function validates a matching username.
1866  */
1867 static void valexp_U_start (void *vcmd, struct valexp *ve, char pred) {
1868         //TODO//;
1869         valexp_setpredicate (ve, pred, 0);
1870 }
1871
1872 /* valexp_Ss_start -- validation function for the GnuTLS backend.
1873  * This function ensures that the local end is a server.
1874  * While _S_ denies credentials also usable for clients, _s_ permits them.
1875  */
1876 static void valexp_Ss_start (void *vcmd, struct valexp *ve, char pred) {
1877         struct command *cmd = (struct command *) vcmd;
1878         int flagval;
1879         if ((pred == 'S') && (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
1880                 flagval = 0;
1881         } else {
1882                 flagval = (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) != 0;
1883         }
1884         valexp_setpredicate (ve, pred, flagval);
1885 }
1886
1887 /* valexp_Cc_start -- validation function for the GnuTLS backend.
1888  * This function ensures that the local end is a client.
1889  * While _C_ denies credentials also usable for servers, _c_ permits them.
1890  */
1891 static void valexp_Cc_start (void *vcmd, struct valexp *ve, char pred) {
1892         struct command *cmd = (struct command *) vcmd;
1893         int flagval;
1894         if ((pred == 'C') && (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)) {
1895                 flagval = 0;
1896         } else {
1897                 flagval = (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) != 0;
1898         }
1899         valexp_setpredicate (ve, pred, flagval);
1900 }
1901
1902
1903
1904 /* Fetch local credentials.  This can be done before TLS is started, to find
1905  * the possible authentication forms that can be offered.  The function
1906  * can additionally be used after interaction with the client to establish
1907  * a local identity that was not initially provided, or that was not
1908  * considered public at the time.
1909  */
1910 gtls_error fetch_local_credentials (struct command *cmd) {
1911         int lidrole;
1912         char *lid, *rid;
1913         DBC *crs_disclose = NULL;
1914         DBC *crs_localid = NULL;
1915         DBT discpatn;
1916         DBT keydata;
1917         DBT creddata;
1918         selector_t remote_selector;
1919         int gtls_errno = 0;
1920         int db_errno = 0;
1921         int found = 0;
1922         gtls_error certificate_onthefly (struct command *cmd);
1923
1924         //
1925         // When applicable, try to create an on-the-fly certificate
1926         if (((cmd->cmd.pio_cmd == PIOC_STARTTLS_V2) &&
1927                         (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_ONTHEFLY))
1928         || ((cmd->cmd.pio_cmd == PIOC_LIDENTRY_CALLBACK_V2) &&
1929                         (cmd->cmd.pio_data.pioc_lidentry.flags & PIOF_LIDENTRY_ONTHEFLY))) {
1930                 gtls_errno = certificate_onthefly (cmd);
1931                 if (gtls_errno != GNUTLS_E_AGAIN) {
1932                         // This includes GNUTLS_E_SUCCESS
1933 fprintf (stderr, "DEBUG: otfcert retrieval returned %d\n", gtls_errno);
1934                         return gtls_errno;
1935                 } else {
1936 fprintf (stderr, "DEBUG: otfcert retrieval returned GNUTLS_E_AGAIN, so skip it\n", gtls_errno);
1937                         gtls_errno = GNUTLS_E_SUCCESS;  // Attempt failed, ignore
1938                 }
1939         }
1940
1941         //
1942         // Setup a number of common references and structures
1943         // Note: Current GnuTLS cannot support being a peer
1944         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
1945                 lidrole = LID_ROLE_CLIENT;
1946         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
1947                 lidrole = LID_ROLE_SERVER;
1948         } else {
1949                 E_g2e ("TLS Pool command supports neither local client nor local server role",
1950                         GNUTLS_E_INVALID_SESSION);
1951                 return gtls_errno;
1952         }
1953         lid = cmd->cmd.pio_data.pioc_starttls.localid;
1954         rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1955
1956         //
1957         // Refuse to disclose client credentials when the server name is unset;
1958         // note that server-claimed identities are unproven during handshake.
1959         if ((lidrole == LID_ROLE_CLIENT) && (*rid == '\0')) {
1960                 tlog (TLOG_USER, LOG_ERR, "No remote identity (server name) set, so no client credential disclosure");
1961                 E_g2e ("Missing remote ID",
1962                         GNUTLS_E_NO_CERTIFICATE_FOUND);
1963                 return gtls_errno;
1964         }
1965         //
1966         // Setup database iterators to map identities to credentials
1967         if (lidrole == LID_ROLE_CLIENT) {
1968                 E_d2e ("Failed to create db_disclose cursor",
1969                         dbh_disclose->cursor (
1970                                 dbh_disclose,
1971                                 cmd->txn,
1972                                 &crs_disclose,
1973                                 0));
1974         }
1975         E_d2e ("Failed to create db_localid cursor",
1976                 dbh_localid->cursor (
1977                         dbh_localid,
1978                         cmd->txn,
1979                         &crs_localid,
1980                         0));
1981         //
1982         // Prepare for iteration over possible local identities / credentials
1983         char mid [128];
1984         char cid [128];
1985         if (gtls_errno != 0) {
1986                 ; // Skip setup
1987         } else if (lidrole == LID_ROLE_CLIENT) {
1988                 memcpy (cid, rid, sizeof (cid));
1989                 dbt_init_fixbuf (&discpatn, cid, strlen (cid));
1990                 dbt_init_fixbuf (&keydata,  mid, sizeof (mid)-1);
1991                 dbt_init_malloc (&creddata);
1992                 selector_t ridsel;
1993                 donai_t remote_donai = donai_from_stable_string (rid, strlen (rid));
1994                 if (!selector_iterate_init (&remote_selector, &remote_donai)) {
1995                         E_g2e ("Syntax of remote ID unsuitable for selector",
1996                                 GNUTLS_E_INVALID_REQUEST);
1997                 } else {
1998                         E_d2e ("Failed to start iterator on remote ID selector",
1999                                 dbcred_iterate_from_remoteid_selector (
2000                                         crs_disclose,
2001                                         crs_localid,
2002                                         &remote_selector,
2003                                         &discpatn,
2004                                         &keydata,
2005                                         &creddata));
2006                 }
2007         } else {
2008                 dbt_init_fixbuf (&discpatn, "", 0);     // Unused but good style
2009                 dbt_init_fixbuf (&keydata,  lid, strlen (lid));
2010                 dbt_init_malloc (&creddata);
2011                 E_d2e ("Failed to start iterator on local ID",
2012                         dbcred_iterate_from_localid (
2013                         crs_localid,
2014                         &keydata,
2015                         &creddata));
2016         }
2017         if (db_errno != 0) {
2018                 gtls_errno = GNUTLS_E_DB_ERROR;
2019         }
2020
2021         //
2022         // Now store the local identities inasfar as they are usable
2023         db_errno = 0;
2024         while ((gtls_errno == GNUTLS_E_SUCCESS) && (db_errno == 0)) {
2025                 int ok;
2026                 uint32_t flags;
2027                 int lidtype;
2028
2029                 tlog (TLOG_DB, LOG_DEBUG, "Found BDB entry %s disclosed to %s", creddata.data + 4, (lidrole == LID_ROLE_CLIENT)? rid: "all clients");
2030                 ok = dbcred_flags (
2031                         &creddata,
2032                         &flags);
2033                 lidtype = flags & LID_TYPE_MASK;
2034                 ok = ok && ((flags & lidrole) != 0);
2035                 ok = ok && ((flags & LID_NO_PKCS11) == 0);
2036                 ok = ok && (lidtype >= LID_TYPE_MIN);
2037                 ok = ok && (lidtype <= LID_TYPE_MAX);
2038 #ifdef HAVE_TLS_KDH
2039                 // For current/simple Kerberos, refuse data after PKCS #11 URI
2040                 ok = ok && ((lidtype != LID_TYPE_KRB5) || (NULL == memchr (creddata.data + 4, '\0', creddata.size - 4 - 1)));
2041 #endif
2042                 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 ");
2043                 if (ok) {
2044                         // Move the credential into the command structure
2045                         dbt_store (&creddata,
2046                                 &cmd->lids [lidtype - LID_TYPE_MIN]);
2047                         found = 1;
2048                 } else {
2049                         // Skip the credential by freeing its data structure
2050                         dbt_free (&creddata);
2051                 }
2052                 db_errno = dbcred_iterate_next (crs_disclose, crs_localid, &discpatn, &keydata, &creddata);
2053         }
2054
2055         if (db_errno == DB_NOTFOUND) {
2056                 if (!found) {
2057                         gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
2058                 }
2059         }
2060         if (crs_localid != NULL) {
2061                 crs_localid->close (crs_localid);
2062                 crs_localid = NULL;
2063         }
2064         if (crs_disclose != NULL) {
2065                 crs_disclose->close (crs_disclose);
2066                 crs_disclose = NULL;
2067         }
2068         return gtls_errno;
2069 }
2070
2071
2072 /*
2073  * Check if a given cmd has the given LID_TYPE setup.
2074  * Return 1 for yes or 0 for no; this is used in priority strings.
2075  */
2076 static inline int lidtpsup (struct command *cmd, int lidtp) {
2077         return 1;       //TODO// Can we decide if we needn't authenticate?
2078         return cmd->lids [lidtp - LID_TYPE_MIN].data != NULL;
2079 }
2080
2081 /* Configure the GnuTLS session with suitable credentials and priority string.
2082  * The anonpre_ok flag should be non-zero to permit Anonymous Precursor.
2083  *
2084  * The credential setup is optional; when creds is NULL, no changes will
2085  * be made.
2086  */
2087 static int configure_session (struct command *cmd,
2088                         gnutls_session_t session,
2089                         struct credinfo *creds,
2090                         int credcount,
2091                         int anonpre_ok) {
2092         int i;
2093         int gtls_errno = GNUTLS_E_SUCCESS;
2094         //
2095         // Install the shared credentials for the client or server role
2096         if (creds != NULL) {
2097                 gnutls_credentials_clear (session);
2098                 for (i=0; i<credcount; i++) {
2099                         E_g2e ("Failed to install credentials into TLS session",
2100                                 gnutls_credentials_set (
2101                                         session,
2102                                         creds [i].credtp,
2103                                         creds [i].cred  ));
2104                 }
2105         }
2106         //
2107         // Setup the priority string for this session; this avoids future
2108         // credential callbacks that ask for something impossible or
2109         // undesired.
2110         //
2111         // Variation factors:
2112         //  - starting configuration (can it be empty?)
2113         //  - Configured security parameters (database? variable?)
2114         //  - CTYPEs, SRP, ANON-or-not --> fill in as + or - characters
2115         if (gtls_errno == GNUTLS_E_SUCCESS) {
2116                 char priostr [256];
2117                 snprintf (priostr, sizeof (priostr)-1,
2118                         // "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
2119                         "NONE:"
2120 #ifdef HAVE_TLS_KDH
2121                         "%GNUTLS_ASYM_CERT_TYPES:"
2122 #endif
2123                         "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
2124                         "+COMP-NULL:"
2125                         "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
2126                         "%cANON-ECDH:"
2127                         "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
2128                         "%cCTYPE-X.509:"
2129                         "%cCTYPE-OPENPGP:"
2130 #ifdef HAVE_TLS_KDH
2131                         "%cCTYPE-CLI-KRB:%cCTYPE-SRV-X.509:",
2132 #endif
2133                         "%cSRP:%cSRP-RSA:%cSRP-DSS",
2134                         anonpre_ok                              ?'+':'-',
2135                         lidtpsup (cmd, LID_TYPE_X509)           ?'+':'-',
2136                         lidtpsup (cmd, LID_TYPE_PGP)            ?'+':'-',
2137 #ifdef HAVE_TLS_KDH
2138                         lidtpsup (cmd, LID_TYPE_KRB5)           ?'+':'-',
2139                         lidtpsup (cmd, LID_TYPE_KRB5)           ?'+':'-',
2140 #endif
2141                         //TODO// Temporarily patched out SRP
2142                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
2143                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
2144                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-');
2145 // strcpy (priostr, "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL");  //TODO:TEST//
2146 // strcpy (priostr, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL");  //TODO:TEST//
2147                 tlog (TLOG_TLS, LOG_DEBUG, "Constructed priority string %s for local ID %s",
2148                         priostr, cmd->cmd.pio_data.pioc_starttls.localid);
2149                 E_g2e ("Failed to set GnuTLS priority string",
2150                         gnutls_priority_set_direct (
2151                         session,
2152                         priostr,
2153                         NULL));
2154         }
2155         //
2156         // Return the application GNUTLS_E_ code including _SUCCESS
2157         return gtls_errno;
2158 }
2159
2160 /* The callback functions retrieve various bits of information for the client
2161  * or server in the course of the handshake procedure.
2162  *
2163  * The logic here is based on client-sent information, such as:
2164  *  - TLS hints -- X.509 or alternatives like OpenPGP, SRP, PSK
2165  *  - TLS hints -- Server Name Indication
2166  *  - User hints -- local and remote identities provided
2167  */
2168 int srv_clienthello (gnutls_session_t session) {
2169         struct command *cmd;
2170         char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)]; // static
2171         size_t snilen = sizeof (sni);
2172         int snitype;
2173         int gtls_errno = GNUTLS_E_SUCCESS;
2174         char *lid;
2175
2176 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2177 errno = 0;
2178 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2179         //
2180         // Setup a number of common references
2181         cmd = (struct command *) gnutls_session_get_ptr (session);
2182         if (cmd == NULL) {
2183                 return GNUTLS_E_INVALID_SESSION;
2184         }
2185         lid = cmd->cmd.pio_data.pioc_starttls.localid;
2186
2187         //
2188         // Setup server-specific credentials and priority string
2189         //TODO// get anonpre value here
2190 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2191 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2192         E_g2e ("Failed to reconfigure GnuTLS as a server",
2193                 configure_session (cmd,
2194                         session,
2195                         srv_creds, srv_credcount, 
2196                         cmd->anonpre & ANONPRE_SERVER));
2197 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2198
2199         //
2200         // Setup to ignore/request/require remote identity (from client)
2201 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2202         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
2203                 // Neither Request nor Require remoteid; ignore it
2204                 ;
2205         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REQUEST_REMOTEID) {
2206                 // Use Request instead of Require for remoteid
2207                 ( //RETURNS_VOID// E_g2e ("Failed to request remote identity",
2208                         gnutls_certificate_server_set_request (
2209                                 session,
2210                                 GNUTLS_CERT_REQUEST));
2211 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2212         } else {
2213                 // Require a remoteid from the client (default)
2214                 ( //RETURNS_VOID// E_g2e ("Failed to require remote identity (the default)",
2215                         gnutls_certificate_server_set_request (
2216                                 session,
2217                                 GNUTLS_CERT_REQUIRE));
2218 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2219         }
2220
2221         //
2222         // Find the client-helloed ServerNameIndication, or the service name
2223 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2224         sni [0] = '\0';
2225         if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) == 0) {
2226 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2227                 switch (snitype) {
2228                 case GNUTLS_NAME_DNS:
2229                         break;
2230                 // Note: In theory, other name types could be sent, and it would
2231                 // be useful to access indexes beyond 0.  In practice, nobody
2232                 // uses other name types than exactly one GNUTLS_NAME_DNS.
2233                 default:
2234                         sni [0] = '\0';
2235                         tlog (TLOG_TLS, LOG_ERR, "Received an unexpected SNI type; that is possible but uncommon; skipping SNI");
2236 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2237                         break;
2238                 }
2239         }
2240 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2241         if (sni [0] != '\0') {
2242                 if (*lid != '\0') {
2243                         int atidx;
2244                         for (atidx=128; atidx > 0; atidx--) {
2245                                 if (lid [atidx-1] == '@') {
2246                                         break;
2247                                 }
2248                         }
2249                         if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
2250                                 tlog (TLOG_USER | TLOG_TLS, LOG_ERR, "Mismatch between client-sent SNI %s and local identity %s", sni, lid);
2251 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2252                                 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
2253                         }
2254                 } else {
2255                         memcpy (lid, sni, sizeof (sni));
2256 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2257                 }
2258         } else {
2259                 memcpy (sni, lid, sizeof (sni)-1);
2260 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2261                 sni [sizeof (sni) - 1] = '\0';
2262         }
2263 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2264
2265         //
2266         // Lap up any unnoticed POSIX error messages
2267         if (errno != 0) {
2268                 cmd->session_errno = errno;
2269 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2270                 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
2271 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2272         }
2273
2274         //
2275         // Round off with an overal judgement
2276 fprintf (stderr, "DEBUG: Returning gtls_errno = %d or \"%s\" from srv_clihello()\n", gtls_errno, gnutls_strerror (gtls_errno));
2277         return gtls_errno;
2278 }
2279
2280
2281 int cli_srpcreds_retrieve (gnutls_session_t session,
2282                                 char **username,
2283                                 char **password) {
2284         //TODO:FIXED//
2285         tlog (TLOG_CRYPTO, LOG_DEBUG, "Picking up SRP credentials");
2286         *username = strdup ("tester");
2287         *password = strdup ("test");
2288         return GNUTLS_E_SUCCESS;
2289 }
2290
2291
2292 /* Setup credentials to be shared by all clients and servers.
2293  * Credentials are generally implemented through callback functions.
2294  * This should be called after setting up DH parameters.
2295  */
2296 int setup_starttls_credentials (void) {
2297         gnutls_anon_server_credentials_t srv_anoncred = NULL;
2298         gnutls_anon_client_credentials_t cli_anoncred = NULL;
2299         gnutls_certificate_credentials_t clisrv_certcred = NULL;
2300         //TODO:NOTHERE// int srpbits;
2301         gnutls_srp_server_credentials_t srv_srpcred = NULL;
2302         gnutls_srp_client_credentials_t cli_srpcred = NULL;
2303         //TODO// gnutls_kdh_server_credentials_t srv_kdhcred = NULL;
2304         //TODO// gnutls_kdh_server_credentials_t cli_kdhcred = NULL;
2305         int gtls_errno = GNUTLS_E_SUCCESS;
2306         int gtls_errno_stack0 = GNUTLS_E_SUCCESS;
2307         int krb5_errno = 0;
2308
2309         //
2310         // Construct anonymous server credentials
2311         E_g2e ("Failed to allocate ANON-DH server credentials",
2312                 gnutls_anon_allocate_server_credentials (
2313                         &srv_anoncred));
2314         if (!have_error_codes ()) /* E_g2e (...) */ gnutls_anon_set_server_dh_params (
2315                 srv_anoncred,
2316                 dh_params);
2317         if (gtls_errno == GNUTLS_E_SUCCESS) {
2318                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server anonymous credentials");
2319                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_ANON;
2320                 srv_creds [srv_credcount].cred   = (void *) srv_anoncred;
2321                 srv_credcount++;
2322         } else if (srv_anoncred != NULL) {
2323                 gnutls_anon_free_server_credentials (srv_anoncred);
2324                 srv_anoncred = NULL;
2325         }
2326
2327         //
2328         // Construct anonymous client credentials
2329         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2330         E_g2e ("Failed to allocate ANON-DH client credentials",
2331                 gnutls_anon_allocate_client_credentials (
2332                         &cli_anoncred));
2333 #ifdef MIRROR_IMAGE_OF_SERVER_ANONYMOUS_CREDENTIALS
2334         // NOTE: This is not done under TLS; server always provides DH params
2335         if (!have_error_codes ()) gnutls_anon_set_client_dh_params (
2336                 cli_anoncred,
2337                 dh_params);
2338 #endif
2339         if (gtls_errno == GNUTLS_E_SUCCESS) {
2340                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client anonymous credentials");
2341                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_ANON;
2342                 cli_creds [cli_credcount].cred   = (void *) cli_anoncred;
2343                 cli_credcount++;
2344         } else if (cli_anoncred != NULL) {
2345                 gnutls_anon_free_client_credentials (cli_anoncred);
2346                 cli_anoncred = NULL;
2347         }
2348
2349         //
2350         // Construct certificate credentials for X.509 and OpenPGP cli/srv
2351         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2352         E_g2e ("Failed to allocate certificate credentials",
2353                 gnutls_certificate_allocate_credentials (
2354                         &clisrv_certcred));
2355         //TODO// What to do here when we add locking on DH params?
2356         gnutls_certificate_set_dh_params (
2357                 clisrv_certcred,
2358                 dh_params);
2359         gtls_errno_stack0 = gtls_errno;
2360         /* TODO: Bad code.  GnuTLS 3.2.1 ignores retrieve_function2 when
2361          * checking if it can handle the OpenPGP certificate type in
2362          * _gnutls_session_cert_type_supported (gnutls_status.c:175) but
2363          * it does see the "1" version field.  It does not callback the
2364          * "1" version if "2" is present though.
2365          */
2366         if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function (
2367                 clisrv_certcred,
2368                 (void *) exit);
2369         if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function2 (
2370                 clisrv_certcred,
2371                 clisrv_cert_retrieve);
2372         if (gtls_errno == GNUTLS_E_SUCCESS) {
2373                 // Setup for certificates
2374                 tlog (TLOG_CERT, LOG_INFO, "Setting client and server certificate credentials");
2375                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
2376                 cli_creds [cli_credcount].cred   = (void *) clisrv_certcred;
2377                 cli_credcount++;
2378                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
2379                 srv_creds [srv_credcount].cred   = (void *) clisrv_certcred;
2380                 srv_credcount++;
2381         } else if (clisrv_certcred != NULL) {
2382                 gnutls_certificate_free_credentials (clisrv_certcred);
2383                 clisrv_certcred = NULL;
2384         }
2385
2386         //
2387         // Construct server credentials for SRP authentication
2388         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2389         E_g2e ("Failed to allocate SRP server credentials",
2390                 gnutls_srp_allocate_server_credentials (
2391                         &srv_srpcred));
2392         E_g2e ("Failed to set SRP server credentials",
2393                 gnutls_srp_set_server_credentials_file (
2394                         srv_srpcred,
2395                         "../testdata/tlspool-test-srp.passwd",
2396                         "../testdata/tlspool-test-srp.conf"));
2397         if (gtls_errno == GNUTLS_E_SUCCESS) {
2398                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server SRP credentials");
2399                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_SRP;
2400                 srv_creds [srv_credcount].cred   = (void *) srv_srpcred;
2401                 srv_credcount++;
2402         } else if (srv_srpcred != NULL) {
2403                 gnutls_srp_free_server_credentials (srv_srpcred);
2404                 srv_srpcred = NULL;
2405         }
2406
2407         //
2408         // Construct client credentials for SRP authentication
2409         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2410         E_g2e ("Failed to allocate SRP client credentials",
2411                 gnutls_srp_allocate_client_credentials (
2412                         &cli_srpcred));
2413         if (!have_error_codes ()) gnutls_srp_set_client_credentials_function (
2414                 cli_srpcred,
2415                 cli_srpcreds_retrieve);
2416         if (gtls_errno == GNUTLS_E_SUCCESS) {
2417                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client SRP credentials");
2418                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_SRP;
2419                 cli_creds [cli_credcount].cred   = (void *) cli_srpcred;
2420                 cli_credcount++;
2421         } else if (cli_srpcred != NULL) {
2422                 gnutls_srp_free_client_credentials (cli_srpcred);
2423                 cli_srpcred = NULL;
2424         }
2425
2426         //
2427         // Construct credentials caching for Kerberos
2428         kerberos_context = NULL;
2429         //TODO:ALLOW_GLOBAL_CCACHE_LOOKUPS// kerberos_credcache = NULL;
2430         if (krb5_errno == 0) {
2431                 krb5_errno = krb5_init_context (&kerberos_context);
2432         }
2433
2434         //
2435         // Construct server credentials for KDH authentication
2436         //TODO// gtls_errno = gtls_errno_stack0;        // Don't pop, just forget last failures
2437         //TODO// E_g2e ("Failed to allocate KDH server credentials",
2438         //TODO//        gnutls_kdh_allocate_server_credentials (
2439         //TODO//                &srv_kdhcred));
2440         //TODO// E_g2e ("Failed to set KDH server DH params",
2441         //TODO//        gnutls_kdh_set_server_dh_params (
2442         //TODO//                srv_kdhcred,
2443         //TODO//                dh_params));
2444         //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
2445         //TODO//        tlog (TLOG_CRYPTO, LOG_INFO, "Setting server KDH credentials");
2446         //TODO//        srv_creds [srv_credcount].credtp = GNUTLS_CRD_KDH;
2447         //TODO//        srv_creds [srv_credcount].cred   = (void *) srv_kdhcred;
2448         //TODO//        srv_credcount++;
2449         //TODO// } else if (srv_kdhcred != NULL) {
2450         //TODO//        gnutls_kdh_free_server_credentials (srv_kdhcred);
2451         //TODO//        srv_kdhcred = NULL;
2452         //TODO// }
2453
2454         //
2455         // Construct client credentials for KDH
2456         //TODO// gtls_errno = gtls_errno_stack0;        // Don't pop, just forget last failures
2457         //TODO// E_g2e ("Failed to allocate KDH client credentials",
2458         //TODO//        gnutls_kdh_allocate_client_credentials (
2459         //TODO//                &cli_kdhcred));
2460         //TODO// E_g2e ("Failed to set KDH client credentials",
2461         //TODO//        gnutls_kdh_set_client_credentials_function (
2462         //TODO//                cli_kdhcred,
2463         //TODO//                cli_kdh_retrieve));
2464         //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
2465         //TODO//        tlog (TLOG_CRYPTO, LOG_INFO, "Setting client KDH credentials");
2466         //TODO//        cli_creds [cli_credcount].credtp = GNUTLS_CRD_KDH;
2467         //TODO//        cli_creds [cli_credcount].cred   = (void *) cli_kdhcred;
2468         //TODO//        cli_credcount++;
2469         //TODO// } else if (cli_kdhcred != NULL) {
2470         //TODO//        gnutls_kdh_free_client_credentials (cli_kdhcred);
2471         //TODO//        cli_kdhcred = NULL;
2472         //TODO// }
2473
2474         //
2475         // Ensure that at least one credential has been set
2476         // TODO: Look at the counters; but at boot, we can require all okay
2477         if ((gtls_errno == GNUTLS_E_SUCCESS) &&
2478                         ( (cli_credcount != EXPECTED_CLI_CREDCOUNT) ||
2479                           (srv_credcount != EXPECTED_SRV_CREDCOUNT) ) ) {
2480                 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);
2481                 E_g2e ("Not all credentials could be setup",
2482                         GNUTLS_E_INSUFFICIENT_CREDENTIALS);
2483         }
2484
2485         //
2486         // Report overall error or success
2487         return gtls_errno;
2488 }
2489
2490
2491 /* Cleanup all credentials created, just before exiting the daemon.
2492  */
2493 void cleanup_starttls_credentials (void) {
2494         while (srv_credcount-- > 0) {
2495                 struct credinfo *crd = &srv_creds [srv_credcount];
2496                 switch (crd->credtp) {
2497                 case GNUTLS_CRD_CERTIFICATE:
2498                         // Shared with client; skipped in server and removed in client
2499                         // gnutls_certificate_free_credentials (crd->cred);
2500                         break;
2501                 case GNUTLS_CRD_ANON:
2502                         gnutls_anon_free_server_credentials (crd->cred);
2503                         break;
2504                 case GNUTLS_CRD_SRP:
2505                         gnutls_srp_free_server_credentials (crd->cred);
2506                         break;
2507                 //TODO// case GNUTLS_CRD_KDH:
2508                 //TODO//        gnutls_kdh_free_server_credentials (crd->cred);
2509                 //TODO//        break;
2510                 }
2511         }
2512         while (cli_credcount-- > 0) {
2513                 struct credinfo *crd = &cli_creds [cli_credcount];
2514                 switch (crd->credtp) {
2515                 case GNUTLS_CRD_CERTIFICATE:
2516                         // Shared with client; skipped in server and removed in client
2517                         gnutls_certificate_free_credentials (crd->cred);
2518                         break;
2519                 case GNUTLS_CRD_ANON:
2520                         gnutls_anon_free_client_credentials (crd->cred);
2521                         break;
2522                 case GNUTLS_CRD_SRP:
2523                         gnutls_srp_free_client_credentials (crd->cred);
2524                         break;
2525                 //TODO// case GNUTLS_CRD_KDH:
2526                 //TODO//        gnutls_kdh_free_client_credentials (crd->cred);
2527                 //TODO//        break;
2528                 }
2529         }
2530 }
2531
2532
2533 /*
2534  * The starttls_thread is a main program for the setup of a TLS connection,
2535  * either in client mode or server mode.  Note that the distinction between
2536  * client and server mode is only a TLS concern, but not of interest to the
2537  * application or the records exchanged.
2538  *
2539  * If the STARTTLS operation succeeds, this will be reported back to the
2540  * application, but the TLS pool will continue to be active in a copycat
2541  * procedure: encrypting outgoing traffic and decrypting incoming traffic.
2542  *
2543  * A new handshake may be initiated with a STARTTLS command with the special
2544  * flag PIOF_STARTTLS_RENEGOTIATE and the ctlkey set to a previously setup
2545  * TLS connection.  This command runs in a new thread, that cancels the old
2546  * one (which it can only do while it is waiting in copycat) and then join
2547  * that thread (and its data) with the current one.  This is based on the
2548  * ctlkey, which serves to lookup the old thread's data.  When the
2549  * connection ends for other reasons than a permitted cancel by another
2550  * thread, will the thread cleanup its own resources.  In these situations,
2551  * the new command determines the negotiation parameters, and returns identity
2552  * information.
2553  *
2554  * In addition, the remote side may initiate renegotiation.  This is accepted
2555  * without further ado (although future versions of the TLS Pool may add a
2556  * callback mechanism to get it approved).  The renegotiation now runs under
2557  * the originally supplied negotiation parameters.  In case it needs a new
2558  * local identity, it may also perform callbacks.  Possibly repeating what
2559  * happened before -- but most often, a server will start processing a
2560  * protocol and determine that it requires more for the requested level of
2561  * service, and then renegotiate.  This is common, for example, with HTTPS
2562  * connections that decide they need a client certificate for certain URLs.
2563  * The implementation of this facility is currently as unstructured as the
2564  * facility itself, namely through a goto.  We may come to the conclusion
2565  * that a loop is in fact a warranted alternative, but we're not yet
2566  * convinced that this would match with other "structures" in TLS.
2567  *
2568  * In conclusion, there are three possible ways of running this code:
2569  *  1. For a new connection.  Many variables are not known and build up
2570  *     in the course of running the function.
2571  *  2. After a command requesting renegotiation.  This overtakes the prior
2572  *     connection's thread, and copies its data from the ctlkeynode_tls.
2573  *     The resulting code has a number of variables filled in already at
2574  *     an earlier stage.
2575  *  3. After a remote request for renegotiation.  This loops back to an
2576  *     earlier phase, but after the thread takeover and ctlkeynode_tls copy
2577  *     of the explicit command for renegotation.  Its behaviour is subtly
2578  *     different in that it has no command to act on, and so it cannot
2579  *     send responses or error codes.  It will however log and shutdown
2580  *     as the command-driven options would.  It will not perform callbacks
2581  *     for PIOC_STARTTLS_LOCALID_V2 or PIOC_PLAINTEXT_CONNECT_V2.  It will
2582  *     however trigger the PIOC_LIDENTRY_CALLBACK_V2 through the separate
2583  *     callback command, if one is registered.
2584  * Yeah, it's great fun, coding TLS and keeping it both flexible and secure.
2585  */
2586 static void *starttls_thread (void *cmd_void) {
2587         struct command *cmd, *replycmd;
2588         struct command cmd_copy; // for relooping during renegotiation
2589         struct pioc_starttls orig_starttls;
2590         uint32_t orig_cmdcode;
2591         int plainfd = -1;
2592         int cryptfd = -1;
2593         gnutls_session_t session;
2594         int got_session = 0;
2595         int gtls_errno = GNUTLS_E_SUCCESS;
2596         int i;
2597         struct ctlkeynode_tls *ckn = NULL;
2598         uint32_t tout;
2599         int forked = 0;
2600         int want_remoteid = 1;
2601         int got_remoteid = 0;
2602         int renegotiating = 0;
2603         char *preauth = NULL;
2604         unsigned int preauthlen = 0;
2605         int taking_over = 0;
2606         int my_maxpreauth = 0;
2607         int anonpost = 0;
2608
2609         //
2610         // Block thread cancellation -- and re-enable it in copycat()
2611         assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
2612
2613         //
2614         // General thread setup
2615         replycmd = cmd = (struct command *) cmd_void;
2616         if (cmd == NULL) {
2617                 send_error (replycmd, EINVAL, "Command structure not received");
2618                 assert (pthread_detach (pthread_self ()) == 0);
2619                 return NULL;
2620         }
2621         *cmd->valflags = '\0';
2622         cmd->session_errno = 0;
2623         cmd->anonpre = 0;
2624         orig_cmdcode = cmd->cmd.pio_cmd;
2625         memcpy (&orig_starttls, &cmd->cmd.pio_data.pioc_starttls, sizeof (orig_starttls));
2626         cmd->orig_starttls = &orig_starttls;
2627         cryptfd = cmd->passfd;
2628         cmd->passfd = -1;
2629 //TODO:TEST Removed here because it is tested below
2630 /*
2631         if (cryptfd < 0) {
2632                 tlog (TLOG_UNIXSOCK, LOG_ERR, "No ciphertext file descriptor supplied to TLS Pool");
2633                 send_error (replycmd, EINVAL, "No ciphertext file descriptor supplied to TLS Pool");
2634                 assert (pthread_detach (pthread_self ()) == 0);
2635                 return NULL;
2636         }
2637 */
2638         cmd->session_certificate = (intptr_t) (void *) NULL;
2639         cmd->session_privatekey  = (intptr_t) (void *) NULL;
2640
2641         //
2642         // In case of renegotiation, lookup the previous ctlkeynode by its
2643         // ctlkey.  The fact that we have ckn != NULL indicates that we are
2644         // renegotiating in the code below; it will supply information as
2645         // we continue to run the TLS process.
2646         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_RENEGOTIATE) {
2647 fprintf (stderr, "DEBUG: Got a request to renegotiate existing TLS connection\n");
2648                 //
2649                 // Check that no FD was passed (and ended up in cryptfd)
2650                 if (cryptfd >= 0) {
2651                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Renegotiation started with extraneous file descriptor");
2652                         send_error (replycmd, EPROTO, "File handle supplied for renegotiation");
2653                         close (cryptfd);
2654                         assert (pthread_detach (pthread_self ()) == 0);
2655                         return NULL;
2656                 }
2657                 //
2658                 // First find the ctlkeynode_tls
2659                 ckn = (struct ctlkeynode_tls *) ctlkey_find (cmd->cmd.pio_data.pioc_starttls.ctlkey, security_tls, cmd->clientfd);
2660 fprintf (stderr, "DEBUG: Got ckn == 0x%0x\n", (intptr_t) ckn);
2661                 if (ckn == NULL) {
2662                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to find TLS connection for renegotiation by its ctlkey");
2663                         send_error (replycmd, ESRCH, "Cannot find TLS connection for renegotiation");
2664                         assert (pthread_detach (pthread_self ()) == 0);
2665                         return NULL;
2666                 }
2667                 //
2668                 // Now cancel the pthread for this process
2669                 errno = pthread_cancel (ckn->owner);
2670 fprintf (stderr, "DEBUG: pthread_cancel returned %d\n", errno);
2671                 if (errno == 0) {
2672                         void *retval;
2673                         errno = pthread_join (ckn->owner, &retval);
2674 fprintf (stderr, "DEBUG: pthread_join returned %d\n", errno);
2675                 }
2676                 if (errno != 0) {
2677                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to interrupt TLS connection for renegotiation");
2678                         send_error (replycmd, errno, "Cannot interrupt TLS connection for renegotiation");
2679                         ctlkey_unfind (&ckn->regent);
2680                         assert (pthread_detach (pthread_self ()) == 0);
2681                         // Do not free the ckn, as the other thread still runs
2682                         return NULL;
2683                 }
2684                 //
2685                 // We are in control!  Assimilate the TLS connection data.
2686                 renegotiating = 1;
2687                 plainfd = ckn->plainfd;
2688                 cryptfd = ckn->cryptfd;
2689                 session = ckn->session;
2690                 got_session = 1;
2691                 taking_over = 1;
2692                 ctlkey_unfind (&ckn->regent);
2693         }
2694
2695         // Then follows the unstructured entry point for the unstructured
2696         // request to a TLS connection to renegotiate its security parameters.
2697         // Doing this in any other way than with goto would add a lot of
2698         // make-belief structure that only existed to make this looping
2699         // possible.  We'd rather be honest and admit the lack of structure
2700         // that TLS has in this respect.  Maybe we'll capture it one giant loop
2701         // at some point, but for now that does not seem to add any relief.
2702         renegotiate:
2703 printf ("DEBUG: Renegotiating = %d, anonpost = %d, plainfd = %d, cryptfd = %d, flags = 0x%x, session = 0x%x, got_session = %d, lid = \"%s\", rid = \"%s\"\n", renegotiating, anonpost, plainfd, cryptfd, cmd->cmd.pio_data.pioc_starttls.flags, session, got_session, cmd->cmd.pio_data.pioc_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid);
2704
2705         //
2706         // If this is server renegotiating, send a request to that end
2707         //TODO// Only invoke gnutls_rehandshake() on the server
2708         if (renegotiating && (taking_over || anonpost) && (gtls_errno == GNUTLS_E_SUCCESS)) {
2709 printf ("DEBUG: Invoking gnutls_rehandshake in renegotiation loop\n");
2710                 gtls_errno = gnutls_rehandshake (session);
2711                 if (gtls_errno == GNUTLS_E_INVALID_REQUEST) {
2712                         // Clients should not do this; be forgiving
2713                         gtls_errno = GNUTLS_E_SUCCESS;
2714 printf ("DEBUG: Client-side invocation flagged as wrong; compensated error\n");
2715                 }
2716         }
2717
2718         //
2719         // When renegotiating TLS security, ensure that it is done securely
2720         if (renegotiating && (gnutls_safe_renegotiation_status (session) == 0)) {
2721                 send_error (replycmd, EPROTO, "Renegotiation requested while secure renegotiation is unavailable on remote");
2722                 if (cryptfd >= 0) {
2723                         close (cryptfd);
2724                         cryptfd = -1;
2725                 }
2726                 if (plainfd >= 0) {
2727                         close (plainfd);
2728                         plainfd = -1;
2729                 }
2730                 if (ckn != NULL) {
2731                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
2732                                 free (ckn);
2733                                 ckn = NULL;
2734                         }
2735                 }
2736                 assert (pthread_detach (pthread_self ()) == 0);
2737                 return NULL;
2738         }
2739
2740         //
2741         // Potentially decouple the controlling fd (ctlkey is in orig_starttls)
2742         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_FORK) {
2743                 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_FORK;
2744                 forked = 1;
2745         }
2746
2747         //
2748         // Setup BDB transactions and reset credential datum fields
2749         if (!anonpost) {
2750                 bzero (&cmd->lids, sizeof (cmd->lids));
2751                 manage_txn_begin (&cmd->txn);
2752         }
2753
2754         //
2755         // Permit cancellation of this thread -- TODO: Cleanup?
2756 //TODO:TEST// Defer setcancelstate untill copycat() activity
2757 /*
2758         errno = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
2759         if (errno != 0) {
2760                 send_error (replycmd, ESRCH, "STARTTLS handler thread cancellability refused");
2761                 if (cryptfd >= 0) {
2762                         close (cryptfd);
2763                         cryptfd = -1;
2764                 }
2765                 if (plainfd >= 0) {
2766                         close (plainfd);
2767                         plainfd = -1;
2768                 }
2769                 if (ckn != NULL) {
2770                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
2771                                 free (ckn);
2772                                 ckn = NULL;
2773                         }
2774                 }
2775                 manage_txn_rollback (&cmd->txn);
2776                 assert (pthread_detach (pthread_self ()) == 0);
2777                 return NULL;
2778         }
2779 */
2780         //
2781         // Check and setup the plaintext file handle
2782         if (cryptfd < 0) {
2783                 send_error (replycmd, EPROTO, "You must supply a TLS-protected socket");
2784                 if (plainfd >= 0) {
2785                         close (plainfd);
2786                         plainfd = -1;
2787                 }
2788 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2789                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
2790                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
2791                                 free (ckn);
2792                                 ckn = NULL;
2793                         }
2794                 }
2795                 manage_txn_rollback (&cmd->txn);
2796                 assert (pthread_detach (pthread_self ()) == 0);
2797                 return NULL;
2798         }
2799
2800         //
2801         // Decide on support for the Anonymous Precursor, based on the
2802         // service name and its appearance in the anonpre_registry.
2803         // If the remoteid is not interesting to the client then also
2804         // support an Anonymous Precursor; we have nothing to loose.
2805         cmd->anonpre &= ~ANONPRE_EITHER;
2806         if (renegotiating) {
2807                 ; // Indeed, during renegotiation we always disable ANON-DH
2808         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
2809                 cmd->anonpre = ANONPRE_EITHER;
2810                 want_remoteid = 0;
2811         } else {
2812                 int anonpre_regidx =  anonpre_registry_size      >> 1;
2813                 int anonpre_regjmp = (anonpre_registry_size + 1) >> 1;
2814                 int cmp;
2815                 while (anonpre_regjmp > 0) {
2816                         anonpre_regjmp = anonpre_regjmp >> 1;
2817                         cmp = strncasecmp (anonpre_registry [anonpre_regidx].service,
2818                                 cmd->cmd.pio_data.pioc_starttls.service,
2819                                 TLSPOOL_SERVICELEN);
2820 printf ("DEBUG: anonpre_determination, comparing [%d] %s to %s, found cmp==%d\n", anonpre_regidx, anonpre_registry [anonpre_regidx].service, cmd->cmd.pio_data.pioc_starttls.service, cmp);
2821                         if (cmp == 0) {
2822                                 // anonpre_regent matches
2823                                 cmd->anonpre = anonpre_registry [anonpre_regidx].flags;
2824                                 break;
2825                         } else if (cmp > 0) {
2826                                 // anonpre_regent too high
2827                                 anonpre_regidx -= 1 + anonpre_regjmp;
2828                                 if (anonpre_regidx < 0) {
2829                                         anonpre_regidx = 0;
2830                                 }
2831                         } else {
2832                                 // anonpre_regent too low
2833                                 anonpre_regidx += 1 + anonpre_regjmp;
2834                                 if (anonpre_regidx >= anonpre_registry_size) {
2835                                         anonpre_regidx = anonpre_registry_size - 1;
2836                                 }
2837                         }
2838                 }
2839         }
2840
2841         //
2842         // Setup flags for client and/or server roles (make sure there is one)
2843         if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_CLIENT) == 0)) {
2844                 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_SERVER;
2845         }
2846         if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_SERVER) == 0)) {
2847                 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_CLIENT;
2848         }
2849         if ((cmd->cmd.pio_data.pioc_starttls.flags & (PIOF_STARTTLS_LOCALROLE_CLIENT | PIOF_STARTTLS_LOCALROLE_SERVER)) == 0) {
2850                 //
2851                 // Neither a TLS client nor a TLS server
2852                 //
2853                 send_error (replycmd, ENOTSUP, "Command not supported");
2854                 close (cryptfd);
2855                 if (plainfd >= 0) {
2856                         close (plainfd);
2857                         plainfd = -1;
2858                 }
2859 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2860                 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
2861                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
2862                                 free (ckn);
2863                                 ckn = NULL;
2864                         }
2865                 }
2866                 manage_txn_rollback (&cmd->txn);
2867                 assert (pthread_detach (pthread_self ()) == 0);
2868                 return NULL;
2869         }
2870
2871         //
2872         // Setup the TLS session.  Also see doc/p2p-tls.*
2873         //
2874         // TODO: GnuTLS cannot yet setup p2p connections
2875         if (ckn != NULL) {
2876                 gnutls_session_set_ptr (
2877                         session,
2878                         cmd);
2879                 //TODO:DONE?// Clear various settings... creds, flags, modes? CLI/SRV?
2880         } else {
2881                 E_g2e ("Failed to initialise GnuTLS peer session",
2882                         gnutls_init (
2883                                 &session,
2884                                 (((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)? GNUTLS_CLIENT: 0) |
2885                                  ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)? GNUTLS_SERVER: 0))
2886                                 ));
2887                 if (gtls_errno == GNUTLS_E_SUCCESS) {
2888                         got_session = 1;
2889                         gnutls_session_set_ptr (
2890                                 session,
2891                                 cmd);
2892                 }
2893         }
2894         cmd->session = session;
2895         //
2896         // Setup client-specific behaviour if needed
2897         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
2898 if (!renegotiating) {   //TODO:TEST//
2899                 //
2900                 // Setup as a TLS client
2901                 //
2902                 int srpbits;
2903                 //
2904                 // Require a minimum security level for SRP
2905                 srpbits = 3072;
2906                 //TODO:CRASH// if (gtls_errno == GNUTLS_E_SUCCESS) gnutls_srp_set_prime_bits (
2907                         //TODO:CRASH// session,
2908                         //TODO:CRASH// srpbits);
2909                 //
2910                 // Setup as a TLS client
2911                 //
2912                 // Setup for potential sending of SNI
2913                 if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_WITHOUT_SNI) == 0) {
2914                         char *str = cmd->cmd.pio_data.pioc_starttls.remoteid;
2915                         int ofs = 0;
2916                         int len = 0;
2917                         while (str [len] && (len < 128)) {
2918                                 if (str [len] == '@') {
2919                                         ofs = len + 1;
2920                                 }
2921                                 len++;
2922                         }
2923                         // If no usable remoteid was setup, ignore it
2924                         if ((len + ofs > 0) && (len < 128)) {
2925                                 cmd->cmd.pio_data.pioc_starttls.remoteid [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)-1] = '\0';
2926                                 E_g2e ("Client failed to setup SNI",
2927                                         gnutls_server_name_set (
2928                                                 session,
2929                                                 GNUTLS_NAME_DNS,
2930                                                 str + ofs,
2931                                                 len - ofs));
2932                         }
2933                 }
2934 } //TODO:TEST//
2935                 //
2936                 // Setup for client credential installation in this session
2937                 //
2938                 // Setup client-specific credentials and priority string
2939 printf ("DEBUG: Configuring client credentials\n");
2940                 E_g2e ("Failed to configure GnuTLS as a client",
2941                         configure_session (cmd,
2942                                 session,
2943                                 anonpost? NULL: cli_creds,
2944                                 anonpost?    0: cli_credcount, 
2945                                 cmd->anonpre & ANONPRE_CLIENT));
2946         }
2947         //
2948         // Setup callback to server-specific behaviour if needed
2949         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
2950 printf ("DEBUG: Configuring for server credentials callback if %d==0\n", gtls_errno);
2951 if (!renegotiating) {   //TODO:TEST//
2952                 if (gtls_errno == GNUTLS_E_SUCCESS) {
2953                         gnutls_handshake_set_post_client_hello_function (
2954                                 session,
2955                                 srv_clienthello);
2956                 }
2957 } //TODO:TEST//
2958                 //TODO:TEST// configure_session _if_ not setup as a client (too)
2959                 //
2960                 // Setup for server credential installation in this session
2961                 //
2962                 // Setup server-specific credentials and priority string
2963 #if 0
2964                 if (! (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
2965 printf ("DEBUG: Configuring server credentials (because it is not a client)\n");
2966                         E_g2e ("Failed to configure GnuTLS as a server",
2967                                 configure_session (cmd,
2968                                         session,
2969                                         anonpost? NULL: srv_creds,
2970                                         anonpost?    0: srv_credcount, 
2971                                         cmd->anonpre & ANONPRE_SERVER));
2972                 }
2973 #endif
2974         }
2975
2976         //
2977         // Prefetch local identities that might be used in this session
2978         if (!anonpost) {
2979                 E_g2e ("Failed to fetch local credentials",
2980                         fetch_local_credentials (cmd));
2981         }
2982
2983         //
2984         // Setup a temporary priority string so handshaking can start
2985         if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) == 0) {
2986                 E_g2e ("Failed to preconfigure server token priority string",
2987                                 gnutls_priority_set (
2988                                         session,
2989                                         priority_normal));
2990         }
2991
2992         //
2993         // Check if past code stored an error code through POSIX
2994         if (cmd->session_errno) {
2995                 gtls_errno = GNUTLS_E_USER_ERROR;
2996         }
2997
2998         //
2999         // Setup a timeout value as specified in the command, where TLS Pool
3000         // defines 0 as default and ~0 as infinite (GnuTLS has 0 as infinite).
3001         tout = cmd->cmd.pio_data.pioc_starttls.timeout;
3002 if (renegotiating) {
3003 ; // Do not set timeout
3004 } else
3005         if (tout == TLSPOOL_TIMEOUT_DEFAULT) {
3006                 gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
3007         } else if (tout == TLSPOOL_TIMEOUT_INFINITE) {
3008                 gnutls_handshake_set_timeout (session, 0);
3009         } else {
3010                 gnutls_handshake_set_timeout (session, tout);
3011         }
3012
3013         //
3014         // Now setup for the GnuTLS handshake
3015         //
3016 if (renegotiating) {
3017 ; // Do not setup cryptfd
3018 } else
3019         if (gtls_errno == GNUTLS_E_SUCCESS) {
3020                 gnutls_transport_set_int (session, cryptfd);
3021         }
3022         if (gtls_errno != GNUTLS_E_SUCCESS) {
3023                 tlog (TLOG_TLS, LOG_ERR, "Failed to prepare for TLS: %s", gnutls_strerror (gtls_errno));
3024                 if (cmd->session_errno) {
3025                         send_error (replycmd, cmd->session_errno, error_getstring ());
3026                 } else {
3027                         send_error (replycmd, EIO, "Failed to prepare for TLS");
3028                 }
3029                 if (got_session) {
3030 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3031                         gnutls_deinit (session);
3032                         got_session = 0;
3033                 }
3034                 close (cryptfd);
3035                 if (plainfd >= 0) {
3036                         close (plainfd);
3037                         plainfd = -1;
3038                 }
3039 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3040                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
3041                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
3042                                 free (ckn);
3043                                 ckn = NULL;
3044                         }
3045                 }
3046                 manage_txn_rollback (&cmd->txn);
3047                 assert (pthread_detach (pthread_self ()) == 0);
3048                 return NULL;
3049         }
3050         tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake started over %d", cryptfd);
3051         do {
3052                 //
3053                 // Take a rehandshaking step forward.
3054                 //
3055                 gtls_errno = gnutls_handshake (session);
3056                 //
3057                 // When data is sent before completing
3058                 // the rehandshake, then it's something
3059                 // harmless, given the criteria for the
3060                 // anonpre_registry.  We pass it on and
3061                 // don't worry about it.  We do report
3062                 // it though!
3063                 //
3064                 // Note: Applications should be willing
3065                 // to buffer or process such early data
3066                 // before the handshake is over or else
3067                 // the handshake will bail out in error.
3068                 //
3069                 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
3070                         if (my_maxpreauth <= 0) {
3071                                 tlog (TLOG_COPYCAT, LOG_ERR, "Received unwanted early data before authentication is complete");
3072                                 break; // Terminate the handshake
3073                         } else if (preauth == NULL) {
3074                                 preauth = malloc (my_maxpreauth);
3075                                 if (preauth == NULL) {
3076                                         gtls_errno = GNUTLS_E_MEMORY_ERROR;
3077                                         break; // Terminate the handshake
3078                                 }
3079                         }
3080                 }
3081                 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
3082                         if (preauthlen >= my_maxpreauth) {
3083                                 tlog (TLOG_COPYCAT, LOG_ERR, "Received more early data than willing to receive (%d bytes)", my_maxpreauth);
3084                                 break; // Terminate the handshake
3085                         }
3086                 }
3087                 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
3088                         ssize_t sz;
3089                         sz = gnutls_record_recv (session, preauth + preauthlen, my_maxpreauth - preauthlen);
3090                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Received %d remote bytes (or error if <0) from %d during anonymous precursor\n", (int) sz, cryptfd);
3091                         if (sz > 0) {
3092                                 preauthlen += sz;
3093                                 gtls_errno = GNUTLS_E_SUCCESS;
3094                         } else {
3095                                 gtls_errno = sz; // It's actually an error code
3096                         }
3097                 }
3098         } while ((gtls_errno < 0) &&
3099                 //DROPPED// (gtls_errno != GNUTLS_E_GOT_APPLICATION_DATA) &&
3100                 //DROPPED// (gtls_errno != GNUTLS_E_WARNING_ALERT_RECEIVED) &&
3101                 (gnutls_error_is_fatal (gtls_errno) == 0));
3102         if (gtls_errno == 0) {
3103                 const gnutls_datum_t *certs;
3104                 unsigned int num_certs;
3105                 got_remoteid = 0;
3106                 switch (gnutls_auth_get_type (session)) { // Peer's cred type
3107                 case GNUTLS_CRD_CERTIFICATE:
3108                         certs = gnutls_certificate_get_peers (session, &num_certs);
3109                         if ((certs != NULL) && (num_certs >= 1)) {
3110                                 got_remoteid = 1;
3111                         }
3112                         // "certs" points into GnuTLS' internal data structures
3113                         E_g2e ("Failed to validate peer",
3114                                 gnutls_certificate_verify_peers2 (
3115                                         session,
3116                                         &cmd->vfystatus));
3117                         break;
3118                 case GNUTLS_CRD_PSK:
3119                         // Difficult... what did the history say about this?
3120                         got_remoteid = 0;
3121                         cmd->vfystatus = GNUTLS_CERT_SIGNER_NOT_FOUND;
3122                         break;
3123                 case GNUTLS_CRD_SRP:
3124                         // Got a credential, validation follows later on
3125                         //TODO// SRP does not really auth the server
3126                         got_remoteid = 1;
3127                         cmd->vfystatus = GNUTLS_CERT_SIGNER_NOT_FOUND;
3128                         break;
3129                 case GNUTLS_CRD_ANON:
3130                         // Did not get a credential, perhaps due to anonpre
3131                         got_remoteid = 0;
3132                         cmd->vfystatus = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNATURE_FAILURE;
3133                         break;
3134                 case GNUTLS_CRD_IA:
3135                         // Inner Application extension is no true credential
3136                         // Should we compare the client-requested service?
3137                         // Should we renegotiate into the ALPN protocol?
3138                         got_remoteid = 0;
3139                         cmd->vfystatus = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNATURE_FAILURE;
3140                         break;
3141                 default:
3142                         // Unknown creds cautiously considered unauthentitcated
3143                         got_remoteid = 0;
3144                         cmd->vfystatus = ~ (unsigned short) 0;  // It's all bad
3145                         break;
3146                 }
3147                 //
3148                 // Now recognise and handle the Anonymous Precursor
3149                 if (((cmd->anonpre & ANONPRE_EITHER) != 0)
3150                                         && want_remoteid && !got_remoteid) {
3151                         assert (anonpost == 0);
3152                         valexp_valflag_set (cmd, 'A');
3153                         // Disable ANON-protocols but keep creds from before
3154                         //TODO:ELSEWHERE// tlog (TLOG_TLS, LOG_DEBUG, "Reconfiguring TLS over %d without Anonymous Precursor\n", cryptfd);
3155                         //TODO:ELSEWHERE// E_g2e ("Failed to reconfigure GnuTLS without anonymous precursor",
3156                                 //TODO:ELSEWHERE// configure_session (cmd,
3157                                         //TODO:ELSEWHERE// session,
3158                                         //TODO:ELSEWHERE// NULL, 0, 
3159                                         //TODO:ELSEWHERE// 0));
3160                         // We do not want to use ANON-DH if the flag
3161                         // ANONPRE_EXTEND_MASTER_SECRET is set for the protocol
3162                         // but the remote peer does not support it.  Only if
3163                         // this problem cannot possibly occur, permit
3164                         // my_maxpreauth > 0 for early data acceptance.
3165                         my_maxpreauth = 0;
3166                         if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
3167 #if GNUTLS_VERSION_NUMBER >= 0x030400
3168                                 gnutls_ext_priv_data_t ext;
3169                                 if (!gnutls_ext_get_data (session, 23, &ext)) {
3170                                         my_maxpreauth = maxpreauth;
3171                                 }
3172 #endif
3173                         } else {
3174                                 my_maxpreauth = maxpreauth;
3175                         }
3176                         if (gtls_errno == 0) {
3177                                 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake continued over %d after anonymous precursor", cryptfd);
3178                                 renegotiating = 1; // (de)selects steps
3179                                 anonpost = 1;      // (de)selects steps
3180                                 goto renegotiate;
3181                         }
3182                 }
3183         }
3184         if ((gtls_errno == GNUTLS_E_SUCCESS) && cmd->session_errno) {
3185                 gtls_errno = GNUTLS_E_USER_ERROR;
3186         }
3187         taking_over = 0;
3188
3189         //
3190         // Cleanup any prefetched identities
3191         for (i=LID_TYPE_MIN; i<=LID_TYPE_MAX; i++) {
3192                 if (cmd->lids [i - LID_TYPE_MIN].data != NULL) {
3193                         free (cmd->lids [i - LID_TYPE_MIN].data);
3194                 }
3195         }
3196         bzero (cmd->lids, sizeof (cmd->lids));
3197
3198 #if 0
3199 /* This is not proper.  gnutls_certificate_set_key() suggests that these are
3200  * automatically cleaned up, and although this is not repeated in
3201  * gnutls_certificate_set_retrieve_function2() it is likely to be related.
3202  * Plus, renegotiation with this code in place bogged down on failed pcerts;
3203  * they were detected in _gnutls_selected_cert_supported_kx() but their
3204  * key exchange algorithm was never found.
3205  */
3206         if (NULL != (void *) cmd->session_privatekey) {
3207                 gnutls_privkey_deinit ((void *) cmd->session_privatekey);
3208                 cmd->session_privatekey = (intptr_t) (void *) NULL;
3209         }
3210         if (NULL != (void *) cmd->session_certificate) {
3211                 gnutls_pcert_deinit ((void *) cmd->session_certificate);
3212                 free ((void *) cmd->session_certificate);
3213                 cmd->session_certificate = (intptr_t) (void *) NULL;
3214         }
3215 #endif
3216
3217         //
3218         // From here, assume nothing about the cmd->cmd structure; as part of
3219         // the handshake, it may have passed through the client's control, as
3220         // part of a callback.  So, reinitialise the entire return structure.
3221         //TODO// Or backup the (struct pioc_starttls) before handshaking
3222         cmd->cmd.pio_cmd = orig_cmdcode;
3223         cmd->cmd.pio_data.pioc_starttls.localid  [0] =
3224         cmd->cmd.pio_data.pioc_starttls.remoteid [0] = 0;
3225
3226         //
3227         // Respond to positive or negative outcome of the handshake
3228         if (gtls_errno != GNUTLS_E_SUCCESS) {
3229                 tlog (TLOG_TLS, LOG_ERR, "TLS handshake failed: %s", gnutls_strerror (gtls_errno));
3230                 if (cmd->session_errno) {
3231                         char *errstr;
3232                         tlog (TLOG_TLS, LOG_ERR, "Underlying cause may be: %s", strerror (cmd->session_errno));
3233                         errstr = error_getstring ();
3234                         if (errstr == NULL) {
3235                                 errstr = "TLS handshake failed";
3236                         }
3237                         send_error (replycmd, cmd->session_errno, errstr);
3238                 } else {
3239                         send_error (replycmd, EPERM, "TLS handshake failed");
3240                 }
3241                 if (preauth) {
3242                         free (preauth);
3243                 }
3244                 if (got_session) {
3245 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3246                         gnutls_deinit (session);
3247                         got_session = 0;
3248                 }
3249                 close (cryptfd);
3250                 if (plainfd >= 0) {
3251                         close (plainfd);
3252                         plainfd = -1;
3253                 }
3254 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3255                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
3256                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
3257                                 free (ckn);
3258                                 ckn = NULL;
3259                         }
3260                 }
3261                 manage_txn_rollback (&cmd->txn);
3262                 assert (pthread_detach (pthread_self ()) == 0);
3263                 return NULL;
3264         } else {
3265                 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_INFO, "TLS handshake succeeded over %d", cryptfd);
3266                 //TODO// extract_authenticated_remote_identity (cmd);
3267         }
3268
3269         //
3270         // Request the plaintext file descriptor with a callback
3271         if (plainfd < 0) {
3272                 uint32_t oldcmd = cmd->cmd.pio_cmd;
3273                 struct command *resp;
3274                 cmd->cmd.pio_cmd = PIOC_PLAINTEXT_CONNECT_V2;
3275                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_PLAINTEXT_CONNECT_V2");
3276                 resp = send_callback_and_await_response (replycmd, 0);
3277                 assert (resp != NULL);  // No timeout, should be non-NULL
3278                 if (resp->cmd.pio_cmd != PIOC_PLAINTEXT_CONNECT_V2) {
3279                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
3280                         send_error (replycmd, EINVAL, "Callback response has bad command code");
3281                         if (preauth) {
3282                                 free (preauth);
3283                         }
3284                         if (got_session) {
3285 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3286                                 gnutls_deinit (session);
3287                                 got_session = 0;
3288                         }
3289                         close (cryptfd);
3290 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3291                         if (ckn) {      /* TODO: CHECK NEEDED? PRACTICE=>YES */
3292                                 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3293                                         free (ckn);
3294                                         ckn = NULL;
3295                                 }
3296                         }
3297                         manage_txn_rollback (&cmd->txn);
3298                         assert (pthread_detach (pthread_self ()) == 0);
3299                         return NULL;
3300                 }
3301                 cmd->cmd.pio_cmd = oldcmd;
3302                 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);
3303                 plainfd = resp->passfd;
3304                 resp->passfd = -1;
3305         }
3306         if (plainfd < 0) {
3307                 tlog (TLOG_UNIXSOCK, LOG_ERR, "No plaintext file descriptor supplied to TLS Pool");
3308                 send_error (replycmd, EINVAL, "No plaintext file descriptor supplied to TLS Pool");
3309                 if (preauth) {
3310                         free (preauth);
3311                 }
3312                 if (got_session) {
3313 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3314                         gnutls_deinit (session);
3315                         got_session = 0;
3316                 }
3317                 close (cryptfd);
3318 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3319                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
3320                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
3321                                 free (ckn);
3322                                 ckn = NULL;
3323                         }
3324                 }
3325                 manage_txn_rollback (&cmd->txn);
3326                 assert (pthread_detach (pthread_self ()) == 0);
3327                 return NULL;
3328         }
3329         //DEFERRED// send_command (replycmd, -1);               // app sent plainfd to us
3330
3331         //
3332         // Copy TLS records until the connection is closed
3333         manage_txn_commit (&cmd->txn);
3334         if (!renegotiating) {
3335                 ckn = (struct ctlkeynode_tls *) malloc (sizeof (struct ctlkeynode_tls));
3336         }
3337         if (ckn == NULL) {
3338                 send_error (replycmd, ENOMEM, "Out of memory allocating control key structure");
3339         } else {
3340                 int detach = (orig_starttls.flags & PIOF_STARTTLS_DETACH) != 0;
3341                 ckn->session = session;
3342                 ckn->owner = pthread_self ();
3343                 ckn->cryptfd = cryptfd;
3344                 ckn->plainfd = plainfd;
3345 //DEBUG// fprintf (stderr, "Registering control key\n");
3346                 if (renegotiating || (ctlkey_register (orig_starttls.ctlkey, &ckn->regent, security_tls, detach? -1: cmd->clientfd, forked) == 0)) {
3347                         int copied = GNUTLS_E_SUCCESS;
3348                         send_command (replycmd, -1);            // app sent plainfd to us
3349                         if (preauth) {
3350
3351                                 //
3352                                 // Check on extended master secret if desired
3353                                 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
3354 #if GNUTLS_VERSION_NUMBER >= 0x030400
3355                                         gnutls_ext_priv_data_t ext;
3356                                         if (!gnutls_ext_get_data (session, 23, &ext)) {
3357                                                 cmd->anonpre &= ~ANONPRE_EXTEND_MASTER_SECRET;
3358                                         }
3359 #endif
3360                                 }
3361                                 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
3362                                         tlog (TLOG_COPYCAT, LOG_ERR, "Received %d remote bytes from anonymous precursor but lacking %s-required authentication through extended master secret", orig_starttls.service);
3363                                         gtls_errno = GNUTLS_E_LARGE_PACKET;
3364                                         copied = 0;
3365
3366                                 } else if (write (plainfd, preauth, preauthlen) == preauthlen) {
3367                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Passed on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
3368                                         free (preauth);
3369                                         preauth = NULL;
3370                                         copied = copycat (plainfd, cryptfd, session, detach? -1: cmd->clientfd);
3371                                 } else {
3372                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Failed to pass on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
3373                                 }
3374                         } else {
3375                                 copied = copycat (plainfd, cryptfd, session, detach? -1: cmd->clientfd);
3376                         }
3377                         // Renegotiate if copycat asked us to
3378                         if (copied == GNUTLS_E_REHANDSHAKE) {
3379                                 // Yes, goto is a dirty technique.  On the
3380                                 // other hand, so is forcing unstructured
3381                                 // code flows into a make-belief structure
3382                                 // that needs changing over and over again.
3383                                 // I fear goto is the most reasonable way
3384                                 // of handling this rather obtuse structure
3385                                 // of renegotiation of security in TLS :(
3386                                 //TODO// Ensure secure renegotiation!!!
3387                                 renegotiating = 1;
3388                                 replycmd = NULL; // Bypass all send_XXX()
3389                                 memcpy (&cmd_copy, cmd, sizeof (cmd_copy));
3390                                 cmd = &cmd_copy;
3391                                 memcpy (cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid));
3392                                 memcpy (cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid));
3393                                 cmd->cmd.pio_data.pioc_starttls.flags = orig_starttls.flags & ~PIOF_STARTTLS_LOCALID_CHECK;
3394                                 // Disabling the flag causing LOCALID_CHECK
3395                                 // ...and plainfd >= 0 so no PLAINTEXT_CONNECT
3396                                 // ...so there will be no callbacks to cmd
3397 printf ("DEBUG: Goto renegotiate with cmd.lid = \"%s\" and orig_cmd.lid = \"%s\" and cmd.rid = \"%s\" and orig_cmd.rid = \"%s\" and cmd.flags = 0x%x and orig_cmd.flags = 0x%x\n", cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, cmd->cmd.pio_data.pioc_starttls.flags, orig_starttls.flags);
3398                                 goto renegotiate;
3399                         }
3400 //DEBUG// fprintf (stderr, "Unregistering control key\n");
3401                         // Unregister by ctlkey, which should always succeed
3402                         // if the TLS connection hadn't been closed down yet;
3403                         // and if it does, the memory can be freed.  Note that
3404                         // the ctlkey is not taken from the ckn, which may
3405                         // already have been freed if the ctlfd was closed
3406                         // and the connection could not continue detached
3407                         // (such as after forking it).
3408 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3409                         if (ctlkey_unregister (orig_starttls.ctlkey)) {
3410                                 free (ckn);
3411                         }
3412                         ckn = NULL;
3413 //DEBUG// fprintf (stderr, "Unregistered  control key\n");
3414                 } else {
3415                         send_error (replycmd, ENOENT, "Failed to register control key for TLS connection");
3416                 }
3417         }
3418         if (preauth) {
3419                 free (preauth);
3420                 preauth = NULL;
3421         }
3422         close (plainfd);
3423         close (cryptfd);
3424         if (got_session) {
3425 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3426                 gnutls_deinit (session);
3427                 got_session = 0;
3428         }
3429         assert (pthread_detach (pthread_self ()) == 0);
3430         return NULL;
3431 }
3432
3433
3434 /*
3435  * The starttls function responds to an application's request to 
3436  * setup TLS for a given file descriptor, and return a file descriptor
3437  * with the unencrypted view when done.  The main thing done here is to
3438  * spark off a new thread that handles the operations.
3439  */
3440 void starttls (struct command *cmd) {
3441         /* Create a thread and, if successful, wait for it to unlock cmd */
3442         errno = pthread_create (&cmd->handler, NULL, starttls_thread, (void *) cmd);
3443         if (errno != 0) {
3444                 send_error (cmd, ESRCH, "STARTTLS thread refused");
3445                 return;
3446         }
3447 //TODO:TEST// Thread detaches itself before terminating w/o followup
3448 /*
3449         errno = pthread_detach (cmd->handler);
3450         if (errno != 0) {
3451                 pthread_cancel (cmd->handler);
3452                 send_error (cmd, ESRCH, "STARTTLS thread detachment refused");
3453                 return;
3454         }
3455 */
3456 }
3457
3458
3459 /*
3460  * Run the PRNG for a TLS connection, identified by its control key.  If the connection
3461  * is not a TLS connection, or if the control key is not found, reply with ERROR;
3462  * otherwise, the session should help to create pseudo-random bytes.
3463  */
3464 void starttls_prng (struct command *cmd) {
3465         uint8_t in1 [TLSPOOL_PRNGBUFLEN];
3466         uint8_t in2 [TLSPOOL_PRNGBUFLEN];
3467         int16_t in1len, in2len, prnglen;
3468         struct ctlkeynode_tls *ckn = NULL;
3469         char **prefixes;
3470         int err = 0;
3471         int gtls_errno = GNUTLS_E_SUCCESS;
3472         struct pioc_prng *prng = &cmd->cmd.pio_data.pioc_prng;
3473         //
3474         // Find arguments and validate them
3475         in1len  = prng->in1_len;
3476         in2len  = prng->in2_len;
3477         prnglen = prng->prng_len;
3478         err = err || (in1len <= 0);
3479         err = err || (prnglen > TLSPOOL_PRNGBUFLEN);
3480         err = err || ((TLSPOOL_CTLKEYLEN + in1len + (in2len >= 0? in2len: 0))
3481                                 > TLSPOOL_PRNGBUFLEN);
3482         if (!err) {
3483                 memcpy (in1, prng->buffer + TLSPOOL_CTLKEYLEN         , in1len);
3484                 if (in2len > 0) {
3485                         memcpy (in2, prng->buffer + TLSPOOL_CTLKEYLEN + in1len, in2len);
3486                 }
3487         }
3488         //  - check the label string
3489         prefixes = tlsprng_label_prefixes;
3490         while ((!err) && (*prefixes)) {
3491                 char *pf = *prefixes++;
3492                 if (strlen (pf) != in1len) {
3493                         continue;
3494                 }
3495                 if (strcmp (pf, in1) != 0) {
3496                         continue;
3497                 }
3498         }
3499         if (*prefixes == NULL) {
3500                 // RFC 5705 defines a private-use prefix "EXPERIMENTAL"
3501                 if ((in1len <= 12) || (strncmp (in1, "EXPERIMENTAL", 12) != 0)) {
3502                         err = 1;
3503                 }
3504         }
3505         //  - check the ctlkey (and ensure it is for TLS)
3506         if (!err) {
3507 //DEBUG// fprintf (stderr, "Hoping to find control key\n");
3508                 ckn = (struct ctlkeynode_tls *) ctlkey_find (prng->buffer, security_tls, cmd->clientfd);
3509         }
3510         //
3511         // Now wipe the PRNG buffer to get rid of any sensitive bytes
3512         memset (prng->buffer, 0, TLSPOOL_PRNGBUFLEN);
3513         //
3514         // If an error occurrend with the command, report it now
3515         if (err) {
3516                 send_error (cmd, EINVAL, "TLS PRNG request invalid");
3517                 // ckn is NULL if err != 0, so no need for ctlkey_unfind()
3518                 return;
3519         }
3520         if (ckn == NULL) {
3521                 send_error (cmd, ENOENT, "Invalid control key");
3522                 return;
3523         }
3524         //
3525         // Now actually invoke the PRNG command in the GnuTLS backend
3526         errno = 0;
3527         E_g2e ("GnuTLS PRNG based on session master key failed",
3528                 gnutls_prf_rfc5705 (ckn->session,
3529                         in1len, in1,
3530                         (in2len >= 0)? in2len: 0, (in2len >= 0) ? in2: NULL,
3531                         prnglen, prng->buffer));
3532         err = err || (errno != 0);
3533         //
3534         // Wipe temporary data / buffers for security reasons
3535         memset (in1, 0, sizeof (in1));
3536         memset (in2, 0, sizeof (in2));
3537         ctlkey_unfind ((struct ctlkeynode *) ckn);
3538         //
3539         // Return the outcome to the user
3540         if (err) {
3541                 send_error (cmd, errno? errno: EIO, "PRNG in TLS backend failed");
3542         } else {
3543                 send_command (cmd, -1);
3544         }
3545 }
3546
3547
3548 /* Flying signer functionality.  Create an on-the-fly certificate because
3549  * the lidentry daemon and/or application asks for this to represent the
3550  * local identity.  Note that this will only work if the remote party
3551  * accepts the root identity under which on-the-signing is done.
3552  *
3553  * When no root credentials have been configured, this function will
3554  * fail with GNUTLS_E_AGAIN; it may be used as a hint to try through
3555  * other (more conventional) means to obtain a client certificate.
3556  *
3557  * The API of this function matches that of fetch_local_credentials()
3558  * and that is not a coincidence; this is a drop-in replacement in some
3559  * cases.
3560  *
3561  * Limitations: The current implementation only supports X.509 certificates
3562  * to be generated on the fly.  So, this will set LID_TYPE_X509, if anything.
3563  */
3564 gtls_error certificate_onthefly (struct command *cmd) {
3565         gtls_error gtls_errno = GNUTLS_E_SUCCESS;
3566         gnutls_x509_crt_t otfcert;
3567         time_t now;
3568         gnutls_x509_subject_alt_name_t altnmtp;
3569         int i;
3570
3571         //
3572         // Sanity checks
3573         if ((onthefly_issuercrt == NULL) || (onthefly_issuerkey == NULL) || (onthefly_subjectkey == NULL)) {
3574                 // Not able to supply on-the-fly certificates; try someway else
3575                 return GNUTLS_E_AGAIN;
3576         }
3577         if (cmd->cmd.pio_data.pioc_starttls.localid [0] == '\0') {
3578                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
3579         }
3580         if (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data != NULL) {
3581                 free (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data);
3582                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = NULL;
3583                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
3584         }
3585         
3586         //
3587         // Create an empty certificate
3588         E_g2e ("Failed to initialise on-the-fly certificate",
3589                 gnutls_x509_crt_init (&otfcert));
3590         if (gtls_errno != GNUTLS_E_SUCCESS) {
3591                 return gtls_errno;
3592         }
3593
3594         //
3595         // Fill the certificate with the usual field
3596         E_g2e ("Failed to set on-the-fly certificate to non-CA mode",
3597                 gnutls_x509_crt_set_ca_status (otfcert, 0));
3598         E_g2e ("Failed to set on-the-fly certificate version",
3599                 gnutls_x509_crt_set_version (otfcert, 3));
3600         onthefly_serial++;      //TODO// Consider a random byte string
3601         E_g2e ("Failed to set on-the-fly serial number",
3602                 gnutls_x509_crt_set_serial (otfcert, &onthefly_serial, sizeof (onthefly_serial)));
3603         // Skip gnutls_x509_crt_set_issuer_by_dn_by_oid(), added when signing
3604         time (&now);
3605         E_g2e ("Failed to set on-the-fly activation time to now - 2 min",
3606                 gnutls_x509_crt_set_activation_time (otfcert, now - 120));
3607         E_g2e ("Failed to set on-the-fly expiration time to now + 3 min",
3608                 gnutls_x509_crt_set_expiration_time (otfcert, now + 180));
3609         E_g2e ("Setup certificate CN with local identity",
3610                 gnutls_x509_crt_set_dn_by_oid (otfcert, GNUTLS_OID_X520_COMMON_NAME, 0, cmd->cmd.pio_data.pioc_starttls.localid, strnlen (cmd->cmd.pio_data.pioc_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid)-1))); /* TODO: Consider pioc_lidentry as well? */
3611         E_g2e ("Setup certificate OU with TLS Pool on-the-fly",
3612                 gnutls_x509_crt_set_dn_by_oid (otfcert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "TLS Pool on-the-fly", 19));
3613         if (strchr (cmd->cmd.pio_data.pioc_starttls.localid, '@')) {
3614                 // localid has the format of an emailAddress
3615                 altnmtp = GNUTLS_SAN_RFC822NAME;
3616         } else {
3617                 // localid has the format of a dnsName
3618                 altnmtp = GNUTLS_SAN_DNSNAME;
3619         }
3620         E_g2e ("Failed to set subjectAltName to localid",
3621                 gnutls_x509_crt_set_subject_alt_name (otfcert, altnmtp, &cmd->cmd.pio_data.pioc_starttls.localid, strnlen (cmd->cmd.pio_data.pioc_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid) - 1), GNUTLS_FSAN_APPEND));
3622         //TODO:SKIP, hoping that signing adds: gnutls_x509_crt_set_authority_key_id()
3623         //TODO:SKIP, hoping that a cert without also works: gnutls_x509_crt_set_subjectkey_id()
3624         //TODO:SKIP? gnutls_x509_crt_set_extension_by_oid
3625         //TODO:      gnutls_x509_crt_set_key_usage
3626         //TODO:SKIP? gnutls_x509_crt_set_ca_status
3627         for (i=0; i < svcusage_registry_size; i++) {
3628                 if (strcmp (svcusage_registry [i].service, cmd->cmd.pio_data.pioc_starttls.service) == 0) {
3629                         const char **walker;
3630                         E_g2e ("Failed to setup basic key usage during on-the-fly certificate creation",
3631                                 gnutls_x509_crt_set_key_usage (otfcert, svcusage_registry [i].usage));
3632                         walker = svcusage_registry [i].oids_non_critical;
3633                         if (walker) {
3634                                 while (*walker) {
3635                                         E_g2e ("Failed to append non-critical extended key purpose during on-the-fly certificate creation",
3636                                                 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 0));
3637                                         walker++;
3638                                 }
3639                         }
3640                         walker = svcusage_registry [i].oids_critical;
3641                         if (walker) {
3642                                 while (*walker) {
3643                                         E_g2e ("Failed to append critical extended key purpose during on-the-fly certificate creation",
3644                                                 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 1));
3645                                         walker++;
3646                                 }
3647                         }
3648                         break;
3649                 }
3650         }
3651         E_g2e ("Failed to et the on-the-fly subject key",
3652                 gnutls_x509_crt_set_key (otfcert, onthefly_subjectkey));
3653         /* TODO: The lock below should not be necessary; it is handled by p11-kit
3654          *       or at least it ought to be.  What I found however, was that
3655          *       a client and server would try to use the onthefly_issuerkey
3656          *       at virtually the same time, and then the second call to
3657          *       C_SignInit returns CKR_OPERATION_ACTIVE.  The lock solved this.
3658          *       This makes me frown about server keys stored in PKCS #11...
3659          */
3660 {gnutls_datum_t data = { 0, 0}; if (gnutls_x509_crt_print (otfcert, GNUTLS_CRT_PRINT_UNSIGNED_FULL, &data) == 0) { fprintf (stderr, "DEBUG: PRESIGCERT: %s\n", data.data); gnutls_free (data.data); } else {fprintf (stderr, "DEBUG: PRESIGCERT failed to print\n"); } }
3661         assert (pthread_mutex_lock (&onthefly_signer_lock) == 0);
3662         E_g2e ("Failed to sign on-the-fly certificate",
3663                 gnutls_x509_crt_privkey_sign (otfcert, onthefly_issuercrt, onthefly_issuerkey, GNUTLS_DIG_SHA256, 0));
3664         pthread_mutex_unlock (&onthefly_signer_lock);
3665
3666         //
3667         // Construct cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data+size for this certificate
3668         cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
3669         if (gtls_errno == GNUTLS_E_SUCCESS) {
3670                 gtls_errno = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, NULL, &cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
3671                 if (gtls_errno == GNUTLS_E_SHORT_MEMORY_BUFFER) {
3672                         // This is as expected, now .size will have been set
3673                         gtls_errno = GNUTLS_E_SUCCESS;
3674                 } else {
3675                         if (gtls_errno = GNUTLS_E_SUCCESS) {
3676                                 // Something must be wrong if we receive OK
3677                                 gtls_errno = GNUTLS_E_INVALID_REQUEST;
3678                         }
3679                 }
3680                 E_g2e ("Error while measuring on-the-fly certificate size",
3681                         gtls_errno);
3682         }
3683         uint8_t *ptr = NULL;
3684         if (gtls_errno == GNUTLS_E_SUCCESS) {
3685                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size += 4 + strlen (onthefly_p11uri) + 1;
3686                 ptr = malloc (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
3687                 if (ptr == NULL) {
3688                         cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
3689                         gnutls_x509_crt_deinit (otfcert);
3690                         return GNUTLS_E_MEMORY_ERROR;
3691                 }
3692         }
3693         if (ptr != NULL) {
3694                 size_t restsz;
3695                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = ptr;
3696                 * (uint32_t *) ptr = htonl (LID_TYPE_X509 | LID_ROLE_BOTH);
3697                 ptr += 4;
3698                 strcpy (ptr, onthefly_p11uri);
3699                 ptr += strlen (onthefly_p11uri) + 1;
3700                 restsz = cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size - 4 - strlen (onthefly_p11uri) - 1;
3701                 E_g2e ("Failed to export on-the-fly certificate as a credential",
3702                         gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, ptr, &restsz));
3703 char *pembuf [10000];
3704 size_t pemlen = sizeof (pembuf) - 1;
3705 int exporterror = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_PEM, pembuf, &pemlen);
3706 if (exporterror == 0) {
3707 pembuf [pemlen] = '\0';
3708 fprintf (stderr, "DEBUG: otfcert ::=\n%s\n", pembuf);
3709 } else {
3710 fprintf (stderr, "DEBUG: otfcert export to PEM failed with %d, gtls_errno already was %d\n", exporterror, gtls_errno);
3711 }
3712         }
3713
3714         //
3715         // Cleanup the allocated and built structures
3716         gnutls_x509_crt_deinit (otfcert);
3717
3718         //
3719         // Return the overall result that might have stopped otf halfway
3720         return gtls_errno;
3721 }
3722