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