Now passing Ticket and Authenticator between client and server
[tlspool] / src / starttls.c
1 /* tlspool/starttls.c -- Setup and validation handler for TLS session */
2
3 #include "whoami.h"
4
5 #include <stdlib.h>
6 #include <stdint.h>
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <memory.h>
10 #include <string.h>
11 #include <pthread.h>
12 #include <assert.h>
13
14 #include <ctype.h>
15
16 #include <unistd.h>
17 #include <syslog.h>
18 #include <errno.h>
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22
23 #include <arpa/inet.h>
24 #include <netinet/in.h>
25
26 #include <gnutls/gnutls.h>
27 #include <gnutls/pkcs11.h>
28 #include <gnutls/abstract.h>
29 #include <gnutls/dane.h>
30
31 #include <p11-kit/pkcs11.h>
32
33 #include <tlspool/commands.h>
34 #include <tlspool/internal.h>
35
36 #include <libtasn1.h>
37
38 #include <krb5.h>
39 /* Plus, from k5-int.h: */
40 krb5_error_code KRB5_CALLCONV krb5_decrypt_tkt_part(krb5_context,
41                                                     const krb5_keyblock *,
42                                                     krb5_ticket * );
43
44
45 #include <quick-der/api.h>
46 #include <quick-der/rfc4120.h>
47 typedef DER_OVLY_rfc4120_Ticket ticket_t;
48 typedef DER_OVLY_rfc4120_Authenticator authenticator_t;
49 typedef DER_OVLY_rfc4120_EncryptedData encrypted_data_t;
50
51 #include <tlspool/internal.h>
52
53 #ifdef WINDOWS_PORT
54 #include <winsock2.h>
55 #else
56 #include <poll.h>
57 #include <sys/types.h>
58 #include <sys/socket.h>
59
60 #ifndef __MINGW64__
61 #include <arpa/inet.h>
62 #endif
63 #endif
64
65 #ifdef WINDOWS_PORT
66 #include <windows.h>
67 #define RECV_FLAGS 0
68 #define SHUT_RD SD_RECEIVE
69 #define SHUT_WR SD_SEND
70 #else /* WINDOWS_PORT */
71 #define RECV_FLAGS MSG_DONTWAIT | MSG_NOSIGNAL
72 #endif /* WINDOWS_PORT */
73
74 #include "manage.h"
75 #include "donai.h"
76 #include "trust.h"
77
78
79 #if EXPECTED_LID_TYPE_COUNT != LID_TYPE_CNT
80 #error "Set EXPECTED_LID_TYPE_COUNT in <tlspool/internal.h> to match LID_TYPE_CNT"
81 #endif
82
83
84 /* This module hosts TLS handlers which treat an individual connection.
85  *
86  * Initially, the TLS setup is processed, which means validating the
87  * connection.  If and when this succeeds, a continued process is needed
88  * to encrypt and decrypt traffic while it is in transit.
89  *
90  * Every TLS connection (including the attempt to set it up) is hosted in
91  * its own thread.  This means that it can abide time to wait for PINENTRY,
92  * LOCALID or LIDENTRY responses.  It also means a very clear flow when the
93  * time comes to destroy a connection.
94  *
95  * While encrypting and decrypting traffic passing through, the thread
96  * will use its own poll() call, and thus offload the potentially large
97  * one of the main thread, which is supposed to be a low-traffic task.
98  * The set of file descriptors used by the session-handler threads are
99  * in contrast very small and can easily be started for every single
100  * packet passing through.
101  *
102  * Might the user terminate a process while this one is waiting for a
103  * callback command request, then the main TLS pool thread will take
104  * care of taking down this thread.  To that end, it sets the followup
105  * pointer that normally holds a callback response to NULL, and then
106  * permits this thread to run again.  This will lead to a shutdown of
107  * this process, and proper closing of all connections.  The remote peer
108  * will therefore see the result of a local kill as a connection reset.
109  *
110  * In case one of the end points of the connection is terminated, a
111  * similar thing will happen; the thread will terminate itself after
112  * a cleanup of any outstanding resources.  This, once again, leads
113  * to passing on the reset of a connection between the encrypted and
114  * side of the connection.
115  */
116
117
118
119 /*
120  * GnuTLS infrastructure setup.
121  * Session-shared DH-keys, credentials structures, and so on.
122  */
123 static gnutls_dh_params_t dh_params;
124
125 struct credinfo {
126         gnutls_credentials_type_t credtp;
127         void *cred;
128 };
129
130 #define EXPECTED_SRV_CREDCOUNT 3
131 #define EXPECTED_CLI_CREDCOUNT 3
132 static struct credinfo srv_creds [EXPECTED_SRV_CREDCOUNT];
133 static struct credinfo cli_creds [EXPECTED_CLI_CREDCOUNT];
134 static int srv_credcount = 0;
135 static int cli_credcount = 0;
136 static const char const *onthefly_p11uri = "pkcs11:manufacturer=ARPA2.net;token=TLS+Pool+internal;object=on-the-fly+signer;type=private;serial=1";
137 static unsigned long long onthefly_serial;  //TODO: Fill with now * 1000
138 static gnutls_x509_crt_t onthefly_issuercrt = NULL;
139 static gnutls_privkey_t onthefly_issuerkey = NULL;
140 static gnutls_x509_privkey_t onthefly_subjectkey = NULL;
141 static pthread_mutex_t onthefly_signer_lock = PTHREAD_MUTEX_INITIALIZER;
142
143 #ifdef HAVE_TLS_KDH
144 static krb5_context krbctx_cli, krbctx_srv;
145 static krb5_keytab  krb_kt_cli, krb_kt_srv;
146 static bool         got_cc_cli, got_cc_srv;
147 static int have_key_tgt_cc (
148                                 struct command *cmd, // in, session context
149                                 krb5_context ctx,    // in, kerberos context
150                                 bool use_cc,         // in, whether to use cc
151                                 krb5_kvno kvno,      // in, kvno (0 for highest)
152                                 krb5_enctype enctype,// in, enctype (0 for any)
153                                 char *p11uri,        // in/opt, PKCS #11 pwd URI
154                                 krb5_keytab kt,      // in/opt, keytab
155                                 krb5_keyblock *key,  // opt/opt session key
156                                 krb5_creds **tgt,    // out/opt, tkt granting tkt
157                                 krb5_ccache *cc);    // out/opt, cred cache
158 static int have_service_ticket (
159                                 struct command *cmd, // in, session context
160                                 krb5_context ctx,    // in, kerberos context
161                                 krb5_ccache cc_opt,  // in/opt, credcache
162                                 krb5_principal cli,  // in, client principal
163                                 krb5_creds **ticket);// out/opt, tkt granting tkt
164 #endif
165
166
167 /* The local variation on the ctlkeynode structure, with TLS-specific fields
168  */
169 struct ctlkeynode_tls {
170         struct ctlkeynode regent;       // Structure for ctlkey_register()
171         gnutls_session_t session;       // Additional data specifically for TLS
172         pthread_t owner;                // For interruption of copycat()
173         int plainfd;                    // Plain-side connection
174         int cryptfd;                    // Crypt-side connection
175 };
176
177 /* A local structure used for iterating over PKCS #11 entries.  This is used
178  * to iterate over password attempts, no more than MAX_P11ITER_ATTEMPTS though.
179  *
180  * When a password is requested but none is available, the password request
181  * will be passed to the user using the PIN callback mechanism.  When this
182  * is done, a warning may be given that the TLS Pool overtakes control over
183  * the account (when thusly configured).  In support of that option, the
184  * $attempt is counted and the respective $p11pwd is CK_INVALID_HANDLE.
185  * TODO: Perhaps interact for saving, such as entering an certain string?
186  *
187  * When a number of attempts needs to be made before success, then any
188  * objects that precede a succeeded $attempt can be removed.  The same may
189  * be true for any objects after it.
190  *
191  * This mechanism is useful during password changes.  When a new password is
192  * desired by the KDC, then a random object is created and returned twice.
193  * To support repeated delivery, the password is stored in $newpwd;
194  * In this case, the safest choice is still to leave the last $p11pwd.
195  *
196  * The caller may decide to invoke the password changing procedure, namely
197  * after manual entry as evidenced by the condition
198  *      (attempts >= 0) &&
199  *      (attempts < MAX_P11_ITER_ATTEMPTS) &&
200  *      (p11pwd [attempt] == CK_INVALID_HANDLE)
201  *
202  * TODO: This is a designed data structure, but not yet installed.
203  *
204  * TODO: It is more useful to abolish passwords, and truly use PKCS #11.
205  */
206 #define MAX_P11ITER_ATTEMPTS 3
207 struct pkcs11iter {
208         struct command *cmd;            // The session command structure
209         CK_SESSION_HANDLE p11ses;       // The PKCS #11 session in motion
210         int attempt;                    // Starts at -1, incremented by pwd entry
211         CK_OBJECT_HANDLE p11pwd [MAX_P11ITER_ATTEMPTS];
212                                         // Sequence of $attempt objects returned
213         CK_OBJECT_HANDLE newpwd;        // Set when a new password was offered
214 };
215
216 /* The list of accepted Exporter Label Prefixes for starttls_prng()
217  */
218 char *tlsprng_label_prefixes [] = {
219         // Forbidden by RFC 5705: "client finished",
220         // Forbidden by RFC 5705: "server finished",
221         // Forbidden by RFC 5705: "master secret",
222         // Forbidden by RFC 5705: "key expansion",
223         "client EAP encryption",                // not suited for DTLS
224         "ttls keying material",                 // not suited for DTLS
225         "ttls challenge",                       // not suited for DTLS
226         "EXTRACTOR-dtls_srtp",
227         "EXPORTER_DTLS_OVER_SCTP",
228         "EXPORTER-ETSI-TC-M2M-Bootstrap",
229         "EXPORTER-ETSI-TC-M2M-Connection",
230         "TLS_MK_Extr",
231         "EXPORTER_GBA_Digest",
232         "EXPORTER: teap session key seed",      // not suited for DTLS
233         "EXPORTER-oneM2M-Bootstrap",
234         "EXPORTER-oneM2M-Connection",
235         NULL
236 };
237
238 /* The registry with the service names that are deemed safe for an
239  * anonymous precursor phase; that is, the service names that may offer
240  * ANON-DH initially, and immediately renegotiate an authenticated
241  * connection.  See doc/anonymising-precursor.* for more information.
242  *
243  * The registry is ordered by case-independent service name, so it can
244  * be searched in 2log time.  Service names are as defined by IANA in the
245  * "Service Name and Transport Protocol Port Number Registry".
246  *
247  * The entries in the registry depend on the role played; either as a
248  * client or as a server.  This refers to the local node, and depends on
249  * uncertainty of the remote party's TLS implementation and whether or
250  * not the protocol could lead to the remote sending information that
251  * requires authentication before the secure renogiation into an
252  * authenticated connection has been completed by this side.  This is
253  * a protocol-dependent matter and the registry provided here serves to
254  * encapsulate this knowledge inside the TLS Pool instead of bothering
255  * application designers with it.  Entries that are not found in the
256  * registry are interpreted as not allowing an anonymising precursor.
257  *
258  * Note that ANONPRE_EXTEND_MASTER_SECRET cannot be verified before
259  * GnuTLS version 3.4.0; see "imap" below for the resulting impact.  This
260  * also impacts dynamic linking, because 3.4.0 introduces the new function
261  * gnutls_ext_get_data() that is used for this requirement.
262  */
263 #define ANONPRE_FORBID 0x00
264 #define ANONPRE_CLIENT 0x01
265 #define ANONPRE_SERVER 0x02
266 #define ANONPRE_EITHER (ANONPRE_CLIENT | ANONPRE_SERVER)
267 #define ANONPRE_EXTEND_MASTER_SECRET 0x10
268 struct anonpre_regentry {
269         char *service;
270         uint8_t flags;
271 };
272 struct anonpre_regentry anonpre_registry [] = {
273 /* This registry is commented out for now, although the code to use it seems
274  * to work fine.  GnuTLS however, does not seem to support making the switch
275  * from ANON-ECDH to an authenticated handshake.  Details:
276  * http://lists.gnutls.org/pipermail/gnutls-help/2015-November/003998.html
277  *
278         { "generic_anonpre", ANONPRE_EITHER },  // Name invalid as per RFC 6335
279         { "http", ANONPRE_CLIENT },     // Server also if it ignores client ID
280 #if GNUTLS_VERSION_NUMBER < 0x030400
281         { "imap", ANONPRE_SERVER },
282 #else
283         { "imap", ANONPRE_EITHER | ANONPRE_EXTEND_MASTER_SECRET },
284 #endif
285         { "pop3", ANONPRE_EITHER },
286         { "smtp", ANONPRE_EITHER },
287  *
288  * End of commenting out the registry
289  */
290 };
291 const int anonpre_registry_size = sizeof (anonpre_registry) / sizeof (struct anonpre_regentry);
292
293
294 /* The registry of Key Usage and Extended Key Usage for any given service name.
295  */
296 static const char *http_noncrit [] = { GNUTLS_KP_TLS_WWW_SERVER, GNUTLS_KP_TLS_WWW_CLIENT, NULL };
297 struct svcusage_regentry {
298         char *service;
299         unsigned int usage;
300         const char **oids_non_critical;
301         const char **oids_critical;
302 };
303 struct svcusage_regentry svcusage_registry [] = {
304         { "generic_anonpre",
305                 GNUTLS_KEY_KEY_ENCIPHERMENT |
306                 GNUTLS_KEY_KEY_AGREEMENT,
307                 NULL,
308                 NULL
309         },
310         { "http",
311                 GNUTLS_KEY_DIGITAL_SIGNATURE |
312                 GNUTLS_KEY_KEY_ENCIPHERMENT |
313                 GNUTLS_KEY_KEY_AGREEMENT,
314                 http_noncrit,
315                 NULL
316         },
317 };
318 const int svcusage_registry_size = sizeof (svcusage_registry) / sizeof (struct svcusage_regentry);
319
320
321 /* The maximum number of bytes that can be passed over a TLS connection before
322  * the authentication is complete in case of a anonymous precursor within a
323  * protocol that ensures that this cannot be a problem.
324  */
325 int maxpreauth;
326
327 /* The priorities cache for "NORMAL" -- used to preconfigure the server,
328  * actually to overcome its unwillingness to perform the handshake, and
329  * leave it to srv_clienthello() to setup the priority string.
330  */
331 gnutls_priority_t priority_normal;
332
333
334 /* Map a GnuTLS call (usually a function call) to a POSIX errno,
335  * optionally reporting an errstr to avoid loosing information.
336  * Retain errno if it already exists.
337  * Continue if errno differs from 0, GnuTLS may "damage" it even when OK. */
338 #define E_g2e(errstr,gtlscall) { \
339         if (gtls_errno == GNUTLS_E_SUCCESS) { \
340                 gtls_errno = (gtlscall); \
341                 if (gtls_errno != GNUTLS_E_SUCCESS) { \
342                         error_gnutls2posix (gtls_errno, errstr); \
343                 } \
344         } \
345 }
346
347 /* Cleanup when GnuTLS leaves errno damaged but returns no gtls_errno */
348 #define E_gnutls_clear_errno() { \
349         if (gtls_errno == GNUTLS_E_SUCCESS) { \
350                 errno = 0; \
351         } \
352 }
353
354 /* Error number translation, including error string setup.  See E_g2e(). */
355 void error_gnutls2posix (int gtls_errno, char *new_errstr) {
356         char *errstr;
357         register int newerrno;
358         //
359         // Sanity checks
360         if (gtls_errno == GNUTLS_E_SUCCESS) {
361                 return;
362         }
363         errstr =  error_getstring ();
364         if (errstr != NULL) {
365                 return;
366         }
367         //
368         // Report the textual error
369         if (new_errstr == NULL) {
370                 new_errstr = "GnuTLS error";
371         }
372         tlog (TLOG_TLS, LOG_ERR, "%s: %s",
373                 new_errstr,
374                 gnutls_strerror (gtls_errno));
375         error_setstring (new_errstr);
376         //
377         // Translate error to a POSIX errno value
378         switch (gtls_errno) {
379         case GNUTLS_E_SUCCESS:
380                 return;
381         case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
382         case GNUTLS_E_UNKNOWN_CIPHER_TYPE:
383         case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
384         case GNUTLS_E_UNWANTED_ALGORITHM:
385         case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
386         case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
387         case GNUTLS_E_X509_UNKNOWN_SAN:
388         case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
389         case GNUTLS_E_UNKNOWN_PK_ALGORITHM:
390         case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
391         case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
392         case GNUTLS_E_NO_CIPHER_SUITES:
393         case GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED:
394         case GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE:
395         case GNUTLS_E_UNKNOWN_HASH_ALGORITHM:
396         case GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE:
397         case GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE:
398         case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
399         case GNUTLS_E_UNKNOWN_ALGORITHM:
400         case GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM:
401         case GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED:
402         case GNUTLS_E_X509_UNSUPPORTED_OID:
403         case GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE:
404         case GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL:
405         case GNUTLS_E_ECC_NO_SUPPORTED_CURVES:
406         case GNUTLS_E_ECC_UNSUPPORTED_CURVE:
407         case GNUTLS_E_X509_UNSUPPORTED_EXTENSION:
408         case GNUTLS_E_NO_CERTIFICATE_STATUS:
409         case GNUTLS_E_NO_APPLICATION_PROTOCOL:
410 #ifdef GNUTLS_E_NO_SELF_TEST
411         case GNUTLS_E_NO_SELF_TEST:
412 #endif
413                 newerrno = EOPNOTSUPP;
414                 break;
415         case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
416         case GNUTLS_E_INVALID_REQUEST:
417                 newerrno = EINVAL;
418                 break;
419         case GNUTLS_E_INVALID_SESSION:
420         case GNUTLS_E_REHANDSHAKE:
421         case GNUTLS_E_CERTIFICATE_KEY_MISMATCH:
422                 newerrno = ENOTCONN;
423                 break;
424         case GNUTLS_E_PUSH_ERROR:
425         case GNUTLS_E_PULL_ERROR:
426         case GNUTLS_E_PREMATURE_TERMINATION:
427         case GNUTLS_E_SESSION_EOF:
428                 newerrno = ECONNRESET;
429                 break;
430         case GNUTLS_E_UNEXPECTED_PACKET:
431         case GNUTLS_E_WARNING_ALERT_RECEIVED:
432         case GNUTLS_E_FATAL_ALERT_RECEIVED:
433         case GNUTLS_E_LARGE_PACKET:
434         case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
435         case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
436         case GNUTLS_E_MPI_SCAN_FAILED:
437         case GNUTLS_E_DECRYPTION_FAILED:
438         case GNUTLS_E_DECOMPRESSION_FAILED:
439         case GNUTLS_E_COMPRESSION_FAILED:
440         case GNUTLS_E_BASE64_DECODING_ERROR:
441         case GNUTLS_E_MPI_PRINT_FAILED:
442         case GNUTLS_E_GOT_APPLICATION_DATA:
443         case GNUTLS_E_RECORD_LIMIT_REACHED:
444         case GNUTLS_E_ENCRYPTION_FAILED:
445         case GNUTLS_E_PK_ENCRYPTION_FAILED:
446         case GNUTLS_E_PK_DECRYPTION_FAILED:
447         case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
448         case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
449         case GNUTLS_E_PKCS1_WRONG_PAD:
450         case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
451         case GNUTLS_E_FILE_ERROR:
452         case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
453         case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
454         case GNUTLS_E_ASN1_DER_ERROR:
455         case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
456         case GNUTLS_E_ASN1_GENERIC_ERROR:
457         case GNUTLS_E_ASN1_VALUE_NOT_VALID:
458         case GNUTLS_E_ASN1_TAG_ERROR:
459         case GNUTLS_E_ASN1_TAG_IMPLICIT:
460         case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
461         case GNUTLS_E_ASN1_SYNTAX_ERROR:
462         case GNUTLS_E_ASN1_DER_OVERFLOW:
463         case GNUTLS_E_TOO_MANY_EMPTY_PACKETS:
464         case GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS:
465         case GNUTLS_E_SRP_PWD_PARSING_ERROR:
466         case GNUTLS_E_BASE64_ENCODING_ERROR:
467         case GNUTLS_E_OPENPGP_KEYRING_ERROR:
468         case GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR:
469         case GNUTLS_E_OPENPGP_SUBKEY_ERROR:
470         case GNUTLS_E_CRYPTO_ALREADY_REGISTERED:
471         case GNUTLS_E_HANDSHAKE_TOO_LARGE:
472         case GNUTLS_E_BAD_COOKIE:
473         case GNUTLS_E_PARSING_ERROR:
474         case GNUTLS_E_CERTIFICATE_LIST_UNSORTED:
475         case GNUTLS_E_NO_PRIORITIES_WERE_SET:
476 #ifdef GNUTLS_E_PK_GENERATION_ERROR
477         case GNUTLS_E_PK_GENERATION_ERROR:
478 #endif
479 #ifdef GNUTLS_E_SELF_TEST_ERROR
480         case GNUTLS_E_SELF_TEST_ERROR:
481 #endif
482 #ifdef GNUTLS_E_SOCKETS_INIT_ERROR
483         case GNUTLS_E_SOCKETS_INIT_ERROR:
484 #endif
485                 newerrno = EIO;
486                 break;
487         case GNUTLS_E_MEMORY_ERROR:
488         case GNUTLS_E_SHORT_MEMORY_BUFFER:
489                 newerrno = ENOMEM;
490                 break;
491         case GNUTLS_E_AGAIN:
492                 newerrno = EAGAIN;
493                 break;
494         case GNUTLS_E_EXPIRED:
495         case GNUTLS_E_TIMEDOUT:
496                 newerrno = ETIMEDOUT;
497                 break;
498         case GNUTLS_E_DB_ERROR:
499 #ifdef ENODATA
500                 newerrno = ENODATA;
501 #else
502                 newerrno = ENOENT;
503 #endif
504                 break;
505         case GNUTLS_E_SRP_PWD_ERROR:
506         case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
507         case GNUTLS_E_HASH_FAILED:
508         case GNUTLS_E_PK_SIGN_FAILED:
509         case GNUTLS_E_CERTIFICATE_ERROR:
510         case GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION:
511         case GNUTLS_E_KEY_USAGE_VIOLATION:
512         case GNUTLS_E_NO_CERTIFICATE_FOUND:
513         case GNUTLS_E_OPENPGP_UID_REVOKED:
514         case GNUTLS_E_OPENPGP_GETKEY_FAILED:
515         case GNUTLS_E_PK_SIG_VERIFY_FAILED:
516         case GNUTLS_E_ILLEGAL_SRP_USERNAME:
517         case GNUTLS_E_INVALID_PASSWORD:
518         case GNUTLS_E_MAC_VERIFY_FAILED:
519         case GNUTLS_E_IA_VERIFY_FAILED:
520         case GNUTLS_E_UNKNOWN_SRP_USERNAME:
521         case GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR:
522         case GNUTLS_E_USER_ERROR:
523         case GNUTLS_E_AUTH_ERROR:
524                 newerrno = EACCES;
525                 break;
526         case GNUTLS_E_INTERRUPTED:
527                 newerrno = EINTR;
528                 break;
529         case GNUTLS_E_INTERNAL_ERROR:
530         case GNUTLS_E_CONSTRAINT_ERROR:
531         case GNUTLS_E_ILLEGAL_PARAMETER:
532                 newerrno = EINVAL;
533                 break;
534         case GNUTLS_E_SAFE_RENEGOTIATION_FAILED:
535                 newerrno = ECONNREFUSED;
536                 break;
537         case GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY:
538         case GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY:
539 #ifdef GNUTLS_E_LIB_IN_ERROR_STATE
540         case GNUTLS_E_LIB_IN_ERROR_STATE:
541 #endif
542                 newerrno = ENOEXEC;
543                 break;
544         case GNUTLS_E_RANDOM_FAILED:
545                 newerrno = EBADF;
546                 break;
547         case GNUTLS_E_CRYPTODEV_IOCTL_ERROR:
548         case GNUTLS_E_CRYPTODEV_DEVICE_ERROR:
549         case GNUTLS_E_HEARTBEAT_PONG_RECEIVED:
550         case GNUTLS_E_HEARTBEAT_PING_RECEIVED:
551         case GNUTLS_E_PKCS11_ERROR:
552         case GNUTLS_E_PKCS11_LOAD_ERROR:
553         case GNUTLS_E_PKCS11_PIN_ERROR:
554         case GNUTLS_E_PKCS11_SLOT_ERROR:
555         case GNUTLS_E_LOCKING_ERROR:
556         case GNUTLS_E_PKCS11_ATTRIBUTE_ERROR:
557         case GNUTLS_E_PKCS11_DEVICE_ERROR:
558         case GNUTLS_E_PKCS11_DATA_ERROR:
559         case GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR:
560         case GNUTLS_E_PKCS11_KEY_ERROR:
561         case GNUTLS_E_PKCS11_PIN_EXPIRED:
562         case GNUTLS_E_PKCS11_PIN_LOCKED:
563         case GNUTLS_E_PKCS11_SESSION_ERROR:
564         case GNUTLS_E_PKCS11_SIGNATURE_ERROR:
565         case GNUTLS_E_PKCS11_TOKEN_ERROR:
566         case GNUTLS_E_PKCS11_USER_ERROR:
567         case GNUTLS_E_CRYPTO_INIT_FAILED:
568         case GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE:
569         case GNUTLS_E_TPM_ERROR:
570         case GNUTLS_E_TPM_KEY_PASSWORD_ERROR:
571         case GNUTLS_E_TPM_SRK_PASSWORD_ERROR:
572         case GNUTLS_E_TPM_SESSION_ERROR:
573         case GNUTLS_E_TPM_KEY_NOT_FOUND:
574         case GNUTLS_E_TPM_UNINITIALIZED:
575         case GNUTLS_E_OCSP_RESPONSE_ERROR:
576         case GNUTLS_E_RANDOM_DEVICE_ERROR:
577 #ifdef EREMOTEIO
578                 newerrno = EREMOTEIO;
579 #else
580                 newerrno = EIO;
581 #endif
582                 break;
583         default:
584                 newerrno = EIO;
585                 break;
586         }
587         errno = newerrno;
588         return;
589 }
590
591 /* Generate Diffie-Hellman parameters - for use with DHE
592  * kx algorithms. TODO: These should be discarded and regenerated
593  * once a day, once a week or once a month. Depending on the
594  * security requirements.
595  */
596 static gtls_error generate_dh_params (void) {
597         unsigned int bits;
598         int gtls_errno = GNUTLS_E_SUCCESS;
599         bits = gnutls_sec_param_to_pk_bits (
600                 GNUTLS_PK_DH,
601                 GNUTLS_SEC_PARAM_LEGACY);
602         //TODO// Acquire DH-params lock
603         E_g2e ("Failed to initialise DH params",
604                 gnutls_dh_params_init (
605                         &dh_params));
606         E_g2e ("Failed to generate DH params",
607                 gnutls_dh_params_generate2 (
608                         dh_params,
609                         bits));
610         //TODO// Release DH-params lock
611         return gtls_errno;
612 }
613
614 /* Load Diffie-Hellman parameters from file - or generate them when load fails.
615  */
616 static gtls_error load_dh_params (void) {
617         gnutls_dh_params_t dhp;
618         gnutls_datum_t pkcs3;
619         char *filename = cfg_tls_dhparamfile ();
620         int gtls_errno = GNUTLS_E_SUCCESS;
621         memset (&pkcs3, 0, sizeof (pkcs3));
622         if (filename) {
623                 E_g2e ("No PKCS #3 PEM file with DH params",
624                         gnutls_load_file (
625                                 filename,
626                                 &pkcs3));
627                 E_gnutls_clear_errno ();
628                 E_g2e ("Failed to initialise DH params",
629                         gnutls_dh_params_init (
630                                 &dhp));
631                 E_g2e ("Failed to import DH params from PKCS #3 PEM",
632                         gnutls_dh_params_import_pkcs3 (
633                                 dhp,
634                                 &pkcs3,
635                                 GNUTLS_X509_FMT_PEM));
636                 E_gnutls_clear_errno ();
637         }
638         if (pkcs3.data != NULL) {
639                 free (pkcs3.data);
640         }
641         if (gtls_errno != GNUTLS_E_SUCCESS) {
642                 //
643                 // File failed to load, so try to generate fresh DH params
644                 int gtls_errno_stack0;
645                 gtls_errno = GNUTLS_E_SUCCESS;
646                 tlog (TLOG_CRYPTO, LOG_DEBUG, "Failed to load DH params from %s; generating fresh parameters", filename);
647                 E_g2e ("Failed to generate DH params",
648                         generate_dh_params ());
649                 gtls_errno_stack0 = gtls_errno;
650                 //TODO// Acquire DH-params lock
651                 E_g2e ("Failed to format DH params as PKCS #3 PEM",
652                         gnutls_dh_params_export2_pkcs3 (
653                                 dh_params,
654                                 GNUTLS_X509_FMT_PEM,
655                                 &pkcs3));
656                 //TODO// Release DH-params lock
657                 if ((gtls_errno == GNUTLS_E_SUCCESS) && (filename != NULL)) {
658                         FILE *pemf;
659                         //
660                         // Best effor file save -- readback will parse
661                         pemf = fopen (filename, "w");
662                         if (pemf != NULL) {
663                                 fwrite (pkcs3.data, 1, pkcs3.size, pemf);
664                                 fclose (pemf);
665                                 tlog (TLOG_FILES, LOG_DEBUG, "Saved DH params to %s (best-effort)", filename);
666                         }
667                         E_gnutls_clear_errno ();
668                 }
669                 gtls_errno = gtls_errno_stack0;
670         } else {
671                 gnutls_dh_params_t old_dh;
672                 //TODO// Acquire DH-params lock
673                 old_dh = dh_params;
674                 dh_params = dhp;
675                 //TODO// Release DH-params lock
676                 if (old_dh) {
677                         gnutls_dh_params_deinit (old_dh);
678                 }
679         }
680         return gtls_errno;
681 }
682
683 /* Remove DH parameters, to be used during program cleanup. */
684 static void remove_dh_params (void) {
685         if (dh_params) {
686                 gnutls_dh_params_deinit (dh_params);
687                 dh_params = NULL;
688         }
689 }
690
691
692 /* A log printing function
693  */
694 void log_gnutls (int level, const char *msg) {
695         tlog (TLOG_TLS, level, "GnuTLS: %s", msg);
696 }
697
698
699 /* Implement the GnuTLS function for token insertion callback.  This function
700  * refers back to the generic callback for token insertion.
701  */
702 int gnutls_token_callback (void *const userdata,
703                                 const char *const label,
704                                 unsigned retry) {
705         if (token_callback (label, retry)) {
706                 return GNUTLS_E_SUCCESS;
707         } else {
708                 return GNUTLS_E_PKCS11_TOKEN_ERROR;
709         }
710 }
711  
712
713 /*
714  * Implement the GnuTLS function for PIN callback.  This function calls
715  * the generic PIN callback operation.
716  */
717 int gnutls_pin_callback (void *userdata,
718                                 int attempt,
719                                 const char *token_url,
720                                 const char *token_label,
721                                 unsigned int flags,
722                                 char *pin,
723                                 size_t pin_max) {
724         if (flags & GNUTLS_PIN_SO) {
725                 return GNUTLS_E_USER_ERROR;
726         }
727         if (pin_callback (attempt, token_url, NULL, pin, pin_max)) {
728                 return 0;
729         } else {
730                 return GNUTLS_E_PKCS11_PIN_ERROR;
731         }
732 }
733
734
735 /* Register a PKCS #11 provider with the GnuTLS environment. */
736 void starttls_pkcs11_provider (char *p11path) {
737         unsigned int token_seq = 0;
738         char *p11uri;
739         if (gnutls_pkcs11_add_provider (p11path, NULL) != 0) {
740                 fprintf (stderr, "Failed to register PKCS #11 library %s with GnuTLS\n", p11path);
741                 exit (1);
742         }
743         while (gnutls_pkcs11_token_get_url (token_seq, 0, &p11uri) == 0) {
744 #ifdef DEBUG
745                 fprintf (stderr, "DEBUG: Found token URI %s\n", p11uri);
746 #endif
747                 //TODO// if (gnutls_pkcs11_token_get_info (p11uri, GNUTLS_PKCS11_TOKEN_LABEL-of-SERIAL-of-MANUFACTURER-of-MODEL, output, utput_size) == 0) { ... }
748                 gnutls_free (p11uri);
749                 token_seq++;
750         }
751         //TODO// Select token by name (value)
752         //TODO// if PIN available then set it up
753         //TODO:WHY?// free_p11pin ();
754 }
755
756 static void cleanup_starttls_credentials (void);/* Defined below */
757 static void cleanup_starttls_validation (void); /* Defined below */
758 #ifdef HAVE_TLS_KDH
759 static void cleanup_starttls_kerberos (void);   /* Defined below */
760 static int setup_starttls_kerberos (void);      /* Defined below */
761 #endif
762 static int setup_starttls_credentials (void);   /* Defined below */
763
764 /* The global and static setup function for the starttls functions.
765  */
766 void setup_starttls (void) {
767         const char *curver;
768         int gtls_errno = GNUTLS_E_SUCCESS;
769         char *otfsigcrt, *otfsigkey;
770         //
771         // Setup configuration variables
772         maxpreauth = cfg_tls_maxpreauth ();
773         //
774         // Basic library actions
775         tlog (TLOG_TLS, LOG_DEBUG, "Compiled against GnuTLS version %s", GNUTLS_VERSION);
776         curver = gnutls_check_version (GNUTLS_VERSION);
777         tlog (TLOG_TLS, LOG_DEBUG, "Running against %s GnuTLS version %s", curver? "acceptable": "OLDER", curver? curver: gnutls_check_version (NULL));
778         E_g2e ("GnuTLS global initialisation failed",
779                 gnutls_global_init ());
780         E_gnutls_clear_errno ();
781         E_g2e ("GnuTLS PKCS #11 initialisation failed",
782                 gnutls_pkcs11_init (
783                         GNUTLS_PKCS11_FLAG_MANUAL, NULL));
784         //
785         // Setup logging / debugging
786         if (cfg_log_level () == LOG_DEBUG) {
787                 gnutls_global_set_log_function (log_gnutls);
788                 gnutls_global_set_log_level (9);
789         }
790         //
791         // Setup Kerberos
792 #ifdef HAVE_TLS_KDH
793         E_g2e ("Kerberos initialisation failed",
794                 setup_starttls_kerberos ());
795 #endif
796         //
797         // Setup callbacks for user communication
798         gnutls_pkcs11_set_token_function (gnutls_token_callback, NULL);
799         gnutls_pkcs11_set_pin_function (gnutls_pin_callback, NULL);
800         //
801         // Setup DH parameters
802         E_g2e ("Loading DH params failed",
803                 load_dh_params ());
804         //
805         // Setup shared credentials for all client server processes
806         E_g2e ("Failed to setup GnuTLS callback credentials",
807                 setup_starttls_credentials ());
808         //
809         // Parse the default priority string
810 #ifdef HAVE_TLS_KDH
811         E_g2e ("Failed to setup NORMAL priority cache",
812                 gnutls_priority_init (&priority_normal,
813                         "NONE:"
814                         "%ASYM_CERT_TYPES:"
815                         "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
816                         "+COMP-NULL:"
817                         "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
818                         "+ANON-ECDH:"
819                         "+ECDHE-KRB:" // +ECDHE-KRB-RSA:+ECDHE-KRB-ECDSA:"
820                         "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:"
821                         "+CTYPE-SRV-KRB:+CTYPE-SRV-X.509:+CTYPE-SRV-OPENPGP:"
822                         "+CTYPE-CLI-KRB:+CTYPE-CLI-X.509:+CTYPE-CLI-OPENPGP:"
823                         "+SRP:+SRP-RSA:+SRP-DSS",
824                         NULL));
825 #else
826         E_g2e ("Failed to setup NORMAL priority cache",
827                 gnutls_priority_init (&priority_normal,
828                         "NONE:"
829                         "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
830                         "+COMP-NULL:+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
831                         "+ANON-ECDH:"
832                         "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:"
833                         "+CTYPE-X.509:+CTYPE-OPENPGP:"
834                         "+SRP:+SRP-RSA:+SRP-DSS",
835                         NULL));
836 #endif
837         //
838         // Try to setup on-the-fly signing key / certificate and gen a certkey
839         otfsigcrt = cfg_tls_onthefly_signcert ();
840         otfsigkey = cfg_tls_onthefly_signkey ();
841 fprintf (stderr, "DEBUG: gtls_errno = %d, otfsigcrt == %s, otfsigkey == %s\n", gtls_errno, otfsigcrt? otfsigcrt: "NULL", otfsigkey? otfsigkey: "NULL");
842         if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigcrt != NULL)) {
843                 FILE *crtfile = NULL;
844 fprintf (stderr, "DEBUG: gtls_errno==%d when initialising onthefly_issuercrt\n", gtls_errno);
845                 E_g2e ("Failed to initialise on-the-fly issuer certificate structure",
846                         gnutls_x509_crt_init (&onthefly_issuercrt));
847                 if (strncmp (otfsigcrt, "file:", 5) == 0) {
848                         // Provisionary support for the "file:" prefix
849                         otfsigcrt += 5;
850                 }
851                 crtfile = fopen (otfsigcrt, "r");
852                 if (crtfile == NULL) {
853                         E_g2e ("Failed to open on-the-fly issuer certificate file",
854                                 GNUTLS_E_FILE_ERROR);
855 fprintf (stderr, "DEBUG: gtls_errno==%d after failing to open file for onthefly_issuercrt\n", gtls_errno);
856                 } else {
857                         char crt [5001];
858                         size_t len = fread (crt, 1, sizeof (crt), crtfile);
859                         if (ferror (crtfile)) {
860                                 E_g2e ("Failed to read on-the-fly issuer certificate from file",
861                                         GNUTLS_E_FILE_ERROR);
862                         } else if ((len >= sizeof (crt)) || !feof (crtfile)) {
863                                 E_g2e ("Unexpectedly long on-the-fly issuer certificate file",
864                                         GNUTLS_E_FILE_ERROR);
865                         } else {
866                                 gnutls_datum_t cd = {
867                                         .data = crt,
868                                         .size = len
869                                 };
870 fprintf (stderr, "DEBUG: gtls_errno==%d before importing onthefly_issuercrt\n", gtls_errno);
871                                 E_g2e ("Failed to import on-the-fly certificate from file",
872                                         gnutls_x509_crt_import (onthefly_issuercrt, &cd, GNUTLS_X509_FMT_DER));
873 fprintf (stderr, "DEBUG: gtls_errno==%d after  importing onthefly_issuercrt\n", gtls_errno);
874                         }
875                         fclose (crtfile);
876                 }
877         }
878         if ((gtls_errno == GNUTLS_E_SUCCESS) && (otfsigkey != NULL)) {
879                 E_g2e ("Failed to initialise on-the-fly issuer private key structure",
880                         gnutls_privkey_init (&onthefly_issuerkey));
881 fprintf (stderr, "DEBUG: before onthefly p11 import, gtlserrno = %d\n", gtls_errno);
882                 E_g2e ("Failed to import pkcs11: URI into on-the-fly issuer private key",
883                         gnutls_privkey_import_pkcs11_url (onthefly_issuerkey, otfsigkey));
884 fprintf (stderr, "DEBUG: after  onthefly p11 import, gtlserrno = %d\n", gtls_errno);
885         }
886 fprintf (stderr, "DEBUG: When it matters, gtls_errno = %d, onthefly_issuercrt %s NULL, onthefly_issuerkey %s NULL\n", gtls_errno, onthefly_issuercrt?"!=":"==", onthefly_issuerkey?"!=":"==");
887         if ((gtls_errno == GNUTLS_E_SUCCESS) && (onthefly_issuercrt != NULL) && (onthefly_issuerkey != NULL)) {
888                 E_g2e ("Failed to initialise on-the-fly certificate session key",
889                         gnutls_x509_privkey_init (&onthefly_subjectkey));
890                 E_g2e ("Failed to generate on-the-fly certificate session key",
891                         gnutls_x509_privkey_generate (onthefly_subjectkey, GNUTLS_PK_RSA, 2048 /*TODO:FIXED*/, 0));
892                 if (gtls_errno == GNUTLS_E_SUCCESS) {
893                         tlog (TLOG_TLS, LOG_INFO, "Setup for on-the-fly signing with the TLS Pool");
894                 } else {
895                         tlog (TLOG_TLS, LOG_ERR, "Failed to setup on-the-fly signing (shall continue without it)");
896                         gnutls_x509_privkey_deinit (onthefly_subjectkey);
897                         onthefly_subjectkey = NULL;
898                 }
899         } else {
900                 gtls_errno = GNUTLS_E_SUCCESS;
901                 E_gnutls_clear_errno ();
902         }
903         if (onthefly_subjectkey == NULL) {
904                 if (onthefly_issuercrt != NULL) {
905                         gnutls_x509_crt_deinit (onthefly_issuercrt);
906                         onthefly_issuercrt = NULL;
907                 }
908                 if (onthefly_issuerkey != NULL) {
909                         gnutls_privkey_deinit (onthefly_issuerkey);
910                         onthefly_issuerkey = NULL;
911                 }
912         }
913         //
914         // Finally, check whether there was any error setting up GnuTLS
915         if (gtls_errno != GNUTLS_E_SUCCESS) {
916                 tlog (TLOG_TLS, LOG_CRIT, "FATAL: GnuTLS setup failed: %s", gnutls_strerror (gtls_errno));
917                 exit (1);
918         }
919         //MOVED// //
920         //MOVED// // Setup the management databases
921         //MOVED// tlog (TLOG_DB, LOG_DEBUG, "Setting up management databases");
922         //MOVED// E_e2e ("Failed to setup management databases",
923         //MOVED//       setup_management ());
924         //MOVED// if (errno != 0) {
925         //MOVED//       tlog (TLOG_DB, LOG_CRIT, "FATAL: Management databases setup failed: %s", strerror (errno));
926         //MOVED//       exit (1);
927         //MOVED// }
928 }
929
930 /* Cleanup the structures and resources that were setup for handling TLS.
931  */
932 void cleanup_starttls (void) {
933         //MOVED// cleanup_management ();
934         if (onthefly_subjectkey != NULL) {
935                 gnutls_x509_privkey_deinit (onthefly_subjectkey);
936                 onthefly_subjectkey = NULL;
937         }
938         if (onthefly_issuercrt != NULL) {
939                 gnutls_x509_crt_deinit (onthefly_issuercrt);
940                 onthefly_issuercrt = NULL;
941         }
942         if (onthefly_issuerkey != NULL) {
943                 gnutls_privkey_deinit (onthefly_issuerkey);
944                 onthefly_issuerkey = NULL;
945         }
946
947         cleanup_starttls_credentials ();
948 #ifdef HAVE_TLS_KDH
949         cleanup_starttls_kerberos ();
950 #endif
951         remove_dh_params ();
952         gnutls_pkcs11_set_pin_function (NULL, NULL);
953         gnutls_pkcs11_set_token_function (NULL, NULL);
954         gnutls_pkcs11_deinit ();
955         gnutls_priority_deinit (priority_normal);
956         gnutls_global_deinit ();
957 }
958
959
960 /*
961  * The copycat function is a bidirectional transport between the given
962  * remote and local sockets, but it will encrypt traffic from local to
963  * remote, and decrypt traffic from remote to local.  It will do this
964  * until one of the end points is shut down, at which time it will
965  * return and assume the context will close down both pre-existing
966  * sockets.
967  *
968  * This copycat actually has a few sharp claws to watch for -- shutdown
969  * of sockets may drop the last bit of information sent.  First, the
970  * signal POLLHUP is best ignored because it travels asynchronously.
971  * Second, reading 0 is a good indicator of end-of-file and may be
972  * followed by an shutdown of reading from that stream.  But, more
973  * importantly, the other side must have this information forwarded
974  * so it can shutdown.  This means that a shutdown for writing to that
975  * stream is to be sent.  Even when *both* sides have agreed to not send
976  * anything, they may still not have received all they were offered for
977  * reading, so we should SO_LINGER on the sockets so they can acknowledge,
978  * and after a timeout we can establish that shutdown failed and log and
979  * return an error for it.
980  * Will you believe that I had looked up if close() would suffice?  The man
981  * page clearly stated yes.  However, these articles offer much more detail:
982  * http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable
983  * http://www.greenend.org.uk/rjk/tech/poll.html
984  *
985  * This function blocks during its call to poll(), in a state that can easily
986  * be restarted.  This is when thread cancellation is temporarily enabled.
987  * Other threads may use this to cancel the thread and have it joined with that
988  * thread which will subsume its tasks and restart the handshake.  We might
989  * later make this more advanced, by using a cancel stack push/pull mechanisms
990  * to ensure that recv() always results in send() in spite of cancellation.
991  *
992  * The return value of copycat is a GNUTLS_E_ code, usually GNUTLS_E_SUCCESS.
993  * For the moment, only one special value is of concern, namely
994  * GNUTLS_E_REHANDSHAKE which client or server side may receive when an
995  * attempt is made to renegotiate the security of the connection.
996  */
997 static int copycat (int local, int remote, gnutls_session_t wrapped, pool_handle_t client) {
998         char buf [1024];
999         struct pollfd inout [3];
1000         ssize_t sz;
1001         struct linger linger = { 1, 10 };
1002         int have_client;
1003         int retval = GNUTLS_E_SUCCESS;
1004
1005 client = INVALID_POOL_HANDLE;
1006         inout [0].fd = local;
1007         inout [1].fd = remote;
1008 #ifdef WINDOWS_PORT
1009         have_client = 0;
1010 #else
1011         inout [2].fd = client;
1012         have_client = inout [2].fd != INVALID_POOL_HANDLE;
1013 #endif
1014         if (!have_client) {
1015                 inout [2].revents = 0;  // Will not be written by poll
1016                 //FORK!=DETACH// inout [2].fd = ctlkey_signalling_fd;
1017         }
1018         inout [0].events = POLLIN;
1019         inout [1].events = POLLIN;
1020         inout [2].events = 0;   // error events only
1021         tlog (TLOG_COPYCAT, LOG_DEBUG, "Starting copycat cycle for local=%d, remote=%d, control=%d", local, remote, client);
1022         while (((inout [0].events | inout [1].events) & POLLIN) != 0) {
1023                 int polled;
1024                 assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE,  NULL) == 0);
1025                 pthread_testcancel ();  // Efficiency & Certainty
1026                 polled = poll (inout, have_client? 3: 2, -1);
1027                 assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
1028                 if (polled == -1) {
1029                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat polling returned an error");
1030                         break;  // Polling sees an error
1031                 }
1032                 if (inout [0].revents & POLLIN) {
1033                         // Read local and encrypt to remote
1034                         sz = recv (local, buf, sizeof (buf), RECV_FLAGS);
1035                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d local bytes (or error<0) from %d", (int) sz, local);
1036                         if (sz == -1) {
1037                                 tlog (TLOG_COPYCAT, LOG_ERR, "Error while receiving: %s", strerror (errno));
1038                                 break;  // stream error
1039                         } else if (sz == 0) {
1040                                 inout [0].events &= ~POLLIN;
1041                                 shutdown (local, SHUT_RD);
1042 #ifdef WINDOWS_PORT
1043                                 setsockopt (remote, SOL_SOCKET, SO_LINGER, (const char *) &linger, sizeof (linger));
1044 #else /* WINDOWS_PORT */
1045                                 setsockopt (remote, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
1046 #endif /* WINDOWS_PORT */
1047                                 gnutls_bye (wrapped, GNUTLS_SHUT_WR);
1048                         } else if (gnutls_record_send (wrapped, buf, sz) != sz) {
1049                                 tlog (TLOG_COPYCAT, LOG_ERR, "gnutls_record_send() failed to pass on the requested bytes");
1050                                 break;  // communication error
1051                         } else {
1052                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to remote %d", (int) sz, remote);
1053                         }
1054                 }
1055                 if (inout [1].revents & POLLIN) {
1056                         // Read remote and decrypt to local
1057                         sz = gnutls_record_recv (wrapped, buf, sizeof (buf));
1058                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat received %d remote bytes from %d (or error if <0)", (int) sz, remote);
1059                         if (sz < 0) {
1060                                 //TODO// Process GNUTLS_E_REHANDSHAKE
1061                                 if (sz == GNUTLS_E_REHANDSHAKE) {
1062                                         tlog (TLOG_TLS, LOG_INFO, "Received renegotiation request over TLS handle %d", remote);
1063                                         retval = GNUTLS_E_REHANDSHAKE;
1064                                         break;
1065                                 } else if (gnutls_error_is_fatal (sz)) {
1066                                         tlog (TLOG_TLS, LOG_ERR, "GnuTLS fatal error: %s", gnutls_strerror (sz));
1067                                         break;  // stream error
1068                                 } else {
1069                                         tlog (TLOG_TLS, LOG_INFO, "GnuTLS recoverable error: %s", gnutls_strerror (sz));
1070                                 }
1071                         } else if (sz == 0) {
1072                                 inout [1].events &= ~POLLIN;
1073                                 shutdown (remote, SHUT_RD);
1074 #ifdef WINDOWS_PORT
1075                                 setsockopt (local, SOL_SOCKET, SO_LINGER, (const char *) &linger, sizeof (linger));
1076 #else /* WINDOWS_PORT */
1077                                 setsockopt (local, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger));
1078 #endif /* WINDOWS_PORT */
1079                                 shutdown (local, SHUT_WR);
1080                         } else if (send (local, buf, sz, RECV_FLAGS) != sz) {
1081                                 break;  // communication error
1082                         } else {
1083                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat sent %d bytes to local %d", (int) sz, local);
1084                         }
1085                 }
1086                 inout [0].revents &= ~(POLLIN | POLLHUP); // Thy copying cat?
1087                 inout [1].revents &= ~(POLLIN | POLLHUP); // Retract thee claws!
1088                 if ((inout [0].revents | inout [1].revents) & ~POLLIN) {
1089                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat data connection polling returned a special condition");
1090                         break;  // Apparently, one of POLLERR, POLLHUP, POLLNVAL
1091                 }
1092 #ifndef WINDOWS_PORT
1093                 if (inout [2].revents & ~POLLIN) {
1094                         if (have_client) {
1095                                 // This case is currently not ever triggered
1096                                 tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat control connection polling returned a special condition");
1097                                 break;  // Apparently, one of POLLERR, POLLHUP, POLLNVAL
1098                         } else {
1099                                 inout [2].fd = client;
1100                                 have_client = inout [2].fd >= 0;
1101                                 if (have_client) {
1102                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal to set control fd to %d", inout [2].fd);
1103                                 } else {
1104                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Copycat signalling_fd polling raised a signal that could be ignored");
1105                                 }
1106                                 continue;
1107                         }
1108                 }
1109 #endif /* !WINDOWS_PORT */
1110         }
1111         tlog (TLOG_COPYCAT, LOG_DEBUG, "Ending copycat cycle for local=%d, remote=%d", local, remote);
1112         return retval;
1113 }
1114
1115
1116 /* The callback function that retrieves certification information from either
1117  * the client or the server in the course of the handshake procedure.
1118  */
1119 gtls_error clisrv_cert_retrieve (gnutls_session_t session,
1120                                 const gnutls_datum_t* req_ca_dn,
1121                                 int nreqs,
1122                                 const gnutls_pk_algorithm_t* pk_algos,
1123                                 int pk_algos_length,
1124                                 gnutls_pcert_st** pcert,
1125                                 unsigned int *pcert_length,
1126                                 gnutls_privkey_t *pkey) {
1127         gnutls_certificate_type_t certtp;
1128         gnutls_pcert_st *pc = NULL;
1129         struct command *cmd;
1130         char *lid, *rid;
1131         gnutls_datum_t privdatum = { NULL, 0 };
1132         gnutls_datum_t certdatum = { NULL, 0 };
1133         gnutls_openpgp_crt_t pgpcert = NULL;
1134         gnutls_openpgp_privkey_t pgppriv = NULL;
1135         int gtls_errno = GNUTLS_E_SUCCESS;
1136         int lidtype;
1137         int lidrole = 0;
1138         char *rolestr;
1139         char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.localid)];
1140         size_t snilen = sizeof (sni);
1141         int snitype;
1142         int ok;
1143         uint32_t flags;
1144         char *p11priv;
1145         uint8_t *pubdata;
1146         int pubdatalen;
1147         gtls_error fetch_local_credentials (struct command *cmd);
1148         gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum);
1149
1150         //
1151         // Setup a number of common references and structures
1152         errno = 0;
1153         *pcert = NULL;
1154         cmd = (struct command *) gnutls_session_get_ptr (session);
1155         if (cmd == NULL) {
1156                 E_g2e ("No data pointer with session",
1157                         GNUTLS_E_INVALID_SESSION);
1158                 return gtls_errno;
1159         }
1160         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
1161                 lidrole = LID_ROLE_CLIENT;
1162                 rolestr = "client";
1163         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
1164                 lidrole = LID_ROLE_SERVER;
1165                 rolestr = "server";
1166         } else {
1167                 E_g2e ("TLS Pool command supports neither local client nor local server role",
1168                         GNUTLS_E_INVALID_SESSION);
1169                 return gtls_errno;
1170         }
1171         lid = cmd->cmd.pio_data.pioc_starttls.localid;
1172         rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
1173
1174         //
1175         // On a server, lookup the server name and match it against lid.
1176         // TODO: For now assume a single server name in SNI (as that is normal).
1177         if (lidrole == LID_ROLE_SERVER) {
1178                 if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) || (snitype != GNUTLS_NAME_DNS)) {
1179                         E_g2e ("Requested SNI error or not a DNS name",
1180                                 GNUTLS_E_NO_CERTIFICATE_FOUND);
1181                         return gtls_errno;
1182                 }
1183                 if (*lid != '\0') {
1184                         int atidx;
1185                         for (atidx=128; atidx > 0; atidx--) {
1186                                 if (lid [atidx-1] == '@') {
1187                                         break;
1188                                 }
1189                         }
1190                         if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
1191                                 tlog (TLOG_TLS, LOG_ERR, "SNI %s does not match preset local identity %s", sni, lid);
1192                                 E_g2e ("Requested SNI does not match local identity",
1193                                         GNUTLS_E_NO_CERTIFICATE_FOUND);
1194                                 return gtls_errno;
1195                         }
1196                 } else {
1197                         // TODO: Should ask for permission before accepting SNI
1198                         memcpy (lid, sni, sizeof (sni));
1199                 }
1200         }
1201
1202         //
1203         // Setup the lidtype parameter for responding
1204 #ifdef HAVE_TLS_KDH
1205         certtp = gnutls_certificate_type_get_ours (session);
1206 #else
1207         certtp = gnutls_certificate_type_get (session);
1208 #endif
1209         if (certtp == GNUTLS_CRT_OPENPGP) {
1210                 tlog (TLOG_TLS, LOG_INFO, "Serving OpenPGP certificate request as a %s", rolestr);
1211                 lidtype = LID_TYPE_PGP;
1212         } else if (certtp == GNUTLS_CRT_X509) {
1213                 tlog (TLOG_TLS, LOG_INFO, "Serving X.509 certificate request as a %s", rolestr);
1214                 lidtype = LID_TYPE_X509;
1215 #ifdef HAVE_TLS_KDH
1216         } else if (certtp == GNUTLS_CRT_KRB) {
1217                 tlog (TLOG_TLS, LOG_INFO, "Serving Kerberos Ticket request as a %s", rolestr);
1218                 lidtype = LID_TYPE_KRB5;
1219 #endif
1220         } else {
1221                 // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
1222                 tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate %d retrieval attempted as a %s", certtp, rolestr);
1223                 E_g2e ("Requested certtype is neither X.509 nor OpenPGP",
1224                         GNUTLS_E_CERTIFICATE_ERROR);
1225                 return gtls_errno;
1226         }
1227
1228         //
1229         // Find the prefetched local identity to use towards this remote
1230         // Send a callback to the user if none is available and accessible
1231         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_CHECK) {
1232                 uint32_t oldcmd = cmd->cmd.pio_cmd;
1233                 struct command *resp;
1234                 cmd->cmd.pio_cmd = PIOC_STARTTLS_LOCALID_V2;
1235                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_STARTTLS_LOCALID_V2");
1236                 resp = send_callback_and_await_response (cmd, 0);
1237                 assert (resp != NULL);  // No timeout, should be non-NULL
1238                 if (resp->cmd.pio_cmd != PIOC_STARTTLS_LOCALID_V2) {
1239                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
1240                         cmd->cmd.pio_cmd = oldcmd;
1241                         return GNUTLS_E_CERTIFICATE_ERROR;
1242                 }
1243                 assert (resp == cmd);  // No ERROR, so should be the same
1244                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Processing callback response that sets plainfd:=%d and lid:=\"%s\" for rid==\"%s\"", cmd->passfd, lid, rid);
1245                 cmd->cmd.pio_cmd = oldcmd;
1246                 //
1247                 // Check that new rid is a generalisation of original rid
1248                 // Note: This is only of interest for client operation
1249                 if (lidrole == LID_ROLE_CLIENT) {
1250                         selector_t newrid = donai_from_stable_string (rid, strlen (rid));
1251                         donai_t oldrid = donai_from_stable_string (cmd->orig_starttls->remoteid, strlen (cmd->orig_starttls->remoteid));
1252                         if (!donai_matches_selector (&oldrid, &newrid)) {
1253                                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
1254                         }
1255                 }
1256                 //
1257                 // Now reiterate to lookup lid credentials in db_localid
1258                 E_g2e ("Missing local credentials",
1259                         fetch_local_credentials (cmd));
1260         }
1261         if (cmd->lids [lidtype - LID_TYPE_MIN].data == NULL) {
1262 fprintf (stderr, "DEBUG: Missing certificate for local ID %s and remote ID %s\n", lid, rid);
1263                 E_g2e ("Missing certificate for local ID",
1264                         GNUTLS_E_NO_CERTIFICATE_FOUND);
1265                 return gtls_errno;
1266         }
1267
1268         //
1269         // Split the credential into its various aspects
1270         ok = dbcred_interpret (
1271                 &cmd->lids [lidtype - LID_TYPE_MIN],
1272                 &flags,
1273                 &p11priv,
1274                 &certdatum.data,
1275                 &certdatum.size);
1276         tlog (TLOG_DB, LOG_DEBUG, "BDB entry has flags=0x%08x, p11priv=\"%s\", cert.size=%d", flags, p11priv, certdatum.size);
1277         //TODO// ok = ok && verify_cert_... (...); -- keyidlookup
1278         if (!ok) {
1279                 gtls_errno = GNUTLS_E_CERTIFICATE_ERROR;
1280         }
1281
1282         //
1283         // Allocate response structures
1284         *pcert_length = 0;
1285         *pcert = load_certificate_chain (flags, pcert_length, &certdatum);
1286         if (*pcert == NULL) {
1287                 E_g2e ("Failed to load certificate chain",
1288                         GNUTLS_E_CERTIFICATE_ERROR);
1289                 return gtls_errno;
1290         }
1291         cmd->session_certificate = (intptr_t) (void *) *pcert;  //TODO// Used for session cleanup
1292
1293         //
1294         // Setup private key
1295         E_g2e ("Failed to initialise private key",
1296                 gnutls_privkey_init (
1297                         pkey));
1298         if ((onthefly_subjectkey != NULL) && (strcmp (p11priv, onthefly_p11uri) == 0)) {
1299                 // Setup the on-the-fly certification key as private key
1300                 E_g2e ("Failed to import on-the-fly subject private key",
1301                         gnutls_privkey_import_x509 (
1302                                 *pkey,
1303                                 onthefly_subjectkey,
1304                                 GNUTLS_PRIVKEY_IMPORT_COPY));
1305 #ifdef HAVE_TLS_KDH
1306         } else if (lidtype == LID_TYPE_KRB5) {
1307                 // Fake a private key for Kerberos (we sign it out here, not GnuTLS)
1308                 E_g2e ("Failed to generate a private-key placeholder for Kerberos",
1309                         gnutls_privkey_generate_krb (
1310                                 *pkey,
1311                                 0));
1312 #endif
1313         } else {
1314                 // Import the PKCS #11 key as the private key for use by GnuTLS
1315                 if (gtls_errno == GNUTLS_E_SUCCESS) {
1316                         cmd->session_privatekey = (intptr_t) (void *) *pkey;    //TODO// Used for session cleanup
1317                 }
1318                 E_g2e ("Failed to import PKCS #11 private key URI",
1319                         gnutls_privkey_import_pkcs11_url (
1320                                 *pkey,
1321                                 p11priv));
1322         }
1323         E_gnutls_clear_errno ();
1324
1325 //TODO// Moved out (start)
1326
1327         //
1328         // Setup public key certificate
1329         switch (lidtype) {
1330         case LID_TYPE_X509:
1331                 E_g2e ("MOVED: Failed to import X.509 certificate into chain",
1332                         gnutls_pcert_import_x509_raw (
1333                                 *pcert,
1334                                 &certdatum,
1335                                 GNUTLS_X509_FMT_DER,
1336                                 0));
1337                 break;
1338         case LID_TYPE_PGP:
1339                 E_g2e ("MOVED: Failed to import OpenPGP public key",
1340                         gnutls_pcert_import_openpgp_raw (
1341                                 *pcert,
1342                                 &certdatum,
1343                                 GNUTLS_OPENPGP_FMT_RAW,
1344                                 NULL,   /* use master key */
1345                                 0));
1346                 break;
1347 #ifdef HAVE_TLS_KDH
1348         case LID_TYPE_KRB5:
1349                 if (lidrole == LID_ROLE_CLIENT) {
1350                         //
1351                         // KDH-Only or KDH-Enhanced; fetch ticket for localid
1352                         // and a TGT based on it for service/remoteid@REALM
1353                         //
1354                         // First, try to obtain a TGT and key, in various ways
1355                         krb5_keyblock key;
1356                         krb5_creds *tgt = NULL;
1357                         krb5_creds *ticket = NULL;
1358                         krb5_ccache cc = NULL;
1359                         int status = 0;
1360                         memset (&key,    0, sizeof (key   ));
1361                         status = have_key_tgt_cc (
1362                                 cmd, krbctx_cli,
1363                                 1, 0, 0,
1364                                 p11priv,
1365                                 krb_kt_cli,
1366                                 &key, &tgt, &cc);
1367                         if (status >= 1) {
1368                                 // We never use this key ourselves
1369                                 krb5_free_keyblock_contents (krbctx_cli, &key);
1370                         }
1371                         if (status < 2) {
1372                                 // Stop processing when no tgt was found
1373                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1374                                 break;
1375                         }
1376                         //
1377                         // Store client identity in session object
1378                         if (0 != krb5_copy_principal (
1379                                         krbctx_cli,
1380                                         tgt->client,
1381                                         &cmd->krbid_cli)) {
1382                                 krb5_free_creds (krbctx_cli, tgt);
1383                                 tgt = NULL;
1384                                 if (cc != NULL) {
1385                                         krb5_cc_close (krbctx_cli, cc);
1386                                         cc = NULL;
1387                                 }
1388                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1389                                 break;
1390                         }
1391                         //
1392                         // Now find a service ticket to talk to, and its key
1393                         //TODO// Pass credcache instead?
1394                         status = have_service_ticket (
1395                                 cmd, krbctx_cli,
1396                                 cc,
1397                                 cmd->krbid_cli,
1398                                 &ticket);
1399                         if (cc != NULL) {
1400                                 // We don't need cc anymore below
1401                                 krb5_cc_close (krbctx_cli, cc);
1402                         }
1403                         if (status < 1) {
1404                                 // Stop processing when no ticket was found
1405                                 krb5_free_creds (krbctx_cli, tgt);
1406                                 tgt = NULL;
1407                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1408                                 break;
1409                         }
1410                         //
1411                         // Only for KDH-Only mode can the client rely on a
1412                         // server principal taken from the ticket;
1413                         // So only store krbid_srv for KDH-Only mode.
1414                         if ((gnutls_certificate_type_get_peers (cmd->session)
1415                                                 == GNUTLS_CRT_KRB) &&
1416                                         (0 != krb5_copy_principal (
1417                                                 krbctx_cli,
1418                                                 tgt->server,
1419                                                 &cmd->krbid_srv))) {
1420                                 krb5_free_creds (krbctx_cli, ticket);
1421                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1422                                 break;
1423                         }
1424                         krb5_free_creds (krbctx_cli, tgt);
1425                         tgt = NULL;
1426                         if (0 != krb5_copy_keyblock_contents (
1427                                         krbctx_cli,
1428                                         &ticket->keyblock,
1429                                         &cmd->krb_key)) {
1430                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1431                                 // continue, with E_g2e() skipping import
1432                         }
1433                         certdatum.data = ticket->ticket.data;
1434                         certdatum.size = ticket->ticket.length;
1435                         E_g2e ("MOVED: Failed to import Kerberos ticket",
1436                                 gnutls_pcert_import_krb_raw (
1437                                         *pcert,
1438                                         &certdatum,
1439                                         0));
1440                         krb5_free_creds (krbctx_cli, ticket);
1441                 } else {
1442                         //
1443                         // For KDH-Only, the server supplies one of:
1444                         //  - an empty ticket (0 bytes long)
1445                         //  - a TGT for user-to-user mode (where considered useful)
1446                         //TODO// E_g2e ("MOVED: Failed to import Kerberos ticket",
1447                         //TODO//        gnutls_pcert_import_krb_raw (
1448                         //TODO//                *pcert,
1449                         //TODO//                &certdatum,     //TODO:WHATSFOUND//
1450                         //TODO//                0));
1451                         int u2u = 0;
1452                         int status = 0;
1453                         krb5_creds *tgt = NULL;
1454                         //
1455                         // Determine whether we want to run in user-to-user mode
1456                         // for which we should supply a TGT to the TLS client
1457                         u2u = u2u || ((PIOF_STARTTLS_BOTHROLES_PEER & ~cmd->cmd.pio_data.pioc_starttls.flags) == 0);
1458                         u2u = u2u || (strchr (rid, '@') != NULL);
1459                         // u2u = u2u || "shaken hands on TLS symmetry extension"
1460                         u2u = u2u && got_cc_srv;  // We may simply not be able!
1461                         //
1462                         // When not in user-to-user mode, deliver 0 bytes
1463                         if (!u2u) {
1464                                 certdatum.data = "";
1465                                 certdatum.size = 0;
1466                                 E_g2e ("Failed to withhold Kerberos server ticket",
1467                                         gnutls_pcert_import_krb_raw (
1468                                                 *pcert,
1469                                                 &certdatum,
1470                                                 0));
1471                                 break;
1472                         }
1473                         //
1474                         // Continue specifically for user-to-user mode.
1475                         //TODO// Setup server principal identity
1476                         //
1477                         // Fetch the service's key
1478                         status = have_key_tgt_cc (
1479                                 cmd, krbctx_srv,
1480                                 1, 0, 0,        // Hmm... later we know kvno/etype
1481                                 p11priv,
1482                                 krb_kt_srv,
1483                                 &cmd->krb_key, &tgt, NULL);
1484                         if (status == 1) {
1485                                 // There's no use in having just the key
1486                                 krb5_free_keyblock_contents (krbctx_srv, &cmd->krb_key);
1487                                 memset (&cmd->krb_key, 0, sizeof (cmd->krb_key));
1488                         }
1489                         if (status < 2) {
1490                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1491                         } else if (0 != krb5_copy_principal (
1492                                                 krbctx_srv, 
1493                                                 tgt->server, 
1494                                                 &cmd->krbid_srv)) {
1495                                 gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
1496                         }
1497                         certdatum.data = tgt->ticket.data;
1498                         certdatum.size = tgt->ticket.length;
1499                         E_g2e ("Failed to withhold Kerberos server ticket",
1500                                 gnutls_pcert_import_krb_raw (
1501                                         *pcert,
1502                                         &certdatum,
1503                                         0));
1504                         krb5_free_creds (krbctx_cli, tgt);
1505                         tgt = NULL;
1506                 }
1507                 break;
1508 #endif
1509         default:
1510                 /* Should not happen */
1511                 break;
1512         }
1513
1514 //TODO// Moved out (end)
1515
1516 #ifdef ANCIENT_CODE_WHEN_DBERRNO_RAN_IN_PARALLEL
1517         //
1518         // Lap up any overseen POSIX error codes in errno
1519         if (errno) {
1520                 tlog (TLOG_TLS, LOG_DEBUG, "Failing TLS on errno=%d / %s", errno, strerror (errno));
1521                 cmd->session_errno = errno;
1522                 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
1523         }
1524 #endif
1525
1526         //
1527         // Return the overral error code, hopefully GNUTLS_E_SUCCESS
1528         tlog (TLOG_TLS, LOG_DEBUG, "Returning %d / %s from clisrv_cert_retrieve()", gtls_errno, gnutls_strerror (gtls_errno));
1529 fprintf (stderr, "DEBUG: clisrv_cert_retrieve() sets *pcert to 0x%xl (length %d)... {pubkey = 0x%lx, cert= {data = 0x%lx, size=%ld}, type=%ld}\n", (long) *pcert, *pcert_length, (long) (*pcert)->pubkey, (long) (*pcert)->cert.data, (long) (*pcert)->cert.size, (long) (*pcert)->type);
1530         return gtls_errno;
1531 }
1532
1533 /* Load a single certificate in the given gnutls_pcert_st from the given
1534  * gnutls_datum_t.  Use the lidtype to determine how to do this.
1535  */
1536 gtls_error load_certificate (int lidtype, gnutls_pcert_st *pcert, gnutls_datum_t *certdatum) {
1537         int gtls_errno = GNUTLS_E_SUCCESS;
1538         //
1539         // Setup public key certificate
1540         switch (lidtype) {
1541         case LID_TYPE_X509:
1542 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]);
1543                 E_g2e ("Failed to import X.509 certificate into chain",
1544                         gnutls_pcert_import_x509_raw (
1545                                 pcert,
1546                                 certdatum,
1547                                 GNUTLS_X509_FMT_DER,
1548                                 0));
1549                 break;
1550         case LID_TYPE_PGP:
1551                 E_g2e ("Failed to import OpenPGP certificate",
1552                         gnutls_pcert_import_openpgp_raw (
1553                                 pcert,
1554                                 certdatum,
1555                                 GNUTLS_OPENPGP_FMT_RAW,
1556                                 NULL,   /* use master key */
1557                                 0));
1558                 break;
1559         case LID_TYPE_KRB5:
1560                 /* Binary information is currently moot, so do not load it */
1561                 break;
1562         default:
1563                 /* Should not happen */
1564                 break;
1565         }
1566         return gtls_errno;
1567 }
1568
1569
1570 /* Load a certificate chain.  This returns a value for a retrieval function's
1571  * pcert, and also modifies the chainlen.  The latter starts at 0, and is
1572  * incremented in a nested procedure that unrolls until all certificates are
1573  * loaded.
1574  */
1575 gnutls_pcert_st *load_certificate_chain (uint32_t flags, unsigned int *chainlen, gnutls_datum_t *certdatum) {
1576         gnutls_pcert_st *chain;
1577         unsigned int mypos = *chainlen;
1578         int gtls_errno = GNUTLS_E_SUCCESS;
1579
1580         //
1581         // Quick and easy: No chaining required, just add the literal data.
1582         // Note however, this may be the end of a chain, so allocate all
1583         // structures and load the single one at the end.
1584         if ((flags & (LID_CHAINED | LID_NEEDS_CHAIN)) == 0) {
1585                 (*chainlen)++;
1586                 chain = (gnutls_pcert_st *) calloc (*chainlen, sizeof (gnutls_pcert_st));
1587                 if (chain != NULL) {
1588                         memset (chain,
1589                                 0,
1590                                 (*chainlen) * sizeof (gnutls_pcert_st));
1591                 } else {
1592                         gtls_errno = GNUTLS_E_MEMORY_ERROR;
1593                 }
1594                 E_g2e ("Failed to load certificate into chain",
1595                         load_certificate (
1596                                 flags & LID_TYPE_MASK,
1597                                 &chain [mypos],
1598                                 certdatum));
1599                 if (gtls_errno != GNUTLS_E_SUCCESS) {
1600                         if (chain) {
1601                                 free (chain);
1602                         }
1603                         *chainlen = 0;
1604                         chain = NULL;
1605                 }
1606                 return chain;
1607         }
1608
1609         //
1610         // First extended case.  Chain certs in response to LID_CHAINED.
1611         // Recursive calls are depth-first, so we only add our first cert
1612         // after a recursive call succeeds.  Any LID_NEEDS_CHAIN work is
1613         // added after LID_CHAINED, so is higher up in the hierarchy, but
1614         // it is loaded as part of the recursion.  To support that, a
1615         // recursive call with certdatum.size==0 is possible when the
1616         // LID_NEEDS_CHAIN flag is set, and this section then skips.
1617         // Note that this code is also used to load the certificate chain
1618         // provided by LID_NEEDS_CHAIN, but by then the flag in a recursive
1619         // call is replaced with LID_CHAINED and no more LID_NEEDS_CHAIN.
1620         if (((flags & LID_CHAINED) != 0) && (certdatum->size > 0)) {
1621                 long certlen;
1622                 int lenlen;
1623                 gnutls_datum_t nextdatum;
1624                 long nextlen;
1625                 // Note: Accept BER because the outside SEQUENCE is not signed
1626                 certlen = asn1_get_length_ber (
1627                         ((char *) certdatum->data) + 1,
1628                         certdatum->size,
1629                         &lenlen);
1630                 certlen += 1 + lenlen;
1631                 tlog (TLOG_CERT, LOG_DEBUG, "Found LID_CHAINED certificate size %d", certlen);
1632                 if (certlen > certdatum->size) {
1633                         tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate beyond data size %d", certdatum->size);
1634                         *chainlen = 0;
1635                         return NULL;
1636                 } else if (certlen <= 0) {
1637                         tlog (TLOG_CERT, LOG_ERR, "Refusing LID_CHAINED certificate of too-modest data size %d", certlen);
1638                         *chainlen = 0;
1639                         return NULL;
1640                 }
1641                 nextdatum.data = ((char *) certdatum->data) + certlen;
1642                 nextdatum.size =           certdatum->size  - certlen;
1643                 certdatum->size = certlen;
1644                 nextlen = asn1_get_length_ber (
1645                         ((char *) nextdatum.data) + 1,
1646                         nextdatum.size,
1647                         &lenlen);
1648                 nextlen += 1 + lenlen;
1649                 if (nextlen == nextdatum.size) {
1650                         // The last cert is loaded thinking it is not CHAINED,
1651                         // but NEEDS_CHAIN can still be present for expansion.
1652                         flags &= ~LID_CHAINED;
1653                 }
1654                 (*chainlen)++;
1655                 chain = load_certificate_chain (flags, chainlen, &nextdatum);
1656                 if (chain != NULL) {
1657                         E_g2e ("Failed to add chained certificate",
1658                                 load_certificate (
1659                                         flags & LID_TYPE_MASK,
1660                                         &chain [mypos],
1661                                         certdatum));
1662                         if (gtls_errno != GNUTLS_E_SUCCESS) {
1663                                 free (chain);
1664                                 chain = NULL;
1665                                 *chainlen = 0;
1666                         }
1667                 }
1668                 return chain;
1669         }
1670
1671         //
1672         // Second extended case.  Chain certs in response to LID_NEEDS_CHAIN.
1673         // These are the highest-up in the hierarchy, above any LID_CHAINED
1674         // certificates.  The procedure for adding them is looking them up
1675         // in a central database by their authority key identifier.  What is
1676         // found is assumed to be a chain, and will be unrolled by replacing
1677         // the LID_NEEDS_CHAIN flag with LID_CHAINED and calling recursively.
1678         if (((flags & LID_NEEDS_CHAIN) != 0) && (certdatum->size == 0)) {
1679                 //TODO//CODE// lookup new certdatum
1680                 flags &= ~LID_NEEDS_CHAIN;
1681                 flags |=  LID_CHAINED;
1682                 //TODO//CODE// recursive call
1683                 //TODO//CODE// no structures to fill here
1684                 //TODO//CODE// cleanup new certdatum
1685         }
1686
1687         //
1688         // Final judgement.  Nothing worked.  Return failure.
1689         *chainlen = 0;
1690         return NULL;
1691 }
1692
1693
1694
1695 /********** KERBEROS SUPPORT FUNCTIONS FOR TLS-KDH **********/
1696
1697
1698
1699 /* Prepare the Kerberos resources for use by clients and/or servers.
1700  */
1701 #ifdef HAVE_TLS_KDH
1702 static int setup_starttls_kerberos (void) {
1703         int k5err = 0;
1704         char *cfg;
1705         int retval = GNUTLS_E_SUCCESS;
1706         krb5_ccache krb_cc_tmp;
1707         const char *cctype_cli = NULL;
1708         const char *cctype_srv = NULL;
1709         //
1710         // Initialise
1711         krbctx_cli = krbctx_srv = NULL;
1712         krb_kt_cli = krb_kt_srv = NULL;
1713         got_cc_cli = got_cc_srv = 0;
1714         //
1715         // Construct credentials caching for Kerberos
1716         if (k5err == 0) {
1717                 k5err = krb5_init_context (&krbctx_cli);
1718         }
1719         if (k5err == 0) {
1720                 k5err = krb5_init_context (&krbctx_srv);
1721         }
1722         //
1723         // Load the various configuration variables
1724         cfg = cfg_krb_client_keytab ();
1725         if ((k5err == 0) && (cfg != NULL)) {
1726                 k5err = krb5_kt_resolve (krbctx_cli, cfg, &krb_kt_cli);
1727         }
1728         cfg = cfg_krb_server_keytab ();
1729         if ((k5err == 0) && (cfg != NULL)) {
1730                 k5err = krb5_kt_resolve (krbctx_srv, cfg, &krb_kt_srv);
1731         }
1732         cfg = cfg_krb_client_credcache ();
1733 #if 0  /* Temporary bypass of cctype checks */
1734         if ((k5err == 0) && (cfg != NULL)) {
1735                 k5err = krb5_cc_set_default_name (krbctx_cli, cfg);
1736                 if (k5err == 0) {
1737                         k5err = krb5_cc_default (krbctx_cli, &krb_cc_tmp);
1738                 }
1739                 if (k5err == 0) {
1740                         got_cc_cli = 1;
1741                         cctype_cli = krb5_cc_get_type (krbctx_cli, krb_cc_tmp);
1742                         krb5_cc_close (krbctx_cli, krb_cc_tmp);
1743                 }
1744         }
1745 #endif
1746         cfg = cfg_krb_server_credcache ();
1747 #if 0  /* Temporary bypass of cctype checks */
1748         if ((k5err == 0) && (cfg != NULL)) {
1749                 k5err = krb5_cc_set_default_name (krbctx_srv, cfg);
1750                 if (k5err == 0) {
1751                         k5err = krb5_cc_default (krbctx_srv, &krb_cc_tmp);
1752                 }
1753                 if (k5err == 0) {
1754                         got_cc_srv = 1;
1755                         cctype_srv = krb5_cc_get_type (krbctx_cli, krb_cc_tmp);
1756                         krb5_cc_close (krbctx_srv, krb_cc_tmp);
1757                 }
1758         }
1759 #endif
1760         //
1761         // Check for consistency and log helpful messages for the sysop
1762         if (k5err != 0) {
1763                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Error during STARTTLS setup: %s (acting on %s)",
1764                                 krb5_get_error_message (krbctx_cli, k5err),
1765                                 cfg);
1766                 retval = GNUTLS_E_UNWANTED_ALGORITHM;
1767         }
1768         if (krb_kt_cli != NULL) {
1769                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_WARNING, "Ignoring the configured kerberos_client_keytab -- it is not implemented yet");
1770         }
1771         if (krb_kt_srv == NULL) {
1772                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "No kerberos_server_keytab configured, so Kerberos cannot work at all");
1773                 retval = GNUTLS_E_UNWANTED_ALGORITHM;
1774 /* TODO: Only for MIT krb5 1.11 and up
1775         } else if (0 == krb5_kt_have_content (krb_ctx, krb_kt_srv)) {
1776                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Keytab in kerberos_server_keytab is absent or empty");
1777                 retval = GNUTLS_E_UNWANTED_ALGORITHM;
1778  */
1779         }
1780         if (krbctx_cli == NULL) {
1781                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "No kerberos_client_credcache configured, so Kerberos cannot work at all");
1782                 retval = GNUTLS_E_UNWANTED_ALGORITHM;
1783 #if 0  /* Temporary bypass of cctype checks */
1784         } else if (!krb5_cc_support_switch (
1785                         krbctx_cli, cctype_cli)) {
1786                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Your kerberos_client_credcache does not support multilpe identities");
1787                 retval = GNUTLS_E_UNWANTED_ALGORITHM;
1788 #endif
1789         }
1790         if (krbctx_srv == NULL) {
1791                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_WARNING, "No kerberos_server_credcache configured, so user-to-user Kerberos will not work");
1792 #if 0  /* Temporary bypass of cctype checks */
1793         } else if (!krb5_cc_support_switch (
1794                         krbctx_srv, cctype_srv)) {
1795                 tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Your kerberos_server_credcache does not support multilpe identities");
1796                 retval = GNUTLS_E_UNWANTED_ALGORITHM;
1797 #endif
1798         }
1799         if (retval != GNUTLS_E_SUCCESS) {
1800                 cleanup_starttls_kerberos ();
1801         }
1802         return retval;
1803 }
1804 #endif
1805
1806
1807 /* Cleanup Kerberos resources.  This must be an idempotent function, because
1808  * it is called when Kerberos panics as well as when 
1809  */
1810 #ifdef HAVE_TLS_KDH
1811 static void cleanup_starttls_kerberos (void) {
1812         if (krb_kt_srv != NULL) {
1813                 krb5_kt_close (krbctx_srv, krb_kt_srv);
1814                 krb_kt_srv = NULL;
1815         }
1816         if (krb_kt_cli != NULL) {
1817                 krb5_kt_close (krbctx_cli, krb_kt_cli);
1818                 krb_kt_cli = NULL;
1819         }
1820         if (krbctx_srv != NULL) {
1821                 krb5_free_context (krbctx_srv);
1822                 krbctx_srv = NULL;
1823         }
1824         if (krbctx_cli != NULL) {
1825                 krb5_free_context (krbctx_cli);
1826                 krbctx_cli = NULL;
1827         }
1828 }
1829 #endif
1830
1831
1832 /* Prompter callback function for PKCS #11.
1833  *
1834  * TODO: Use "struct pkcs11iter" as data, possibly interact with the user,
1835  * and keep a score on where we stand with password entry and changes.
1836  * Create clisrv_p11krb_setup() and clisrv_p11krb_cleanup() functions.
1837  *
1838  * In the current release for Kerberos, we have a very minimal mode for
1839  * doing this.  We may embellish it later or, preferrably, turn to a more
1840  * PKCS #11 styled approach, perhaps PKINIT or FAST.
1841  */
1842 #ifdef HAVE_TLS_KDH
1843 static krb5_error_code clisrv_p11krb_callback (krb5_context ctx,
1844                                         void *vcmd,
1845                                         const char *name,
1846                                         const char *banner,
1847                                         int num_prompts,
1848                                         krb5_prompt prompts []) {
1849         struct command *cmd = (struct command *) vcmd;
1850         int i;
1851         krb5_prompt_type *codes = krb5_get_prompt_types (ctx);
1852         int attempt = 0;
1853         static const char *token_url = "pkcs11:manufacturer=Kerberos+infrastructure;model=TLS+Pool;serial=%28none%29";
1854         static const char *token_label = "Kerberos infrastructure";
1855         for (i=0; i<num_prompts; i++) {
1856                 //
1857                 // Visit each prompt in turn, setting responses or return failure
1858                 switch (codes [i]) {
1859                 case KRB5_PROMPT_TYPE_PASSWORD:
1860                         //TODO// Read a password from PKCS #11
1861                         //TODO// Do we need to cycle passwords to cover retry?
1862                         //TODO// Delete any failed passwords?
1863                         //TODO:FIXED//
1864                         if (attempt >= MAX_P11ITER_ATTEMPTS) {
1865                                 return KRB5_LIBOS_CANTREADPWD;
1866                         }
1867                         // Nothing in PKCS #11 --> so fallback on manual entry
1868                         if (!pin_callback (attempt,
1869                                         token_url, "Enter Kerberos password:",
1870                                         prompts [i].reply->data,
1871                                         prompts [i].reply->length)) {
1872                                 memset (prompts [i].reply->data, 0, prompts [i].reply->length);
1873                                 return KRB5_LIBOS_CANTREADPWD;
1874                         }
1875                         //TODO// Manage data structure
1876                         prompts [i].reply->length = strlen (prompts [i].reply->data);
1877                         return 0;
1878                 case KRB5_PROMPT_TYPE_NEW_PASSWORD:
1879                 case KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:
1880                         //TODO// Setup new password in PKCS #11
1881                 case KRB5_PROMPT_TYPE_PREAUTH:
1882                         //TODO// Use FAST, PKINIT, and so on...
1883                 default:
1884                         // Unrecognised and unimplemented prompt types end here
1885                         return KRB5_LIBOS_CANTREADPWD;
1886                 }
1887         }
1888         return 0;
1889 }
1890 #endif
1891
1892
1893 /* Find a Kerberos keyblock and ticket to use for the localid.  Do not look
1894  * into services yet in this function.  This function implements a simple
1895  * procedure, based on optional arguments p11uri, keytab, credcache.  It
1896  * produces <key,tgt> or <key,NULL> or (for errors) <NULL,NULL>.
1897  *
1898  * The procedure followed, fully written out, is outlined below:
1899  *
1900  *      IF      have(credcache) AND acceptable (renewable) time
1901  *      THEN    RETURN <key,tgt>
1902  *      ELSE    IF have (keytab) AND found a suitable key
1903  *              THEN    IF have(credcache) and it works
1904  *                      THEN    fetch cred tgt and key (auth with key in keytab)
1905  *                              create credcache
1906  *                              RETURN <key,tgt>
1907  *                      ELSE    RETURN <key,NULL>
1908  *              ELSE    IF have(p11uri) AND it works
1909  *                      THEN    fetch cred tgt and key (auth with pwd in p11uri)
1910  *                              create credcache
1911  *                              RETURN <key,tgt>
1912  *                      ELSE    RETURN <NULL,NULL>
1913  *
1914  * The function returns a status value counting the number of values returned,
1915  * so 0 means error, 1 means key only and 2 means key and tgt.
1916  */
1917 #ifdef HAVE_TLS_KDH
1918 static int have_key_tgt_cc (struct command *cmd,             // in, session context
1919                                 krb5_context ctx,    // in, kerberos context
1920                                 bool use_cc,         // in, whether to use cc
1921                                 krb5_kvno kvno,      // in, kvno (0 for highest)
1922                                 krb5_enctype enctype,// in, enctype (0 for any)
1923                                 char *p11uri,        // in/opt, PKCS #11 pwd URI
1924                                 krb5_keytab kt,      // in/opt, keytab
1925                                 krb5_keyblock *key,  // opt/opt session key
1926                                 krb5_creds **tgt,    // out/opt, tkt granting tkt
1927                                 krb5_ccache *cc) {   // out/opt, cred cache
1928         int k5err = 0;
1929         krb5_ccache newcc = NULL;
1930         krb5_principal sought  = NULL;
1931         krb5_principal sought1 = NULL;
1932         krb5_principal tgtname = NULL;
1933         krb5_keytab_entry ktentry;
1934         const char *svc = cmd->cmd.pio_data.pioc_starttls.service;
1935         const char *lid = cmd->cmd.pio_data.pioc_starttls.localid;
1936         const char *liddom;
1937         int lid1len;
1938         char **realms;
1939         char realm [128];
1940         uint32_t nametype, nametype_alt;
1941         time_t now = 0;
1942         //
1943         // Assertions, and initialise variables
1944         assert ( cmd != NULL);
1945         assert ( ctx != NULL);
1946         assert ( key != NULL);
1947         assert (*tgt == NULL);
1948         krb5_free_keyblock_contents (ctx, key);
1949         if (cc != NULL) {
1950                 *cc = NULL;
1951         }
1952         //
1953         // Construct the realm name
1954         liddom = strrchr (lid, '@');
1955         if (liddom != NULL) {
1956                 lid1len = ((intptr_t) liddom) - ((intptr_t) lid);
1957                 liddom++;  // Skip '@'
1958         } else {
1959                 liddom = lid;  // localid is a host
1960                 lid1len = strnlen (lid, 128);
1961         }
1962         k5err = krb5_get_host_realm (ctx, liddom, &realms);
1963         if ((k5err == 0) && (realms [0] != NULL) && (*realms [0] != '\0')) {
1964                 strncpy (realm, realms [0], sizeof (realm));
1965                 realm [sizeof (realm)-1] = '\0';
1966         } else {
1967                 int i = 0;
1968                 do {
1969                         realm [i] = toupper (liddom [i]);
1970                         i++;
1971                 } while (liddom [i-1] != '\0');
1972         }
1973         if (k5err == 0) {
1974                 krb5_free_host_realm (ctx, realms);
1975         } else {
1976                 k5err = 0;
1977         }
1978         //
1979         // Construct a sought principal name in a given naming style,
1980         // and try to locate it in the existing cache.
1981         // With @, try liduser@liddom@REALM or else liduser@REALM
1982         // Without @, try svc/liddom@REALM
1983         nametype = (lid == liddom) ? KRB5_NT_SRV_HST : KRB5_NT_ENTERPRISE_PRINCIPAL;
1984 retry:
1985         nametype_alt = nametype;
1986         switch (nametype) {
1987         case KRB5_NT_ENTERPRISE_PRINCIPAL:
1988                 nametype_alt = KRB5_NT_PRINCIPAL;
1989                 k5err = krb5_build_principal_ext (ctx, &sought,
1990                                         strlen (realm), realm,
1991                                         strnlen (lid, 128), lid,
1992                                         0);
1993                 break;
1994         case KRB5_NT_SRV_HST:
1995                 if (strcmp (svc, "http") == 0) {
1996                         svc = "HTTP";
1997                 }
1998                 k5err = krb5_build_principal_ext (ctx, &sought,
1999                                         strlen (realm), realm,
2000                                         strlen (svc), svc,
2001                                         lid1len, lid,
2002                                         0);
2003                 break;
2004         case KRB5_NT_PRINCIPAL:
2005                 k5err = krb5_build_principal_ext (ctx, &sought,
2006                                         strlen (realm), realm,
2007                                         lid1len, lid,
2008                                         0);
2009                 break;
2010         }
2011         if (k5err == 0) {
2012                 sought->type = nametype;
2013         } else {
2014                 sought = NULL;
2015         }
2016         k5err = krb5_cc_cache_match (ctx, sought, &newcc);
2017         if (k5err != 0) {
2018                 if ((nametype_alt != nametype) && (sought1 == NULL)) {
2019                         nametype = nametype_alt;
2020                         sought1  = sought;
2021                         sought   = NULL;
2022                         goto retry;
2023                 }
2024                 //
2025                 // We failed to find an *existing* credentials cache
2026                 // for the local identity.
2027                 //
2028                 // Our new hope is to create a fresh credential, and add
2029                 // it to the current credcache.  To that end, we now try
2030                 // to overrule k5err by getting hold of our default cc.
2031                 goto from_scratch;
2032         }
2033         //
2034         // Construct the TGT name
2035         k5err = krb5_build_principal_ext (ctx, &tgtname,
2036                                 strlen (realm), realm,
2037                                 6, "krbtgt",
2038                                 strlen (realm), realm,
2039                                 0);
2040         if (k5err != 0) {
2041                 tgtname = NULL;
2042                 k5err = 0;
2043         }
2044         tgtname->type = KRB5_NT_SRV_INST;
2045         //
2046         // Try to get the service ticket for the TGT name from the cache
2047         krb5_creds credreq;
2048         memset (&credreq, 0, sizeof (credreq));
2049         credreq.client = sought;
2050         credreq.server = tgtname;
2051         k5err = krb5_get_credentials (ctx,
2052                                 /* KRB5_GC_USER_USER ?|? */
2053                                         ( use_cc ? 0 : KRB5_GC_CACHED ),
2054                                 newcc,
2055                                 &credreq, tgt);
2056         time (&now);
2057         if ((k5err == 0)
2058                                 && (now + 300 > (*tgt)->times.endtime)
2059                                 && (now + 300 < (*tgt)->times.renew_till)) {
2060                 //TODO:NOTHERE// krb5_free_creds (ctx, *tgt);
2061                 //TODO:NOTHERE// *tgt = NULL;
2062                 // Try to renew the ticket
2063                 k5err = krb5_get_renewed_creds (ctx,
2064                                 *tgt,
2065                                 sought,
2066                                 newcc,
2067                                 NULL);   /* krbtgt/REALM@REALM */
2068         }
2069         if ((k5err == 0)
2070                                 && (now + 300 > (*tgt)->times.endtime)) {
2071                 // Thanks, but no thanks!
2072                 krb5_free_creds (ctx, *tgt);
2073                 *tgt = NULL;
2074                 k5err = 666;
2075         }
2076         if (k5err == 0) {
2077                 // First case worked -- return <key,tgt> from credout
2078                 k5err = krb5_copy_keyblock_contents (ctx,
2079                                 &(*tgt)->keyblock,
2080                                 key);
2081                 // On failure, key shows failure
2082                 if (cc != NULL) {
2083                         *cc = newcc;
2084                         newcc = NULL;
2085                 }
2086                 goto cleanup;
2087         }
2088 from_scratch:
2089         //
2090         // Prior attempts failed.  Instead, look for keytab or p11uri presence.
2091         // This is skipped when the use_cc option below welcomes krb5_creds.
2092         if ((key->contents == NULL) && (p11uri == NULL) && (kt == NULL)) {
2093                 // We cannot obtain a new krbtgt
2094                 // We simply return what we've got (which may be nothing)
2095                 goto cleanup;
2096         }
2097         if ((kt == NULL) && (!use_cc)) {
2098                 // We have nowhere to store a new krbtgt if we got it
2099                 // We simply return what we've got (which is at least a key)
2100                 goto cleanup;
2101         }
2102         //
2103         // Either we have a keytab key, or we have a p11uri,
2104         // so we can attempt to create a new credcache with a new krbtgt
2105         if (use_cc) {
2106                 if (newcc == NULL) {
2107                         k5err = krb5_cc_default (ctx, &newcc);
2108                         if (k5err != 0) {
2109                                 // Utter failure to do even the simplest thing
2110                                 goto cleanup;
2111                         }
2112                 }
2113                 *tgt = malloc (sizeof (**tgt));
2114                 if (*tgt == NULL) {
2115                         // Memory error
2116                         goto cleanup;
2117                 }
2118                 memset (*tgt, 0, sizeof (**tgt));
2119                 if ((sought != NULL) && (sought1 == NULL)) {
2120                         // We only tried one name
2121                         sought1 = sought;
2122                         sought = NULL;
2123                 }
2124                 do {
2125                         if (sought1 == NULL) {
2126                                 break;
2127                         }
2128                         if (p11uri == NULL) {
2129                                 k5err = krb5_get_init_creds_keytab (
2130                                                 ctx,
2131                                                 *tgt,
2132                                                 sought1,
2133                                                 kt,
2134                                                 0,    /* start now please */
2135                                                 NULL, /* get a TGT please */
2136                                                 NULL);  //TODO// opts needed?
2137                         } else {
2138                                 //TODO// Prepare PKCS #11 access
2139                                 k5err = krb5_get_init_creds_password (
2140                                                 ctx,
2141                                                 *tgt,
2142                                                 sought1,
2143 #ifdef TOM_IS_WEG
2144                                                 NULL,   // Use callbacks for password
2145                                                 clisrv_p11krb_callback,
2146 #else
2147                                                 "1234",
2148                                                 NULL,
2149 #endif
2150                                                 cmd,  /* callback data pointer */
2151                                                 0,    /* start now please */
2152                                                 NULL, /* get a TGT please */
2153                                                 NULL);  //TODO// opts needed?
2154                                 //TODO// End PKCS #11 access
2155                         }
2156                         krb5_free_principal (ctx, sought1);
2157                         sought1 = sought;
2158                         sought = NULL;
2159                 } while (k5err != 0);
2160                 if (k5err != 0) {
2161                         // Failed to initiate new credentials
2162                         krb5_free_creds (ctx, *tgt);
2163                         *tgt = NULL;
2164                         goto cleanup;
2165                 }
2166                 // Try to store the credential, if it was found
2167                 if (sought1 != NULL) {
2168                         k5err = krb5_cc_initialize (ctx, newcc, sought1);
2169                         if (k5err == 0) {
2170                                 k5err = krb5_cc_store_cred (ctx, newcc, *tgt);
2171                         }
2172                 }
2173                 // Copy the keyblock; any failure will show up in key
2174                 krb5_copy_keyblock_contents (ctx,
2175                         &(*tgt)->keyblock, //TODO:UNINIT// &ktentry.key,
2176                         key);
2177                 //
2178                 // We succeeded in setting up a new Ticket Granting Ticket!
2179                 if (cc != NULL) {
2180                         *cc = newcc;
2181                         newcc = NULL;
2182                 }
2183                 goto cleanup;
2184         }
2185         //
2186         // As a last resort, dig up a key directly from the keytab;
2187         // this is the only place where kvno and enctype are used
2188         if (kt != NULL) {
2189                 //NOTE// Might be more direct as krb5_kt_read_service_key()
2190                 k5err = krb5_kt_get_entry (
2191                                         ctx, kt,
2192                                         sought,
2193                                         kvno, enctype,
2194                                         &ktentry);
2195                 if (k5err == 0) {
2196                         k5err = krb5_copy_keyblock_contents (ctx,
2197                                 &ktentry.key,
2198                                 key);
2199                         krb5_free_keytab_entry_contents (ctx, &ktentry);
2200                         // On failure, key shows failure.
2201                         if (cc != NULL) {
2202                                 *cc = newcc;
2203                                 newcc = NULL;
2204                         }
2205                         goto cleanup;
2206                 }
2207         }
2208         //
2209         // Nothing more to try, so we continue into cleanup
2210 cleanup:
2211         //
2212         // Cleanup and return the <key,tgt> values as they were delivered
2213         if (sought1 != NULL) {
2214                 krb5_free_principal (ctx, sought1);
2215                 sought1 = NULL;
2216         }
2217         if (sought != NULL) {
2218                 krb5_free_principal (ctx, sought);
2219                 sought = NULL;
2220         }
2221         if (tgtname != NULL) {
2222                 krb5_free_principal (ctx, tgtname);
2223                 tgtname = NULL;
2224         }
2225         if (newcc != NULL) {
2226                 krb5_cc_close (ctx, newcc);
2227                 newcc = NULL;
2228         }
2229         if (key->contents == NULL) {
2230                 if (k5err != 0) {
2231                         const char *errmsg = krb5_get_error_message (ctx, k5err);
2232                         tlog (TLOG_DAEMON, LOG_ERR, "Kerberos error in have_key_tgt_cc: %s", errmsg);
2233                         krb5_free_error_message (ctx, errmsg);
2234                 }
2235                 if (*tgt != NULL) {
2236                         krb5_free_creds (ctx, *tgt);
2237                         *tgt = NULL;
2238                 }
2239                 if ((cc != NULL) && (*cc != NULL)) {
2240                         krb5_cc_close (ctx, *cc);
2241                         *cc = NULL;
2242                 }
2243                 return 0;
2244         } else if (tgt == NULL) {
2245                 if ((cc != NULL) && (*cc != NULL)) {
2246                         krb5_cc_close (ctx, *cc);
2247                         *cc = NULL;
2248                 }
2249                 return 1;
2250         } else if ((cc == NULL) || (*cc == NULL)) {
2251                 return 2;
2252         } else {
2253                 return 3;
2254         }
2255 }
2256 #endif
2257
2258
2259 /* Have a ticket for the remote service.  Do this as a client.  The client
2260  * principal and realm are provided, and the ticket to be returned will
2261  * also provide the accompanying key.
2262  *
2263  * This function will incorporate the peer TGT, when it is provided.  This
2264  * is the case in KDH-Only exchanges with a non-empty Server Certificate.
2265  *
2266  * TODO: We are not currently serving backend tickets, but these could be
2267  * passed in as authorization data along with the credential request.
2268  * Note however, that authorization data is copied by default from the TGT,
2269  * but not necessarily from the request.  Not without KDC modifications.
2270  * But then again, the KDC should have responded with an error that it was
2271  * missing backend services; this is not something the client should decide
2272  * on, and certainly not after being requested by the service.  The error
2273  * and recovery could be implemented here (if we can get the error info out
2274  * of the libkrb5 API).  Alternatively, we might consider passing the
2275  * authorization data in the authenticator since we get to control it.
2276  * What will the specification say?
2277  *
2278  * The return value indicates how many of the requested output values have
2279  * been provided, counting from the first.  So, 0 means a total failure and
2280  * anything higher is a (partial) success.
2281  */
2282 #ifdef HAVE_TLS_KDH
2283 static int have_service_ticket (
2284                                 struct command *cmd,  // in, session context
2285                                 krb5_context ctx,     // in, kerberos context
2286                                 krb5_ccache cc_opt,   // in/opt, credcache
2287                                 krb5_principal cli,   // in, client principal
2288                                 krb5_creds **ticket) {// out, tkt granting tkt
2289         int k5err = 0;
2290         krb5_ccache cc = cc_opt;
2291         krb5_flags u2u = 0;
2292         krb5_principal srv = NULL;
2293         krb5_data tkt_srv;
2294         krb5_creds credreq;
2295         //
2296         // Sanity checks and initialisation
2297         memset (&tkt_srv, 0, sizeof (tkt_srv));
2298         memset (&credreq, 0, sizeof (credreq));
2299         *ticket = NULL;
2300         //
2301         // Determine the optional cc parameter if it was not provided
2302         //TODO// This can go if we always get it passed from have_key_tgt_cc()
2303         if (cc == NULL) {
2304                 k5err = krb5_cc_cache_match (ctx, cli, &cc);
2305                 if (k5err != 0) {
2306                         goto cleanup;
2307                 }
2308         }
2309         //
2310         // Build the server's principal name
2311         const char *svc = cmd->cmd.pio_data.pioc_starttls.service;
2312         const char *rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
2313         const char *riddom;
2314         char **realms;
2315         char realm [128];
2316         riddom = strrchr (rid, '@');
2317         if (riddom != NULL) {
2318                 riddom++;  // Skip '@'
2319         } else {
2320                 riddom = rid;  // localid is a host
2321         }
2322         k5err = krb5_get_host_realm (ctx, riddom, &realms);
2323         if ((k5err == 0) && (realms [0] != NULL) && (*realms [0] != '\0')) {
2324                 strncpy (realm, realms [0], sizeof (realm));
2325                 realm [sizeof (realm)-1] = '\0';
2326         } else {
2327                 int i = 0;
2328                 do {
2329                         realm [i] = toupper (riddom [i]);
2330                         i++;
2331                 } while (riddom [i-1] != '\0');
2332         }
2333         if (k5err == 0) {
2334                 krb5_free_host_realm (ctx, realms);
2335         } else {
2336                 k5err = 0;
2337         }
2338         if (strcmp (svc, "http") == 0) {
2339                 svc = "HTTP";
2340         }
2341         k5err = krb5_build_principal_ext (ctx, &srv,
2342                                 strlen (realm), realm,
2343                                 strlen (svc), svc,
2344                                 strlen (rid), rid,
2345                                 0);
2346         if (k5err != 0) {
2347                 goto cleanup;
2348         }
2349         srv->type = KRB5_NT_SRV_HST;
2350         //
2351         // Construct credential request
2352         credreq.client = cli;
2353         credreq.server = srv;
2354         //TODO// credreq.authdata may be used for backend service tickets
2355         //
2356         // See if our peer provided us with a TGT
2357         //  - we are sure of GNUTLS_CRD_CERTIFICATE because we implement it now
2358         //  - we must ensure that this is KDH-Only (remote GNUTLS_CRT_KRB)
2359         //  - we must ensure that the remote provided a non-empty ticket
2360         if (gnutls_certificate_type_get_peers (cmd->session) == GNUTLS_CRT_KRB) {
2361                 // This is KDH-Only -- and the server may present a TGT
2362                 const gnutls_datum_t *opt_srv_tkt;
2363                 unsigned int srv_tkt_count;
2364                 opt_srv_tkt = gnutls_certificate_get_peers (cmd->session, &srv_tkt_count);
2365                 if ((opt_srv_tkt != NULL) && (srv_tkt_count >= 1) && (opt_srv_tkt [0].size > 5)) {
2366                         // Looks good, we'll use only the first (normally only) one
2367                         credreq.second_ticket.data   = opt_srv_tkt [0].data;
2368                         credreq.second_ticket.length = opt_srv_tkt [0].size;
2369                         u2u = KRB5_GC_USER_USER;
2370                 }
2371         }
2372         //
2373         // Fetch the ticket for the service
2374         k5err = krb5_get_credentials (ctx, u2u, cc, &credreq, ticket);
2375         //
2376         // Cleanup and return; the return value depends on k5err
2377 cleanup:
2378         if ((cc != NULL) && (cc_opt == NULL)) {
2379                 //TODO// This can go if we always get it passed from have_key_tgt_cc()
2380                 krb5_cc_close (ctx, cc);
2381                 cc = NULL;
2382         }
2383         if (srv != NULL) {
2384                 krb5_free_principal (ctx, srv);
2385         }
2386         return (k5err == 0) ? 1 : 0;
2387 }
2388 #endif
2389
2390
2391 /* DER utility: This should probably appear in Quick DER sometime soon.
2392  *
2393  * Pack an Int32 or UInt32 and return the number of bytes.  Do not pack a header
2394  * around it.  The function returns the number of bytes taken, even 0 is valid.
2395  */
2396 typedef uint8_t QDERBUF_INT32_T [4];
2397 dercursor qder2b_pack_int32 (uint8_t *target_4b, int32_t value) {
2398         dercursor retval;
2399         int shift = 24;
2400         retval.derptr = target_4b;
2401         retval.derlen = 0;
2402         while (shift >= 0) {
2403                 if ((retval.derlen == 0) && (shift > 0)) {
2404                         // Skip sign-extending initial bytes
2405                         uint32_t neutro = (value >> (shift - 1) ) & 0x000001ff;
2406                         if ((neutro == 0x000001ff) || (neutro == 0x00000000)) {
2407                                 shift -= 8;
2408                                 continue;
2409                         }
2410                 }
2411                 target_4b [retval.derlen] = (value >> shift) & 0xff;
2412                 retval.derlen++;
2413                 shift -= 8;
2414         }
2415         return retval;
2416 }
2417 typedef uint8_t QDERBUF_UINT32_T [5];
2418 dercursor qder2b_pack_uint32 (uint8_t *target_5b, uint32_t value) {
2419         dercursor retval;
2420         int ofs = 0;
2421         if (value & 0x80000000) {
2422                 *target_5b = 0x00;
2423                 ofs = 1;
2424         }
2425         retval = qder2b_pack_int32 (target_5b + ofs, (int32_t) value);
2426         retval.derptr -= ofs;
2427         retval.derlen += ofs;
2428         return retval;
2429 }
2430
2431
2432 /* DER utility: This should probably appear in Quick DER sometime soon.
2433  *
2434  * Unpack an Int32 or UInt32 from a given number of bytes.  Do not assume a header
2435  * around it.  The function returns the value found.
2436  *
2437  * Out of range values are returned as 0.  This value only indicates invalid
2438  * return when len > 1, so check for that.
2439  */
2440 int32_t qder2b_unpack_int32 (dercursor data4) {
2441         int32_t retval = 0;
2442         int idx;
2443         if (data4.derlen > 4) {
2444                 goto done;
2445         }
2446         if ((data4.derlen > 0) && (0x80 & *data4.derptr)) {
2447                 retval = -1;
2448         }
2449         for (idx=0; idx<data4.derlen; idx++) {
2450                 retval <<= 8;
2451                 retval += data4.derptr [idx];
2452         }
2453 done:
2454         return retval;
2455 }
2456 uint32_t qder2b_unpack_uint32 (dercursor data5) {
2457         uint32_t retval = 0;
2458         int ofs = 0;
2459         if (data5.derlen > 5) {
2460                 goto done;
2461         }
2462         if (data5.derlen == 5) {
2463                 if (*data5.derptr != 0x00) {
2464                         goto done;
2465                 }
2466                 // Modify the local copy on our stack
2467                 data5.derlen--;
2468                 data5.derptr++;
2469         }
2470         retval = (uint32_t) qder2b_unpack_int32 (data5);
2471 done:
2472         return retval;
2473 }
2474
2475
2476 #ifdef HAVE_TLS_KDH
2477 /* TODO: Debugging function for printing (descr,ptr,len) ranges */
2478 static inline void prange (char *descr, uint8_t *ptr, int len) {
2479         fprintf (stderr, "%s #%04d: %02x %02x %02x %02x %02x %02x %02x %02x...%02x %02x %02x %02x\n",
2480                         descr, len,
2481                         ptr [0], ptr [1], ptr [2], ptr [3],
2482                         ptr [4], ptr [5], ptr [6], ptr [7],
2483                         ptr [len-4], ptr [len-3], ptr [len-2], ptr [len-1]);
2484 }
2485 static inline void prangefull (char *descr, uint8_t *ptr, int len) {
2486         fprintf (stderr, "%s #%04d:", descr, len);
2487         while (len-- > 0) {
2488                 fprintf (stderr, " %02x", *ptr++);
2489         }
2490         fprintf (stderr, "\n");
2491 }
2492 #endif
2493
2494
2495 /* The callback function that retrieves a TLS-KDH "signature", which is kept
2496  * outside of GnuTLS.  The callback computes an authenticator encrypted to
2497  * the session's Kerberos key.
2498  */
2499 #ifdef HAVE_TLS_KDH
2500 static gtls_error cli_kdhsig_encode (gnutls_session_t session,
2501                         gnutls_datum_t *enc_authenticator,
2502                         gnutls_datum_t *dec_authenticator,
2503                         const gnutls_datum_t *hash,
2504                         int32_t checksum_type) {
2505         //
2506         // Variables, sanity checking, initialisation
2507         struct command *cmd;
2508         int k5err = 0;
2509         authenticator_t auth;
2510         QDERBUF_INT32_T derv5;
2511         QDERBUF_INT32_T dernametype;
2512         QDERBUF_INT32_T dercksumtype;
2513         krb5_keyblock subkey;
2514         gnutls_certificate_type_t peercert;
2515         QDERBUF_INT32_T dersubkey;
2516         krb5_timestamp now_s;
2517         char derctime [100];
2518         krb5_int32 now_us;
2519         QDERBUF_INT32_T dercusec;
2520         cmd = (struct command *) gnutls_session_get_ptr (session);
2521         memset (&auth, 0, sizeof (auth));
2522         memset (&subkey, 0, sizeof (subkey));
2523         assert (cmd->krbid_cli != NULL);
2524         assert (cmd->krb_key.contents != NULL);
2525         static const uint8_t auth_packer [] = {
2526                         DER_PACK_rfc4120_Authenticator, DER_PACK_END };
2527         static const uint8_t encdata_packer [] = {
2528                         DER_PACK_rfc4120_EncryptedData, DER_PACK_END };
2529         //
2530         // Setup secure hash in authenticator (never optional for TLS-KDH)
2531         auth.cksum.cksumtype = qder2b_pack_int32 (dercksumtype, checksum_type);
2532         auth.cksum.checksum.derptr = hash->data;
2533         auth.cksum.checksum.derlen = hash->size;
2534         //
2535         // Optionally include a subkey (namely, for KDH-Only)
2536         peercert = gnutls_certificate_type_get_peers (session);
2537         if (peercert == GNUTLS_CRT_KRB) {
2538                 // This is KDH-Only, for which we MUST create a random subkey
2539                 k5err = krb5_c_make_random_key (
2540                                 krbctx_cli,
2541                                 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
2542                                 &subkey);
2543                 if (k5err != 0) {
2544                         return GNUTLS_E_ENCRYPTION_FAILED;
2545                 }
2546                 auth.subkey.keytype = qder2b_pack_int32 (dersubkey, subkey.enctype);
2547                 auth.subkey.keyvalue.derptr = subkey.contents;
2548                 auth.subkey.keyvalue.derlen = subkey.length;
2549 prange ("cli_K", subkey.contents, subkey.length);
2550         }
2551         //
2552         // Setup the client realm and principal name
2553         auth.crealm.derptr = cmd->krbid_cli->realm.data;
2554         auth.crealm.derlen = cmd->krbid_cli->realm.length;
2555         auth.cname.name_type = qder2b_pack_int32 (dernametype, cmd->krbid_cli->type);
2556         // The SEQUENCE OF with just one component is trivial to prepack
2557         auth.cname.name_string.derptr = cmd->krbid_cli->data [0].data;
2558         auth.cname.name_string.derlen = cmd->krbid_cli->data [0].length;
2559         //
2560         // Setup the Kerberos version number (5)
2561         auth.authenticator_vno = qder2b_pack_int32 (derv5, 5);
2562         //
2563         // Setup the obliged microsecond timer values (ignore error returns)
2564         krb5_us_timeofday (krbctx_cli, &now_s, &now_us);
2565         krb5_timestamp_to_string (now_s, derctime, sizeof (derctime));
2566         derctime [sizeof (derctime)-1] = '\0';
2567         auth.ctime.derptr = derctime;
2568         auth.ctime.derlen = strlen (derctime);
2569         auth.cusec = qder2b_pack_int32 (dercusec, now_us);
2570         //
2571         // Pack the decoded result into dec_authenticator
2572         size_t declen = der_pack (      auth_packer,
2573                                         (const dercursor *) &auth,
2574                                         NULL    // Measure length, no output yet
2575                                         );
2576         uint8_t *decptr = malloc (declen);
2577         if (decptr == NULL) {
2578                 return GNUTLS_E_MEMORY_ERROR;
2579         }
2580         der_pack (                      auth_packer,
2581                                         (const dercursor *) &auth,
2582                                         decptr + declen);
2583 prangefull ("cli_A", decptr, declen);
2584         size_t rawlen;
2585         if (0 != krb5_c_encrypt_length (krbctx_cli,
2586                                         cmd->krb_key.enctype,
2587                                         declen,
2588                                         &rawlen)) {
2589                 free (decptr);
2590                 return GNUTLS_E_ENCRYPTION_FAILED;
2591         }
2592         uint8_t *rawptr = malloc (rawlen);
2593         if (rawptr == NULL) {
2594                 free (decptr);
2595                 return GNUTLS_E_MEMORY_ERROR;
2596         }
2597         krb5_data decdata;
2598         krb5_enc_data rawdata;
2599         memset (&decdata, 0, sizeof (decdata));
2600         memset (&rawdata, 0, sizeof (rawdata));
2601         decdata.data   = decptr;
2602         decdata.length = declen;
2603         rawdata.ciphertext.data   = rawptr;
2604         rawdata.ciphertext.length = rawlen;
2605         if (0 != krb5_c_encrypt (       krbctx_cli,
2606                                         &cmd->krb_key,
2607                                         11 /* stealing key usage from AP-REQ */,
2608                                         NULL,
2609                                         &decdata,
2610                                         &rawdata)) {
2611                 free (rawptr);
2612                 free (decptr);
2613                 return GNUTLS_E_ENCRYPTION_FAILED;
2614         }
2615         //
2616         // Prepare the header information
2617         QDERBUF_INT32_T deretype;
2618         QDERBUF_UINT32_T derkvno;
2619         encrypted_data_t encdata;
2620         encdata.etype = qder2b_pack_int32 (deretype, cmd->krb_key.enctype);
2621         //NOT// encdata.kvno  = qder2b_pack_int32 (derkvno,  cmd->krb_key.kvno);
2622         encdata.cipher.derptr = rawdata.ciphertext.data;
2623         encdata.cipher.derlen = rawdata.ciphertext.length;
2624         //
2625         // Prepare for packing the header and rawdata as EncryptedData
2626         size_t enclen = der_pack (      encdata_packer,
2627                                         (const dercursor *) &encdata,
2628                                         NULL    // Measure length, no output yet
2629                                         );
2630         uint8_t *encptr = malloc (enclen);
2631         if (encptr == NULL) {
2632                 free (rawptr);
2633                 free (decptr);
2634                 return GNUTLS_E_MEMORY_ERROR;
2635         }
2636         der_pack (                      encdata_packer,
2637                                         (const dercursor *) &encdata,
2638                                         encptr + enclen);
2639         free (rawptr);
2640         //
2641         // Return our final verdict on the generation of the Authenticator
2642         dec_authenticator->data = decptr;
2643         dec_authenticator->size = declen;
2644         enc_authenticator->data = encptr;
2645         enc_authenticator->size = enclen;
2646 prange ("cli_D", decptr, declen);
2647 prange ("cli_E", encptr, enclen);
2648         return 0;
2649 }
2650 #endif
2651
2652
2653 /* The callback function that verifies a TLS-KDH "signature", which is kept
2654  * outside of GnuTLS.  The callback verifies the authenticator against the
2655  * provided session hash and returns the decrypted authenticator.
2656  */
2657 #ifdef HAVE_TLS_KDH
2658 static int srv_kdhsig_decode (gnutls_session_t session,
2659                         const gnutls_datum_t *enc_authenticator,
2660                         gnutls_datum_t *dec_authenticator,
2661                         gnutls_datum_t *hash,
2662                         int32_t *checksum_type) {
2663         //
2664         // Variables, sanity checks and initialisation
2665         int k5err = 0;
2666         struct command *cmd;
2667         static const uint8_t encdata_packer [] = {
2668                 DER_PACK_rfc4120_EncryptedData, DER_PACK_END };
2669         static const uint8_t auth_packer [] = {
2670                 DER_PACK_rfc4120_Authenticator, DER_PACK_END };
2671         encrypted_data_t encdata;
2672         cmd = (struct command *) gnutls_session_get_ptr (session);
2673 prange ("srv_E", enc_authenticator->data, enc_authenticator->size);
2674         //
2675         // Retrieve the session key and store it in cmd->krb_key.
2676         //
2677         // Prior setting of cmd->krb_key would be due to user-to-user mode
2678         // having been setup with this as the server-supplied TGT key, in
2679         // which case cmd->krb_key would need to be overwritten by the
2680         // session key.
2681         //
2682         // When no prior cmd->krb_key is available, use the keytab to
2683         // decode the client's ticket.
2684         assert (gnutls_certificate_type_get_peers (session) == GNUTLS_CRT_KRB);
2685         const gnutls_datum_t *certs;
2686         unsigned int num_certs;
2687         certs = gnutls_certificate_get_peers (cmd->session, &num_certs);
2688         if (num_certs != 1) {
2689                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
2690         }
2691         krb5_data krbcert;
2692         krb5_ticket *tkt;
2693         krbcert.data   = certs [0].data;
2694         krbcert.length = certs [0].size;
2695 prange ("srv_C", certs [0].data, certs [0].size);
2696         if (0 != krb5_decode_ticket (&krbcert, &tkt)) {
2697                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
2698         }
2699         if (cmd->krb_key.contents != NULL) {
2700                 // user-to-user mode
2701                 k5err = krb5_decrypt_tkt_part (
2702                                         krbctx_srv,
2703                                         &cmd->krb_key,
2704                                         tkt);
2705                 krb5_free_keyblock_contents (
2706                                         krbctx_srv,
2707                                         &cmd->krb_key);
2708         } else {
2709                 // client-to-server mode
2710                 k5err = krb5_server_decrypt_ticket_keytab (
2711                                         krbctx_srv,
2712                                         krb_kt_srv,
2713                                         tkt);
2714         }
2715         if (k5err == 0) {
2716                 k5err = krb5_copy_keyblock_contents (
2717                                         krbctx_srv,
2718                                         tkt->enc_part2->session,
2719                                         &cmd->krb_key);
2720         }
2721         if (k5err == 0) {
2722                 k5err = krb5_copy_principal (
2723                                         krbctx_srv,
2724                                         tkt->enc_part2->client,
2725                                         &cmd->krbid_cli);
2726         }
2727         if (k5err == 0) {
2728                 if (cmd->krbid_srv != NULL) {
2729                         k5err = krb5_principal_compare (
2730                                                         krbctx_srv,
2731                                                         tkt->server,
2732                                                         cmd->krbid_srv);
2733                                 // Server name changed since u2u setup => k5err
2734                 } else {
2735                         k5err = krb5_copy_principal (
2736                                                         krbctx_srv,
2737                                                         tkt->server,
2738                                                         &cmd->krbid_srv);
2739                 }
2740         }
2741         krb5_free_ticket (krbctx_srv, tkt);
2742         if (k5err != 0) {
2743                 const char *errmsg = krb5_get_error_message (krbctx_srv, k5err);
2744                 tlog (TLOG_DAEMON, LOG_ERR, "Kerberos error in srv_kdhsig_decode: %s", errmsg);
2745                 krb5_free_error_message (krbctx_srv, errmsg);
2746                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
2747         }
2748         //
2749         // Harvest the EncryptedData fields from the enc_authenticator
2750         dercursor enctransport;
2751         enctransport.derptr = enc_authenticator->data;
2752         enctransport.derlen = enc_authenticator->size;
2753         memset (&encdata, 0, sizeof (encdata));
2754         if (0 != der_unpack (           &enctransport,
2755                                         encdata_packer,
2756                                         (dercursor *) &encdata,
2757                                         1)) {
2758                 tlog (TLOG_DAEMON, LOG_ERR, "Failed to der_unpack(EncryptedData) in server: %s", strerror (errno));
2759                 return GNUTLS_E_DECRYPTION_FAILED;
2760         }
2761         if (encdata.kvno.derptr != NULL) {
2762                 //TODO//NOTYET//ANDWHY// return GNUTLS_E_DECRYPTION_FAILED;
2763         }
2764         int32_t etype = qder2b_unpack_int32 (encdata.etype);
2765         //
2766         // Decrypt the EncryptedData fields into the dec_authenticator
2767         krb5_enc_data rawdata;
2768         krb5_data decdata;
2769         memset (&rawdata, 0, sizeof (rawdata));
2770         memset (&decdata, 0, sizeof (decdata));
2771         rawdata.enctype = etype;
2772         rawdata.ciphertext.data   = encdata.cipher.derptr;
2773         rawdata.ciphertext.length = encdata.cipher.derlen;
2774 prange ("srv_R", encdata.cipher.derptr, encdata.cipher.derlen);
2775         decdata.data   = dec_authenticator->data;
2776         decdata.length = dec_authenticator->size;
2777         if (0 != krb5_c_decrypt (       krbctx_srv,
2778                                         &cmd->krb_key,
2779                                         11 /* stealing key usage from AP-REQ */,
2780                                         NULL,
2781                                         &rawdata,
2782                                         &decdata)) {
2783                 return GNUTLS_E_DECRYPTION_FAILED;
2784         }
2785         dec_authenticator->size = decdata.length;
2786 prange ("srv_D", decdata.data, decdata.length);
2787         //
2788         // Unpack the decrypted Authenticator
2789         dercursor decsyntax;
2790         decsyntax.derptr = decdata.data;
2791         decsyntax.derlen = decdata.length;
2792 prangefull ("srv_A", decdata.data, decdata.length);
2793         authenticator_t auth;
2794         memset (&auth, 0, sizeof (auth));
2795         if (0 != der_unpack (           &decsyntax,
2796                                         auth_packer,
2797                                         (dercursor *) &auth,
2798                                         1)) {
2799                 tlog (TLOG_DAEMON, LOG_ERR, "Failed to der_unpack(Authenticator) in server: %s", strerror (errno));
2800                 return GNUTLS_E_DECRYPTION_FAILED;
2801         }
2802         //
2803         // Validate the contents of the Authenticator
2804         if (qder2b_unpack_int32 (auth.authenticator_vno) != 5) {
2805                 return GNUTLS_E_DECRYPTION_FAILED;
2806         }
2807         if (auth.cksum.checksum.derptr == NULL) {
2808                 return GNUTLS_E_DECRYPTION_FAILED;
2809         }
2810         if (auth.cksum.checksum.derlen < 16) {
2811                 return GNUTLS_E_DECRYPTION_FAILED;
2812         }
2813         //TODO// Optionally, for KDH-Only, ensure presence and size of a subkey
2814         //
2815         // Produce the requested content from the Authenticator and return
2816         *checksum_type = qder2b_unpack_int32 (auth.cksum.cksumtype);
2817         hash->data = auth.cksum.checksum.derptr;
2818         hash->size = auth.cksum.checksum.derlen;
2819         return 0;
2820 }
2821 #endif
2822
2823
2824
2825 /********** VALIDATION EXPRESSION LINKUP TO GNUTLS **********/
2826
2827
2828
2829 /*
2830  * The following functions implement the various validation expression
2831  * components in terms of the GnuTLS sessions of this code file.
2832  * Some work is repeated in various expression variables, notably the
2833  * lookup of a session's peer credentials, and possibly importing them
2834  * into X.509 structures.  We may at some point decide to instead do
2835  * this ahead of time, ath the expense of some compleity and possibly
2836  * slow-down of the start of the computations.
2837  */
2838
2839
2840
2841 /* valexp_store_final -- store the valexp outcome in cmd->valexp_result.
2842  */
2843 static void valexp_store_final (void *vcmd, struct valexp *ve, bool result) {
2844         ((struct command *) vcmd)->valexp_result = result;
2845 }
2846
2847 /* valexp_valflag_set -- set a validation flag bit for an uppercase predicate.
2848  */
2849 static void valexp_valflag_set (struct command *cmd, char pred) {
2850         int len = strlen (cmd->valflags);
2851         cmd->valflags [len++] = pred;
2852         cmd->valflags [len  ] = '\0';
2853 }
2854
2855 /* valexp_valflag_start -- get a prior set bit with validation information.
2856  * Where cmd->valflags is a string of uppercase letters that were ensured.
2857  */
2858 static void valexp_valflag_start (void *vcmd, struct valexp *ve, char pred) {
2859         struct command *cmd = (struct command *) vcmd;
2860         pred &= 0xdf;   // lowercase->uppercase
2861         valexp_setpredicate (ve, pred, NULL != strchr (cmd->valflags, pred));
2862 }
2863
2864 /* valexp_0_start -- validation function for the GnuTLS backend.
2865  * This function immediately sends failure on something impossible.
2866  */
2867 static void valexp_0_start (void *vcmd, struct valexp *ve, char pred) {
2868         valexp_setpredicate (ve, pred, 0);
2869 }
2870
2871 /* valexp_1_start -- validation function for the GnuTLS backend.
2872  * This function immediately sends success on something trivial.
2873  */
2874 static void valexp_1_start (void *vcmd, struct valexp *ve, char pred) {
2875         valexp_setpredicate (ve, pred, 1);
2876 }
2877
2878 //TODO// valexp_L_start, valexp_l_start
2879
2880 /* valexp_I_start -- validation function for the GnuTLS backend.
2881  * This function ensures that the remote peer provides an identity.
2882  * TODO: We should compare the hostname as well, or compare if in remoteid
2883  * TODO: We may need to support more than just X509/PGP certificates 
2884  */
2885 static void valexp_I_start (void *vcmd, struct valexp *ve, char pred) {
2886         struct command *cmd = (struct command *) vcmd;
2887         int ok = 1;
2888         ok = ok && (cmd->remote_auth_type == GNUTLS_CRD_CERTIFICATE);
2889         ok = ok && (cmd->remote_cert_count > 0);
2890         // Accept most certificates, but not for example GNUTLS_CRT_RAW
2891         ok = ok && (
2892 #ifdef GNUTLS_CRT_KRB
2893                 (cmd->remote_cert_type == GNUTLS_CRT_KRB) ||
2894 #endif
2895                 (cmd->remote_cert_type == GNUTLS_CRT_X509) ||
2896                 (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) );
2897         // peer-returned "certs" points into GnuTLS' internal data structures
2898         valexp_setpredicate (ve, pred, ok);
2899 }
2900
2901 /* valexp_i_start -- is opportunistic and will always succeed
2902  */
2903 #define valexp_i_start valexp_1_start
2904
2905 /* valexp_Ff_start -- validation function for the GnuTLS backend.
2906  * This functin ensures that forward secrecy is applied.
2907  * While _F_ only accepts DHE, _f_ will also accept DH.
2908  * Note: GnuTLS does not seem to show DH that is not also DHE.
2909  */
2910 static void valexp_Ff_start (void *vcmd, struct valexp *ve, char pred) {
2911         struct command *cmd = (struct command *) vcmd;
2912         gnutls_kx_algorithm_t kx = gnutls_kx_get (cmd->session);
2913         switch (kx) {
2914         case GNUTLS_KX_UNKNOWN:
2915         case GNUTLS_KX_RSA:
2916         case GNUTLS_KX_RSA_EXPORT:
2917         case GNUTLS_KX_PSK:
2918         default:
2919                 valexp_setpredicate (ve, pred, 0);
2920                 break;
2921         case GNUTLS_KX_DHE_DSS:
2922         case GNUTLS_KX_DHE_RSA:
2923         case GNUTLS_KX_SRP:
2924         case GNUTLS_KX_SRP_RSA:
2925         case GNUTLS_KX_SRP_DSS:
2926         case GNUTLS_KX_DHE_PSK:
2927         case GNUTLS_KX_ECDHE_RSA:
2928         case GNUTLS_KX_ECDHE_ECDSA:
2929         case GNUTLS_KX_ECDHE_PSK:
2930         case GNUTLS_KX_ANON_ECDH:       // Assume DHE is in fact implemented
2931         case GNUTLS_KX_ANON_DH:         // Assume DHE is in fact implemented
2932                 valexp_setpredicate (ve, pred, 1);
2933                 break;
2934         // case GNUTLS_KX_xxx_DH:
2935         //      valexp_setpredicate (ve, pred, pred != 'F');
2936         //      break;
2937         }
2938 }
2939
2940 /* valexp_A_start -- validation function for the GnuTLS backend.
2941  * This function ensures that an anonymising precursor is used.
2942  */
2943 #define valexp_A_start valexp_valflag_start
2944
2945 /* valexp_a_start -- is opportunistic and will always succeed */
2946 #define valexp_a_start valexp_1_start
2947
2948 /* valexp_Tt_start -- validation function for the GnuTLS backend.
2949  * This function ensures trust based on a trusted certificate/key list.
2950  * In the _t_ case, self-signed certificates are also accepted.
2951  */
2952 static void valexp_Tt_start (void *vcmd, struct valexp *ve, char pred) {
2953         struct command *cmd = (struct command *) vcmd;
2954         int flagval = 0;
2955         unsigned int vfyresult;
2956         int bad;
2957         int i;
2958         if (cmd->vfystatus != 0) {
2959                 goto setflagval;
2960         }
2961         if (cmd->remote_auth_type != GNUTLS_CRD_CERTIFICATE) {
2962                 goto setflagval;
2963         }
2964         //
2965         // Handle self-signed peer certificates in a special way
2966         if (cmd->remote_cert_count == 1) {
2967                 int bad = 0;
2968                 bad = bad || (pred == 'T');     // Reject self-signed
2969                 if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
2970                         vfyresult = 0;
2971                         bad = bad || gnutls_x509_crt_verify (
2972                                 (gnutls_x509_crt_t   ) cmd->remote_cert [0],
2973                                 (gnutls_x509_crt_t *) &cmd->remote_cert [0], 1,
2974                                 GNUTLS_VERIFY_DISABLE_CA_SIGN,
2975                                 &vfyresult);
2976                         // Apply the most stringent test.  This includes all of
2977                         // GNUTLS_CERT_INVALID (always set, often with others)
2978                         // GNUTLS_CERT_NOT_ACTIVATED
2979                         // GNUTLS_CERT_EXPIRED
2980                         // GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE
2981                         // GNUTLS_CERT_SIGNER_NOT_FOUND
2982                         // GNUTLS_CERT_SIGNER_NOT_CA => oops...
2983                         //      stopped with GNUTLS_VERIFY_DISABLE_CA_SIGN
2984                         // GNUTLS_CERT_SIGNATURE_FAILURE
2985                         // GNUTLS_CERT_INSECURE_ALGORITHM
2986                         bad = bad || (vfyresult != 0);
2987                         if (!bad) {
2988                                 flagval = 1;
2989                                 goto setflagval;
2990                         }
2991                 } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
2992                         //TODO// Prefer to actually check PGP self-signature
2993                         //TODO// But only value is check private-key ownership
2994                         flagval = 0;
2995                         goto setflagval;
2996 #ifdef GNUTLS_CRT_KRB
2997                 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
2998                         // Kerberos has authenticated the ticket for us
2999                         //TODO// Should we try reading from the ticket/auth?
3000                         flagval = 1;
3001                         goto setflagval;
3002 #endif
3003                 }
3004                 if (bad) {
3005                         goto setflagval;
3006                 }
3007         }
3008         if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
3009                 // Now check the certificate chain, taking CA bits into account
3010                 for (i=1; i<cmd->remote_cert_count; i++) {
3011                         vfyresult = 0;
3012                         bad = bad || gnutls_x509_crt_verify (
3013                                 (gnutls_x509_crt_t  )  cmd->remote_cert [i-1],
3014                                 (gnutls_x509_crt_t *) &cmd->remote_cert [i], 1,
3015                                 0,
3016                                 &vfyresult);
3017                         // Apply the most stringent test.  This includes all of
3018                         // GNUTLS_CERT_INVALID (always set, often with others)
3019                         // GNUTLS_CERT_NOT_ACTIVATED
3020                         // GNUTLS_CERT_EXPIRED
3021                         // GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE
3022                         // GNUTLS_CERT_SIGNER_NOT_FOUND
3023                         // GNUTLS_CERT_SIGNER_NOT_CA => oops...
3024                         //      stopped with GNUTLS_VERIFY_DISABLE_CA_SIGN
3025                         // GNUTLS_CERT_SIGNATURE_FAILURE
3026                         // GNUTLS_CERT_INSECURE_ALGORITHM
3027                         bad = bad || (vfyresult != 0);
3028                 }
3029         } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
3030                 ; //TODO// Check PGP direct signature (and also use in self-sig)
3031 #ifdef GNUTLS_CRT_KRB
3032         } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
3033                 ; // Trust has already been validated through Kerberos
3034 #endif
3035         }
3036 setflagval:
3037         valexp_setpredicate (ve, pred, flagval);
3038 }
3039
3040 /* valexp_Dd_start -- validation function for the GnuTLS backend.
3041  * This function validates through DNSSEC.
3042  * While _D_ enforces DNSSEC, _d_ also accepts opted-out security.
3043  */
3044 static void valexp_Dd_start (void *vcmd, struct valexp *ve, char pred) {
3045         struct command *cmd = (struct command *) vcmd;
3046         int flagval = 0;
3047         dane_state_t stat;
3048         unsigned int vfystat;
3049         char *host;
3050         char *proto;
3051         int sox;
3052         struct sockaddr peername;
3053         socklen_t peernamesz = sizeof (peername);
3054         uint16_t port;
3055         host = strchr (cmd->cmd.pio_data.pioc_starttls.remoteid, '@');
3056         if (host == NULL) {
3057                 host = cmd->cmd.pio_data.pioc_starttls.remoteid;
3058         }
3059         switch (cmd->cmd.pio_data.pioc_starttls.ipproto) {
3060         case IPPROTO_TCP:
3061                 proto = "tcp";
3062                 break;
3063         case IPPROTO_UDP:
3064                 proto = "udp";
3065                 break;
3066         case IPPROTO_SCTP:
3067                 proto = "sctp";
3068                 break;
3069         default:
3070                 goto setflagval;
3071         }
3072         sox = gnutls_transport_get_int (cmd->session);
3073         if (sox < 0) {
3074                 goto setflagval;
3075         }
3076         if (getpeername (sox, &peername, &peernamesz) != 0) {
3077                 goto setflagval;
3078         }
3079         if ((peername.sa_family == AF_INET) &&
3080                                 (peernamesz == sizeof (struct sockaddr_in))) {
3081                 port = ntohs (((struct sockaddr_in *) &peername)->sin_port);
3082         } else if ((peername.sa_family == AF_INET6) &&
3083                                 (peernamesz == sizeof (struct sockaddr_in6))) {
3084         } else {
3085                 port = ntohs (((struct sockaddr_in6 *) &peername)->sin6_port);
3086                 goto setflagval;
3087         }
3088         //TODO// We might use online.c code instead?
3089         if (dane_state_init (&stat, /*TODO:*/ 0) != GNUTLS_E_SUCCESS) {
3090                 goto setflagval;
3091         }
3092         if (dane_verify_session_crt (stat,
3093                                 cmd->session,
3094                                 host,
3095                                 proto,
3096                                 port,
3097                                 0,
3098                                 DANE_VFLAG_FAIL_IF_NOT_CHECKED,
3099                                 &vfystat) == DANE_E_SUCCESS) {
3100                 if ((pred == 'D') && (vfystat & DANE_VERIFY_UNKNOWN_DANE_INFO)) {
3101                         dane_state_deinit (stat);
3102                         goto setflagval;
3103                 }
3104                 flagval = ((vfystat & ~DANE_VERIFY_UNKNOWN_DANE_INFO) == 0);
3105         }
3106         dane_state_deinit (stat);
3107 setflagval:
3108         valexp_setpredicate (ve, pred, flagval);
3109 }
3110
3111 /* valexp_Rr_start -- validation function for the GnuTLS backend.
3112  * This function validates through a CRL.
3113  * While _R_ requires the CRL to be present, _r_ accepts confirmed absense.
3114  * TODO: This is not implemented yet.
3115  */
3116 static void valexp_Rr_start (void *vcmd, struct valexp *ve, char pred) {
3117         //TODO//;
3118         valexp_setpredicate (ve, pred, 0);
3119 }
3120
3121 /* valexp_Ee_start -- validation function for the GnuTLS backend.
3122  * This function validates certificate extensions for the named service.
3123  * While _E_ required OIDs to be marked critical, _e_ also accepts non-crit.
3124  */
3125 static void valexp_Ee_start (void *vcmd, struct valexp *ve, char pred) {
3126         //TODO//;
3127         valexp_setpredicate (ve, pred, 0);
3128 }
3129
3130 /* valexp_Oo_start -- validation function for the GnuTLS backend.
3131  * This function validates with online/live information.
3132  * While _O_ required positive confirmation, _o_ also accepts unknown.
3133  *  -> For X.509,    look in OCSP or CRL or Global Directory
3134  *  -> For OpenPGP,  redirect O->G, o->g
3135  *  -> For Kerberos, accept anything as sufficiently live / online
3136  */
3137 static void valexp_Oo_start (void *vcmd, struct valexp *ve, char pred) {
3138         struct command *cmd = (struct command *) vcmd;
3139         int valflag = 0;
3140         online2success_t o2vf;
3141         char *rid;
3142         gnutls_datum_t *raw;
3143         if (cmd->remote_auth_type != GNUTLS_CRD_CERTIFICATE) {
3144                 // No authentication types other than certificates yet
3145                 goto setvalflag;
3146         } else {
3147                 if ((pred >= 'a') && (pred <= 'z')) {
3148                         o2vf = online2success_optional;
3149                 } else {
3150                         o2vf = online2success_enforced;
3151                 }
3152                 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
3153                 raw = (gnutls_datum_t *) cmd->remote_cert_raw;
3154                 if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
3155                         valflag = o2vf (online_globaldir_pgp (
3156                                         rid,
3157                                         raw->data, raw->size));
3158                 } else if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
3159                         // OCSP inquiry or globaldir
3160                         valflag = o2vf (online_globaldir_x509 (
3161                                         rid,
3162                                         raw->data, raw->size));
3163 #ifdef HAVE_TLS_KDH
3164                 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
3165                         // Kerberos is sufficiently "live" to be pass O
3166                         valflag = 1;
3167                         goto setvalflag;
3168 #endif
3169                 } else {
3170                         // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
3171                         goto setvalflag;
3172                 }
3173         }
3174 setvalflag:
3175         valexp_setpredicate (ve, pred, valflag);
3176 }
3177
3178 /* valexp_Gg_start -- validation function for the GnuTLS backend.
3179  * This function validates through the LDAP global directory.
3180  * While _G_ requires information to be present, _g_ also accepts absense.
3181  *  -> For X.509,   lookup userCertificate
3182  *  -> For OpenPGP, lookup pgpKey
3183  *  -> For KDH,     lookup krbPrincipalName
3184  *  -> For SRP,     nothing is defined
3185  *  -> For OpenSSH, no TLS support
3186  */
3187 static void valexp_Gg_start (void *vcmd, struct valexp *ve, char pred) {
3188         struct command *cmd = (struct command *) vcmd;
3189         int valflag = 0;
3190         online2success_t o2vf;
3191         char *rid;
3192         gnutls_datum_t *raw;
3193         if (cmd->remote_auth_type != GNUTLS_CRD_CERTIFICATE) {
3194                 // No authentication types other than certificates yet
3195                 goto setvalflag;
3196         } else {
3197                 if ((pred >= 'a') && (pred <= 'z')) {
3198                         o2vf = online2success_optional;
3199                 } else {
3200                         o2vf = online2success_enforced;
3201                 }
3202                 rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
3203                 raw = (gnutls_datum_t *) cmd->remote_cert_raw;
3204                 if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
3205                         valflag = o2vf (online_globaldir_pgp (
3206                                         rid,
3207                                         raw->data, raw->size));
3208                 } else if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
3209                         //TODO// OCSP inquiry or globaldir
3210                         valflag = o2vf (online_globaldir_x509 (
3211                                         rid,
3212                                         raw->data, raw->size));
3213 #ifdef GNUTLS_CRT_KRB
3214                 } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
3215                         valflag = 0;
3216                         //TODO// valflag = o2vf (online_globaldir_kerberos (
3217                         //TODO//                rid,
3218                         //TODO//                raw->data, raw->size));
3219 #endif
3220                 } else {
3221                         // GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
3222                         goto setvalflag;
3223                 }
3224         }
3225 setvalflag:
3226         valexp_setpredicate (ve, pred, valflag);
3227 }
3228
3229 /* valexp_Pp_start -- validation function for the GnuTLS backend.
3230  * This function validates through pinning information.
3231  * While _P_ requires pinning to be present, _p_ will Trust On First Use.
3232  */
3233 static void valexp_Pp_start (void *vcmd, struct valexp *ve, char pred) {
3234         //TODO//;
3235         valexp_setpredicate (ve, pred, 0);
3236 }
3237
3238 /* valexp_U_start -- validation function for the GnuTLS backend.
3239  * This function validates a matching username.
3240  */
3241 static void valexp_U_start (void *vcmd, struct valexp *ve, char pred) {
3242         //TODO//;
3243         valexp_setpredicate (ve, pred, 0);
3244 }
3245
3246 /* valexp_Ss_start -- validation function for the GnuTLS backend.
3247  * This function ensures that the local end is a server.
3248  * While _S_ denies credentials also usable for clients, _s_ permits them.
3249  */
3250 static void valexp_Ss_start (void *vcmd, struct valexp *ve, char pred) {
3251         struct command *cmd = (struct command *) vcmd;
3252         int flagval;
3253         if ((pred == 'S') && (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
3254                 flagval = 0;
3255         } else {
3256                 flagval = (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) != 0;
3257         }
3258         valexp_setpredicate (ve, pred, flagval);
3259 }
3260
3261 /* valexp_Cc_start -- validation function for the GnuTLS backend.
3262  * This function ensures that the local end is a client.
3263  * While _C_ denies credentials also usable for servers, _c_ permits them.
3264  */
3265 static void valexp_Cc_start (void *vcmd, struct valexp *ve, char pred) {
3266         struct command *cmd = (struct command *) vcmd;
3267         int flagval;
3268         if ((pred == 'C') && (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)) {
3269                 flagval = 0;
3270         } else {
3271                 flagval = (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) != 0;
3272         }
3273         valexp_setpredicate (ve, pred, flagval);
3274 }
3275
3276
3277 static void valexp_error_start (void *handler_data, struct valexp *ve, char pred) {
3278         assert (0);
3279 }
3280 static void valexp_ignore_stop (void *handler_data, struct valexp *ve, char pred) {
3281         ; // Nothing to do
3282 }
3283 static void valexp_ignore_final (void *handler_data, struct valexp *ve, bool value) {
3284         ; // Nothing to do
3285 }
3286
3287
3288 /* Given a predicate, invoke its start routine.
3289  */
3290 static void valexp_switch_start (void *handler_data, struct valexp *ve, char pred) {
3291         switch (pred) {
3292         case 'I':
3293                 valexp_I_start (handler_data, ve, pred);
3294                 break;
3295         case 'i':
3296                 valexp_i_start (handler_data, ve, pred);
3297                 break;
3298         case 'F':
3299         case 'f':
3300                 valexp_Ff_start (handler_data, ve, pred);
3301                 break;
3302         case 'A':
3303                 valexp_A_start (handler_data, ve, pred);
3304                 break;
3305         case 'a':
3306                 valexp_a_start (handler_data, ve, pred);
3307                 break;
3308         case 'T':
3309         case 't':
3310                 valexp_Tt_start (handler_data, ve, pred);
3311                 break;
3312         case 'D':
3313         case 'd':
3314                 valexp_Dd_start (handler_data, ve, pred);
3315                 break;
3316         case 'R':
3317         case 'r':
3318                 valexp_Rr_start (handler_data, ve, pred);
3319                 break;
3320         case 'E':
3321         case 'e':
3322                 valexp_Ee_start (handler_data, ve, pred);
3323                 break;
3324         case 'O':
3325         case 'o':
3326                 valexp_Oo_start (handler_data, ve, pred);
3327                 break;
3328         case 'G':
3329         case 'g':
3330                 valexp_Gg_start (handler_data, ve, pred);
3331                 break;
3332         case 'P':
3333         case 'p':
3334                 valexp_Pp_start (handler_data, ve, pred);
3335                 break;
3336         case 'U':
3337                 valexp_U_start (handler_data, ve, pred);
3338                 break;
3339         case 'S':
3340         case 's':
3341                 valexp_Ss_start (handler_data, ve, pred);
3342                 break;
3343         case 'C':
3344         case 'c':
3345                 valexp_Cc_start (handler_data, ve, pred);
3346                 break;
3347         default:
3348                 // Called on an unregistered symbol, that spells failure
3349                 valexp_setpredicate (ve, pred, 0);
3350                 break;
3351         }
3352 }
3353
3354 /* Return a shared constant structure for valexp_handling with GnuTLS.
3355  * This function does not fail; it always returns a non-NULL value.
3356  */
3357 static const struct valexp_handling *have_starttls_validation (void) {
3358         static const struct valexp_handling starttls_valexp_handling = {
3359                 .handler_start = valexp_switch_start,
3360                 .handler_stop  = valexp_ignore_stop,
3361                 .handler_final = valexp_store_final,
3362         };
3363         return &starttls_valexp_handling;
3364 }
3365
3366
3367
3368 /* If any remote credentials are noted, cleanup on them.  This removes
3369  * any remote_cert[...] entries, counting up to remote_cert_count which
3370  * is naturally set to 0 initially, as well as after this has run.
3371  */
3372 static void cleanup_any_remote_credentials (struct command *cmd) {
3373         while (cmd->remote_cert_count > 0) {
3374                 gnutls_x509_crt_deinit (
3375                         cmd->remote_cert [--cmd->remote_cert_count]);
3376         }
3377         memset (cmd->remote_cert, 0, sizeof (cmd->remote_cert));
3378 }
3379
3380 /* Fetch remote credentials.  This can be done after TLS handshaking has
3381  * completed, to find the certificates or other credentials provided by
3382  * the peer to establish its identity.  The validation expression routines
3383  * can then refer to this resource, and won't have to request the same
3384  * information over and over again.  To this end, the information is stored
3385  * in the session object.  The arrays in which this information is stored
3386  * are size-constrained, but that is also a good security precaution.
3387  *
3388  * The information ends up in the following variables:
3389  *  - remote_auth_type
3390  *  - remote_cert_type (if remote_auth_type == GNUTLS_CRD_CERTIFICATE)
3391  *  - remote_cert[...] (if remote_cert_type == GNUTLS_CRD_CERTIFICATE)
3392  *  - remote_cert_count is the number of entries in remote_cert (up to root)
3393  *
3394  * When certificates are used, the root certificate is looked up, for
3395  * X.509 and PGP.
3396  *
3397  * After running successfully, a call to cleanup_any_remote_credentials()
3398  * must be called to clean up any data in the cmd structure.  This may be
3399  * done on cmd at any time after initialisation, even multiple times and
3400  * even when this call fails.  This call actually cleans up anything it
3401  * setup in the past, before setting up the data anew.
3402  */
3403 static gtls_error fetch_remote_credentials (struct command *cmd) {
3404         gtls_error gtls_errno = GNUTLS_E_SUCCESS;
3405         const gnutls_datum_t *certs;
3406         unsigned int num_certs;
3407         gnutls_x509_crt_t x509peers [11]; // Peers + Root for GNUTLS_CRT_X509
3408         int i;
3409         bool got_chain = 0;
3410         int peer_tad = -1;
3411
3412         // Did we run this before?  Then cleanup.
3413         cleanup_any_remote_credentials (cmd);
3414         //INVOLVES// memset (cmd->remote_cert, 0, sizeof (cmd->remote_cert));
3415         //INVOLVES// cmd->remote_cert_count = 0;
3416         // Prepare as-yet-unset default return values
3417         cmd->remote_auth_type = -1;
3418         cmd->remote_cert_raw = NULL;
3419         //
3420         // Obtain the authentication type for the peer
3421         cmd->remote_auth_type = gnutls_auth_get_type (cmd->session);
3422         switch (cmd->remote_auth_type) {
3423         case GNUTLS_CRD_CERTIFICATE:
3424                 // Continue loading certificates in the GnuTLS format
3425                 break;
3426         case GNUTLS_CRD_ANON:
3427                 // No basis for any identity claim
3428                 cmd->cmd.pio_data.pioc_starttls.remoteid [0] = '\0';
3429                 return GNUTLS_E_SUCCESS;
3430         case GNUTLS_CRD_SRP:
3431                 return GNUTLS_E_SUCCESS;
3432         case GNUTLS_CRD_PSK:
3433                 return GNUTLS_E_SUCCESS;
3434         default:
3435                 return GNUTLS_E_AUTH_ERROR;
3436         }
3437         //
3438         // Continue loading the certificate information: X.509, PGP, ...
3439 #ifdef HAVE_TLS_KDH
3440         cmd->remote_cert_type = gnutls_certificate_type_get_peers (cmd->session);
3441         certs = gnutls_certificate_get_peers (cmd->session, &num_certs);
3442 #else
3443         cmd->remote_cert_type = gnutls_certificate_type_get (cmd->session);
3444         certs = gnutls_certificate_get (cmd->session, &num_certs);
3445 #endif
3446         if (certs == NULL) {
3447                 num_certs = 0;
3448         }
3449         // "certs" points into GnuTLS' internal data structures
3450         if ((num_certs < 1) || (num_certs > CERTS_MAX_DEPTH)) {
3451                 return GNUTLS_E_AUTH_ERROR;
3452         }
3453         cmd->remote_cert_raw = (void *) &certs [0];
3454         //
3455         // Turn certificate data into GnuTLS' data structures (to be cleaned)
3456         if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
3457                 peer_tad = TAD_TYPE_X509;
3458                 for (i=0; i < num_certs; i++) {
3459                         E_g2e ("Failed to initialise peer X.509 certificate",
3460                                 gnutls_x509_crt_init (
3461                                         (gnutls_x509_crt_t *) &cmd->remote_cert [i]));
3462                         if (gtls_errno == GNUTLS_E_SUCCESS) {
3463                                 cmd->remote_cert_count++;
3464                         }
3465                         E_g2e ("Failed to import peer X.509 certificate",
3466                                 gnutls_x509_crt_import (
3467                                         cmd->remote_cert [i],
3468                                         &certs [i], GNUTLS_X509_FMT_DER));
3469                 }
3470                 if (gtls_errno != GNUTLS_E_SUCCESS) {
3471                         goto cleanup;
3472                 }
3473         } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
3474                 peer_tad = TAD_TYPE_PGP;
3475                 E_g2e ("Failed to initialise peer PGP key",
3476                                 gnutls_x509_crt_init (
3477                                         (gnutls_x509_crt_t *) &cmd->remote_cert [0]));
3478                 if (gtls_errno == GNUTLS_E_SUCCESS) {
3479                         cmd->remote_cert_count = 1;
3480                 }
3481                 E_g2e ("Failed to import peer PGP key",
3482                                 gnutls_openpgp_crt_import (
3483                                         cmd->remote_cert [0],
3484                                         &certs [0], GNUTLS_OPENPGP_FMT_RAW));
3485                 if (gtls_errno != GNUTLS_E_SUCCESS) {
3486                         goto cleanup;
3487                 }
3488         }
3489
3490         //
3491         // Lookup the trusted party that the peers certificates is promoting.
3492         // Note that even if the peer ends in a CA cert (which it may not
3493         // always send along) then we can still add it ourselves again :-)
3494         // Only worry might be that CA certs require no AuthorityKeyIdentifier.
3495         if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
3496                 // Retrieve the AuthorityKeyIdentifier from last (or semi-last)
3497                 uint8_t id [100];
3498                 size_t idsz;
3499                 DBT rootca;
3500                 DBT anchor;
3501                 DBC *crs_trust = NULL;
3502                 int db_errno;
3503                 gnutls_datum_t anchor_gnutls;
3504                 gnutls_x509_crt_t dbroot;
3505                 dbt_init_empty (&rootca);
3506                 dbt_init_empty (&anchor);
3507                 idsz = sizeof (id);
3508                 gtls_errno = gnutls_x509_crt_get_authority_key_id (
3509                         cmd->remote_cert [cmd->remote_cert_count-1],
3510                         id, &idsz,
3511                         NULL);
3512                 if (gtls_errno == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
3513                         // Only retry if the last is a signer, possibly CA
3514                         if (cmd->remote_cert_count == 1) {
3515                                 // Permit self-signed certificate evaluation
3516                                 gtls_errno = GNUTLS_E_SUCCESS;
3517                         } else if (cmd->remote_cert_count > 1) {
3518                                 // Assume the last is a root cert, as it lacks authid
3519                                 gnutls_x509_crt_deinit (
3520                                         cmd->remote_cert [--cmd->remote_cert_count]);
3521                                 cmd->remote_cert [cmd->remote_cert_count] = NULL;
3522                                 idsz = sizeof (id);
3523                                 gtls_errno = gnutls_x509_crt_get_authority_key_id (
3524                                         cmd->remote_cert [cmd->remote_cert_count-1],
3525                                         id, &idsz,
3526                                         NULL);
3527                         }
3528                 }
3529                 if (gtls_errno != GNUTLS_E_SUCCESS) {
3530                         goto cleanup;
3531                 }
3532                 // Get root cert from trustdb into remote_cert [_count++]
3533                 dbt_init_fixbuf (&rootca, id, idsz);
3534                 dbt_init_malloc (&anchor);
3535                 E_d2e ("Failed to create db_disclose cursor",
3536                         dbh_trust->cursor (
3537                                 dbh_trust,
3538                                 cmd->txn,
3539                                 &crs_trust,
3540                                 0));
3541                 E_d2e ("X.509 authority key identifier not found in trust database",
3542                         dba_trust_iterate (
3543                                 crs_trust, &rootca, &anchor));
3544                 while (db_errno == 0) {
3545                         // Process "anchor" entry (inasfar as meaningful)
3546                         uint32_t anchorflags;
3547                         uint8_t *trustdata;
3548                         int trustdatalen;
3549                         char *valexp;   //TODO// Initiate this before cleanup
3550                         int tstatus = trust_interpret (&anchor, &anchorflags, &valexp, &trustdata, &trustdatalen);
3551                         dbt_free (&anchor);
3552                         if (tstatus != TAD_STATUS_SUCCESS) {
3553                                 // Signal any DB error to bail out of this loop
3554                                 db_errno = DB_KEYEMPTY;
3555                         } else if ((anchorflags & TAD_TYPE_MASK) != peer_tad) {
3556                                 ;       // Skip unsought trust database entry
3557                         } else if ((anchorflags & TAD_TYPE_MASK) == TAD_TYPE_X509) {
3558                                 E_g2e ("Certificate chain too long",
3559                                         (cmd->remote_cert_count >= CERTS_MAX_DEPTH)
3560                                         ? GNUTLS_E_AUTH_ERROR
3561                                         : GNUTLS_E_SUCCESS);
3562                                 // Turn the anchor into an X.509 certificate
3563                                 E_g2e ("Failet to initialise X.509 peer trust anchor",
3564                                         gnutls_x509_crt_init ((gnutls_x509_crt_t *) &cmd->remote_cert [cmd->remote_cert_count]));
3565                                 if (gtls_errno == GNUTLS_E_SUCCESS) {
3566                                         cmd->remote_cert_count++;
3567                                         anchor_gnutls.data = anchor.data;
3568                                         anchor_gnutls.size = anchor.size;
3569                                         E_g2e ("Failed to import X.509 peer trust anchor",
3570                                                 gnutls_x509_crt_import (cmd->remote_cert [cmd->remote_cert_count-1], &anchor_gnutls, GNUTLS_X509_FMT_DER));
3571                                 }
3572                                 if (gtls_errno == GNUTLS_E_SUCCESS) {
3573                                         // Everything worked, we have a chain
3574                                         got_chain = 1;
3575                                         if (cmd->trust_valexp) {
3576                                                 free (cmd->trust_valexp);
3577                                         }
3578                                         cmd->trust_valexp = strdup (valexp);
3579                                 } else {
3580                                         // Signal arbitrary DB error
3581                                         db_errno = DB_KEYEMPTY;
3582                                 }
3583                         } else if ((anchorflags & TAD_TYPE_MASK) == TAD_TYPE_REVOKE_X509) {
3584                                 //TODO// Possibly verify end cert revocation
3585                         } else {
3586                                 /* Ignore entry, continue with the next */;
3587                         }
3588                         db_errno = dba_trust_iterate (crs_trust, &rootca, &anchor);
3589                 }
3590                 if (crs_trust != NULL) {
3591                         crs_trust->close (crs_trust);
3592                         crs_trust = NULL;
3593                 }
3594                 dbt_free (&anchor);
3595                 // No dbt_free (&rootca) because it is set to a fixed buffer
3596                 if (db_errno != DB_NOTFOUND) {
3597                         goto cleanup;
3598                 }
3599         } else if (cmd->remote_cert_type == GNUTLS_CRT_OPENPGP) {
3600                 ; //TODO// Attempt to load PGP direct signer(s)
3601                 ; //OPTION// May use the _count for alternative signers!
3602                 ; //OPTION// May setup/reload a keyring based on trust.db
3603 #ifdef GNUTLS_CRT_KRB
3604         } else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
3605                 ; //TODO// Process as appropriate for Kerberos (store Ticket?)
3606 #endif
3607         }
3608         //
3609         // Cleanup (when returning an error code) and return
3610 cleanup:
3611         if (gtls_errno != GNUTLS_E_SUCCESS) {
3612                 cleanup_any_remote_credentials (cmd);
3613         }
3614         while ((!got_chain) && (cmd->remote_cert_count > 1)) {
3615                 --cmd->remote_cert_count;
3616                 gnutls_x509_crt_deinit (
3617                         cmd->remote_cert [cmd->remote_cert_count]);
3618                 cmd->remote_cert [cmd->remote_cert_count] = NULL;
3619         }
3620         return gtls_errno;
3621 }
3622
3623
3624 /* Fetch local credentials.  This can be done before TLS is started, to find
3625  * the possible authentication forms that can be offered.  The function
3626  * can additionally be used after interaction with the client to establish
3627  * a local identity that was not initially provided, or that was not
3628  * considered public at the time.
3629  */
3630 gtls_error fetch_local_credentials (struct command *cmd) {
3631         int lidrole;
3632         char *lid, *rid;
3633         DBC *crs_disclose = NULL;
3634         DBC *crs_localid = NULL;
3635         DBT discpatn;
3636         DBT keydata;
3637         DBT creddata;
3638         selector_t remote_selector;
3639         int gtls_errno = 0;
3640         int db_errno = 0;
3641         int found = 0;
3642         gtls_error certificate_onthefly (struct command *cmd);
3643
3644         //
3645         // When applicable, try to create an on-the-fly certificate
3646         if (((cmd->cmd.pio_cmd == PIOC_STARTTLS_V2) &&
3647                         (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALID_ONTHEFLY))
3648         || ((cmd->cmd.pio_cmd == PIOC_LIDENTRY_CALLBACK_V2) &&
3649                         (cmd->cmd.pio_data.pioc_lidentry.flags & PIOF_LIDENTRY_ONTHEFLY))) {
3650                 gtls_errno = certificate_onthefly (cmd);
3651                 if (gtls_errno != GNUTLS_E_AGAIN) {
3652                         // This includes GNUTLS_E_SUCCESS
3653 fprintf (stderr, "DEBUG: otfcert retrieval returned %d\n", gtls_errno);
3654                         return gtls_errno;
3655                 } else {
3656 fprintf (stderr, "DEBUG: otfcert retrieval returned GNUTLS_E_AGAIN, so skip it\n", gtls_errno);
3657                         gtls_errno = GNUTLS_E_SUCCESS;  // Attempt failed, ignore
3658                 }
3659         }
3660
3661         //
3662         // Setup a number of common references and structures
3663         // Note: Current GnuTLS cannot support being a peer
3664         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
3665                 lidrole = LID_ROLE_CLIENT;
3666         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
3667                 lidrole = LID_ROLE_SERVER;
3668         } else {
3669                 E_g2e ("TLS Pool command supports neither local client nor local server role",
3670                         GNUTLS_E_INVALID_SESSION);
3671                 return gtls_errno;
3672         }
3673         lid = cmd->cmd.pio_data.pioc_starttls.localid;
3674         rid = cmd->cmd.pio_data.pioc_starttls.remoteid;
3675
3676         //
3677         // Refuse to disclose client credentials when the server name is unset;
3678         // note that server-claimed identities are unproven during handshake.
3679         if ((lidrole == LID_ROLE_CLIENT) && (*rid == '\0')) {
3680                 tlog (TLOG_USER, LOG_ERR, "No remote identity (server name) set, so no client credential disclosure");
3681                 E_g2e ("Missing remote ID",
3682                         GNUTLS_E_NO_CERTIFICATE_FOUND);
3683                 return gtls_errno;
3684         }
3685         //
3686         // Setup database iterators to map identities to credentials
3687         if (lidrole == LID_ROLE_CLIENT) {
3688                 E_d2e ("Failed to create db_disclose cursor",
3689                         dbh_disclose->cursor (
3690                                 dbh_disclose,
3691                                 cmd->txn,
3692                                 &crs_disclose,
3693                                 0));
3694         }
3695         E_d2e ("Failed to create db_localid cursor",
3696                 dbh_localid->cursor (
3697                         dbh_localid,
3698                         cmd->txn,
3699                         &crs_localid,
3700                         0));
3701         //
3702         // Prepare for iteration over possible local identities / credentials
3703         char mid [128];
3704         char cid [128];
3705         if (gtls_errno != 0) {
3706                 ; // Skip setup
3707         } else if (lidrole == LID_ROLE_CLIENT) {
3708                 memcpy (cid, rid, sizeof (cid));
3709                 dbt_init_fixbuf (&discpatn, cid, strlen (cid));
3710                 dbt_init_fixbuf (&keydata,  mid, sizeof (mid)-1);
3711                 dbt_init_malloc (&creddata);
3712                 selector_t ridsel;
3713                 donai_t remote_donai = donai_from_stable_string (rid, strlen (rid));
3714                 if (!selector_iterate_init (&remote_selector, &remote_donai)) {
3715                         E_g2e ("Syntax of remote ID unsuitable for selector",
3716                                 GNUTLS_E_INVALID_REQUEST);
3717                 } else {
3718                         E_d2e ("Failed to start iterator on remote ID selector",
3719                                 dbcred_iterate_from_remoteid_selector (
3720                                         crs_disclose,
3721                                         crs_localid,
3722                                         &remote_selector,
3723                                         &discpatn,
3724                                         &keydata,
3725                                         &creddata));
3726                 }
3727         } else {
3728                 dbt_init_fixbuf (&discpatn, "", 0);     // Unused but good style
3729                 dbt_init_fixbuf (&keydata,  lid, strlen (lid));
3730                 dbt_init_malloc (&creddata);
3731                 E_d2e ("Failed to start iterator on local ID",
3732                         dbcred_iterate_from_localid (
3733                         crs_localid,
3734                         &keydata,
3735                         &creddata));
3736         }
3737         if (db_errno != 0) {
3738                 gtls_errno = GNUTLS_E_DB_ERROR;
3739         }
3740
3741         //
3742         // Now store the local identities inasfar as they are usable
3743         db_errno = 0;
3744         while ((gtls_errno == GNUTLS_E_SUCCESS) && (db_errno == 0)) {
3745                 int ok;
3746                 uint32_t flags;
3747                 int lidtype;
3748
3749                 tlog (TLOG_DB, LOG_DEBUG, "Found BDB entry %s disclosed to %s", creddata.data + 4, (lidrole == LID_ROLE_CLIENT)? rid: "all clients");
3750                 ok = dbcred_flags (
3751                         &creddata,
3752                         &flags);
3753                 lidtype = flags & LID_TYPE_MASK;
3754                 ok = ok && ((flags & lidrole) != 0);
3755                 ok = ok && ((flags & LID_NO_PKCS11) == 0);
3756                 ok = ok && (lidtype >= LID_TYPE_MIN);
3757                 ok = ok && (lidtype <= LID_TYPE_MAX);
3758 #ifdef HAVE_TLS_KDH
3759                 // For current/simple Kerberos, refuse data after PKCS #11 URI
3760                 ok = ok && ((lidtype != LID_TYPE_KRB5) || (NULL == memchr (creddata.data + 4, '\0', creddata.size - 4 - 1)));
3761 #endif
3762                 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 ");
3763                 if (ok) {
3764                         // Move the credential into the command structure
3765                         dbt_store (&creddata,
3766                                 &cmd->lids [lidtype - LID_TYPE_MIN]);
3767                         found = 1;
3768                 } else {
3769                         // Skip the credential by freeing its data structure
3770                         dbt_free (&creddata);
3771                 }
3772                 db_errno = dbcred_iterate_next (crs_disclose, crs_localid, &discpatn, &keydata, &creddata);
3773         }
3774
3775         if (db_errno == DB_NOTFOUND) {
3776                 if (!found) {
3777                         gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
3778                 }
3779         }
3780         if (crs_localid != NULL) {
3781                 crs_localid->close (crs_localid);
3782                 crs_localid = NULL;
3783         }
3784         if (crs_disclose != NULL) {
3785                 crs_disclose->close (crs_disclose);
3786                 crs_disclose = NULL;
3787         }
3788         return gtls_errno;
3789 }
3790
3791
3792 /*
3793  * Check if a given cmd has the given LID_TYPE setup.
3794  * Return 1 for yes or 0 for no; this is used in priority strings.
3795  */
3796 static inline int lidtpsup (struct command *cmd, int lidtp) {
3797         return cmd->lids [lidtp - LID_TYPE_MIN].data != NULL;
3798 }
3799
3800 /* Configure the GnuTLS session with suitable credentials and priority string.
3801  * The anonpre_ok flag should be non-zero to permit Anonymous Precursor.
3802  *
3803  * The credential setup is optional; when creds is NULL, no changes will
3804  * be made.
3805  */
3806 static int configure_session (struct command *cmd,
3807                         gnutls_session_t session,
3808                         struct credinfo *creds,
3809                         int credcount,
3810                         int anonpre_ok) {
3811         int i;
3812         int gtls_errno = GNUTLS_E_SUCCESS;
3813         //
3814         // Install the shared credentials for the client or server role
3815         if (creds != NULL) {
3816                 gnutls_credentials_clear (session);
3817                 for (i=0; i<credcount; i++) {
3818                         E_g2e ("Failed to install credentials into TLS session",
3819                                 gnutls_credentials_set (
3820                                         session,
3821                                         creds [i].credtp,
3822                                         creds [i].cred  ));
3823                 }
3824         }
3825         //
3826         // Setup the priority string for this session; this avoids future
3827         // credential callbacks that ask for something impossible or
3828         // undesired.
3829         //
3830         // Variation factors:
3831         //  - starting configuration (can it be empty?)
3832         //  - Configured security parameters (database? variable?)
3833         //  - CTYPEs, SRP, ANON-or-not --> fill in as + or - characters
3834         if (gtls_errno == GNUTLS_E_SUCCESS) {
3835                 char priostr [512];
3836 #ifdef HAVE_TLS_KDH
3837                 snprintf (priostr, sizeof (priostr)-1,
3838                         // "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
3839                         "NONE:"
3840                         "%%ASYM_CERT_TYPES:"
3841                         "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
3842                         "+COMP-NULL:"
3843                         "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
3844                         "%cANON-ECDH:"
3845                         "+ECDHE-KRB:" // +ECDHE-KRB-RSA:+ECDHE-KRB-ECDHE:" // opt?
3846                         "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
3847                         "+CTYPE-SRV-KRB:+CTYPE-SRV-X.509:+CTYPE-SRV-OPENPGP:"
3848                         "%cCTYPE-CLI-KRB:"
3849                         "%cCTYPE-CLI-X.509:"
3850                         "%cCTYPE-CLI-OPENPGP:"
3851                         "%cSRP:%cSRP-RSA:%cSRP-DSS",
3852                         anonpre_ok                              ?'+':'-',
3853                         1 /* lidtpsup (cmd, LID_TYPE_KRB5)*/            ?'+':'-',
3854                         1 /*lidtpsup (cmd, LID_TYPE_X509)*/             ?'+':'-',
3855                         1 /*lidtpsup (cmd, LID_TYPE_PGP)*/              ?'+':'-',
3856                         //TODO// Temporarily patched out SRP
3857                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
3858                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-',
3859                         lidtpsup (cmd, LID_TYPE_SRP)            ?'+':'-');
3860 #else
3861                 // It's not possible to make good decisions on certificate type
3862                 // for both sides based on knowledge of local authentication
3863                 // abilities.  So we permit all (but would like to be subtler).
3864                 snprintf (priostr, sizeof (priostr)-1,
3865                         // "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
3866                         "NONE:"
3867                         "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
3868                         "+COMP-NULL:"
3869                         "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
3870                         "%cANON-ECDH:"
3871                         "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
3872                         "%cCTYPE-X.509:"
3873                         "%cCTYPE-OPENPGP:"
3874                         "%cSRP:%cSRP-RSA:%cSRP-DSS",
3875                         anonpre_ok                              ?'+':'-',
3876                         1               ?'+':'-',
3877                         1               ?'+':'-',
3878                         //TODO// Temporarily patched out SRP
3879                         1               ?'+':'-',
3880                         1               ?'+':'-',
3881                         1               ?'+':'-');
3882 #endif
3883                 tlog (TLOG_TLS, LOG_DEBUG, "Constructed priority string %s for local ID %s",
3884                         priostr, cmd->cmd.pio_data.pioc_starttls.localid);
3885                 E_g2e ("Failed to set GnuTLS priority string",
3886                         gnutls_priority_set_direct (
3887                         session,
3888                         priostr,
3889                         NULL));
3890         }
3891         //
3892         // Return the application GNUTLS_E_ code including _SUCCESS
3893         return gtls_errno;
3894 }
3895
3896 /* The callback functions retrieve various bits of information for the client
3897  * or server in the course of the handshake procedure.
3898  *
3899  * The logic here is based on client-sent information, such as:
3900  *  - TLS hints -- X.509 or alternatives like OpenPGP, SRP, PSK
3901  *  - TLS hints -- Server Name Indication
3902  *  - User hints -- local and remote identities provided
3903  */
3904 static int srv_clienthello (gnutls_session_t session, unsigned int htype, unsigned int post, unsigned int incoming, const gnutls_datum_t *msg) {
3905         struct command *cmd;
3906         int gtls_errno = GNUTLS_E_SUCCESS;
3907         char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)]; // static
3908         size_t snilen = sizeof (sni);
3909         int snitype;
3910         char *lid;
3911
3912 tlog (LOG_DAEMON, LOG_INFO, "Invoked %sprocessor for Client Hello, htype=%d, incoming=%d\n",
3913                 post ? "post" : "pre",
3914                 htype,
3915                 incoming);
3916
3917 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3918 errno = 0;
3919 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3920
3921 if (!post) {
3922         //
3923         // Setup a number of common references
3924         cmd = (struct command *) gnutls_session_get_ptr (session);
3925         if (cmd == NULL) {
3926                 return GNUTLS_E_INVALID_SESSION;
3927         }
3928
3929         //
3930         // Setup server-specific credentials and priority string
3931         //TODO// get anonpre value here
3932 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
3933 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3934         E_g2e ("Failed to reconfigure GnuTLS as a server",
3935                 configure_session (cmd,
3936                         session,
3937                         srv_creds, srv_credcount, 
3938                         cmd->anonpre & ANONPRE_SERVER));
3939 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
3940
3941 } else {
3942
3943         //
3944         // Setup a number of common references
3945         cmd = (struct command *) gnutls_session_get_ptr (session);
3946         if (cmd == NULL) {
3947                 return GNUTLS_E_INVALID_SESSION;
3948         }
3949         lid = cmd->cmd.pio_data.pioc_starttls.localid;
3950
3951         //
3952         // Setup to ignore/request/require remote identity (from client)
3953 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3954         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
3955                 // Neither Request nor Require remoteid; ignore it
3956                 ;
3957         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REQUEST_REMOTEID) {
3958                 // Use Request instead of Require for remoteid
3959                 ( //RETURNS_VOID// E_g2e ("Failed to request remote identity",
3960                         gnutls_certificate_server_set_request (
3961                                 session,
3962                                 GNUTLS_CERT_REQUEST));
3963 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
3964         } else {
3965                 // Require a remoteid from the client (default)
3966                 ( //RETURNS_VOID// E_g2e ("Failed to require remote identity (the default)",
3967                         gnutls_certificate_server_set_request (
3968                                 session,
3969                                 GNUTLS_CERT_REQUIRE));
3970 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
3971         }
3972
3973         //
3974         // Find the client-helloed ServerNameIndication, or the service name
3975 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3976         sni [0] = '\0';
3977         if (gnutls_server_name_get (session, sni, &snilen, &snitype, 0) == 0) {
3978 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3979                 switch (snitype) {
3980                 case GNUTLS_NAME_DNS:
3981                         break;
3982                 // Note: In theory, other name types could be sent, and it would
3983                 // be useful to access indexes beyond 0.  In practice, nobody
3984                 // uses other name types than exactly one GNUTLS_NAME_DNS.
3985                 default:
3986                         sni [0] = '\0';
3987                         tlog (TLOG_TLS, LOG_ERR, "Received an unexpected SNI type; that is possible but uncommon; skipping SNI");
3988 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3989                         break;
3990                 }
3991         }
3992 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
3993         if (sni [0] != '\0') {
3994                 if (*lid != '\0') {
3995                         int atidx;
3996                         for (atidx=128; atidx > 0; atidx--) {
3997                                 if (lid [atidx-1] == '@') {
3998                                         break;
3999                                 }
4000                         }
4001                         if (strncmp (sni, lid + atidx, sizeof (sni)-atidx) != 0) {
4002                                 tlog (TLOG_USER | TLOG_TLS, LOG_ERR, "Mismatch between client-sent SNI %s and local identity %s", sni, lid);
4003 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
4004                                 return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
4005                         }
4006                 } else {
4007                         memcpy (lid, sni, sizeof (sni));
4008 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
4009                 }
4010         } else {
4011                 memcpy (sni, lid, sizeof (sni)-1);
4012 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
4013                 sni [sizeof (sni) - 1] = '\0';
4014         }
4015 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
4016 }
4017
4018         //
4019         // Lap up any unnoticed POSIX error messages
4020         if (errno != 0) {
4021                 cmd->session_errno = errno;
4022 fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
4023                 gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
4024 fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
4025         }
4026
4027         //
4028         // Round off with an overal judgement
4029 fprintf (stderr, "DEBUG: Returning gtls_errno = %d or \"%s\" from srv_clihello()\n", gtls_errno, gnutls_strerror (gtls_errno));
4030         return gtls_errno;
4031 }
4032
4033
4034 int cli_srpcreds_retrieve (gnutls_session_t session,
4035                                 char **username,
4036                                 char **password) {
4037         //TODO:FIXED//
4038         tlog (TLOG_CRYPTO, LOG_DEBUG, "Picking up SRP credentials");
4039         *username = strdup ("tester");
4040         *password = strdup ("test");
4041         return GNUTLS_E_SUCCESS;
4042 }
4043
4044
4045 /* Setup credentials to be shared by all clients and servers.
4046  * Credentials are generally implemented through callback functions.
4047  * This should be called after setting up DH parameters.
4048  */
4049 static int setup_starttls_credentials (void) {
4050         gnutls_anon_server_credentials_t srv_anoncred = NULL;
4051         gnutls_anon_client_credentials_t cli_anoncred = NULL;
4052         gnutls_certificate_credentials_t clisrv_certcred = NULL;
4053         //TODO:NOTHERE// int srpbits;
4054         gnutls_srp_server_credentials_t srv_srpcred = NULL;
4055         gnutls_srp_client_credentials_t cli_srpcred = NULL;
4056         //TODO// gnutls_kdh_server_credentials_t srv_kdhcred = NULL;
4057         //TODO// gnutls_kdh_server_credentials_t cli_kdhcred = NULL;
4058         int gtls_errno = GNUTLS_E_SUCCESS;
4059         int gtls_errno_stack0 = GNUTLS_E_SUCCESS;
4060
4061         //
4062         // Construct anonymous server credentials
4063         E_g2e ("Failed to allocate ANON-DH server credentials",
4064                 gnutls_anon_allocate_server_credentials (
4065                         &srv_anoncred));
4066         if (!have_error_codes ()) /* E_g2e (...) */ gnutls_anon_set_server_dh_params (
4067                 srv_anoncred,
4068                 dh_params);
4069         if (gtls_errno == GNUTLS_E_SUCCESS) {
4070                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server anonymous credentials");
4071                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_ANON;
4072                 srv_creds [srv_credcount].cred   = (void *) srv_anoncred;
4073                 srv_credcount++;
4074         } else if (srv_anoncred != NULL) {
4075                 gnutls_anon_free_server_credentials (srv_anoncred);
4076                 srv_anoncred = NULL;
4077         }
4078
4079         //
4080         // Construct anonymous client credentials
4081         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
4082         E_g2e ("Failed to allocate ANON-DH client credentials",
4083                 gnutls_anon_allocate_client_credentials (
4084                         &cli_anoncred));
4085 #ifdef MIRROR_IMAGE_OF_SERVER_ANONYMOUS_CREDENTIALS
4086         // NOTE: This is not done under TLS; server always provides DH params
4087         if (!have_error_codes ()) gnutls_anon_set_client_dh_params (
4088                 cli_anoncred,
4089                 dh_params);
4090 #endif
4091         if (gtls_errno == GNUTLS_E_SUCCESS) {
4092                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client anonymous credentials");
4093                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_ANON;
4094                 cli_creds [cli_credcount].cred   = (void *) cli_anoncred;
4095                 cli_credcount++;
4096         } else if (cli_anoncred != NULL) {
4097                 gnutls_anon_free_client_credentials (cli_anoncred);
4098                 cli_anoncred = NULL;
4099         }
4100
4101         //
4102         // Construct certificate credentials for X.509 and OpenPGP cli/srv
4103         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
4104         E_g2e ("Failed to allocate certificate credentials",
4105                 gnutls_certificate_allocate_credentials (
4106                         &clisrv_certcred));
4107         //TODO// What to do here when we add locking on DH params?
4108         gnutls_certificate_set_dh_params (
4109                 clisrv_certcred,
4110                 dh_params);
4111         gtls_errno_stack0 = gtls_errno;
4112         /* TODO: Bad code.  GnuTLS 3.2.1 ignores retrieve_function2 when
4113          * checking if it can handle the OpenPGP certificate type in
4114          * _gnutls_session_cert_type_supported (gnutls_status.c:175) but
4115          * it does see the "1" version field.  It does not callback the
4116          * "1" version if "2" is present though.
4117          */
4118         if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function (
4119                 clisrv_certcred,
4120                 (void *) exit);
4121         if (!have_error_codes ()) /* TODO:GnuTLSversions E_g2e (...) */ gnutls_certificate_set_retrieve_function2 (
4122                 clisrv_certcred,
4123                 clisrv_cert_retrieve);
4124 #ifdef HAVE_TLS_KDH
4125         E_g2e ("Failed to set encoding callback for Kerberos Authenticators",
4126                         gnutls_authenticator_set_encode_function (
4127                                         clisrv_certcred,
4128                                         cli_kdhsig_encode));
4129         E_g2e ("Failed to set decoding callback for Kerberos Authenticators",
4130                         gnutls_authenticator_set_decode_function (
4131                                         clisrv_certcred,
4132                                         srv_kdhsig_decode));
4133 #endif
4134         if (gtls_errno == GNUTLS_E_SUCCESS) {
4135                 // Setup for certificates
4136                 tlog (TLOG_CERT, LOG_INFO, "Setting client and server certificate credentials");
4137                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
4138                 cli_creds [cli_credcount].cred   = (void *) clisrv_certcred;
4139                 cli_credcount++;
4140                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_CERTIFICATE;
4141                 srv_creds [srv_credcount].cred   = (void *) clisrv_certcred;
4142                 srv_credcount++;
4143         } else if (clisrv_certcred != NULL) {
4144                 gnutls_certificate_free_credentials (clisrv_certcred);
4145                 clisrv_certcred = NULL;
4146         }
4147
4148         //
4149         // Construct server credentials for SRP authentication
4150         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
4151         E_g2e ("Failed to allocate SRP server credentials",
4152                 gnutls_srp_allocate_server_credentials (
4153                         &srv_srpcred));
4154         E_g2e ("Failed to set SRP server credentials",
4155                 gnutls_srp_set_server_credentials_file (
4156                         srv_srpcred,
4157                         "../testdata/tlspool-test-srp.passwd",
4158                         "../testdata/tlspool-test-srp.conf"));
4159         if (gtls_errno == GNUTLS_E_SUCCESS) {
4160                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting server SRP credentials");
4161                 srv_creds [srv_credcount].credtp = GNUTLS_CRD_SRP;
4162                 srv_creds [srv_credcount].cred   = (void *) srv_srpcred;
4163                 srv_credcount++;
4164         } else if (srv_srpcred != NULL) {
4165                 gnutls_srp_free_server_credentials (srv_srpcred);
4166                 srv_srpcred = NULL;
4167         }
4168
4169         //
4170         // Construct client credentials for SRP authentication
4171         gtls_errno = gtls_errno_stack0; // Don't pop, just forget last failures
4172         E_g2e ("Failed to allocate SRP client credentials",
4173                 gnutls_srp_allocate_client_credentials (
4174                         &cli_srpcred));
4175         if (!have_error_codes ()) gnutls_srp_set_client_credentials_function (
4176                 cli_srpcred,
4177                 cli_srpcreds_retrieve);
4178         if (gtls_errno == GNUTLS_E_SUCCESS) {
4179                 tlog (TLOG_CRYPTO, LOG_INFO, "Setting client SRP credentials");
4180                 cli_creds [cli_credcount].credtp = GNUTLS_CRD_SRP;
4181                 cli_creds [cli_credcount].cred   = (void *) cli_srpcred;
4182                 cli_credcount++;
4183         } else if (cli_srpcred != NULL) {
4184                 gnutls_srp_free_client_credentials (cli_srpcred);
4185                 cli_srpcred = NULL;
4186         }
4187
4188         //
4189         // Construct server credentials for KDH authentication
4190         //TODO// gtls_errno = gtls_errno_stack0;        // Don't pop, just forget last failures
4191         //TODO// E_g2e ("Failed to allocate KDH server credentials",
4192         //TODO//        gnutls_kdh_allocate_server_credentials (
4193         //TODO//                &srv_kdhcred));
4194         //TODO// E_g2e ("Failed to set KDH server DH params",
4195         //TODO//        gnutls_kdh_set_server_dh_params (
4196         //TODO//                srv_kdhcred,
4197         //TODO//                dh_params));
4198         //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
4199         //TODO//        tlog (TLOG_CRYPTO, LOG_INFO, "Setting server KDH credentials");
4200         //TODO//        srv_creds [srv_credcount].credtp = GNUTLS_CRD_KDH;
4201         //TODO//        srv_creds [srv_credcount].cred   = (void *) srv_kdhcred;
4202         //TODO//        srv_credcount++;
4203         //TODO// } else if (srv_kdhcred != NULL) {
4204         //TODO//        gnutls_kdh_free_server_credentials (srv_kdhcred);
4205         //TODO//        srv_kdhcred = NULL;
4206         //TODO// }
4207
4208         //
4209         // Construct client credentials for KDH
4210         //TODO// gtls_errno = gtls_errno_stack0;        // Don't pop, just forget last failures
4211         //TODO// E_g2e ("Failed to allocate KDH client credentials",
4212         //TODO//        gnutls_kdh_allocate_client_credentials (
4213         //TODO//                &cli_kdhcred));
4214         //TODO// E_g2e ("Failed to set KDH client credentials",
4215         //TODO//        gnutls_kdh_set_client_credentials_function (
4216         //TODO//                cli_kdhcred,
4217         //TODO//                cli_kdh_retrieve));
4218         //TODO// if (gtls_errno == GNUTLS_E_SUCCESS) {
4219         //TODO//        tlog (TLOG_CRYPTO, LOG_INFO, "Setting client KDH credentials");
4220         //TODO//        cli_creds [cli_credcount].credtp = GNUTLS_CRD_KDH;
4221         //TODO//        cli_creds [cli_credcount].cred   = (void *) cli_kdhcred;
4222         //TODO//        cli_credcount++;
4223         //TODO// } else if (cli_kdhcred != NULL) {
4224         //TODO//        gnutls_kdh_free_client_credentials (cli_kdhcred);
4225         //TODO//        cli_kdhcred = NULL;
4226         //TODO// }
4227
4228         //
4229         // Ensure that at least one credential has been set
4230         // TODO: Look at the counters; but at boot, we can require all okay
4231         if ((gtls_errno == GNUTLS_E_SUCCESS) &&
4232                         ( (cli_credcount != EXPECTED_CLI_CREDCOUNT) ||
4233                           (srv_credcount != EXPECTED_SRV_CREDCOUNT) ) ) {
4234                 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);
4235                 E_g2e ("Not all credentials could be setup",
4236                         GNUTLS_E_INSUFFICIENT_CREDENTIALS);
4237         }
4238
4239         //
4240         // Report overall error or success
4241         return gtls_errno;
4242 }
4243
4244
4245 /* Cleanup all credentials created, just before exiting the daemon.
4246  */
4247 static void cleanup_starttls_credentials (void) {
4248         while (srv_credcount-- > 0) {
4249                 struct credinfo *crd = &srv_creds [srv_credcount];
4250                 switch (crd->credtp) {
4251                 case GNUTLS_CRD_CERTIFICATE:
4252                         // Shared with client; skipped in server and removed in client
4253                         // gnutls_certificate_free_credentials (crd->cred);
4254                         break;
4255                 case GNUTLS_CRD_ANON:
4256                         gnutls_anon_free_server_credentials (crd->cred);
4257                         break;
4258                 case GNUTLS_CRD_SRP:
4259                         gnutls_srp_free_server_credentials (crd->cred);
4260                         break;
4261                 //TODO// case GNUTLS_CRD_KDH:
4262                 //TODO//        gnutls_kdh_free_server_credentials (crd->cred);
4263                 //TODO//        break;
4264                 }
4265         }
4266         while (cli_credcount-- > 0) {
4267                 struct credinfo *crd = &cli_creds [cli_credcount];
4268                 switch (crd->credtp) {
4269                 case GNUTLS_CRD_CERTIFICATE:
4270                         // Shared with client; skipped in server and removed in client
4271                         gnutls_certificate_free_credentials (crd->cred);
4272                         break;
4273                 case GNUTLS_CRD_ANON:
4274                         gnutls_anon_free_client_credentials (crd->cred);
4275                         break;
4276                 case GNUTLS_CRD_SRP:
4277                         gnutls_srp_free_client_credentials (crd->cred);
4278                         break;
4279                 //TODO// case GNUTLS_CRD_KDH:
4280                 //TODO//        gnutls_kdh_free_client_credentials (crd->cred);
4281                 //TODO//        break;
4282                 }
4283         }
4284 }
4285
4286
4287 /*
4288  * The starttls_thread is a main program for the setup of a TLS connection,
4289  * either in client mode or server mode.  Note that the distinction between
4290  * client and server mode is only a TLS concern, but not of interest to the
4291  * application or the records exchanged.
4292  *
4293  * If the STARTTLS operation succeeds, this will be reported back to the
4294  * application, but the TLS pool will continue to be active in a copycat
4295  * procedure: encrypting outgoing traffic and decrypting incoming traffic.
4296  *
4297  * A new handshake may be initiated with a STARTTLS command with the special
4298  * flag PIOF_STARTTLS_RENEGOTIATE and the ctlkey set to a previously setup
4299  * TLS connection.  This command runs in a new thread, that cancels the old
4300  * one (which it can only do while it is waiting in copycat) and then join
4301  * that thread (and its data) with the current one.  This is based on the
4302  * ctlkey, which serves to lookup the old thread's data.  When the
4303  * connection ends for other reasons than a permitted cancel by another
4304  * thread, will the thread cleanup its own resources.  In these situations,
4305  * the new command determines the negotiation parameters, and returns identity
4306  * information.
4307  *
4308  * In addition, the remote side may initiate renegotiation.  This is accepted
4309  * without further ado (although future versions of the TLS Pool may add a
4310  * callback mechanism to get it approved).  The renegotiation now runs under
4311  * the originally supplied negotiation parameters.  In case it needs a new
4312  * local identity, it may also perform callbacks.  Possibly repeating what
4313  * happened before -- but most often, a server will start processing a
4314  * protocol and determine that it requires more for the requested level of
4315  * service, and then renegotiate.  This is common, for example, with HTTPS
4316  * connections that decide they need a client certificate for certain URLs.
4317  * The implementation of this facility is currently as unstructured as the
4318  * facility itself, namely through a goto.  We may come to the conclusion
4319  * that a loop is in fact a warranted alternative, but we're not yet
4320  * convinced that this would match with other "structures" in TLS.
4321  *
4322  * In conclusion, there are three possible ways of running this code:
4323  *  1. For a new connection.  Many variables are not known and build up
4324  *     in the course of running the function.
4325  *  2. After a command requesting renegotiation.  This overtakes the prior
4326  *     connection's thread, and copies its data from the ctlkeynode_tls.
4327  *     The resulting code has a number of variables filled in already at
4328  *     an earlier stage.
4329  *  3. After a remote request for renegotiation.  This loops back to an
4330  *     earlier phase, but after the thread takeover and ctlkeynode_tls copy
4331  *     of the explicit command for renegotation.  Its behaviour is subtly
4332  *     different in that it has no command to act on, and so it cannot
4333  *     send responses or error codes.  It will however log and shutdown
4334  *     as the command-driven options would.  It will not perform callbacks
4335  *     for PIOC_STARTTLS_LOCALID_V2 or PIOC_PLAINTEXT_CONNECT_V2.  It will
4336  *     however trigger the PIOC_LIDENTRY_CALLBACK_V2 through the separate
4337  *     callback command, if one is registered.
4338  * Yeah, it's great fun, coding TLS and keeping it both flexible and secure.
4339  */
4340 static void *starttls_thread (void *cmd_void) {
4341         struct command *cmd, *replycmd;
4342         struct command cmd_copy; // for relooping during renegotiation
4343         struct pioc_starttls orig_starttls;
4344         uint32_t orig_cmdcode;
4345         int plainfd = -1;
4346         int cryptfd = -1;
4347         gnutls_session_t session;
4348         int got_session = 0;
4349         int gtls_errno = GNUTLS_E_SUCCESS;
4350         int i;
4351         struct ctlkeynode_tls *ckn = NULL;
4352         uint32_t tout;
4353         int forked = 0;
4354         int want_remoteid = 1;
4355         int got_remoteid = 0;
4356         int renegotiating = 0;
4357         char *preauth = NULL;
4358         unsigned int preauthlen = 0;
4359         int taking_over = 0;
4360         int my_maxpreauth = 0;
4361         int anonpost = 0;
4362
4363         //
4364         // Block thread cancellation -- and re-enable it in copycat()
4365         assert (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) == 0);
4366
4367         //
4368         // General thread setup
4369         replycmd = cmd = (struct command *) cmd_void;
4370         if (cmd == NULL) {
4371                 send_error (replycmd, EINVAL, "Command structure not received");
4372                 assert (pthread_detach (pthread_self ()) == 0);
4373                 return NULL;
4374         }
4375         *cmd->valflags = '\0';
4376         cmd->session_errno = 0;
4377         cmd->anonpre = 0;
4378         orig_cmdcode = cmd->cmd.pio_cmd;
4379         memcpy (&orig_starttls, &cmd->cmd.pio_data.pioc_starttls, sizeof (orig_starttls));
4380         cmd->orig_starttls = &orig_starttls;
4381         cryptfd = cmd->passfd;
4382         cmd->passfd = -1;
4383 //TODO:TEST Removed here because it is tested below
4384 /*
4385         if (cryptfd < 0) {
4386                 tlog (TLOG_UNIXSOCK, LOG_ERR, "No ciphertext file descriptor supplied to TLS Pool");
4387                 send_error (replycmd, EINVAL, "No ciphertext file descriptor supplied to TLS Pool");
4388                 assert (pthread_detach (pthread_self ()) == 0);
4389                 return NULL;
4390         }
4391 */
4392         cmd->session_certificate = (intptr_t) (void *) NULL;
4393         cmd->session_privatekey  = (intptr_t) (void *) NULL;
4394
4395         //
4396         // In case of renegotiation, lookup the previous ctlkeynode by its
4397         // ctlkey.  The fact that we have ckn != NULL indicates that we are
4398         // renegotiating in the code below; it will supply information as
4399         // we continue to run the TLS process.
4400         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_RENEGOTIATE) {
4401 fprintf (stderr, "DEBUG: Got a request to renegotiate existing TLS connection\n");
4402                 //
4403                 // Check that no FD was passed (and ended up in cryptfd)
4404                 if (cryptfd >= 0) {
4405                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Renegotiation started with extraneous file descriptor");
4406                         send_error (replycmd, EPROTO, "File handle supplied for renegotiation");
4407                         close (cryptfd);
4408                         assert (pthread_detach (pthread_self ()) == 0);
4409                         return NULL;
4410                 }
4411                 //
4412                 // First find the ctlkeynode_tls
4413                 ckn = (struct ctlkeynode_tls *) ctlkey_find (cmd->cmd.pio_data.pioc_starttls.ctlkey, security_tls, cmd->clientfd);
4414 fprintf (stderr, "DEBUG: Got ckn == 0x%0x\n", (intptr_t) ckn);
4415                 if (ckn == NULL) {
4416                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to find TLS connection for renegotiation by its ctlkey");
4417                         send_error (replycmd, ESRCH, "Cannot find TLS connection for renegotiation");
4418                         assert (pthread_detach (pthread_self ()) == 0);
4419                         return NULL;
4420                 }
4421                 //
4422                 // Now cancel the pthread for this process
4423                 errno = pthread_cancel (ckn->owner);
4424 fprintf (stderr, "DEBUG: pthread_cancel returned %d\n", errno);
4425                 if (errno == 0) {
4426                         void *retval;
4427                         errno = pthread_join (ckn->owner, &retval);
4428 fprintf (stderr, "DEBUG: pthread_join returned %d\n", errno);
4429                 }
4430                 if (errno == 0) {
4431                         // We have now synchronised with the cancelled thread
4432                         // Cleanup any _remote data in ckn->session->cmd
4433                         cleanup_any_remote_credentials (
4434                                 (struct command *) gnutls_session_get_ptr (
4435                                         ckn->session));
4436                 }
4437                 if (errno != 0) {
4438                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to interrupt TLS connection for renegotiation");
4439                         send_error (replycmd, errno, "Cannot interrupt TLS connection for renegotiation");
4440                         ctlkey_unfind (&ckn->regent);
4441                         assert (pthread_detach (pthread_self ()) == 0);
4442                         // Do not free the ckn, as the other thread still runs
4443                         return NULL;
4444                 }
4445                 //
4446                 // We are in control!  Assimilate the TLS connection data.
4447                 renegotiating = 1;
4448                 plainfd = ckn->plainfd;
4449                 cryptfd = ckn->cryptfd;
4450                 session = ckn->session;
4451                 got_session = 1;
4452                 taking_over = 1;
4453                 ctlkey_unfind (&ckn->regent);
4454         }
4455
4456         // Then follows the unstructured entry point for the unstructured
4457         // request to a TLS connection to renegotiate its security parameters.
4458         // Doing this in any other way than with goto would add a lot of
4459         // make-belief structure that only existed to make this looping
4460         // possible.  We'd rather be honest and admit the lack of structure
4461         // that TLS has in this respect.  Maybe we'll capture it one giant loop
4462         // at some point, but for now that does not seem to add any relief.
4463         renegotiate:
4464 fprintf (stderr, "DEBUG: Renegotiating = %d, anonpost = %d, plainfd = %d, cryptfd = %d, flags = 0x%x, session = 0x%x, got_session = %d, lid = \"%s\", rid = \"%s\"\n", renegotiating, anonpost, plainfd, cryptfd, cmd->cmd.pio_data.pioc_starttls.flags, session, got_session, cmd->cmd.pio_data.pioc_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid);
4465
4466         //
4467         // If this is server renegotiating, send a request to that end
4468         //TODO// Only invoke gnutls_rehandshake() on the server
4469         if (renegotiating && (taking_over || anonpost) && (gtls_errno == GNUTLS_E_SUCCESS)) {
4470 fprintf (stderr, "DEBUG: Invoking gnutls_rehandshake in renegotiation loop\n");
4471                 gtls_errno = gnutls_rehandshake (session);
4472                 if (gtls_errno == GNUTLS_E_INVALID_REQUEST) {
4473                         // Clients should not do this; be forgiving
4474                         gtls_errno = GNUTLS_E_SUCCESS;
4475 fprintf (stderr, "DEBUG: Client-side invocation flagged as wrong; compensated error\n");
4476                 }
4477         }
4478
4479         //
4480         // When renegotiating TLS security, ensure that it is done securely
4481         if (renegotiating && (gnutls_safe_renegotiation_status (session) == 0)) {
4482                 send_error (replycmd, EPROTO, "Renegotiation requested while secure renegotiation is unavailable on remote");
4483                 if (cryptfd >= 0) {
4484                         close (cryptfd);
4485                         cryptfd = -1;
4486                 }
4487                 if (plainfd >= 0) {
4488                         close (plainfd);
4489                         plainfd = -1;
4490                 }
4491                 if (ckn != NULL) {
4492                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
4493                                 free (ckn);
4494                                 ckn = NULL;
4495                         }
4496                 }
4497                 assert (pthread_detach (pthread_self ()) == 0);
4498                 return NULL;
4499         }
4500
4501         //
4502         // Potentially decouple the controlling fd (ctlkey is in orig_starttls)
4503         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_FORK) {
4504                 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_FORK;
4505                 forked = 1;
4506         }
4507
4508         //
4509         // Setup BDB transactions and reset credential datum fields
4510         if (!anonpost) {
4511                 memset (&cmd->lids, 0, sizeof (cmd->lids));
4512                 manage_txn_begin (&cmd->txn);
4513         }
4514
4515         //
4516         // Permit cancellation of this thread -- TODO: Cleanup?
4517 //TODO:TEST// Defer setcancelstate until copycat() activity
4518 /*
4519         errno = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
4520         if (errno != 0) {
4521                 send_error (replycmd, ESRCH, "STARTTLS handler thread cancellability refused");
4522                 if (cryptfd >= 0) {
4523                         close (cryptfd);
4524                         cryptfd = -1;
4525                 }
4526                 if (plainfd >= 0) {
4527                         close (plainfd);
4528                         plainfd = -1;
4529                 }
4530                 if (ckn != NULL) {
4531                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
4532                                 free (ckn);
4533                                 ckn = NULL;
4534                         }
4535                 }
4536                 manage_txn_rollback (&cmd->txn);
4537                 assert (pthread_detach (pthread_self ()) == 0);
4538                 return NULL;
4539         }
4540 */
4541         //
4542         // Check and setup the plaintext file handle
4543         if (cryptfd < 0) {
4544                 send_error (replycmd, EPROTO, "You must supply a TLS-protected socket");
4545                 if (plainfd >= 0) {
4546                         close (plainfd);
4547                         plainfd = -1;
4548                 }
4549 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
4550                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
4551                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
4552                                 free (ckn);
4553                                 ckn = NULL;
4554                         }
4555                 }
4556                 manage_txn_rollback (&cmd->txn);
4557                 assert (pthread_detach (pthread_self ()) == 0);
4558                 return NULL;
4559         }
4560
4561         //
4562         // Decide on support for the Anonymous Precursor, based on the
4563         // service name and its appearance in the anonpre_registry.
4564         // If the remoteid is not interesting to the client then also
4565         // support an Anonymous Precursor; we have nothing to loose.
4566         cmd->anonpre &= ~ANONPRE_EITHER;
4567         if (renegotiating) {
4568                 ; // Indeed, during renegotiation we always disable ANON-DH
4569         } else if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID) {
4570                 cmd->anonpre = ANONPRE_EITHER;
4571                 want_remoteid = 0;
4572         } else {
4573                 int anonpre_regidx =  anonpre_registry_size      >> 1;
4574                 int anonpre_regjmp = (anonpre_registry_size + 1) >> 1;
4575                 int cmp;
4576                 while (anonpre_regjmp > 0) {
4577                         anonpre_regjmp = anonpre_regjmp >> 1;
4578                         cmp = strncasecmp (anonpre_registry [anonpre_regidx].service,
4579                                 cmd->cmd.pio_data.pioc_starttls.service,
4580                                 TLSPOOL_SERVICELEN);
4581 fprintf (stderr, "DEBUG: anonpre_determination, comparing [%d] %s to %s, found cmp==%d\n", anonpre_regidx, anonpre_registry [anonpre_regidx].service, cmd->cmd.pio_data.pioc_starttls.service, cmp);
4582                         if (cmp == 0) {
4583                                 // anonpre_regent matches
4584                                 cmd->anonpre = anonpre_registry [anonpre_regidx].flags;
4585                                 break;
4586                         } else if (cmp > 0) {
4587                                 // anonpre_regent too high
4588                                 anonpre_regidx -= 1 + anonpre_regjmp;
4589                                 if (anonpre_regidx < 0) {
4590                                         anonpre_regidx = 0;
4591                                 }
4592                         } else {
4593                                 // anonpre_regent too low
4594                                 anonpre_regidx += 1 + anonpre_regjmp;
4595                                 if (anonpre_regidx >= anonpre_registry_size) {
4596                                         anonpre_regidx = anonpre_registry_size - 1;
4597                                 }
4598                         }
4599                 }
4600         }
4601
4602         //
4603         // Setup flags for client and/or server roles (make sure there is one)
4604         if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_CLIENT) == 0)) {
4605                 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_SERVER;
4606         }
4607         if ((!renegotiating) && ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REMOTEROLE_SERVER) == 0)) {
4608                 cmd->cmd.pio_data.pioc_starttls.flags &= ~PIOF_STARTTLS_LOCALROLE_CLIENT;
4609         }
4610         if ((cmd->cmd.pio_data.pioc_starttls.flags & (PIOF_STARTTLS_LOCALROLE_CLIENT | PIOF_STARTTLS_LOCALROLE_SERVER)) == 0) {
4611                 //
4612                 // Neither a TLS client nor a TLS server
4613                 //
4614                 send_error (replycmd, ENOTSUP, "Command not supported");
4615                 close (cryptfd);
4616                 if (plainfd >= 0) {
4617                         close (plainfd);
4618                         plainfd = -1;
4619                 }
4620 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
4621                 if (ckn != NULL) { /* TODO: CHECK NEEDED? */
4622                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
4623                                 free (ckn);
4624                                 ckn = NULL;
4625                         }
4626                 }
4627                 manage_txn_rollback (&cmd->txn);
4628                 assert (pthread_detach (pthread_self ()) == 0);
4629                 return NULL;
4630         }
4631
4632         //
4633         // Setup the TLS session.  Also see doc/p2p-tls.*
4634         //
4635         // TODO: GnuTLS cannot yet setup p2p connections
4636         if (ckn != NULL) {
4637                 gnutls_session_set_ptr (
4638                         session,
4639                         cmd);
4640                 //TODO:DONE?// Clear various settings... creds, flags, modes? CLI/SRV?
4641         } else {
4642                 E_g2e ("Failed to initialise GnuTLS peer session",
4643                         gnutls_init (
4644                                 &session,
4645                                 (((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)? GNUTLS_CLIENT: 0) |
4646                                  ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER)? GNUTLS_SERVER: 0))
4647                                 ));
4648                 if (gtls_errno == GNUTLS_E_SUCCESS) {
4649                         got_session = 1;
4650                         gnutls_session_set_ptr (
4651                                 session,
4652                                 cmd);
4653                 }
4654         }
4655         cmd->session = session;
4656         //
4657         // Setup client-specific behaviour if needed
4658         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) {
4659 if (!renegotiating) {   //TODO:TEST//
4660                 //
4661                 // Setup as a TLS client
4662                 //
4663                 int srpbits;
4664                 //
4665                 // Require a minimum security level for SRP
4666                 srpbits = 3072;
4667                 //TODO:CRASH// if (gtls_errno == GNUTLS_E_SUCCESS) gnutls_srp_set_prime_bits (
4668                         //TODO:CRASH// session,
4669                         //TODO:CRASH// srpbits);
4670                 //
4671                 // Setup as a TLS client
4672                 //
4673                 // Setup for potential sending of SNI
4674                 if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_WITHOUT_SNI) == 0) {
4675                         char *str = cmd->cmd.pio_data.pioc_starttls.remoteid;
4676                         int ofs = 0;
4677                         int len = 0;
4678                         while (str [len] && (len < 128)) {
4679                                 if (str [len] == '@') {
4680                                         ofs = len + 1;
4681                                 }
4682                                 len++;
4683                         }
4684                         // If no usable remoteid was setup, ignore it
4685                         if ((len + ofs > 0) && (len < 128)) {
4686                                 cmd->cmd.pio_data.pioc_starttls.remoteid [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)-1] = '\0';
4687                                 E_g2e ("Client failed to setup SNI",
4688                                         gnutls_server_name_set (
4689                                                 session,
4690                                                 GNUTLS_NAME_DNS,
4691                                                 str + ofs,
4692                                                 len - ofs));
4693                         }
4694                 }
4695 } //TODO:TEST//
4696                 //
4697                 // Setup for client credential installation in this session
4698                 //
4699                 // Setup client-specific credentials and priority string
4700 fprintf (stderr, "DEBUG: Configuring client credentials\n");
4701                 E_g2e ("Failed to configure GnuTLS as a client",
4702                         configure_session (cmd,
4703                                 session,
4704                                 anonpost? NULL: cli_creds,
4705                                 anonpost?    0: cli_credcount, 
4706                                 cmd->anonpre & ANONPRE_CLIENT));
4707         }
4708         //
4709         // Setup callback to server-specific behaviour if needed
4710         if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_SERVER) {
4711 fprintf (stderr, "DEBUG: Configuring for server credentials callback if %d==0\n", gtls_errno);
4712 if (!renegotiating) {   //TODO:TEST//
4713                 if (gtls_errno == GNUTLS_E_SUCCESS) {
4714                         gnutls_handshake_set_hook_function (
4715                                 session,
4716                                 GNUTLS_HANDSHAKE_CLIENT_HELLO,
4717                                 GNUTLS_HOOK_BOTH,
4718                                 srv_clienthello);
4719                 }
4720 } //TODO:TEST//
4721                 //TODO:TEST// configure_session _if_ not setup as a client (too)
4722                 //
4723                 // Setup for server credential installation in this session
4724                 //
4725                 // Setup server-specific credentials and priority string
4726 #if 0
4727                 if (! (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT)) {
4728 fprintf (stderr, "DEBUG: Configuring server credentials (because it is not a client)\n");
4729                         E_g2e ("Failed to configure GnuTLS as a server",
4730                                 configure_session (cmd,
4731                                         session,
4732                                         anonpost? NULL: srv_creds,
4733                                         anonpost?    0: srv_credcount, 
4734                                         cmd->anonpre & ANONPRE_SERVER));
4735                 }
4736 #endif
4737         }
4738
4739         //
4740         // Prefetch local identities that might be used in this session
4741         if (!anonpost) {
4742                 E_g2e ("Failed to fetch local credentials",
4743                         fetch_local_credentials (cmd));
4744         }
4745
4746         //
4747         // Setup a temporary priority string so handshaking can start
4748         if ((cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_LOCALROLE_CLIENT) == 0) {
4749                 E_g2e ("Failed to preconfigure server token priority string",
4750                                 gnutls_priority_set (
4751                                         session,
4752                                         priority_normal));
4753         }
4754
4755         //
4756         // Check if past code stored an error code through POSIX
4757         if (cmd->session_errno) {
4758                 gtls_errno = GNUTLS_E_USER_ERROR;
4759         }
4760
4761         //
4762         // Setup a timeout value as specified in the command, where TLS Pool
4763         // defines 0 as default and ~0 as infinite (GnuTLS has 0 as infinite).
4764         tout = cmd->cmd.pio_data.pioc_starttls.timeout;
4765 if (renegotiating) {
4766 ; // Do not set timeout
4767 } else
4768         if (tout == TLSPOOL_TIMEOUT_DEFAULT) {
4769                 gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
4770         } else if (tout == TLSPOOL_TIMEOUT_INFINITE) {
4771                 gnutls_handshake_set_timeout (session, 0);
4772         } else {
4773                 gnutls_handshake_set_timeout (session, tout);
4774         }
4775
4776         //
4777         // Now setup for the GnuTLS handshake
4778         //
4779 if (renegotiating) {
4780 ; // Do not setup cryptfd
4781 } else
4782         if (gtls_errno == GNUTLS_E_SUCCESS) {
4783                 gnutls_transport_set_int (session, cryptfd);
4784         }
4785         if (gtls_errno != GNUTLS_E_SUCCESS) {
4786                 tlog (TLOG_TLS, LOG_ERR, "Failed to prepare for TLS: %s", gnutls_strerror (gtls_errno));
4787                 if (cmd->session_errno) {
4788                         send_error (replycmd, cmd->session_errno, error_getstring ());
4789                 } else {
4790                         send_error (replycmd, EIO, "Failed to prepare for TLS");
4791                 }
4792                 if (got_session) {
4793 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
4794                         gnutls_deinit (session);
4795                         got_session = 0;
4796                 }
4797                 close (cryptfd);
4798                 if (plainfd >= 0) {
4799                         close (plainfd);
4800                         plainfd = -1;
4801                 }
4802 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
4803                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
4804                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
4805                                 free (ckn);
4806                                 ckn = NULL;
4807                         }
4808                 }
4809                 manage_txn_rollback (&cmd->txn);
4810                 assert (pthread_detach (pthread_self ()) == 0);
4811                 return NULL;
4812         }
4813         tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake started over %d", cryptfd);
4814         do {
4815                 //
4816                 // Take a rehandshaking step forward.
4817                 //
4818                 gtls_errno = gnutls_handshake (session);
4819                 //
4820                 // When data is sent before completing
4821                 // the rehandshake, then it's something
4822                 // harmless, given the criteria for the
4823                 // anonpre_registry.  We pass it on and
4824                 // don't worry about it.  We do report
4825                 // it though!
4826                 //
4827                 // Note: Applications should be willing
4828                 // to buffer or process such early data
4829                 // before the handshake is over or else
4830                 // the handshake will bail out in error.
4831                 //
4832                 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
4833                         if (my_maxpreauth <= 0) {
4834                                 tlog (TLOG_COPYCAT, LOG_ERR, "Received unwanted early data before authentication is complete");
4835                                 break; // Terminate the handshake
4836                         } else if (preauth == NULL) {
4837                                 preauth = malloc (my_maxpreauth);
4838                                 if (preauth == NULL) {
4839                                         gtls_errno = GNUTLS_E_MEMORY_ERROR;
4840                                         break; // Terminate the handshake
4841                                 }
4842                         }
4843                 }
4844                 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
4845                         if (preauthlen >= my_maxpreauth) {
4846                                 tlog (TLOG_COPYCAT, LOG_ERR, "Received more early data than willing to receive (%d bytes)", my_maxpreauth);
4847                                 break; // Terminate the handshake
4848                         }
4849                 }
4850                 if (gtls_errno == GNUTLS_E_GOT_APPLICATION_DATA) {
4851                         ssize_t sz;
4852                         sz = gnutls_record_recv (session, preauth + preauthlen, my_maxpreauth - preauthlen);
4853                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Received %d remote bytes (or error if <0) from %d during anonymous precursor\n", (int) sz, cryptfd);
4854                         if (sz > 0) {
4855                                 preauthlen += sz;
4856                                 gtls_errno = GNUTLS_E_SUCCESS;
4857                         } else {
4858                                 gtls_errno = sz; // It's actually an error code
4859                         }
4860                 }
4861         } while ((gtls_errno < 0) &&
4862                 //DROPPED// (gtls_errno != GNUTLS_E_GOT_APPLICATION_DATA) &&
4863                 //DROPPED// (gtls_errno != GNUTLS_E_WARNING_ALERT_RECEIVED) &&
4864                 (gnutls_error_is_fatal (gtls_errno) == 0));
4865         //
4866         // Handshake done -- initialise remote_xxx, vfystatus, got_remoteid
4867         E_g2e ("Failed to retrieve peer credentials",
4868                         fetch_remote_credentials (cmd));
4869         if (gtls_errno == 0) {
4870                 const gnutls_datum_t *certs;
4871                 unsigned int num_certs;
4872                 got_remoteid = 0;
4873                 switch (cmd->remote_auth_type) { // Peer's cred type
4874                 case GNUTLS_CRD_CERTIFICATE:
4875                         if (cmd->remote_cert_count >= 1) {
4876                                 got_remoteid = 1;
4877                         }
4878 #ifdef PHASED_OUT_DIRECT_VALIDATION
4879                         E_g2e ("Failed to validate peer",
4880                                 gnutls_certificate_verify_peers2 (
4881                                         session,
4882                                         &cmd->vfystatus));
4883 #endif
4884                         cmd->vfystatus = 0;
4885                         break;
4886                 case GNUTLS_CRD_PSK:
4887                         // Difficult... what did the history say about this?
4888                         got_remoteid = 0;
4889                         cmd->vfystatus = GNUTLS_CERT_SIGNER_NOT_FOUND;
4890                         break;
4891                 case GNUTLS_CRD_SRP:
4892                         // Got a credential, validation follows later on
4893                         //TODO// SRP does not really auth the server
4894                         got_remoteid = 1;
4895                         cmd->vfystatus = GNUTLS_CERT_SIGNER_NOT_FOUND;
4896                         break;
4897                 case GNUTLS_CRD_ANON:
4898                         // Did not get a credential, perhaps due to anonpre
4899                         got_remoteid = 0;
4900                         cmd->vfystatus = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNATURE_FAILURE;
4901                         break;
4902                 case GNUTLS_CRD_IA:
4903                         // Inner Application extension is no true credential
4904                         // Should we compare the client-requested service?
4905                         // Should we renegotiate into the ALPN protocol?
4906                         got_remoteid = 0;
4907                         cmd->vfystatus = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNATURE_FAILURE;
4908                         break;
4909                 default:
4910                         // Unknown creds cautiously considered unauthentitcated
4911                         got_remoteid = 0;
4912                         cmd->vfystatus = ~ (unsigned short) 0;  // It's all bad
4913                         break;
4914                 }
4915                 //
4916                 // Now recognise and handle the Anonymous Precursor
4917                 if (((cmd->anonpre & ANONPRE_EITHER) != 0)
4918                                         && want_remoteid && !got_remoteid) {
4919                         assert (anonpost == 0);
4920                         valexp_valflag_set (cmd, 'A');
4921                         // Disable ANON-protocols but keep creds from before
4922                         //TODO:ELSEWHERE// tlog (TLOG_TLS, LOG_DEBUG, "Reconfiguring TLS over %d without Anonymous Precursor\n", cryptfd);
4923                         //TODO:ELSEWHERE// E_g2e ("Failed to reconfigure GnuTLS without anonymous precursor",
4924                                 //TODO:ELSEWHERE// configure_session (cmd,
4925                                         //TODO:ELSEWHERE// session,
4926                                         //TODO:ELSEWHERE// NULL, 0, 
4927                                         //TODO:ELSEWHERE// 0));
4928                         // We do not want to use ANON-DH if the flag
4929                         // ANONPRE_EXTEND_MASTER_SECRET is set for the protocol
4930                         // but the remote peer does not support it.  Only if
4931                         // this problem cannot possibly occur, permit
4932                         // my_maxpreauth > 0 for early data acceptance.
4933                         my_maxpreauth = 0;
4934                         if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
4935 #if GNUTLS_VERSION_NUMBER >= 0x030400
4936                                 gnutls_ext_priv_data_t ext;
4937                                 if (!gnutls_ext_get_data (session, 23, &ext)) {
4938                                         my_maxpreauth = maxpreauth;
4939                                 }
4940 #endif
4941                         } else {
4942                                 my_maxpreauth = maxpreauth;
4943                         }
4944                         if (gtls_errno == 0) {
4945                                 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_DEBUG, "TLS handshake continued over %d after anonymous precursor", cryptfd);
4946                                 renegotiating = 1; // (de)selects steps
4947                                 anonpost = 1;      // (de)selects steps
4948                                 goto renegotiate;
4949                         }
4950                 }
4951         }
4952         if ((gtls_errno == GNUTLS_E_SUCCESS) && cmd->session_errno) {
4953                 gtls_errno = GNUTLS_E_USER_ERROR;
4954         }
4955         taking_over = 0;
4956
4957         //
4958         // Run the validation expression logic, using expressions we ran into
4959 fprintf (stderr, "DEBUG: Prior to valexp, gtls_errno = %d\n", gtls_errno);
4960         if (gtls_errno == GNUTLS_E_SUCCESS) {
4961                 struct valexp *verun = NULL;
4962                 char *valexp_conj [3];
4963                 int valexp_conj_count = 0;
4964                 // Setup for validation expression runthrough
4965                 cmd->valexp_result = -1;
4966                 if ((cmd->trust_valexp != NULL) && (0 != strcmp (cmd->trust_valexp, "1"))) {
4967 fprintf (stderr, "DEBUG: Trust valexp \"%s\" @ 0x%016x\n", cmd->trust_valexp, (uint64_t) cmd->trust_valexp);
4968                         valexp_conj [valexp_conj_count++] = cmd->trust_valexp;
4969                 }
4970                 if (cmd->lids [LID_TYPE_VALEXP - LID_TYPE_MIN].data != NULL) {
4971                         // Interpret the entry, abuse p11uri as valexp
4972                         int ok;
4973                         uint32_t flags;
4974                         char *lid_valexp;
4975                         gnutls_datum_t ignored;
4976                         ok = dbcred_interpret (
4977                                 &cmd->lids [LID_TYPE_VALEXP - LID_TYPE_MIN],
4978                                 &flags,
4979                                 &lid_valexp,
4980                                 &ignored.data,
4981                                 &ignored.size);
4982 fprintf (stderr, "DEBUG: LocalID valexp \"%s\" @ 0x%016x (ok=%d)\n", lid_valexp, (uint64_t) lid_valexp, ok);
4983                         if (ok && (lid_valexp != NULL)) {
4984                                 valexp_conj [valexp_conj_count++] = lid_valexp;
4985                         } else {
4986                                 gtls_errno = GNUTLS_E_AUTH_ERROR;
4987                         }
4988                 }
4989 fprintf (stderr, "DEBUG: Number of valexp is %d, gtls_errno=%d\n", valexp_conj_count, gtls_errno);
4990                 // Optionally start computing the validation expression
4991                 if ((gtls_errno == GNUTLS_E_SUCCESS) && (valexp_conj_count > 0)) {
4992                         valexp_conj [valexp_conj_count] = NULL;
4993                         verun = valexp_register (
4994                                 valexp_conj,
4995                                 have_starttls_validation (),
4996                                 (void *) cmd);
4997 fprintf (stderr, "DEBUG: Registered to verun = 0x%016x\n", (uint64_t) verun);
4998                         if (verun == NULL) {
4999                                 gtls_errno = GNUTLS_E_AUTH_ERROR;
5000                         }
5001                 }
5002                 // When setup, run the validation expressions to completion
5003                 if (verun != NULL) {
5004                         while (cmd->valexp_result == -1) {
5005                                 ; //TODO: Tickle async predicate run completion
5006                         }
5007 fprintf (stderr, "DEBUG: Finishing tickling \"async\" predicates for valexp\n");
5008                         if (cmd->valexp_result != 1) {
5009                                 tlog (TLOG_TLS, LOG_INFO, "TLS validation expression result is %d", cmd->valexp_result);
5010                                 gtls_errno = GNUTLS_E_AUTH_ERROR;
5011 fprintf (stderr, "DEBUG: valexp returns NEGATIVE result\n");
5012                         }
5013 else fprintf (stderr, "DEBUG: valexp returns POSITIVE result\n");
5014                         valexp_unregister (verun);
5015 fprintf (stderr, "DEBUG: Unregistered verun 0x%016x\n", (uint64_t) verun);
5016                 }
5017         }
5018
5019         //
5020         // Cleanup any prefetched identities
5021         for (i=LID_TYPE_MIN; i<=LID_TYPE_MAX; i++) {
5022                 if (cmd->lids [i - LID_TYPE_MIN].data != NULL) {
5023                         free (cmd->lids [i - LID_TYPE_MIN].data);
5024                 }
5025         }
5026         memset (cmd->lids, 0, sizeof (cmd->lids));
5027         //
5028         // Cleanup any trust_valexp duplicate string
5029         if (cmd->trust_valexp != NULL) {
5030                 free (cmd->trust_valexp);
5031                 cmd->trust_valexp = NULL;
5032         }
5033         //
5034         // Cleanup any Kerberos session key -- it served its purpose
5035         if (cmd->krb_key.contents != NULL) {
5036                 // RATHER BLUNT: It shouldn't matter which krbctx_ is used...
5037                 krb5_free_keyblock_contents (krbctx_srv, &cmd->krb_key);
5038                 memset (&cmd->krb_key, 0, sizeof (cmd->krb_key));
5039         }
5040         if (cmd->krbid_srv != NULL) {
5041                 // RATHER BLUNT: It shouldn't matter which krbctx_ is used...
5042                 krb5_free_principal (krbctx_srv, cmd->krbid_srv);
5043                 cmd->krbid_srv = NULL;
5044         }
5045         if (cmd->krbid_cli != NULL) {
5046                 // RATHER BLUNT: It shouldn't matter which krbctx_ is used...
5047                 krb5_free_principal (krbctx_srv, cmd->krbid_cli);
5048                 cmd->krbid_cli = NULL;
5049         }
5050
5051 #if 0
5052 /* This is not proper.  gnutls_certificate_set_key() suggests that these are
5053  * automatically cleaned up, and although this is not repeated in
5054  * gnutls_certificate_set_retrieve_function2() it is likely to be related.
5055  * Plus, renegotiation with this code in place bogged down on failed pcerts;
5056  * they were detected in _gnutls_selected_cert_supported_kx() but their
5057  * key exchange algorithm was never found.
5058  */
5059         if (NULL != (void *) cmd->session_privatekey) {
5060                 gnutls_privkey_deinit ((void *) cmd->session_privatekey);
5061                 cmd->session_privatekey = (intptr_t) (void *) NULL;
5062         }
5063         if (NULL != (void *) cmd->session_certificate) {
5064                 gnutls_pcert_deinit ((void *) cmd->session_certificate);
5065                 free ((void *) cmd->session_certificate);
5066                 cmd->session_certificate = (intptr_t) (void *) NULL;
5067         }
5068 #endif
5069
5070         //
5071         // From here, assume nothing about the cmd->cmd structure; as part of
5072         // the handshake, it may have passed through the client's control, as
5073         // part of a callback.  So, reinitialise the entire return structure.
5074         //TODO// Or backup the (struct pioc_starttls) before handshaking
5075         cmd->cmd.pio_cmd = orig_cmdcode;
5076         cmd->cmd.pio_data.pioc_starttls.localid  [0] =
5077         cmd->cmd.pio_data.pioc_starttls.remoteid [0] = '\0';
5078
5079         //
5080         // Respond to positive or negative outcome of the handshake
5081         if (gtls_errno != GNUTLS_E_SUCCESS) {
5082                 tlog (TLOG_TLS, LOG_ERR, "TLS handshake failed: %s", gnutls_strerror (gtls_errno));
5083                 if (cmd->session_errno) {
5084                         char *errstr;
5085                         tlog (TLOG_TLS, LOG_ERR, "Underlying cause may be: %s", strerror (cmd->session_errno));
5086                         errstr = error_getstring ();
5087                         if (errstr == NULL) {
5088                                 errstr = "TLS handshake failed";
5089                         }
5090                         send_error (replycmd, cmd->session_errno, errstr);
5091                 } else {
5092                         send_error (replycmd, EPERM, "TLS handshake failed");
5093                 }
5094                 if (preauth) {
5095                         free (preauth);
5096                 }
5097                 if (got_session) {
5098 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
5099                         gnutls_deinit (session);
5100                         got_session = 0;
5101                 }
5102                 close (cryptfd);
5103                 if (plainfd >= 0) {
5104                         close (plainfd);
5105                         plainfd = -1;
5106                 }
5107 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
5108                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
5109                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
5110                                 free (ckn);
5111                                 ckn = NULL;
5112                         }
5113                 }
5114                 manage_txn_rollback (&cmd->txn);
5115                 assert (pthread_detach (pthread_self ()) == 0);
5116                 return NULL;
5117         } else {
5118                 tlog (TLOG_UNIXSOCK | TLOG_TLS, LOG_INFO, "TLS handshake succeeded over %d", cryptfd);
5119                 //TODO// extract_authenticated_remote_identity (cmd);
5120         }
5121
5122         //
5123         // Request the plaintext file descriptor with a callback
5124         if (plainfd < 0) {
5125                 uint32_t oldcmd = cmd->cmd.pio_cmd;
5126                 struct command *resp;
5127                 cmd->cmd.pio_cmd = PIOC_PLAINTEXT_CONNECT_V2;
5128                 tlog (TLOG_UNIXSOCK, LOG_DEBUG, "Calling send_callback_and_await_response with PIOC_PLAINTEXT_CONNECT_V2");
5129                 resp = send_callback_and_await_response (replycmd, 0);
5130                 assert (resp != NULL);  // No timeout, should be non-NULL
5131                 if (resp->cmd.pio_cmd != PIOC_PLAINTEXT_CONNECT_V2) {
5132                         tlog (TLOG_UNIXSOCK, LOG_ERR, "Callback response has unexpected command code");
5133                         send_error (replycmd, EINVAL, "Callback response has bad command code");
5134                         if (preauth) {
5135                                 free (preauth);
5136                         }
5137                         if (got_session) {
5138 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
5139                                 gnutls_deinit (session);
5140                                 got_session = 0;
5141                         }
5142                         close (cryptfd);
5143 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
5144                         if (ckn) {      /* TODO: CHECK NEEDED? PRACTICE=>YES */
5145                                 if (ctlkey_unregister (ckn->regent.ctlkey)) {
5146                                         free (ckn);
5147                                         ckn = NULL;
5148                                 }
5149                         }
5150                         manage_txn_rollback (&cmd->txn);
5151                         assert (pthread_detach (pthread_self ()) == 0);
5152                         return NULL;
5153                 }
5154                 cmd->cmd.pio_cmd = oldcmd;
5155                 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);
5156                 plainfd = resp->passfd;
5157                 resp->passfd = -1;
5158         }
5159         if (plainfd < 0) {
5160                 tlog (TLOG_UNIXSOCK, LOG_ERR, "No plaintext file descriptor supplied to TLS Pool");
5161                 send_error (replycmd, EINVAL, "No plaintext file descriptor supplied to TLS Pool");
5162                 if (preauth) {
5163                         free (preauth);
5164                 }
5165                 if (got_session) {
5166 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
5167                         gnutls_deinit (session);
5168                         got_session = 0;
5169                 }
5170                 close (cryptfd);
5171 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
5172                 if (ckn != NULL) {      /* TODO: CHECK NEEDED? */
5173                         if (ctlkey_unregister (ckn->regent.ctlkey)) {
5174                                 free (ckn);
5175                                 ckn = NULL;
5176                         }
5177                 }
5178                 manage_txn_rollback (&cmd->txn);
5179                 assert (pthread_detach (pthread_self ()) == 0);
5180                 return NULL;
5181         }
5182         //DEFERRED// send_command (replycmd, -1);               // app sent plainfd to us
5183
5184         //
5185         // Copy TLS records until the connection is closed
5186         manage_txn_commit (&cmd->txn);
5187         if (!renegotiating) {
5188                 ckn = (struct ctlkeynode_tls *) malloc (sizeof (struct ctlkeynode_tls));
5189         }
5190         if (ckn == NULL) {
5191                 send_error (replycmd, ENOMEM, "Out of memory allocating control key structure");
5192         } else {
5193                 int detach = (orig_starttls.flags & PIOF_STARTTLS_DETACH) != 0;
5194                 ckn->session = session;
5195                 ckn->owner = pthread_self ();
5196                 ckn->cryptfd = cryptfd;
5197                 ckn->plainfd = plainfd;
5198 //DEBUG// fprintf (stderr, "Registering control key\n");
5199                 if (renegotiating || (ctlkey_register (orig_starttls.ctlkey, &ckn->regent, security_tls, detach ? INVALID_POOL_HANDLE : cmd->clientfd, forked) == 0)) {
5200                         int copied = GNUTLS_E_SUCCESS;
5201                         send_command (replycmd, -1);            // app sent plainfd to us
5202                         if (preauth) {
5203
5204                                 //
5205                                 // Check on extended master secret if desired
5206                                 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
5207 #if GNUTLS_VERSION_NUMBER >= 0x030400
5208                                         gnutls_ext_priv_data_t ext;
5209                                         if (!gnutls_ext_get_data (session, 23, &ext)) {
5210                                                 cmd->anonpre &= ~ANONPRE_EXTEND_MASTER_SECRET;
5211                                         }
5212 #endif
5213                                 }
5214                                 if (cmd->anonpre & ANONPRE_EXTEND_MASTER_SECRET) {
5215                                         tlog (TLOG_COPYCAT, LOG_ERR, "Received %d remote bytes from anonymous precursor but lacking %s-required authentication through extended master secret", orig_starttls.service);
5216                                         gtls_errno = GNUTLS_E_LARGE_PACKET;
5217                                         copied = 0;
5218
5219                                 } else if (write (plainfd, preauth, preauthlen) == preauthlen) {
5220                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Passed on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
5221                                         free (preauth);
5222                                         preauth = NULL;
5223                                         copied = copycat (plainfd, cryptfd, session, detach ? INVALID_POOL_HANDLE : cmd->clientfd);
5224                                 } else {
5225                                         tlog (TLOG_COPYCAT, LOG_DEBUG, "Failed to pass on %d remote bytes from anonymous precursor to %d\n", preauthlen, plainfd);
5226                                 }
5227                         } else {
5228                                 copied = copycat (plainfd, cryptfd, session, detach ? INVALID_POOL_HANDLE : cmd->clientfd);
5229                         }
5230                         // Renegotiate if copycat asked us to
5231                         if (copied == GNUTLS_E_REHANDSHAKE) {
5232                                 // Yes, goto is a dirty technique.  On the
5233                                 // other hand, so is forcing unstructured
5234                                 // code flows into a make-belief structure
5235                                 // that needs changing over and over again.
5236                                 // I fear goto is the most reasonable way
5237                                 // of handling this rather obtuse structure
5238                                 // of renegotiation of security in TLS :(
5239                                 //TODO// Ensure secure renegotiation!!!
5240                                 renegotiating = 1;
5241                                 replycmd = NULL; // Bypass all send_XXX()
5242                                 memcpy (&cmd_copy, cmd, sizeof (cmd_copy));
5243                                 cmd = &cmd_copy;
5244                                 memcpy (cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, sizeof (cmd->cmd.pio_data.pioc_starttls.localid));
5245                                 memcpy (cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid));
5246                                 cmd->cmd.pio_data.pioc_starttls.flags = orig_starttls.flags & ~PIOF_STARTTLS_LOCALID_CHECK;
5247                                 // Disabling the flag causing LOCALID_CHECK
5248                                 // ...and plainfd >= 0 so no PLAINTEXT_CONNECT
5249                                 // ...so there will be no callbacks to cmd
5250 fprintf (stderr, "DEBUG: Goto renegotiate with cmd.lid = \"%s\" and orig_cmd.lid = \"%s\" and cmd.rid = \"%s\" and orig_cmd.rid = \"%s\" and cmd.flags = 0x%x and orig_cmd.flags = 0x%x\n", cmd->cmd.pio_data.pioc_starttls.localid, orig_starttls.localid, cmd->cmd.pio_data.pioc_starttls.remoteid, orig_starttls.remoteid, cmd->cmd.pio_data.pioc_starttls.flags, orig_starttls.flags);
5251                                 goto renegotiate;
5252                         }
5253 //DEBUG// fprintf (stderr, "Unregistering control key\n");
5254                         // Unregister by ctlkey, which should always succeed
5255                         // if the TLS connection hadn't been closed down yet;
5256                         // and if it does, the memory can be freed.  Note that
5257                         // the ctlkey is not taken from the ckn, which may
5258                         // already have been freed if the ctlfd was closed
5259                         // and the connection could not continue detached
5260                         // (such as after forking it).
5261 fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
5262                         if (ctlkey_unregister (orig_starttls.ctlkey)) {
5263                                 free (ckn);
5264                         }
5265                         ckn = NULL;
5266 //DEBUG// fprintf (stderr, "Unregistered  control key\n");
5267                 } else {
5268                         send_error (replycmd, ENOENT, "Failed to register control key for TLS connection");
5269                 }
5270         }
5271         if (preauth) {
5272                 free (preauth);
5273                 preauth = NULL;
5274         }
5275         close (plainfd);
5276         close (cryptfd);
5277         cleanup_any_remote_credentials (cmd);
5278         if (got_session) {
5279 fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
5280                 gnutls_deinit (session);
5281                 got_session = 0;
5282         }
5283         assert (pthread_detach (pthread_self ()) == 0);
5284         return NULL;
5285 }
5286
5287
5288 /*
5289  * The starttls function responds to an application's request to 
5290  * setup TLS for a given file descriptor, and return a file descriptor
5291  * with the unencrypted view when done.  The main thing done here is to
5292  * spark off a new thread that handles the operations.
5293  */
5294 void starttls (struct command *cmd) {
5295         /* Create a thread and, if successful, wait for it to unlock cmd */
5296         errno = pthread_create (&cmd->handler, NULL, starttls_thread, (void *) cmd);
5297         if (errno != 0) {
5298                 send_error (cmd, ESRCH, "STARTTLS thread refused");
5299                 return;
5300         }
5301 //TODO:TEST// Thread detaches itself before terminating w/o followup
5302 /*
5303         errno = pthread_detach (cmd->handler);
5304         if (errno != 0) {
5305                 pthread_cancel (cmd->handler);
5306                 send_error (cmd, ESRCH, "STARTTLS thread detachment refused");
5307                 return;
5308         }
5309 */
5310 }
5311
5312
5313 /*
5314  * Run the PRNG for a TLS connection, identified by its control key.  If the connection
5315  * is not a TLS connection, or if the control key is not found, reply with ERROR;
5316  * otherwise, the session should help to create pseudo-random bytes.
5317  */
5318 void starttls_prng (struct command *cmd) {
5319         uint8_t in1 [TLSPOOL_PRNGBUFLEN];
5320         uint8_t in2 [TLSPOOL_PRNGBUFLEN];
5321         int16_t in1len, in2len, prnglen;
5322         struct ctlkeynode_tls *ckn = NULL;
5323         char **prefixes;
5324         int err = 0;
5325         int gtls_errno = GNUTLS_E_SUCCESS;
5326         struct pioc_prng *prng = &cmd->cmd.pio_data.pioc_prng;
5327         //
5328         // Find arguments and validate them
5329         in1len  = prng->in1_len;
5330         in2len  = prng->in2_len;
5331         prnglen = prng->prng_len;
5332         err = err || (in1len <= 0);
5333         err = err || (prnglen > TLSPOOL_PRNGBUFLEN);
5334         err = err || ((TLSPOOL_CTLKEYLEN + in1len + (in2len >= 0? in2len: 0))
5335                                 > TLSPOOL_PRNGBUFLEN);
5336         if (!err) {
5337                 memcpy (in1, prng->buffer + TLSPOOL_CTLKEYLEN         , in1len);
5338                 if (in2len > 0) {
5339                         memcpy (in2, prng->buffer + TLSPOOL_CTLKEYLEN + in1len, in2len);
5340                 }
5341         }
5342         //  - check the label string
5343         prefixes = tlsprng_label_prefixes;
5344         while ((!err) && (*prefixes)) {
5345                 char *pf = *prefixes++;
5346                 if (strlen (pf) != in1len) {
5347                         continue;
5348                 }
5349                 if (strcmp (pf, in1) != 0) {
5350                         continue;
5351                 }
5352         }
5353         if (*prefixes == NULL) {
5354                 // RFC 5705 defines a private-use prefix "EXPERIMENTAL"
5355                 if ((in1len <= 12) || (strncmp (in1, "EXPERIMENTAL", 12) != 0)) {
5356                         err = 1;
5357                 }
5358         }
5359         //  - check the ctlkey (and ensure it is for TLS)
5360         if (!err) {
5361 //DEBUG// fprintf (stderr, "Hoping to find control key\n");
5362                 ckn = (struct ctlkeynode_tls *) ctlkey_find (prng->buffer, security_tls, cmd->clientfd);
5363         }
5364         //
5365         // Now wipe the PRNG buffer to get rid of any sensitive bytes
5366         memset (prng->buffer, 0, TLSPOOL_PRNGBUFLEN);
5367         //
5368         // If an error occurrend with the command, report it now
5369         if (err) {
5370                 send_error (cmd, EINVAL, "TLS PRNG request invalid");
5371                 // ckn is NULL if err != 0, so no need for ctlkey_unfind()
5372                 return;
5373         }
5374         if (ckn == NULL) {
5375                 send_error (cmd, ENOENT, "Invalid control key");
5376                 return;
5377         }
5378         //
5379         // Now actually invoke the PRNG command in the GnuTLS backend
5380         errno = 0;
5381         E_g2e ("GnuTLS PRNG based on session master key failed",
5382                 gnutls_prf_rfc5705 (ckn->session,
5383                         in1len, in1,
5384                         (in2len >= 0)? in2len: 0, (in2len >= 0) ? in2: NULL,
5385                         prnglen, prng->buffer));
5386         err = err || (errno != 0);
5387         //
5388         // Wipe temporary data / buffers for security reasons
5389         memset (in1, 0, sizeof (in1));
5390         memset (in2, 0, sizeof (in2));
5391         ctlkey_unfind ((struct ctlkeynode *) ckn);
5392         //
5393         // Return the outcome to the user
5394         if (err) {
5395                 send_error (cmd, errno? errno: EIO, "PRNG in TLS backend failed");
5396         } else {
5397                 send_command (cmd, -1);
5398         }
5399 }
5400
5401
5402 /* Flying signer functionality.  Create an on-the-fly certificate because
5403  * the lidentry daemon and/or application asks for this to represent the
5404  * local identity.  Note that this will only work if the remote party
5405  * accepts the root identity under which on-the-signing is done.
5406  *
5407  * When no root credentials have been configured, this function will
5408  * fail with GNUTLS_E_AGAIN; it may be used as a hint to try through
5409  * other (more conventional) means to obtain a client certificate.
5410  *
5411  * The API of this function matches that of fetch_local_credentials()
5412  * and that is not a coincidence; this is a drop-in replacement in some
5413  * cases.
5414  *
5415  * Limitations: The current implementation only supports X.509 certificates
5416  * to be generated on the fly.  So, this will set LID_TYPE_X509, if anything.
5417  */
5418 gtls_error certificate_onthefly (struct command *cmd) {
5419         gtls_error gtls_errno = GNUTLS_E_SUCCESS;
5420         gnutls_x509_crt_t otfcert;
5421         time_t now;
5422         gnutls_x509_subject_alt_name_t altnmtp;
5423         int i;
5424
5425         //
5426         // Sanity checks
5427         if ((onthefly_issuercrt == NULL) || (onthefly_issuerkey == NULL) || (onthefly_subjectkey == NULL)) {
5428                 // Not able to supply on-the-fly certificates; try someway else
5429                 return GNUTLS_E_AGAIN;
5430         }
5431         if (cmd->cmd.pio_data.pioc_starttls.localid [0] == '\0') {
5432                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
5433         }
5434         if (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data != NULL) {
5435                 free (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data);
5436                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = NULL;
5437                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
5438         }
5439         
5440         //
5441         // Create an empty certificate
5442         E_g2e ("Failed to initialise on-the-fly certificate",
5443                 gnutls_x509_crt_init (&otfcert));
5444         if (gtls_errno != GNUTLS_E_SUCCESS) {
5445                 return gtls_errno;
5446         }
5447
5448         //
5449         // Fill the certificate with the usual field
5450         E_g2e ("Failed to set on-the-fly certificate to non-CA mode",
5451                 gnutls_x509_crt_set_ca_status (otfcert, 0));
5452         E_g2e ("Failed to set on-the-fly certificate version",
5453                 gnutls_x509_crt_set_version (otfcert, 3));
5454         onthefly_serial++;      //TODO// Consider a random byte string
5455         E_g2e ("Failed to set on-the-fly serial number",
5456                 gnutls_x509_crt_set_serial (otfcert, &onthefly_serial, sizeof (onthefly_serial)));
5457         // Skip gnutls_x509_crt_set_issuer_by_dn_by_oid(), added when signing
5458         time (&now);
5459         E_g2e ("Failed to set on-the-fly activation time to now - 2 min",
5460                 gnutls_x509_crt_set_activation_time (otfcert, now - 120));
5461         E_g2e ("Failed to set on-the-fly expiration time to now + 3 min",
5462                 gnutls_x509_crt_set_expiration_time (otfcert, now + 180));
5463         E_g2e ("Setup certificate CN with local identity",
5464                 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? */
5465         E_g2e ("Setup certificate OU with TLS Pool on-the-fly",
5466                 gnutls_x509_crt_set_dn_by_oid (otfcert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "TLS Pool on-the-fly", 19));
5467         if (strchr (cmd->cmd.pio_data.pioc_starttls.localid, '@')) {
5468                 // localid has the format of an emailAddress
5469                 altnmtp = GNUTLS_SAN_RFC822NAME;
5470         } else {
5471                 // localid has the format of a dnsName
5472                 altnmtp = GNUTLS_SAN_DNSNAME;
5473         }
5474         E_g2e ("Failed to set subjectAltName to localid",
5475                 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));
5476         //TODO:SKIP, hoping that signing adds: gnutls_x509_crt_set_authority_key_id()
5477         //TODO:SKIP, hoping that a cert without also works: gnutls_x509_crt_set_subjectkey_id()
5478         //TODO:SKIP? gnutls_x509_crt_set_extension_by_oid
5479         //TODO:      gnutls_x509_crt_set_key_usage
5480         //TODO:SKIP? gnutls_x509_crt_set_ca_status
5481         for (i=0; i < svcusage_registry_size; i++) {
5482                 if (strcmp (svcusage_registry [i].service, cmd->cmd.pio_data.pioc_starttls.service) == 0) {
5483                         const char **walker;
5484                         E_g2e ("Failed to setup basic key usage during on-the-fly certificate creation",
5485                                 gnutls_x509_crt_set_key_usage (otfcert, svcusage_registry [i].usage));
5486                         walker = svcusage_registry [i].oids_non_critical;
5487                         if (walker) {
5488                                 while (*walker) {
5489                                         E_g2e ("Failed to append non-critical extended key purpose during on-the-fly certificate creation",
5490                                                 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 0));
5491                                         walker++;
5492                                 }
5493                         }
5494                         walker = svcusage_registry [i].oids_critical;
5495                         if (walker) {
5496                                 while (*walker) {
5497                                         E_g2e ("Failed to append critical extended key purpose during on-the-fly certificate creation",
5498                                                 gnutls_x509_crt_set_key_purpose_oid (otfcert, *walker, 1));
5499                                         walker++;
5500                                 }
5501                         }
5502                         break;
5503                 }
5504         }
5505         E_g2e ("Failed to et the on-the-fly subject key",
5506                 gnutls_x509_crt_set_key (otfcert, onthefly_subjectkey));
5507         /* TODO: The lock below should not be necessary; it is handled by p11-kit
5508          *       or at least it ought to be.  What I found however, was that
5509          *       a client and server would try to use the onthefly_issuerkey
5510          *       at virtually the same time, and then the second call to
5511          *       C_SignInit returns CKR_OPERATION_ACTIVE.  The lock solved this.
5512          *       This makes me frown about server keys stored in PKCS #11...
5513          */
5514 {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"); } }
5515         assert (pthread_mutex_lock (&onthefly_signer_lock) == 0);
5516         E_g2e ("Failed to sign on-the-fly certificate",
5517                 gnutls_x509_crt_privkey_sign (otfcert, onthefly_issuercrt, onthefly_issuerkey, GNUTLS_DIG_SHA256, 0));
5518         pthread_mutex_unlock (&onthefly_signer_lock);
5519
5520         //
5521         // Construct cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data+size for this certificate
5522         cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
5523         if (gtls_errno == GNUTLS_E_SUCCESS) {
5524                 gtls_errno = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, NULL, &cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
5525                 if (gtls_errno == GNUTLS_E_SHORT_MEMORY_BUFFER) {
5526                         // This is as expected, now .size will have been set
5527                         gtls_errno = GNUTLS_E_SUCCESS;
5528                 } else {
5529                         if (gtls_errno = GNUTLS_E_SUCCESS) {
5530                                 // Something must be wrong if we receive OK
5531                                 gtls_errno = GNUTLS_E_INVALID_REQUEST;
5532                         }
5533                 }
5534                 E_g2e ("Error while measuring on-the-fly certificate size",
5535                         gtls_errno);
5536         }
5537         uint8_t *ptr = NULL;
5538         if (gtls_errno == GNUTLS_E_SUCCESS) {
5539                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size += 4 + strlen (onthefly_p11uri) + 1;
5540                 ptr = malloc (cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size);
5541                 if (ptr == NULL) {
5542                         cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
5543                         gnutls_x509_crt_deinit (otfcert);
5544                         return GNUTLS_E_MEMORY_ERROR;
5545                 }
5546         }
5547         if (ptr != NULL) {
5548                 size_t restsz;
5549                 cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = ptr;
5550                 * (uint32_t *) ptr = htonl (LID_TYPE_X509 | LID_ROLE_BOTH);
5551                 ptr += 4;
5552                 strcpy (ptr, onthefly_p11uri);
5553                 ptr += strlen (onthefly_p11uri) + 1;
5554                 restsz = cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size - 4 - strlen (onthefly_p11uri) - 1;
5555                 E_g2e ("Failed to export on-the-fly certificate as a credential",
5556                         gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, ptr, &restsz));
5557 char *pembuf [10000];
5558 size_t pemlen = sizeof (pembuf) - 1;
5559 int exporterror = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_PEM, pembuf, &pemlen);
5560 if (exporterror == 0) {
5561 pembuf [pemlen] = '\0';
5562 fprintf (stderr, "DEBUG: otfcert ::=\n%s\n", pembuf);
5563 } else {
5564 fprintf (stderr, "DEBUG: otfcert export to PEM failed with %d, gtls_errno already was %d\n", exporterror, gtls_errno);
5565 }
5566         }
5567
5568         //
5569         // Cleanup the allocated and built structures
5570         gnutls_x509_crt_deinit (otfcert);
5571
5572         //
5573         // Return the overall result that might have stopped otf halfway
5574         return gtls_errno;
5575 }
5576