#include <syslog.h>
#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-
#include <gnutls/gnutls.h>
#include <gnutls/pkcs11.h>
#include <gnutls/abstract.h>
#include <libtasn1.h>
#include <krb5.h>
+/* Plus, from k5-int.h: */
+krb5_error_code KRB5_CALLCONV krb5_decrypt_tkt_part(krb5_context,
+ const krb5_keyblock *,
+ krb5_ticket * );
+
#include <quick-der/api.h>
#include <quick-der/rfc4120.h>
#ifdef WINDOWS_PORT
#include <winsock2.h>
+#include <ws2tcpip.h>
#else
#include <poll.h>
#include <sys/types.h>
#ifndef __MINGW64__
#include <arpa/inet.h>
#endif
+#include <netinet/in.h>
#endif
#ifdef WINDOWS_PORT
static struct credinfo cli_creds [EXPECTED_CLI_CREDCOUNT];
static int srv_credcount = 0;
static int cli_credcount = 0;
-static const char const *onthefly_p11uri = "pkcs11:manufacturer=ARPA2.net;token=TLS+Pool+internal;object=on-the-fly+signer;type=private;serial=1";
+static const char onthefly_p11uri[] = "pkcs11:manufacturer=ARPA2.net;token=TLS+Pool+internal;object=on-the-fly+signer;type=private;serial=1";
static unsigned long long onthefly_serial; //TODO: Fill with now * 1000
static gnutls_x509_crt_t onthefly_issuercrt = NULL;
static gnutls_privkey_t onthefly_issuerkey = NULL;
static krb5_context krbctx_cli, krbctx_srv;
static krb5_keytab krb_kt_cli, krb_kt_srv;
static bool got_cc_cli, got_cc_srv;
-static int have_key_tgt (
+static int have_key_tgt_cc (
struct command *cmd, // in, session context
krb5_context ctx, // in, kerberos context
bool use_cc, // in, whether to use cc
char *p11uri, // in/opt, PKCS #11 pwd URI
krb5_keytab kt, // in/opt, keytab
krb5_keyblock *key, // opt/opt session key
- krb5_creds *tgt); // out/opt, tkt granting tkt
+ krb5_creds **tgt, // out/opt, tkt granting tkt
+ krb5_ccache *cc); // out/opt, cred cache
static int have_service_ticket (
struct command *cmd, // in, session context
krb5_context ctx, // in, kerberos context
krb5_ccache cc_opt, // in/opt, credcache
krb5_principal cli, // in, client principal
- krb5_creds *ticket); // out/opt, tkt granting tkt
+ krb5_creds **ticket);// out/opt, tkt granting tkt
#endif
return GNUTLS_E_PKCS11_TOKEN_ERROR;
}
}
-
+
/*
* Implement the GnuTLS function for PIN callback. This function calls
setup_starttls_credentials ());
//
// Parse the default priority string
- E_g2e ("Failed to setup NORMAL priority cache",
- gnutls_priority_init (&priority_normal, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+COMP-NULL:"
#ifdef HAVE_TLS_KDH
- "%%ASYM_CERT_TYPES:"
+ E_g2e ("Failed to setup NORMAL priority cache",
+ gnutls_priority_init (&priority_normal,
+ "NONE:"
+ "%ASYM_CERT_TYPES:"
+ "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
+ "+COMP-NULL:"
+ "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
+ "+ANON-ECDH:"
+ "+ECDHE-KRB:" // +ECDHE-KRB-RSA:+ECDHE-KRB-ECDSA:"
+ "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:"
+ "+CTYPE-SRV-KRB:+CTYPE-SRV-X.509:+CTYPE-SRV-OPENPGP:"
+ "+CTYPE-CLI-KRB:+CTYPE-CLI-X.509:+CTYPE-CLI-OPENPGP:"
+ "+SRP:+SRP-RSA:+SRP-DSS",
+ NULL));
+#else
+ E_g2e ("Failed to setup NORMAL priority cache",
+ gnutls_priority_init (&priority_normal,
+ "NONE:"
+ "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
+ "+COMP-NULL:+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
+ "+ANON-ECDH:"
+ "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:"
+ "+CTYPE-X.509:+CTYPE-OPENPGP:"
+ "+SRP:+SRP-RSA:+SRP-DSS",
+ NULL));
#endif
- "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:+ANON-ECDH:+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
- // gnutls_priority_init (&priority_normal, "NORMAL:-RSA:+ANON-ECDH:+RSA:+CTYPE-X.509:+CTYPE-OPENPGP:+SRP:+SRP-RSA:+SRP-DSS", NULL));
//
// Try to setup on-the-fly signing key / certificate and gen a certkey
otfsigcrt = cfg_tls_onthefly_signcert ();
GNUTLS_E_FILE_ERROR);
} else {
gnutls_datum_t cd = {
- .data = crt,
+ .data = (unsigned char *)(&crt[0]),
.size = len
};
fprintf (stderr, "DEBUG: gtls_errno==%d before importing onthefly_issuercrt\n", gtls_errno);
char *rolestr;
char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.localid)];
size_t snilen = sizeof (sni);
- int snitype;
+ unsigned int snitype;
int ok;
uint32_t flags;
char *p11priv;
//
// Setup a number of common references and structures
+ errno = 0;
*pcert = NULL;
cmd = (struct command *) gnutls_session_get_ptr (session);
if (cmd == NULL) {
#endif
} else {
// GNUTLS_CRT_RAW, GNUTLS_CRT_UNKNOWN, or other
- tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate retrieval attempted as a %s", rolestr);
+ tlog (TLOG_TLS, LOG_ERR, "Funny sort of certificate %d retrieval attempted as a %s", certtp, rolestr);
E_g2e ("Requested certtype is neither X.509 nor OpenPGP",
GNUTLS_E_CERTIFICATE_ERROR);
return gtls_errno;
//
// First, try to obtain a TGT and key, in various ways
krb5_keyblock key;
- krb5_creds tgt;
- int status;
- memset (&key, 0, sizeof (key));
- memset (&tgt, 0, sizeof (tgt));
- status = have_key_tgt (
+ krb5_creds *tgt = NULL;
+ krb5_creds *ticket = NULL;
+ krb5_ccache cc = NULL;
+ int status = 0;
+ memset (&key, 0, sizeof (key ));
+ status = have_key_tgt_cc (
cmd, krbctx_cli,
1, 0, 0,
p11priv,
krb_kt_cli,
- &key, &tgt);
+ &key, &tgt, &cc);
if (status >= 1) {
// We never use this key ourselves
krb5_free_keyblock_contents (krbctx_cli, &key);
break;
}
//
- // Now find a service ticket to talk to
+ // Store client identity in session object
+ if (0 != krb5_copy_principal (
+ krbctx_cli,
+ tgt->client,
+ &cmd->krbid_cli)) {
+ krb5_free_creds (krbctx_cli, tgt);
+ tgt = NULL;
+ if (cc != NULL) {
+ krb5_cc_close (krbctx_cli, cc);
+ cc = NULL;
+ }
+ gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
+ break;
+ }
+ //
+ // Now find a service ticket to talk to, and its key
//TODO// Pass credcache instead?
status = have_service_ticket (
cmd, krbctx_cli,
- NULL, //TODO// Should get cc from have_key_tgt()
- tgt.client,
- &cmd->krb_tkt);
- krb5_free_cred_contents (krbctx_cli, &tgt);
+ cc,
+ cmd->krbid_cli,
+ &ticket);
+ if (cc != NULL) {
+ // We don't need cc anymore below
+ krb5_cc_close (krbctx_cli, cc);
+ }
if (status < 1) {
// Stop processing when no ticket was found
+ krb5_free_creds (krbctx_cli, tgt);
+ tgt = NULL;
gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
break;
}
- certdatum.data = cmd->krb_tkt.ticket.data;
- certdatum.size = cmd->krb_tkt.ticket.length;
+ //
+ // Only for KDH-Only mode can the client rely on a
+ // server principal taken from the ticket;
+ // So only store krbid_srv for KDH-Only mode.
+ if ((gnutls_certificate_type_get_peers (cmd->session)
+ == GNUTLS_CRT_KRB) &&
+ (0 != krb5_copy_principal (
+ krbctx_cli,
+ tgt->server,
+ &cmd->krbid_srv))) {
+ krb5_free_creds (krbctx_cli, ticket);
+ gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
+ break;
+ }
+ krb5_free_creds (krbctx_cli, tgt);
+ tgt = NULL;
+ if (0 != krb5_copy_keyblock_contents (
+ krbctx_cli,
+ &ticket->keyblock,
+ &cmd->krb_key)) {
+ gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
+ // continue, with E_g2e() skipping import
+ }
+ certdatum.data = ticket->ticket.data;
+ certdatum.size = ticket->ticket.length;
E_g2e ("MOVED: Failed to import Kerberos ticket",
gnutls_pcert_import_krb_raw (
*pcert,
&certdatum,
0));
+ krb5_free_creds (krbctx_cli, ticket);
} 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,
//TODO// &certdatum, //TODO:WHATSFOUND//
//TODO// 0));
int u2u = 0;
- int status;
+ int status = 0;
+ krb5_creds *tgt = NULL;
//
// Determine whether we want to run in user-to-user mode
// for which we should supply a TGT to the TLS client
// 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;
+ static unsigned char der_null_data[] = "\x05\x00";
+ certdatum.data = der_null_data;
+ certdatum.size = 2;
E_g2e ("Failed to withhold Kerberos server ticket",
gnutls_pcert_import_krb_raw (
*pcert,
}
//
// Continue specifically for user-to-user mode.
+ //TODO// Setup server principal identity
//
// Fetch the service's key
- status = have_key_tgt (
+ status = have_key_tgt_cc (
cmd, krbctx_srv,
1, 0, 0, // Hmm... later we know kvno/etype
p11priv,
krb_kt_srv,
- &cmd->krb_key, &cmd->krb_tkt);
+ &cmd->krb_key, &tgt, NULL);
if (status == 1) {
// There's no use in having just the key
krb5_free_keyblock_contents (krbctx_srv, &cmd->krb_key);
+ memset (&cmd->krb_key, 0, sizeof (cmd->krb_key));
}
if (status < 2) {
gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
- break;
+ } else if (0 != krb5_copy_principal (
+ krbctx_srv,
+ tgt->server,
+ &cmd->krbid_srv)) {
+ gtls_errno = GNUTLS_E_NO_CERTIFICATE_FOUND;
}
- certdatum.data = cmd->krb_tkt.ticket.data;
- certdatum.size = cmd->krb_tkt.ticket.length;
+ certdatum.data = tgt->ticket.data;
+ certdatum.size = tgt->ticket.length;
E_g2e ("Failed to withhold Kerberos server ticket",
gnutls_pcert_import_krb_raw (
*pcert,
&certdatum,
0));
+ krb5_free_creds (krbctx_cli, tgt);
+ tgt = NULL;
}
break;
#endif
//TODO// Moved out (end)
+#ifdef ANCIENT_CODE_WHEN_DBERRNO_RAN_IN_PARALLEL
//
// Lap up any overseen POSIX error codes in errno
if (errno) {
cmd->session_errno = errno;
gtls_errno = GNUTLS_E_NO_CIPHER_SUITES; /* Vaguely matching */
}
+#endif
//
// Return the overral error code, hopefully GNUTLS_E_SUCCESS
tlog (TLOG_TLS, LOG_DEBUG, "Returning %d / %s from clisrv_cert_retrieve()", gtls_errno, gnutls_strerror (gtls_errno));
-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);
+fprintf (stderr, "DEBUG: clisrv_cert_retrieve() sets *pcert to 0x%lx (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);
return gtls_errno;
}
NULL, /* use master key */
0));
break;
+ case LID_TYPE_KRB5:
+ /* Binary information is currently moot, so do not load it */
+ break;
default:
/* Should not happen */
break;
long nextlen;
// Note: Accept BER because the outside SEQUENCE is not signed
certlen = asn1_get_length_ber (
- ((char *) certdatum->data) + 1,
+ (certdatum->data) + 1,
certdatum->size,
&lenlen);
certlen += 1 + lenlen;
*chainlen = 0;
return NULL;
}
- nextdatum.data = ((char *) certdatum->data) + certlen;
- nextdatum.size = certdatum->size - certlen;
+ nextdatum.data = (certdatum->data) + certlen;
+ nextdatum.size = certdatum->size - certlen;
certdatum->size = certlen;
nextlen = asn1_get_length_ber (
- ((char *) nextdatum.data) + 1,
+ nextdatum.data + 1,
nextdatum.size,
&lenlen);
nextlen += 1 + lenlen;
}
+
+/********** KERBEROS SUPPORT FUNCTIONS FOR TLS-KDH **********/
+
+
+
/* Prepare the Kerberos resources for use by clients and/or servers.
*/
#ifdef HAVE_TLS_KDH
k5err = krb5_kt_resolve (krbctx_srv, cfg, &krb_kt_srv);
}
cfg = cfg_krb_client_credcache ();
+#if 0 /* Temporary bypass of cctype checks */
if ((k5err == 0) && (cfg != NULL)) {
k5err = krb5_cc_set_default_name (krbctx_cli, cfg);
if (k5err == 0) {
krb5_cc_close (krbctx_cli, krb_cc_tmp);
}
}
+#endif
cfg = cfg_krb_server_credcache ();
+#if 0 /* Temporary bypass of cctype checks */
if ((k5err == 0) && (cfg != NULL)) {
k5err = krb5_cc_set_default_name (krbctx_srv, cfg);
if (k5err == 0) {
krb5_cc_close (krbctx_srv, krb_cc_tmp);
}
}
+#endif
//
// Check for consistency and log helpful messages for the sysop
if (k5err != 0) {
tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "No kerberos_server_keytab configured, so Kerberos cannot work at all");
retval = GNUTLS_E_UNWANTED_ALGORITHM;
/* TODO: Only for MIT krb5 1.11 and up
- } else if (0 == krb5_kt_have_content (krb_ctx, krb_kt_cli)) {
- tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Keytab in kerberos_client_keytab is absent or empty");
+ } else if (0 == krb5_kt_have_content (krb_ctx, krb_kt_srv)) {
+ tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Keytab in kerberos_server_keytab is absent or empty");
retval = GNUTLS_E_UNWANTED_ALGORITHM;
*/
}
if (krbctx_cli == NULL) {
tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "No kerberos_client_credcache configured, so Kerberos cannot work at all");
retval = GNUTLS_E_UNWANTED_ALGORITHM;
+#if 0 /* Temporary bypass of cctype checks */
} else if (!krb5_cc_support_switch (
krbctx_cli, cctype_cli)) {
tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Your kerberos_client_credcache does not support multilpe identities");
retval = GNUTLS_E_UNWANTED_ALGORITHM;
+#endif
}
if (krbctx_srv == NULL) {
tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_WARNING, "No kerberos_server_credcache configured, so user-to-user Kerberos will not work");
+#if 0 /* Temporary bypass of cctype checks */
} else if (!krb5_cc_support_switch (
krbctx_srv, cctype_srv)) {
tlog (TLOG_DAEMON | TLOG_KERBEROS, LOG_ERR, "Your kerberos_server_credcache does not support multilpe identities");
retval = GNUTLS_E_UNWANTED_ALGORITHM;
+#endif
}
if (retval != GNUTLS_E_SUCCESS) {
cleanup_starttls_kerberos ();
/* Cleanup Kerberos resources. This must be an idempotent function, because
- * it is called when Kerberos panics as well as when
+ * it is called when Kerberos panics as well as when
*/
#ifdef HAVE_TLS_KDH
static void cleanup_starttls_kerberos (void) {
#endif
-
-/********** KERBEROS SUPPORT FUNCTIONS FOR TLS-KDH **********/
-
-
-
/* Prompter callback function for PKCS #11.
*
* TODO: Use "struct pkcs11iter" as data, possibly interact with the user,
* so 0 means error, 1 means key only and 2 means key and tgt.
*/
#ifdef HAVE_TLS_KDH
-static int have_key_tgt (struct command *cmd, // in, session context
+static int have_key_tgt_cc (struct command *cmd, // in, session context
krb5_context ctx, // in, kerberos context
bool use_cc, // in, whether to use cc
krb5_kvno kvno, // in, kvno (0 for highest)
char *p11uri, // in/opt, PKCS #11 pwd URI
krb5_keytab kt, // in/opt, keytab
krb5_keyblock *key, // opt/opt session key
- krb5_creds *tgt) { // out/opt, tkt granting tkt
+ krb5_creds **tgt, // out/opt, tkt granting tkt
+ krb5_ccache *cc) { // out/opt, cred cache
int k5err = 0;
- krb5_ccache cc = NULL;
+ krb5_ccache newcc = NULL;
krb5_principal sought = NULL;
+ krb5_principal sought1 = NULL;
krb5_principal tgtname = NULL;
krb5_keytab_entry ktentry;
const char *svc = cmd->cmd.pio_data.pioc_starttls.service;
time_t now = 0;
//
// Assertions, and initialise variables
- assert (cmd != NULL);
- assert (ctx != NULL);
- assert (key != NULL);
- assert (tgt != NULL);
+ assert ( cmd != NULL);
+ assert ( ctx != NULL);
+ assert ( key != NULL);
+ assert (*tgt == NULL);
krb5_free_keyblock_contents (ctx, key);
- krb5_free_cred_contents (ctx, tgt);
+ if (cc != NULL) {
+ *cc = NULL;
+ }
//
// Construct the realm name
liddom = strrchr (lid, '@');
lid1len = strnlen (lid, 128);
}
k5err = krb5_get_host_realm (ctx, liddom, &realms);
- if ((k5err == 0) && (realms [0] != NULL) && (**realms != '\0')) {
+ if ((k5err == 0) && (realms [0] != NULL) && (*realms [0] != '\0')) {
strncpy (realm, realms [0], sizeof (realm));
realm [sizeof (realm)-1] = '\0';
} else {
strlen (realm), realm,
strnlen (lid, 128), lid,
0);
+ break;
case KRB5_NT_SRV_HST:
if (strcmp (svc, "http") == 0) {
svc = "HTTP";
} else {
sought = NULL;
}
- k5err = krb5_cc_cache_match (ctx, sought, &cc);
- if (sought != NULL) {
- krb5_free_principal (ctx, sought);
- sought = NULL;
- }
+ k5err = krb5_cc_cache_match (ctx, sought, &newcc);
if (k5err != 0) {
- if (nametype_alt != nametype) {
+ if ((nametype_alt != nametype) && (sought1 == NULL)) {
nametype = nametype_alt;
+ sought1 = sought;
+ sought = NULL;
goto retry;
}
- // We utterly failed
- goto cleanup;
+ //
+ // We failed to find an *existing* credentials cache
+ // for the local identity.
+ //
+ // Our new hope is to create a fresh credential, and add
+ // it to the current credcache. To that end, we now try
+ // to overrule k5err by getting hold of our default cc.
+ goto from_scratch;
}
//
// Construct the TGT name
- k5err = krb5_build_principal (ctx, &tgtname,
+ k5err = krb5_build_principal_ext (ctx, &tgtname,
strlen (realm), realm,
6, "krbtgt",
strlen (realm), realm,
//
// Try to get the service ticket for the TGT name from the cache
krb5_creds credreq;
+ memset (&credreq, 0, sizeof (credreq));
+ credreq.client = sought;
+ credreq.server = tgtname;
k5err = krb5_get_credentials (ctx,
/* KRB5_GC_USER_USER ?|? */
( use_cc ? 0 : KRB5_GC_CACHED ),
- cc,
- &credreq, &tgt);
+ newcc,
+ &credreq, tgt);
time (&now);
if ((k5err == 0)
- && (now + 300 > tgt->times.endtime)
- && (now + 300 < tgt->times.renew_till)) {
- krb5_free_creds (ctx, tgt);
+ && (now + 300 > (*tgt)->times.endtime)
+ && (now + 300 < (*tgt)->times.renew_till)) {
+ //TODO:NOTHERE// krb5_free_creds (ctx, *tgt);
+ //TODO:NOTHERE// *tgt = NULL;
// Try to renew the ticket
k5err = krb5_get_renewed_creds (ctx,
- tgt,
+ *tgt,
sought,
- cc,
+ newcc,
NULL); /* krbtgt/REALM@REALM */
}
if ((k5err == 0)
- && (now + 300 > tgt->times.endtime)) {
+ && (now + 300 > (*tgt)->times.endtime)) {
// Thanks, but no thanks!
- krb5_free_creds (ctx, tgt);
+ krb5_free_creds (ctx, *tgt);
+ *tgt = NULL;
k5err = 666;
}
if (k5err == 0) {
// First case worked -- return <key,tgt> from credout
k5err = krb5_copy_keyblock_contents (ctx,
- &tgt->keyblock,
+ &(*tgt)->keyblock,
key);
// On failure, key shows failure
+ if (cc != NULL) {
+ *cc = newcc;
+ newcc = NULL;
+ }
goto cleanup;
}
+from_scratch:
//
- // Prior attempts failed. Instead, look for keytab presence.
+ // Prior attempts failed. Instead, look for keytab or p11uri presence.
// This is skipped when the use_cc option below welcomes krb5_creds.
- if ((key->contents == NULL) && (p11uri == NULL)) {
+ if ((key->contents == NULL) && (p11uri == NULL) && (kt == NULL)) {
// We cannot obtain a new krbtgt
// We simply return what we've got (which may be nothing)
goto cleanup;
}
- if (!use_cc) {
+ if ((kt == NULL) && (!use_cc)) {
// We have nowhere to store a new krbtgt if we got it
// We simply return what we've got (which is at least a key)
goto cleanup;
// Either we have a keytab key, or we have a p11uri,
// so we can attempt to create a new credcache with a new krbtgt
if (use_cc) {
- if (cc == NULL) {
- k5err = krb5_cc_default (ctx, &cc);
+ if (newcc == NULL) {
+ k5err = krb5_cc_default (ctx, &newcc);
if (k5err != 0) {
// Utter failure to do even the simplest thing
goto cleanup;
}
}
- if (p11uri == NULL) {
- k5err = krb5_get_init_creds_keytab (
- ctx,
- tgt,
- sought, //TODO:KEEP
- kt,
- 0, /* start now please */
- NULL, /* get a TGT please */
- NULL); //TODO// opts needed?
- } else {
- //TODO// Prepare PKCS #11 access
- k5err = krb5_get_init_creds_password (
- ctx,
- tgt,
- sought, //TODO:KEEP
- NULL, // Use callbacks for password
- clisrv_p11krb_callback,
- cmd, /* callback data pointer */
- 0, /* start now please */
- NULL, /* get a TGT please */
- NULL); //TODO// opts needed?
- //TODO// End PKCS #11 access
+ *tgt = malloc (sizeof (**tgt));
+ if (*tgt == NULL) {
+ // Memory error
+ goto cleanup;
}
- if (k5err == 0) {
- krb5_copy_keyblock_contents (ctx,
- &ktentry.key,
- key);
- // Failure will show up in key
+ memset (*tgt, 0, sizeof (**tgt));
+ if ((sought != NULL) && (sought1 == NULL)) {
+ // We only tried one name
+ sought1 = sought;
+ sought = NULL;
}
+ do {
+ if (sought1 == NULL) {
+ break;
+ }
+ if (p11uri == NULL) {
+ k5err = krb5_get_init_creds_keytab (
+ ctx,
+ *tgt,
+ sought1,
+ kt,
+ 0, /* start now please */
+ NULL, /* get a TGT please */
+ NULL); //TODO// opts needed?
+ } else {
+ //TODO// Prepare PKCS #11 access
+ k5err = krb5_get_init_creds_password (
+ ctx,
+ *tgt,
+ sought1,
+#ifdef TOM_IS_WEG
+ NULL, // Use callbacks for password
+ clisrv_p11krb_callback,
+#else
+ "1234",
+ NULL,
+#endif
+ cmd, /* callback data pointer */
+ 0, /* start now please */
+ NULL, /* get a TGT please */
+ NULL); //TODO// opts needed?
+ //TODO// End PKCS #11 access
+ }
+ krb5_free_principal (ctx, sought1);
+ sought1 = sought;
+ sought = NULL;
+ } while (k5err != 0);
if (k5err != 0) {
// Failed to initiate new credentials
+ krb5_free_creds (ctx, *tgt);
+ *tgt = NULL;
goto cleanup;
}
+ // Try to store the credential, if it was found
+ if (sought1 != NULL) {
+ k5err = krb5_cc_initialize (ctx, newcc, sought1);
+ if (k5err == 0) {
+ k5err = krb5_cc_store_cred (ctx, newcc, *tgt);
+ }
+ }
+ // Copy the keyblock; any failure will show up in key
+ krb5_copy_keyblock_contents (ctx,
+ &(*tgt)->keyblock, //TODO:UNINIT// &ktentry.key,
+ key);
//
// We succeeded in setting up a new Ticket Granting Ticket!
+ if (cc != NULL) {
+ *cc = newcc;
+ newcc = NULL;
+ }
goto cleanup;
}
//
key);
krb5_free_keytab_entry_contents (ctx, &ktentry);
// On failure, key shows failure.
+ if (cc != NULL) {
+ *cc = newcc;
+ newcc = NULL;
+ }
goto cleanup;
}
}
cleanup:
//
// Cleanup and return the <key,tgt> values as they were delivered
+ if (sought1 != NULL) {
+ krb5_free_principal (ctx, sought1);
+ sought1 = NULL;
+ }
+ if (sought != NULL) {
+ krb5_free_principal (ctx, sought);
+ sought = NULL;
+ }
if (tgtname != NULL) {
krb5_free_principal (ctx, tgtname);
tgtname = NULL;
}
- if (cc != NULL) {
- krb5_cc_close (ctx, cc);
+ if (newcc != NULL) {
+ krb5_cc_close (ctx, newcc);
+ newcc = NULL;
}
if (key->contents == NULL) {
+ if (k5err != 0) {
+ const char *errmsg = krb5_get_error_message (ctx, k5err);
+ tlog (TLOG_DAEMON, LOG_ERR, "Kerberos error in have_key_tgt_cc: %s", errmsg);
+ krb5_free_error_message (ctx, errmsg);
+ }
+ if (*tgt != NULL) {
+ krb5_free_creds (ctx, *tgt);
+ *tgt = NULL;
+ }
+ if ((cc != NULL) && (*cc != NULL)) {
+ krb5_cc_close (ctx, *cc);
+ *cc = NULL;
+ }
return 0;
- } else if (tgt->ticket.data == NULL) {
+ } else if (tgt == NULL) {
+ if ((cc != NULL) && (*cc != NULL)) {
+ krb5_cc_close (ctx, *cc);
+ *cc = NULL;
+ }
return 1;
- } else {
+ } else if ((cc == NULL) || (*cc == NULL)) {
return 2;
+ } else {
+ return 3;
}
}
#endif
krb5_context ctx, // in, kerberos context
krb5_ccache cc_opt, // in/opt, credcache
krb5_principal cli, // in, client principal
- krb5_creds *ticket) { // out, tkt granting tkt
+ krb5_creds **ticket) {// out, tkt granting tkt
int k5err = 0;
krb5_ccache cc = cc_opt;
krb5_flags u2u = 0;
// Sanity checks and initialisation
memset (&tkt_srv, 0, sizeof (tkt_srv));
memset (&credreq, 0, sizeof (credreq));
+ *ticket = NULL;
//
// Determine the optional cc parameter if it was not provided
- //TODO// This can go if we always get it passed from have_key_tgt()
+ //TODO// This can go if we always get it passed from have_key_tgt_cc()
if (cc == NULL) {
k5err = krb5_cc_cache_match (ctx, cli, &cc);
if (k5err != 0) {
riddom = rid; // localid is a host
}
k5err = krb5_get_host_realm (ctx, riddom, &realms);
- if ((k5err == 0) && (realms [0] != NULL) && (**realms != '\0')) {
+ if ((k5err == 0) && (realms [0] != NULL) && (*realms [0] != '\0')) {
strncpy (realm, realms [0], sizeof (realm));
realm [sizeof (realm)-1] = '\0';
} else {
// - we are sure of GNUTLS_CRD_CERTIFICATE because we implement it now
// - we must ensure that this is KDH-Only (remote GNUTLS_CRT_KRB)
// - we must ensure that the remote provided a non-empty ticket
- if (gnutls_certificate_type_get (cmd->session) == GNUTLS_CRT_KRB) {
- // This is KDH-Only
- const gnutls_datum_t *peer_tkt;
- unsigned int peer_tkt_count;
- peer_tkt = gnutls_certificate_get_peers (cmd->session, &peer_tkt_count);
- if ((peer_tkt != NULL) && (peer_tkt_count >= 1) && (peer_tkt [0].size > 5)) {
+ if (gnutls_certificate_type_get_peers (cmd->session) == GNUTLS_CRT_KRB) {
+ // This is KDH-Only -- and the server may present a TGT
+ const gnutls_datum_t *opt_srv_tkt;
+ unsigned int srv_tkt_count;
+ opt_srv_tkt = gnutls_certificate_get_peers (cmd->session, &srv_tkt_count);
+ if ((opt_srv_tkt != NULL) && (srv_tkt_count >= 1) && (opt_srv_tkt [0].size > 5)) {
// Looks good, we'll use only the first (normally only) one
- credreq.second_ticket.data = peer_tkt [0].data;
- credreq.second_ticket.length = peer_tkt [0].size;
+ credreq.second_ticket.data = opt_srv_tkt [0].data;
+ credreq.second_ticket.length = opt_srv_tkt [0].size;
u2u = KRB5_GC_USER_USER;
}
}
//
// Fetch the ticket for the service
- k5err = krb5_get_credentials (ctx, u2u, cc, &credreq, &ticket);
+ k5err = krb5_get_credentials (ctx, u2u, cc, &credreq, ticket);
//
// Cleanup and return; the return value depends on k5err
cleanup:
if ((cc != NULL) && (cc_opt == NULL)) {
- //TODO// This can go if we always get it passed from have_key_tgt()
+ //TODO// This can go if we always get it passed from have_key_tgt_cc()
krb5_cc_close (ctx, cc);
cc = NULL;
}
// Skip sign-extending initial bytes
uint32_t neutro = (value >> (shift - 1) ) & 0x000001ff;
if ((neutro == 0x000001ff) || (neutro == 0x00000000)) {
+ shift -= 8;
continue;
}
}
}
+#ifdef HAVE_TLS_KDH
+/* TODO: Debugging function for printing (descr,ptr,len) ranges */
+static inline void prange (char *descr, uint8_t *ptr, int len) {
+ fprintf (stderr, "%s #%04d: %02x %02x %02x %02x %02x %02x %02x %02x...%02x %02x %02x %02x\n",
+ descr, len,
+ ptr [0], ptr [1], ptr [2], ptr [3],
+ ptr [4], ptr [5], ptr [6], ptr [7],
+ ptr [len-4], ptr [len-3], ptr [len-2], ptr [len-1]);
+}
+static inline void prangefull (char *descr, uint8_t *ptr, int len) {
+ fprintf (stderr, "%s #%04d:", descr, len);
+ while (len-- > 0) {
+ fprintf (stderr, " %02x", *ptr++);
+ }
+ fprintf (stderr, "\n");
+}
+#endif
+
+
/* The callback function that retrieves a TLS-KDH "signature", which is kept
* outside of GnuTLS. The callback computes an authenticator encrypted to
* the session's Kerberos key.
*/
#ifdef HAVE_TLS_KDH
-gtls_error cli_kdhsig_encode (gnutls_session_t session,
+static gtls_error cli_kdhsig_encode (gnutls_session_t session,
gnutls_datum_t *enc_authenticator,
gnutls_datum_t *dec_authenticator,
const gnutls_datum_t *hash,
cmd = (struct command *) gnutls_session_get_ptr (session);
memset (&auth, 0, sizeof (auth));
memset (&subkey, 0, sizeof (subkey));
- assert (cmd->krb_tkt.client != NULL);
+ assert (cmd->krbid_cli != NULL);
assert (cmd->krb_key.contents != NULL);
+ static const uint8_t auth_packer [] = {
+ DER_PACK_rfc4120_Authenticator, DER_PACK_END };
+ static const uint8_t encdata_packer [] = {
+ DER_PACK_rfc4120_EncryptedData, DER_PACK_END };
//
// Setup secure hash in authenticator (never optional for TLS-KDH)
auth.cksum.cksumtype = qder2b_pack_int32 (dercksumtype, checksum_type);
+ auth.cksum.checksum.derptr = hash->data;
+ auth.cksum.checksum.derlen = hash->size;
//
// Optionally include a subkey (namely, for KDH-Only)
peercert = gnutls_certificate_type_get_peers (session);
ENCTYPE_AES256_CTS_HMAC_SHA1_96,
&subkey);
if (k5err != 0) {
- return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
+ return GNUTLS_E_ENCRYPTION_FAILED;
}
auth.subkey.keytype = qder2b_pack_int32 (dersubkey, subkey.enctype);
auth.subkey.keyvalue.derptr = subkey.contents;
auth.subkey.keyvalue.derlen = subkey.length;
+prange ("cli_K", subkey.contents, subkey.length);
}
//
// Setup the client realm and principal name
- auth.crealm.derptr = cmd->krb_tkt.client->realm.data;
- auth.crealm.derlen = cmd->krb_tkt.client->realm.length;
- auth.cname.name_type = qder2b_pack_int32 (dernametype, cmd->krb_tkt.client->type);
+ auth.crealm.derptr = cmd->krbid_cli->realm.data;
+ auth.crealm.derlen = cmd->krbid_cli->realm.length;
+ auth.cname.name_type = qder2b_pack_int32 (dernametype, cmd->krbid_cli->type);
// The SEQUENCE OF with just one component is trivial to prepack
- auth.cname.name_string.derptr = cmd->krb_tkt.client->data [0].data;
- auth.cname.name_string.derlen = cmd->krb_tkt.client->data [0].length;
+ auth.cname.name_string.derptr = cmd->krbid_cli->data [0].data;
+ auth.cname.name_string.derlen = cmd->krbid_cli->data [0].length;
//
// Setup the Kerberos version number (5)
auth.authenticator_vno = qder2b_pack_int32 (derv5, 5);
auth.cusec = qder2b_pack_int32 (dercusec, now_us);
//
// Pack the decoded result into dec_authenticator
- uint8_t auth_packer [] = { DER_PACK_rfc4120_Authenticator };
size_t declen = der_pack ( auth_packer,
(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;
}
der_pack ( auth_packer,
(const dercursor *) &auth,
- decptr);
+ decptr + declen);
+ krb5_free_keyblock_contents (krbctx_cli, &subkey);
+prangefull ("cli_A", decptr, declen);
size_t rawlen;
if (0 != krb5_c_encrypt_length (krbctx_cli,
- cmd->krb_tkt.keyblock.enctype,
+ cmd->krb_key.enctype,
declen,
&rawlen)) {
- return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
+ 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;
krb5_enc_data rawdata;
memset (&decdata, 0, sizeof (decdata));
+ memset (&rawdata, 0, sizeof (rawdata));
decdata.data = decptr;
decdata.length = declen;
rawdata.ciphertext.data = rawptr;
rawdata.ciphertext.length = rawlen;
if (0 != krb5_c_encrypt ( krbctx_cli,
- &cmd->krb_tkt.keyblock,
+ &cmd->krb_key,
11 /* stealing key usage from AP-REQ */,
NULL,
&decdata,
&rawdata)) {
- return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
+ gnutls_free (rawptr);
+ gnutls_free (decptr);
+ return GNUTLS_E_ENCRYPTION_FAILED;
}
//
// Prepare the header information
QDERBUF_INT32_T deretype;
QDERBUF_UINT32_T derkvno;
encrypted_data_t encdata;
- encdata.etype = qder2b_pack_int32 (deretype, cmd->krb_tkt.keyblock.enctype);
- //NOT// encdata.kvno = qder2b_pack_int32 (derkvno, cmd->krb_tkt.keyblock.kvno);
+ 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;
encdata.cipher.derlen = rawdata.ciphertext.length;
//
// Prepare for packing the header and rawdata as EncryptedData
- uint8_t encdata_packer [] = { DER_PACK_rfc4120_EncryptedData };
size_t enclen = der_pack ( encdata_packer,
(const dercursor *) &encdata,
NULL // Measure length, no output yet
);
- uint8_t *encptr = malloc (enclen);
+ uint8_t *encptr = gnutls_malloc (enclen);
if (encptr == NULL) {
+ gnutls_free (rawptr);
+ gnutls_free (decptr);
return GNUTLS_E_MEMORY_ERROR;
}
der_pack ( encdata_packer,
(const dercursor *) &encdata,
- encptr);
- free (rawptr);
+ encptr + enclen);
+ gnutls_free (rawptr);
//
// Return our final verdict on the generation of the Authenticator
dec_authenticator->data = decptr;
dec_authenticator->size = declen;
enc_authenticator->data = encptr;
enc_authenticator->size = enclen;
+prange ("cli_D", decptr, declen);
+prange ("cli_E", encptr, enclen);
return 0;
}
#endif
* provided session hash and returns the decrypted authenticator.
*/
#ifdef HAVE_TLS_KDH
-int srv_kdhsig_decode (gnutls_session_t session,
+static int srv_kdhsig_decode (gnutls_session_t session,
const gnutls_datum_t *enc_authenticator,
gnutls_datum_t *dec_authenticator,
gnutls_datum_t *hash,
int32_t *checksum_type) {
- return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
+ //
+ // Variables, sanity checks and initialisation
+ int k5err = 0;
+ struct command *cmd;
+ static const uint8_t encdata_packer [] = {
+ DER_PACK_rfc4120_EncryptedData, DER_PACK_END };
+ static const uint8_t auth_packer [] = {
+ DER_PACK_rfc4120_Authenticator, DER_PACK_END };
+ encrypted_data_t encdata;
+ cmd = (struct command *) gnutls_session_get_ptr (session);
+prange ("srv_E", enc_authenticator->data, enc_authenticator->size);
+ //
+ // Retrieve the session key and store it in cmd->krb_key.
+ //
+ // Prior setting of cmd->krb_key would be due to user-to-user mode
+ // having been setup with this as the server-supplied TGT key, in
+ // which case cmd->krb_key would need to be overwritten by the
+ // session key.
+ //
+ // When no prior cmd->krb_key is available, use the keytab to
+ // decode the client's ticket.
+ assert (gnutls_certificate_type_get_peers (session) == GNUTLS_CRT_KRB);
+ const gnutls_datum_t *certs;
+ unsigned int num_certs;
+ certs = gnutls_certificate_get_peers (cmd->session, &num_certs);
+ if (num_certs != 1) {
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+ krb5_data krbcert;
+ krb5_ticket *tkt;
+ krbcert.data = certs [0].data;
+ krbcert.length = certs [0].size;
+prange ("srv_C", certs [0].data, certs [0].size);
+ if (0 != krb5_decode_ticket (&krbcert, &tkt)) {
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+ if (cmd->krb_key.contents != NULL) {
+ // user-to-user mode
+ k5err = krb5_decrypt_tkt_part (
+ krbctx_srv,
+ &cmd->krb_key,
+ tkt);
+ krb5_free_keyblock_contents (
+ krbctx_srv,
+ &cmd->krb_key);
+ } else {
+ // client-to-server mode
+ k5err = krb5_server_decrypt_ticket_keytab (
+ krbctx_srv,
+ krb_kt_srv,
+ tkt);
+ }
+ if (k5err == 0) {
+ k5err = krb5_copy_keyblock_contents (
+ krbctx_srv,
+ tkt->enc_part2->session,
+ &cmd->krb_key);
+ }
+ if (k5err == 0) {
+ k5err = krb5_copy_principal (
+ krbctx_srv,
+ tkt->enc_part2->client,
+ &cmd->krbid_cli);
+ }
+ if (k5err == 0) {
+ if (cmd->krbid_srv != NULL) {
+ k5err = krb5_principal_compare (
+ krbctx_srv,
+ tkt->server,
+ cmd->krbid_srv);
+ // Server name changed since u2u setup => k5err
+ } else {
+ k5err = krb5_copy_principal (
+ krbctx_srv,
+ tkt->server,
+ &cmd->krbid_srv);
+ }
+ }
+ krb5_free_ticket (krbctx_srv, tkt);
+ if (k5err != 0) {
+ const char *errmsg = krb5_get_error_message (krbctx_srv, k5err);
+ tlog (TLOG_DAEMON, LOG_ERR, "Kerberos error in srv_kdhsig_decode: %s", errmsg);
+ krb5_free_error_message (krbctx_srv, errmsg);
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+ //
+ // Harvest the EncryptedData fields from the enc_authenticator
+ 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,
+ (dercursor *) &encdata,
+ 1)) {
+ tlog (TLOG_DAEMON, LOG_ERR, "Failed to der_unpack(EncryptedData) in server: %s", strerror (errno));
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ if (encdata.kvno.derptr != NULL) {
+ //TODO//NOTYET//ANDWHY// return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ int32_t etype = qder2b_unpack_int32 (encdata.etype);
+ //
+ // Decrypt the EncryptedData fields into the dec_authenticator
+ krb5_enc_data rawdata;
+ krb5_data decdata;
+ memset (&rawdata, 0, sizeof (rawdata));
+ memset (&decdata, 0, sizeof (decdata));
+ rawdata.enctype = etype;
+ rawdata.ciphertext.data = encdata.cipher.derptr;
+ rawdata.ciphertext.length = encdata.cipher.derlen;
+prange ("srv_R", encdata.cipher.derptr, encdata.cipher.derlen);
+ decdata.data = dec_authenticator->data;
+ decdata.length = dec_authenticator->size;
+ if (0 != krb5_c_decrypt ( krbctx_srv,
+ &cmd->krb_key,
+ 11 /* stealing key usage from AP-REQ */,
+ NULL,
+ &rawdata,
+ &decdata)) {
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ dec_authenticator->size = decdata.length;
+prange ("srv_D", decdata.data, decdata.length);
+ //
+ // Unpack the decrypted Authenticator
+ dercursor decsyntax;
+ decsyntax.derptr = decdata.data;
+ decsyntax.derlen = decdata.length;
+prangefull ("srv_A", decdata.data, decdata.length);
+ authenticator_t auth;
+ memset (&auth, 0, sizeof (auth));
+ if (0 != der_unpack ( &decsyntax,
+ auth_packer,
+ (dercursor *) &auth,
+ 1)) {
+ tlog (TLOG_DAEMON, LOG_ERR, "Failed to der_unpack(Authenticator) in server: %s", strerror (errno));
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ //
+ // Validate the contents of the Authenticator
+ if (qder2b_unpack_int32 (auth.authenticator_vno) != 5) {
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ if (auth.cksum.checksum.derptr == NULL) {
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ if (auth.cksum.checksum.derlen < 16) {
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ //TODO// Optionally, for KDH-Only, ensure presence and size of a subkey
+ //
+ // Produce the requested content from the Authenticator and return
+ *checksum_type = qder2b_unpack_int32 (auth.cksum.cksumtype);
+ hash->data = auth.cksum.checksum.derptr;
+ hash->size = auth.cksum.checksum.derlen;
+ return 0;
}
#endif
/* valexp_I_start -- validation function for the GnuTLS backend.
* This function ensures that the remote peer provides an identity.
* TODO: We should compare the hostname as well, or compare if in remoteid
- * TODO: We may need to support more than just X509/PGP certificates
+ * TODO: We may need to support more than just X509/PGP certificates
*/
static void valexp_I_start (void *vcmd, struct valexp *ve, char pred) {
struct command *cmd = (struct command *) vcmd;
case IPPROTO_UDP:
proto = "udp";
break;
+#ifndef WINDOWS_PORT
case IPPROTO_SCTP:
proto = "sctp";
break;
+#endif
default:
goto setflagval;
}
valflag = o2vf (online_globaldir_x509 (
rid,
raw->data, raw->size));
-#ifdef GNUTLS_CRT_KRB
+#ifdef HAVE_TLS_KDH
} else if (cmd->remote_cert_type == GNUTLS_CRT_KRB) {
- // Kerberos is sufficiently "live" to always pass O
+ // Kerberos is sufficiently "live" to be pass O
valflag = 1;
goto setvalflag;
#endif
}
//
// Continue loading the certificate information: X.509, PGP, ...
+#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_peers (cmd->session, &num_certs);
+#endif
if (certs == NULL) {
num_certs = 0;
}
fprintf (stderr, "DEBUG: otfcert retrieval returned %d\n", gtls_errno);
return gtls_errno;
} else {
-fprintf (stderr, "DEBUG: otfcert retrieval returned GNUTLS_E_AGAIN, so skip it\n", gtls_errno);
+fprintf (stderr, "DEBUG: otfcert retrieval returned GNUTLS_E_AGAIN, so skip it\n");
gtls_errno = GNUTLS_E_SUCCESS; // Attempt failed, ignore
}
}
#endif
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 ");
if (ok) {
+ if (cmd->lids [lidtype - LID_TYPE_MIN].data != NULL) {
+ free (cmd->lids [lidtype - LID_TYPE_MIN].data);
+ }
// Move the credential into the command structure
dbt_store (&creddata,
&cmd->lids [lidtype - LID_TYPE_MIN]);
+fprintf (stderr, "DEBUG: Storing cmd->lids[%d].data %p\n", lidtype-LID_TYPE_MIN, cmd->lids [lidtype-LID_TYPE_MIN].data);
found = 1;
} else {
// Skip the credential by freeing its data structure
* Return 1 for yes or 0 for no; this is used in priority strings.
*/
static inline int lidtpsup (struct command *cmd, int lidtp) {
- return 1; //TODO// Can we decide if we needn't authenticate?
return cmd->lids [lidtp - LID_TYPE_MIN].data != NULL;
}
// - Configured security parameters (database? variable?)
// - CTYPEs, SRP, ANON-or-not --> fill in as + or - characters
if (gtls_errno == GNUTLS_E_SUCCESS) {
- char priostr [256];
+ char priostr [512];
+#ifdef HAVE_TLS_KDH
snprintf (priostr, sizeof (priostr)-1,
// "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
"NONE:"
-#ifdef HAVE_TLS_KDH
"%%ASYM_CERT_TYPES:"
-#endif
"+VERS-TLS-ALL:+VERS-DTLS-ALL:"
"+COMP-NULL:"
"+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
"%cANON-ECDH:"
+ "+ECDHE-KRB:" // +ECDHE-KRB-RSA:+ECDHE-KRB-ECDHE:" // opt?
"+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
- "%cCTYPE-X.509:"
- "%cCTYPE-OPENPGP:"
-#ifdef HAVE_TLS_KDH
- "%cCTYPE-CLI-KRB:%cCTYPE-SRV-X.509:"
-#endif
+ "+CTYPE-SRV-KRB:+CTYPE-SRV-X.509:+CTYPE-SRV-OPENPGP:"
+ "%cCTYPE-CLI-KRB:"
+ "%cCTYPE-CLI-X.509:"
+ "%cCTYPE-CLI-OPENPGP:"
"%cSRP:%cSRP-RSA:%cSRP-DSS",
anonpre_ok ?'+':'-',
- lidtpsup (cmd, LID_TYPE_X509) ?'+':'-',
- lidtpsup (cmd, LID_TYPE_PGP) ?'+':'-',
-#ifdef HAVE_TLS_KDH
- lidtpsup (cmd, LID_TYPE_KRB5) ?'+':'-',
- lidtpsup (cmd, LID_TYPE_KRB5) ?'+':'-',
-#endif
+ 1 /* lidtpsup (cmd, LID_TYPE_KRB5)*/ ?'+':'-',
+ 1 /*lidtpsup (cmd, LID_TYPE_X509)*/ ?'+':'-',
+ 1 /*lidtpsup (cmd, LID_TYPE_PGP)*/ ?'+':'-',
//TODO// Temporarily patched out SRP
lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-',
lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-',
lidtpsup (cmd, LID_TYPE_SRP) ?'+':'-');
-// strcpy (priostr, "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"); //TODO:TEST//
-// strcpy (priostr, "NONE:+VERS-TLS-ALL:+VERS-DTLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"); //TODO:TEST//
+#else
+ // It's not possible to make good decisions on certificate type
+ // for both sides based on knowledge of local authentication
+ // abilities. So we permit all (but would like to be subtler).
+ snprintf (priostr, sizeof (priostr)-1,
+ // "NORMAL:-RSA:" -- also ECDH-RSA, ECDHE-RSA, ...DSA...
+ "NONE:"
+ "+VERS-TLS-ALL:+VERS-DTLS-ALL:"
+ "+COMP-NULL:"
+ "+CIPHER-ALL:+CURVE-ALL:+SIGN-ALL:+MAC-ALL:"
+ "%cANON-ECDH:"
+ "+ECDHE-RSA:+DHE-RSA:+ECDHE-ECDSA:+DHE-DSS:+RSA:" //TODO//
+ "%cCTYPE-X.509:"
+ "%cCTYPE-OPENPGP:"
+ "%cSRP:%cSRP-RSA:%cSRP-DSS",
+ anonpre_ok ?'+':'-',
+ 1 ?'+':'-',
+ 1 ?'+':'-',
+ //TODO// Temporarily patched out SRP
+ 1 ?'+':'-',
+ 1 ?'+':'-',
+ 1 ?'+':'-');
+#endif
tlog (TLOG_TLS, LOG_DEBUG, "Constructed priority string %s for local ID %s",
priostr, cmd->cmd.pio_data.pioc_starttls.localid);
E_g2e ("Failed to set GnuTLS priority string",
* - TLS hints -- Server Name Indication
* - User hints -- local and remote identities provided
*/
-int srv_clienthello (gnutls_session_t session) {
+static int srv_clienthello (gnutls_session_t session, unsigned int htype, unsigned int post, unsigned int incoming, const gnutls_datum_t *msg) {
struct command *cmd;
+ int gtls_errno = GNUTLS_E_SUCCESS;
char sni [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)]; // static
size_t snilen = sizeof (sni);
- int snitype;
- int gtls_errno = GNUTLS_E_SUCCESS;
+ unsigned int snitype;
char *lid;
+tlog (LOG_DAEMON, LOG_INFO, "Invoked %sprocessor for Client Hello, htype=%d, incoming=%d\n",
+ post ? "post" : "pre",
+ htype,
+ incoming);
+
fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
errno = 0;
fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
+
+if (!post) {
//
// Setup a number of common references
cmd = (struct command *) gnutls_session_get_ptr (session);
if (cmd == NULL) {
return GNUTLS_E_INVALID_SESSION;
}
- lid = cmd->cmd.pio_data.pioc_starttls.localid;
//
// Setup server-specific credentials and priority string
E_g2e ("Failed to reconfigure GnuTLS as a server",
configure_session (cmd,
session,
- srv_creds, srv_credcount,
+ srv_creds, srv_credcount,
cmd->anonpre & ANONPRE_SERVER));
fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
+} else {
+
+ //
+ // Setup a number of common references
+ cmd = (struct command *) gnutls_session_get_ptr (session);
+ if (cmd == NULL) {
+ return GNUTLS_E_INVALID_SESSION;
+ }
+ lid = cmd->cmd.pio_data.pioc_starttls.localid;
+
//
// Setup to ignore/request/require remote identity (from client)
fprintf (stderr, "DEBUG: Got errno = %d / %s at %d\n", errno, strerror (errno), __LINE__);
sni [sizeof (sni) - 1] = '\0';
}
fprintf (stderr, "DEBUG: Got gtls_errno = %d at %d\n", gtls_errno, __LINE__);
+}
//
// Lap up any unnoticed POSIX error messages
case GNUTLS_CRD_SRP:
gnutls_srp_free_server_credentials (crd->cred);
break;
+ case GNUTLS_CRD_PSK:
+ case GNUTLS_CRD_IA:
+ //TODO: not handled
+ break;
//TODO// case GNUTLS_CRD_KDH:
//TODO// gnutls_kdh_free_server_credentials (crd->cred);
//TODO// break;
case GNUTLS_CRD_SRP:
gnutls_srp_free_client_credentials (crd->cred);
break;
+ case GNUTLS_CRD_PSK:
+ case GNUTLS_CRD_IA:
+ //TODO: not handled
+ break;
//TODO// case GNUTLS_CRD_KDH:
//TODO// gnutls_kdh_free_client_credentials (crd->cred);
//TODO// break;
//
// First find the ctlkeynode_tls
ckn = (struct ctlkeynode_tls *) ctlkey_find (cmd->cmd.pio_data.pioc_starttls.ctlkey, security_tls, cmd->clientfd);
-fprintf (stderr, "DEBUG: Got ckn == 0x%0x\n", (intptr_t) ckn);
+fprintf (stderr, "DEBUG: Got ckn == %p\n", (void *) ckn);
if (ckn == NULL) {
tlog (TLOG_UNIXSOCK, LOG_ERR, "Failed to find TLS connection for renegotiation by its ctlkey");
send_error (replycmd, ESRCH, "Cannot find TLS connection for renegotiation");
// that TLS has in this respect. Maybe we'll capture it one giant loop
// at some point, but for now that does not seem to add any relief.
renegotiate:
-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);
+fprintf (stderr, "DEBUG: Renegotiating = %d, anonpost = %d, plainfd = %d, cryptfd = %d, flags = 0x%x, session = %p, 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);
//
// If this is server renegotiating, send a request to that end
close (plainfd);
plainfd = -1;
}
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ckn != NULL) { /* TODO: CHECK NEEDED? */
if (ctlkey_unregister (ckn->regent.ctlkey)) {
free (ckn);
while (anonpre_regjmp > 0) {
anonpre_regjmp = anonpre_regjmp >> 1;
cmp = strncasecmp (anonpre_registry [anonpre_regidx].service,
- cmd->cmd.pio_data.pioc_starttls.service,
+ (const char *)cmd->cmd.pio_data.pioc_starttls.service,
TLSPOOL_SERVICELEN);
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);
if (cmp == 0) {
close (plainfd);
plainfd = -1;
}
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ckn != NULL) { /* TODO: CHECK NEEDED? */
if (ctlkey_unregister (ckn->regent.ctlkey)) {
free (ckn);
len++;
}
// If no usable remoteid was setup, ignore it
- if ((len + ofs > 0) && (len < 128)) {
+ if ((len > ofs) && (len < 128)) {
cmd->cmd.pio_data.pioc_starttls.remoteid [sizeof (cmd->cmd.pio_data.pioc_starttls.remoteid)-1] = '\0';
+ tlog (TLOG_TLS, LOG_DEBUG, "Sending ServerNameIndication \"%.*s\"", len - ofs, str + ofs);
E_g2e ("Client failed to setup SNI",
gnutls_server_name_set (
session,
configure_session (cmd,
session,
anonpost? NULL: cli_creds,
- anonpost? 0: cli_credcount,
+ anonpost? 0: cli_credcount,
cmd->anonpre & ANONPRE_CLIENT));
}
//
fprintf (stderr, "DEBUG: Configuring for server credentials callback if %d==0\n", gtls_errno);
if (!renegotiating) { //TODO:TEST//
if (gtls_errno == GNUTLS_E_SUCCESS) {
- gnutls_handshake_set_post_client_hello_function (
+ gnutls_handshake_set_hook_function (
session,
+ GNUTLS_HANDSHAKE_CLIENT_HELLO,
+ GNUTLS_HOOK_BOTH,
srv_clienthello);
}
} //TODO:TEST//
configure_session (cmd,
session,
anonpost? NULL: srv_creds,
- anonpost? 0: srv_credcount,
+ anonpost? 0: srv_credcount,
cmd->anonpre & ANONPRE_SERVER));
}
#endif
send_error (replycmd, EIO, "Failed to prepare for TLS");
}
if (got_session) {
-fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
+fprintf (stderr, "gnutls_deinit (%p) at %d\n", (void *)session, __LINE__);
gnutls_deinit (session);
got_session = 0;
}
close (plainfd);
plainfd = -1;
}
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ckn != NULL) { /* TODO: CHECK NEEDED? */
if (ctlkey_unregister (ckn->regent.ctlkey)) {
free (ckn);
(gnutls_error_is_fatal (gtls_errno) == 0));
//
// Handshake done -- initialise remote_xxx, vfystatus, got_remoteid
- E_g2e ("Failed to retrieve peer credentials",
- fetch_remote_credentials (cmd));
+ if ((gtls_errno == 0) && !(cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_IGNORE_REMOTEID)) {
+ // We want to try to authenticate the peer
+ E_g2e ("Failed to retrieve peer credentials",
+ fetch_remote_credentials (cmd));
+ if (gtls_errno == GNUTLS_E_AUTH_ERROR) {
+ if (cmd->cmd.pio_data.pioc_starttls.flags & PIOF_STARTTLS_REQUEST_REMOTEID) {
+ // We do not _require_ authentication of the peer
+ gtls_errno = 0;
+ }
+ }
+ }
if (gtls_errno == 0) {
const gnutls_datum_t *certs;
unsigned int num_certs;
//TODO:ELSEWHERE// E_g2e ("Failed to reconfigure GnuTLS without anonymous precursor",
//TODO:ELSEWHERE// configure_session (cmd,
//TODO:ELSEWHERE// session,
- //TODO:ELSEWHERE// NULL, 0,
+ //TODO:ELSEWHERE// NULL, 0,
//TODO:ELSEWHERE// 0));
// We do not want to use ANON-DH if the flag
// ANONPRE_EXTEND_MASTER_SECRET is set for the protocol
// Setup for validation expression runthrough
cmd->valexp_result = -1;
if ((cmd->trust_valexp != NULL) && (0 != strcmp (cmd->trust_valexp, "1"))) {
-fprintf (stderr, "DEBUG: Trust valexp \"%s\" @ 0x%016x\n", cmd->trust_valexp, (uint64_t) cmd->trust_valexp);
+fprintf (stderr, "DEBUG: Trust valexp \"%s\" @ %p\n", cmd->trust_valexp, (void *) cmd->trust_valexp);
valexp_conj [valexp_conj_count++] = cmd->trust_valexp;
}
if (cmd->lids [LID_TYPE_VALEXP - LID_TYPE_MIN].data != NULL) {
&lid_valexp,
&ignored.data,
&ignored.size);
-fprintf (stderr, "DEBUG: LocalID valexp \"%s\" @ 0x%016x (ok=%d)\n", lid_valexp, (uint64_t) lid_valexp, ok);
+fprintf (stderr, "DEBUG: LocalID valexp \"%s\" @ %p (ok=%d)\n", lid_valexp, (void *) lid_valexp, ok);
if (ok && (lid_valexp != NULL)) {
valexp_conj [valexp_conj_count++] = lid_valexp;
} else {
valexp_conj,
have_starttls_validation (),
(void *) cmd);
-fprintf (stderr, "DEBUG: Registered to verun = 0x%016x\n", (uint64_t) verun);
+fprintf (stderr, "DEBUG: Registered to verun = %p\n", (void *) verun);
if (verun == NULL) {
gtls_errno = GNUTLS_E_AUTH_ERROR;
}
}
else fprintf (stderr, "DEBUG: valexp returns POSITIVE result\n");
valexp_unregister (verun);
-fprintf (stderr, "DEBUG: Unregistered verun 0x%016x\n", (uint64_t) verun);
+fprintf (stderr, "DEBUG: Unregistered verun %p\n", (void *) verun);
}
}
// Cleanup any prefetched identities
for (i=LID_TYPE_MIN; i<=LID_TYPE_MAX; i++) {
if (cmd->lids [i - LID_TYPE_MIN].data != NULL) {
+fprintf (stderr, "DEBUG: Freeing cmd->lids[%d].data %p\n", i-LID_TYPE_MIN, (void *)(cmd->lids [i-LID_TYPE_MIN].data));
free (cmd->lids [i - LID_TYPE_MIN].data);
}
}
krb5_free_keyblock_contents (krbctx_srv, &cmd->krb_key);
memset (&cmd->krb_key, 0, sizeof (cmd->krb_key));
}
- if (cmd->krb_tkt.client != NULL) {
+ if (cmd->krbid_srv != NULL) {
+ // RATHER BLUNT: It shouldn't matter which krbctx_ is used...
+ krb5_free_principal (krbctx_srv, cmd->krbid_srv);
+ cmd->krbid_srv = NULL;
+ }
+ if (cmd->krbid_cli != NULL) {
// RATHER BLUNT: It shouldn't matter which krbctx_ is used...
- krb5_free_cred_contents (krbctx_srv, &cmd->krb_tkt);
- memset (&cmd->krb_tkt, 0, sizeof (cmd->krb_tkt));
+ krb5_free_principal (krbctx_srv, cmd->krbid_cli);
+ cmd->krbid_cli = NULL;
}
#if 0
free (preauth);
}
if (got_session) {
-fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
+fprintf (stderr, "gnutls_deinit (%p) at %d\n", (void *)session, __LINE__);
gnutls_deinit (session);
got_session = 0;
}
close (plainfd);
plainfd = -1;
}
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ckn != NULL) { /* TODO: CHECK NEEDED? */
if (ctlkey_unregister (ckn->regent.ctlkey)) {
free (ckn);
free (preauth);
}
if (got_session) {
-fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
+fprintf (stderr, "gnutls_deinit (%p) at %d\n", (void *)session, __LINE__);
gnutls_deinit (session);
got_session = 0;
}
close (cryptfd);
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ckn) { /* TODO: CHECK NEEDED? PRACTICE=>YES */
if (ctlkey_unregister (ckn->regent.ctlkey)) {
free (ckn);
free (preauth);
}
if (got_session) {
-fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
+fprintf (stderr, "gnutls_deinit (%p) at %d\n", (void *)session, __LINE__);
gnutls_deinit (session);
got_session = 0;
}
close (cryptfd);
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ckn != NULL) { /* TODO: CHECK NEEDED? */
if (ctlkey_unregister (ckn->regent.ctlkey)) {
free (ckn);
// already have been freed if the ctlfd was closed
// and the connection could not continue detached
// (such as after forking it).
-fprintf (stderr, "ctlkey_unregister under ckn=0x%x at %d\n", ckn, __LINE__);
+fprintf (stderr, "ctlkey_unregister under ckn=%p at %d\n", (void *)ckn, __LINE__);
if (ctlkey_unregister (orig_starttls.ctlkey)) {
free (ckn);
}
close (cryptfd);
cleanup_any_remote_credentials (cmd);
if (got_session) {
-fprintf (stderr, "gnutls_deinit (0x%x) at %d\n", session, __LINE__);
+fprintf (stderr, "gnutls_deinit (%p) at %d\n", (void *)session, __LINE__);
gnutls_deinit (session);
got_session = 0;
}
/*
- * The starttls function responds to an application's request to
+ * The starttls function responds to an application's request to
* setup TLS for a given file descriptor, and return a file descriptor
* with the unencrypted view when done. The main thing done here is to
* spark off a new thread that handles the operations.
if (strlen (pf) != in1len) {
continue;
}
- if (strcmp (pf, in1) != 0) {
+ if (strcmp (pf, (const char *)in1) != 0) {
continue;
}
}
if (*prefixes == NULL) {
// RFC 5705 defines a private-use prefix "EXPERIMENTAL"
- if ((in1len <= 12) || (strncmp (in1, "EXPERIMENTAL", 12) != 0)) {
+ if ((in1len <= 12) || (strncmp ((const char *)in1, "EXPERIMENTAL", 12) != 0)) {
err = 1;
}
}
errno = 0;
E_g2e ("GnuTLS PRNG based on session master key failed",
gnutls_prf_rfc5705 (ckn->session,
- in1len, in1,
- (in2len >= 0)? in2len: 0, (in2len >= 0) ? in2: NULL,
- prnglen, prng->buffer));
+ in1len, (const char *)in1,
+ (in2len >= 0)? in2len: 0,
+ (const char *)((in2len >= 0) ? in2: NULL),
+ prnglen, (char *)prng->buffer));
err = err || (errno != 0);
//
// Wipe temporary data / buffers for security reasons
cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = NULL;
cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size = 0;
}
-
+
//
// Create an empty certificate
E_g2e ("Failed to initialise on-the-fly certificate",
//TODO: gnutls_x509_crt_set_key_usage
//TODO:SKIP? gnutls_x509_crt_set_ca_status
for (i=0; i < svcusage_registry_size; i++) {
- if (strcmp (svcusage_registry [i].service, cmd->cmd.pio_data.pioc_starttls.service) == 0) {
+ if (strcmp (svcusage_registry [i].service, (const char *)(cmd->cmd.pio_data.pioc_starttls.service)) == 0) {
const char **walker;
E_g2e ("Failed to setup basic key usage during on-the-fly certificate creation",
gnutls_x509_crt_set_key_usage (otfcert, svcusage_registry [i].usage));
// This is as expected, now .size will have been set
gtls_errno = GNUTLS_E_SUCCESS;
} else {
- if (gtls_errno = GNUTLS_E_SUCCESS) {
+ if (gtls_errno == GNUTLS_E_SUCCESS) {
// Something must be wrong if we receive OK
gtls_errno = GNUTLS_E_INVALID_REQUEST;
}
cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].data = ptr;
* (uint32_t *) ptr = htonl (LID_TYPE_X509 | LID_ROLE_BOTH);
ptr += 4;
- strcpy (ptr, onthefly_p11uri);
+ strcpy ((char *)ptr, onthefly_p11uri);
ptr += strlen (onthefly_p11uri) + 1;
restsz = cmd->lids [LID_TYPE_X509 - LID_TYPE_MIN].size - 4 - strlen (onthefly_p11uri) - 1;
E_g2e ("Failed to export on-the-fly certificate as a credential",
gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_DER, ptr, &restsz));
-char *pembuf [10000];
+char pembuf [10000];
size_t pemlen = sizeof (pembuf) - 1;
int exporterror = gnutls_x509_crt_export (otfcert, GNUTLS_X509_FMT_PEM, pembuf, &pemlen);
if (exporterror == 0) {