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