1 /* tlspool/starttls.c -- Setup and validation handler for TLS session */
17 #include <gnutls/gnutls.h>
18 #include <gnutls/pkcs11.h>
19 #include <gnutls/abstract.h>
20 #include <gnutls/dane.h>
22 #include <tlspool/commands.h>
23 #include <tlspool/internal.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
36 #include <arpa/inet.h>
38 #include <netinet/in.h>
44 #define SHUT_RD SD_RECEIVE
45 #define SHUT_WR SD_SEND
46 #else /* WINDOWS_PORT */
47 #define RECV_FLAGS MSG_DONTWAIT | MSG_NOSIGNAL
48 #endif /* WINDOWS_PORT */
55 #if EXPECTED_LID_TYPE_COUNT != LID_TYPE_CNT
56 #error "Set EXPECTED_LID_TYPE_COUNT in <tlspool/internal.h> to match LID_TYPE_CNT"
60 /* This module hosts TLS handlers which treat an individual connection.
62 * Initially, the TLS setup is processed, which means validating the
63 * connection. If and when this succeeds, a continued process is needed
64 * to encrypt and decrypt traffic while it is in transit.
66 * Every TLS connection (including the attempt to set it up) is hosted in
67 * its own thread. This means that it can abide time to wait for PINENTRY,
68 * LOCALID or LIDENTRY responses. It also means a very clear flow when the
69 * time comes to destroy a connection.
71 * While encrypting and decrypting traffic passing through, the thread
72 * will use its own poll() call, and thus offload the potentially large
73 * one of the main thread, which is supposed to be a low-traffic task.
74 * The set of file descriptors used by the session-handler threads are
75 * in contrast very small and can easily be started for every single
76 * packet passing through.
78 * Might the user terminate a process while this one is waiting for a
79 * callback command request, then the main TLS pool thread will take
80 * care of taking down this thread. To that end, it sets the followup
81 * pointer that normally holds a callback response to NULL, and then
82 * permits this thread to run again. This will lead to a shutdown of
83 * this process, and proper closing of all connections. The remote peer
84 * will therefore see the result of a local kill as a connection reset.
86 * In case one of the end points of the connection is terminated, a
87 * similar thing will happen; the thread will terminate itself after
88 * a cleanup of any outstanding resources. This, once again, leads
89 * to passing on the reset of a connection between the encrypted and
90 * side of the connection.
96 * GnuTLS infrastructure setup.
97 * Session-shared DH-keys, credentials structures, and so on.
99 static gnutls_dh_params_t dh_params;
102 gnutls_credentials_type_t credtp;
106 #define EXPECTED_SRV_CREDCOUNT 3
107 #define EXPECTED_CLI_CREDCOUNT 3
108 static struct credinfo srv_creds [EXPECTED_SRV_CREDCOUNT];
109 static struct credinfo cli_creds [EXPECTED_CLI_CREDCOUNT];
110 static int srv_credcount = 0;
111 static int cli_credcount = 0;
112 static const char const *onthefly_p11uri = "pkcs11:manufacturer=ARPA2.net;token=TLS+Pool+internal;object=on-the-fly+signer;type=private;serial=1";
113 static unsigned long long onthefly_serial; //TODO: Fill with now * 1000
114 static gnutls_x509_crt_t onthefly_issuercrt = NULL;
115 static gnutls_privkey_t onthefly_issuerkey = NULL;
116 static gnutls_x509_privkey_t onthefly_subjectkey = NULL;
117 static pthread_mutex_t onthefly_signer_lock = PTHREAD_MUTEX_INITIALIZER;
119 /* The local variation on the ctlkeynode structure, with TLS-specific fields
121 struct ctlkeynode_tls {
122 struct ctlkeynode regent; // Structure for ctlkey_register()
123 gnutls_session_t session; // Additional data specifically for TLS
124 pthread_t owner; // For interruption of copycat()
125 int plainfd; // Plain-side connection
126 int cryptfd; // Crypt-side connection
129 /* The list of accepted Exporter Label Prefixes for starttls_prng()
131 char *tlsprng_label_prefixes [] = {
132 // Forbidden by RFC 5705: "client finished",
133 // Forbidden by RFC 5705: "server finished",
134 // Forbidden by RFC 5705: "master secret",
135 // Forbidden by RFC 5705: "key expansion",
136 "client EAP encryption", // not suited for DTLS
137 "ttls keying material", // not suited for DTLS
138 "ttls challenge", // not suited for DTLS
139 "EXTRACTOR-dtls_srtp",
140 "EXPORTER_DTLS_OVER_SCTP",
141 "EXPORTER-ETSI-TC-M2M-Bootstrap",
142 "EXPORTER-ETSI-TC-M2M-Connection",
144 "EXPORTER_GBA_Digest",
145 "EXPORTER: teap session key seed", // not suited for DTLS
146 "EXPORTER-oneM2M-Bootstrap",
147 "EXPORTER-oneM2M-Connection",
151 /* The registry with the service names that are deemed safe for an
152 * anonymous precursor phase; that is, the service names that may offer
153 * ANON-DH initially, and immediately renegotiate an authenticated
154 * connection. See doc/anonymising-precursor.* for more information.
156 * The registry is ordered by case-independent service name, so it can
157 * be searched in 2log time. Service names are as defined by IANA in the
158 * "Service Name and Transport Protocol Port Number Registry".
160 * The entries in the registry depend on the role played; either as a
161 * client or as a server. This refers to the local node, and depends on
162 * uncertainty of the remote party's TLS implementation and whether or
163 * not the protocol could lead to the remote sending information that
164 * requires authentication before the secure renogiation into an
165 * authenticated connection has been completed by this side. This is
166 * a protocol-dependent matter and the registry provided here serves to
167 * encapsulate this knowledge inside the TLS Pool instead of bothering
168 * application designers with it. Entries that are not found in the
169 * registry are interpreted as not allowing an anonymising precursor.
171 * Note that ANONPRE_EXTEND_MASTER_SECRET cannot be verified before
172 * GnuTLS version 3.4.0; see "imap" below for the resulting impact. This
173 * also impacts dynamic linking, because 3.4.0 introduces the new function
174 * gnutls_ext_get_data() that is used for this requirement.
176 #define ANONPRE_FORBID 0x00
177 #define ANONPRE_CLIENT 0x01
178 #define ANONPRE_SERVER 0x02
179 #define ANONPRE_EITHER (ANONPRE_CLIENT | ANONPRE_SERVER)
180 #define ANONPRE_EXTEND_MASTER_SECRET 0x10
181 struct anonpre_regentry {
185 struct anonpre_regentry anonpre_registry [] = {
186 /* This registry is commented out for now, although the code to use it seems
187 * to work fine. GnuTLS however, does not seem to support making the switch
188 * from ANON-ECDH to an authenticated handshake. Details:
189 * http://lists.gnutls.org/pipermail/gnutls-help/2015-November/003998.html
191 { "generic_anonpre", ANONPRE_EITHER }, // Name invalid as per RFC 6335
192 { "http", ANONPRE_CLIENT }, // Server also if it ignores client ID
193 #if GNUTLS_VERSION_NUMBER < 0x030400
194 { "imap", ANONPRE_SERVER },
196 { "imap", ANONPRE_EITHER | ANONPRE_EXTEND_MASTER_SECRET },
198 { "pop3", ANONPRE_EITHER },
199 { "smtp", ANONPRE_EITHER },
201 * End of commenting out the registry
204 const int anonpre_registry_size = sizeof (anonpre_registry) / sizeof (struct anonpre_regentry);
207 /* The registry of Key Usage and Extended Key Usage for any given service name.
209 static const char *http_noncrit [] = { GNUTLS_KP_TLS_WWW_SERVER, GNUTLS_KP_TLS_WWW_CLIENT, NULL };
210 struct svcusage_regentry {
213 const char **oids_non_critical;
214 const char **oids_critical;
216 struct svcusage_regentry svcusage_registry [] = {
218 GNUTLS_KEY_KEY_ENCIPHERMENT |
219 GNUTLS_KEY_KEY_AGREEMENT,
224 GNUTLS_KEY_DIGITAL_SIGNATURE |
225 GNUTLS_KEY_KEY_ENCIPHERMENT |
226 GNUTLS_KEY_KEY_AGREEMENT,
231 const int svcusage_registry_size = sizeof (svcusage_registry) / sizeof (struct svcusage_regentry);
234 /* The maximum number of bytes that can be passed over a TLS connection before
235 * the authentication is complete in case of a anonymous precursor within a
236 * protocol that ensures that this cannot be a problem.
240 /* The priorities cache for "NORMAL" -- used to preconfigure the server,
241 * actually to overcome its unwillingness to perform the handshake, and
242 * leave it to srv_clienthello() to setup the priority string.
244 gnutls_priority_t priority_normal;
247 /* Map a GnuTLS call (usually a function call) to a POSIX errno,
248 * optionally reporting an errstr to avoid loosing information.
249 * Retain errno if it already exists.
250 * Continue if errno differs from 0, GnuTLS may "damage" it even when OK. */
251 #define E_g2e(errstr,gtlscall) { \
252 if (gtls_errno == GNUTLS_E_SUCCESS) { \
253 gtls_errno = (gtlscall); \
254 if (gtls_errno != GNUTLS_E_SUCCESS) { \
255 error_gnutls2posix (gtls_errno, errstr); \
260 /* Cleanup when GnuTLS leaves errno damaged but returns no gtls_errno */
261 #define E_gnutls_clear_errno() { \
262 if (gtls_errno == GNUTLS_E_SUCCESS) { \
267 /* Error number translation, including error string setup. See E_g2e(). */
268 void error_gnutls2posix (int gtls_errno, char *new_errstr) {
270 register int newerrno;
273 if (gtls_errno == GNUTLS_E_SUCCESS) {
276 errstr = error_getstring ();
277 if (errstr != NULL) {
281 // Report the textual error
282 if (new_errstr == NULL) {
283 new_errstr = "GnuTLS error";
285 tlog (TLOG_TLS, LOG_ERR, "%s: %s",
287 gnutls_strerror (gtls_errno));
288 error_setstring (new_errstr);
290 // Translate error to a POSIX errno value
291 switch (gtls_errno) {
292 case GNUTLS_E_SUCCESS:
294 case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
295 case GNUTLS_E_UNKNOWN_CIPHER_TYPE:
296 case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
297 case GNUTLS_E_UNWANTED_ALGORITHM:
298 case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
299 case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
300 case GNUTLS_E_X509_UNKNOWN_SAN:
301 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
302 case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
303 case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
304 case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
305 case GNUTLS_E_NO_CIPHER_SUITES:
306 case GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED:
307 case GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE:
308 case GNUTLS_E_UNKNOWN_HASH_ALGORITHM:
309 case GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE:
310 case GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE:
311 case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
312 case GNUTLS_E_UNKNOWN_ALGORITHM:
313 case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
314 case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
315 case GNUTLS_E_X509_UNSUPPORTED_OID:
316 case GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE:
317 case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
318 case GNUTLS_E_ECC_NO_SUPPORTED_CURVES:
319 case GNUTLS_E_ECC_UNSUPPORTED_CURVE:
320 case GNUTLS_E_X509_UNSUPPORTED_EXTENSION:
321 case GNUTLS_E_NO_CERTIFICATE_STATUS:
322 case GNUTLS_E_NO_APPLICATION_PROTOCOL:
323 #ifdef GNUTLS_E_NO_SELF_TEST
324 case GNUTLS_E_NO_SELF_TEST:
326 newerrno = EOPNOTSUPP;
328 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
329 case GNUTLS_E_INVALID_REQUEST:
332 case GNUTLS_E_INVALID_SESSION:
333 case GNUTLS_E_REHANDSHAKE:
334 case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
337 case GNUTLS_E_PUSH_ERROR:
338 case GNUTLS_E_PULL_ERROR:
339 case GNUTLS_E_PREMATURE_TERMINATION:
340 case GNUTLS_E_SESSION_EOF:
341 newerrno = ECONNRESET;
343 case GNUTLS_E_UNEXPECTED_PACKET:
344 case GNUTLS_E_WARNING_ALERT_RECEIVED:
345 case GNUTLS_E_FATAL_ALERT_RECEIVED:
346 case GNUTLS_E_LARGE_PACKET:
347 case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
348 case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
349 case GNUTLS_E_MPI_SCAN_FAILED:
350 case GNUTLS_E_DECRYPTION_FAILED:
351 case GNUTLS_E_DECOMPRESSION_FAILED:
352 case GNUTLS_E_COMPRESSION_FAILED:
353 case GNUTLS_E_BASE64_DECODING_ERROR:
354 case GNUTLS_E_MPI_PRINT_FAILED:
355 case GNUTLS_E_GOT_APPLICATION_DATA:
356 case GNUTLS_E_RECORD_LIMIT_REACHED:
357 case GNUTLS_E_ENCRYPTION_FAILED:
358 case GNUTLS_E_PK_ENCRYPTION_FAILED:
359 case GNUTLS_E_PK_DECRYPTION_FAILED:
360 case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
361 case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
362 case GNUTLS_E_PKCS1_WRONG_PAD:
363 case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
364 case GNUTLS_E_FILE_ERROR:
365 case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
366 case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
367 case GNUTLS_E_ASN1_DER_ERROR:
368 case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
369 case GNUTLS_E_ASN1_GENERIC_ERROR:
370 case GNUTLS_E_ASN1_VALUE_NOT_VALID:
371 case GNUTLS_E_ASN1_TAG_ERROR:
372 case GNUTLS_E_ASN1_TAG_IMPLICIT:
373 case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
374 case GNUTLS_E_ASN1_SYNTAX_ERROR:
375 case GNUTLS_E_ASN1_DER_OVERFLOW:
376 case GNUTLS_E_TOO_MANY_EMPTY_PACKETS:
377 case GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS:
378 case GNUTLS_E_SRP_PWD_PARSING_ERROR:
379 case GNUTLS_E_BASE64_ENCODING_ERROR:
380 case GNUTLS_E_OPENPGP_KEYRING_ERROR:
381 case GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR:
382 case GNUTLS_E_OPENPGP_SUBKEY_ERROR:
383 case GNUTLS_E_CRYPTO_ALREADY_REGISTERED:
384 case GNUTLS_E_HANDSHAKE_TOO_LARGE:
385 case GNUTLS_E_BAD_COOKIE:
386 case GNUTLS_E_PARSING_ERROR:
387 case GNUTLS_E_CERTIFICATE_LIST_UNSORTED:
388 case GNUTLS_E_NO_PRIORITIES_WERE_SET:
389 #ifdef GNUTLS_E_PK_GENERATION_ERROR
390 case GNUTLS_E_PK_GENERATION_ERROR:
392 #ifdef GNUTLS_E_SELF_TEST_ERROR
393 case GNUTLS_E_SELF_TEST_ERROR:
395 #ifdef GNUTLS_E_SOCKETS_INIT_ERROR
396 case GNUTLS_E_SOCKETS_INIT_ERROR:
400 case GNUTLS_E_MEMORY_ERROR:
401 case GNUTLS_E_SHORT_MEMORY_BUFFER:
407 case GNUTLS_E_EXPIRED:
408 case GNUTLS_E_TIMEDOUT:
409 newerrno = ETIMEDOUT;
411 case GNUTLS_E_DB_ERROR:
418 case GNUTLS_E_SRP_PWD_ERROR:
419 case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
420 case GNUTLS_E_HASH_FAILED:
421 case GNUTLS_E_PK_SIGN_FAILED:
422 case GNUTLS_E_CERTIFICATE_ERROR:
423 case GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION:
424 case GNUTLS_E_KEY_USAGE_VIOLATION:
425 case GNUTLS_E_NO_CERTIFICATE_FOUND:
426 case GNUTLS_E_OPENPGP_UID_REVOKED:
427 case GNUTLS_E_OPENPGP_GETKEY_FAILED:
428 case GNUTLS_E_PK_SIG_VERIFY_FAILED:
429 case GNUTLS_E_ILLEGAL_SRP_USERNAME:
430 case GNUTLS_E_INVALID_PASSWORD:
431 case GNUTLS_E_MAC_VERIFY_FAILED:
432 case GNUTLS_E_IA_VERIFY_FAILED:
433 case GNUTLS_E_UNKNOWN_SRP_USERNAME:
434 case GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR:
435 case GNUTLS_E_USER_ERROR:
436 case GNUTLS_E_AUTH_ERROR:
439 case GNUTLS_E_INTERRUPTED:
442 case GNUTLS_E_INTERNAL_ERROR:
443 case GNUTLS_E_CONSTRAINT_ERROR:
444 case GNUTLS_E_ILLEGAL_PARAMETER:
447 case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
448 newerrno = ECONNREFUSED;
450 case GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY:
451 case GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY:
452 #ifdef GNUTLS_E_LIB_IN_ERROR_STATE
453 case GNUTLS_E_LIB_IN_ERROR_STATE:
457 case GNUTLS_E_RANDOM_FAILED:
460 case GNUTLS_E_CRYPTODEV_IOCTL_ERROR:
461 case GNUTLS_E_CRYPTODEV_DEVICE_ERROR:
462 case GNUTLS_E_HEARTBEAT_PONG_RECEIVED:
463 case GNUTLS_E_HEARTBEAT_PING_RECEIVED:
464 case GNUTLS_E_PKCS11_ERROR:
465 case GNUTLS_E_PKCS11_LOAD_ERROR:
466 case GNUTLS_E_PKCS11_PIN_ERROR:
467 case GNUTLS_E_PKCS11_SLOT_ERROR:
468 case GNUTLS_E_LOCKING_ERROR:
469 case GNUTLS_E_PKCS11_ATTRIBUTE_ERROR:
470 case GNUTLS_E_PKCS11_DEVICE_ERROR:
471 case GNUTLS_E_PKCS11_DATA_ERROR:
472 case GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR:
473 case GNUTLS_E_PKCS11_KEY_ERROR:
474 case GNUTLS_E_PKCS11_PIN_EXPIRED:
475 case GNUTLS_E_PKCS11_PIN_LOCKED:
476 case GNUTLS_E_PKCS11_SESSION_ERROR:
477 case GNUTLS_E_PKCS11_SIGNATURE_ERROR:
478 case GNUTLS_E_PKCS11_TOKEN_ERROR:
479 case GNUTLS_E_PKCS11_USER_ERROR:
480 case GNUTLS_E_CRYPTO_INIT_FAILED:
481 case GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE:
482 case GNUTLS_E_TPM_ERROR:
483 case GNUTLS_E_TPM_KEY_PASSWORD_ERROR:
484 case GNUTLS_E_TPM_SRK_PASSWORD_ERROR:
485 case GNUTLS_E_TPM_SESSION_ERROR:
486 case GNUTLS_E_TPM_KEY_NOT_FOUND:
487 case GNUTLS_E_TPM_UNINITIALIZED:
488 case GNUTLS_E_OCSP_RESPONSE_ERROR:
489 case GNUTLS_E_RANDOM_DEVICE_ERROR:
491 newerrno = EREMOTEIO;
504 /* Generate Diffie-Hellman parameters - for use with DHE
505 * kx algorithms. TODO: These should be discarded and regenerated
506 * once a day, once a week or once a month. Depending on the
507 * security requirements.
509 static gtls_error generate_dh_params (void) {
511 int gtls_errno = GNUTLS_E_SUCCESS;
512 bits = gnutls_sec_param_to_pk_bits (
514 GNUTLS_SEC_PARAM_LEGACY);
515 //TODO// Acquire DH-params lock
516 E_g2e ("Failed to initialise DH params",
517 gnutls_dh_params_init (
519 E_g2e ("Failed to generate DH params",
520 gnutls_dh_params_generate2 (
523 //TODO// Release DH-params lock
527 /* Load Diffie-Hellman parameters from file - or generate them when load fails.
529 static gtls_error load_dh_params (void) {
530 gnutls_dh_params_t dhp;
531 gnutls_datum_t pkcs3;
532 char *filename = cfg_tls_dhparamfile ();
533 int gtls_errno = GNUTLS_E_SUCCESS;
534 memset (&pkcs3, 0, sizeof (pkcs3));
536 E_g2e ("No PKCS #3 PEM file with DH params",
540 E_gnutls_clear_errno ();
541 E_g2e ("Failed to initialise DH params",
542 gnutls_dh_params_init (
544 E_g2e ("Failed to import DH params from PKCS #3 PEM",
545 gnutls_dh_params_import_pkcs3 (
548 GNUTLS_X509_FMT_PEM));
549 E_gnutls_clear_errno ();
551 if (pkcs3.data != NULL) {
554 if (gtls_errno != GNUTLS_E_SUCCESS) {
556 // File failed to load, so try to generate fresh DH params
557 int gtls_errno_stack0;
558 gtls_errno = GNUTLS_E_SUCCESS;
559 tlog (TLOG_CRYPTO, LOG_DEBUG, "Failed to load DH params from %s; generating fresh parameters", filename);
560 E_g2e ("Failed to generate DH params",
561 generate_dh_params ());
562 gtls_errno_stack0 = gtls_errno;
563 //TODO// Acquire DH-params lock
564 E_g2e ("Failed to format DH params as PKCS #3 PEM",
565 gnutls_dh_params_export2_pkcs3 (
569 //TODO// Release DH-params lock
570 if ((gtls_errno == GNUTLS_E_SUCCESS) && (filename != NULL)) {
573 // Best effor file save -- readback will parse
574 pemf = fopen (filename, "w");
576 fwrite (pkcs3.data, 1, pkcs3.size, pemf);
578 tlog (TLOG_FILES, LOG_DEBUG, "Saved DH params to %s (best-effort)", filename);
580 E_gnutls_clear_errno ();
582 gtls_errno = gtls_errno_stack0;
584 gnutls_dh_params_t old_dh;
585 //TODO// Acquire DH-params lock
588 //TODO// Release DH-params lock
590 gnutls_dh_params_deinit (old_dh);
596 /* Remove DH parameters, to be used during program cleanup. */
597 static void remove_dh_params (void) {
599 gnutls_dh_params_deinit (dh_params);
605 /* A log printing function
607 void log_gnutls (int level, const char *msg) {
608 tlog (TLOG_TLS, level, "GnuTLS: %s", msg);
612 /* Implement the GnuTLS function for token insertion callback. This function
613 * refers back to the generic callback for token insertion.
615 int gnutls_token_callback (void *const userdata,
616 const char *const label,
618 if (token_callback (label, retry)) {
619 return GNUTLS_E_SUCCESS;
621 return GNUTLS_E_PKCS11_TOKEN_ERROR;
627 * Implement the GnuTLS function for PIN callback. This function calls
628 * the generic PIN callback operation.
630 int gnutls_pin_callback (void *userdata,
632 const char *token_url,
633 const char *token_label,
637 if (flags & GNUTLS_PIN_SO) {
638 return GNUTLS_E_USER_ERROR;
640 if (pin_callback (attempt, token_url, token_label, pin, pin_max)) {
643 return GNUTLS_E_PKCS11_PIN_ERROR;
648 /* Register a PKCS #11 provider with the GnuTLS environment. */
649 void starttls_pkcs11_provider (char *p11path) {
650 unsigned int token_seq = 0;
652 if (gnutls_pkcs11_add_provider (p11path, NULL) != 0) {
653 fprintf (stderr, "Failed to register PKCS #11 library %s with GnuTLS\n", p11path);
656 while (gnutls_pkcs11_token_get_url (token_seq, 0, &p11uri) == 0) {
658 fprintf (stderr, "DEBUG: Found token URI %s\n", p11uri);
660 //TODO// if (gnutls_pkcs11_token_get_info (p11uri, GNUTLS_PKCS11_TOKEN_LABEL-of-SERIAL-of-MANUFACTURER-of-MODEL, output, utput_size) == 0) { ... }
661 gnutls_free (p11uri);
664 //TODO// Select token by name (value)
665 //TODO// if PIN available then set it up
666 //TODO:WHY?// free_p11pin ();
669 static void cleanup_starttls_credentials (void);/* Defined below */
670 static void cleanup_starttls_validation (void); /* Defined below */
671 static int setup_starttls_credentials (void); /* Defined below */
673 /* The global and static setup function for the starttls functions.
675 void setup_starttls (void) {
677 int gtls_errno = GNUTLS_E_SUCCESS;
678 char *otfsigcrt, *otfsigkey;
680 // Setup configuration variables
681 maxpreauth = cfg_tls_maxpreauth ();
683 // Basic library actions
684 tlog (TLOG_TLS, LOG_DEBUG, "Compiled against GnuTLS version %s", GNUTLS_VERSION);
685 curver = gnutls_check_version (GNUTLS_VERSION);
686 tlog (TLOG_TLS, LOG_DEBUG, "Running against %s GnuTLS version %s", curver? "acceptable": "OLDER", curver? curver: gnutls_check_version (NULL));
687 E_g2e ("GnuTLS global initialisation failed",
688 gnutls_global_init ());
689 E_gnutls_clear_errno ();
690 E_g2e ("GnuTLS PKCS #11 initialisation failed",
692 GNUTLS_PKCS11_FLAG_MANUAL, NULL));
694 // Setup logging / debugging
695 if (cfg_log_level () == LOG_DEBUG) {
696 gnutls_global_set_log_function (log_gnutls);
697 gnutls_global_set_log_level (9);
700 // Setup callbacks for user communication
701 gnutls_pkcs11_set_token_function (gnutls_token_callback, NULL);
702 gnutls_pkcs11_set_pin_function (gnutls_pin_callback, NULL);
704 // Setup DH parameters
705 E_g2e ("Loading DH params failed",
708 // Setup shared credentials for all client server processes
709 E_g2e ("Failed to setup GnuTLS callback credentials",
710 setup_starttls_credentials ());
712 // Parse the default priority string
713 E_g2e ("Failed to setup NORMAL priority cache",
714 gnutls_priority_init (&priority_normal, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+COMP-NULL:+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:+ANON-ECDH:+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
715 // gnutls_priority_init (&priority_normal, "NORMAL:-RSA:+ANON-ECDH:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
717 // Try to setup on-the-fly signing key / certificate and gen a certkey
718 otfsigcrt = cfg_tls_onthefly_signcert ();
719 otfsigkey = cfg_tls_onthefly_signkey ();
720 fprintf (stderr, "DEBUG: gtls_errno = %d, otfsigcrt == %s, otfsigkey == %s\n", gtls_errno, otfsigcrt? otfsigcrt: "NULL", otfsigkey? otfsigkey: "NULL");
721 if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigcrt != NULL)) {
722 FILE *crtfile = NULL;
723 fprintf (stderr, "DEBUG: gtls_errno==%d when initialising onthefly_issuercrt\n", gtls_errno);
724 E_g2e ("Failed to initialise on-the-fly issuer certificate structure",
725 gnutls_x509_crt_init (&onthefly_issuercrt));
726 if (strncmp (otfsigcrt, "file:", 5) == 0) {
727 // Provisionary support for the "file:" prefix
730 crtfile = fopen (otfsigcrt, "r");
731 if (crtfile == NULL) {
732 E_g2e ("Failed to open on-the-fly issuer certificate file",
733 GNUTLS_E_FILE_ERROR);
734 fprintf (stderr, "DEBUG: gtls_errno==%d after failing to open file for onthefly_issuercrt\n", gtls_errno);
737 size_t len = fread (crt, 1, sizeof (crt), crtfile);
738 if (ferror (crtfile)) {
739 E_g2e ("Failed to read on-the-fly issuer certificate from file",
740 GNUTLS_E_FILE_ERROR);
741 } else if ((len >= sizeof (crt)) || !feof (crtfile)) {
742 E_g2e ("Unexpectedly long on-the-fly issuer certificate file",
743 GNUTLS_E_FILE_ERROR);
745 gnutls_datum_t cd = {
749 fprintf (stderr, "DEBUG: gtls_errno==%d before importing onthefly_issuercrt\n", gtls_errno);
750 E_g2e ("Failed to import on-the-fly certificate from file",
751 gnutls_x509_crt_import (onthefly_issuercrt, &cd, GNUTLS_X509_FMT_DER));
752 fprintf (stderr, "DEBUG: gtls_errno==%d after importing onthefly_issuercrt\n", gtls_errno);
757 if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigkey != NULL)) {
758 E_g2e ("Failed to initialise on-the-fly issuer private key structure",
759 gnutls_privkey_init (&onthefly_issuerkey));
760 fprintf (stderr, "DEBUG: before onthefly p11 import, gtlserrno = %d\n", gtls_errno);
761 E_g2e ("Failed to import pkcs11: URI into on-the-fly issuer private key",
762 gnutls_privkey_import_pkcs11_url (onthefly_issuerkey, otfsigkey));
763 fprintf (stderr, "DEBUG: after onthefly p11 import, gtlserrno = %d\n", gtls_errno);
765 fprintf (stderr, "DEBUG: When it matters, gtls_errno = %d, onthefly_issuercrt %s NULL, onthefly_issuerkey %s NULL\n", gtls_errno, onthefly_issuercrt?"!=":"==", onthefly_issuerkey?"!=":"==");
766 if ((gtls_errno == GNUTLS_E_SUCCESS) && (onthefly_issuercrt != NULL) && (onthefly_issuerkey != NULL)) {
767 E_g2e ("Failed to initialise on-the-fly certificate session key",
768 gnutls_x509_privkey_init (&onthefly_subjectkey));
769 E_g2e ("Failed to generate on-the-fly certificate session key",
770 gnutls_x509_privkey_generate (onthefly_subjectkey, GNUTLS_PK_RSA, 2048 /*TODO:FIXED*/, 0));
771 if (gtls_errno == GNUTLS_E_SUCCESS) {
772 tlog (TLOG_TLS, LOG_INFO, "Setup for on-the-fly signing with the TLS Pool");
774 tlog (TLOG_TLS, LOG_ERR, "Failed to setup on-the-fly signing (shall continue without it)");
775 gnutls_x509_privkey_deinit (onthefly_subjectkey);
776 onthefly_subjectkey = NULL;
779 gtls_errno = GNUTLS_E_SUCCESS;
780 E_gnutls_clear_errno ();
782 if (onthefly_subjectkey == NULL) {
783 if (onthefly_issuercrt != NULL) {
784 gnutls_x509_crt_deinit (onthefly_issuercrt);
785 onthefly_issuercrt = NULL;
787 if (onthefly_issuerkey != NULL) {
788 gnutls_privkey_deinit (onthefly_issuerkey);
789 onthefly_issuerkey = NULL;
793 // Finally, check whether there was any error setting up GnuTLS
794 if (gtls_errno != GNUTLS_E_SUCCESS) {
795 tlog (TLOG_TLS, LOG_CRIT, "FATAL: GnuTLS setup failed: %s", gnutls_strerror (gtls_errno));
799 //MOVED// // Setup the management databases
800 //MOVED// tlog (TLOG_DB, LOG_DEBUG, "Setting up management databases");
801 //MOVED// E_e2e ("Failed to setup management databases",
802 //MOVED// setup_management ());
803 //MOVED// if (errno != 0) {
804 //MOVED// tlog (TLOG_DB, LOG_CRIT, "FATAL: Management databases setup failed: %s", strerror (errno));
809 /* Cleanup the structures and resources that were setup for handling TLS.
811 void cleanup_starttls (void) {
812 //MOVED// cleanup_management ();
813 if (onthefly_subjectkey != NULL) {
814 gnutls_x509_privkey_deinit (onthefly_subjectkey);
815 onthefly_subjectkey = NULL;
817 if (onthefly_issuercrt != NULL) {
818 gnutls_x509_crt_deinit (onthefly_issuercrt);
819 onthefly_issuercrt = NULL;
821 if (onthefly_issuerkey != NULL) {
822 gnutls_privkey_deinit (onthefly_issuerkey);
823 onthefly_issuerkey = NULL;
825 cleanup_starttls_credentials ();
827 gnutls_pkcs11_set_pin_function (NULL, NULL);
828 gnutls_pkcs11_set_token_function (NULL, NULL);
829 gnutls_pkcs11_deinit ();
830 gnutls_priority_deinit (priority_normal);
831 gnutls_global_deinit ();
836 * The copycat function is a bidirectional transport between the given
837 * remote and local sockets, but it will encrypt traffic from local to
838 * remote, and decrypt traffic from remote to local. It will do this
839 * until one of the end points is shut down, at which time it will
840 * return and assume the context will close down both pre-existing
843 * This copycat actually has a few sharp claws to watch for -- shutdown
844 * of sockets may drop the last bit of information sent. First, the
845 * signal POLLHUP is best ignored because it travels asynchronously.
846 * Second, reading 0 is a good indicator of end-of-file and may be
847 * followed by an shutdown of reading from that stream. But, more
848 * importantly, the other side must have this information forwarded
849 * so it can shutdown. This means that a shutdown for writing to that
850 * stream is to be sent. Even when *both* sides have agreed to not send
851 * anything, they may still not have received all they were offered for
852 * reading, so we should SO_LINGER on the sockets so they can acknowledge,
853 * and after a timeout we can establish that shutdown failed and log and
854 * return an error for it.
855 * Will you believe that I had looked up if close() would suffice? The man
856 * page clearly stated yes. However, these articles offer much more detail:
857 * http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable
858 * http://www.greenend.org.uk/rjk/tech/poll.html
860 * This function blocks during its call to poll(), in a state that can easily
861 * be restarted. This is when thread cancellation is temporarily enabled.
862 * Other threads may use this to cancel the thread and have it joined with that
863 * thread which will subsume its tasks and restart the handshake. We might
864 * later make this more advanced, by using a cancel stack push/pull mechanisms
865 * to ensure that recv() always results in send() in spite of cancellation.
867 * The return value of copycat is a GNUTLS_E_ code, usually GNUTLS_E_SUCCESS.
868 * For the moment, only one special value is of concern, namely
869 * GNUTLS_E_REHANDSHAKE which client or server side may receive when an
870 * attempt is made to renegotiate the security of the connection.
872 static int copycat (int local, int remote, gnutls_session_t wrapped, pool_handle_t client) {
874 struct pollfd inout [3];
876 struct linger linger = { 1, 10 };
878 int retval = GNUTLS_E_SUCCESS;
880 client = INVALID_POOL_HANDLE;
881 inout [0].fd = local;
882 inout [1].fd = remote;
886 inout [2].fd = client;
887 have_client = inout [2].fd != INVALID_POOL_HANDLE;
890 inout [2].revents = 0; // Will not be written by poll
891 //FORK!=DETACH// inout [2].fd = ctlkey_signalling_fd;
893 inout [0].events = POLLIN;
894 inout [1].events = POLLIN;
895 inout [2].events = 0; // error events only
896 tlog (TLOG_COPYCAT, LOG_DEBUG, "Starting copycat cycle for local=%d, remote=%d, control=%d", local, remote, client);
897 while (((inout [0].events | inout [1].events) & POLLIN) != 0) {
899 assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) == 0);
900 pthread_testcancel (); // Efficiency & Certainty
901 polled = poll (inout, have_client? 3: 2, -1);
902 assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
904 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat polling returned an error");
905 break; // Polling sees an error
907 if (inout [0].revents & POLLIN) {
908 // Read local and encrypt to remote
909 sz = recv (local, buf, sizeof (buf), RECV_FLAGS);
910 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d local bytes (or error<0) from %d", (int) sz, local);
912 tlog (TLOG_COPYCAT, LOG_ERR, "Error while receiving: %s", strerror (errno));
913 break; // stream error
914 } else if (sz == 0) {
915 inout [0].events &= ~POLLIN;
916 shutdown (local, SHUT_RD);
918 setsockopt (remote, SOL_SOCKET, SO_LINGER, (const char *) &linger, sizeof (linger));
919 #else /* WINDOWS_PORT */
920 setsockopt (remote, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
921 #endif /* WINDOWS_PORT */
922 gnutls_bye (wrapped, GNUTLS_SHUT_WR);
923 } else if (gnutls_record_send (wrapped, buf, sz) != sz) {
924 tlog (TLOG_COPYCAT, LOG_ERR, "gnutls_record_send() failed to pass on the requested bytes");
925 break; // communication error
927 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to remote %d", (int) sz, remote);
930 if (inout [1].revents & POLLIN) {
931 // Read remote and decrypt to local
932 sz = gnutls_record_recv (wrapped, buf, sizeof (buf));
933 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d remote bytes from %d (or error if <0)", (int) sz, remote);
935 //TODO// Process GNUTLS_E_REHANDSHAKE
936 if (sz == GNUTLS_E_REHANDSHAKE) {
937 tlog (TLOG_TLS, LOG_INFO, "Received renegotiation request over TLS handle %d", remote);
938 retval = GNUTLS_E_REHANDSHAKE;
940 } else if (gnutls_error_is_fatal (sz)) {
941 tlog (TLOG_TLS, LOG_ERR, "GnuTLS fatal error: %s", gnutls_strerror (sz));
942 break; // stream error
944 tlog (TLOG_TLS, LOG_INFO, "GnuTLS recoverable error: %s", gnutls_strerror (sz));
946 } else if (sz == 0) {
947 inout [1].events &= ~POLLIN;
948 shutdown (remote, SHUT_RD);
950 setsockopt (local, SOL_SOCKET, SO_LINGER, (const char *) &linger, sizeof (linger));
951 #else /* WINDOWS_PORT */
952 setsockopt (local, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
953 #endif /* WINDOWS_PORT */
954 shutdown (local, SHUT_WR);
955 } else if (send (local, buf, sz, RECV_FLAGS) != sz) {
956 break; // communication error
958 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to local %d", (int) sz, local);
961 inout [0].revents &= ~(POLLIN | POLLHUP); // Thy copying cat?
962 inout [1].revents &= ~(POLLIN | POLLHUP); // Retract thee claws!
963 if ((inout [0].revents | inout [1].revents) & ~POLLIN) {
964 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat data connection polling returned a special condition");
965 break; // Apparently, one of POLLERR, POLLHUP, POLLNVAL
968 if (inout [2].revents & ~POLLIN) {
970 // This case is currently not ever triggered
971 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat control connection polling returned a special condition");
972 break; // Apparently, one of POLLERR, POLLHUP, POLLNVAL
974 inout [2].fd = client;
975 have_client = inout [2].fd >= 0;
977 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal to set control fd to %d", inout [2].fd);
979 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal that could be ignored");
984 #endif /* !WINDOWS_PORT */
986 tlog (TLOG_COPYCAT, LOG_DEBUG, "Ending copycat cycle for local=%d, remote=%d", local, remote);
991 /* The callback function that retrieves certification information from either
992 * the client or the server in the course of the handshake procedure.
994 gtls_error clisrv_cert_retrieve (gnutls_session_t session,
995 const gnutls_datum_t* req_ca_dn,
997 const gnutls_pk_algorithm_t* pk_algos,
999 gnutls_pcert_st** pcert,
1000 unsigned int *pcert_length,
1001 gnutls_privkey_t *pkey) {
1002 gnutls_certificate_type_t certtp;
1003 gnutls_pcert_st *pc = NULL;
1004 struct command *cmd;
1006 gnutls_datum_t privdatum = { NULL, 0 };
1007 gnutls_datum_t certdatum = { NULL, 0 };
1008 gnutls_openpgp_crt_t pgpcert = NULL;
1009 gnutls_openpgp_privkey_t pgppriv = NULL;
1010 int gtls_errno = GNUTLS_E_SUCCESS;
1014 char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.localid)];
1015 size_t snilen = sizeof (sni);
1022 gtls_error fetch_local_credentials (struct command *cmd);
1023 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum);
1026 // Setup a number of common references and structures
1028 cmd = (struct command *) gnutls_session_get_ptr (session);
1030 E_g2e ("No data pointer with session",
1031 GNUTLS_E_INVALID_SESSION);
1034 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
1035 lidrole = LID_ROLE_CLIENT;
1037 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
1038 lidrole = LID_ROLE_SERVER;
1041 E_g2e ("TLS Pool command supports neither local client nor local server role",
1042 GNUTLS_E_INVALID_SESSION);
1045 lid = cmd->cmd.pio_data.pioc_starttls.localid;
1046 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1049 // On a server, lookup the server name and match it against lid.
1050 // TODO: For now assume a single server name in SNI (as that is normal).
1051 if (lidrole == LID_ROLE_SERVER) {
1052 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) || (snitype != GNUTLS_NAME_DNS)) {
1053 E_g2e ("Requested SNI error or not a DNS name",
1054 GNUTLS_E_NO_CERTIFICATE_FOUND);
1059 for (atidx=128; atidx > 0; atidx--) {
1060 if (lid [atidx-1] == '@') {
1064 if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
1065 tlog (TLOG_TLS, LOG_ERR, "SNI %s does not match preset local identity %s", sni, lid);
1066 E_g2e ("Requested SNI does not match local identity",
1067 GNUTLS_E_NO_CERTIFICATE_FOUND);
1071 // TODO: Should ask for permission before accepting SNI
1072 memcpy (lid, sni, sizeof (sni));
1077 // Setup the lidtype parameter for responding
1078 certtp = gnutls_certificate_type_get (session);
1079 if (certtp == GNUTLS_CRT_OPENPGP) {
1080 tlog (TLOG_TLS, LOG_INFO, "Serving OpenPGP certificate request as a %s", rolestr);
1081 lidtype = LID_TYPE_PGP;
1082 } else if (certtp == GNUTLS_CRT_X509) {
1083 tlog (TLOG_TLS, LOG_INFO, "Serving X.509 certificate request as a %s", rolestr);
1084 lidtype = LID_TYPE_X509;
1086 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1087 tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate retrieval attempted as a %s", rolestr);
1088 E_g2e ("Requested certtype is neither X.509 nor OpenPGP",
1089 GNUTLS_E_CERTIFICATE_ERROR);
1094 // Find the prefetched local identity to use towards this remote
1095 // Send a callback to the user if none is available and accessible
1096 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_CHECK) {
1097 uint32_t oldcmd = cmd->cmd.pio_cmd;
1098 struct command *resp;
1099 cmd->cmd.pio_cmd = PIOC_STARTTLS_LOCALID_V2;
1100 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_STARTTLS_LOCALID_V2");
1101 resp = send_callback_and_await_response (cmd, 0);
1102 assert (resp != NULL); // No timeout, should be non-NULL
1103 if (resp->cmd.pio_cmd != PIOC_STARTTLS_LOCALID_V2) {
1104 tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
1105 cmd->cmd.pio_cmd = oldcmd;
1106 return GNUTLS_E_CERTIFICATE_ERROR;
1108 assert (resp == cmd); // No ERROR, so should be the same
1109 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that sets plainfd:=%d and lid:=\"%s\" for rid==\"%s\"", cmd->passfd, lid, rid);
1110 cmd->cmd.pio_cmd = oldcmd;
1112 // Check that new rid is a generalisation of original rid
1113 // Note: This is only of interest for client operation
1114 if (lidrole == LID_ROLE_CLIENT) {
1115 selector_t newrid = donai_from_stable_string (rid, strlen (rid));
1116 donai_t oldrid = donai_from_stable_string (cmd->orig_starttls->remoteid, strlen (cmd->orig_starttls->remoteid));
1117 if (!donai_matches_selector (&oldrid, &newrid)) {
1118 return GNUTLS_E_NO_CERTIFICATE_FOUND;
1122 // Now reiterate to lookup lid credentials in db_localid
1123 E_g2e ("Missing local credentials",
1124 fetch_local_credentials (cmd));
1126 if (cmd->lids [lidtype - LID_TYPE_MIN].data == NULL) {
1127 fprintf (stderr, "DEBUG: Missing certificate for local ID %s and remote ID %s\n", lid, rid);
1128 E_g2e ("Missing certificate for local ID",
1129 GNUTLS_E_NO_CERTIFICATE_FOUND);
1134 // Split the credential into its various aspects
1135 ok = dbcred_interpret (
1136 &cmd->lids [lidtype - LID_TYPE_MIN],
1141 tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, p11priv=\"%s\", cert.size=%d", flags, p11priv, certdatum.size);
1142 //TODO// ok = ok && verify_cert_... (...); -- keyidlookup
1144 gtls_errno = GNUTLS_E_CERTIFICATE_ERROR;
1148 // Allocate response structures
1150 *pcert = load_certificate_chain (flags, pcert_length, &certdatum);
1151 if (*pcert == NULL) {
1152 E_g2e ("Failed to load certificate chain",
1153 GNUTLS_E_CERTIFICATE_ERROR);
1156 cmd->session_certificate = (intptr_t) (void *) *pcert; //TODO// Used for session cleanup
1159 // Setup private key
1160 E_g2e ("Failed to initialise private key",
1161 gnutls_privkey_init (
1163 if ((onthefly_subjectkey != NULL) && (strcmp (p11priv, onthefly_p11uri) == 0)) {
1164 E_g2e ("Failed to import on-the-fly subject private key",
1165 gnutls_privkey_import_x509 (
1167 onthefly_subjectkey,
1168 GNUTLS_PRIVKEY_IMPORT_COPY));
1170 if (gtls_errno == GNUTLS_E_SUCCESS) {
1171 cmd->session_privatekey = (intptr_t) (void *) *pkey; //TODO// Used for session cleanup
1173 E_g2e ("Failed to import PKCS #11 private key URI",
1174 gnutls_privkey_import_pkcs11_url (
1178 E_gnutls_clear_errno ();
1180 //TODO// Moved out (start)
1183 // Setup public key certificate
1186 E_g2e ("MOVED: Failed to import X.509 certificate into chain",
1187 gnutls_pcert_import_x509_raw (
1190 GNUTLS_X509_FMT_DER,
1194 E_g2e ("MOVED: Failed to import OpenPGP certificate",
1195 gnutls_pcert_import_openpgp_raw (
1198 GNUTLS_OPENPGP_FMT_RAW,
1199 NULL, /* use master key */
1203 /* Should not happen */
1207 //TODO// Moved out (end)
1210 // Lap up any overseen POSIX error codes in errno
1212 tlog (TLOG_TLS, LOG_DEBUG, "Failing TLS on errno=%d / %s", errno, strerror (errno));
1213 cmd->session_errno = errno;
1214 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
1218 // Return the overral error code, hopefully GNUTLS_E_SUCCESS
1219 tlog (TLOG_TLS, LOG_DEBUG, "Returning %d / %s from clisrv_cert_retrieve()", gtls_errno, gnutls_strerror (gtls_errno));
1220 fprintf (stderr, "DEBUG: clisrv_cert_retrieve() sets *pcert to 0x%xl (length %d)... {pubkey = 0x%lx, cert= {data = 0x%lx, size=%ld}, type=%ld}\n", (long) *pcert, *pcert_length, (long) (*pcert)->pubkey, (long) (*pcert)->cert.data, (long) (*pcert)->cert.size, (long) (*pcert)->type);
1224 /* Load a single certificate in the given gnutls_pcert_st from the given
1225 * gnutls_datum_t. Use the lidtype to determine how to do this.
1227 gtls_error load_certificate (int lidtype, gnutls_pcert_st *pcert, gnutls_datum_t *certdatum) {
1228 int gtls_errno = GNUTLS_E_SUCCESS;
1230 // Setup public key certificate
1233 fprintf (stderr, "DEBUG: About to import %d bytes worth of X.509 certificate into chain: %02x %02x %02x %02x...\n", certdatum->size, certdatum->data[0], certdatum->data[1], certdatum->data[2], certdatum->data[3]);
1234 E_g2e ("Failed to import X.509 certificate into chain",
1235 gnutls_pcert_import_x509_raw (
1238 GNUTLS_X509_FMT_DER,
1242 E_g2e ("Failed to import OpenPGP certificate",
1243 gnutls_pcert_import_openpgp_raw (
1246 GNUTLS_OPENPGP_FMT_RAW,
1247 NULL, /* use master key */
1251 /* Should not happen */
1258 /* Load a certificate chain. This returns a value for a retrieval function's
1259 * pcert, and also modifies the chainlen. The latter starts at 0, and is
1260 * incremented in a nested procedure that unrolls until all certificates are
1263 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum) {
1264 gnutls_pcert_st *chain;
1265 unsigned int mypos = *chainlen;
1266 int gtls_errno = GNUTLS_E_SUCCESS;
1269 // Quick and easy: No chaining required, just add the literal data.
1270 // Note however, this may be the end of a chain, so allocate all
1271 // structures and load the single one at the end.
1272 if ((flags & (LID_CHAINED | LID_NEEDS_CHAIN)) == 0) {
1274 chain = (gnutls_pcert_st *) calloc (*chainlen, sizeof (gnutls_pcert_st));
1275 if (chain != NULL) {
1278 (*chainlen) * sizeof (gnutls_pcert_st));
1280 gtls_errno = GNUTLS_E_MEMORY_ERROR;
1282 E_g2e ("Failed to load certificate into chain",
1284 flags & LID_TYPE_MASK,
1287 if (gtls_errno != GNUTLS_E_SUCCESS) {
1298 // First extended case. Chain certs in response to LID_CHAINED.
1299 // Recursive calls are depth-first, so we only add our first cert
1300 // after a recursive call succeeds. Any LID_NEEDS_CHAIN work is
1301 // added after LID_CHAINED, so is higher up in the hierarchy, but
1302 // it is loaded as part of the recursion. To support that, a
1303 // recursive call with certdatum.size==0 is possible when the
1304 // LID_NEEDS_CHAIN flag is set, and this section then skips.
1305 // Note that this code is also used to load the certificate chain
1306 // provided by LID_NEEDS_CHAIN, but by then the flag in a recursive
1307 // call is replaced with LID_CHAINED and no more LID_NEEDS_CHAIN.
1308 if (((flags & LID_CHAINED) != 0) && (certdatum->size > 0)) {
1311 gnutls_datum_t nextdatum;
1313 // Note: Accept BER because the outside SEQUENCE is not signed
1314 certlen = asn1_get_length_ber (
1315 ((char *) certdatum->data) + 1,
1318 certlen += 1 + lenlen;
1319 tlog (TLOG_CERT, LOG_DEBUG, "Found LID_CHAINED certificate size %d", certlen);
1320 if (certlen > certdatum->size) {
1321 tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate beyond data size %d", certdatum->size);
1324 } else if (certlen <= 0) {
1325 tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate of too-modest data size %d", certlen);
1329 nextdatum.data = ((char *) certdatum->data) + certlen;
1330 nextdatum.size = certdatum->size - certlen;
1331 certdatum->size = certlen;
1332 nextlen = asn1_get_length_ber (
1333 ((char *) nextdatum.data) + 1,
1336 nextlen += 1 + lenlen;
1337 if (nextlen == nextdatum.size) {
1338 // The last cert is loaded thinking it is not CHAINED,
1339 // but NEEDS_CHAIN can still be present for expansion.
1340 flags &= ~LID_CHAINED;
1343 chain = load_certificate_chain (flags, chainlen, &nextdatum);
1344 if (chain != NULL) {
1345 E_g2e ("Failed to add chained certificate",
1347 flags & LID_TYPE_MASK,
1350 if (gtls_errno != GNUTLS_E_SUCCESS) {
1360 // Second extended case. Chain certs in response to LID_NEEDS_CHAIN.
1361 // These are the highest-up in the hierarchy, above any LID_CHAINED
1362 // certificates. The procedure for adding them is looking them up
1363 // in a central database by their authority key identifier. What is
1364 // found is assumed to be a chain, and will be unrolled by replacing
1365 // the LID_NEEDS_CHAIN flag with LID_CHAINED and calling recursively.
1366 if (((flags & LID_NEEDS_CHAIN) != 0) && (certdatum->size == 0)) {
1367 //TODO//CODE// lookup new certdatum
1368 flags &= ~LID_NEEDS_CHAIN;
1369 flags |= LID_CHAINED;
1370 //TODO//CODE// recursive call
1371 //TODO//CODE// no structures to fill here
1372 //TODO//CODE// cleanup new certdatum
1376 // Final judgement. Nothing worked. Return failure.
1382 /********** VALIDATION EXPRESSION LINKUP TO GNUTLS **********/
1386 * The following functions implement the various validation expression
1387 * components in terms of the GnuTLS sessions of this code file.
1388 * Some work is repeated in various expression variables, notably the
1389 * lookup of a session's peer credentials, and possibly importing them
1390 * into X.509 structures. We may at some point decide to instead do
1391 * this ahead of time, ath the expense of some compleity and possibly
1392 * slow-down of the start of the computations.
1397 /* valexp_store_final -- store the valexp outcome in cmd->valexp_result.
1399 static void valexp_store_final (void *vcmd, struct valexp *ve, bool result) {
1400 ((struct command *) vcmd)->valexp_result = result;
1403 /* valexp_valflag_set -- set a validation flag bit for an uppercase predicate.
1405 static void valexp_valflag_set (struct command *cmd, char pred) {
1406 int len = strlen (cmd->valflags);
1407 cmd->valflags [len++] = pred;
1408 cmd->valflags [len ] = '\0';
1411 /* valexp_valflag_start -- get a prior set bit with validation information.
1412 * Where cmd->valflags is a string of uppercase letters that were ensured.
1414 static void valexp_valflag_start (void *vcmd, struct valexp *ve, char pred) {
1415 struct command *cmd = (struct command *) vcmd;
1416 pred &= 0xdf; // lowercase->uppercase
1417 valexp_setpredicate (ve, pred, NULL != strchr (cmd->valflags, pred));
1420 /* valexp_0_start -- validation function for the GnuTLS backend.
1421 * This function immediately sends failure on something impossible.
1423 static void valexp_0_start (void *vcmd, struct valexp *ve, char pred) {
1424 valexp_setpredicate (ve, pred, 0);
1427 /* valexp_1_start -- validation function for the GnuTLS backend.
1428 * This function immediately sends success on something trivial.
1430 static void valexp_1_start (void *vcmd, struct valexp *ve, char pred) {
1431 valexp_setpredicate (ve, pred, 1);
1434 //TODO// valexp_L_start, valexp_l_start
1436 /* valexp_I_start -- validation function for the GnuTLS backend.
1437 * This function ensures that the remote peer provides an identity.
1438 * TODO: We should compare the hostname as well, or compare if in remoteid
1439 * TODO: We may need to support more than just X509/PGP certificates
1441 static void valexp_I_start (void *vcmd, struct valexp *ve, char pred) {
1442 struct command *cmd = (struct command *) vcmd;
1444 ok = ok && (cmd->remote_auth_type == GNUTLS_CRD_CERTIFICATE);
1445 ok = ok && (cmd->remote_cert_count > 0);
1446 // Accept most certificates, but not for example GNUTLS_CRT_RAW
1448 #ifdef GNUTLS_CRT_KRB
1449 (cmd->remote_cert_type == GNUTLS_CRT_KRB) ||
1451 (cmd->remote_cert_type == GNUTLS_CRT_X509) ||
1452 (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) );
1453 // peer-returned "certs" points into GnuTLS' internal data structures
1454 valexp_setpredicate (ve, pred, ok);
1457 /* valexp_i_start -- is opportunistic and will always succeed
1459 #define valexp_i_start valexp_1_start
1461 /* valexp_Ff_start -- validation function for the GnuTLS backend.
1462 * This functin ensures that forward secrecy is applied.
1463 * While _F_ only accepts DHE, _f_ will also accept DH.
1464 * Note: GnuTLS does not seem to show DH that is not also DHE.
1466 static void valexp_Ff_start (void *vcmd, struct valexp *ve, char pred) {
1467 struct command *cmd = (struct command *) vcmd;
1468 gnutls_kx_algorithm_t kx = gnutls_kx_get (cmd->session);
1470 case GNUTLS_KX_UNKNOWN:
1472 case GNUTLS_KX_RSA_EXPORT:
1475 valexp_setpredicate (ve, pred, 0);
1477 case GNUTLS_KX_DHE_DSS:
1478 case GNUTLS_KX_DHE_RSA:
1480 case GNUTLS_KX_SRP_RSA:
1481 case GNUTLS_KX_SRP_DSS:
1482 case GNUTLS_KX_DHE_PSK:
1483 case GNUTLS_KX_ECDHE_RSA:
1484 case GNUTLS_KX_ECDHE_ECDSA:
1485 case GNUTLS_KX_ECDHE_PSK:
1486 case GNUTLS_KX_ANON_ECDH: // Assume DHE is in fact implemented
1487 case GNUTLS_KX_ANON_DH: // Assume DHE is in fact implemented
1488 valexp_setpredicate (ve, pred, 1);
1490 // case GNUTLS_KX_xxx_DH:
1491 // valexp_setpredicate (ve, pred, pred != 'F');
1496 /* valexp_A_start -- validation function for the GnuTLS backend.
1497 * This function ensures that an anonymising precursor is used.
1499 #define valexp_A_start valexp_valflag_start
1501 /* valexp_a_start -- is opportunistic and will always succeed */
1502 #define valexp_a_start valexp_1_start
1504 /* valexp_Tt_start -- validation function for the GnuTLS backend.
1505 * This function ensures trust based on a trusted certificate/key list.
1506 * In the _t_ case, self-signed certificates are also accepted.
1508 static void valexp_Tt_start (void *vcmd, struct valexp *ve, char pred) {
1509 struct command *cmd = (struct command *) vcmd;
1511 unsigned int vfyresult;
1514 if (cmd->vfystatus != 0) {
1517 if (cmd->remote_auth_type != GNUTLS_CRD_CERTIFICATE) {
1521 // Handle self-signed peer certificates in a special way
1522 if (cmd->remote_cert_count == 1) {
1524 bad = bad || (pred == 'T'); // Reject self-signed
1525 if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
1527 bad = bad || gnutls_x509_crt_verify (
1528 (gnutls_x509_crt_t ) cmd->remote_cert [0],
1529 (gnutls_x509_crt_t *) &cmd->remote_cert [0], 1,
1530 GNUTLS_VERIFY_DISABLE_CA_SIGN,
1532 // Apply the most stringent test. This includes all of
1533 // GNUTLS_CERT_INVALID (always set, often with others)
1534 // GNUTLS_CERT_NOT_ACTIVATED
1535 // GNUTLS_CERT_EXPIRED
1536 // GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE
1537 // GNUTLS_CERT_SIGNER_NOT_FOUND
1538 // GNUTLS_CERT_SIGNER_NOT_CA => oops...
1539 // stopped with GNUTLS_VERIFY_DISABLE_CA_SIGN
1540 // GNUTLS_CERT_SIGNATURE_FAILURE
1541 // GNUTLS_CERT_INSECURE_ALGORITHM
1542 bad = bad || (vfyresult != 0);
1547 } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
1548 //TODO// Prefer to actually check PGP self-signature
1549 //TODO// But only value is check private-key ownership
1552 #ifdef GNUTLS_CRT_KRB
1553 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
1554 // Kerberos has authenticated the ticket for us
1555 //TODO// Should we try reading from the ticket/auth?
1564 if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
1565 // Now check the certificate chain, taking CA bits into account
1566 for (i=1; i<cmd->remote_cert_count; i++) {
1568 bad = bad || gnutls_x509_crt_verify (
1569 (gnutls_x509_crt_t ) cmd->remote_cert [i-1],
1570 (gnutls_x509_crt_t *) &cmd->remote_cert [i], 1,
1573 // Apply the most stringent test. This includes all of
1574 // GNUTLS_CERT_INVALID (always set, often with others)
1575 // GNUTLS_CERT_NOT_ACTIVATED
1576 // GNUTLS_CERT_EXPIRED
1577 // GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE
1578 // GNUTLS_CERT_SIGNER_NOT_FOUND
1579 // GNUTLS_CERT_SIGNER_NOT_CA => oops...
1580 // stopped with GNUTLS_VERIFY_DISABLE_CA_SIGN
1581 // GNUTLS_CERT_SIGNATURE_FAILURE
1582 // GNUTLS_CERT_INSECURE_ALGORITHM
1583 bad = bad || (vfyresult != 0);
1585 } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
1586 ; //TODO// Check PGP direct signature (and also use in self-sig)
1587 #ifdef GNUTLS_CRT_KRB
1588 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
1589 ; // Trust has already been validated through Kerberos
1593 valexp_setpredicate (ve, pred, flagval);
1596 /* valexp_Dd_start -- validation function for the GnuTLS backend.
1597 * This function validates through DNSSEC.
1598 * While _D_ enforces DNSSEC, _d_ also accepts opted-out security.
1600 static void valexp_Dd_start (void *vcmd, struct valexp *ve, char pred) {
1601 struct command *cmd = (struct command *) vcmd;
1604 unsigned int vfystat;
1608 struct sockaddr peername;
1609 socklen_t peernamesz = sizeof (peername);
1611 host = strchr (cmd->cmd.pio_data.pioc_starttls.remoteid, '@');
1613 host = cmd->cmd.pio_data.pioc_starttls.remoteid;
1615 switch (cmd->cmd.pio_data.pioc_starttls.ipproto) {
1622 #ifndef WINDOWS_PORT
1630 sox = gnutls_transport_get_int (cmd->session);
1634 if (getpeername (sox, &peername, &peernamesz) != 0) {
1637 if ((peername.sa_family == AF_INET) &&
1638 (peernamesz == sizeof (struct sockaddr_in))) {
1639 port = ntohs (((struct sockaddr_in *) &peername)->sin_port);
1640 } else if ((peername.sa_family == AF_INET6) &&
1641 (peernamesz == sizeof (struct sockaddr_in6))) {
1643 port = ntohs (((struct sockaddr_in6 *) &peername)->sin6_port);
1646 //TODO// We might use online.c code instead?
1647 if (dane_state_init (&stat, /*TODO:*/ 0) != GNUTLS_E_SUCCESS) {
1650 if (dane_verify_session_crt (stat,
1656 DANE_VFLAG_FAIL_IF_NOT_CHECKED,
1657 &vfystat) == DANE_E_SUCCESS) {
1658 if ((pred == 'D') && (vfystat & DANE_VERIFY_UNKNOWN_DANE_INFO)) {
1659 dane_state_deinit (stat);
1662 flagval = ((vfystat & ~DANE_VERIFY_UNKNOWN_DANE_INFO) == 0);
1664 dane_state_deinit (stat);
1666 valexp_setpredicate (ve, pred, flagval);
1669 /* valexp_Rr_start -- validation function for the GnuTLS backend.
1670 * This function validates through a CRL.
1671 * While _R_ requires the CRL to be present, _r_ accepts confirmed absense.
1672 * TODO: This is not implemented yet.
1674 static void valexp_Rr_start (void *vcmd, struct valexp *ve, char pred) {
1676 valexp_setpredicate (ve, pred, 0);
1679 /* valexp_Ee_start -- validation function for the GnuTLS backend.
1680 * This function validates certificate extensions for the named service.
1681 * While _E_ required OIDs to be marked critical, _e_ also accepts non-crit.
1683 static void valexp_Ee_start (void *vcmd, struct valexp *ve, char pred) {
1685 valexp_setpredicate (ve, pred, 0);
1688 /* valexp_Oo_start -- validation function for the GnuTLS backend.
1689 * This function validates with online/live information.
1690 * While _O_ required positive confirmation, _o_ also accepts unknown.
1691 * -> For X.509, look in OCSP or CRL or Global Directory
1692 * -> For OpenPGP, redirect O->G, o->g
1693 * -> For Kerberos, accept anything as sufficiently live / online
1695 static void valexp_Oo_start (void *vcmd, struct valexp *ve, char pred) {
1696 struct command *cmd = (struct command *) vcmd;
1698 online2success_t o2vf;
1700 gnutls_datum_t *raw;
1701 if (cmd->remote_auth_type != GNUTLS_CRD_CERTIFICATE) {
1702 // No authentication types other than certificates yet
1705 if ((pred >= 'a') && (pred <= 'z')) {
1706 o2vf = online2success_optional;
1708 o2vf = online2success_enforced;
1710 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1711 raw = (gnutls_datum_t *) cmd->remote_cert_raw;
1712 if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
1713 valflag = o2vf (online_globaldir_pgp (
1715 raw->data, raw->size));
1716 } else if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
1717 // OCSP inquiry or globaldir
1718 valflag = o2vf (online_globaldir_x509 (
1720 raw->data, raw->size));
1721 #ifdef GNUTLS_CRT_KRB
1722 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
1723 // Kerberos is sufficiently "live" to always pass O
1728 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1733 valexp_setpredicate (ve, pred, valflag);
1736 /* valexp_Gg_start -- validation function for the GnuTLS backend.
1737 * This function validates through the LDAP global directory.
1738 * While _G_ requires information to be present, _g_ also accepts absense.
1739 * -> For X.509, lookup userCertificate
1740 * -> For OpenPGP, lookup pgpKey
1741 * -> For KDH, lookup krbPrincipalName
1742 * -> For SRP, nothing is defined
1743 * -> For OpenSSH, no TLS support
1745 static void valexp_Gg_start (void *vcmd, struct valexp *ve, char pred) {
1746 struct command *cmd = (struct command *) vcmd;
1748 online2success_t o2vf;
1750 gnutls_datum_t *raw;
1751 if (cmd->remote_auth_type != GNUTLS_CRD_CERTIFICATE) {
1752 // No authentication types other than certificates yet
1755 if ((pred >= 'a') && (pred <= 'z')) {
1756 o2vf = online2success_optional;
1758 o2vf = online2success_enforced;
1760 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1761 raw = (gnutls_datum_t *) cmd->remote_cert_raw;
1762 if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
1763 valflag = o2vf (online_globaldir_pgp (
1765 raw->data, raw->size));
1766 } else if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
1767 //TODO// OCSP inquiry or globaldir
1768 valflag = o2vf (online_globaldir_x509 (
1770 raw->data, raw->size));
1771 #ifdef GNUTLS_CRT_KRB
1772 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
1774 //TODO// valflag = o2vf (online_globaldir_kerberos (
1776 //TODO// raw->data, raw->size));
1779 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1784 valexp_setpredicate (ve, pred, valflag);
1787 /* valexp_Pp_start -- validation function for the GnuTLS backend.
1788 * This function validates through pinning information.
1789 * While _P_ requires pinning to be present, _p_ will Trust On First Use.
1791 static void valexp_Pp_start (void *vcmd, struct valexp *ve, char pred) {
1793 valexp_setpredicate (ve, pred, 0);
1796 /* valexp_U_start -- validation function for the GnuTLS backend.
1797 * This function validates a matching username.
1799 static void valexp_U_start (void *vcmd, struct valexp *ve, char pred) {
1801 valexp_setpredicate (ve, pred, 0);
1804 /* valexp_Ss_start -- validation function for the GnuTLS backend.
1805 * This function ensures that the local end is a server.
1806 * While _S_ denies credentials also usable for clients, _s_ permits them.
1808 static void valexp_Ss_start (void *vcmd, struct valexp *ve, char pred) {
1809 struct command *cmd = (struct command *) vcmd;
1811 if ((pred == 'S') && (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
1814 flagval = (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) != 0;
1816 valexp_setpredicate (ve, pred, flagval);
1819 /* valexp_Cc_start -- validation function for the GnuTLS backend.
1820 * This function ensures that the local end is a client.
1821 * While _C_ denies credentials also usable for servers, _c_ permits them.
1823 static void valexp_Cc_start (void *vcmd, struct valexp *ve, char pred) {
1824 struct command *cmd = (struct command *) vcmd;
1826 if ((pred == 'C') && (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)) {
1829 flagval = (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) != 0;
1831 valexp_setpredicate (ve, pred, flagval);
1835 static void valexp_error_start (void *handler_data, struct valexp *ve, char pred) {
1838 static void valexp_ignore_stop (void *handler_data, struct valexp *ve, char pred) {
1841 static void valexp_ignore_final (void *handler_data, struct valexp *ve, bool value) {
1846 /* Given a predicate, invoke its start routine.
1848 static void valexp_switch_start (void *handler_data, struct valexp *ve, char pred) {
1851 valexp_I_start (handler_data, ve, pred);
1854 valexp_i_start (handler_data, ve, pred);
1858 valexp_Ff_start (handler_data, ve, pred);
1861 valexp_A_start (handler_data, ve, pred);
1864 valexp_a_start (handler_data, ve, pred);
1868 valexp_Tt_start (handler_data, ve, pred);
1872 valexp_Dd_start (handler_data, ve, pred);
1876 valexp_Rr_start (handler_data, ve, pred);
1880 valexp_Ee_start (handler_data, ve, pred);
1884 valexp_Oo_start (handler_data, ve, pred);
1888 valexp_Gg_start (handler_data, ve, pred);
1892 valexp_Pp_start (handler_data, ve, pred);
1895 valexp_U_start (handler_data, ve, pred);
1899 valexp_Ss_start (handler_data, ve, pred);
1903 valexp_Cc_start (handler_data, ve, pred);
1906 // Called on an unregistered symbol, that spells failure
1907 valexp_setpredicate (ve, pred, 0);
1912 /* Return a shared constant structure for valexp_handling with GnuTLS.
1913 * This function does not fail; it always returns a non-NULL value.
1915 static const struct valexp_handling *have_starttls_validation (void) {
1916 static const struct valexp_handling starttls_valexp_handling = {
1917 .handler_start = valexp_switch_start,
1918 .handler_stop = valexp_ignore_stop,
1919 .handler_final = valexp_store_final,
1921 return &starttls_valexp_handling;
1926 /* If any remote credentials are noted, cleanup on them. This removes
1927 * any remote_cert[...] entries, counting up to remote_cert_count which
1928 * is naturally set to 0 initially, as well as after this has run.
1930 static void cleanup_any_remote_credentials (struct command *cmd) {
1931 while (cmd->remote_cert_count > 0) {
1932 gnutls_x509_crt_deinit (
1933 cmd->remote_cert [--cmd->remote_cert_count]);
1935 memset (cmd->remote_cert, 0, sizeof (cmd->remote_cert));
1938 /* Fetch remote credentials. This can be done after TLS handshaking has
1939 * completed, to find the certificates or other credentials provided by
1940 * the peer to establish its identity. The validation expression routines
1941 * can then refer to this resource, and won't have to request the same
1942 * information over and over again. To this end, the information is stored
1943 * in the session object. The arrays in which this information is stored
1944 * are size-constrained, but that is also a good security precaution.
1946 * The information ends up in the following variables:
1947 * - remote_auth_type
1948 * - remote_cert_type (if remote_auth_type == GNUTLS_CRD_CERTIFICATE)
1949 * - remote_cert[...] (if remote_cert_type == GNUTLS_CRD_CERTIFICATE)
1950 * - remote_cert_count is the number of entries in remote_cert (up to root)
1952 * When certificates are used, the root certificate is looked up, for
1955 * After running successfully, a call to cleanup_any_remote_credentials()
1956 * must be called to clean up any data in the cmd structure. This may be
1957 * done on cmd at any time after initialisation, even multiple times and
1958 * even when this call fails. This call actually cleans up anything it
1959 * setup in the past, before setting up the data anew.
1961 static gtls_error fetch_remote_credentials (struct command *cmd) {
1962 gtls_error gtls_errno = GNUTLS_E_SUCCESS;
1963 const gnutls_datum_t *certs;
1964 unsigned int num_certs;
1965 gnutls_x509_crt_t x509peers [11]; // Peers + Root for GNUTLS_CRT_X509
1970 // Did we run this before? Then cleanup.
1971 cleanup_any_remote_credentials (cmd);
1972 //INVOLVES// memset (cmd->remote_cert, 0, sizeof (cmd->remote_cert));
1973 //INVOLVES// cmd->remote_cert_count = 0;
1974 // Prepare as-yet-unset default return values
1975 cmd->remote_auth_type = -1;
1976 cmd->remote_cert_raw = NULL;
1978 // Obtain the authentication type for the peer
1979 cmd->remote_auth_type = gnutls_auth_get_type (cmd->session);
1980 switch (cmd->remote_auth_type) {
1981 case GNUTLS_CRD_CERTIFICATE:
1982 // Continue loading certificates in the GnuTLS format
1984 case GNUTLS_CRD_ANON:
1985 // No basis for any identity claim
1986 cmd->cmd.pio_data.pioc_starttls.remoteid [0] = '\0';
1987 return GNUTLS_E_SUCCESS;
1988 case GNUTLS_CRD_SRP:
1989 return GNUTLS_E_SUCCESS;
1990 case GNUTLS_CRD_PSK:
1991 return GNUTLS_E_SUCCESS;
1993 return GNUTLS_E_AUTH_ERROR;
1996 // Continue loading the certificate information: X.509, PGP, ...
1997 cmd->remote_cert_type = gnutls_certificate_type_get (cmd->session);
1998 certs = gnutls_certificate_get_peers (cmd->session, &num_certs);
1999 if (certs == NULL) {
2002 // "certs" points into GnuTLS' internal data structures
2003 if ((num_certs < 1) || (num_certs > CERTS_MAX_DEPTH)) {
2004 return GNUTLS_E_AUTH_ERROR;
2006 cmd->remote_cert_raw = (void *) &certs [0];
2008 // Turn certificate data into GnuTLS' data structures (to be cleaned)
2009 if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
2010 peer_tad = TAD_TYPE_X509;
2011 for (i=0; i < num_certs; i++) {
2012 E_g2e ("Failed to initialise peer X.509 certificate",
2013 gnutls_x509_crt_init (
2014 (gnutls_x509_crt_t *) &cmd->remote_cert [i]));
2015 if (gtls_errno == GNUTLS_E_SUCCESS) {
2016 cmd->remote_cert_count++;
2018 E_g2e ("Failed to import peer X.509 certificate",
2019 gnutls_x509_crt_import (
2020 cmd->remote_cert [i],
2021 &certs [i], GNUTLS_X509_FMT_DER));
2023 if (gtls_errno != GNUTLS_E_SUCCESS) {
2026 } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
2027 peer_tad = TAD_TYPE_PGP;
2028 E_g2e ("Failed to initialise peer PGP key",
2029 gnutls_x509_crt_init (
2030 (gnutls_x509_crt_t *) &cmd->remote_cert [0]));
2031 if (gtls_errno == GNUTLS_E_SUCCESS) {
2032 cmd->remote_cert_count = 1;
2034 E_g2e ("Failed to import peer PGP key",
2035 gnutls_openpgp_crt_import (
2036 cmd->remote_cert [0],
2037 &certs [0], GNUTLS_OPENPGP_FMT_RAW));
2038 if (gtls_errno != GNUTLS_E_SUCCESS) {
2044 // Lookup the trusted party that the peers certificates is promoting.
2045 // Note that even if the peer ends in a CA cert (which it may not
2046 // always send along) then we can still add it ourselves again :-)
2047 // Only worry might be that CA certs require no AuthorityKeyIdentifier.
2048 if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
2049 // Retrieve the AuthorityKeyIdentifier from last (or semi-last)
2054 DBC *crs_trust = NULL;
2056 gnutls_datum_t anchor_gnutls;
2057 gnutls_x509_crt_t dbroot;
2058 dbt_init_empty (&rootca);
2059 dbt_init_empty (&anchor);
2061 gtls_errno = gnutls_x509_crt_get_authority_key_id (
2062 cmd->remote_cert [cmd->remote_cert_count-1],
2065 if (gtls_errno == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2066 // Only retry if the last is a signer, possibly CA
2067 if (cmd->remote_cert_count == 1) {
2068 // Permit self-signed certificate evaluation
2069 gtls_errno = GNUTLS_E_SUCCESS;
2070 } else if (cmd->remote_cert_count > 1) {
2071 // Assume the last is a root cert, as it lacks authid
2072 gnutls_x509_crt_deinit (
2073 cmd->remote_cert [--cmd->remote_cert_count]);
2074 cmd->remote_cert [cmd->remote_cert_count] = NULL;
2076 gtls_errno = gnutls_x509_crt_get_authority_key_id (
2077 cmd->remote_cert [cmd->remote_cert_count-1],
2082 if (gtls_errno != GNUTLS_E_SUCCESS) {
2085 // Get root cert from trustdb into remote_cert [_count++]
2086 dbt_init_fixbuf (&rootca, id, idsz);
2087 dbt_init_malloc (&anchor);
2088 E_d2e ("Failed to create db_disclose cursor",
2094 E_d2e ("X.509 authority key identifier not found in trust database",
2096 crs_trust, &rootca, &anchor));
2097 while (db_errno == 0) {
2098 // Process "anchor" entry (inasfar as meaningful)
2099 uint32_t anchorflags;
2102 char *valexp; //TODO// Initiate this before cleanup
2103 int tstatus = trust_interpret (&anchor, &anchorflags, &valexp, &trustdata, &trustdatalen);
2105 if (tstatus != TAD_STATUS_SUCCESS) {
2106 // Signal any DB error to bail out of this loop
2107 db_errno = DB_KEYEMPTY;
2108 } else if ((anchorflags & TAD_TYPE_MASK) != peer_tad) {
2109 ; // Skip unsought trust database entry
2110 } else if ((anchorflags & TAD_TYPE_MASK) == TAD_TYPE_X509) {
2111 E_g2e ("Certificate chain too long",
2112 (cmd->remote_cert_count >= CERTS_MAX_DEPTH)
2113 ? GNUTLS_E_AUTH_ERROR
2114 : GNUTLS_E_SUCCESS);
2115 // Turn the anchor into an X.509 certificate
2116 E_g2e ("Failet to initialise X.509 peer trust anchor",
2117 gnutls_x509_crt_init ((gnutls_x509_crt_t *) &cmd->remote_cert [cmd->remote_cert_count]));
2118 if (gtls_errno == GNUTLS_E_SUCCESS) {
2119 cmd->remote_cert_count++;
2120 anchor_gnutls.data = anchor.data;
2121 anchor_gnutls.size = anchor.size;
2122 E_g2e ("Failed to import X.509 peer trust anchor",
2123 gnutls_x509_crt_import (cmd->remote_cert [cmd->remote_cert_count-1], &anchor_gnutls, GNUTLS_X509_FMT_DER));
2125 if (gtls_errno == GNUTLS_E_SUCCESS) {
2126 // Everything worked, we have a chain
2128 if (cmd->trust_valexp) {
2129 free (cmd->trust_valexp);
2131 cmd->trust_valexp = strdup (valexp);
2133 // Signal arbitrary DB error
2134 db_errno = DB_KEYEMPTY;
2136 } else if ((anchorflags & TAD_TYPE_MASK) == TAD_TYPE_REVOKE_X509) {
2137 //TODO// Possibly verify end cert revocation
2139 /* Ignore entry, continue with the next */;
2141 db_errno = dba_trust_iterate (crs_trust, &rootca, &anchor);
2143 if (crs_trust != NULL) {
2144 crs_trust->close (crs_trust);
2148 // No dbt_free (&rootca) because it is set to a fixed buffer
2149 if (db_errno != DB_NOTFOUND) {
2152 } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
2153 ; //TODO// Attempt to load PGP direct signer(s)
2154 ; //OPTION// May use the _count for alternative signers!
2155 ; //OPTION// May setup/reload a keyring based on trust.db
2156 #ifdef GNUTLS_CRT_KRB
2157 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
2158 ; //TODO// Process as appropriate for Kerberos (store Ticket?)
2162 // Cleanup (when returning an error code) and return
2164 if (gtls_errno != GNUTLS_E_SUCCESS) {
2165 cleanup_any_remote_credentials (cmd);
2167 while ((!got_chain) && (cmd->remote_cert_count > 1)) {
2168 --cmd->remote_cert_count;
2169 gnutls_x509_crt_deinit (
2170 cmd->remote_cert [cmd->remote_cert_count]);
2171 cmd->remote_cert [cmd->remote_cert_count] = NULL;
2177 /* Fetch local credentials. This can be done before TLS is started, to find
2178 * the possible authentication forms that can be offered. The function
2179 * can additionally be used after interaction with the client to establish
2180 * a local identity that was not initially provided, or that was not
2181 * considered public at the time.
2183 gtls_error fetch_local_credentials (struct command *cmd) {
2186 DBC *crs_disclose = NULL;
2187 DBC *crs_localid = NULL;
2191 selector_t remote_selector;
2195 gtls_error certificate_onthefly (struct command *cmd);
2198 // When applicable, try to create an on-the-fly certificate
2199 if (((cmd->cmd.pio_cmd == PIOC_STARTTLS_V2) &&
2200 (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_ONTHEFLY))
2201 || ((cmd->cmd.pio_cmd == PIOC_LIDENTRY_CALLBACK_V2) &&
2202 (cmd->cmd.pio_data.pioc_lidentry.flags & PIOF_LIDENTRY_ONTHEFLY))) {
2203 gtls_errno = certificate_onthefly (cmd);
2204 if (gtls_errno != GNUTLS_E_AGAIN) {
2205 // This includes GNUTLS_E_SUCCESS
2206 fprintf (stderr, "DEBUG: otfcert retrieval returned %d\n", gtls_errno);
2209 fprintf (stderr, "DEBUG: otfcert retrieval returned GNUTLS_E_AGAIN, so skip it\n", gtls_errno);
2210 gtls_errno = GNUTLS_E_SUCCESS; // Attempt failed, ignore
2215 // Setup a number of common references and structures
2216 // Note: Current GnuTLS cannot support being a peer
2217 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
2218 lidrole = LID_ROLE_CLIENT;
2219 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
2220 lidrole = LID_ROLE_SERVER;
2222 E_g2e ("TLS Pool command supports neither local client nor local server role",
2223 GNUTLS_E_INVALID_SESSION);
2226 lid = cmd->cmd.pio_data.pioc_starttls.localid;
2227 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
2230 // Refuse to disclose client credentials when the server name is unset;
2231 // note that server-claimed identities are unproven during handshake.
2232 if ((lidrole == LID_ROLE_CLIENT) && (*rid == '\0')) {
2233 tlog (TLOG_USER, LOG_ERR, "No remote identity (server name) set, so no client credential disclosure");
2234 E_g2e ("Missing remote ID",
2235 GNUTLS_E_NO_CERTIFICATE_FOUND);
2239 // Setup database iterators to map identities to credentials
2240 if (lidrole == LID_ROLE_CLIENT) {
2241 E_d2e ("Failed to create db_disclose cursor",
2242 dbh_disclose->cursor (
2248 E_d2e ("Failed to create db_localid cursor",
2249 dbh_localid->cursor (
2255 // Prepare for iteration over possible local identities / credentials
2258 if (gtls_errno != 0) {
2260 } else if (lidrole == LID_ROLE_CLIENT) {
2261 memcpy (cid, rid, sizeof (cid));
2262 dbt_init_fixbuf (&discpatn, cid, strlen (cid));
2263 dbt_init_fixbuf (&keydata, mid, sizeof (mid)-1);
2264 dbt_init_malloc (&creddata);
2266 donai_t remote_donai = donai_from_stable_string (rid, strlen (rid));
2267 if (!selector_iterate_init (&remote_selector, &remote_donai)) {
2268 E_g2e ("Syntax of remote ID unsuitable for selector",
2269 GNUTLS_E_INVALID_REQUEST);
2271 E_d2e ("Failed to start iterator on remote ID selector",
2272 dbcred_iterate_from_remoteid_selector (
2281 dbt_init_fixbuf (&discpatn, "", 0); // Unused but good style
2282 dbt_init_fixbuf (&keydata, lid, strlen (lid));
2283 dbt_init_malloc (&creddata);
2284 E_d2e ("Failed to start iterator on local ID",
2285 dbcred_iterate_from_localid (
2290 if (db_errno != 0) {
2291 gtls_errno = GNUTLS_E_DB_ERROR;
2295 // Now store the local identities inasfar as they are usable
2297 while ((gtls_errno == GNUTLS_E_SUCCESS) && (db_errno == 0)) {
2302 tlog (TLOG_DB, LOG_DEBUG, "Found BDB entry %s disclosed to %s", creddata.data + 4, (lidrole == LID_ROLE_CLIENT)? rid: "all clients");
2306 lidtype = flags & LID_TYPE_MASK;
2307 ok = ok && ((flags & lidrole) != 0);
2308 ok = ok && ((flags & LID_NO_PKCS11) == 0);
2309 ok = ok && (lidtype >= LID_TYPE_MIN);
2310 ok = ok && (lidtype <= LID_TYPE_MAX);
2311 tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, so we (%04x/%04x) %s it", flags, lidrole, LID_ROLE_MASK, ok? "store": "skip ");
2313 // Move the credential into the command structure
2314 dbt_store (&creddata,
2315 &cmd->lids [lidtype - LID_TYPE_MIN]);
2318 // Skip the credential by freeing its data structure
2319 dbt_free (&creddata);
2321 db_errno = dbcred_iterate_next (crs_disclose, crs_localid, &discpatn, &keydata, &creddata);
2324 if (db_errno == DB_NOTFOUND) {
2326 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
2329 if (crs_localid != NULL) {
2330 crs_localid->close (crs_localid);
2333 if (crs_disclose != NULL) {
2334 crs_disclose->close (crs_disclose);
2335 crs_disclose = NULL;
2342 * Check if a given cmd has the given LID_TYPE setup.
2343 * Return 1 for yes or 0 for no; this is used in priority strings.
2345 static inline int lidtpsup (struct command *cmd, int lidtp) {
2346 return 1; //TODO// Can we decide if we needn't authenticate?
2347 return cmd->lids [lidtp - LID_TYPE_MIN].data != NULL;
2350 /* Configure the GnuTLS session with suitable credentials and priority string.
2351 * The anonpre_ok flag should be non-zero to permit Anonymous Precursor.
2353 * The credential setup is optional; when creds is NULL, no changes will
2356 static int configure_session (struct command *cmd,
2357 gnutls_session_t session,
2358 struct credinfo *creds,
2362 int gtls_errno = GNUTLS_E_SUCCESS;
2364 // Install the shared credentials for the client or server role
2365 if (creds != NULL) {
2366 gnutls_credentials_clear (session);
2367 for (i=0; i<credcount; i++) {
2368 E_g2e ("Failed to install credentials into TLS session",
2369 gnutls_credentials_set (
2376 // Setup the priority string for this session; this avoids future
2377 // credential callbacks that ask for something impossible or
2380 // Variation factors:
2381 // - starting configuration (can it be empty?)
2382 // - Configured security parameters (database? variable?)
2383 // - CTYPEs, SRP, ANON-or-not --> fill in as + or - characters
2384 if (gtls_errno == GNUTLS_E_SUCCESS) {
2386 snprintf (priostr, sizeof (priostr)-1,
2387 // "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
2389 "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
2391 "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
2393 "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
2396 "%cSRP:%cSRP-RSA:%cSRP-DSS",
2397 anonpre_ok ?'+':'-',
2398 lidtpsup (cmd, LID_TYPE_X509) ?'+':'-',
2399 lidtpsup (cmd, LID_TYPE_PGP) ?'+':'-',
2400 //TODO// Temporarily patched out SRP
2401 lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-',
2402 lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-',
2403 lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-');
2404 // strcpy (priostr, "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"); //TODO:TEST//
2405 // strcpy (priostr, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"); //TODO:TEST//
2406 tlog (TLOG_TLS, LOG_DEBUG, "Constructed priority string %s for local ID %s",
2407 priostr, cmd->cmd.pio_data.pioc_starttls.localid);
2408 E_g2e ("Failed to set GnuTLS priority string",
2409 gnutls_priority_set_direct (
2415 // Return the application GNUTLS_E_ code including _SUCCESS
2419 /* The callback functions retrieve various bits of information for the client
2420 * or server in the course of the handshake procedure.
2422 * The logic here is based on client-sent information, such as:
2423 * - TLS hints -- X.509 or alternatives like OpenPGP, SRP, PSK
2424 * - TLS hints -- Server Name Indication
2425 * - User hints -- local and remote identities provided
2427 int srv_clienthello (gnutls_session_t session) {
2428 struct command *cmd;
2429 char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)]; // static
2430 size_t snilen = sizeof (sni);
2432 int gtls_errno = GNUTLS_E_SUCCESS;
2435 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2437 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2439 // Setup a number of common references
2440 cmd = (struct command *) gnutls_session_get_ptr (session);
2442 return GNUTLS_E_INVALID_SESSION;
2444 lid = cmd->cmd.pio_data.pioc_starttls.localid;
2447 // Setup server-specific credentials and priority string
2448 //TODO// get anonpre value here
2449 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2450 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2451 E_g2e ("Failed to reconfigure GnuTLS as a server",
2452 configure_session (cmd,
2454 srv_creds, srv_credcount,
2455 cmd->anonpre & ANONPRE_SERVER));
2456 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2459 // Setup to ignore/request/require remote identity (from client)
2460 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2461 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
2462 // Neither Request nor Require remoteid; ignore it
2464 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REQUEST_REMOTEID) {
2465 // Use Request instead of Require for remoteid
2466 ( //RETURNS_VOID// E_g2e ("Failed to request remote identity",
2467 gnutls_certificate_server_set_request (
2469 GNUTLS_CERT_REQUEST));
2470 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2472 // Require a remoteid from the client (default)
2473 ( //RETURNS_VOID// E_g2e ("Failed to require remote identity (the default)",
2474 gnutls_certificate_server_set_request (
2476 GNUTLS_CERT_REQUIRE));
2477 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2481 // Find the client-helloed ServerNameIndication, or the service name
2482 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2484 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) == 0) {
2485 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2487 case GNUTLS_NAME_DNS:
2489 // Note: In theory, other name types could be sent, and it would
2490 // be useful to access indexes beyond 0. In practice, nobody
2491 // uses other name types than exactly one GNUTLS_NAME_DNS.
2494 tlog (TLOG_TLS, LOG_ERR, "Received an unexpected SNI type; that is possible but uncommon; skipping SNI");
2495 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2499 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2500 if (sni [0] != '\0') {
2503 for (atidx=128; atidx > 0; atidx--) {
2504 if (lid [atidx-1] == '@') {
2508 if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
2509 tlog (TLOG_USER | TLOG_TLS, LOG_ERR, "Mismatch between client-sent SNI %s and local identity %s", sni, lid);
2510 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2511 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
2514 memcpy (lid, sni, sizeof (sni));
2515 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2518 memcpy (sni, lid, sizeof (sni)-1);
2519 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2520 sni [sizeof (sni) - 1] = '\0';
2522 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2525 // Lap up any unnoticed POSIX error messages
2527 cmd->session_errno = errno;
2528 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
2529 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
2530 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
2534 // Round off with an overal judgement
2535 fprintf (stderr, "DEBUG: Returning gtls_errno = %d or \"%s\" from srv_clihello()\n", gtls_errno, gnutls_strerror (gtls_errno));
2540 int cli_srpcreds_retrieve (gnutls_session_t session,
2544 tlog (TLOG_CRYPTO, LOG_DEBUG, "Picking up SRP credentials");
2545 *username = strdup ("tester");
2546 *password = strdup ("test");
2547 return GNUTLS_E_SUCCESS;
2551 /* Setup credentials to be shared by all clients and servers.
2552 * Credentials are generally implemented through callback functions.
2553 * This should be called after setting up DH parameters.
2555 static int setup_starttls_credentials (void) {
2556 gnutls_anon_server_credentials_t srv_anoncred = NULL;
2557 gnutls_anon_client_credentials_t cli_anoncred = NULL;
2558 gnutls_certificate_credentials_t clisrv_certcred = NULL;
2559 //TODO:NOTHERE// int srpbits;
2560 gnutls_srp_server_credentials_t srv_srpcred = NULL;
2561 gnutls_srp_client_credentials_t cli_srpcred = NULL;
2562 //TODO// gnutls_kdh_server_credentials_t srv_kdhcred = NULL;
2563 //TODO// gnutls_kdh_server_credentials_t cli_kdhcred = NULL;
2564 int gtls_errno = GNUTLS_E_SUCCESS;
2565 int gtls_errno_stack0 = GNUTLS_E_SUCCESS;
2568 // Construct anonymous server credentials
2569 E_g2e ("Failed to allocate ANON-DH server credentials",
2570 gnutls_anon_allocate_server_credentials (
2572 if (!have_error_codes ()) /* E_g2e (...) */ gnutls_anon_set_server_dh_params (
2575 if (gtls_errno == GNUTLS_E_SUCCESS) {
2576 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server anonymous credentials");
2577 srv_creds [srv_credcount].credtp = GNUTLS_CRD_ANON;
2578 srv_creds [srv_credcount].cred = (void *) srv_anoncred;
2580 } else if (srv_anoncred != NULL) {
2581 gnutls_anon_free_server_credentials (srv_anoncred);
2582 srv_anoncred = NULL;
2586 // Construct anonymous client credentials
2587 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2588 E_g2e ("Failed to allocate ANON-DH client credentials",
2589 gnutls_anon_allocate_client_credentials (
2591 #ifdef MIRROR_IMAGE_OF_SERVER_ANONYMOUS_CREDENTIALS
2592 // NOTE: This is not done under TLS; server always provides DH params
2593 if (!have_error_codes ()) gnutls_anon_set_client_dh_params (
2597 if (gtls_errno == GNUTLS_E_SUCCESS) {
2598 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client anonymous credentials");
2599 cli_creds [cli_credcount].credtp = GNUTLS_CRD_ANON;
2600 cli_creds [cli_credcount].cred = (void *) cli_anoncred;
2602 } else if (cli_anoncred != NULL) {
2603 gnutls_anon_free_client_credentials (cli_anoncred);
2604 cli_anoncred = NULL;
2608 // Construct certificate credentials for X.509 and OpenPGP cli/srv
2609 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2610 E_g2e ("Failed to allocate certificate credentials",
2611 gnutls_certificate_allocate_credentials (
2613 //TODO// What to do here when we add locking on DH params?
2614 gnutls_certificate_set_dh_params (
2617 gtls_errno_stack0 = gtls_errno;
2618 /* TODO: Bad code. GnuTLS 3.2.1 ignores retrieve_function2 when
2619 * checking if it can handle the OpenPGP certificate type in
2620 * _gnutls_session_cert_type_supported (gnutls_status.c:175) but
2621 * it does see the "1" version field. It does not callback the
2622 * "1" version if "2" is present though.
2624 if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function (
2627 if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function2 (
2629 clisrv_cert_retrieve);
2630 if (gtls_errno == GNUTLS_E_SUCCESS) {
2631 // Setup for certificates
2632 tlog (TLOG_CERT, LOG_INFO, "Setting client and server certificate credentials");
2633 cli_creds [cli_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
2634 cli_creds [cli_credcount].cred = (void *) clisrv_certcred;
2636 srv_creds [srv_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
2637 srv_creds [srv_credcount].cred = (void *) clisrv_certcred;
2639 } else if (clisrv_certcred != NULL) {
2640 gnutls_certificate_free_credentials (clisrv_certcred);
2641 clisrv_certcred = NULL;
2645 // Construct server credentials for SRP authentication
2646 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2647 E_g2e ("Failed to allocate SRP server credentials",
2648 gnutls_srp_allocate_server_credentials (
2650 E_g2e ("Failed to set SRP server credentials",
2651 gnutls_srp_set_server_credentials_file (
2653 "../testdata/tlspool-test-srp.passwd",
2654 "../testdata/tlspool-test-srp.conf"));
2655 if (gtls_errno == GNUTLS_E_SUCCESS) {
2656 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server SRP credentials");
2657 srv_creds [srv_credcount].credtp = GNUTLS_CRD_SRP;
2658 srv_creds [srv_credcount].cred = (void *) srv_srpcred;
2660 } else if (srv_srpcred != NULL) {
2661 gnutls_srp_free_server_credentials (srv_srpcred);
2666 // Construct client credentials for SRP authentication
2667 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2668 E_g2e ("Failed to allocate SRP client credentials",
2669 gnutls_srp_allocate_client_credentials (
2671 if (!have_error_codes ()) gnutls_srp_set_client_credentials_function (
2673 cli_srpcreds_retrieve);
2674 if (gtls_errno == GNUTLS_E_SUCCESS) {
2675 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client SRP credentials");
2676 cli_creds [cli_credcount].credtp = GNUTLS_CRD_SRP;
2677 cli_creds [cli_credcount].cred = (void *) cli_srpcred;
2679 } else if (cli_srpcred != NULL) {
2680 gnutls_srp_free_client_credentials (cli_srpcred);
2685 // Construct server credentials for KDH authentication
2686 //TODO// gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2687 //TODO// E_g2e ("Failed to allocate KDH server credentials",
2688 //TODO// gnutls_kdh_allocate_server_credentials (
2689 //TODO// &srv_kdhcred));
2690 //TODO// E_g2e ("Failed to set KDH server DH params",
2691 //TODO// gnutls_kdh_set_server_dh_params (
2692 //TODO// srv_kdhcred,
2693 //TODO// dh_params));
2694 //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
2695 //TODO// tlog (TLOG_CRYPTO, LOG_INFO, "Setting server KDH credentials");
2696 //TODO// srv_creds [srv_credcount].credtp = GNUTLS_CRD_KDH;
2697 //TODO// srv_creds [srv_credcount].cred = (void *) srv_kdhcred;
2698 //TODO// srv_credcount++;
2699 //TODO// } else if (srv_kdhcred != NULL) {
2700 //TODO// gnutls_kdh_free_server_credentials (srv_kdhcred);
2701 //TODO// srv_kdhcred = NULL;
2705 // Construct client credentials for KDH
2706 //TODO// gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
2707 //TODO// E_g2e ("Failed to allocate KDH client credentials",
2708 //TODO// gnutls_kdh_allocate_client_credentials (
2709 //TODO// &cli_kdhcred));
2710 //TODO// E_g2e ("Failed to set KDH client credentials",
2711 //TODO// gnutls_kdh_set_client_credentials_function (
2712 //TODO// cli_kdhcred,
2713 //TODO// cli_kdh_retrieve));
2714 //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
2715 //TODO// tlog (TLOG_CRYPTO, LOG_INFO, "Setting client KDH credentials");
2716 //TODO// cli_creds [cli_credcount].credtp = GNUTLS_CRD_KDH;
2717 //TODO// cli_creds [cli_credcount].cred = (void *) cli_kdhcred;
2718 //TODO// cli_credcount++;
2719 //TODO// } else if (cli_kdhcred != NULL) {
2720 //TODO// gnutls_kdh_free_client_credentials (cli_kdhcred);
2721 //TODO// cli_kdhcred = NULL;
2725 // Ensure that at least one credential has been set
2726 // TODO: Look at the counters; but at boot, we can require all okay
2727 if ((gtls_errno == GNUTLS_E_SUCCESS) &&
2728 ( (cli_credcount != EXPECTED_CLI_CREDCOUNT) ||
2729 (srv_credcount != EXPECTED_SRV_CREDCOUNT) ) ) {
2730 tlog (TLOG_CRYPTO, LOG_ERR, "Not all credential types could be setup (cli %d/%d, srv %d/%d, gtls_errno %d)", cli_credcount, EXPECTED_CLI_CREDCOUNT, srv_credcount, EXPECTED_SRV_CREDCOUNT, gtls_errno);
2731 E_g2e ("Not all credentials could be setup",
2732 GNUTLS_E_INSUFFICIENT_CREDENTIALS);
2736 // Report overall error or success
2741 /* Cleanup all credentials created, just before exiting the daemon.
2743 static void cleanup_starttls_credentials (void) {
2744 while (srv_credcount-- > 0) {
2745 struct credinfo *crd = &srv_creds [srv_credcount];
2746 switch (crd->credtp) {
2747 case GNUTLS_CRD_CERTIFICATE:
2748 // Shared with client; skipped in server and removed in client
2749 // gnutls_certificate_free_credentials (crd->cred);
2751 case GNUTLS_CRD_ANON:
2752 gnutls_anon_free_server_credentials (crd->cred);
2754 case GNUTLS_CRD_SRP:
2755 gnutls_srp_free_server_credentials (crd->cred);
2757 //TODO// case GNUTLS_CRD_KDH:
2758 //TODO// gnutls_kdh_free_server_credentials (crd->cred);
2762 while (cli_credcount-- > 0) {
2763 struct credinfo *crd = &cli_creds [cli_credcount];
2764 switch (crd->credtp) {
2765 case GNUTLS_CRD_CERTIFICATE:
2766 // Shared with client; skipped in server and removed in client
2767 gnutls_certificate_free_credentials (crd->cred);
2769 case GNUTLS_CRD_ANON:
2770 gnutls_anon_free_client_credentials (crd->cred);
2772 case GNUTLS_CRD_SRP:
2773 gnutls_srp_free_client_credentials (crd->cred);
2775 //TODO// case GNUTLS_CRD_KDH:
2776 //TODO// gnutls_kdh_free_client_credentials (crd->cred);
2784 * The starttls_thread is a main program for the setup of a TLS connection,
2785 * either in client mode or server mode. Note that the distinction between
2786 * client and server mode is only a TLS concern, but not of interest to the
2787 * application or the records exchanged.
2789 * If the STARTTLS operation succeeds, this will be reported back to the
2790 * application, but the TLS pool will continue to be active in a copycat
2791 * procedure: encrypting outgoing traffic and decrypting incoming traffic.
2793 * A new handshake may be initiated with a STARTTLS command with the special
2794 * flag PIOF_STARTTLS_RENEGOTIATE and the ctlkey set to a previously setup
2795 * TLS connection. This command runs in a new thread, that cancels the old
2796 * one (which it can only do while it is waiting in copycat) and then join
2797 * that thread (and its data) with the current one. This is based on the
2798 * ctlkey, which serves to lookup the old thread's data. When the
2799 * connection ends for other reasons than a permitted cancel by another
2800 * thread, will the thread cleanup its own resources. In these situations,
2801 * the new command determines the negotiation parameters, and returns identity
2804 * In addition, the remote side may initiate renegotiation. This is accepted
2805 * without further ado (although future versions of the TLS Pool may add a
2806 * callback mechanism to get it approved). The renegotiation now runs under
2807 * the originally supplied negotiation parameters. In case it needs a new
2808 * local identity, it may also perform callbacks. Possibly repeating what
2809 * happened before -- but most often, a server will start processing a
2810 * protocol and determine that it requires more for the requested level of
2811 * service, and then renegotiate. This is common, for example, with HTTPS
2812 * connections that decide they need a client certificate for certain URLs.
2813 * The implementation of this facility is currently as unstructured as the
2814 * facility itself, namely through a goto. We may come to the conclusion
2815 * that a loop is in fact a warranted alternative, but we're not yet
2816 * convinced that this would match with other "structures" in TLS.
2818 * In conclusion, there are three possible ways of running this code:
2819 * 1. For a new connection. Many variables are not known and build up
2820 * in the course of running the function.
2821 * 2. After a command requesting renegotiation. This overtakes the prior
2822 * connection's thread, and copies its data from the ctlkeynode_tls.
2823 * The resulting code has a number of variables filled in already at
2825 * 3. After a remote request for renegotiation. This loops back to an
2826 * earlier phase, but after the thread takeover and ctlkeynode_tls copy
2827 * of the explicit command for renegotation. Its behaviour is subtly
2828 * different in that it has no command to act on, and so it cannot
2829 * send responses or error codes. It will however log and shutdown
2830 * as the command-driven options would. It will not perform callbacks
2831 * for PIOC_STARTTLS_LOCALID_V2 or PIOC_PLAINTEXT_CONNECT_V2. It will
2832 * however trigger the PIOC_LIDENTRY_CALLBACK_V2 through the separate
2833 * callback command, if one is registered.
2834 * Yeah, it's great fun, coding TLS and keeping it both flexible and secure.
2836 static void *starttls_thread (void *cmd_void) {
2837 struct command *cmd, *replycmd;
2838 struct command cmd_copy; // for relooping during renegotiation
2839 struct pioc_starttls orig_starttls;
2840 uint32_t orig_cmdcode;
2843 gnutls_session_t session;
2844 int got_session = 0;
2845 int gtls_errno = GNUTLS_E_SUCCESS;
2847 struct ctlkeynode_tls *ckn = NULL;
2850 int want_remoteid = 1;
2851 int got_remoteid = 0;
2852 int renegotiating = 0;
2853 char *preauth = NULL;
2854 unsigned int preauthlen = 0;
2855 int taking_over = 0;
2856 int my_maxpreauth = 0;
2860 // Block thread cancellation -- and re-enable it in copycat()
2861 assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
2864 // General thread setup
2865 replycmd = cmd = (struct command *) cmd_void;
2867 send_error (replycmd, EINVAL, "Command structure not received");
2868 assert (pthread_detach (pthread_self ()) == 0);
2871 *cmd->valflags = '\0';
2872 cmd->session_errno = 0;
2874 orig_cmdcode = cmd->cmd.pio_cmd;
2875 memcpy (&orig_starttls, &cmd->cmd.pio_data.pioc_starttls, sizeof (orig_starttls));
2876 cmd->orig_starttls = &orig_starttls;
2877 cryptfd = cmd->passfd;
2879 //TODO:TEST Removed here because it is tested below
2882 tlog (TLOG_UNIXSOCK, LOG_ERR, "No ciphertext file descriptor supplied to TLS Pool");
2883 send_error (replycmd, EINVAL, "No ciphertext file descriptor supplied to TLS Pool");
2884 assert (pthread_detach (pthread_self ()) == 0);
2888 cmd->session_certificate = (intptr_t) (void *) NULL;
2889 cmd->session_privatekey = (intptr_t) (void *) NULL;
2892 // In case of renegotiation, lookup the previous ctlkeynode by its
2893 // ctlkey. The fact that we have ckn != NULL indicates that we are
2894 // renegotiating in the code below; it will supply information as
2895 // we continue to run the TLS process.
2896 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_RENEGOTIATE) {
2897 fprintf (stderr, "DEBUG: Got a request to renegotiate existing TLS connection\n");
2899 // Check that no FD was passed (and ended up in cryptfd)
2901 tlog (TLOG_UNIXSOCK, LOG_ERR, "Renegotiation started with extraneous file descriptor");
2902 send_error (replycmd, EPROTO, "File handle supplied for renegotiation");
2904 assert (pthread_detach (pthread_self ()) == 0);
2908 // First find the ctlkeynode_tls
2909 ckn = (struct ctlkeynode_tls *) ctlkey_find (cmd->cmd.pio_data.pioc_starttls.ctlkey, security_tls, cmd->clientfd);
2910 fprintf (stderr, "DEBUG: Got ckn == 0x%0x\n", (intptr_t) ckn);
2912 tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to find TLS connection for renegotiation by its ctlkey");
2913 send_error (replycmd, ESRCH, "Cannot find TLS connection for renegotiation");
2914 assert (pthread_detach (pthread_self ()) == 0);
2918 // Now cancel the pthread for this process
2919 errno = pthread_cancel (ckn->owner);
2920 fprintf (stderr, "DEBUG: pthread_cancel returned %d\n", errno);
2923 errno = pthread_join (ckn->owner, &retval);
2924 fprintf (stderr, "DEBUG: pthread_join returned %d\n", errno);
2927 // We have now synchronised with the cancelled thread
2928 // Cleanup any _remote data in ckn->session->cmd
2929 cleanup_any_remote_credentials (
2930 (struct command *) gnutls_session_get_ptr (
2934 tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to interrupt TLS connection for renegotiation");
2935 send_error (replycmd, errno, "Cannot interrupt TLS connection for renegotiation");
2936 ctlkey_unfind (&ckn->regent);
2937 assert (pthread_detach (pthread_self ()) == 0);
2938 // Do not free the ckn, as the other thread still runs
2942 // We are in control! Assimilate the TLS connection data.
2944 plainfd = ckn->plainfd;
2945 cryptfd = ckn->cryptfd;
2946 session = ckn->session;
2949 ctlkey_unfind (&ckn->regent);
2952 // Then follows the unstructured entry point for the unstructured
2953 // request to a TLS connection to renegotiate its security parameters.
2954 // Doing this in any other way than with goto would add a lot of
2955 // make-belief structure that only existed to make this looping
2956 // possible. We'd rather be honest and admit the lack of structure
2957 // that TLS has in this respect. Maybe we'll capture it one giant loop
2958 // at some point, but for now that does not seem to add any relief.
2960 fprintf (stderr, "DEBUG: Renegotiating = %d, anonpost = %d, plainfd = %d, cryptfd = %d, flags = 0x%x, session = 0x%x, got_session = %d, lid = \"%s\", rid = \"%s\"\n", renegotiating, anonpost, plainfd, cryptfd, cmd->cmd.pio_data.pioc_starttls.flags, session, got_session, cmd->cmd.pio_data.pioc_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid);
2963 // If this is server renegotiating, send a request to that end
2964 //TODO// Only invoke gnutls_rehandshake() on the server
2965 if (renegotiating && (taking_over || anonpost) && (gtls_errno == GNUTLS_E_SUCCESS)) {
2966 fprintf (stderr, "DEBUG: Invoking gnutls_rehandshake in renegotiation loop\n");
2967 gtls_errno = gnutls_rehandshake (session);
2968 if (gtls_errno == GNUTLS_E_INVALID_REQUEST) {
2969 // Clients should not do this; be forgiving
2970 gtls_errno = GNUTLS_E_SUCCESS;
2971 fprintf (stderr, "DEBUG: Client-side invocation flagged as wrong; compensated error\n");
2976 // When renegotiating TLS security, ensure that it is done securely
2977 if (renegotiating && (gnutls_safe_renegotiation_status (session) == 0)) {
2978 send_error (replycmd, EPROTO, "Renegotiation requested while secure renegotiation is unavailable on remote");
2988 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2993 assert (pthread_detach (pthread_self ()) == 0);
2998 // Potentially decouple the controlling fd (ctlkey is in orig_starttls)
2999 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_FORK) {
3000 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_FORK;
3005 // Setup BDB transactions and reset credential datum fields
3007 memset (&cmd->lids, 0, sizeof (cmd->lids));
3008 manage_txn_begin (&cmd->txn);
3012 // Permit cancellation of this thread -- TODO: Cleanup?
3013 //TODO:TEST// Defer setcancelstate until copycat() activity
3015 errno = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
3017 send_error (replycmd, ESRCH, "STARTTLS handler thread cancellability refused");
3027 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3032 manage_txn_rollback (&cmd->txn);
3033 assert (pthread_detach (pthread_self ()) == 0);
3038 // Check and setup the plaintext file handle
3040 send_error (replycmd, EPROTO, "You must supply a TLS-protected socket");
3045 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3046 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
3047 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3052 manage_txn_rollback (&cmd->txn);
3053 assert (pthread_detach (pthread_self ()) == 0);
3058 // Decide on support for the Anonymous Precursor, based on the
3059 // service name and its appearance in the anonpre_registry.
3060 // If the remoteid is not interesting to the client then also
3061 // support an Anonymous Precursor; we have nothing to loose.
3062 cmd->anonpre &= ~ANONPRE_EITHER;
3063 if (renegotiating) {
3064 ; // Indeed, during renegotiation we always disable ANON-DH
3065 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
3066 cmd->anonpre = ANONPRE_EITHER;
3069 int anonpre_regidx = anonpre_registry_size >> 1;
3070 int anonpre_regjmp = (anonpre_registry_size + 1) >> 1;
3072 while (anonpre_regjmp > 0) {
3073 anonpre_regjmp = anonpre_regjmp >> 1;
3074 cmp = strncasecmp (anonpre_registry [anonpre_regidx].service,
3075 cmd->cmd.pio_data.pioc_starttls.service,
3076 TLSPOOL_SERVICELEN);
3077 fprintf (stderr, "DEBUG: anonpre_determination, comparing [%d] %s to %s, found cmp==%d\n", anonpre_regidx, anonpre_registry [anonpre_regidx].service, cmd->cmd.pio_data.pioc_starttls.service, cmp);
3079 // anonpre_regent matches
3080 cmd->anonpre = anonpre_registry [anonpre_regidx].flags;
3082 } else if (cmp > 0) {
3083 // anonpre_regent too high
3084 anonpre_regidx -= 1 + anonpre_regjmp;
3085 if (anonpre_regidx < 0) {
3089 // anonpre_regent too low
3090 anonpre_regidx += 1 + anonpre_regjmp;
3091 if (anonpre_regidx >= anonpre_registry_size) {
3092 anonpre_regidx = anonpre_registry_size - 1;
3099 // Setup flags for client and/or server roles (make sure there is one)
3100 if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_CLIENT) == 0)) {
3101 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_SERVER;
3103 if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_SERVER) == 0)) {
3104 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_CLIENT;
3106 if ((cmd->cmd.pio_data.pioc_starttls.flags & (PIOF_STARTTLS_LOCALROLE_CLIENT | PIOF_STARTTLS_LOCALROLE_SERVER)) == 0) {
3108 // Neither a TLS client nor a TLS server
3110 send_error (replycmd, ENOTSUP, "Command not supported");
3116 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3117 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
3118 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3123 manage_txn_rollback (&cmd->txn);
3124 assert (pthread_detach (pthread_self ()) == 0);
3129 // Setup the TLS session. Also see doc/p2p-tls.*
3131 // TODO: GnuTLS cannot yet setup p2p connections
3133 gnutls_session_set_ptr (
3136 //TODO:DONE?// Clear various settings... creds, flags, modes? CLI/SRV?
3138 E_g2e ("Failed to initialise GnuTLS peer session",
3141 (((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)? GNUTLS_CLIENT: 0) |
3142 ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)? GNUTLS_SERVER: 0))
3144 if (gtls_errno == GNUTLS_E_SUCCESS) {
3146 gnutls_session_set_ptr (
3151 cmd->session = session;
3153 // Setup client-specific behaviour if needed
3154 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
3155 if (!renegotiating) { //TODO:TEST//
3157 // Setup as a TLS client
3161 // Require a minimum security level for SRP
3163 //TODO:CRASH// if (gtls_errno == GNUTLS_E_SUCCESS) gnutls_srp_set_prime_bits (
3164 //TODO:CRASH// session,
3165 //TODO:CRASH// srpbits);
3167 // Setup as a TLS client
3169 // Setup for potential sending of SNI
3170 if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_WITHOUT_SNI) == 0) {
3171 char *str = cmd->cmd.pio_data.pioc_starttls.remoteid;
3174 while (str [len] && (len < 128)) {
3175 if (str [len] == '@') {
3180 // If no usable remoteid was setup, ignore it
3181 if ((len > ofs) && (len < 128)) {
3182 cmd->cmd.pio_data.pioc_starttls.remoteid [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)-1] = '\0';
3183 tlog (TLOG_TLS, LOG_DEBUG, "Sending ServerNameIndication \"%.*s\"", len - ofs, str + ofs);
3184 E_g2e ("Client failed to setup SNI",
3185 gnutls_server_name_set (
3194 // Setup for client credential installation in this session
3196 // Setup client-specific credentials and priority string
3197 fprintf (stderr, "DEBUG: Configuring client credentials\n");
3198 E_g2e ("Failed to configure GnuTLS as a client",
3199 configure_session (cmd,
3201 anonpost? NULL: cli_creds,
3202 anonpost? 0: cli_credcount,
3203 cmd->anonpre & ANONPRE_CLIENT));
3206 // Setup callback to server-specific behaviour if needed
3207 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
3208 fprintf (stderr, "DEBUG: Configuring for server credentials callback if %d==0\n", gtls_errno);
3209 if (!renegotiating) { //TODO:TEST//
3210 if (gtls_errno == GNUTLS_E_SUCCESS) {
3211 gnutls_handshake_set_post_client_hello_function (
3216 //TODO:TEST// configure_session _if_ not setup as a client (too)
3218 // Setup for server credential installation in this session
3220 // Setup server-specific credentials and priority string
3222 if (! (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
3223 fprintf (stderr, "DEBUG: Configuring server credentials (because it is not a client)\n");
3224 E_g2e ("Failed to configure GnuTLS as a server",
3225 configure_session (cmd,
3227 anonpost? NULL: srv_creds,
3228 anonpost? 0: srv_credcount,
3229 cmd->anonpre & ANONPRE_SERVER));
3235 // Prefetch local identities that might be used in this session
3237 E_g2e ("Failed to fetch local credentials",
3238 fetch_local_credentials (cmd));
3242 // Setup a temporary priority string so handshaking can start
3243 if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) == 0) {
3244 E_g2e ("Failed to preconfigure server token priority string",
3245 gnutls_priority_set (
3251 // Check if past code stored an error code through POSIX
3252 if (cmd->session_errno) {
3253 gtls_errno = GNUTLS_E_USER_ERROR;
3257 // Setup a timeout value as specified in the command, where TLS Pool
3258 // defines 0 as default and ~0 as infinite (GnuTLS has 0 as infinite).
3259 tout = cmd->cmd.pio_data.pioc_starttls.timeout;
3260 if (renegotiating) {
3261 ; // Do not set timeout
3263 if (tout == TLSPOOL_TIMEOUT_DEFAULT) {
3264 gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
3265 } else if (tout == TLSPOOL_TIMEOUT_INFINITE) {
3266 gnutls_handshake_set_timeout (session, 0);
3268 gnutls_handshake_set_timeout (session, tout);
3272 // Now setup for the GnuTLS handshake
3274 if (renegotiating) {
3275 ; // Do not setup cryptfd
3277 if (gtls_errno == GNUTLS_E_SUCCESS) {
3278 gnutls_transport_set_int (session, cryptfd);
3280 if (gtls_errno != GNUTLS_E_SUCCESS) {
3281 tlog (TLOG_TLS, LOG_ERR, "Failed to prepare for TLS: %s", gnutls_strerror (gtls_errno));
3282 if (cmd->session_errno) {
3283 send_error (replycmd, cmd->session_errno, error_getstring ());
3285 send_error (replycmd, EIO, "Failed to prepare for TLS");
3288 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3289 gnutls_deinit (session);
3297 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3298 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
3299 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3304 manage_txn_rollback (&cmd->txn);
3305 assert (pthread_detach (pthread_self ()) == 0);
3308 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake started over %d", cryptfd);
3311 // Take a rehandshaking step forward.
3313 gtls_errno = gnutls_handshake (session);
3315 // When data is sent before completing
3316 // the rehandshake, then it's something
3317 // harmless, given the criteria for the
3318 // anonpre_registry. We pass it on and
3319 // don't worry about it. We do report
3322 // Note: Applications should be willing
3323 // to buffer or process such early data
3324 // before the handshake is over or else
3325 // the handshake will bail out in error.
3327 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
3328 if (my_maxpreauth <= 0) {
3329 tlog (TLOG_COPYCAT, LOG_ERR, "Received unwanted early data before authentication is complete");
3330 break; // Terminate the handshake
3331 } else if (preauth == NULL) {
3332 preauth = malloc (my_maxpreauth);
3333 if (preauth == NULL) {
3334 gtls_errno = GNUTLS_E_MEMORY_ERROR;
3335 break; // Terminate the handshake
3339 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
3340 if (preauthlen >= my_maxpreauth) {
3341 tlog (TLOG_COPYCAT, LOG_ERR, "Received more early data than willing to receive (%d bytes)", my_maxpreauth);
3342 break; // Terminate the handshake
3345 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
3347 sz = gnutls_record_recv (session, preauth + preauthlen, my_maxpreauth - preauthlen);
3348 tlog (TLOG_COPYCAT, LOG_DEBUG, "Received %d remote bytes (or error if <0) from %d during anonymous precursor\n", (int) sz, cryptfd);
3351 gtls_errno = GNUTLS_E_SUCCESS;
3353 gtls_errno = sz; // It's actually an error code
3356 } while ((gtls_errno < 0) &&
3357 //DROPPED// (gtls_errno != GNUTLS_E_GOT_APPLICATION_DATA) &&
3358 //DROPPED// (gtls_errno != GNUTLS_E_WARNING_ALERT_RECEIVED) &&
3359 (gnutls_error_is_fatal (gtls_errno) == 0));
3361 // Handshake done -- initialise remote_xxx, vfystatus, got_remoteid
3362 if ((gtls_errno == 0) && !(cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID)) {
3363 // We want to try to authenticate the peer
3364 E_g2e ("Failed to retrieve peer credentials",
3365 fetch_remote_credentials (cmd));
3366 if (gtls_errno == GNUTLS_E_AUTH_ERROR) {
3367 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REQUEST_REMOTEID) {
3368 // We do not _require_ authentication of the peer
3373 if (gtls_errno == 0) {
3374 const gnutls_datum_t *certs;
3375 unsigned int num_certs;
3377 switch (cmd->remote_auth_type) { // Peer's cred type
3378 case GNUTLS_CRD_CERTIFICATE:
3379 if (cmd->remote_cert_count >= 1) {
3382 #ifdef PHASED_OUT_DIRECT_VALIDATION
3383 E_g2e ("Failed to validate peer",
3384 gnutls_certificate_verify_peers2 (
3390 case GNUTLS_CRD_PSK:
3391 // Difficult... what did the history say about this?
3393 cmd->vfystatus = GNUTLS_CERT_SIGNER_NOT_FOUND;
3395 case GNUTLS_CRD_SRP:
3396 // Got a credential, validation follows later on
3397 //TODO// SRP does not really auth the server
3399 cmd->vfystatus = GNUTLS_CERT_SIGNER_NOT_FOUND;
3401 case GNUTLS_CRD_ANON:
3402 // Did not get a credential, perhaps due to anonpre
3404 cmd->vfystatus = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNATURE_FAILURE;
3407 // Inner Application extension is no true credential
3408 // Should we compare the client-requested service?
3409 // Should we renegotiate into the ALPN protocol?
3411 cmd->vfystatus = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNATURE_FAILURE;
3414 // Unknown creds cautiously considered unauthentitcated
3416 cmd->vfystatus = ~ (unsigned short) 0; // It's all bad
3420 // Now recognise and handle the Anonymous Precursor
3421 if (((cmd->anonpre & ANONPRE_EITHER) != 0)
3422 && want_remoteid && !got_remoteid) {
3423 assert (anonpost == 0);
3424 valexp_valflag_set (cmd, 'A');
3425 // Disable ANON-protocols but keep creds from before
3426 //TODO:ELSEWHERE// tlog (TLOG_TLS, LOG_DEBUG, "Reconfiguring TLS over %d without Anonymous Precursor\n", cryptfd);
3427 //TODO:ELSEWHERE// E_g2e ("Failed to reconfigure GnuTLS without anonymous precursor",
3428 //TODO:ELSEWHERE// configure_session (cmd,
3429 //TODO:ELSEWHERE// session,
3430 //TODO:ELSEWHERE// NULL, 0,
3431 //TODO:ELSEWHERE// 0));
3432 // We do not want to use ANON-DH if the flag
3433 // ANONPRE_EXTEND_MASTER_SECRET is set for the protocol
3434 // but the remote peer does not support it. Only if
3435 // this problem cannot possibly occur, permit
3436 // my_maxpreauth > 0 for early data acceptance.
3438 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
3439 #if GNUTLS_VERSION_NUMBER >= 0x030400
3440 gnutls_ext_priv_data_t ext;
3441 if (!gnutls_ext_get_data (session, 23, &ext)) {
3442 my_maxpreauth = maxpreauth;
3446 my_maxpreauth = maxpreauth;
3448 if (gtls_errno == 0) {
3449 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake continued over %d after anonymous precursor", cryptfd);
3450 renegotiating = 1; // (de)selects steps
3451 anonpost = 1; // (de)selects steps
3456 if ((gtls_errno == GNUTLS_E_SUCCESS) && cmd->session_errno) {
3457 gtls_errno = GNUTLS_E_USER_ERROR;
3462 // Run the validation expression logic, using expressions we ran into
3463 fprintf (stderr, "DEBUG: Prior to valexp, gtls_errno = %d\n", gtls_errno);
3464 if (gtls_errno == GNUTLS_E_SUCCESS) {
3465 struct valexp *verun = NULL;
3466 char *valexp_conj [3];
3467 int valexp_conj_count = 0;
3468 // Setup for validation expression runthrough
3469 cmd->valexp_result = -1;
3470 if ((cmd->trust_valexp != NULL) && (0 != strcmp (cmd->trust_valexp, "1"))) {
3471 fprintf (stderr, "DEBUG: Trust valexp \"%s\" @ 0x%016x\n", cmd->trust_valexp, (uint64_t) cmd->trust_valexp);
3472 valexp_conj [valexp_conj_count++] = cmd->trust_valexp;
3474 if (cmd->lids [LID_TYPE_VALEXP - LID_TYPE_MIN].data != NULL) {
3475 // Interpret the entry, abuse p11uri as valexp
3479 gnutls_datum_t ignored;
3480 ok = dbcred_interpret (
3481 &cmd->lids [LID_TYPE_VALEXP - LID_TYPE_MIN],
3486 fprintf (stderr, "DEBUG: LocalID valexp \"%s\" @ 0x%016x (ok=%d)\n", lid_valexp, (uint64_t) lid_valexp, ok);
3487 if (ok && (lid_valexp != NULL)) {
3488 valexp_conj [valexp_conj_count++] = lid_valexp;
3490 gtls_errno = GNUTLS_E_AUTH_ERROR;
3493 fprintf (stderr, "DEBUG: Number of valexp is %d, gtls_errno=%d\n", valexp_conj_count, gtls_errno);
3494 // Optionally start computing the validation expression
3495 if ((gtls_errno == GNUTLS_E_SUCCESS) && (valexp_conj_count > 0)) {
3496 valexp_conj [valexp_conj_count] = NULL;
3497 verun = valexp_register (
3499 have_starttls_validation (),
3501 fprintf (stderr, "DEBUG: Registered to verun = 0x%016x\n", (uint64_t) verun);
3502 if (verun == NULL) {
3503 gtls_errno = GNUTLS_E_AUTH_ERROR;
3506 // When setup, run the validation expressions to completion
3507 if (verun != NULL) {
3508 while (cmd->valexp_result == -1) {
3509 ; //TODO: Tickle async predicate run completion
3511 fprintf (stderr, "DEBUG: Finishing tickling \"async\" predicates for valexp\n");
3512 if (cmd->valexp_result != 1) {
3513 tlog (TLOG_TLS, LOG_INFO, "TLS validation expression result is %d", cmd->valexp_result);
3514 gtls_errno = GNUTLS_E_AUTH_ERROR;
3515 fprintf (stderr, "DEBUG: valexp returns NEGATIVE result\n");
3517 else fprintf (stderr, "DEBUG: valexp returns POSITIVE result\n");
3518 valexp_unregister (verun);
3519 fprintf (stderr, "DEBUG: Unregistered verun 0x%016x\n", (uint64_t) verun);
3524 // Cleanup any prefetched identities
3525 for (i=LID_TYPE_MIN; i<=LID_TYPE_MAX; i++) {
3526 if (cmd->lids [i - LID_TYPE_MIN].data != NULL) {
3527 free (cmd->lids [i - LID_TYPE_MIN].data);
3530 memset (cmd->lids, 0, sizeof (cmd->lids));
3532 // Cleanup any trust_valexp duplicate string
3533 if (cmd->trust_valexp != NULL) {
3534 free (cmd->trust_valexp);
3535 cmd->trust_valexp = NULL;
3539 /* This is not proper. gnutls_certificate_set_key() suggests that these are
3540 * automatically cleaned up, and although this is not repeated in
3541 * gnutls_certificate_set_retrieve_function2() it is likely to be related.
3542 * Plus, renegotiation with this code in place bogged down on failed pcerts;
3543 * they were detected in _gnutls_selected_cert_supported_kx() but their
3544 * key exchange algorithm was never found.
3546 if (NULL != (void *) cmd->session_privatekey) {
3547 gnutls_privkey_deinit ((void *) cmd->session_privatekey);
3548 cmd->session_privatekey = (intptr_t) (void *) NULL;
3550 if (NULL != (void *) cmd->session_certificate) {
3551 gnutls_pcert_deinit ((void *) cmd->session_certificate);
3552 free ((void *) cmd->session_certificate);
3553 cmd->session_certificate = (intptr_t) (void *) NULL;
3558 // From here, assume nothing about the cmd->cmd structure; as part of
3559 // the handshake, it may have passed through the client's control, as
3560 // part of a callback. So, reinitialise the entire return structure.
3561 //TODO// Or backup the (struct pioc_starttls) before handshaking
3562 cmd->cmd.pio_cmd = orig_cmdcode;
3563 cmd->cmd.pio_data.pioc_starttls.localid [0] =
3564 cmd->cmd.pio_data.pioc_starttls.remoteid [0] = '\0';
3567 // Respond to positive or negative outcome of the handshake
3568 if (gtls_errno != GNUTLS_E_SUCCESS) {
3569 tlog (TLOG_TLS, LOG_ERR, "TLS handshake failed: %s", gnutls_strerror (gtls_errno));
3570 if (cmd->session_errno) {
3572 tlog (TLOG_TLS, LOG_ERR, "Underlying cause may be: %s", strerror (cmd->session_errno));
3573 errstr = error_getstring ();
3574 if (errstr == NULL) {
3575 errstr = "TLS handshake failed";
3577 send_error (replycmd, cmd->session_errno, errstr);
3579 send_error (replycmd, EPERM, "TLS handshake failed");
3585 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3586 gnutls_deinit (session);
3594 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3595 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
3596 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3601 manage_txn_rollback (&cmd->txn);
3602 assert (pthread_detach (pthread_self ()) == 0);
3605 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_INFO, "TLS handshake succeeded over %d", cryptfd);
3606 //TODO// extract_authenticated_remote_identity (cmd);
3610 // Request the plaintext file descriptor with a callback
3612 uint32_t oldcmd = cmd->cmd.pio_cmd;
3613 struct command *resp;
3614 cmd->cmd.pio_cmd = PIOC_PLAINTEXT_CONNECT_V2;
3615 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_PLAINTEXT_CONNECT_V2");
3616 resp = send_callback_and_await_response (replycmd, 0);
3617 assert (resp != NULL); // No timeout, should be non-NULL
3618 if (resp->cmd.pio_cmd != PIOC_PLAINTEXT_CONNECT_V2) {
3619 tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
3620 send_error (replycmd, EINVAL, "Callback response has bad command code");
3625 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3626 gnutls_deinit (session);
3630 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3631 if (ckn) { /* TODO: CHECK NEEDED? PRACTICE=>YES */
3632 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3637 manage_txn_rollback (&cmd->txn);
3638 assert (pthread_detach (pthread_self ()) == 0);
3641 cmd->cmd.pio_cmd = oldcmd;
3642 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);
3643 plainfd = resp->passfd;
3647 tlog (TLOG_UNIXSOCK, LOG_ERR, "No plaintext file descriptor supplied to TLS Pool");
3648 send_error (replycmd, EINVAL, "No plaintext file descriptor supplied to TLS Pool");
3653 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3654 gnutls_deinit (session);
3658 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3659 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
3660 if (ctlkey_unregister (ckn->regent.ctlkey)) {
3665 manage_txn_rollback (&cmd->txn);
3666 assert (pthread_detach (pthread_self ()) == 0);
3669 //DEFERRED// send_command (replycmd, -1); // app sent plainfd to us
3672 // Copy TLS records until the connection is closed
3673 manage_txn_commit (&cmd->txn);
3674 if (!renegotiating) {
3675 ckn = (struct ctlkeynode_tls *) malloc (sizeof (struct ctlkeynode_tls));
3678 send_error (replycmd, ENOMEM, "Out of memory allocating control key structure");
3680 int detach = (orig_starttls.flags & PIOF_STARTTLS_DETACH) != 0;
3681 ckn->session = session;
3682 ckn->owner = pthread_self ();
3683 ckn->cryptfd = cryptfd;
3684 ckn->plainfd = plainfd;
3685 //DEBUG// fprintf (stderr, "Registering control key\n");
3686 if (renegotiating || (ctlkey_register (orig_starttls.ctlkey, &ckn->regent, security_tls, detach ? INVALID_POOL_HANDLE : cmd->clientfd, forked) == 0)) {
3687 int copied = GNUTLS_E_SUCCESS;
3688 send_command (replycmd, -1); // app sent plainfd to us
3692 // Check on extended master secret if desired
3693 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
3694 #if GNUTLS_VERSION_NUMBER >= 0x030400
3695 gnutls_ext_priv_data_t ext;
3696 if (!gnutls_ext_get_data (session, 23, &ext)) {
3697 cmd->anonpre &= ~ANONPRE_EXTEND_MASTER_SECRET;
3701 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
3702 tlog (TLOG_COPYCAT, LOG_ERR, "Received %d remote bytes from anonymous precursor but lacking %s-required authentication through extended master secret", orig_starttls.service);
3703 gtls_errno = GNUTLS_E_LARGE_PACKET;
3706 } else if (write (plainfd, preauth, preauthlen) == preauthlen) {
3707 tlog (TLOG_COPYCAT, LOG_DEBUG, "Passed on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
3710 copied = copycat (plainfd, cryptfd, session, detach ? INVALID_POOL_HANDLE : cmd->clientfd);
3712 tlog (TLOG_COPYCAT, LOG_DEBUG, "Failed to pass on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
3715 copied = copycat (plainfd, cryptfd, session, detach ? INVALID_POOL_HANDLE : cmd->clientfd);
3717 // Renegotiate if copycat asked us to
3718 if (copied == GNUTLS_E_REHANDSHAKE) {
3719 // Yes, goto is a dirty technique. On the
3720 // other hand, so is forcing unstructured
3721 // code flows into a make-belief structure
3722 // that needs changing over and over again.
3723 // I fear goto is the most reasonable way
3724 // of handling this rather obtuse structure
3725 // of renegotiation of security in TLS :(
3726 //TODO// Ensure secure renegotiation!!!
3728 replycmd = NULL; // Bypass all send_XXX()
3729 memcpy (&cmd_copy, cmd, sizeof (cmd_copy));
3731 memcpy (cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid));
3732 memcpy (cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid));
3733 cmd->cmd.pio_data.pioc_starttls.flags = orig_starttls.flags & ~PIOF_STARTTLS_LOCALID_CHECK;
3734 // Disabling the flag causing LOCALID_CHECK
3735 // ...and plainfd >= 0 so no PLAINTEXT_CONNECT
3736 // ...so there will be no callbacks to cmd
3737 fprintf (stderr, "DEBUG: Goto renegotiate with cmd.lid = \"%s\" and orig_cmd.lid = \"%s\" and cmd.rid = \"%s\" and orig_cmd.rid = \"%s\" and cmd.flags = 0x%x and orig_cmd.flags = 0x%x\n", cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, cmd->cmd.pio_data.pioc_starttls.flags, orig_starttls.flags);
3740 //DEBUG// fprintf (stderr, "Unregistering control key\n");
3741 // Unregister by ctlkey, which should always succeed
3742 // if the TLS connection hadn't been closed down yet;
3743 // and if it does, the memory can be freed. Note that
3744 // the ctlkey is not taken from the ckn, which may
3745 // already have been freed if the ctlfd was closed
3746 // and the connection could not continue detached
3747 // (such as after forking it).
3748 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
3749 if (ctlkey_unregister (orig_starttls.ctlkey)) {
3753 //DEBUG// fprintf (stderr, "Unregistered control key\n");
3755 send_error (replycmd, ENOENT, "Failed to register control key for TLS connection");
3764 cleanup_any_remote_credentials (cmd);
3766 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
3767 gnutls_deinit (session);
3770 assert (pthread_detach (pthread_self ()) == 0);
3776 * The starttls function responds to an application's request to
3777 * setup TLS for a given file descriptor, and return a file descriptor
3778 * with the unencrypted view when done. The main thing done here is to
3779 * spark off a new thread that handles the operations.
3781 void starttls (struct command *cmd) {
3782 /* Create a thread and, if successful, wait for it to unlock cmd */
3783 errno = pthread_create (&cmd->handler, NULL, starttls_thread, (void *) cmd);
3785 send_error (cmd, ESRCH, "STARTTLS thread refused");
3788 //TODO:TEST// Thread detaches itself before terminating w/o followup
3790 errno = pthread_detach (cmd->handler);
3792 pthread_cancel (cmd->handler);
3793 send_error (cmd, ESRCH, "STARTTLS thread detachment refused");
3801 * Run the PRNG for a TLS connection, identified by its control key. If the connection
3802 * is not a TLS connection, or if the control key is not found, reply with ERROR;
3803 * otherwise, the session should help to create pseudo-random bytes.
3805 void starttls_prng (struct command *cmd) {
3806 uint8_t in1 [TLSPOOL_PRNGBUFLEN];
3807 uint8_t in2 [TLSPOOL_PRNGBUFLEN];
3808 int16_t in1len, in2len, prnglen;
3809 struct ctlkeynode_tls *ckn = NULL;
3812 int gtls_errno = GNUTLS_E_SUCCESS;
3813 struct pioc_prng *prng = &cmd->cmd.pio_data.pioc_prng;
3815 // Find arguments and validate them
3816 in1len = prng->in1_len;
3817 in2len = prng->in2_len;
3818 prnglen = prng->prng_len;
3819 err = err || (in1len <= 0);
3820 err = err || (prnglen > TLSPOOL_PRNGBUFLEN);
3821 err = err || ((TLSPOOL_CTLKEYLEN + in1len + (in2len >= 0? in2len: 0))
3822 > TLSPOOL_PRNGBUFLEN);
3824 memcpy (in1, prng->buffer + TLSPOOL_CTLKEYLEN , in1len);
3826 memcpy (in2, prng->buffer + TLSPOOL_CTLKEYLEN + in1len, in2len);
3829 // - check the label string
3830 prefixes = tlsprng_label_prefixes;
3831 while ((!err) && (*prefixes)) {
3832 char *pf = *prefixes++;
3833 if (strlen (pf) != in1len) {
3836 if (strcmp (pf, in1) != 0) {
3840 if (*prefixes == NULL) {
3841 // RFC 5705 defines a private-use prefix "EXPERIMENTAL"
3842 if ((in1len <= 12) || (strncmp (in1, "EXPERIMENTAL", 12) != 0)) {
3846 // - check the ctlkey (and ensure it is for TLS)
3848 //DEBUG// fprintf (stderr, "Hoping to find control key\n");
3849 ckn = (struct ctlkeynode_tls *) ctlkey_find (prng->buffer, security_tls, cmd->clientfd);
3852 // Now wipe the PRNG buffer to get rid of any sensitive bytes
3853 memset (prng->buffer, 0, TLSPOOL_PRNGBUFLEN);
3855 // If an error occurrend with the command, report it now
3857 send_error (cmd, EINVAL, "TLS PRNG request invalid");
3858 // ckn is NULL if err != 0, so no need for ctlkey_unfind()
3862 send_error (cmd, ENOENT, "Invalid control key");
3866 // Now actually invoke the PRNG command in the GnuTLS backend
3868 E_g2e ("GnuTLS PRNG based on session master key failed",
3869 gnutls_prf_rfc5705 (ckn->session,
3871 (in2len >= 0)? in2len: 0, (in2len >= 0) ? in2: NULL,
3872 prnglen, prng->buffer));
3873 err = err || (errno != 0);
3875 // Wipe temporary data / buffers for security reasons
3876 memset (in1, 0, sizeof (in1));
3877 memset (in2, 0, sizeof (in2));
3878 ctlkey_unfind ((struct ctlkeynode *) ckn);
3880 // Return the outcome to the user
3882 send_error (cmd, errno? errno: EIO, "PRNG in TLS backend failed");
3884 send_command (cmd, -1);
3889 /* Flying signer functionality. Create an on-the-fly certificate because
3890 * the lidentry daemon and/or application asks for this to represent the
3891 * local identity. Note that this will only work if the remote party
3892 * accepts the root identity under which on-the-signing is done.
3894 * When no root credentials have been configured, this function will
3895 * fail with GNUTLS_E_AGAIN; it may be used as a hint to try through
3896 * other (more conventional) means to obtain a client certificate.
3898 * The API of this function matches that of fetch_local_credentials()
3899 * and that is not a coincidence; this is a drop-in replacement in some
3902 * Limitations: The current implementation only supports X.509 certificates
3903 * to be generated on the fly. So, this will set LID_TYPE_X509, if anything.
3905 gtls_error certificate_onthefly (struct command *cmd) {
3906 gtls_error gtls_errno = GNUTLS_E_SUCCESS;
3907 gnutls_x509_crt_t otfcert;
3909 gnutls_x509_subject_alt_name_t altnmtp;
3914 if ((onthefly_issuercrt == NULL) || (onthefly_issuerkey == NULL) || (onthefly_subjectkey == NULL)) {
3915 // Not able to supply on-the-fly certificates; try someway else
3916 return GNUTLS_E_AGAIN;
3918 if (cmd->cmd.pio_data.pioc_starttls.localid [0] == '\0') {
3919 return GNUTLS_E_NO_CERTIFICATE_FOUND;
3921 if (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data != NULL) {
3922 free (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data);
3923 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = NULL;
3924 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
3928 // Create an empty certificate
3929 E_g2e ("Failed to initialise on-the-fly certificate",
3930 gnutls_x509_crt_init (&otfcert));
3931 if (gtls_errno != GNUTLS_E_SUCCESS) {
3936 // Fill the certificate with the usual field
3937 E_g2e ("Failed to set on-the-fly certificate to non-CA mode",
3938 gnutls_x509_crt_set_ca_status (otfcert, 0));
3939 E_g2e ("Failed to set on-the-fly certificate version",
3940 gnutls_x509_crt_set_version (otfcert, 3));
3941 onthefly_serial++; //TODO// Consider a random byte string
3942 E_g2e ("Failed to set on-the-fly serial number",
3943 gnutls_x509_crt_set_serial (otfcert, &onthefly_serial, sizeof (onthefly_serial)));
3944 // Skip gnutls_x509_crt_set_issuer_by_dn_by_oid(), added when signing
3946 E_g2e ("Failed to set on-the-fly activation time to now - 2 min",
3947 gnutls_x509_crt_set_activation_time (otfcert, now - 120));
3948 E_g2e ("Failed to set on-the-fly expiration time to now + 3 min",
3949 gnutls_x509_crt_set_expiration_time (otfcert, now + 180));
3950 E_g2e ("Setup certificate CN with local identity",
3951 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? */
3952 E_g2e ("Setup certificate OU with TLS Pool on-the-fly",
3953 gnutls_x509_crt_set_dn_by_oid (otfcert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "TLS Pool on-the-fly", 19));
3954 if (strchr (cmd->cmd.pio_data.pioc_starttls.localid, '@')) {
3955 // localid has the format of an emailAddress
3956 altnmtp = GNUTLS_SAN_RFC822NAME;
3958 // localid has the format of a dnsName
3959 altnmtp = GNUTLS_SAN_DNSNAME;
3961 E_g2e ("Failed to set subjectAltName to localid",
3962 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));
3963 //TODO:SKIP, hoping that signing adds: gnutls_x509_crt_set_authority_key_id()
3964 //TODO:SKIP, hoping that a cert without also works: gnutls_x509_crt_set_subjectkey_id()
3965 //TODO:SKIP? gnutls_x509_crt_set_extension_by_oid
3966 //TODO: gnutls_x509_crt_set_key_usage
3967 //TODO:SKIP? gnutls_x509_crt_set_ca_status
3968 for (i=0; i < svcusage_registry_size; i++) {
3969 if (strcmp (svcusage_registry [i].service, cmd->cmd.pio_data.pioc_starttls.service) == 0) {
3970 const char **walker;
3971 E_g2e ("Failed to setup basic key usage during on-the-fly certificate creation",
3972 gnutls_x509_crt_set_key_usage (otfcert, svcusage_registry [i].usage));
3973 walker = svcusage_registry [i].oids_non_critical;
3976 E_g2e ("Failed to append non-critical extended key purpose during on-the-fly certificate creation",
3977 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 0));
3981 walker = svcusage_registry [i].oids_critical;
3984 E_g2e ("Failed to append critical extended key purpose during on-the-fly certificate creation",
3985 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 1));
3992 E_g2e ("Failed to et the on-the-fly subject key",
3993 gnutls_x509_crt_set_key (otfcert, onthefly_subjectkey));
3994 /* TODO: The lock below should not be necessary; it is handled by p11-kit
3995 * or at least it ought to be. What I found however, was that
3996 * a client and server would try to use the onthefly_issuerkey
3997 * at virtually the same time, and then the second call to
3998 * C_SignInit returns CKR_OPERATION_ACTIVE. The lock solved this.
3999 * This makes me frown about server keys stored in PKCS #11...
4001 {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"); } }
4002 assert (pthread_mutex_lock (&onthefly_signer_lock) == 0);
4003 E_g2e ("Failed to sign on-the-fly certificate",
4004 gnutls_x509_crt_privkey_sign (otfcert, onthefly_issuercrt, onthefly_issuerkey, GNUTLS_DIG_SHA256, 0));
4005 pthread_mutex_unlock (&onthefly_signer_lock);
4008 // Construct cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data+size for this certificate
4009 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
4010 if (gtls_errno == GNUTLS_E_SUCCESS) {
4011 gtls_errno = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, NULL, &cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
4012 if (gtls_errno == GNUTLS_E_SHORT_MEMORY_BUFFER) {
4013 // This is as expected, now .size will have been set
4014 gtls_errno = GNUTLS_E_SUCCESS;
4016 if (gtls_errno = GNUTLS_E_SUCCESS) {
4017 // Something must be wrong if we receive OK
4018 gtls_errno = GNUTLS_E_INVALID_REQUEST;
4021 E_g2e ("Error while measuring on-the-fly certificate size",
4024 uint8_t *ptr = NULL;
4025 if (gtls_errno == GNUTLS_E_SUCCESS) {
4026 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size += 4 + strlen (onthefly_p11uri) + 1;
4027 ptr = malloc (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
4029 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
4030 gnutls_x509_crt_deinit (otfcert);
4031 return GNUTLS_E_MEMORY_ERROR;
4036 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = ptr;
4037 * (uint32_t *) ptr = htonl (LID_TYPE_X509 | LID_ROLE_BOTH);
4039 strcpy (ptr, onthefly_p11uri);
4040 ptr += strlen (onthefly_p11uri) + 1;
4041 restsz = cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size - 4 - strlen (onthefly_p11uri) - 1;
4042 E_g2e ("Failed to export on-the-fly certificate as a credential",
4043 gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, ptr, &restsz));
4044 char *pembuf [10000];
4045 size_t pemlen = sizeof (pembuf) - 1;
4046 int exporterror = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_PEM, pembuf, &pemlen);
4047 if (exporterror == 0) {
4048 pembuf [pemlen] = '\0';
4049 fprintf (stderr, "DEBUG: otfcert ::=\n%s\n", pembuf);
4051 fprintf (stderr, "DEBUG: otfcert export to PEM failed with %d, gtls_errno already was %d\n", exporterror, gtls_errno);
4056 // Cleanup the allocated and built structures
4057 gnutls_x509_crt_deinit (otfcert);
4060 // Return the overall result that might have stopped otf halfway