First working TLS-KDH system! (Still with possible memleaks)
authorRick van Rein <rick@openfortress.nl>
Mon, 17 Oct 2016 19:33:00 +0000 (20:33 +0100)
committerRick van Rein <rick@openfortress.nl>
Mon, 17 Oct 2016 21:57:37 +0000 (22:57 +0100)
doc/kerberos.md [new file with mode: 0644]
src/starttls.c

diff --git a/doc/kerberos.md b/doc/kerberos.md
new file mode 100644 (file)
index 0000000..8d22f28
--- /dev/null
@@ -0,0 +1,53 @@
+# Kerberos and the TLS Pool
+
+> *We have started to integrate Kerberos into the TLS Pool, but for now it is
+> a bit crude.  We haven't yet established how to distribute responsibilities.*
+
+The integration of
+[TLS-KDH](https://tools.ietf.org/html/draft-vanrein-tls-kdh)
+into the TLS Pool is a major contribution towards a secure, yet fast
+Internet.  It combines fluently with our sub-projects on
+[realm crossover](http://realm-xover.arpa2.net/kerberos.html)
+and
+[bring your own identity](http://internetwide.org/blog/2015/04/22/id-2-byoid.html)
+combined with
+[authorisation](http://internetwide.org/blog/2015/04/25/id-5-ksaml.html)
+for privacy in spite of
+[hosting-market specialisation](http://internetwide.org/blog/2014/11/19/back-to-hosting.html).
+Yeah, we have a
+[pretty big plan](http://internetwide.org/blog/2016/06/24/iwo-phases.html)
+on where to take the Internet!
+
+The matter with Kerberos is mainly who should hold the ticket cache being
+used.  There are two basic possibilities, it could be made internal to the
+TLS Pool, or it could be externally provided over a new API.
+
+When we choose to use a new API for Kerberos it
+may or may not integrate with the user's desktop.  Very often, desktops
+can hold Kerberos credentials or they can easily have them added, sometimes
+even united with the desktop login (and screensaver-protected) session.
+Moreover, the desktop is the place where the user might switch the primary
+identity being used.
+
+The alternative is to let the TLS Pool hold the Kerberos credentials for
+a user, and that would allow the integration of PKCS #11 in the sign-up
+process, which is specifically interesting in relation to PKINIT.
+
+The matters that help to decide on this are:
+
+  * The desktop location would require the
+    [new socket protocol](socketprotocol.rst)
+    because Kerberos tickets can grow larger than what we have fixed-allocated.
+  * Whether PKINIT is a good idea depends on what is the "security foundation";
+    is it Kerberos, or is it PKCS #11 -- because each can cause the other to
+    be created.  We should even ask ourselves if the TLS Pool should make this
+    choice, or be supportive to both.  Desktops and mobile stations may need
+    to make different choices, for example.
+
+At present, the crude implementation of Kerberos involves using the PIN
+request to obtain a Kerberos password; this means that it must be entered
+manually *or* that the Kerberos password should match the configuration
+file's fixed PIN setting `pkcs11_pin`.  Clearly, the choice of layering
+one mechanism on top of the other has not yet been forced and so we are
+dealing with this kludge for now.
+
index 6fc33d6..7976945 100644 (file)
@@ -1443,8 +1443,8 @@ fprintf (stderr, "DEBUG: Missing certificate for local ID %s and remote ID %s\n"
                } else {
                        //
                        // For KDH-Only, the server supplies one of:
-                       //  - an empty ticket (0 bytes long)
-                       //  - a TGT for user-to-user mode (where considered useful)
+                       //  - a TGT for user-to-user mode (for p2p exchanges)
+                       //  - an DER NULL to waive u2u mode
                        //TODO// E_g2e ("MOVED: Failed to import Kerberos ticket",
                        //TODO//        gnutls_pcert_import_krb_raw (
                        //TODO//                *pcert,
@@ -1461,10 +1461,10 @@ fprintf (stderr, "DEBUG: Missing certificate for local ID %s and remote ID %s\n"
                        // u2u = u2u || "shaken hands on TLS symmetry extension"
                        u2u = u2u && got_cc_srv;  // We may simply not be able!
                        //
-                       // When not in user-to-user mode, deliver 0 bytes
+                       // When not in user-to-user mode, deliver DER NULL
                        if (!u2u) {
-                               certdatum.data = "";
-                               certdatum.size = 0;
+                               certdatum.data = "\x05\x00";
+                               certdatum.size = 2;
                                E_g2e ("Failed to withhold Kerberos server ticket",
                                        gnutls_pcert_import_krb_raw (
                                                *pcert,
@@ -2575,7 +2575,7 @@ prange ("cli_K", subkey.contents, subkey.length);
                                        (const dercursor *) &auth,
                                        NULL    // Measure length, no output yet
                                        );
-       uint8_t *decptr = malloc (declen);
+       uint8_t *decptr = gnutls_malloc (declen);
        if (decptr == NULL) {
                return GNUTLS_E_MEMORY_ERROR;
        }
@@ -2588,12 +2588,12 @@ prangefull ("cli_A", decptr, declen);
                                        cmd->krb_key.enctype,
                                        declen,
                                        &rawlen)) {
-               free (decptr);
+               gnutls_free (decptr);
                return GNUTLS_E_ENCRYPTION_FAILED;
        }
-       uint8_t *rawptr = malloc (rawlen);
+       uint8_t *rawptr = gnutls_malloc (rawlen);
        if (rawptr == NULL) {
-               free (decptr);
+               gnutls_free (decptr);
                return GNUTLS_E_MEMORY_ERROR;
        }
        krb5_data decdata;
@@ -2610,8 +2610,8 @@ prangefull ("cli_A", decptr, declen);
                                        NULL,
                                        &decdata,
                                        &rawdata)) {
-               free (rawptr);
-               free (decptr);
+               gnutls_free (rawptr);
+               gnutls_free (decptr);
                return GNUTLS_E_ENCRYPTION_FAILED;
        }
        //
@@ -2619,6 +2619,7 @@ prangefull ("cli_A", decptr, declen);
        QDERBUF_INT32_T deretype;
        QDERBUF_UINT32_T derkvno;
        encrypted_data_t encdata;
+       memset (&encdata, 0, sizeof (encdata));
        encdata.etype = qder2b_pack_int32 (deretype, cmd->krb_key.enctype);
        //NOT// encdata.kvno  = qder2b_pack_int32 (derkvno,  cmd->krb_key.kvno);
        encdata.cipher.derptr = rawdata.ciphertext.data;
@@ -2629,16 +2630,16 @@ prangefull ("cli_A", decptr, declen);
                                        (const dercursor *) &encdata,
                                        NULL    // Measure length, no output yet
                                        );
-       uint8_t *encptr = malloc (enclen);
+       uint8_t *encptr = gnutls_malloc (enclen);
        if (encptr == NULL) {
-               free (rawptr);
-               free (decptr);
+               gnutls_free (rawptr);
+               gnutls_free (decptr);
                return GNUTLS_E_MEMORY_ERROR;
        }
        der_pack (                      encdata_packer,
                                        (const dercursor *) &encdata,
                                        encptr + enclen);
-       free (rawptr);
+       gnutls_free (rawptr);
        //
        // Return our final verdict on the generation of the Authenticator
        dec_authenticator->data = decptr;
@@ -2752,6 +2753,7 @@ prange ("srv_C", certs [0].data, certs [0].size);
        dercursor enctransport;
        enctransport.derptr = enc_authenticator->data;
        enctransport.derlen = enc_authenticator->size;
+prangefull ("EncData2unpack", enctransport.derptr, enctransport.derlen);
        memset (&encdata, 0, sizeof (encdata));
        if (0 != der_unpack (           &enctransport,
                                        encdata_packer,
@@ -3441,6 +3443,7 @@ static gtls_error fetch_remote_credentials (struct command *cmd) {
 #ifdef HAVE_TLS_KDH
        cmd->remote_cert_type = gnutls_certificate_type_get_peers (cmd->session);
        certs = gnutls_certificate_get_peers (cmd->session, &num_certs);
+       // Note: server's certs _may_ be DER NULL due to mutual auth in Kerberos
 #else
        cmd->remote_cert_type = gnutls_certificate_type_get (cmd->session);
        certs = gnutls_certificate_get (cmd->session, &num_certs);