r1418: Merge Samba 3.0's recent kerberos changes into Samba4. None of this
authorAndrew Bartlett <abartlet@samba.org>
Fri, 9 Jul 2004 11:46:42 +0000 (11:46 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:56:54 +0000 (12:56 -0500)
is used yet.

Andrew Bartlett

source/libads/config.m4
source/libcli/auth/clikrb5.c
source/libcli/auth/kerberos.c
source/libcli/auth/kerberos_verify.c

index c6029a4d80c71337b9c24e3e4bbbf22fdc4b1e68..2e4041829d13eb33670aafd051f911aaa93ab99a 100644 (file)
@@ -113,7 +113,7 @@ if test x"$with_ldap_support" != x"yes"; then
 fi
 
 if test x"$with_ads_support" != x"no"; then
-  FOUND_KRB5=no
+
   # Do no harm to the values of CFLAGS and LIBS while testing for
   # Kerberos support.
 
@@ -260,6 +260,7 @@ if test x"$with_ads_support" != x"no"; then
   # now see if we can find the krb5 libs in standard paths
   # or as specified above
   AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_mk_req_extended)
+  AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_kt_compare)
 
   ########################################################
   # now see if we can find the gssapi libs in standard paths
@@ -282,6 +283,9 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_unparsed_name, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_keytab_entry_contents, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_kt_free_entry, $KRB5_LIBS)
 
   LIBS="$LIBS $KRB5_LIBS"
   
@@ -364,6 +368,18 @@ if test x"$with_ads_support" != x"no"; then
               [Whether the AP_OPTS_USE_SUBKEY ap option is available])
   fi
 
+  AC_CACHE_CHECK([for KV5M_KEYTAB],
+                 samba_cv_HAVE_KV5M_KEYTAB,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_keytab_entry entry; entry.magic = KV5M_KEYTAB;],
+      samba_cv_HAVE_KV5M_KEYTAB=yes,
+      samba_cv_HAVE_KV5M_KEYTAB=no)])
+
+  if test x"$samba_cv_HAVE_KV5M_KEYTAB" = x"yes"; then
+      AC_DEFINE(HAVE_KV5M_KEYTAB,1,
+             [Whether the KV5M_KEYTAB option is available])
+  fi
+
   AC_CACHE_CHECK([for the krb5_princ_component macro],
                 samba_cv_HAVE_KRB5_PRINC_COMPONENT,[
     AC_TRY_LINK([#include <krb5.h>],
@@ -376,28 +392,6 @@ if test x"$with_ads_support" != x"no"; then
                [Whether krb5_princ_component is available])
   fi
 
-  AC_CACHE_CHECK([for memory keytab support],
-                samba_cv_HAVE_MEMORY_KEYTAB,[
-    AC_TRY_RUN([
-#include<krb5.h>
-  main()
-  {
-    krb5_context context;
-    krb5_keytab keytab;
-    
-    krb5_init_context(&context);
-    if (krb5_kt_resolve(context, "MEMORY:", &keytab))
-      exit(1);
-    exit(0);
-  }], 
-  samba_cv_HAVE_MEMORY_KEYTAB=yes,
-  samba_cv_HAVE_MEMORY_KEYTAB=no)])
-
-  if test x"$samba_cv_HAVE_MEMORY_KEYTAB" = x"yes"; then
-      AC_DEFINE(HAVE_MEMORY_KEYTAB,1,
-               [Whether in-memory keytabs are supported])
-  fi
-
   AC_CACHE_CHECK([for key in krb5_keytab_entry],
                  samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEY,[
     AC_TRY_COMPILE([#include <krb5.h>],
@@ -425,10 +419,8 @@ if test x"$with_ads_support" != x"no"; then
   if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then
     AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support])
     AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
-    AC_MSG_CHECKING(whether Active Directory and KRB5 support is used)
+    AC_MSG_CHECKING(whether Active Directory and krb5 support is used)
     AC_MSG_RESULT(yes)
-    with_ads_support=yes
-    SMB_EXT_LIB_ENABLE(KRB5,YES)
   else
     if test x"$with_ads_support" = x"yes"; then
        AC_MSG_ERROR(libkrb5 is needed for Active Directory support)
@@ -438,9 +430,48 @@ if test x"$with_ads_support" != x"no"; then
     KRB5_LIBS=""
     with_ads_support=no 
   fi
-  LIBS="$ac_save_LIBS"
+
+  AC_CACHE_CHECK([for WRFILE: keytab support],
+                samba_cv_HAVE_WRFILE_KEYTAB,[
+    AC_TRY_RUN([
+#include<krb5.h>
+  main()
+  {
+    krb5_context context;
+    krb5_keytab keytab;
+
+    krb5_init_context(&context);
+    if (krb5_kt_resolve(context, "WRFILE:api", &keytab))
+      exit(0);
+    exit(1);
+  }],
+  samba_cv_HAVE_WRFILE_KEYTAB=no,
+  samba_cv_HAVE_WRFILE_KEYTAB=yes)])
+
+  if test x"$samba_cv_HAVE_WRFILE_KEYTAB" = x"yes"; then
+      AC_DEFINE(HAVE_WRFILE_KEYTAB,1,
+               [Whether the WRFILE:-keytab is supported])
+  fi
+
+  AC_CACHE_CHECK([for krb5_princ_realm returns krb5_realm or krb5_data],
+               samba_cv_KRB5_PRINC_REALM_RETURNS_REALM,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+    [
+    krb5_context context;
+    krb5_principal principal;
+    krb5_realm realm; realm = *krb5_princ_realm(context, principal);],
+    samba_cv_KRB5_PRINC_REALM_RETURNS_REALM=yes,
+    samba_cv_KRB5_PRINC_REALM_RETURNS_REALM=no)])
+
+  if test x"$samba_cv_KRB5_PRINC_REALM_RETURNS_REALM" = x"yes"; then
+    AC_DEFINE(KRB5_PRINC_REALM_RETURNS_REALM,1,
+              [Whether krb5_princ_realm returns krb5_realm or krb5_data])
+  fi
+
+LIBS="$ac_save_LIBS"
 fi
 
+
 SMB_EXT_LIB(LDAP,[${LDAP_LIBS}],[${LDAP_CFLAGS}],[${LDAP_CPPFLAGS}],[${LDAP_LDFLAGS}])
 SMB_EXT_LIB(KRB5,[${KRB5_LIBS}],[${KRB5_CFLAGS}],[${KRB5_CPPFLAGS}],[${KRB5_LDFLAGS}])
 
index 6e19d4dc184b76bb6214508bc78649c01262d613..b3aa9008ca4b93d783fa03c628ca73b3f040a3dc 100644 (file)
 #endif
 
 #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES)
-krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
+ krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
                                            krb5_enctype **enctypes)
 {
        return krb5_get_permitted_enctypes(context, enctypes);
 }
 #elif defined(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES)
-krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
+ krb5_error_code get_kerberos_allowed_etypes(krb5_context context, 
                                            krb5_enctype **enctypes)
 {
        return krb5_get_default_in_tkt_etypes(context, enctypes);
@@ -434,9 +434,12 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
 failed:
 
        if ( context ) {
-#if 0  /* JERRY -- disabled since it causes heimdal 0.6.1rc3 to die 
-          SuSE 9.1 Pro */
+/* Removed by jra. They really need to fix their kerberos so we don't leak memory. 
+ JERRY -- disabled since it causes heimdal 0.6.1rc3 to die
+          SuSE 9.1 Pro 
+*/
                if (ccdef)
+#if 0 /* redisabled by gd :) at least until any official heimdal version has it fixed. */
                        krb5_cc_close(context, ccdef);
 #endif
                if (auth_context)
@@ -486,6 +489,17 @@ failed:
 }
 #endif
 
+ krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry)
+{
+#if defined(HAVE_KRB5_KT_FREE_ENTRY)
+       return krb5_kt_free_entry(context, kt_entry);
+#elif defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS)
+       return krb5_free_keytab_entry_contents(context, kt_entry);
+#else
+#error UNKNOWN_KT_FREE_FUNCTION
+#endif
+}
+
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
index e8bf4b08462484dadd7cbedb0630361e0b8a2c65..97b895a2418a976b272512da720c528c2e3beacb 100644 (file)
@@ -79,9 +79,9 @@ int kerberos_kinit_password(const char *principal, const char *password, int tim
                return code;
        }
        
-       if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, NULL
+       if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, password
                                                 kerb_prompter, 
-                                                password, 0, NULL, NULL))) {
+                                                NULL, 0, NULL, NULL))) {
                krb5_free_principal(ctx, me);
                krb5_free_context(ctx);         
                return code;
index 805a3f570f99180ccd5c39ce502a4f4e930715a3..e93d3aa6e8dd3b77e846ffb30c8aa90f493d0b86 100644 (file)
 
 #ifdef HAVE_KRB5
 
-/*
-  verify an incoming ticket and parse out the principal name and 
-  authorization_data if available 
-*/
+/**********************************************************************************
+ Try to verify a ticket using the system keytab... the system keytab has kvno -1 entries, so
+ it's more like what microsoft does... see comment in utils/net_ads.c in the
+ ads_keytab_add_entry function for details.
+***********************************************************************************/
+
+static BOOL 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_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);
+
+       ret = krb5_kt_default(context, &keytab);
+       if (ret) {
+               DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_default failed (%s)\n", error_message(ret)));
+               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;
+       }
+
+       while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
+               ret = krb5_unparse_name(context, kt_entry.principal, &princ_name);
+               if (ret) {
+                       DEBUG(1, ("ads_keytab_verify_ticket: krb5_unparse_name failed (%s)\n", error_message(ret)));
+                       goto out;
+               }
+               /* Look for a CIFS ticket */
+               if (!StrnCaseCmp(princ_name, "cifs/", 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;
+
+                       if (!(ret = krb5_rd_req(context, &auth_context, p_packet, NULL, NULL, NULL, pp_tkt))) {
+                               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;
+#else
+                               keytype = (unsigned int) kt_entry.key.enctype;
+#endif
+                               DEBUG(10,("ads_keytab_verify_ticket: enc type [%u] decrypted message !\n",
+                                         keytype));
+                               auth_ok = True;
+                               break;
+                       }
+               }
+               krb5_free_unparsed_name(context, princ_name);
+               princ_name = NULL;
+       }
+       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)));
+               goto out;
+       }
+
+  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);
+       }
+
+       return auth_ok;
+}
+
+/**********************************************************************************
+ Try to verify a ticket using the secrets.tdb.
+***********************************************************************************/
+
+static BOOL 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_error_code ret = 0;
+       BOOL auth_ok = False;
+       char *password_s = NULL;
+       krb5_data password;
+       krb5_enctype *enctypes = NULL;
+       int i;
+
+       if (!secrets_init()) {
+               DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
+               return False;
+       }
+
+       password_s = secrets_fetch_machine_password(lp_workgroup());
+       if (!password_s) {
+               DEBUG(1,("ads_secrets_verify_ticket: failed to fetch machine password\n"));
+               return False;
+       }
+
+       password.data = password_s;
+       password.length = strlen(password_s);
+
+       /* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
+
+       if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
+               DEBUG(1,("ads_secrets_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", 
+                        error_message(ret)));
+               goto out;
+       }
+
+       p_packet->length = ticket->length;
+       p_packet->data = (krb5_pointer)ticket->data;
+
+       /* We need to setup a auth context with each possible encoding type in turn. */
+       for (i=0;enctypes[i];i++) {
+               krb5_keyblock *key = NULL;
+
+               if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
+                       goto out;
+               }
+       
+               if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
+                       SAFE_FREE(key);
+                       continue;
+               }
+
+               krb5_auth_con_setuseruserkey(context, auth_context, key);
+
+               krb5_free_keyblock(context, key);
+
+               if (!(ret = krb5_rd_req(context, &auth_context, p_packet, 
+                                       NULL,
+                                       NULL, NULL, pp_tkt))) {
+                       DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
+                               (unsigned int)enctypes[i] ));
+                       auth_ok = True;
+                       break;
+               }
+       
+               DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
+                               ("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
+                               (unsigned int)enctypes[i], error_message(ret)));
+       }
+
+ out:
+
+       free_kerberos_etypes(context, enctypes);
+       SAFE_FREE(password_s);
+
+       return auth_ok;
+}
+
+/**********************************************************************************
+ Verify an incoming ticket and parse out the principal name and 
+ authorization_data if available.
+***********************************************************************************/
+
 NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, 
                           char **principal, DATA_BLOB *auth_data,
                           DATA_BLOB *ap_rep,
@@ -41,43 +213,21 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        krb5_data packet;
        krb5_ticket *tkt = NULL;
        krb5_rcache rcache = NULL;
-       int ret, i;
-       krb5_keyblock *key = NULL;
+       int ret;
 
-       krb5_principal host_princ;
+       krb5_principal host_princ = NULL;
        char *host_princ_s = NULL;
-       BOOL free_host_princ = False;
        BOOL got_replay_mutex = False;
 
        fstring myname;
-       char *password_s = NULL;
-       krb5_data password;
-       krb5_enctype *enctypes = NULL;
-#if 0
-       krb5_address local_addr;
-       krb5_address remote_addr;
-#endif
        BOOL auth_ok = False;
 
        ZERO_STRUCT(packet);
-       ZERO_STRUCT(password);
        ZERO_STRUCTP(auth_data);
        ZERO_STRUCTP(ap_rep);
+       ZERO_STRUCTP(session_key);
 
-       if (!secrets_init()) {
-               DEBUG(1,("ads_verify_ticket: secrets_init failed\n"));
-               return NT_STATUS_LOGON_FAILURE;
-       }
-
-       password_s = secrets_fetch_machine_password(lp_workgroup());
-       if (!password_s) {
-               DEBUG(1,("ads_verify_ticket: failed to fetch machine password\n"));
-               return NT_STATUS_LOGON_FAILURE;
-       }
-
-       password.data = password_s;
-       password.length = strlen(password_s);
-
+       initialize_krb5_error_table();
        ret = krb5_init_context(&context);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret)));
@@ -87,7 +237,6 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        ret = krb5_set_default_realm(context, realm);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
@@ -98,22 +247,29 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        ret = krb5_auth_con_init(context, &auth_context);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
-       fstrcpy(myname, global_myname());
+       name_to_fqdn(myname, global_myname());
        strlower_m(myname);
-       asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
+       asprintf(&host_princ_s, "host/%s@%s", myname, lp_realm());
        ret = krb5_parse_name(context, host_princ_s, &host_princ);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
                                        host_princ_s, error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
-       free_host_princ = True;
+
+       /* Lock a mutex surrounding the replay as there is no locking in the MIT krb5
+        * code surrounding the replay cache... */
+
+       if (!grab_server_mutex("replay cache mutex")) {
+               DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
+               goto out;
+       }
+
+       got_replay_mutex = True;
 
        /*
         * JRA. We must set the rcache here. This will prevent replay attacks.
@@ -122,67 +278,19 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
        ret = krb5_auth_con_setrcache(context, auth_context, rcache);
        if (ret) {
                DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache failed (%s)\n", error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
-       /* CIFS doesn't use addresses in tickets. This would breat NAT. JRA */
-
-       if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
-               DEBUG(1,("ads_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", 
-                        error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
-               goto out;
-       }
-
-       /* Lock a mutex surrounding the replay as there is no locking in the MIT krb5
-        * code surrounding the replay cache... */
-
-       if (!grab_server_mutex("replay cache mutex")) {
-               DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
-               sret = NT_STATUS_LOGON_FAILURE;
-               goto out;
-       }
-
-       got_replay_mutex = True;
-
-       /* We need to setup a auth context with each possible encoding type in turn. */
-       for (i=0;enctypes[i];i++) {
-               if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
-                       sret = NT_STATUS_NO_MEMORY;
-                       goto out;
-               }
-       
-               if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
-                       continue;
-               }
-
-               krb5_auth_con_setuseruserkey(context, auth_context, key);
-
-               krb5_free_keyblock(context, key);
-
-               packet.length = ticket->length;
-               packet.data = (krb5_pointer)ticket->data;
-
-               if (!(ret = krb5_rd_req(context, &auth_context, &packet, 
-                                       NULL,
-                                       NULL, NULL, &tkt))) {
-                       DEBUG(10,("ads_verify_ticket: enc type [%u] decrypted message !\n",
-                               (unsigned int)enctypes[i] ));
-                       auth_ok = True;
-                       break;
-               }
-       
-               DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
-                               ("ads_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
-                               (unsigned int)enctypes[i], error_message(ret)));
+       auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt);
+       if (!auth_ok) {
+               auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
+                                                       ticket, &packet, &tkt);
        }
 
        release_server_mutex();
@@ -191,7 +299,6 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        if (!auth_ok) {
                DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", 
                         error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
@@ -199,12 +306,12 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        if (ret) {
                DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
                        error_message(ret)));
-               sret = NT_STATUS_LOGON_FAILURE;
                goto out;
        }
 
        *ap_rep = data_blob(packet.data, packet.length);
-       free(packet.data);
+       SAFE_FREE(packet.data);
+       packet.length = 0;
 
        get_krb5_smb_session_key(context, auth_context, session_key, True);
        dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);
@@ -213,7 +320,6 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        file_save("/tmp/ticket.dat", ticket->data, ticket->length);
 #endif
 
-       /* auth_data is the PAC */
        get_auth_data_from_tkt(auth_data, tkt);
 
 #if 0
@@ -236,29 +342,35 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
 
  out:
 
-       if (got_replay_mutex)
+       if (got_replay_mutex) {
                release_server_mutex();
+       }
 
-       if (!NT_STATUS_IS_OK(sret))
+       if (!NT_STATUS_IS_OK(sret)) {
                data_blob_free(auth_data);
+       }
 
-       if (!NT_STATUS_IS_OK(sret))
+       if (!NT_STATUS_IS_OK(sret)) {
                data_blob_free(ap_rep);
+       }
 
-       if (free_host_princ)
+       if (host_princ) {
                krb5_free_principal(context, host_princ);
+       }
 
-       if (tkt != NULL)
+       if (tkt != NULL) {
                krb5_free_ticket(context, tkt);
-       free_kerberos_etypes(context, enctypes);
-       SAFE_FREE(password_s);
+       }
+
        SAFE_FREE(host_princ_s);
 
-       if (auth_context)
+       if (auth_context) {
                krb5_auth_con_free(context, auth_context);
+       }
 
-       if (context)
+       if (context) {
                krb5_free_context(context);
+       }
 
        return sret;
 }