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