summaryrefslogtreecommitdiff
path: root/source4/libcli/auth/kerberos_verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libcli/auth/kerberos_verify.c')
-rw-r--r--source4/libcli/auth/kerberos_verify.c184
1 files changed, 96 insertions, 88 deletions
diff --git a/source4/libcli/auth/kerberos_verify.c b/source4/libcli/auth/kerberos_verify.c
index d00394fd79..92980f1122 100644
--- a/source4/libcli/auth/kerberos_verify.c
+++ b/source4/libcli/auth/kerberos_verify.c
@@ -29,6 +29,9 @@
#ifdef HAVE_KRB5
+#if !defined(HAVE_KRB5_PRINC_COMPONENT)
+const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int );
+#endif
static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
{
DATA_BLOB out;
@@ -65,21 +68,23 @@ static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
ads_keytab_add_entry function for details.
***********************************************************************************/
-static krb5_error_code ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context,
- const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt,
- krb5_keyblock *keyblock)
+static krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_context context,
+ krb5_auth_context auth_context,
+ const char *service,
+ const DATA_BLOB *ticket, krb5_data *p_packet,
+ krb5_ticket **pp_tkt,
+ krb5_keyblock *keyblock)
{
krb5_error_code ret = 0;
-
+ BOOL auth_ok = False;
krb5_keytab keytab = NULL;
- krb5_kt_cursor cursor;
- krb5_keytab_entry kt_entry;
- char *princ_name = NULL;
-
- ZERO_STRUCT(kt_entry);
- ZERO_STRUCT(cursor);
-
- ZERO_STRUCTP(keyblock);
+ char *my_fqdn;
+ fstring my_name;
+ fstring my_Fqdn, my_NAME;
+ char *p_fqdn;
+ char *host_princ_s[18];
+ krb5_principal host_princ;
+ int i;
ret = krb5_kt_default(context, &keytab);
if (ret) {
@@ -87,73 +92,74 @@ static krb5_error_code ads_keytab_verify_ticket(krb5_context context, krb5_auth_
goto out;
}
- ret = krb5_kt_start_seq_get(context, keytab, &cursor);
- if (ret) {
- DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s)\n", error_message(ret)));
- goto out;
+ /* Generate the list of principal names which we expect clients might
+ * want to use for authenticating to the file service. */
+
+ fstrcpy(my_name, lp_netbios_name());
+ strlower_m(my_name);
+
+ fstrcpy(my_NAME, lp_netbios_name());
+ strupper_m(my_NAME);
+
+ my_fqdn = name_to_fqdn(mem_ctx, lp_netbios_name());
+ strlower_m(my_fqdn);
+
+ p_fqdn = strchr_m(my_fqdn, '.');
+ fstrcpy(my_Fqdn, my_NAME);
+ if (p_fqdn) {
+ fstrcat(my_Fqdn, p_fqdn);
}
- while (!(ret = krb5_kt_next_entry(context, keytab, &kt_entry, &cursor))) {
- ret = krb5_unparse_name(context, kt_entry.principal, &princ_name);
+ asprintf(&host_princ_s[0], "%s$@%s", my_name, lp_realm());
+ asprintf(&host_princ_s[1], "%s$@%s", my_NAME, lp_realm());
+ asprintf(&host_princ_s[2], "host/%s@%s", my_name, lp_realm());
+ asprintf(&host_princ_s[3], "host/%s@%s", my_NAME, lp_realm());
+ asprintf(&host_princ_s[4], "host/%s@%s", my_fqdn, lp_realm());
+ asprintf(&host_princ_s[5], "host/%s@%s", my_Fqdn, lp_realm());
+ asprintf(&host_princ_s[6], "HOST/%s@%s", my_name, lp_realm());
+ asprintf(&host_princ_s[7], "HOST/%s@%s", my_NAME, lp_realm());
+ asprintf(&host_princ_s[8], "HOST/%s@%s", my_fqdn, lp_realm());
+ asprintf(&host_princ_s[9], "HOST/%s@%s", my_Fqdn, lp_realm());
+ asprintf(&host_princ_s[10], "%s/%s@%s", service, my_name, lp_realm());
+ asprintf(&host_princ_s[11], "%s/%s@%s", service, my_NAME, lp_realm());
+ asprintf(&host_princ_s[12], "%s/%s@%s", service, my_fqdn, lp_realm());
+ asprintf(&host_princ_s[13], "%s/%s@%s", service, my_Fqdn, lp_realm());
+ asprintf(&host_princ_s[14], "%s/%s@%s", strupper_talloc(mem_ctx, service), my_name, lp_realm());
+ asprintf(&host_princ_s[15], "%s/%s@%s", strupper_talloc(mem_ctx, service), my_NAME, lp_realm());
+ asprintf(&host_princ_s[16], "%s/%s@%s", strupper_talloc(mem_ctx, service), my_fqdn, lp_realm());
+ asprintf(&host_princ_s[17], "%s/%s@%s", strupper_talloc(mem_ctx, service), my_Fqdn, lp_realm());
+
+ /* Now try to verify the ticket using the key associated with each of
+ * the principals which we think clients will expect us to be
+ * participating as. */
+ for (i = 0; i < sizeof(host_princ_s) / sizeof(host_princ_s[0]); i++) {
+ host_princ = NULL;
+ ret = krb5_parse_name(context, host_princ_s[i], &host_princ);
if (ret) {
- DEBUG(1, ("ads_keytab_verify_ticket: krb5_unparse_name failed (%s)\n", error_message(ret)));
+ DEBUG(1, ("ads_keytab_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
+ host_princ_s[i], error_message(ret)));
goto out;
}
- DEBUG(10, ("Checking principal: %s\n", princ_name));
- /* Look for a CIFS ticket */
- if (!strncasecmp(princ_name, "cifs/", 5) ||
- !strncasecmp(princ_name, "host/", 5) ||
- !strncasecmp(princ_name, "ldap/", 5)) {
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK
- krb5_auth_con_setuseruserkey(context, auth_context, &kt_entry.keyblock);
-#else
- krb5_auth_con_setuseruserkey(context, auth_context, &kt_entry.key);
-#endif
-
- p_packet->length = ticket->length;
- p_packet->data = (krb5_pointer)ticket->data;
-
- ret = krb5_rd_req(context, &auth_context, p_packet, NULL, NULL, NULL, pp_tkt);
- if (!ret) {
- unsigned int keytype;
- krb5_free_unparsed_name(context, princ_name);
- princ_name = NULL;
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK
- keytype = (unsigned int) kt_entry.keyblock.keytype;
- copy_EncryptionKey(&kt_entry.keyblock, keyblock);
-#else
- keytype = (unsigned int) kt_entry.key.enctype;
- /* TODO: copy the keyblock on MIT krb5*/
-#endif
- DEBUG(10,("ads_keytab_verify_ticket: enc type [%u] decrypted message !\n",
- keytype));
-
- break;
- }
- }
- krb5_free_unparsed_name(context, princ_name);
- princ_name = NULL;
+ p_packet->length = ticket->length;
+ p_packet->data = (krb5_pointer)ticket->data;
+ *pp_tkt = NULL;
+ ret = krb5_rd_req(context, &auth_context, p_packet, host_princ, keytab, NULL, pp_tkt);
+ krb5_free_principal(context, host_princ);
+ if (ret) {
+ DEBUG(0, ("krb5_rd_req(%s) failed: %s\n", host_princ_s[i], error_message(ret)));
+ } else {
+ DEBUG(10,("krb5_rd_req succeeded for principal %s\n", host_princ_s[i]));
+ auth_ok = True;
+ break;
+ }
}
- if (ret && ret != KRB5_KT_END) {
- /* This failed because something went wrong, not because the keytab file was empty. */
- DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_next_entry failed (%s)\n", error_message(ret)));
- } else if (ret == KRB5_KT_END) {
- DEBUG(10, ("ads_keytab_verify_ticket: no keytab entry found: %s\n", error_message(ret)));
- } else {
- DEBUG(10, ("ads_keytab_verify_ticket: keytab entry found: %s\n", princ_name));
+
+ for (i = 0; i < sizeof(host_princ_s) / sizeof(host_princ_s[0]); i++) {
+ SAFE_FREE(host_princ_s[i]);
}
+
out:
- if (princ_name) {
- krb5_free_unparsed_name(context, princ_name);
- }
- {
- krb5_kt_cursor zero_csr;
- ZERO_STRUCT(zero_csr);
- if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
- krb5_kt_end_seq_get(context, keytab, &cursor);
- }
- }
if (keytab) {
krb5_kt_close(context, keytab);
}
@@ -165,10 +171,12 @@ static krb5_error_code ads_keytab_verify_ticket(krb5_context context, krb5_auth_
Try to verify a ticket using the secrets.tdb.
***********************************************************************************/
-static krb5_error_code ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context,
- krb5_principal host_princ,
- const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt,
- krb5_keyblock *keyblock)
+static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx, krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_principal host_princ,
+ const DATA_BLOB *ticket, krb5_data *p_packet,
+ krb5_ticket **pp_tkt,
+ krb5_keyblock *keyblock)
{
krb5_error_code ret = 0;
char *password_s = NULL;
@@ -250,12 +258,13 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, krb5_auth
***********************************************************************************/
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
- krb5_context context,
- krb5_auth_context auth_context,
- const char *realm, const DATA_BLOB *ticket,
- char **principal, DATA_BLOB *auth_data,
- DATA_BLOB *ap_rep,
- krb5_keyblock *keyblock)
+ krb5_context context,
+ krb5_auth_context auth_context,
+ const char *realm, const char *service,
+ const DATA_BLOB *ticket,
+ char **principal, DATA_BLOB *auth_data,
+ DATA_BLOB *ap_rep,
+ krb5_keyblock *keyblock)
{
NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
krb5_data packet;
@@ -267,8 +276,6 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, krb5_auth
char *host_princ_s = NULL;
BOOL got_replay_mutex = False;
- char *myname;
-
char *malloc_principal;
ZERO_STRUCT(packet);
@@ -279,9 +286,8 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, krb5_auth
like. We have to go through all this to allow us to store
the secret internally, instead of using /etc/krb5.keytab */
- myname = name_to_fqdn(mem_ctx, lp_netbios_name());
- strlower_m(myname);
- asprintf(&host_princ_s, "host/%s@%s", myname, lp_realm());
+ asprintf(&host_princ_s, "%s$", lp_netbios_name());
+ strlower_m(host_princ_s);
ret = krb5_parse_name(context, host_princ_s, &host_princ);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
@@ -316,11 +322,13 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, krb5_auth
goto out;
}
- ret = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt, keyblock);
+ ret = ads_keytab_verify_ticket(mem_ctx, context, auth_context,
+ service, ticket, &packet, &tkt, keyblock);
if (ret) {
DEBUG(10, ("ads_secrets_verify_ticket: using host principal: [%s]\n", host_princ_s));
- ret = ads_secrets_verify_ticket(context, auth_context, host_princ,
- ticket, &packet, &tkt, keyblock);
+ ret = ads_secrets_verify_ticket(mem_ctx, context, auth_context,
+ host_princ, ticket,
+ &packet, &tkt, keyblock);
}
release_server_mutex();