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