along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#define KRB5_PRIVATE 1 /* this file uses PRIVATE interfaces! */
-/* this file uses DEPRECATED interfaces! */
-
#include "includes.h"
+#include "smb_krb5.h"
+#include "../librpc/gen_ndr/krb5pac.h"
+#include "../lib/util/asn1.h"
+#include "libsmb/nmblib.h"
-#ifdef HAVE_KRB5
-
-#define GSSAPI_CHECKSUM 0x8003 /* Checksum type value for Kerberos */
-#define GSSAPI_BNDLENGTH 16 /* Bind Length (rfc-1964 pg.3) */
-#define GSSAPI_CHECKSUM_SIZE (12+GSSAPI_BNDLENGTH)
-
-#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
-static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context,
- krb5_auth_context *auth_context,
- krb5_creds *credsp,
- krb5_ccache ccache,
- krb5_data *authenticator);
+#ifndef KRB5_AUTHDATA_WIN2K_PAC
+#define KRB5_AUTHDATA_WIN2K_PAC 128
#endif
-/**************************************************************
- Wrappers around kerberos string functions that convert from
- utf8 -> unix charset and vica versa.
-**************************************************************/
-
-/**************************************************************
- krb5_parse_name that takes a UNIX charset.
-**************************************************************/
-
- krb5_error_code smb_krb5_parse_name(krb5_context context,
- const char *name, /* in unix charset */
- krb5_principal *principal)
-{
- krb5_error_code ret;
- char *utf8_name;
- size_t converted_size;
-
- if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
- return ENOMEM;
- }
-
- ret = krb5_parse_name(context, utf8_name, principal);
- TALLOC_FREE(utf8_name);
- return ret;
-}
-
-#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
-/**************************************************************
- krb5_parse_name_norealm that takes a UNIX charset.
-**************************************************************/
-
-static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
- const char *name, /* in unix charset */
- krb5_principal *principal)
-{
- krb5_error_code ret;
- char *utf8_name;
- size_t converted_size;
-
- *principal = NULL;
- if (!push_utf8_talloc(talloc_tos(), &utf8_name, name, &converted_size)) {
- return ENOMEM;
- }
-
- ret = krb5_parse_name_norealm(context, utf8_name, principal);
- TALLOC_FREE(utf8_name);
- return ret;
-}
+#ifndef KRB5_AUTHDATA_IF_RELEVANT
+#define KRB5_AUTHDATA_IF_RELEVANT 1
#endif
-/**************************************************************
- krb5_parse_name that returns a UNIX charset name. Must
- be freed with talloc_free() call.
-**************************************************************/
-
-krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx,
- krb5_context context,
- krb5_const_principal principal,
- char **unix_name)
-{
- krb5_error_code ret;
- char *utf8_name;
- size_t converted_size;
+#ifdef HAVE_KRB5
- *unix_name = NULL;
- ret = krb5_unparse_name(context, principal, &utf8_name);
- if (ret) {
- return ret;
- }
+#define GSSAPI_CHECKSUM 0x8003 /* Checksum type value for Kerberos */
+#define GSSAPI_BNDLENGTH 16 /* Bind Length (rfc-1964 pg.3) */
+#define GSSAPI_CHECKSUM_SIZE (4+GSSAPI_BNDLENGTH+4) /* Length of bind length,
+ bind field, flags field. */
- if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) {
- krb5_free_unparsed_name(context, utf8_name);
- return ENOMEM;
- }
- krb5_free_unparsed_name(context, utf8_name);
- return 0;
-}
+/* MIT krb5 1.7beta3 (in Ubuntu Karmic) is missing the prototype,
+ but still has the symbol */
+#if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE
+krb5_error_code krb5_auth_con_set_req_cksumtype(
+ krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_cksumtype cksumtype);
+#endif
#ifndef HAVE_KRB5_SET_REAL_TIME
/*
}
#else
#error UNKNOWN_ADDRTYPE
-#endif
-
-#if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_USE_ENCTYPE) && defined(HAVE_KRB5_STRING_TO_KEY) && defined(HAVE_KRB5_ENCRYPT_BLOCK)
-static int create_kerberos_key_from_string_direct(krb5_context context,
- krb5_principal host_princ,
- krb5_data *password,
- krb5_keyblock *key,
- krb5_enctype enctype)
-{
- int ret = 0;
- krb5_data salt;
- krb5_encrypt_block eblock;
-
- ret = krb5_principal2salt(context, host_princ, &salt);
- if (ret) {
- DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret)));
- return ret;
- }
- krb5_use_enctype(context, &eblock, enctype);
- ret = krb5_string_to_key(context, &eblock, key, password, &salt);
- SAFE_FREE(salt.data);
-
- return ret;
-}
-#elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT)
-static int create_kerberos_key_from_string_direct(krb5_context context,
- krb5_principal host_princ,
- krb5_data *password,
- krb5_keyblock *key,
- krb5_enctype enctype)
-{
- int ret;
- krb5_salt salt;
-
- ret = krb5_get_pw_salt(context, host_princ, &salt);
- if (ret) {
- DEBUG(1,("krb5_get_pw_salt failed (%s)\n", error_message(ret)));
- return ret;
- }
-
- ret = krb5_string_to_key_salt(context, enctype, (const char *)password->data, salt, key);
- krb5_free_salt(context, salt);
-
- return ret;
-}
-#else
-#error UNKNOWN_CREATE_KEY_FUNCTIONS
#endif
int create_kerberos_key_from_string(krb5_context context,
}
asn1_start_tag(data, ASN1_CONTEXT(2));
- asn1_read_OctetString(data, talloc_autofree_context(), &edata_contents);
+ asn1_read_OctetString(data, talloc_tos(), &edata_contents);
asn1_end_tag(data);
asn1_end_tag(data);
asn1_end_tag(data);
asn1_end_tag(data);
asn1_start_tag(data, ASN1_CONTEXT(1));
- asn1_read_OctetString(data, talloc_autofree_context(), &pac_contents);
+ asn1_read_OctetString(data, talloc_tos(), &pac_contents);
asn1_end_tag(data);
asn1_end_tag(data);
asn1_end_tag(data);
#endif /* HAVE_KRB5_LOCATE_KDC */
-#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME)
- void krb5_free_unparsed_name(krb5_context context, char *val)
-{
- SAFE_FREE(val);
-}
-#endif
-
- void kerberos_free_data_contents(krb5_context context, krb5_data *pdata)
-{
-#if defined(HAVE_KRB5_FREE_DATA_CONTENTS)
- if (pdata->data) {
- krb5_free_data_contents(context, pdata);
- }
-#else
- SAFE_FREE(pdata->data);
-#endif
-}
-
void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype)
{
#if defined(HAVE_KRB5_KEYBLOCK_IN_CREDS)
return True;
}
+/* Allocate and setup the auth context into the state we need. */
+
+static krb5_error_code setup_auth_context(krb5_context context,
+ krb5_auth_context *auth_context)
+{
+ krb5_error_code retval;
+
+ retval = krb5_auth_con_init(context, auth_context );
+ if (retval) {
+ DEBUG(1,("krb5_auth_con_init failed (%s)\n",
+ error_message(retval)));
+ return retval;
+ }
+
+ /* Ensure this is an addressless ticket. */
+ retval = krb5_auth_con_setaddrs(context, *auth_context, NULL, NULL);
+ if (retval) {
+ DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n",
+ error_message(retval)));
+ }
+
+ return retval;
+}
+
+#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE)
+static krb5_error_code create_gss_checksum(krb5_data *in_data, /* [inout] */
+ uint32_t gss_flags)
+{
+ unsigned int orig_length = in_data->length;
+ unsigned int base_cksum_size = GSSAPI_CHECKSUM_SIZE;
+ char *gss_cksum = NULL;
+
+ if (orig_length) {
+ /* Extra length field for delgated ticket. */
+ base_cksum_size += 4;
+ }
+
+ if ((unsigned int)base_cksum_size + orig_length <
+ (unsigned int)base_cksum_size) {
+ return EINVAL;
+ }
+
+ gss_cksum = (char *)SMB_MALLOC(base_cksum_size + orig_length);
+ if (gss_cksum == NULL) {
+ return ENOMEM;
+ }
+
+ memset(gss_cksum, '\0', base_cksum_size + orig_length);
+ SIVAL(gss_cksum, 0, GSSAPI_BNDLENGTH);
+
+ /*
+ * GSS_C_NO_CHANNEL_BINDINGS means 16 zero bytes.
+ * This matches the behavior of heimdal and mit.
+ *
+ * And it is needed to work against some closed source
+ * SMB servers.
+ *
+ * See bug #7883
+ */
+ memset(&gss_cksum[4], 0x00, GSSAPI_BNDLENGTH);
+
+ SIVAL(gss_cksum, 20, gss_flags);
+
+ if (orig_length) {
+ SSVAL(gss_cksum, 24, 1); /* The Delegation Option identifier */
+ SSVAL(gss_cksum, 26, orig_length);
+ /* Copy the kerberos KRB_CRED data */
+ memcpy(gss_cksum + 28, in_data->data, orig_length);
+ free(in_data->data);
+ in_data->data = NULL;
+ in_data->length = 0;
+ }
+ in_data->data = gss_cksum;
+ in_data->length = base_cksum_size + orig_length;
+ return 0;
+}
+#endif
+
/*
we can't use krb5_mk_req because w2k wants the service to be in a particular format
*/
krb5_data in_data;
bool creds_ready = False;
int i = 0, maxtries = 3;
-
+
ZERO_STRUCT(in_data);
retval = smb_krb5_parse_name(context, principal, &server);
*expire_time = (time_t)credsp->times.endtime;
}
-#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
- if( credsp->ticket_flags & TKT_FLG_OK_AS_DELEGATE ) {
- /* Fetch a forwarded TGT from the KDC so that we can hand off a 2nd ticket
- as part of the kerberos exchange. */
+ /* Allocate the auth_context. */
+ retval = setup_auth_context(context, auth_context);
+ if (retval) {
+ DEBUG(1,("setup_auth_context failed (%s)\n",
+ error_message(retval)));
+ goto cleanup_creds;
+ }
+
+#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE)
+ {
+ uint32_t gss_flags = 0;
+
+ if( credsp->ticket_flags & TKT_FLG_OK_AS_DELEGATE ) {
+ /* Fetch a forwarded TGT from the KDC so that we can hand off a 2nd ticket
+ as part of the kerberos exchange. */
- DEBUG( 3, ("ads_krb5_mk_req: server marked as OK to delegate to, building forwardable TGT\n") );
+ DEBUG( 3, ("ads_krb5_mk_req: server marked as OK to delegate to, building forwardable TGT\n") );
- if( *auth_context == NULL ) {
- /* Allocate if it has not yet been allocated. */
- retval = krb5_auth_con_init( context, auth_context );
+ retval = krb5_auth_con_setuseruserkey(context,
+ *auth_context,
+ &credsp->keyblock );
if (retval) {
- DEBUG(1,("ads_krb5_mk_req: krb5_auth_con_init failed (%s)\n",
+ DEBUG(1,("krb5_auth_con_setuseruserkey failed (%s)\n",
error_message(retval)));
goto cleanup_creds;
}
- }
- retval = krb5_auth_con_setuseruserkey( context, *auth_context, &credsp->keyblock );
- if (retval) {
- DEBUG(1,("ads_krb5_mk_req: krb5_auth_con_setuseruserkey failed (%s)\n",
- error_message(retval)));
- goto cleanup_creds;
+ /* Must use a subkey for forwarded tickets. */
+ retval = krb5_auth_con_setflags(context,
+ *auth_context,
+ KRB5_AUTH_CONTEXT_USE_SUBKEY);
+ if (retval) {
+ DEBUG(1,("krb5_auth_con_setflags failed (%s)\n",
+ error_message(retval)));
+ goto cleanup_creds;
+ }
+
+ retval = krb5_fwd_tgt_creds(context,/* Krb5 context [in] */
+ *auth_context, /* Authentication context [in] */
+ CONST_DISCARD(char *, KRB5_TGS_NAME), /* Ticket service name ("krbtgt") [in] */
+ credsp->client, /* Client principal for the tgt [in] */
+ credsp->server, /* Server principal for the tgt [in] */
+ ccache, /* Credential cache to use for storage [in] */
+ 1, /* Turn on for "Forwardable ticket" [in] */
+ &in_data ); /* Resulting response [out] */
+
+ if (retval) {
+ DEBUG( 3, ("krb5_fwd_tgt_creds failed (%s)\n",
+ error_message( retval ) ) );
+
+ /*
+ * This is not fatal. Delete the *auth_context and continue
+ * with krb5_mk_req_extended to get a non-forwardable ticket.
+ */
+
+ if (in_data.data) {
+ free( in_data.data );
+ in_data.data = NULL;
+ in_data.length = 0;
+ }
+ krb5_auth_con_free(context, *auth_context);
+ *auth_context = NULL;
+ retval = setup_auth_context(context, auth_context);
+ if (retval) {
+ DEBUG(1,("setup_auth_context failed (%s)\n",
+ error_message(retval)));
+ goto cleanup_creds;
+ }
+ } else {
+ /* We got a delegated ticket. */
+ gss_flags |= GSS_C_DELEG_FLAG;
+ }
}
- /* Must use a subkey for forwarded tickets. */
- retval = krb5_auth_con_setflags( context, *auth_context, KRB5_AUTH_CONTEXT_USE_SUBKEY);
+ /* Frees and reallocates in_data into a GSS checksum blob. */
+ retval = create_gss_checksum(&in_data, gss_flags);
if (retval) {
- DEBUG(1,("ads_krb5_mk_req: krb5_auth_con_setflags failed (%s)\n",
- error_message(retval)));
- goto cleanup_creds;
+ goto cleanup_data;
}
- retval = ads_krb5_get_fwd_ticket( context,
- auth_context,
- credsp,
- ccache,
- &in_data );
+ /* We always want GSS-checksum types. */
+ retval = krb5_auth_con_set_req_cksumtype(context, *auth_context, GSSAPI_CHECKSUM );
if (retval) {
- DEBUG( 3, ("ads_krb5_get_fwd_ticket failed (%s)\n",
- error_message( retval ) ) );
-
- /*
- * This is not fatal. Delete the *auth_context and continue
- * with krb5_mk_req_extended to get a non-forwardable ticket.
- */
-
- if (in_data.data) {
- free( in_data.data );
- in_data.data = NULL;
- in_data.length = 0;
- }
- krb5_auth_con_free(context, *auth_context);
- *auth_context = NULL;
+ DEBUG(1,("krb5_auth_con_set_req_cksumtype failed (%s)\n",
+ error_message(retval)));
+ goto cleanup_data;
}
}
#endif
error_message(retval)));
}
+#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE)
+cleanup_data:
+#endif
+
if (in_data.data) {
free( in_data.data );
in_data.length = 0;
}
/*
- get a kerberos5 ticket for the given service
+ get a kerberos5 ticket for the given service
*/
-int cli_krb5_get_ticket(const char *principal, time_t time_offset,
- DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
- uint32 extra_ap_opts, const char *ccname,
+int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx,
+ const char *principal, time_t time_offset,
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
+ uint32_t extra_ap_opts, const char *ccname,
time_t *tgs_expire,
const char *impersonate_princ_s)
krb5_ccache ccdef = NULL;
krb5_auth_context auth_context = NULL;
krb5_enctype enc_types[] = {
-#ifdef ENCTYPE_ARCFOUR_HMAC
ENCTYPE_ARCFOUR_HMAC,
-#endif
- ENCTYPE_DES_CBC_MD5,
- ENCTYPE_DES_CBC_CRC,
+ ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_DES_CBC_CRC,
ENCTYPE_NULL};
initialize_krb5_error_table();
retval = krb5_init_context(&context);
if (retval) {
- DEBUG(1,("cli_krb5_get_ticket: krb5_init_context failed (%s)\n",
+ DEBUG(1, ("krb5_init_context failed (%s)\n",
error_message(retval)));
goto failed;
}
if ((retval = krb5_cc_resolve(context, ccname ?
ccname : krb5_cc_default_name(context), &ccdef))) {
- DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n",
+ DEBUG(1, ("krb5_cc_default failed (%s)\n",
error_message(retval)));
goto failed;
}
if ((retval = krb5_set_default_tgs_ktypes(context, enc_types))) {
- DEBUG(1,("cli_krb5_get_ticket: krb5_set_default_tgs_ktypes failed (%s)\n",
+ DEBUG(1, ("krb5_set_default_tgs_ktypes failed (%s)\n",
error_message(retval)));
goto failed;
}
- if ((retval = ads_krb5_mk_req(context,
- &auth_context,
- AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
- principal,
- ccdef, &packet,
- tgs_expire,
- impersonate_princ_s))) {
+ retval = ads_krb5_mk_req(context, &auth_context,
+ AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
+ principal, ccdef, &packet,
+ tgs_expire, impersonate_princ_s);
+ if (retval) {
goto failed;
}
- get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
+ get_krb5_smb_session_key(mem_ctx, context, auth_context,
+ session_key_krb5, false);
- *ticket = data_blob(packet.data, packet.length);
+ *ticket = data_blob_talloc(mem_ctx, packet.data, packet.length);
- kerberos_free_data_contents(context, &packet);
+ kerberos_free_data_contents(context, &packet);
failed:
- if ( context ) {
+ if (context) {
if (ccdef)
krb5_cc_close(context, ccdef);
if (auth_context)
krb5_auth_con_free(context, auth_context);
krb5_free_context(context);
}
-
+
return retval;
}
- bool get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, bool remote)
- {
+bool get_krb5_smb_session_key(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ krb5_auth_context auth_context,
+ DATA_BLOB *session_key, bool remote)
+{
krb5_keyblock *skey = NULL;
krb5_error_code err = 0;
bool ret = false;
if (remote) {
- err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
+ err = krb5_auth_con_getremotesubkey(context,
+ auth_context, &skey);
} else {
- err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
+ err = krb5_auth_con_getlocalsubkey(context,
+ auth_context, &skey);
}
if (err || skey == NULL) {
goto done;
}
- DEBUG(10, ("Got KRB5 session key of length %d\n", (int)KRB5_KEY_LENGTH(skey)));
- *session_key = data_blob(KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
- dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
+ DEBUG(10, ("Got KRB5 session key of length %d\n",
+ (int)KRB5_KEY_LENGTH(skey)));
+
+ *session_key = data_blob_talloc(mem_ctx,
+ KRB5_KEY_DATA(skey),
+ KRB5_KEY_LENGTH(skey));
+ dump_data_pw("KRB5 Session Key:\n",
+ session_key->data,
+ session_key->length);
ret = true;
- done:
+done:
if (skey) {
krb5_free_keyblock(context, skey);
}
return ret;
- }
+}
#if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT)
{
static krb5_data kdata;
- kdata.data = (char *)krb5_principal_get_comp_string(context, principal, i);
+ kdata.data = discard_const_p(char, krb5_principal_get_comp_string(context, principal, i));
kdata.length = strlen((const char *)kdata.data);
return &kdata;
}
#endif
- krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry)
-{
-/* Try krb5_free_keytab_entry_contents first, since
- * MIT Kerberos >= 1.7 has both krb5_free_keytab_entry_contents and
- * krb5_kt_free_entry but only has a prototype for the first, while the
- * second is considered private.
- */
-#if defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS)
- return krb5_free_keytab_entry_contents(context, kt_entry);
-#elif defined(HAVE_KRB5_KT_FREE_ENTRY)
- return krb5_kt_free_entry(context, kt_entry);
-#else
-#error UNKNOWN_KT_FREE_FUNCTION
-#endif
-}
-
- void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
- struct PAC_SIGNATURE_DATA *sig)
-{
-#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM
- cksum->cksumtype = (krb5_cksumtype)sig->type;
- cksum->checksum.length = sig->signature.length;
- cksum->checksum.data = sig->signature.data;
-#else
- cksum->checksum_type = (krb5_cksumtype)sig->type;
- cksum->length = sig->signature.length;
- cksum->contents = sig->signature.data;
-#endif
-}
-
- krb5_error_code smb_krb5_verify_checksum(krb5_context context,
- const krb5_keyblock *keyblock,
- krb5_keyusage usage,
- krb5_checksum *cksum,
- uint8 *data,
- size_t length)
-{
- krb5_error_code ret;
-
- /* verify the checksum */
-
- /* welcome to the wonderful world of samba's kerberos abstraction layer:
- *
- * function heimdal 0.6.1rc3 heimdal 0.7 MIT krb 1.4.2
- * -----------------------------------------------------------------------------
- * krb5_c_verify_checksum - works works
- * krb5_verify_checksum works (6 args) works (6 args) broken (7 args)
- */
-
-#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM)
- {
- krb5_boolean checksum_valid = False;
- krb5_data input;
-
- input.data = (char *)data;
- input.length = length;
-
- ret = krb5_c_verify_checksum(context,
- keyblock,
- usage,
- &input,
- cksum,
- &checksum_valid);
- if (ret) {
- DEBUG(3,("smb_krb5_verify_checksum: krb5_c_verify_checksum() failed: %s\n",
- error_message(ret)));
- return ret;
- }
-
- if (!checksum_valid)
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- }
-
-#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY)
-
- /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key
- * without enctype and it ignores any key_usage types - Guenther */
-
- {
-
- krb5_crypto crypto;
- ret = krb5_crypto_init(context,
- keyblock,
- 0,
- &crypto);
- if (ret) {
- DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n",
- error_message(ret)));
- return ret;
- }
-
- ret = krb5_verify_checksum(context,
- crypto,
- usage,
- data,
- length,
- cksum);
-
- krb5_crypto_destroy(context, crypto);
- }
-
-#else
-#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION
-#endif
-
- return ret;
-}
-
time_t get_authtime_from_tkt(krb5_ticket *tkt)
{
#if defined(HAVE_KRB5_TKT_ENC_PART2)
return ret;
}
- krb5_error_code smb_krb5_parse_name_norealm(krb5_context context,
- const char *name,
- krb5_principal *principal)
-{
-#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
- return smb_krb5_parse_name_norealm_conv(context, name, principal);
-#endif
-
- /* we are cheating here because parse_name will in fact set the realm.
- * We don't care as the only caller of smb_krb5_parse_name_norealm
- * ignores the realm anyway when calling
- * smb_krb5_principal_compare_any_realm later - Guenther */
-
- return smb_krb5_parse_name(context, name, principal);
-}
-
- bool smb_krb5_principal_compare_any_realm(krb5_context context,
- krb5_const_principal princ1,
- krb5_const_principal princ2)
-{
-#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM
-
- return krb5_principal_compare_any_realm(context, princ1, princ2);
-
-/* krb5_princ_size is a macro in MIT */
-#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
-
- int i, len1, len2;
- const krb5_data *p1, *p2;
-
- len1 = krb5_princ_size(context, princ1);
- len2 = krb5_princ_size(context, princ2);
-
- if (len1 != len2)
- return False;
-
- for (i = 0; i < len1; i++) {
-
- p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i);
- p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i);
-
- if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length))
- return False;
- }
-
- return True;
-#else
-#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION
-#endif
-}
-
krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, /* FILE:/tmp/krb5cc_0 */
const char *client_string, /* gd@BER.SUSE.DE */
const char *service_string, /* krbtgt/BER.SUSE.DE@BER.SUSE.DE */
DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string));
/* FIXME: we should not fall back to defaults */
- ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache);
+ ret = krb5_cc_resolve(context, discard_const_p(char, ccache_string), &ccache);
if (ret) {
goto done;
}
#ifdef HAVE_KRB5_GET_RENEWED_CREDS /* MIT */
{
- ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string));
+ ret = krb5_get_renewed_creds(context, &creds, client, ccache, discard_const_p(char, service_string));
if (ret) {
DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
goto done;
return ret;
}
-#if defined(TKT_FLG_OK_AS_DELEGATE ) && defined(HAVE_KRB5_FWD_TGT_CREDS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE) && defined(KRB5_AUTH_CONTEXT_USE_SUBKEY)
-/**************************************************************
-Routine: ads_krb5_get_fwd_ticket
- Description:
- When a service ticket is flagged as trusted
- for delegation we should provide a forwardable
- ticket so that the remote host can act on our
- behalf. This is done by taking the 2nd forwardable
- TGT and storing it in the GSS-API authenticator
- "checksum". This routine will populate
- the krb5_data authenticator with this TGT.
- Parameters:
- krb5_context context: The kerberos context for this authentication.
- krb5_auth_context: The authentication context.
- krb5_creds *credsp: The ticket credentials (AS-REP).
- krb5_ccache ccache: The credentials cache.
- krb5_data &authenticator: The checksum field that will store the TGT, and
- authenticator.data must be freed by the caller.
-
- Returns:
- krb5_error_code: 0 if no errors, otherwise set.
-**************************************************************/
-
-static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context,
- krb5_auth_context *auth_context,
- krb5_creds *credsp,
- krb5_ccache ccache,
- krb5_data *authenticator)
-{
- krb5_data fwdData;
- krb5_error_code retval = 0;
- char *pChksum = NULL;
- char *p = NULL;
-
-/* MIT krb5 1.7beta3 (in Ubuntu Karmic) is missing the prototype,
- but still has the symbol */
-#if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE
-krb5_error_code krb5_auth_con_set_req_cksumtype(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_cksumtype cksumtype);
-#endif
-
- ZERO_STRUCT(fwdData);
- ZERO_STRUCTP(authenticator);
-
- retval = krb5_fwd_tgt_creds(context,/* Krb5 context [in] */
- *auth_context, /* Authentication context [in] */
- CONST_DISCARD(char *, KRB5_TGS_NAME), /* Ticket service name ("krbtgt") [in] */
- credsp->client, /* Client principal for the tgt [in] */
- credsp->server, /* Server principal for the tgt [in] */
- ccache, /* Credential cache to use for storage [in] */
- 1, /* Turn on for "Forwardable ticket" [in] */
- &fwdData ); /* Resulting response [out] */
-
-
- if (retval) {
- DEBUG(1,("ads_krb5_get_fwd_ticket: krb5_fwd_tgt_creds failed (%s)\n",
- error_message(retval)));
- goto out;
- }
-
- if ((unsigned int)GSSAPI_CHECKSUM_SIZE + (unsigned int)fwdData.length <
- (unsigned int)GSSAPI_CHECKSUM_SIZE) {
- retval = EINVAL;
- goto out;
- }
-
- /* We're going to allocate a gssChecksum structure with a little
- extra data the length of the kerberos credentials length
- (APPLICATION 22) so that we can pack it on the end of the structure.
- */
-
- pChksum = (char *)SMB_MALLOC(GSSAPI_CHECKSUM_SIZE + fwdData.length );
- if (!pChksum) {
- retval = ENOMEM;
- goto out;
- }
-
- p = pChksum;
-
- SIVAL(p, 0, GSSAPI_BNDLENGTH);
- p += 4;
-
- /* Zero out the bindings fields */
- memset(p, '\0', GSSAPI_BNDLENGTH );
- p += GSSAPI_BNDLENGTH;
-
- SIVAL(p, 0, GSS_C_DELEG_FLAG );
- p += 4;
- SSVAL(p, 0, 1 );
- p += 2;
- SSVAL(p, 0, fwdData.length );
- p += 2;
-
- /* Migrate the kerberos KRB_CRED data to the checksum delegation */
- memcpy(p, fwdData.data, fwdData.length );
- p += fwdData.length;
-
- /* We need to do this in order to allow our GSS-API */
- retval = krb5_auth_con_set_req_cksumtype( context, *auth_context, GSSAPI_CHECKSUM );
- if (retval) {
- goto out;
- }
-
- /* We now have a service ticket, now turn it into an AP-REQ. */
- authenticator->length = fwdData.length + GSSAPI_CHECKSUM_SIZE;
-
- /* Caller should call free() when they're done with this. */
- authenticator->data = (char *)pChksum;
-
- out:
-
- /* Remove that input data, we never needed it anyway. */
- if (fwdData.length > 0) {
- krb5_free_data_contents( context, &fwdData );
- }
-
- return retval;
-}
-#endif
-
#if defined(HAVE_KRB5_GET_CREDS_OPT_SET_IMPERSONATE) && \
defined(HAVE_KRB5_GET_CREDS_OPT_ALLOC) && \
defined(HAVE_KRB5_GET_CREDS)
krb5_principal principal)
{
#ifdef HAVE_KRB5_PRINCIPAL_GET_REALM /* Heimdal */
- return krb5_principal_get_realm(context, principal);
+ return discard_const_p(char, krb5_principal_get_realm(context, principal));
#elif defined(krb5_princ_realm) /* MIT */
krb5_data *realm;
realm = krb5_princ_realm(context, principal);
- return (char *)realm->data;
+ return discard_const_p(char, realm->data);
#else
return NULL;
#endif
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
- int cli_krb5_get_ticket(const char *principal, time_t time_offset,
- DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
+ int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx,
+ const char *principal, time_t time_offset,
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
+ uint32_t extra_ap_opts,
const char *ccname, time_t *tgs_expire,
const char *impersonate_princ_s)
{
return 1;
}
-#endif
+bool unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_pac_data)
+{
+ DEBUG(0,("NO KERBEROS SUPPORT\n"));
+ return false;
+}
+
+#endif /* HAVE_KRB5 */