1 /* tlspool/starttls.c -- Setup and validation handler for TLS session */
19 #include <sys/types.h>
20 #include <sys/socket.h>
22 #include <arpa/inet.h>
24 #include <gnutls/gnutls.h>
25 #include <gnutls/pkcs11.h>
26 #include <gnutls/abstract.h>
28 #include <tlspool/internal.h>
35 #if EXPECTED_LID_TYPE_COUNT != LID_TYPE_CNT
36 #error "Set EXPECTED_LID_TYPE_COUNT in <tlspool/internal.h> to match LID_TYPE_CNT"
40 /* This module hosts TLS handlers which treat an individual connection.
42 * Initially, the TLS setup is processed, which means validating the
43 * connection. If and when this succeeds, a continued process is needed
44 * to encrypt and decrypt traffic while it is in transit.
46 * Every TLS connection (including the attempt to set it up) is hosted in
47 * its own thread. This means that it can abide time to wait for PINENTRY,
48 * LOCALID or LIDENTRY responses. It also means a very clear flow when the
49 * time comes to destroy a connection.
51 * While encrypting and decrypting traffic passing through, the thread
52 * will use its own poll() call, and thus offload the potentially large
53 * one of the main thread, which is supposed to be a low-traffic task.
54 * The set of file descriptors used by the session-handler threads are
55 * in contrast very small and can easily be started for every single
56 * packet passing through.
58 * Might the user terminate a process while this one is waiting for a
59 * callback command request, then the main TLS pool thread will take
60 * care of taking down this thread. To that end, it sets the followup
61 * pointer that normally holds a callback response to NULL, and then
62 * permits this thread to run again. This will lead to a shutdown of
63 * this process, and proper closing of all connections. The remote peer
64 * will therefore see the result of a local kill as a connection reset.
66 * In case one of the end points of the connection is terminated, a
67 * similar thing will happen; the thread will terminate itself after
68 * a cleanup of any outstanding resources. This, once again, leads
69 * to passing on the reset of a connection between the encrypted and
70 * side of the connection.
76 * GnuTLS infrastructure setup.
77 * Session-shared DH-keys, credentials structures, and so on.
79 static gnutls_dh_params_t dh_params;
82 gnutls_credentials_type_t credtp;
86 #define EXPECTED_SRV_CREDCOUNT 3
87 #define EXPECTED_CLI_CREDCOUNT 3
88 static struct credinfo srv_creds [EXPECTED_SRV_CREDCOUNT];
89 static struct credinfo cli_creds [EXPECTED_CLI_CREDCOUNT];
90 static int srv_credcount = 0;
91 static int cli_credcount = 0;
92 static const char const *onthefly_p11uri = "pkcs11:manufacturer=ARPA2.net;token=TLS+Pool+internal;object=on-the-fly+signer;type=private;serial=1";
93 static unsigned long long onthefly_serial; //TODO: Fill with now * 1000
94 static gnutls_x509_crt_t onthefly_issuercrt = NULL;
95 static gnutls_privkey_t onthefly_issuerkey = NULL;
96 static gnutls_x509_privkey_t onthefly_subjectkey = NULL;
97 static pthread_mutex_t onthefly_signer_lock = PTHREAD_MUTEX_INITIALIZER;
99 /* The local variation on the ctlkeynode structure, with TLS-specific fields
101 struct ctlkeynode_tls {
102 struct ctlkeynode regent; // Structure for ctlkey_register()
103 gnutls_session_t session; // Additional data specifically for TLS
104 pthread_t owner; // For interruption of copycat()
105 int plainfd; // Plain-side connection
106 int cryptfd; // Crypt-side connection
109 /* The list of accepted Exporter Label Prefixes for starttls_prng()
111 char *tlsprng_label_prefixes [] = {
112 // Forbidden by RFC 5705: "client finished",
113 // Forbidden by RFC 5705: "server finished",
114 // Forbidden by RFC 5705: "master secret",
115 // Forbidden by RFC 5705: "key expansion",
116 "client EAP encryption", // not suited for DTLS
117 "ttls keying material", // not suited for DTLS
118 "ttls challenge", // not suited for DTLS
119 "EXTRACTOR-dtls_srtp",
120 "EXPORTER_DTLS_OVER_SCTP",
121 "EXPORTER-ETSI-TC-M2M-Bootstrap",
122 "EXPORTER-ETSI-TC-M2M-Connection",
124 "EXPORTER_GBA_Digest",
125 "EXPORTER: teap session key seed", // not suited for DTLS
126 "EXPORTER-oneM2M-Bootstrap",
127 "EXPORTER-oneM2M-Connection",
131 /* The registry with the service names that are deemed safe for an
132 * anonymous precursor phase; that is, the service names that may offer
133 * ANON-DH initially, and immediately renegotiate an authenticated
134 * connection. See doc/anonymising-precursor.* for more information.
136 * The registry is ordered by case-independent service name, so it can
137 * be searched in 2log time. Service names are as defined by IANA in the
138 * "Service Name and Transport Protocol Port Number Registry".
140 * The entries in the registry depend on the role played; either as a
141 * client or as a server. This refers to the local node, and depends on
142 * uncertainty of the remote party's TLS implementation and whether or
143 * not the protocol could lead to the remote sending information that
144 * requires authentication before the secure renogiation into an
145 * authenticated connection has been completed by this side. This is
146 * a protocol-dependent matter and the registry provided here serves to
147 * encapsulate this knowledge inside the TLS Pool instead of bothering
148 * application designers with it. Entries that are not found in the
149 * registry are interpreted as not allowing an anonymising precursor.
151 * Note that ANONPRE_EXTEND_MASTER_SECRET cannot be verified before
152 * GnuTLS version 3.4.0; see "imap" below for the resulting impact. This
153 * also impacts dynamic linking, because 3.4.0 introduces the new function
154 * gnutls_ext_get_data() that is used for this requirement.
156 #define ANONPRE_FORBID 0x00
157 #define ANONPRE_CLIENT 0x01
158 #define ANONPRE_SERVER 0x02
159 #define ANONPRE_EITHER (ANONPRE_CLIENT | ANONPRE_SERVER)
160 #define ANONPRE_EXTEND_MASTER_SECRET 0x10
161 struct anonpre_regentry {
165 struct anonpre_regentry anonpre_registry [] = {
166 /* This registry is commented out for now, although the code to use it seems
167 * to work fine. GnuTLS however, does not seem to support making the switch
168 * from ANON-ECDH to an authenticated handshake. Details:
169 * http://lists.gnutls.org/pipermail/gnutls-help/2015-November/003998.html
171 { "generic_anonpre", ANONPRE_EITHER }, // Name invalid as per RFC 6335
172 { "http", ANONPRE_CLIENT }, // Server also if it ignores client ID
173 #if GNUTLS_VERSION_NUMBER < 0x030400
174 { "imap", ANONPRE_SERVER },
176 { "imap", ANONPRE_EITHER | ANONPRE_EXTEND_MASTER_SECRET },
178 { "pop3", ANONPRE_EITHER },
179 { "smtp", ANONPRE_EITHER },
181 * End of commenting out the registry
184 const int anonpre_registry_size = sizeof (anonpre_registry) / sizeof (struct anonpre_regentry);
187 /* The registry of Key Usage and Extended Key Usage for any given service name.
189 static const char *http_noncrit [] = { GNUTLS_KP_TLS_WWW_SERVER, GNUTLS_KP_TLS_WWW_CLIENT, NULL };
190 struct svcusage_regentry {
193 const char **oids_non_critical;
194 const char **oids_critical;
196 struct svcusage_regentry svcusage_registry [] = {
198 GNUTLS_KEY_KEY_ENCIPHERMENT |
199 GNUTLS_KEY_KEY_AGREEMENT,
204 GNUTLS_KEY_DIGITAL_SIGNATURE |
205 GNUTLS_KEY_KEY_ENCIPHERMENT |
206 GNUTLS_KEY_KEY_AGREEMENT,
211 const int svcusage_registry_size = sizeof (svcusage_registry) / sizeof (struct svcusage_regentry);
214 /* The maximum number of bytes that can be passed over a TLS connection before
215 * the authentication is complete in case of a anonymous precursor within a
216 * protocol that ensures that this cannot be a problem.
220 /* The priorities cache for "NORMAL" -- used to preconfigure the server,
221 * actually to overcome its unwillingness to perform the handshake, and
222 * leave it to srv_clienthello() to setup the priority string.
224 gnutls_priority_t priority_normal;
227 /* Map a GnuTLS call (usually a function call) to a POSIX errno,
228 * optionally reporting an errstr to avoid loosing information.
229 * Retain errno if it already exists.
230 * Continue if errno differs from 0, GnuTLS may "damage" it even when OK. */
231 #define E_g2e(errstr,gtlscall) { \
232 if (gtls_errno == GNUTLS_E_SUCCESS) { \
233 gtls_errno = (gtlscall); \
234 if (gtls_errno != GNUTLS_E_SUCCESS) { \
235 error_gnutls2posix (gtls_errno, errstr); \
240 /* Cleanup when GnuTLS leaves errno damaged but returns no gtls_errno */
241 #define E_gnutls_clear_errno() { \
242 if (gtls_errno == GNUTLS_E_SUCCESS) { \
247 /* Error number translation, including error string setup. See E_g2e(). */
248 void error_gnutls2posix (int gtls_errno, char *new_errstr) {
250 register int newerrno;
253 if (gtls_errno == GNUTLS_E_SUCCESS) {
256 errstr = error_getstring ();
257 if (errstr != NULL) {
261 // Report the textual error
262 if (new_errstr == NULL) {
263 new_errstr = "GnuTLS error";
265 tlog (TLOG_TLS, LOG_ERR, "%s: %s",
267 gnutls_strerror (gtls_errno));
268 error_setstring (new_errstr);
270 // Translate error to a POSIX errno value
271 switch (gtls_errno) {
272 case GNUTLS_E_SUCCESS:
274 case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
275 case GNUTLS_E_UNKNOWN_CIPHER_TYPE:
276 case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
277 case GNUTLS_E_UNWANTED_ALGORITHM:
278 case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
279 case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
280 case GNUTLS_E_X509_UNKNOWN_SAN:
281 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
282 case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
283 case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
284 case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
285 case GNUTLS_E_NO_CIPHER_SUITES:
286 case GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED:
287 case GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE:
288 case GNUTLS_E_UNKNOWN_HASH_ALGORITHM:
289 case GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE:
290 case GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE:
291 case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
292 case GNUTLS_E_UNKNOWN_ALGORITHM:
293 case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
294 case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
295 case GNUTLS_E_X509_UNSUPPORTED_OID:
296 case GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE:
297 case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
298 case GNUTLS_E_ECC_NO_SUPPORTED_CURVES:
299 case GNUTLS_E_ECC_UNSUPPORTED_CURVE:
300 case GNUTLS_E_X509_UNSUPPORTED_EXTENSION:
301 case GNUTLS_E_NO_CERTIFICATE_STATUS:
302 case GNUTLS_E_NO_APPLICATION_PROTOCOL:
303 #ifdef GNUTLS_E_NO_SELF_TEST
304 case GNUTLS_E_NO_SELF_TEST:
306 newerrno = EOPNOTSUPP;
308 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
309 case GNUTLS_E_INVALID_REQUEST:
312 case GNUTLS_E_INVALID_SESSION:
313 case GNUTLS_E_REHANDSHAKE:
314 case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
317 case GNUTLS_E_PUSH_ERROR:
318 case GNUTLS_E_PULL_ERROR:
319 case GNUTLS_E_PREMATURE_TERMINATION:
320 case GNUTLS_E_SESSION_EOF:
321 newerrno = ECONNRESET;
323 case GNUTLS_E_UNEXPECTED_PACKET:
324 case GNUTLS_E_WARNING_ALERT_RECEIVED:
325 case GNUTLS_E_FATAL_ALERT_RECEIVED:
326 case GNUTLS_E_LARGE_PACKET:
327 case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
328 case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
329 case GNUTLS_E_MPI_SCAN_FAILED:
330 case GNUTLS_E_DECRYPTION_FAILED:
331 case GNUTLS_E_DECOMPRESSION_FAILED:
332 case GNUTLS_E_COMPRESSION_FAILED:
333 case GNUTLS_E_BASE64_DECODING_ERROR:
334 case GNUTLS_E_MPI_PRINT_FAILED:
335 case GNUTLS_E_GOT_APPLICATION_DATA:
336 case GNUTLS_E_RECORD_LIMIT_REACHED:
337 case GNUTLS_E_ENCRYPTION_FAILED:
338 case GNUTLS_E_PK_ENCRYPTION_FAILED:
339 case GNUTLS_E_PK_DECRYPTION_FAILED:
340 case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
341 case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
342 case GNUTLS_E_PKCS1_WRONG_PAD:
343 case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
344 case GNUTLS_E_FILE_ERROR:
345 case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
346 case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
347 case GNUTLS_E_ASN1_DER_ERROR:
348 case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
349 case GNUTLS_E_ASN1_GENERIC_ERROR:
350 case GNUTLS_E_ASN1_VALUE_NOT_VALID:
351 case GNUTLS_E_ASN1_TAG_ERROR:
352 case GNUTLS_E_ASN1_TAG_IMPLICIT:
353 case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
354 case GNUTLS_E_ASN1_SYNTAX_ERROR:
355 case GNUTLS_E_ASN1_DER_OVERFLOW:
356 case GNUTLS_E_TOO_MANY_EMPTY_PACKETS:
357 case GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS:
358 case GNUTLS_E_SRP_PWD_PARSING_ERROR:
359 case GNUTLS_E_BASE64_ENCODING_ERROR:
360 case GNUTLS_E_OPENPGP_KEYRING_ERROR:
361 case GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR:
362 case GNUTLS_E_OPENPGP_SUBKEY_ERROR:
363 case GNUTLS_E_CRYPTO_ALREADY_REGISTERED:
364 case GNUTLS_E_HANDSHAKE_TOO_LARGE:
365 case GNUTLS_E_BAD_COOKIE:
366 case GNUTLS_E_PARSING_ERROR:
367 case GNUTLS_E_CERTIFICATE_LIST_UNSORTED:
368 case GNUTLS_E_NO_PRIORITIES_WERE_SET:
369 #ifdef GNUTLS_E_PK_GENERATION_ERROR
370 case GNUTLS_E_PK_GENERATION_ERROR:
372 #ifdef GNUTLS_E_SELF_TEST_ERROR
373 case GNUTLS_E_SELF_TEST_ERROR:
375 #ifdef GNUTLS_E_SOCKETS_INIT_ERROR
376 case GNUTLS_E_SOCKETS_INIT_ERROR:
380 case GNUTLS_E_MEMORY_ERROR:
381 case GNUTLS_E_SHORT_MEMORY_BUFFER:
387 case GNUTLS_E_EXPIRED:
388 case GNUTLS_E_TIMEDOUT:
389 newerrno = ETIMEDOUT;
391 case GNUTLS_E_DB_ERROR:
398 case GNUTLS_E_SRP_PWD_ERROR:
399 case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
400 case GNUTLS_E_HASH_FAILED:
401 case GNUTLS_E_PK_SIGN_FAILED:
402 case GNUTLS_E_CERTIFICATE_ERROR:
403 case GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION:
404 case GNUTLS_E_KEY_USAGE_VIOLATION:
405 case GNUTLS_E_NO_CERTIFICATE_FOUND:
406 case GNUTLS_E_OPENPGP_UID_REVOKED:
407 case GNUTLS_E_OPENPGP_GETKEY_FAILED:
408 case GNUTLS_E_PK_SIG_VERIFY_FAILED:
409 case GNUTLS_E_ILLEGAL_SRP_USERNAME:
410 case GNUTLS_E_INVALID_PASSWORD:
411 case GNUTLS_E_MAC_VERIFY_FAILED:
412 case GNUTLS_E_IA_VERIFY_FAILED:
413 case GNUTLS_E_UNKNOWN_SRP_USERNAME:
414 case GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR:
415 case GNUTLS_E_USER_ERROR:
416 case GNUTLS_E_AUTH_ERROR:
419 case GNUTLS_E_INTERRUPTED:
422 case GNUTLS_E_INTERNAL_ERROR:
423 case GNUTLS_E_CONSTRAINT_ERROR:
424 case GNUTLS_E_ILLEGAL_PARAMETER:
427 case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
428 newerrno = ECONNREFUSED;
430 case GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY:
431 case GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY:
432 #ifdef GNUTLS_E_LIB_IN_ERROR_STATE
433 case GNUTLS_E_LIB_IN_ERROR_STATE:
437 case GNUTLS_E_RANDOM_FAILED:
440 case GNUTLS_E_CRYPTODEV_IOCTL_ERROR:
441 case GNUTLS_E_CRYPTODEV_DEVICE_ERROR:
442 case GNUTLS_E_HEARTBEAT_PONG_RECEIVED:
443 case GNUTLS_E_HEARTBEAT_PING_RECEIVED:
444 case GNUTLS_E_PKCS11_ERROR:
445 case GNUTLS_E_PKCS11_LOAD_ERROR:
446 case GNUTLS_E_PKCS11_PIN_ERROR:
447 case GNUTLS_E_PKCS11_SLOT_ERROR:
448 case GNUTLS_E_LOCKING_ERROR:
449 case GNUTLS_E_PKCS11_ATTRIBUTE_ERROR:
450 case GNUTLS_E_PKCS11_DEVICE_ERROR:
451 case GNUTLS_E_PKCS11_DATA_ERROR:
452 case GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR:
453 case GNUTLS_E_PKCS11_KEY_ERROR:
454 case GNUTLS_E_PKCS11_PIN_EXPIRED:
455 case GNUTLS_E_PKCS11_PIN_LOCKED:
456 case GNUTLS_E_PKCS11_SESSION_ERROR:
457 case GNUTLS_E_PKCS11_SIGNATURE_ERROR:
458 case GNUTLS_E_PKCS11_TOKEN_ERROR:
459 case GNUTLS_E_PKCS11_USER_ERROR:
460 case GNUTLS_E_CRYPTO_INIT_FAILED:
461 case GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE:
462 case GNUTLS_E_TPM_ERROR:
463 case GNUTLS_E_TPM_KEY_PASSWORD_ERROR:
464 case GNUTLS_E_TPM_SRK_PASSWORD_ERROR:
465 case GNUTLS_E_TPM_SESSION_ERROR:
466 case GNUTLS_E_TPM_KEY_NOT_FOUND:
467 case GNUTLS_E_TPM_UNINITIALIZED:
468 case GNUTLS_E_OCSP_RESPONSE_ERROR:
469 case GNUTLS_E_RANDOM_DEVICE_ERROR:
471 newerrno = EREMOTEIO;
484 /* Generate Diffie-Hellman parameters - for use with DHE
485 * kx algorithms. TODO: These should be discarded and regenerated
486 * once a day, once a week or once a month. Depending on the
487 * security requirements.
489 static gtls_error generate_dh_params (void) {
491 int gtls_errno = GNUTLS_E_SUCCESS;
492 bits = gnutls_sec_param_to_pk_bits (
494 GNUTLS_SEC_PARAM_LEGACY);
495 //TODO// Acquire DH-params lock
496 E_g2e ("Failed to initialise DH params",
497 gnutls_dh_params_init (
499 E_g2e ("Failed to generate DH params",
500 gnutls_dh_params_generate2 (
503 //TODO// Release DH-params lock
507 /* Load Diffie-Hellman parameters from file - or generate them when load fails.
509 static gtls_error load_dh_params (void) {
510 gnutls_dh_params_t dhp;
511 gnutls_datum_t pkcs3;
512 char *filename = cfg_tls_dhparamfile ();
513 int gtls_errno = GNUTLS_E_SUCCESS;
514 bzero (&pkcs3, sizeof (pkcs3));
516 E_g2e ("No PKCS #3 PEM file with DH params",
520 E_gnutls_clear_errno ();
521 E_g2e ("Failed to initialise DH params",
522 gnutls_dh_params_init (
524 E_g2e ("Failed to import DH params from PKCS #3 PEM",
525 gnutls_dh_params_import_pkcs3 (
528 GNUTLS_X509_FMT_PEM));
529 E_gnutls_clear_errno ();
531 if (pkcs3.data != NULL) {
534 if (gtls_errno != GNUTLS_E_SUCCESS) {
536 // File failed to load, so try to generate fresh DH params
537 int gtls_errno_stack0;
538 gtls_errno = GNUTLS_E_SUCCESS;
539 tlog (TLOG_CRYPTO, LOG_DEBUG, "Failed to load DH params from %s; generating fresh parameters", filename);
540 E_g2e ("Failed to generate DH params",
541 generate_dh_params ());
542 gtls_errno_stack0 = gtls_errno;
543 //TODO// Acquire DH-params lock
544 E_g2e ("Failed to format DH params as PKCS #3 PEM",
545 gnutls_dh_params_export2_pkcs3 (
549 //TODO// Release DH-params lock
550 if ((gtls_errno == GNUTLS_E_SUCCESS) && (filename != NULL)) {
553 // Best effor file save -- readback will parse
554 pemf = fopen (filename, "w");
556 fwrite (pkcs3.data, 1, pkcs3.size, pemf);
558 tlog (TLOG_FILES, LOG_DEBUG, "Saved DH params to %s (best-effort)", filename);
560 E_gnutls_clear_errno ();
562 gtls_errno = gtls_errno_stack0;
564 gnutls_dh_params_t old_dh;
565 //TODO// Acquire DH-params lock
568 //TODO// Release DH-params lock
570 gnutls_dh_params_deinit (old_dh);
576 /* Remove DH parameters, to be used during program cleanup. */
577 static void remove_dh_params (void) {
579 gnutls_dh_params_deinit (dh_params);
585 /* A log printing function
587 void log_gnutls (int level, const char *msg) {
588 tlog (TLOG_TLS, level, "GnuTLS: %s", msg);
592 /* Implement the GnuTLS function for token insertion callback. This function
593 * refers back to the generic callback for token insertion.
595 int gnutls_token_callback (void *const userdata,
596 const char *const label,
598 if (token_callback (label, retry)) {
599 return GNUTLS_E_SUCCESS;
601 return GNUTLS_E_PKCS11_TOKEN_ERROR;
607 * Implement the GnuTLS function for PIN callback. This function calls
608 * the generic PIN callback operation.
610 int gnutls_pin_callback (void *userdata,
612 const char *token_url,
613 const char *token_label,
617 if (flags & GNUTLS_PIN_SO) {
618 return GNUTLS_E_USER_ERROR;
620 if (pin_callback (attempt, token_url, token_label, pin, pin_max)) {
623 return GNUTLS_E_PKCS11_PIN_ERROR;
628 /* Register a PKCS #11 provider with the GnuTLS environment. */
629 void starttls_pkcs11_provider (char *p11path) {
630 unsigned int token_seq = 0;
632 if (gnutls_pkcs11_add_provider (p11path, NULL) != 0) {
633 fprintf (stderr, "Failed to register PKCS #11 library %s with GnuTLS\n", p11path);
636 while (gnutls_pkcs11_token_get_url (token_seq, 0, &p11uri) == 0) {
638 fprintf (stderr, "DEBUG: Found token URI %s\n", p11uri);
640 //TODO// if (gnutls_pkcs11_token_get_info (p11uri, GNUTLS_PKCS11_TOKEN_LABEL-of-SERIAL-of-MANUFACTURER-of-MODEL, output, utput_size) == 0) { ... }
641 gnutls_free (p11uri);
644 //TODO// Select token by name (value)
645 //TODO// if PIN available then set it up
646 //TODO:WHY?// free_p11pin ();
650 /* The global and static setup function for the starttls functions.
652 void setup_starttls (void) {
653 int setup_starttls_credentials (void); /* Defined below */
655 int gtls_errno = GNUTLS_E_SUCCESS;
656 char *otfsigcrt, *otfsigkey;
658 // Setup configuration variables
659 maxpreauth = cfg_tls_maxpreauth ();
661 // Basic library actions
662 tlog (TLOG_TLS, LOG_DEBUG, "Compiled against GnuTLS version %s", GNUTLS_VERSION);
663 curver = gnutls_check_version (GNUTLS_VERSION);
664 tlog (TLOG_TLS, LOG_DEBUG, "Running against %s GnuTLS version %s", curver? "acceptable": "OLDER", curver? curver: gnutls_check_version (NULL));
665 E_g2e ("GnuTLS global initialisation failed",
666 gnutls_global_init ());
667 E_gnutls_clear_errno ();
668 E_g2e ("GnuTLS PKCS #11 initialisation failed",
670 GNUTLS_PKCS11_FLAG_MANUAL, NULL));
672 // Setup logging / debugging
673 if (cfg_log_level () == LOG_DEBUG) {
674 gnutls_global_set_log_function (log_gnutls);
675 gnutls_global_set_log_level (9);
678 // Setup callbacks for user communication
679 gnutls_pkcs11_set_token_function (gnutls_token_callback, NULL);
680 gnutls_pkcs11_set_pin_function (gnutls_pin_callback, NULL);
682 // Setup DH parameters
683 E_g2e ("Loading DH params failed",
686 // Setup shared credentials for all client server processes
687 E_g2e ("Failed to setup GnuTLS callback credentials",
688 setup_starttls_credentials ());
690 // Parse the default priority string
691 E_g2e ("Failed to setup NORMAL priority cache",
692 gnutls_priority_init (&priority_normal, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+COMP-NULL:+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:+ANON-ECDH:+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
693 // gnutls_priority_init (&priority_normal, "NORMAL:-RSA:+ANON-ECDH:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
695 // Try to setup on-the-fly signing key / certificate and gen a certkey
696 otfsigcrt = cfg_tls_onthefly_signcert ();
697 otfsigkey = cfg_tls_onthefly_signkey ();
698 fprintf (stderr, "DEBUG: gtls_errno = %d, otfsigcrt == %s, otfsigkey == %s\n", gtls_errno, otfsigcrt? otfsigcrt: "NULL", otfsigkey? otfsigkey: "NULL");
699 if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigcrt != NULL)) {
700 FILE *crtfile = NULL;
701 fprintf (stderr, "DEBUG: gtls_errno==%d when initialising onthefly_issuercrt\n", gtls_errno);
702 E_g2e ("Failed to initialise on-the-fly issuer certificate structure",
703 gnutls_x509_crt_init (&onthefly_issuercrt));
704 if (strncmp (otfsigcrt, "file:", 5) == 0) {
705 // Provisionary support for the "file:" prefix
708 crtfile = fopen (otfsigcrt, "r");
709 if (crtfile == NULL) {
710 E_g2e ("Failed to open on-the-fly issuer certificate file",
711 GNUTLS_E_FILE_ERROR);
712 fprintf (stderr, "DEBUG: gtls_errno==%d after failing to open file for onthefly_issuercrt\n", gtls_errno);
715 size_t len = fread (crt, 1, sizeof (crt), crtfile);
716 if (ferror (crtfile)) {
717 E_g2e ("Failed to read on-the-fly issuer certificate from file",
718 GNUTLS_E_FILE_ERROR);
719 } else if ((len >= sizeof (crt)) || !feof (crtfile)) {
720 E_g2e ("Unexpectedly long on-the-fly issuer certificate file",
721 GNUTLS_E_FILE_ERROR);
723 gnutls_datum_t cd = {
727 fprintf (stderr, "DEBUG: gtls_errno==%d before importing onthefly_issuercrt\n", gtls_errno);
728 E_g2e ("Failed to import on-the-fly certificate from file",
729 gnutls_x509_crt_import (onthefly_issuercrt, &cd, GNUTLS_X509_FMT_DER));
730 fprintf (stderr, "DEBUG: gtls_errno==%d after importing onthefly_issuercrt\n", gtls_errno);
735 if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigkey != NULL)) {
736 E_g2e ("Failed to initialise on-the-fly issuer private key structure",
737 gnutls_privkey_init (&onthefly_issuerkey));
738 fprintf (stderr, "DEBUG: before onthefly p11 import, gtlserrno = %d\n", gtls_errno);
739 E_g2e ("Failed to import pkcs11: URI into on-the-fly issuer private key",
740 gnutls_privkey_import_pkcs11_url (onthefly_issuerkey, otfsigkey));
741 fprintf (stderr, "DEBUG: after onthefly p11 import, gtlserrno = %d\n", gtls_errno);
743 fprintf (stderr, "DEBUG: When it matters, gtls_errno = %d, onthefly_issuercrt %s NULL, onthefly_issuerkey %s NULL\n", gtls_errno, onthefly_issuercrt?"!=":"==", onthefly_issuerkey?"!=":"==");
744 if ((gtls_errno == GNUTLS_E_SUCCESS) && (onthefly_issuercrt != NULL) && (onthefly_issuerkey != NULL)) {
745 E_g2e ("Failed to initialise on-the-fly certificate session key",
746 gnutls_x509_privkey_init (&onthefly_subjectkey));
747 E_g2e ("Failed to generate on-the-fly certificate session key",
748 gnutls_x509_privkey_generate (onthefly_subjectkey, GNUTLS_PK_RSA, 2048 /*TODO:FIXED*/, 0));
749 if (gtls_errno == GNUTLS_E_SUCCESS) {
750 tlog (TLOG_TLS, LOG_INFO, "Setup for on-the-fly signing with the TLS Pool");
752 tlog (TLOG_TLS, LOG_ERR, "Failed to setup on-the-fly signing (shall continue without it)");
753 gnutls_x509_privkey_deinit (onthefly_subjectkey);
754 onthefly_subjectkey = NULL;
757 gtls_errno = GNUTLS_E_SUCCESS;
758 E_gnutls_clear_errno ();
760 if (onthefly_subjectkey == NULL) {
761 if (onthefly_issuercrt != NULL) {
762 gnutls_x509_crt_deinit (onthefly_issuercrt);
763 onthefly_issuercrt = NULL;
765 if (onthefly_issuerkey != NULL) {
766 gnutls_privkey_deinit (onthefly_issuerkey);
767 onthefly_issuerkey = NULL;
771 // Finally, check whether there was any error setting up GnuTLS
772 if (gtls_errno != GNUTLS_E_SUCCESS) {
773 tlog (TLOG_TLS, LOG_CRIT, "FATAL: GnuTLS setup failed: %s", gnutls_strerror (gtls_errno));
777 //MOVED// // Setup the management databases
778 //MOVED// tlog (TLOG_DB, LOG_DEBUG, "Setting up management databases");
779 //MOVED// E_e2e ("Failed to setup management databases",
780 //MOVED// setup_management ());
781 //MOVED// if (errno != 0) {
782 //MOVED// tlog (TLOG_DB, LOG_CRIT, "FATAL: Management databases setup failed: %s", strerror (errno));
787 /* Cleanup the structures and resources that were setup for handling TLS.
789 void cleanup_starttls (void) {
790 void cleanup_starttls_credentials (void); /* Defined below */
791 //MOVED// cleanup_management ();
792 if (onthefly_subjectkey != NULL) {
793 gnutls_x509_privkey_deinit (onthefly_subjectkey);
794 onthefly_subjectkey = NULL;
796 if (onthefly_issuercrt != NULL) {
797 gnutls_x509_crt_deinit (onthefly_issuercrt);
798 onthefly_issuercrt = NULL;
800 if (onthefly_issuerkey != NULL) {
801 gnutls_privkey_deinit (onthefly_issuerkey);
802 onthefly_issuerkey = NULL;
804 cleanup_starttls_credentials ();
806 gnutls_pkcs11_set_pin_function (NULL, NULL);
807 gnutls_pkcs11_set_token_function (NULL, NULL);
808 gnutls_pkcs11_deinit ();
809 gnutls_priority_deinit (priority_normal);
810 gnutls_global_deinit ();
815 * The copycat function is a bidirectional transport between the given
816 * remote and local sockets, but it will encrypt traffic from local to
817 * remote, and decrypt traffic from remote to local. It will do this
818 * until one of the end points is shut down, at which time it will
819 * return and assume the context will close down both pre-existing
822 * This copycat actually has a few sharp claws to watch for -- shutdown
823 * of sockets may drop the last bit of information sent. First, the
824 * signal POLLHUP is best ignored because it travels asynchronously.
825 * Second, reading 0 is a good indicator of end-of-file and may be
826 * followed by an shutdown of reading from that stream. But, more
827 * importantly, the other side must have this information forwarded
828 * so it can shutdown. This means that a shutdown for writing to that
829 * stream is to be sent. Even when *both* sides have agreed to not send
830 * anything, they may still not have received all they were offered for
831 * reading, so we should SO_LINGER on the sockets so they can acknowledge,
832 * and after a timeout we can establish that shutdown failed and log and
833 * return an error for it.
834 * Will you believe that I had looked up if close() would suffice? The man
835 * page clearly stated yes. However, these articles offer much more detail:
836 * http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable
837 * http://www.greenend.org.uk/rjk/tech/poll.html
839 * This function blocks during its call to poll(), in a state that can easily
840 * be restarted. This is when thread cancellation is temporarily enabled.
841 * Other threads may use this to cancel the thread and have it joined with that
842 * thread which will subsume its tasks and restart the handshake. We might
843 * later make this more advanced, by using a cancel stack push/pull mechanisms
844 * to ensure that recv() always results in send() in spite of cancellation.
846 * The return value of copycat is a GNUTLS_E_ code, usually GNUTLS_E_SUCCESS.
847 * For the moment, only one special value is of concern, namely
848 * GNUTLS_E_REHANDSHAKE which client or server side may receive when an
849 * attempt is made to renegotiate the security of the connection.
851 static int copycat (int local, int remote, gnutls_session_t wrapped, int client) {
853 struct pollfd inout [3];
855 struct linger linger = { 1, 10 };
857 int retval = GNUTLS_E_SUCCESS;
859 inout [0].fd = local;
860 inout [1].fd = remote;
861 inout [2].fd = client;
862 have_client = inout [2].fd >= 0;
864 inout [2].revents = 0; // Will not be written by poll
865 //FORK!=DETACH// inout [2].fd = ctlkey_signalling_fd;
867 inout [0].events = POLLIN;
868 inout [1].events = POLLIN;
869 inout [2].events = 0; // error events only
870 tlog (TLOG_COPYCAT, LOG_DEBUG, "Starting copycat cycle for local=%d, remote=%d, control=%d", local, remote, client);
871 while (((inout [0].events | inout [1].events) & POLLIN) != 0) {
873 assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) == 0);
874 pthread_testcancel (); // Efficiency & Certainty
875 polled = poll (inout, have_client? 3: 2, -1);
876 assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
878 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat polling returned an error");
879 break; // Polling sees an error
881 if (inout [0].revents & POLLIN) {
882 // Read local and encrypt to remote
883 sz = recv (local, buf, sizeof (buf), MSG_DONTWAIT | MSG_NOSIGNAL);
884 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d local bytes (or error<0) from %d", (int) sz, local);
886 tlog (TLOG_COPYCAT, LOG_ERR, "Error while receiving: %s", strerror (errno));
887 break; // stream error
888 } else if (sz == 0) {
889 inout [0].events &= ~POLLIN;
890 shutdown (local, SHUT_RD);
891 setsockopt (remote, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
892 gnutls_bye (wrapped, GNUTLS_SHUT_WR);
893 } else if (gnutls_record_send (wrapped, buf, sz) != sz) {
894 tlog (TLOG_COPYCAT, LOG_ERR, "gnutls_record_send() failed to pass on the requested bytes");
895 break; // communication error
897 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to remote %d", (int) sz, remote);
900 if (inout [1].revents & POLLIN) {
901 // Read remote and decrypt to local
902 sz = gnutls_record_recv (wrapped, buf, sizeof (buf));
903 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d remote bytes from %d (or error if <0)", (int) sz, remote);
905 //TODO// Process GNUTLS_E_REHANDSHAKE
906 if (sz == GNUTLS_E_REHANDSHAKE) {
907 tlog (TLOG_TLS, LOG_INFO, "Received renegotiation request over TLS handle %d", remote);
908 retval = GNUTLS_E_REHANDSHAKE;
910 } else if (gnutls_error_is_fatal (sz)) {
911 tlog (TLOG_TLS, LOG_ERR, "GnuTLS fatal error: %s", gnutls_strerror (sz));
912 break; // stream error
914 tlog (TLOG_TLS, LOG_INFO, "GnuTLS recoverable error: %s", gnutls_strerror (sz));
916 } else if (sz == 0) {
917 inout [1].events &= ~POLLIN;
918 shutdown (remote, SHUT_RD);
919 setsockopt (local, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
920 shutdown (local, SHUT_WR);
921 } else if (send (local, buf, sz, MSG_DONTWAIT | MSG_NOSIGNAL) != sz) {
922 break; // communication error
924 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to local %d", (int) sz, local);
927 inout [0].revents &= ~(POLLIN | POLLHUP); // Thy copying cat?
928 inout [1].revents &= ~(POLLIN | POLLHUP); // Retract thee claws!
929 if ((inout [0].revents | inout [1].revents) & ~POLLIN) {
930 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat data connection polling returned a special condition");
931 break; // Apparently, one of POLLERR, POLLHUP, POLLNVAL
933 if (inout [2].revents & ~POLLIN) {
935 // This case is currently not ever triggered
936 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat control connection polling returned a special condition");
937 break; // Apparently, one of POLLERR, POLLHUP, POLLNVAL
939 inout [2].fd = client;
940 have_client = inout [2].fd >= 0;
942 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal to set control fd to %d", inout [2].fd);
944 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal that could be ignored");
950 tlog (TLOG_COPYCAT, LOG_DEBUG, "Ending copycat cycle for local=%d, remote=%d", local, remote);
955 /* The callback function that retrieves certification information from either
956 * the client or the server in the course of the handshake procedure.
958 gtls_error clisrv_cert_retrieve (gnutls_session_t session,
959 const gnutls_datum_t* req_ca_dn,
961 const gnutls_pk_algorithm_t* pk_algos,
963 gnutls_pcert_st** pcert,
964 unsigned int *pcert_length,
965 gnutls_privkey_t *pkey) {
966 gnutls_certificate_type_t certtp;
967 gnutls_pcert_st *pc = NULL;
970 gnutls_datum_t privdatum = { NULL, 0 };
971 gnutls_datum_t certdatum = { NULL, 0 };
972 gnutls_openpgp_crt_t pgpcert = NULL;
973 gnutls_openpgp_privkey_t pgppriv = NULL;
974 int gtls_errno = GNUTLS_E_SUCCESS;
978 char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.localid)];
979 size_t snilen = sizeof (sni);
986 gtls_error fetch_local_credentials (struct command *cmd);
987 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum);
990 // Setup a number of common references and structures
992 cmd = (struct command *) gnutls_session_get_ptr (session);
994 E_g2e ("No data pointer with session",
995 GNUTLS_E_INVALID_SESSION);
998 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
999 lidrole = LID_ROLE_CLIENT;
1001 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
1002 lidrole = LID_ROLE_SERVER;
1005 E_g2e ("TLS Pool command supports neither local client nor local server role",
1006 GNUTLS_E_INVALID_SESSION);
1009 lid = cmd->cmd.pio_data.pioc_starttls.localid;
1010 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1013 // On a server, lookup the server name and match it against lid.
1014 // TODO: For now assume a single server name in SNI (as that is normal).
1015 if (lidrole == LID_ROLE_SERVER) {
1016 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) || (snitype != GNUTLS_NAME_DNS)) {
1017 E_g2e ("Requested SNI error or not a DNS name",
1018 GNUTLS_E_NO_CERTIFICATE_FOUND);
1023 for (atidx=128; atidx > 0; atidx--) {
1024 if (lid [atidx-1] == '@') {
1028 if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
1029 tlog (TLOG_TLS, LOG_ERR, "SNI %s does not match preset local identity %s", sni, lid);
1030 E_g2e ("Requested SNI does not match local identity",
1031 GNUTLS_E_NO_CERTIFICATE_FOUND);
1035 // TODO: Should ask for permission before accepting SNI
1036 memcpy (lid, sni, sizeof (sni));
1041 // Setup the lidtype parameter for responding
1042 certtp = gnutls_certificate_type_get (session);
1043 if (certtp == GNUTLS_CRT_OPENPGP) {
1044 tlog (TLOG_TLS, LOG_INFO, "Serving OpenPGP certificate request as a %s", rolestr);
1045 lidtype = LID_TYPE_PGP;
1046 } else if (certtp == GNUTLS_CRT_X509) {
1047 tlog (TLOG_TLS, LOG_INFO, "Serving X.509 certificate request as a %s", rolestr);
1048 lidtype = LID_TYPE_X509;
1050 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1051 tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate retrieval attempted as a %s", rolestr);
1052 E_g2e ("Requested certtype is neither X.509 nor OpenPGP",
1053 GNUTLS_E_CERTIFICATE_ERROR);
1058 // Find the prefetched local identity to use towards this remote
1059 // Send a callback to the user if none is available and accessible
1060 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_CHECK) {
1061 uint32_t oldcmd = cmd->cmd.pio_cmd;
1062 struct command *resp;
1063 cmd->cmd.pio_cmd = PIOC_STARTTLS_LOCALID_V2;
1064 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_STARTTLS_LOCALID_V2");
1065 resp = send_callback_and_await_response (cmd, 0);
1066 assert (resp != NULL); // No timeout, should be non-NULL
1067 if (resp->cmd.pio_cmd != PIOC_STARTTLS_LOCALID_V2) {
1068 tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
1069 cmd->cmd.pio_cmd = oldcmd;
1070 return GNUTLS_E_CERTIFICATE_ERROR;
1072 assert (resp == cmd); // No ERROR, so should be the same
1073 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that sets plainfd:=%d and lid:=\"%s\" for rid==\"%s\"", cmd->passfd, lid, rid);
1074 cmd->cmd.pio_cmd = oldcmd;
1076 // Check that new rid is a generalisation of original rid
1077 // Note: This is only of interest for client operation
1078 if (lidrole == LID_ROLE_CLIENT) {
1079 selector_t newrid = donai_from_stable_string (rid, strlen (rid));
1080 donai_t oldrid = donai_from_stable_string (cmd->orig_starttls->remoteid, strlen (cmd->orig_starttls->remoteid));
1081 if (!donai_matches_selector (&oldrid, &newrid)) {
1082 return GNUTLS_E_NO_CERTIFICATE_FOUND;
1086 // Now reiterate to lookup lid credentials in db_localid
1087 E_g2e ("Missing local credentials",
1088 fetch_local_credentials (cmd));
1090 if (cmd->lids [lidtype - LID_TYPE_MIN].data == NULL) {
1091 fprintf (stderr, "DEBUG: Missing certificate for local ID %s and remote ID %s\n", lid, rid);
1092 E_g2e ("Missing certificate for local ID",
1093 GNUTLS_E_NO_CERTIFICATE_FOUND);
1098 // Split the credential into its various aspects
1099 ok = dbcred_interpret (
1100 &cmd->lids [lidtype - LID_TYPE_MIN],
1105 tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, p11priv=\"%s\", cert.size=%d", flags, p11priv, certdatum.size);
1106 //TODO// ok = ok && verify_cert_... (...); -- keyidlookup
1108 gtls_errno = GNUTLS_E_CERTIFICATE_ERROR;
1112 // Allocate response structures
1114 *pcert = load_certificate_chain (flags, pcert_length, &certdatum);
1115 if (*pcert == NULL) {
1116 E_g2e ("Failed to load certificate chain",
1117 GNUTLS_E_CERTIFICATE_ERROR);
1120 cmd->session_certificate = (intptr_t) (void *) *pcert; //TODO// Used for session cleanup
1123 // Setup private key
1124 E_g2e ("Failed to initialise private key",
1125 gnutls_privkey_init (
1127 if ((onthefly_subjectkey != NULL) && (strcmp (p11priv, onthefly_p11uri) == 0)) {
1128 E_g2e ("Failed to import on-the-fly subject private key",
1129 gnutls_privkey_import_x509 (
1131 onthefly_subjectkey,
1132 GNUTLS_PRIVKEY_IMPORT_COPY));
1134 if (gtls_errno == GNUTLS_E_SUCCESS) {
1135 cmd->session_privatekey = (intptr_t) (void *) *pkey; //TODO// Used for session cleanup
1137 E_g2e ("Failed to import PKCS #11 private key URI",
1138 gnutls_privkey_import_pkcs11_url (
1142 E_gnutls_clear_errno ();
1144 //TODO// Moved out (start)
1147 // Setup public key certificate
1150 E_g2e ("MOVED: Failed to import X.509 certificate into chain",
1151 gnutls_pcert_import_x509_raw (
1154 GNUTLS_X509_FMT_DER,
1158 E_g2e ("MOVED: Failed to import OpenPGP certificate",
1159 gnutls_pcert_import_openpgp_raw (
1162 GNUTLS_OPENPGP_FMT_RAW,
1163 NULL, /* use master key */
1167 /* Should not happen */
1171 //TODO// Moved out (end)
1174 // Lap up any overseen POSIX error codes in errno
1176 tlog (TLOG_TLS, LOG_DEBUG, "Failing TLS on errno=%d / %s", errno, strerror (errno));
1177 cmd->session_errno = errno;
1178 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
1182 // Return the overral error code, hopefully GNUTLS_E_SUCCESS
1183 tlog (TLOG_TLS, LOG_DEBUG, "Returning %d / %s from clisrv_cert_retrieve()", gtls_errno, gnutls_strerror (gtls_errno));
1184 printf ("DEBUG: clisrv_cert_retrieve() sets *pcert to 0x%xl (length %d)... {pubkey = 0x%lx, cert= {data = 0x%lx, size=%ld}, type=%ld}\n", (long) *pcert, *pcert_length, (long) (*pcert)->pubkey, (long) (*pcert)->cert.data, (long) (*pcert)->cert.size, (long) (*pcert)->type);
1188 /* Load a single certificate in the given gnutls_pcert_st from the given
1189 * gnutls_datum_t. Use the lidtype to determine how to do this.
1191 gtls_error load_certificate (int lidtype, gnutls_pcert_st *pcert, gnutls_datum_t *certdatum) {
1192 int gtls_errno = GNUTLS_E_SUCCESS;
1194 // Setup public key certificate
1197 fprintf (stderr, "DEBUG: About to import %d bytes worth of X.509 certificate into chain: %02x %02x %02x %02x...\n", certdatum->size, certdatum->data[0], certdatum->data[1], certdatum->data[2], certdatum->data[3]);
1198 E_g2e ("Failed to import X.509 certificate into chain",
1199 gnutls_pcert_import_x509_raw (
1202 GNUTLS_X509_FMT_DER,
1206 E_g2e ("Failed to import OpenPGP certificate",
1207 gnutls_pcert_import_openpgp_raw (
1210 GNUTLS_OPENPGP_FMT_RAW,
1211 NULL, /* use master key */
1215 /* Should not happen */
1222 /* Load a certificate chain. This returns a value for a retrieval function's
1223 * pcert, and also modifies the chainlen. The latter starts at 0, and is
1224 * incremented in a nested procedure that unrolls until all certificates are
1227 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum) {
1228 gnutls_pcert_st *chain;
1229 unsigned int mypos = *chainlen;
1230 int gtls_errno = GNUTLS_E_SUCCESS;
1233 // Quick and easy: No chaining required, just add the literal data.
1234 // Note however, this may be the end of a chain, so allocate all
1235 // structures and load the single one at the end.
1236 if ((flags & (LID_CHAINED | LID_NEEDS_CHAIN)) == 0) {
1238 chain = (gnutls_pcert_st *) calloc (*chainlen, sizeof (gnutls_pcert_st));
1239 if (chain != NULL) {
1240 bzero (chain, (*chainlen) * sizeof (gnutls_pcert_st));
1242 gtls_errno = GNUTLS_E_MEMORY_ERROR;
1244 E_g2e ("Failed to load certificate into chain",
1246 flags & LID_TYPE_MASK,
1249 if (gtls_errno != GNUTLS_E_SUCCESS) {
1260 // First extended case. Chain certs in response to LID_CHAINED.
1261 // Recursive calls are depth-first, so we only add our first cert
1262 // after a recursive call succeeds. Any LID_NEEDS_CHAIN work is
1263 // added after LID_CHAINED, so is higher up in the hierarchy, but
1264 // it is loaded as part of the recursion. To support that, a
1265 // recursive call with certdatum.size==0 is possible when the
1266 // LID_NEEDS_CHAIN flag is set, and this section then skips.
1267 // Note that this code is also used to load the certificate chain
1268 // provided by LID_NEEDS_CHAIN, but by then the flag in a recursive
1269 // call is replaced with LID_CHAINED and no more LID_NEEDS_CHAIN.
1270 if (((flags & LID_CHAINED) != 0) && (certdatum->size > 0)) {
1273 gnutls_datum_t nextdatum;
1275 // Note: Accept BER because the outside SEQUENCE is not signed
1276 certlen = asn1_get_length_ber (
1277 ((char *) certdatum->data) + 1,
1280 certlen += 1 + lenlen;
1281 tlog (TLOG_CERT, LOG_DEBUG, "Found LID_CHAINED certificate size %d", certlen);
1282 if (certlen > certdatum->size) {
1283 tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate beyond data size %d", certdatum->size);
1286 } else if (certlen <= 0) {
1287 tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate of too-modest data size %d", certlen);
1291 nextdatum.data = ((char *) certdatum->data) + certlen;
1292 nextdatum.size = certdatum->size - certlen;
1293 certdatum->size = certlen;
1294 nextlen = asn1_get_length_ber (
1295 ((char *) nextdatum.data) + 1,
1298 nextlen += 1 + lenlen;
1299 if (nextlen == nextdatum.size) {
1300 // The last cert is loaded thinking it is not CHAINED,
1301 // but NEEDS_CHAIN can still be present for expansion.
1302 flags &= ~LID_CHAINED;
1305 chain = load_certificate_chain (flags, chainlen, &nextdatum);
1306 if (chain != NULL) {
1307 E_g2e ("Failed to add chained certificate",
1309 flags & LID_TYPE_MASK,
1312 if (gtls_errno != GNUTLS_E_SUCCESS) {
1322 // Second extended case. Chain certs in response to LID_NEEDS_CHAIN.
1323 // These are the highest-up in the hierarchy, above any LID_CHAINED
1324 // certificates. The procedure for adding them is looking them up
1325 // in a central database by their authority key identifier. What is
1326 // found is assumed to be a chain, and will be unrolled by replacing
1327 // the LID_NEEDS_CHAIN flag with LID_CHAINED and calling recursively.
1328 if (((flags & LID_NEEDS_CHAIN) != 0) && (certdatum->size == 0)) {
1329 //TODO//CODE// lookup new certdatum
1330 flags &= ~LID_NEEDS_CHAIN;
1331 flags |= LID_CHAINED;
1332 //TODO//CODE// recursive call
1333 //TODO//CODE// no structures to fill here
1334 //TODO//CODE// cleanup new certdatum
1338 // Final judgement. Nothing worked. Return failure.
1344 /* Fetch local credentials. This can be done before TLS is started, to find
1345 * the possible authentication forms that can be offered. The function
1346 * can additionally be used after interaction with the client to establish
1347 * a local identity that was not initially provided, or that was not
1348 * considered public at the time.
1350 gtls_error fetch_local_credentials (struct command *cmd) {
1353 DBC *crs_disclose = NULL;
1354 DBC *crs_localid = NULL;
1358 selector_t remote_selector;
1364 // When applicable, try to create an on-the-fly certificate
1365 if (((cmd->cmd.pio_cmd == PIOC_STARTTLS_V2) &&
1366 (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_ONTHEFLY))
1367 || ((cmd->cmd.pio_cmd == PIOC_LIDENTRY_CALLBACK_V2) &&
1368 (cmd->cmd.pio_data.pioc_lidentry.flags & PIOF_LIDENTRY_ONTHEFLY))) {
1369 gtls_errno = certificate_onthefly (cmd);
1370 if (gtls_errno != GNUTLS_E_AGAIN) {
1371 // This includes GNUTLS_E_SUCCESS
1372 fprintf (stderr, "DEBUG: otfcert retrieval returned %d\n", gtls_errno);
1375 fprintf (stderr, "DEBUG: otfcert retrieval returned GNUTLS_E_AGAIN, so skip it\n", gtls_errno);
1376 gtls_errno = GNUTLS_E_SUCCESS; // Attempt failed, ignore
1381 // Setup a number of common references and structures
1382 // Note: Current GnuTLS cannot support being a peer
1383 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
1384 lidrole = LID_ROLE_CLIENT;
1385 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
1386 lidrole = LID_ROLE_SERVER;
1388 E_g2e ("TLS Pool command supports neither local client nor local server role",
1389 GNUTLS_E_INVALID_SESSION);
1392 lid = cmd->cmd.pio_data.pioc_starttls.localid;
1393 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1396 // Refuse to disclose client credentials when the server name is unset;
1397 // note that server-claimed identities are unproven during handshake.
1398 if ((lidrole == LID_ROLE_CLIENT) && (*rid == '\0')) {
1399 tlog (TLOG_USER, LOG_ERR, "No remote identity (server name) set, so no client credential disclosure");
1400 E_g2e ("Missing remote ID",
1401 GNUTLS_E_NO_CERTIFICATE_FOUND);
1405 // Setup database iterators to map identities to credentials
1406 if (lidrole == LID_ROLE_CLIENT) {
1407 E_d2e ("Failed to create db_disclose cursor",
1408 dbh_disclose->cursor (
1414 E_d2e ("Failed to create db_localid cursor",
1415 dbh_localid->cursor (
1421 // Prepare for iteration over possible local identities / credentials
1424 if (gtls_errno != 0) {
1426 } else if (lidrole == LID_ROLE_CLIENT) {
1427 memcpy (cid, rid, sizeof (cid));
1428 dbt_init_fixbuf (&discpatn, cid, strlen (cid));
1429 dbt_init_fixbuf (&keydata, mid, sizeof (mid)-1);
1430 dbt_init_malloc (&creddata);
1432 donai_t remote_donai = donai_from_stable_string (rid, strlen (rid));
1433 if (!selector_iterate_init (&remote_selector, &remote_donai)) {
1434 E_g2e ("Syntax of remote ID unsuitable for selector",
1435 GNUTLS_E_INVALID_REQUEST);
1437 E_d2e ("Failed to start iterator on remote ID selector",
1438 dbcred_iterate_from_remoteid_selector (
1447 dbt_init_fixbuf (&discpatn, "", 0); // Unused but good style
1448 dbt_init_fixbuf (&keydata, lid, strlen (lid));
1449 dbt_init_malloc (&creddata);
1450 E_d2e ("Failed to start iterator on local ID",
1451 dbcred_iterate_from_localid (
1456 if (db_errno != 0) {
1457 gtls_errno = GNUTLS_E_DB_ERROR;
1461 // Now store the local identities inasfar as they are usable
1463 while ((gtls_errno == GNUTLS_E_SUCCESS) && (db_errno == 0)) {
1468 tlog (TLOG_DB, LOG_DEBUG, "Found BDB entry %s disclosed to %s", creddata.data + 4, (lidrole == LID_ROLE_CLIENT)? rid: "all clients");
1472 lidtype = flags & LID_TYPE_MASK;
1473 ok = ok && ((flags & lidrole) != 0);
1474 ok = ok && ((flags & LID_NO_PKCS11) == 0);
1475 ok = ok && (lidtype >= LID_TYPE_MIN);
1476 ok = ok && (lidtype <= LID_TYPE_MAX);
1477 tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, so we (%04x/%04x) %s it", flags, lidrole, LID_ROLE_MASK, ok? "store": "skip ");
1479 // Move the credential into the command structure
1480 dbt_store (&creddata,
1481 &cmd->lids [lidtype - LID_TYPE_MIN]);
1484 // Skip the credential by freeing its data structure
1485 dbt_free (&creddata);
1487 db_errno = dbcred_iterate_next (crs_disclose, crs_localid, &discpatn, &keydata, &creddata);
1490 if (db_errno == DB_NOTFOUND) {
1492 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1495 if (crs_localid != NULL) {
1496 crs_localid->close (crs_localid);
1499 if (crs_disclose != NULL) {
1500 crs_disclose->close (crs_disclose);
1501 crs_disclose = NULL;
1508 * Check if a given cmd has the given LID_TYPE setup.
1509 * Return 1 for yes or 0 for no; this is used in priority strings.
1511 static inline int lidtpsup (struct command *cmd, int lidtp) {
1512 return 1; //TODO// Can we decide if we needn't authenticate?
1513 return cmd->lids [lidtp - LID_TYPE_MIN].data != NULL;
1516 /* Configure the GnuTLS session with suitable credentials and priority string.
1517 * The anonpre_ok flag should be non-zero to permit Anonymous Precursor.
1519 * The credential setup is optional; when creds is NULL, no changes will
1522 static int configure_session (struct command *cmd,
1523 gnutls_session_t session,
1524 struct credinfo *creds,
1528 int gtls_errno = GNUTLS_E_SUCCESS;
1530 // Install the shared credentials for the client or server role
1531 if (creds != NULL) {
1532 gnutls_credentials_clear (session);
1533 for (i=0; i<credcount; i++) {
1534 E_g2e ("Failed to install credentials into TLS session",
1535 gnutls_credentials_set (
1542 // Setup the priority string for this session; this avoids future
1543 // credential callbacks that ask for something impossible or
1546 // Variation factors:
1547 // - starting configuration (can it be empty?)
1548 // - Configured security parameters (database? variable?)
1549 // - CTYPEs, SRP, ANON-or-not --> fill in as + or - characters
1550 if (gtls_errno == GNUTLS_E_SUCCESS) {
1552 snprintf (priostr, sizeof (priostr)-1,
1553 // "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
1555 "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
1557 "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
1559 "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
1562 "%cSRP:%cSRP-RSA:%cSRP-DSS",
1563 anonpre_ok ?'+':'-',
1564 lidtpsup (cmd, LID_TYPE_X509) ?'+':'-',
1565 lidtpsup (cmd, LID_TYPE_PGP) ?'+':'-',
1566 //TODO// Temporarily patched out SRP
1567 lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-',
1568 lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-',
1569 lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-');
1570 // strcpy (priostr, "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"); //TODO:TEST//
1571 // strcpy (priostr, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"); //TODO:TEST//
1572 tlog (TLOG_TLS, LOG_DEBUG, "Constructed priority string %s for local ID %s",
1573 priostr, cmd->cmd.pio_data.pioc_starttls.localid);
1574 E_g2e ("Failed to set GnuTLS priority string",
1575 gnutls_priority_set_direct (
1581 // Return the application GNUTLS_E_ code including _SUCCESS
1585 /* The callback functions retrieve various bits of information for the client
1586 * or server in the course of the handshake procedure.
1588 * The logic here is based on client-sent information, such as:
1589 * - TLS hints -- X.509 or alternatives like OpenPGP, SRP, PSK
1590 * - TLS hints -- Server Name Indication
1591 * - User hints -- local and remote identities provided
1593 int srv_clienthello (gnutls_session_t session) {
1594 struct command *cmd;
1595 char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)]; // static
1596 size_t snilen = sizeof (sni);
1598 int gtls_errno = GNUTLS_E_SUCCESS;
1601 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1603 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1605 // Setup a number of common references
1606 cmd = (struct command *) gnutls_session_get_ptr (session);
1608 return GNUTLS_E_INVALID_SESSION;
1610 lid = cmd->cmd.pio_data.pioc_starttls.localid;
1613 // Setup server-specific credentials and priority string
1614 //TODO// get anonpre value here
1615 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
1616 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1617 E_g2e ("Failed to reconfigure GnuTLS as a server",
1618 configure_session (cmd,
1620 srv_creds, srv_credcount,
1621 cmd->anonpre & ANONPRE_SERVER));
1622 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
1625 // Setup to ignore/request/require remote identity (from client)
1626 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1627 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
1628 // Neither Request nor Require remoteid; ignore it
1630 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REQUEST_REMOTEID) {
1631 // Use Request instead of Require for remoteid
1632 ( //RETURNS_VOID// E_g2e ("Failed to request remote identity",
1633 gnutls_certificate_server_set_request (
1635 GNUTLS_CERT_REQUEST));
1636 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
1638 // Require a remoteid from the client (default)
1639 ( //RETURNS_VOID// E_g2e ("Failed to require remote identity (the default)",
1640 gnutls_certificate_server_set_request (
1642 GNUTLS_CERT_REQUIRE));
1643 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
1647 // Find the client-helloed ServerNameIndication, or the service name
1648 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1650 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) == 0) {
1651 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1653 case GNUTLS_NAME_DNS:
1655 // Note: In theory, other name types could be sent, and it would
1656 // be useful to access indexes beyond 0. In practice, nobody
1657 // uses other name types than exactly one GNUTLS_NAME_DNS.
1660 tlog (TLOG_TLS, LOG_ERR, "Received an unexpected SNI type; that is possible but uncommon; skipping SNI");
1661 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1665 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1666 if (sni [0] != '\0') {
1669 for (atidx=128; atidx > 0; atidx--) {
1670 if (lid [atidx-1] == '@') {
1674 if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
1675 tlog (TLOG_USER | TLOG_TLS, LOG_ERR, "Mismatch between client-sent SNI %s and local identity %s", sni, lid);
1676 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1677 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
1680 memcpy (lid, sni, sizeof (sni));
1681 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1684 memcpy (sni, lid, sizeof (sni)-1);
1685 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1686 sni [sizeof (sni) - 1] = '\0';
1688 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
1691 // Lap up any unnoticed POSIX error messages
1693 cmd->session_errno = errno;
1694 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
1695 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
1696 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
1700 // Round off with an overal judgement
1701 fprintf (stderr, "DEBUG: Returning gtls_errno = %d or \"%s\" from srv_clihello()\n", gtls_errno, gnutls_strerror (gtls_errno));
1706 int cli_srpcreds_retrieve (gnutls_session_t session,
1710 tlog (TLOG_CRYPTO, LOG_DEBUG, "Picking up SRP credentials");
1711 *username = strdup ("tester");
1712 *password = strdup ("test");
1713 return GNUTLS_E_SUCCESS;
1717 /* Setup credentials to be shared by all clients and servers.
1718 * Credentials are generally implemented through callback functions.
1719 * This should be called after setting up DH parameters.
1721 int setup_starttls_credentials (void) {
1722 gnutls_anon_server_credentials_t srv_anoncred = NULL;
1723 gnutls_anon_client_credentials_t cli_anoncred = NULL;
1724 gnutls_certificate_credentials_t clisrv_certcred = NULL;
1725 //TODO:NOTHERE// int srpbits;
1726 gnutls_srp_server_credentials_t srv_srpcred = NULL;
1727 gnutls_srp_client_credentials_t cli_srpcred = NULL;
1728 //TODO// gnutls_kdh_server_credentials_t srv_kdhcred = NULL;
1729 //TODO// gnutls_kdh_server_credentials_t cli_kdhcred = NULL;
1730 int gtls_errno = GNUTLS_E_SUCCESS;
1731 int gtls_errno_stack0;
1734 // Construct anonymous server credentials
1735 E_g2e ("Failed to allocate ANON-DH server credentials",
1736 gnutls_anon_allocate_server_credentials (
1738 if (!have_error_codes ()) /* E_g2e (...) */ gnutls_anon_set_server_dh_params (
1741 if (gtls_errno == GNUTLS_E_SUCCESS) {
1742 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server anonymous credentials");
1743 srv_creds [srv_credcount].credtp = GNUTLS_CRD_ANON;
1744 srv_creds [srv_credcount].cred = (void *) srv_anoncred;
1746 } else if (srv_anoncred != NULL) {
1747 gnutls_anon_free_server_credentials (srv_anoncred);
1748 srv_anoncred = NULL;
1752 // Construct anonymous client credentials
1753 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1754 E_g2e ("Failed to allocate ANON-DH client credentials",
1755 gnutls_anon_allocate_client_credentials (
1757 #ifdef MIRROR_IMAGE_OF_SERVER_ANONYMOUS_CREDENTIALS
1758 // NOTE: This is not done under TLS; server always provides DH params
1759 if (!have_error_codes ()) gnutls_anon_set_client_dh_params (
1763 if (gtls_errno == GNUTLS_E_SUCCESS) {
1764 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client anonymous credentials");
1765 cli_creds [cli_credcount].credtp = GNUTLS_CRD_ANON;
1766 cli_creds [cli_credcount].cred = (void *) cli_anoncred;
1768 } else if (cli_anoncred != NULL) {
1769 gnutls_anon_free_client_credentials (cli_anoncred);
1770 cli_anoncred = NULL;
1774 // Construct certificate credentials for X.509 and OpenPGP cli/srv
1775 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1776 E_g2e ("Failed to allocate certificate credentials",
1777 gnutls_certificate_allocate_credentials (
1779 //TODO// What to do here when we add locking on DH params?
1780 gnutls_certificate_set_dh_params (
1783 gtls_errno_stack0 = gtls_errno;
1784 /* TODO: Bad code. GnuTLS 3.2.1 ignores retrieve_function2 when
1785 * checking if it can handle the OpenPGP certificate type in
1786 * _gnutls_session_cert_type_supported (gnutls_status.c:175) but
1787 * it does see the "1" version field. It does not callback the
1788 * "1" version if "2" is present though.
1790 if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function (
1793 if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function2 (
1795 clisrv_cert_retrieve);
1796 if (gtls_errno == GNUTLS_E_SUCCESS) {
1797 // Setup for certificates
1798 tlog (TLOG_CERT, LOG_INFO, "Setting client and server certificate credentials");
1799 cli_creds [cli_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
1800 cli_creds [cli_credcount].cred = (void *) clisrv_certcred;
1802 srv_creds [srv_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
1803 srv_creds [srv_credcount].cred = (void *) clisrv_certcred;
1805 } else if (clisrv_certcred != NULL) {
1806 gnutls_certificate_free_credentials (clisrv_certcred);
1807 clisrv_certcred = NULL;
1811 // Construct server credentials for SRP authentication
1812 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1813 E_g2e ("Failed to allocate SRP server credentials",
1814 gnutls_srp_allocate_server_credentials (
1816 E_g2e ("Failed to set SRP server credentials",
1817 gnutls_srp_set_server_credentials_file (
1819 "../testdata/tlspool-test-srp.passwd",
1820 "../testdata/tlspool-test-srp.conf"));
1821 if (gtls_errno == GNUTLS_E_SUCCESS) {
1822 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server SRP credentials");
1823 srv_creds [srv_credcount].credtp = GNUTLS_CRD_SRP;
1824 srv_creds [srv_credcount].cred = (void *) srv_srpcred;
1826 } else if (srv_srpcred != NULL) {
1827 gnutls_srp_free_server_credentials (srv_srpcred);
1832 // Construct client credentials for SRP authentication
1833 gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1834 E_g2e ("Failed to allocate SRP client credentials",
1835 gnutls_srp_allocate_client_credentials (
1837 if (!have_error_codes ()) gnutls_srp_set_client_credentials_function (
1839 cli_srpcreds_retrieve);
1840 if (gtls_errno == GNUTLS_E_SUCCESS) {
1841 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client SRP credentials");
1842 cli_creds [cli_credcount].credtp = GNUTLS_CRD_SRP;
1843 cli_creds [cli_credcount].cred = (void *) cli_srpcred;
1845 } else if (cli_srpcred != NULL) {
1846 gnutls_srp_free_client_credentials (cli_srpcred);
1851 // Construct server credentials for KDH authentication
1852 //TODO// gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1853 //TODO// E_g2e ("Failed to allocate KDH server credentials",
1854 //TODO// gnutls_kdh_allocate_server_credentials (
1855 //TODO// &srv_kdhcred));
1856 //TODO// E_g2e ("Failed to set KDH server DH params",
1857 //TODO// gnutls_kdh_set_server_dh_params (
1858 //TODO// srv_kdhcred,
1859 //TODO// dh_params));
1860 //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
1861 //TODO// tlog (TLOG_CRYPTO, LOG_INFO, "Setting server KDH credentials");
1862 //TODO// srv_creds [srv_credcount].credtp = GNUTLS_CRD_KDH;
1863 //TODO// srv_creds [srv_credcount].cred = (void *) srv_kdhcred;
1864 //TODO// srv_credcount++;
1865 //TODO// } else if (srv_kdhcred != NULL) {
1866 //TODO// gnutls_kdh_free_server_credentials (srv_kdhcred);
1867 //TODO// srv_kdhcred = NULL;
1871 // Construct client credentials for KDH
1872 //TODO// gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
1873 //TODO// E_g2e ("Failed to allocate KDH client credentials",
1874 //TODO// gnutls_kdh_allocate_client_credentials (
1875 //TODO// &cli_kdhcred));
1876 //TODO// E_g2e ("Failed to set KDH client credentials",
1877 //TODO// gnutls_kdh_set_client_credentials_function (
1878 //TODO// cli_kdhcred,
1879 //TODO// cli_kdh_retrieve));
1880 //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
1881 //TODO// tlog (TLOG_CRYPTO, LOG_INFO, "Setting client KDH credentials");
1882 //TODO// cli_creds [cli_credcount].credtp = GNUTLS_CRD_KDH;
1883 //TODO// cli_creds [cli_credcount].cred = (void *) cli_kdhcred;
1884 //TODO// cli_credcount++;
1885 //TODO// } else if (cli_kdhcred != NULL) {
1886 //TODO// gnutls_kdh_free_client_credentials (cli_kdhcred);
1887 //TODO// cli_kdhcred = NULL;
1891 // Ensure that at least one credential has been set
1892 // TODO: Look at the counters; but at boot, we can require all okay
1893 if ((gtls_errno == GNUTLS_E_SUCCESS) &&
1894 ( (cli_credcount != EXPECTED_CLI_CREDCOUNT) ||
1895 (srv_credcount != EXPECTED_SRV_CREDCOUNT) ) ) {
1896 tlog (TLOG_CRYPTO, LOG_ERR, "Not all credential types could be setup (cli %d/%d, srv %d/%d, gtls_errno %d)", cli_credcount, EXPECTED_CLI_CREDCOUNT, srv_credcount, EXPECTED_SRV_CREDCOUNT, gtls_errno);
1897 E_g2e ("Not all credentials could be setup",
1898 GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1902 // Report overall error or success
1907 /* Cleanup all credentials created, just before exiting the daemon.
1909 void cleanup_starttls_credentials (void) {
1910 while (srv_credcount-- > 0) {
1911 struct credinfo *crd = &srv_creds [srv_credcount];
1912 switch (crd->credtp) {
1913 case GNUTLS_CRD_CERTIFICATE:
1914 // Shared with client; skipped in server and removed in client
1915 // gnutls_certificate_free_credentials (crd->cred);
1917 case GNUTLS_CRD_ANON:
1918 gnutls_anon_free_server_credentials (crd->cred);
1920 case GNUTLS_CRD_SRP:
1921 gnutls_srp_free_server_credentials (crd->cred);
1923 //TODO// case GNUTLS_CRD_KDH:
1924 //TODO// gnutls_kdh_free_server_credentials (crd->cred);
1928 while (cli_credcount-- > 0) {
1929 struct credinfo *crd = &cli_creds [cli_credcount];
1930 switch (crd->credtp) {
1931 case GNUTLS_CRD_CERTIFICATE:
1932 // Shared with client; skipped in server and removed in client
1933 gnutls_certificate_free_credentials (crd->cred);
1935 case GNUTLS_CRD_ANON:
1936 gnutls_anon_free_client_credentials (crd->cred);
1938 case GNUTLS_CRD_SRP:
1939 gnutls_srp_free_client_credentials (crd->cred);
1941 //TODO// case GNUTLS_CRD_KDH:
1942 //TODO// gnutls_kdh_free_client_credentials (crd->cred);
1950 * The starttls_thread is a main program for the setup of a TLS connection,
1951 * either in client mode or server mode. Note that the distinction between
1952 * client and server mode is only a TLS concern, but not of interest to the
1953 * application or the records exchanged.
1955 * If the STARTTLS operation succeeds, this will be reported back to the
1956 * application, but the TLS pool will continue to be active in a copycat
1957 * procedure: encrypting outgoing traffic and decrypting incoming traffic.
1959 * A new handshake may be initiated with a STARTTLS command with the special
1960 * flag PIOF_STARTTLS_RENEGOTIATE and the ctlkey set to a previously setup
1961 * TLS connection. This command runs in a new thread, that cancels the old
1962 * one (which it can only do while it is waiting in copycat) and then join
1963 * that thread (and its data) with the current one. This is based on the
1964 * ctlkey, which serves to lookup the old thread's data. When the
1965 * connection ends for other reasons than a permitted cancel by another
1966 * thread, will the thread cleanup its own resources. In these situations,
1967 * the new command determines the negotiation parameters, and returns identity
1970 * In addition, the remote side may initiate renegotiation. This is accepted
1971 * without further ado (although future versions of the TLS Pool may add a
1972 * callback mechanism to get it approved). The renegotiation now runs under
1973 * the originally supplied negotiation parameters. In case it needs a new
1974 * local identity, it may also perform callbacks. Possibly repeating what
1975 * happened before -- but most often, a server will start processing a
1976 * protocol and determine that it requires more for the requested level of
1977 * service, and then renegotiate. This is common, for example, with HTTPS
1978 * connections that decide they need a client certificate for certain URLs.
1979 * The implementation of this facility is currently as unstructured as the
1980 * facility itself, namely through a goto. We may come to the conclusion
1981 * that a loop is in fact a warranted alternative, but we're not yet
1982 * convinced that this would match with other "structures" in TLS.
1984 * In conclusion, there are three possible ways of running this code:
1985 * 1. For a new connection. Many variables are not known and build up
1986 * in the course of running the function.
1987 * 2. After a command requesting renegotiation. This overtakes the prior
1988 * connection's thread, and copies its data from the ctlkeynode_tls.
1989 * The resulting code has a number of variables filled in already at
1991 * 3. After a remote request for renegotiation. This loops back to an
1992 * earlier phase, but after the thread takeover and ctlkeynode_tls copy
1993 * of the explicit command for renegotation. Its behaviour is subtly
1994 * different in that it has no command to act on, and so it cannot
1995 * send responses or error codes. It will however log and shutdown
1996 * as the command-driven options would. It will not perform callbacks
1997 * for PIOC_STARTTLS_LOCALID_V2 or PIOC_PLAINTEXT_CONNECT_V2. It will
1998 * however trigger the PIOC_LIDENTRY_CALLBACK_V2 through the separate
1999 * callback command, if one is registered.
2000 * Yeah, it's great fun, coding TLS and keeping it both flexible and secure.
2002 static void *starttls_thread (void *cmd_void) {
2003 struct command *cmd, *replycmd;
2004 struct command cmd_copy; // for relooping during renegotiation
2005 struct pioc_starttls orig_starttls;
2006 uint32_t orig_cmdcode;
2009 gnutls_session_t session;
2010 int got_session = 0;
2011 int gtls_errno = GNUTLS_E_SUCCESS;
2013 struct ctlkeynode_tls *ckn = NULL;
2016 int want_remoteid = 1;
2017 int got_remoteid = 0;
2018 int renegotiating = 0;
2019 char *preauth = NULL;
2020 unsigned int preauthlen = 0;
2021 int taking_over = 0;
2022 int my_maxpreauth = 0;
2026 // Block thread cancellation -- and re-enable it in copycat()
2027 assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
2030 // General thread setup
2031 replycmd = cmd = (struct command *) cmd_void;
2033 send_error (replycmd, EINVAL, "Command structure not received");
2034 assert (pthread_detach (pthread_self ()) == 0);
2037 cmd->session_errno = 0;
2039 orig_cmdcode = cmd->cmd.pio_cmd;
2040 memcpy (&orig_starttls, &cmd->cmd.pio_data.pioc_starttls, sizeof (orig_starttls));
2041 cmd->orig_starttls = &orig_starttls;
2042 cryptfd = cmd->passfd;
2044 //TODO:TEST Removed here because it is tested below
2047 tlog (TLOG_UNIXSOCK, LOG_ERR, "No ciphertext file descriptor supplied to TLS Pool");
2048 send_error (replycmd, EINVAL, "No ciphertext file descriptor supplied to TLS Pool");
2049 assert (pthread_detach (pthread_self ()) == 0);
2053 cmd->session_certificate = (intptr_t) (void *) NULL;
2054 cmd->session_privatekey = (intptr_t) (void *) NULL;
2057 // In case of renegotiation, lookup the previous ctlkeynode by its
2058 // ctlkey. The fact that we have ckn != NULL indicates that we are
2059 // renegotiating in the code below; it will supply information as
2060 // we continue to run the TLS process.
2061 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_RENEGOTIATE) {
2062 fprintf (stderr, "DEBUG: Got a request to renegotiate existing TLS connection\n");
2064 // Check that no FD was passed (and ended up in cryptfd)
2066 tlog (TLOG_UNIXSOCK, LOG_ERR, "Renegotiation started with extraneous file descriptor");
2067 send_error (replycmd, EPROTO, "File handle supplied for renegotiation");
2069 assert (pthread_detach (pthread_self ()) == 0);
2073 // First find the ctlkeynode_tls
2074 ckn = (struct ctlkeynode_tls *) ctlkey_find (cmd->cmd.pio_data.pioc_starttls.ctlkey, security_tls, cmd->clientfd);
2075 fprintf (stderr, "DEBUG: Got ckn == 0x%0x\n", (intptr_t) ckn);
2077 tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to find TLS connection for renegotiation by its ctlkey");
2078 send_error (replycmd, ESRCH, "Cannot find TLS connection for renegotiation");
2079 assert (pthread_detach (pthread_self ()) == 0);
2083 // Now cancel the pthread for this process
2084 errno = pthread_cancel (ckn->owner);
2085 fprintf (stderr, "DEBUG: pthread_cancel returned %d\n", errno);
2088 errno = pthread_join (ckn->owner, &retval);
2089 fprintf (stderr, "DEBUG: pthread_join returned %d\n", errno);
2092 tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to interrupt TLS connection for renegotiation");
2093 send_error (replycmd, errno, "Cannot interrupt TLS connection for renegotiation");
2094 ctlkey_unfind (&ckn->regent);
2095 assert (pthread_detach (pthread_self ()) == 0);
2096 // Do not free the ckn, as the other thread still runs
2100 // We are in control! Assimilate the TLS connection data.
2102 plainfd = ckn->plainfd;
2103 cryptfd = ckn->cryptfd;
2104 session = ckn->session;
2107 ctlkey_unfind (&ckn->regent);
2110 // Then follows the unstructured entry point for the unstructured
2111 // request to a TLS connection to renegotiate its security parameters.
2112 // Doing this in any other way than with goto would add a lot of
2113 // make-belief structure that only existed to make this looping
2114 // possible. We'd rather be honest and admit the lack of structure
2115 // that TLS has in this respect. Maybe we'll capture it one giant loop
2116 // at some point, but for now that does not seem to add any relief.
2118 printf ("DEBUG: Renegotiating = %d, anonpost = %d, plainfd = %d, cryptfd = %d, flags = 0x%x, session = 0x%x, got_session = %d, lid = \"%s\", rid = \"%s\"\n", renegotiating, anonpost, plainfd, cryptfd, cmd->cmd.pio_data.pioc_starttls.flags, session, got_session, cmd->cmd.pio_data.pioc_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid);
2121 // If this is server renegotiating, send a request to that end
2122 //TODO// Only invoke gnutls_rehandshake() on the server
2123 if (renegotiating && (taking_over || anonpost) && (gtls_errno == GNUTLS_E_SUCCESS)) {
2124 printf ("DEBUG: Invoking gnutls_rehandshake in renegotiation loop\n");
2125 gtls_errno = gnutls_rehandshake (session);
2126 if (gtls_errno == GNUTLS_E_INVALID_REQUEST) {
2127 // Clients should not do this; be forgiving
2128 gtls_errno = GNUTLS_E_SUCCESS;
2129 printf ("DEBUG: Client-side invocation flagged as wrong; compensated error\n");
2134 // When renegotiating TLS security, ensure that it is done securely
2135 if (renegotiating && (gnutls_safe_renegotiation_status (session) == 0)) {
2136 send_error (replycmd, EPROTO, "Renegotiation requested while secure renegotiation is unavailable on remote");
2146 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2151 assert (pthread_detach (pthread_self ()) == 0);
2156 // Potentially decouple the controlling fd (ctlkey is in orig_starttls)
2157 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_FORK) {
2158 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_FORK;
2163 // Setup BDB transactions and reset credential datum fields
2165 bzero (&cmd->lids, sizeof (cmd->lids));
2166 manage_txn_begin (&cmd->txn);
2170 // Permit cancellation of this thread -- TODO: Cleanup?
2171 //TODO:TEST// Defer setcancelstate untill copycat() activity
2173 errno = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
2175 send_error (replycmd, ESRCH, "STARTTLS handler thread cancellability refused");
2185 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2190 manage_txn_rollback (&cmd->txn);
2191 assert (pthread_detach (pthread_self ()) == 0);
2196 // Check and setup the plaintext file handle
2198 send_error (replycmd, EPROTO, "You must supply a TLS-protected socket");
2203 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2204 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
2205 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2210 manage_txn_rollback (&cmd->txn);
2211 assert (pthread_detach (pthread_self ()) == 0);
2216 // Decide on support for the Anonymous Precursor, based on the
2217 // service name and its appearance in the anonpre_registry.
2218 // If the remoteid is not interesting to the client then also
2219 // support an Anonymous Precursor; we have nothing to loose.
2220 cmd->anonpre &= ~ANONPRE_EITHER;
2221 if (renegotiating) {
2222 ; // Indeed, during renegotiation we always disable ANON-DH
2223 } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
2224 cmd->anonpre = ANONPRE_EITHER;
2227 int anonpre_regidx = anonpre_registry_size >> 1;
2228 int anonpre_regjmp = (anonpre_registry_size + 1) >> 1;
2230 while (anonpre_regjmp > 0) {
2231 anonpre_regjmp = anonpre_regjmp >> 1;
2232 cmp = strncasecmp (anonpre_registry [anonpre_regidx].service,
2233 cmd->cmd.pio_data.pioc_starttls.service,
2234 TLSPOOL_SERVICELEN);
2235 printf ("DEBUG: anonpre_determination, comparing [%d] %s to %s, found cmp==%d\n", anonpre_regidx, anonpre_registry [anonpre_regidx].service, cmd->cmd.pio_data.pioc_starttls.service, cmp);
2237 // anonpre_regent matches
2238 cmd->anonpre = anonpre_registry [anonpre_regidx].flags;
2240 } else if (cmp > 0) {
2241 // anonpre_regent too high
2242 anonpre_regidx -= 1 + anonpre_regjmp;
2243 if (anonpre_regidx < 0) {
2247 // anonpre_regent too low
2248 anonpre_regidx += 1 + anonpre_regjmp;
2249 if (anonpre_regidx >= anonpre_registry_size) {
2250 anonpre_regidx = anonpre_registry_size - 1;
2257 // Setup flags for client and/or server roles (make sure there is one)
2258 if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_CLIENT) == 0)) {
2259 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_SERVER;
2261 if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_SERVER) == 0)) {
2262 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_CLIENT;
2264 if ((cmd->cmd.pio_data.pioc_starttls.flags & (PIOF_STARTTLS_LOCALROLE_CLIENT | PIOF_STARTTLS_LOCALROLE_SERVER)) == 0) {
2266 // Neither a TLS client nor a TLS server
2268 send_error (replycmd, ENOTSUP, "Command not supported");
2274 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2275 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
2276 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2281 manage_txn_rollback (&cmd->txn);
2282 assert (pthread_detach (pthread_self ()) == 0);
2287 // Setup the TLS session. Also see doc/p2p-tls.*
2289 // TODO: GnuTLS cannot yet setup p2p connections
2291 gnutls_session_set_ptr (
2294 //TODO:DONE?// Clear various settings... creds, flags, modes? CLI/SRV?
2296 E_g2e ("Failed to initialise GnuTLS peer session",
2299 (((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)? GNUTLS_CLIENT: 0) |
2300 ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)? GNUTLS_SERVER: 0))
2302 if (gtls_errno == GNUTLS_E_SUCCESS) {
2304 gnutls_session_set_ptr (
2310 // Setup client-specific behaviour if needed
2311 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
2312 if (!renegotiating) { //TODO:TEST//
2314 // Setup as a TLS client
2318 // Require a minimum security level for SRP
2320 //TODO:CRASH// if (gtls_errno == GNUTLS_E_SUCCESS) gnutls_srp_set_prime_bits (
2321 //TODO:CRASH// session,
2322 //TODO:CRASH// srpbits);
2324 // Setup as a TLS client
2326 // Setup for potential sending of SNI
2327 if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_WITHOUT_SNI) == 0) {
2328 char *str = cmd->cmd.pio_data.pioc_starttls.remoteid;
2331 while (str [len] && (len < 128)) {
2332 if (str [len] == '@') {
2337 // If no usable remoteid was setup, ignore it
2338 if ((len + ofs > 0) && (len < 128)) {
2339 cmd->cmd.pio_data.pioc_starttls.remoteid [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)-1] = '\0';
2340 E_g2e ("Client failed to setup SNI",
2341 gnutls_server_name_set (
2350 // Setup for client credential installation in this session
2352 // Setup client-specific credentials and priority string
2353 printf ("DEBUG: Configuring client credentials\n");
2354 E_g2e ("Failed to configure GnuTLS as a client",
2355 configure_session (cmd,
2357 anonpost? NULL: cli_creds,
2358 anonpost? 0: cli_credcount,
2359 cmd->anonpre & ANONPRE_CLIENT));
2362 // Setup callback to server-specific behaviour if needed
2363 if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
2364 printf ("DEBUG: Configuring for server credentials callback if %d==0\n", gtls_errno);
2365 if (!renegotiating) { //TODO:TEST//
2366 if (gtls_errno == GNUTLS_E_SUCCESS) {
2367 gnutls_handshake_set_post_client_hello_function (
2372 //TODO:TEST// configure_session _if_ not setup as a client (too)
2374 // Setup for server credential installation in this session
2376 // Setup server-specific credentials and priority string
2378 if (! (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
2379 printf ("DEBUG: Configuring server credentials (because it is not a client)\n");
2380 E_g2e ("Failed to configure GnuTLS as a server",
2381 configure_session (cmd,
2383 anonpost? NULL: srv_creds,
2384 anonpost? 0: srv_credcount,
2385 cmd->anonpre & ANONPRE_SERVER));
2391 // Prefetch local identities that might be used in this session
2393 E_g2e ("Failed to fetch local credentials",
2394 fetch_local_credentials (cmd));
2398 // Setup a temporary priority string so handshaking can start
2399 if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) == 0) {
2400 E_g2e ("Failed to preconfigure server token priority string",
2401 gnutls_priority_set (
2407 // Check if past code stored an error code through POSIX
2408 if (cmd->session_errno) {
2409 gtls_errno = GNUTLS_E_USER_ERROR;
2413 // Setup a timeout value as specified in the command, where TLS Pool
2414 // defines 0 as default and ~0 as infinite (GnuTLS has 0 as infinite).
2415 tout = cmd->cmd.pio_data.pioc_starttls.timeout;
2416 if (renegotiating) {
2417 ; // Do not set timeout
2419 if (tout == TLSPOOL_TIMEOUT_DEFAULT) {
2420 gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
2421 } else if (tout == TLSPOOL_TIMEOUT_INFINITE) {
2422 gnutls_handshake_set_timeout (session, 0);
2424 gnutls_handshake_set_timeout (session, tout);
2428 // Now setup for the GnuTLS handshake
2430 if (renegotiating) {
2431 ; // Do not setup cryptfd
2433 if (gtls_errno == GNUTLS_E_SUCCESS) {
2434 gnutls_transport_set_int (session, cryptfd);
2436 if (gtls_errno != GNUTLS_E_SUCCESS) {
2437 tlog (TLOG_TLS, LOG_ERR, "Failed to prepare for TLS: %s", gnutls_strerror (gtls_errno));
2438 if (cmd->session_errno) {
2439 send_error (replycmd, cmd->session_errno, error_getstring ());
2441 send_error (replycmd, EIO, "Failed to prepare for TLS");
2444 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
2445 gnutls_deinit (session);
2453 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2454 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
2455 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2460 manage_txn_rollback (&cmd->txn);
2461 assert (pthread_detach (pthread_self ()) == 0);
2464 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake started over %d", cryptfd);
2467 // Take a rehandshaking step forward.
2469 gtls_errno = gnutls_handshake (session);
2471 // When data is sent before completing
2472 // the rehandshake, then it's something
2473 // harmless, given the criteria for the
2474 // anonpre_registry. We pass it on and
2475 // don't worry about it. We do report
2478 // Note: Applications should be willing
2479 // to buffer or process such early data
2480 // before the handshake is over or else
2481 // the handshake will bail out in error.
2483 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
2484 if (my_maxpreauth <= 0) {
2485 tlog (TLOG_COPYCAT, LOG_ERR, "Received unwanted early data before authentication is complete");
2486 break; // Terminate the handshake
2487 } else if (preauth == NULL) {
2488 preauth = malloc (my_maxpreauth);
2489 if (preauth == NULL) {
2490 gtls_errno = GNUTLS_E_MEMORY_ERROR;
2491 break; // Terminate the handshake
2495 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
2496 if (preauthlen >= my_maxpreauth) {
2497 tlog (TLOG_COPYCAT, LOG_ERR, "Received more early data than willing to receive (%d bytes)", my_maxpreauth);
2498 break; // Terminate the handshake
2501 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
2503 sz = gnutls_record_recv (session, preauth + preauthlen, my_maxpreauth - preauthlen);
2504 tlog (TLOG_COPYCAT, LOG_DEBUG, "Received %d remote bytes (or error if <0) from %d during anonymous precursor\n", (int) sz, cryptfd);
2507 gtls_errno = GNUTLS_E_SUCCESS;
2509 gtls_errno = sz; // It's actually an error code
2512 } while ((gtls_errno < 0) &&
2513 //DROPPED// (gtls_errno != GNUTLS_E_GOT_APPLICATION_DATA) &&
2514 //DROPPED// (gtls_errno != GNUTLS_E_WARNING_ALERT_RECEIVED) &&
2515 (gnutls_error_is_fatal (gtls_errno) == 0));
2516 if (gtls_errno == 0) {
2517 const gnutls_datum_t *certs;
2518 unsigned int num_certs;
2520 switch (gnutls_auth_get_type (session)) { // Peer's cred type
2521 case GNUTLS_CRD_CERTIFICATE:
2522 certs = gnutls_certificate_get_peers (session, &num_certs);
2523 if ((certs != NULL) && (num_certs >= 1)) {
2526 // "certs" points into GnuTLS' internal data structures
2528 case GNUTLS_CRD_PSK:
2529 // Difficult... what did the history say about this?
2532 case GNUTLS_CRD_SRP:
2533 // Got a credential, validation follows later on
2534 //TODO// SRP does not really auth the server
2537 case GNUTLS_CRD_ANON:
2538 // Did not get a credential, perhaps due to anonpre
2542 // Inner Application extension is no true credential
2543 // Should we compare the client-requested service?
2544 // Should we renegotiate into the ALPN protocol?
2548 // Unknown creds cautiously considered unauthentitcated
2553 // Now recognise and handle the Anonymous Precursor
2554 if (((cmd->anonpre & ANONPRE_EITHER) != 0)
2555 && want_remoteid && !got_remoteid) {
2556 assert (anonpost == 0);
2557 // Disable ANON-protocols but keep creds from before
2558 //TODO:ELSEWHERE// tlog (TLOG_TLS, LOG_DEBUG, "Reconfiguring TLS over %d without Anonymous Precursor\n", cryptfd);
2559 //TODO:ELSEWHERE// E_g2e ("Failed to reconfigure GnuTLS without anonymous precursor",
2560 //TODO:ELSEWHERE// configure_session (cmd,
2561 //TODO:ELSEWHERE// session,
2562 //TODO:ELSEWHERE// NULL, 0,
2563 //TODO:ELSEWHERE// 0));
2564 // We do not want to use ANON-DH if the flag
2565 // ANONPRE_EXTEND_MASTER_SECRET is set for the protocol
2566 // but the remote peer does not support it. Only if
2567 // this problem cannot possibly occur, permit
2568 // my_maxpreauth > 0 for early data acceptance.
2570 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
2571 #if GNUTLS_VERSION_NUMBER >= 0x030400
2572 gnutls_ext_priv_data_t ext;
2573 if (!gnutls_ext_get_data (session, 23, &ext)) {
2574 my_maxpreauth = maxpreauth;
2578 my_maxpreauth = maxpreauth;
2580 if (gtls_errno == 0) {
2581 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake continued over %d after anonymous precursor", cryptfd);
2582 renegotiating = 1; // (de)selects steps
2583 anonpost = 1; // (de)selects steps
2588 if ((gtls_errno == GNUTLS_E_SUCCESS) && cmd->session_errno) {
2589 gtls_errno = GNUTLS_E_USER_ERROR;
2594 // Cleanup any prefetched identities
2595 for (i=LID_TYPE_MIN; i<=LID_TYPE_MAX; i++) {
2596 if (cmd->lids [i - LID_TYPE_MIN].data != NULL) {
2597 free (cmd->lids [i - LID_TYPE_MIN].data);
2600 bzero (cmd->lids, sizeof (cmd->lids));
2603 /* This is not proper. gnutls_certificate_set_key() suggests that these are
2604 * automatically cleaned up, and although this is not repeated in
2605 * gnutls_certificate_set_retrieve_function2() it is likely to be related.
2606 * Plus, renegotiation with this code in place bogged down on failed pcerts;
2607 * they were detected in _gnutls_selected_cert_supported_kx() but their
2608 * key exchange algorithm was never found.
2610 if (NULL != (void *) cmd->session_privatekey) {
2611 gnutls_privkey_deinit ((void *) cmd->session_privatekey);
2612 cmd->session_privatekey = (intptr_t) (void *) NULL;
2614 if (NULL != (void *) cmd->session_certificate) {
2615 gnutls_pcert_deinit ((void *) cmd->session_certificate);
2616 free ((void *) cmd->session_certificate);
2617 cmd->session_certificate = (intptr_t) (void *) NULL;
2622 // From here, assume nothing about the cmd->cmd structure; as part of
2623 // the handshake, it may have passed through the client's control, as
2624 // part of a callback. So, reinitialise the entire return structure.
2625 //TODO// Or backup the (struct pioc_starttls) before handshaking
2626 cmd->cmd.pio_cmd = orig_cmdcode;
2627 cmd->cmd.pio_data.pioc_starttls.localid [0] =
2628 cmd->cmd.pio_data.pioc_starttls.remoteid [0] = 0;
2631 // Respond to positive or negative outcome of the handshake
2632 if (gtls_errno != GNUTLS_E_SUCCESS) {
2633 tlog (TLOG_TLS, LOG_ERR, "TLS handshake failed: %s", gnutls_strerror (gtls_errno));
2634 if (cmd->session_errno) {
2636 tlog (TLOG_TLS, LOG_ERR, "Underlying cause may be: %s", strerror (cmd->session_errno));
2637 errstr = error_getstring ();
2638 if (errstr == NULL) {
2639 errstr = "TLS handshake failed";
2641 send_error (replycmd, cmd->session_errno, errstr);
2643 send_error (replycmd, EPERM, "TLS handshake failed");
2649 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
2650 gnutls_deinit (session);
2658 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2659 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
2660 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2665 manage_txn_rollback (&cmd->txn);
2666 assert (pthread_detach (pthread_self ()) == 0);
2669 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_INFO, "TLS handshake succeeded over %d", cryptfd);
2670 //TODO// extract_authenticated_remote_identity (cmd);
2674 // Request the plaintext file descriptor with a callback
2676 uint32_t oldcmd = cmd->cmd.pio_cmd;
2677 struct command *resp;
2678 cmd->cmd.pio_cmd = PIOC_PLAINTEXT_CONNECT_V2;
2679 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_PLAINTEXT_CONNECT_V2");
2680 resp = send_callback_and_await_response (replycmd, 0);
2681 assert (resp != NULL); // No timeout, should be non-NULL
2682 if (resp->cmd.pio_cmd != PIOC_PLAINTEXT_CONNECT_V2) {
2683 tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
2684 send_error (replycmd, EINVAL, "Callback response has bad command code");
2689 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
2690 gnutls_deinit (session);
2694 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2695 if (ckn) { /* TODO: CHECK NEEDED? PRACTICE=>YES */
2696 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2701 manage_txn_rollback (&cmd->txn);
2702 assert (pthread_detach (pthread_self ()) == 0);
2705 cmd->cmd.pio_cmd = oldcmd;
2706 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that set plainfd:=%d for lid==\"%s\" and rid==\"%s\"", cmd->passfd, cmd->cmd.pio_data.pioc_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid);
2707 plainfd = resp->passfd;
2711 tlog (TLOG_UNIXSOCK, LOG_ERR, "No plaintext file descriptor supplied to TLS Pool");
2712 send_error (replycmd, EINVAL, "No plaintext file descriptor supplied to TLS Pool");
2717 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
2718 gnutls_deinit (session);
2722 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2723 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
2724 if (ctlkey_unregister (ckn->regent.ctlkey)) {
2729 manage_txn_rollback (&cmd->txn);
2730 assert (pthread_detach (pthread_self ()) == 0);
2733 //DEFERRED// send_command (replycmd, -1); // app sent plainfd to us
2736 // Copy TLS records until the connection is closed
2737 manage_txn_commit (&cmd->txn);
2738 if (!renegotiating) {
2739 ckn = (struct ctlkeynode_tls *) malloc (sizeof (struct ctlkeynode_tls));
2742 send_error (replycmd, ENOMEM, "Out of memory allocating control key structure");
2744 int detach = (orig_starttls.flags & PIOF_STARTTLS_DETACH) != 0;
2745 ckn->session = session;
2746 ckn->owner = pthread_self ();
2747 ckn->cryptfd = cryptfd;
2748 ckn->plainfd = plainfd;
2749 //DEBUG// fprintf (stderr, "Registering control key\n");
2750 if (renegotiating || (ctlkey_register (orig_starttls.ctlkey, &ckn->regent, security_tls, detach? -1: cmd->clientfd, forked) == 0)) {
2751 int copied = GNUTLS_E_SUCCESS;
2752 send_command (replycmd, -1); // app sent plainfd to us
2756 // Check on extended master secret if desired
2757 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
2758 #if GNUTLS_VERSION_NUMBER >= 0x030400
2759 gnutls_ext_priv_data_t ext;
2760 if (!gnutls_ext_get_data (session, 23, &ext)) {
2761 cmd->anonpre &= ~ANONPRE_EXTEND_MASTER_SECRET;
2765 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
2766 tlog (TLOG_COPYCAT, LOG_ERR, "Received %d remote bytes from anonymous precursor but lacking %s-required authentication through extended master secret", orig_starttls.service);
2767 gtls_errno = GNUTLS_E_LARGE_PACKET;
2770 } else if (write (plainfd, preauth, preauthlen) == preauthlen) {
2771 tlog (TLOG_COPYCAT, LOG_DEBUG, "Passed on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
2774 copied = copycat (plainfd, cryptfd, session, detach? -1: cmd->clientfd);
2776 tlog (TLOG_COPYCAT, LOG_DEBUG, "Failed to pass on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
2779 copied = copycat (plainfd, cryptfd, session, detach? -1: cmd->clientfd);
2781 // Renegotiate if copycat asked us to
2782 if (copied == GNUTLS_E_REHANDSHAKE) {
2783 // Yes, goto is a dirty technique. On the
2784 // other hand, so is forcing unstructured
2785 // code flows into a make-belief structure
2786 // that needs changing over and over again.
2787 // I fear goto is the most reasonable way
2788 // of handling this rather obtuse structure
2789 // of renegotiation of security in TLS :(
2790 //TODO// Ensure secure renegotiation!!!
2792 replycmd = NULL; // Bypass all send_XXX()
2793 memcpy (&cmd_copy, cmd, sizeof (cmd_copy));
2795 memcpy (cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid));
2796 memcpy (cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid));
2797 cmd->cmd.pio_data.pioc_starttls.flags = orig_starttls.flags & ~PIOF_STARTTLS_LOCALID_CHECK;
2798 // Disabling the flag causing LOCALID_CHECK
2799 // ...and plainfd >= 0 so no PLAINTEXT_CONNECT
2800 // ...so there will be no callbacks to cmd
2801 printf ("DEBUG: Goto renegotiate with cmd.lid = \"%s\" and orig_cmd.lid = \"%s\" and cmd.rid = \"%s\" and orig_cmd.rid = \"%s\" and cmd.flags = 0x%x and orig_cmd.flags = 0x%x\n", cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, cmd->cmd.pio_data.pioc_starttls.flags, orig_starttls.flags);
2804 //DEBUG// fprintf (stderr, "Unregistering control key\n");
2805 // Unregister by ctlkey, which should always succeed
2806 // if the TLS connection hadn't been closed down yet;
2807 // and if it does, the memory can be freed. Note that
2808 // the ctlkey is not taken from the ckn, which may
2809 // already have been freed if the ctlfd was closed
2810 // and the connection could not continue detached
2811 // (such as after forking it).
2812 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
2813 if (ctlkey_unregister (orig_starttls.ctlkey)) {
2817 //DEBUG// fprintf (stderr, "Unregistered control key\n");
2819 send_error (replycmd, ENOENT, "Failed to register control key for TLS connection");
2829 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
2830 gnutls_deinit (session);
2833 assert (pthread_detach (pthread_self ()) == 0);
2839 * The starttls function responds to an application's request to
2840 * setup TLS for a given file descriptor, and return a file descriptor
2841 * with the unencrypted view when done. The main thing done here is to
2842 * spark off a new thread that handles the operations.
2844 void starttls (struct command *cmd) {
2845 /* Create a thread and, if successful, wait for it to unlock cmd */
2846 errno = pthread_create (&cmd->handler, NULL, starttls_thread, (void *) cmd);
2848 send_error (cmd, ESRCH, "STARTTLS thread refused");
2851 //TODO:TEST// Thread detaches itself before terminating w/o followup
2853 errno = pthread_detach (cmd->handler);
2855 pthread_cancel (cmd->handler);
2856 send_error (cmd, ESRCH, "STARTTLS thread detachment refused");
2864 * Run the PRNG for a TLS connection, identified by its control key. If the connection
2865 * is not a TLS connection, or if the control key is not found, reply with ERROR;
2866 * otherwise, the session should help to create pseudo-random bytes.
2868 void starttls_prng (struct command *cmd) {
2869 uint8_t in1 [TLSPOOL_PRNGBUFLEN];
2870 uint8_t in2 [TLSPOOL_PRNGBUFLEN];
2871 int16_t in1len, in2len, prnglen;
2872 struct ctlkeynode_tls *ckn = NULL;
2875 int gtls_errno = GNUTLS_E_SUCCESS;
2876 struct pioc_prng *prng = &cmd->cmd.pio_data.pioc_prng;
2878 // Find arguments and validate them
2879 in1len = prng->in1_len;
2880 in2len = prng->in2_len;
2881 prnglen = prng->prng_len;
2882 err = err || (in1len <= 0);
2883 err = err || (prnglen > TLSPOOL_PRNGBUFLEN);
2884 err = err || ((TLSPOOL_CTLKEYLEN + in1len + (in2len >= 0? in2len: 0))
2885 > TLSPOOL_PRNGBUFLEN);
2887 memcpy (in1, prng->buffer + TLSPOOL_CTLKEYLEN , in1len);
2889 memcpy (in2, prng->buffer + TLSPOOL_CTLKEYLEN + in1len, in2len);
2892 // - check the label string
2893 prefixes = tlsprng_label_prefixes;
2894 while ((!err) && (*prefixes)) {
2895 char *pf = *prefixes++;
2896 if (strlen (pf) != in1len) {
2899 if (strcmp (pf, in1) != 0) {
2903 if (*prefixes == NULL) {
2904 // RFC 5705 defines a private-use prefix "EXPERIMENTAL"
2905 if ((in1len <= 12) || (strncmp (in1, "EXPERIMENTAL", 12) != 0)) {
2909 // - check the ctlkey (and ensure it is for TLS)
2911 //DEBUG// fprintf (stderr, "Hoping to find control key\n");
2912 ckn = (struct ctlkeynode_tls *) ctlkey_find (prng->buffer, security_tls, cmd->clientfd);
2915 // Now wipe the PRNG buffer to get rid of any sensitive bytes
2916 memset (prng->buffer, 0, TLSPOOL_PRNGBUFLEN);
2918 // If an error occurrend with the command, report it now
2920 send_error (cmd, EINVAL, "TLS PRNG request invalid");
2921 // ckn is NULL if err != 0, so no need for ctlkey_unfind()
2925 send_error (cmd, ENOENT, "Invalid control key");
2929 // Now actually invoke the PRNG command in the GnuTLS backend
2931 E_g2e ("GnuTLS PRNG based on session master key failed",
2932 gnutls_prf_rfc5705 (ckn->session,
2934 (in2len >= 0)? in2len: 0, (in2len >= 0) ? in2: NULL,
2935 prnglen, prng->buffer));
2936 err = err || (errno != 0);
2938 // Wipe temporary data / buffers for security reasons
2939 memset (in1, 0, sizeof (in1));
2940 memset (in2, 0, sizeof (in2));
2941 ctlkey_unfind ((struct ctlkeynode *) ckn);
2943 // Return the outcome to the user
2945 send_error (cmd, errno? errno: EIO, "PRNG in TLS backend failed");
2947 send_command (cmd, -1);
2952 /* Flying signer functionality. Create an on-the-fly certificate because
2953 * the lidentry daemon and/or application asks for this to represent the
2954 * local identity. Note that this will only work if the remote party
2955 * accepts the root identity under which on-the-signing is done.
2957 * When no root credentials have been configured, this function will
2958 * fail with GNUTLS_E_AGAIN; it may be used as a hint to try through
2959 * other (more conventional) means to obtain a client certificate.
2961 * The API of this function matches that of fetch_local_credentials()
2962 * and that is not a coincidence; this is a drop-in replacement in some
2965 * Limitations: The current implementation only supports X.509 certificates
2966 * to be generated on the fly. So, this will set LID_TYPE_X509, if anything.
2968 gtls_error certificate_onthefly (struct command *cmd) {
2969 gtls_error gtls_errno = GNUTLS_E_SUCCESS;
2970 gnutls_x509_crt_t otfcert;
2972 gnutls_x509_subject_alt_name_t altnmtp;
2977 if ((onthefly_issuercrt == NULL) || (onthefly_issuerkey == NULL) || (onthefly_subjectkey == NULL)) {
2978 // Not able to supply on-the-fly certificates; try someway else
2979 return GNUTLS_E_AGAIN;
2981 if (cmd->cmd.pio_data.pioc_starttls.localid [0] == '\0') {
2982 return GNUTLS_E_NO_CERTIFICATE_FOUND;
2984 if (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data != NULL) {
2985 free (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data);
2986 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = NULL;
2987 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
2991 // Create an empty certificate
2992 E_g2e ("Failed to initialise on-the-fly certificate",
2993 gnutls_x509_crt_init (&otfcert));
2994 if (gtls_errno != GNUTLS_E_SUCCESS) {
2999 // Fill the certificate with the usual field
3000 E_g2e ("Failed to set on-the-fly certificate to non-CA mode",
3001 gnutls_x509_crt_set_ca_status (otfcert, 0));
3002 E_g2e ("Failed to set on-the-fly certificate version",
3003 gnutls_x509_crt_set_version (otfcert, 3));
3004 onthefly_serial++; //TODO// Consider a random byte string
3005 E_g2e ("Failed to set on-the-fly serial number",
3006 gnutls_x509_crt_set_serial (otfcert, &onthefly_serial, sizeof (onthefly_serial)));
3007 // Skip gnutls_x509_crt_set_issuer_by_dn_by_oid(), added when signing
3009 E_g2e ("Failed to set on-the-fly activation time to now - 2 min",
3010 gnutls_x509_crt_set_activation_time (otfcert, now - 120));
3011 E_g2e ("Failed to set on-the-fly expiration time to now + 3 min",
3012 gnutls_x509_crt_set_expiration_time (otfcert, now + 180));
3013 E_g2e ("Setup certificate CN with local identity",
3014 gnutls_x509_crt_set_dn_by_oid (otfcert, GNUTLS_OID_X520_COMMON_NAME, 0, cmd->cmd.pio_data.pioc_starttls.localid, strnlen (cmd->cmd.pio_data.pioc_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid)-1))); /* TODO: Consider pioc_lidentry as well? */
3015 E_g2e ("Setup certificate OU with TLS Pool on-the-fly",
3016 gnutls_x509_crt_set_dn_by_oid (otfcert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "TLS Pool on-the-fly", 19));
3017 if (strchr (cmd->cmd.pio_data.pioc_starttls.localid, '@')) {
3018 // localid has the format of an emailAddress
3019 altnmtp = GNUTLS_SAN_RFC822NAME;
3021 // localid has the format of a dnsName
3022 altnmtp = GNUTLS_SAN_DNSNAME;
3024 E_g2e ("Failed to set subjectAltName to localid",
3025 gnutls_x509_crt_set_subject_alt_name (otfcert, altnmtp, &cmd->cmd.pio_data.pioc_starttls.localid, strnlen (cmd->cmd.pio_data.pioc_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid) - 1), GNUTLS_FSAN_APPEND));
3026 //TODO:SKIP, hoping that signing adds: gnutls_x509_crt_set_authority_key_id()
3027 //TODO:SKIP, hoping that a cert without also works: gnutls_x509_crt_set_subjectkey_id()
3028 //TODO:SKIP? gnutls_x509_crt_set_extension_by_oid
3029 //TODO: gnutls_x509_crt_set_key_usage
3030 //TODO:SKIP? gnutls_x509_crt_set_ca_status
3031 for (i=0; i < svcusage_registry_size; i++) {
3032 if (strcmp (svcusage_registry [i].service, cmd->cmd.pio_data.pioc_starttls.service) == 0) {
3033 const char **walker;
3034 E_g2e ("Failed to setup basic key usage during on-the-fly certificate creation",
3035 gnutls_x509_crt_set_key_usage (otfcert, svcusage_registry [i].usage));
3036 walker = svcusage_registry [i].oids_non_critical;
3039 E_g2e ("Failed to append non-critical extended key purpose during on-the-fly certificate creation",
3040 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 0));
3044 walker = svcusage_registry [i].oids_critical;
3047 E_g2e ("Failed to append critical extended key purpose during on-the-fly certificate creation",
3048 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 1));
3055 E_g2e ("Failed to et the on-the-fly subject key",
3056 gnutls_x509_crt_set_key (otfcert, onthefly_subjectkey));
3057 /* TODO: The lock below should not be necessary; it is handled by p11-kit
3058 * or at least it ought to be. What I found however, was that
3059 * a client and server would try to use the onthefly_issuerkey
3060 * at virtually the same time, and then the second call to
3061 * C_SignInit returns CKR_OPERATION_ACTIVE. The lock solved this.
3062 * This makes me frown about server keys stored in PKCS #11...
3064 {gnutls_datum_t data = { 0, 0}; if (gnutls_x509_crt_print (otfcert, GNUTLS_CRT_PRINT_UNSIGNED_FULL, &data) == 0) { fprintf (stderr, "DEBUG: PRESIGCERT: %s\n", data.data); gnutls_free (data.data); } else {fprintf (stderr, "DEBUG: PRESIGCERT failed to print\n"); } }
3065 assert (pthread_mutex_lock (&onthefly_signer_lock) == 0);
3066 E_g2e ("Failed to sign on-the-fly certificate",
3067 gnutls_x509_crt_privkey_sign (otfcert, onthefly_issuercrt, onthefly_issuerkey, GNUTLS_DIG_SHA256, 0));
3068 pthread_mutex_unlock (&onthefly_signer_lock);
3071 // Construct cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data+size for this certificate
3072 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
3073 if (gtls_errno == GNUTLS_E_SUCCESS) {
3074 gtls_errno = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, NULL, &cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
3075 if (gtls_errno == GNUTLS_E_SHORT_MEMORY_BUFFER) {
3076 // This is as expected, now .size will have been set
3077 gtls_errno = GNUTLS_E_SUCCESS;
3079 if (gtls_errno = GNUTLS_E_SUCCESS) {
3080 // Something must be wrong if we receive OK
3081 gtls_errno = GNUTLS_E_INVALID_REQUEST;
3084 E_g2e ("Error while measuring on-the-fly certificate size",
3087 uint8_t *ptr = NULL;
3088 if (gtls_errno == GNUTLS_E_SUCCESS) {
3089 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size += 4 + strlen (onthefly_p11uri) + 1;
3090 ptr = malloc (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
3092 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
3093 gnutls_x509_crt_deinit (otfcert);
3094 return GNUTLS_E_MEMORY_ERROR;
3099 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = ptr;
3100 * (uint32_t *) ptr = htonl (LID_TYPE_X509 | LID_ROLE_BOTH);
3102 strcpy (ptr, onthefly_p11uri);
3103 ptr += strlen (onthefly_p11uri) + 1;
3104 restsz = cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size - 4 - strlen (onthefly_p11uri) - 1;
3105 E_g2e ("Failed to export on-the-fly certificate as a credential",
3106 gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, ptr, &restsz));
3107 char *pembuf [10000];
3108 size_t pemlen = sizeof (pembuf) - 1;
3109 int exporterror = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_PEM, pembuf, &pemlen);
3110 if (exporterror == 0) {
3111 pembuf [pemlen] = '\0';
3112 fprintf (stderr, "DEBUG: otfcert ::=\n%s\n", pembuf);
3114 fprintf (stderr, "DEBUG: otfcert export to PEM failed with %d, gtls_errno already was %d\n", exporterror, gtls_errno);
3119 // Cleanup the allocated and built structures
3120 gnutls_x509_crt_deinit (otfcert);
3123 // Return the overall result that might have stopped otf halfway