r11200: Reposition the creation of the kerberos keytab for GSSAPI and Krb5
authorAndrew Bartlett <abartlet@samba.org>
Thu, 20 Oct 2005 03:47:55 +0000 (03:47 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:45:00 +0000 (13:45 -0500)
authentication.  This pulls the creating of the keytab back to the
credentials code, and removes the special case of 'use keberos keytab
= yes' for now.

This allows (and requires) the callers to specify the credentials for
the server credentails to GENSEC.  This allows kpasswdd (soon to be
added) to use a different set of kerberos credentials.

The 'use kerberos keytab' code will be moved into the credentials
layer, as the layers below now expect a keytab.

We also now allow for the old secret to be stored into the
credentials, allowing service password changes.

Andrew Bartlett
(This used to be commit 205f77c579ac8680c85f713a76de5767189c627b)

17 files changed:
source4/auth/credentials/credentials.c
source4/auth/credentials/credentials.h
source4/auth/credentials/credentials_files.c
source4/auth/credentials/credentials_krb5.c
source4/auth/gensec/gensec.c
source4/auth/gensec/gensec_gssapi.c
source4/auth/gensec/gensec_krb5.c
source4/auth/kerberos/kerberos.h
source4/auth/kerberos/kerberos_util.c
source4/auth/kerberos/kerberos_verify.c
source4/ldap_server/ldap_bind.c
source4/rpc_server/dcesrv_auth.c
source4/setup/secrets.ldif
source4/smb_server/negprot.c
source4/smb_server/sesssetup.c
source4/smb_server/smb_server.h
source4/utils/ntlm_auth.c

index f24c4e22316d083efb0f3f187c03064c9133e548..9be877dd2c63610a0aba927f3b7272936524bdaa 100644 (file)
@@ -46,7 +46,12 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
        cred->domain_obtained = CRED_UNINITIALISED;
        cred->realm_obtained = CRED_UNINITIALISED;
        cred->ccache_obtained = CRED_UNINITIALISED;
+       cred->keytab_obtained = CRED_UNINITIALISED;
        cred->principal_obtained = CRED_UNINITIALISED;
+
+       cred->old_password = NULL;
+       cred->smb_krb5_context = NULL;
+
        return cred;
 }
 
@@ -209,6 +214,28 @@ BOOL cli_credentials_set_password_callback(struct cli_credentials *cred,
        return False;
 }
 
+/**
+ * Obtain the 'old' password for this credentials context (used for join accounts).
+ * @param cred credentials context
+ * @retval If set, the cleartext password, otherwise NULL
+ */
+const char *cli_credentials_get_old_password(struct cli_credentials *cred)
+{
+       if (cred->machine_account_pending) {
+               cli_credentials_set_machine_account(cred);
+       }
+
+       return cred->old_password;
+}
+
+BOOL cli_credentials_set_old_password(struct cli_credentials *cred, 
+                                     const char *val, 
+                                     enum credentials_obtained obtained)
+{
+       cred->old_password = talloc_strdup(cred, val);
+       return True;
+}
+
 /**
  * Obtain the password for this credentials context.
  * @param cred credentials context
index 324b5184626716597dabe8c997151eafd2732ab3..aa2a0d0ac2df385ece60aa7093ebdb88ec438993 100644 (file)
@@ -48,10 +48,12 @@ struct cli_credentials {
        enum credentials_obtained realm_obtained;
        enum credentials_obtained ccache_obtained;
        enum credentials_obtained principal_obtained;
+       enum credentials_obtained keytab_obtained;
 
        const char *workstation;
        const char *username;
        const char *password;
+       const char *old_password;
        const char *domain;
        const char *realm;
        const char *principal;
@@ -59,6 +61,7 @@ struct cli_credentials {
        struct samr_Password *nt_hash;
 
        struct ccache_container *ccache;
+       struct keytab_container *keytab;
 
        const char *(*workstation_cb) (struct cli_credentials *);
        const char *(*password_cb) (struct cli_credentials *);
@@ -74,6 +77,8 @@ struct cli_credentials {
        enum netr_SchannelType secure_channel_type;
        int kvno;
 
+       struct smb_krb5_context *smb_krb5_context;
+
        /* We are flagged to get machine account details from the
         * secrets.ldb when we are asked for a username or password */
 
index 353ff61720ef32d256b2a0411e8a54aff252ad70..aa0a7f32131edaae863bcf69af0b86187178667a 100644 (file)
@@ -164,7 +164,9 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file,
  * @param cred Credentials structure to fill in
  * @retval NTSTATUS error detailing any failure
  */
-NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
+static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, 
+                                           const char *base,
+                                           const char *filter)
 {
        TALLOC_CTX *mem_ctx;
        
@@ -184,6 +186,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
        
        const char *machine_account;
        const char *password;
+       const char *old_password;
        const char *domain;
        const char *realm;
        enum netr_SchannelType sct;
@@ -201,10 +204,9 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
 
        /* search for the secret record */
        ldb_ret = gendb_search(ldb,
-                              mem_ctx, ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), 
+                              mem_ctx, ldb_dn_explode(mem_ctx, base), 
                               &msgs, attrs,
-                              SECRETS_PRIMARY_DOMAIN_FILTER, 
-                              cli_credentials_get_domain(cred));
+                              "%s", filter);
        if (ldb_ret == 0) {
                DEBUG(1, ("Could not find join record to domain: %s\n",
                          cli_credentials_get_domain(cred)));
@@ -218,6 +220,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
        }
        
        password = ldb_msg_find_string(msgs[0], "secret", NULL);
+       old_password = ldb_msg_find_string(msgs[0], "priorSecret", NULL);
 
        machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL);
 
@@ -277,6 +280,52 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
        return NT_STATUS_OK;
 }
 
+/**
+ * Fill in credentials for the machine trust account, from the secrets database.
+ * 
+ * @param cred Credentials structure to fill in
+ * @retval NTSTATUS error detailing any failure
+ */
+NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
+{
+       char *filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, 
+                                      cli_credentials_get_domain(cred));
+       return cli_credentials_set_secrets(cred, SECRETS_PRIMARY_DOMAIN_DN,
+                                          filter);
+}
+
+/**
+ * Fill in credentials for the machine trust account, from the secrets database.
+ * 
+ * @param cred Credentials structure to fill in
+ * @retval NTSTATUS error detailing any failure
+ */
+NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred)
+{
+       char *filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH,
+                                      cli_credentials_get_realm(cred),
+                                      cli_credentials_get_domain(cred));
+       return cli_credentials_set_secrets(cred, SECRETS_PRINCIPALS_DN,
+                                          filter);
+}
+
+/**
+ * Fill in credentials for the machine trust account, from the secrets database.
+ * 
+ * @param cred Credentials structure to fill in
+ * @retval NTSTATUS error detailing any failure
+ */
+NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred,
+                                             const char *serviceprincipal)
+{
+       char *filter = talloc_asprintf(cred, SECRETS_PRINCIPAL_SEARCH,
+                                      cli_credentials_get_realm(cred),
+                                      cli_credentials_get_domain(cred),
+                                      serviceprincipal);
+       return cli_credentials_set_secrets(cred, SECRETS_PRINCIPALS_DN,
+                                          filter);
+}
+
 /**
  * Ask that when required, the credentials system will be filled with
  * machine trust account, from the secrets database.
index fb3239494e7044803695830bae7aef198262248c..b20d9ee750ad21aa367ef182a8add1f48ebd3215 100644 (file)
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
 
+int cli_credentials_get_krb5_context(struct cli_credentials *cred, 
+                                    struct smb_krb5_context **smb_krb5_context) 
+{
+       int ret;
+       if (cred->smb_krb5_context) {
+               *smb_krb5_context = cred->smb_krb5_context;
+               return 0;
+       }
+
+       ret = smb_krb5_init_context(cred, &cred->smb_krb5_context);
+       if (ret) {
+               return ret;
+       }
+       *smb_krb5_context = cred->smb_krb5_context;
+       return 0;
+}
 
 int cli_credentials_set_from_ccache(struct cli_credentials *cred, 
                                    enum credentials_obtained obtained)
@@ -95,11 +111,13 @@ int cli_credentials_set_ccache(struct cli_credentials *cred,
                return ENOMEM;
        }
 
-       ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context);
+       ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context);
        if (ret) {
                talloc_free(ccc);
                return ret;
        }
+       talloc_reference(ccc, ccc->smb_krb5_context);
+
        if (name) {
                ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache);
                if (ret) {
@@ -162,7 +180,7 @@ int cli_credentials_new_ccache(struct cli_credentials *cred)
        }
 
        ccache_name = talloc_asprintf(ccc, "MEMORY:%s", 
-                             rand_string);
+                                     rand_string);
        talloc_free(rand_string);
 
        if (!ccache_name) {
@@ -170,12 +188,12 @@ int cli_credentials_new_ccache(struct cli_credentials *cred)
                return ENOMEM;
        }
 
-       ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context);
+       ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context);
        if (ret) {
-               talloc_free(ccache_name);
                talloc_free(ccc);
                return ret;
        }
+       talloc_reference(ccc, ccc->smb_krb5_context);
 
        ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache);
        if (ret) {
@@ -227,6 +245,41 @@ int cli_credentials_get_ccache(struct cli_credentials *cred,
        return ret;
 }
 
+int cli_credentials_get_keytab(struct cli_credentials *cred, 
+                              struct keytab_container **_ktc)
+{
+       krb5_error_code ret;
+       struct keytab_container *ktc;
+       struct smb_krb5_context *smb_krb5_context;
+
+       if (cred->keytab_obtained >= (MAX(cred->principal_obtained, 
+                                         cred->username_obtained))) {
+               *_ktc = cred->keytab;
+               return 0;
+       }
+
+       if (cli_credentials_is_anonymous(cred)) {
+               return EINVAL;
+       }
+
+       ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+       if (ret) {
+               return ret;
+       }
+
+       ret = create_memory_keytab(cred, cred, smb_krb5_context, &ktc);
+       if (ret) {
+               return ret;
+       }
+
+       cred->keytab_obtained = (MAX(cred->principal_obtained, 
+                                    cred->username_obtained));
+
+       cred->keytab = ktc;
+       *_ktc = cred->keytab;
+       return ret;
+}
+
 /** 
  * Set Kerberos KVNO
  */
index 21e70e1c0e5211789ef41fcd57f266e9b5d44279..375c55e3ba5337f4c728204dc3c1b54f14e8e3f3 100644 (file)
@@ -439,7 +439,7 @@ const char *gensec_get_name_by_oid(const char *oid_string)
        if (ops) {
                return ops->name;
        }
-       return NULL;
+       return oid_string;
 }
        
 
@@ -489,6 +489,22 @@ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
        return gensec_start_mech(gensec_security);
 }
 
+/** 
+ * Start a GENSEC sub-mechanism by an internal name
+ *
+ */
+
+NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security, 
+                                       const char *name) 
+{
+       gensec_security->ops = gensec_security_by_name(name);
+       if (!gensec_security->ops) {
+               DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       return gensec_start_mech(gensec_security);
+}
+
 /*
   wrappers for the gensec function pointers
 */
index 8eae8bda71b206470405116fdb59500d23e481c9..97543de445f84d9ac104af50bb5876e6eca6dec3 100644 (file)
@@ -43,7 +43,7 @@ struct gensec_gssapi_state {
        struct smb_krb5_context *smb_krb5_context;
        krb5_ccache ccache;
        const char *ccache_name;
-       krb5_keytab keytab;
+       struct keytab_container *keytab;
 
        gss_cred_id_t cred;
 };
@@ -154,6 +154,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
 {
        NTSTATUS nt_status;
        OM_uint32 maj_stat, min_stat;
+       int ret;
        gss_buffer_desc name_token;
        struct gensec_gssapi_state *gensec_gssapi_state;
        struct cli_credentials *machine_account;
@@ -165,45 +166,43 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
 
        gensec_gssapi_state = gensec_security->private_data;
 
-       machine_account = cli_credentials_init(gensec_gssapi_state);
-       cli_credentials_set_conf(machine_account);
-       nt_status = cli_credentials_set_machine_account(machine_account);
+       machine_account = gensec_get_credentials(gensec_security);
        
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(3, ("Could not obtain machine account credentials from the local database\n"));
-               talloc_free(machine_account);
-               return nt_status;
+       if (!machine_account) {
+               DEBUG(3, ("No machine account credentials specified\n"));
+               return NT_STATUS_INVALID_PARAMETER;
        } else {
-               nt_status = create_memory_keytab(gensec_gssapi_state,
-                                                machine_account, 
-                                                gensec_gssapi_state->smb_krb5_context,
-                                                &gensec_gssapi_state->keytab);
-               if (!NT_STATUS_IS_OK(nt_status)) {
+               ret = cli_credentials_get_keytab(machine_account, &gensec_gssapi_state->keytab);
+               if (ret) {
                        DEBUG(3, ("Could not create memory keytab!\n"));
-                       talloc_free(machine_account);
-                       return nt_status;
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
                }
        }
 
        name_token.value = cli_credentials_get_principal(machine_account, 
                                                         machine_account);
-       name_token.length = strlen(name_token.value);
-
-       maj_stat = gss_import_name (&min_stat,
-                                   &name_token,
-                                   GSS_C_NT_USER_NAME,
-                                   &gensec_gssapi_state->server_name);
-       talloc_free(machine_account);
 
-       if (maj_stat) {
-               DEBUG(2, ("GSS Import name of %s failed: %s\n",
-                         (char *)name_token.value,
-                         gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
-               return NT_STATUS_UNSUCCESSFUL;
+       /* This might have been explicity set to NULL, ie use what the client calls us */
+       if (name_token.value) {
+               name_token.length = strlen(name_token.value);
+               
+               maj_stat = gss_import_name (&min_stat,
+                                           &name_token,
+                                           GSS_C_NT_USER_NAME,
+                                           &gensec_gssapi_state->server_name);
+
+               if (maj_stat) {
+                       DEBUG(2, ("GSS Import name of %s failed: %s\n",
+                                 (char *)name_token.value,
+                                 gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       } else {
+               gensec_gssapi_state->server_name = GSS_C_NO_NAME;
        }
 
        maj_stat = gsskrb5_acquire_cred(&min_stat, 
-                                       gensec_gssapi_state->keytab, NULL,
+                                       gensec_gssapi_state->keytab->keytab, NULL,
                                        gensec_gssapi_state->server_name,
                                        GSS_C_INDEFINITE,
                                        GSS_C_NULL_OID_SET,
index 71974790b1b6713447e29f2aaa78e9200274e33f..d999559a49f253e20642fc98637d9738c10cd247 100644 (file)
@@ -86,6 +86,10 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
 {
        struct gensec_krb5_state *gensec_krb5_state;
 
+       if (!gensec_get_credentials(gensec_security)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state);
        if (!gensec_krb5_state) {
                return NT_STATUS_NO_MEMORY;
@@ -185,7 +189,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
        gensec_krb5_state = gensec_security->private_data;
        gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START;
 
-       ret = cli_credentials_get_ccache(gensec_security->credentials, &ccache_container);
+       ret = cli_credentials_get_ccache(gensec_get_credentials(gensec_security), &ccache_container);
        if (ret) {
                DEBUG(1,("gensec_krb5_start: cli_credentials_get_ccache failed: %s\n", 
                         error_message(ret)));
@@ -391,7 +395,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
                        nt_status = ads_verify_ticket(out_mem_ctx, 
                                                      gensec_krb5_state->smb_krb5_context,
                                                      &gensec_krb5_state->auth_context, 
-                                                     lp_realm(), 
+                                                     gensec_get_credentials(gensec_security),
                                                      gensec_get_target_service(gensec_security), &unwrapped_in, 
                                                      &gensec_krb5_state->ticket, &unwrapped_out,
                                                      &gensec_krb5_state->keyblock);
@@ -400,7 +404,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
                        nt_status = ads_verify_ticket(out_mem_ctx, 
                                                      gensec_krb5_state->smb_krb5_context,
                                                      &gensec_krb5_state->auth_context, 
-                                                     lp_realm(), 
+                                                     gensec_get_credentials(gensec_security),
                                                      gensec_get_target_service(gensec_security), 
                                                      &in, 
                                                      &gensec_krb5_state->ticket, &unwrapped_out,
index bc2a1babe9914478ab19b455d9a5b209c5a56659..13a82b0575eb10ee62933309868a75b532674022 100644 (file)
@@ -28,6 +28,12 @@ struct ccache_container {
        krb5_ccache ccache;
 };
 
+
+struct keytab_container {
+       struct smb_krb5_context *smb_krb5_context;
+       krb5_keytab keytab;
+};
+
 /* not really ASN.1, but RFC 1964 */
 #define TOK_ID_KRB_AP_REQ      "\x01\x00"
 #define TOK_ID_KRB_AP_REP      "\x02\x00"
@@ -81,14 +87,15 @@ krb5_error_code ads_krb5_mk_req(krb5_context context,
                                krb5_data *outbuf);
 DATA_BLOB get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, 
                                 krb5_ticket *tkt);
-NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, 
-                          struct smb_krb5_context *smb_krb5_context,
-                          krb5_auth_context *auth_context,
-                          const char *realm, const char *service, 
-                          const DATA_BLOB *enc_ticket, 
-                          krb5_ticket **tkt,
-                          DATA_BLOB *ap_rep,
-                          krb5_keyblock **keyblock);
+ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, 
+                           struct smb_krb5_context *smb_krb5_context,
+                           krb5_auth_context *auth_context,
+                           struct cli_credentials *machine_account,
+                           const char *service, 
+                           const DATA_BLOB *enc_ticket, 
+                           krb5_ticket **tkt,
+                           DATA_BLOB *ap_rep,
+                           krb5_keyblock **keyblock);
 int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, 
                               krb5_principal principal, const char *password, 
                               time_t *expire_time, time_t *kdc_time);
@@ -115,10 +122,10 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
                                           struct cli_credentials *credentials, 
                                           struct smb_krb5_context *smb_krb5_context,
                                           krb5_principal *princ);
-NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx,
-                             struct cli_credentials *machine_account,
-                             struct smb_krb5_context *smb_krb5_context,
-                             krb5_keytab *keytab);
+int create_memory_keytab(TALLOC_CTX *parent_ctx,
+                         struct cli_credentials *machine_account,
+                         struct smb_krb5_context *smb_krb5_context,
+                        struct keytab_container **keytab_container); 
 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
                             struct PAC_DATA **pac_data_out,
                             DATA_BLOB blob,
index 3a6aff9df892deb4a2ae7d83122e809e193de635..3d7084aa0de78a1a3389fa79955129d49577ac53 100644 (file)
@@ -33,11 +33,6 @@ struct principal_container {
        krb5_principal principal;
 };
 
-struct keytab_container {
-       struct smb_krb5_context *smb_krb5_context;
-       krb5_keytab keytab;
-};
-
 static int free_principal(void *ptr) {
        struct principal_container *pc = ptr;
        /* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
@@ -111,7 +106,8 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
 
        if (!princ_string) {
                talloc_free(mem_ctx);
-               return EINVAL;
+               princ = NULL;
+               return 0;
        }
 
        ret = krb5_parse_name(smb_krb5_context->krb5_context,
@@ -131,9 +127,9 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
  */
 
  krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
-                         struct cli_credentials *credentials,
-                         struct smb_krb5_context *smb_krb5_context,
-                         krb5_ccache ccache) 
+                                struct cli_credentials *credentials,
+                                struct smb_krb5_context *smb_krb5_context,
+                                krb5_ccache ccache) 
 {
        krb5_error_code ret;
        const char *password;
@@ -216,36 +212,40 @@ static int free_keytab(void *ptr) {
        return 0;
 }
 
NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx,
-                              struct cli_credentials *machine_account,
-                              struct smb_krb5_context *smb_krb5_context,
-                              krb5_keytab *keytab
int create_memory_keytab(TALLOC_CTX *parent_ctx,
+                         struct cli_credentials *machine_account,
+                         struct smb_krb5_context *smb_krb5_context,
+                         struct keytab_container **keytab_container
 {
        krb5_error_code ret;
        const char *password_s;
+       char *old_secret;
        krb5_data password;
-       int i;
-       struct keytab_container *mem_ctx = talloc(parent_ctx, struct keytab_container);
+       int i, kvno;
        krb5_enctype *enctypes;
        krb5_principal salt_princ;
        krb5_principal princ;
-       
+       krb5_keytab keytab;
+
+       TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
        if (!mem_ctx) {
-               return NT_STATUS_NO_MEMORY;
+               return ENOMEM;
        }
+       
+       *keytab_container = talloc(mem_ctx, struct keytab_container);
 
-       ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY:", keytab);
+       ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY:", &keytab);
        if (ret) {
                DEBUG(1,("failed to generate a new krb5 keytab: %s\n", 
                         error_message(ret)));
                talloc_free(mem_ctx);
-               return NT_STATUS_INTERNAL_ERROR;
+               return ret;
        }
 
-       mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
-       mem_ctx->keytab = *keytab;
+       (*keytab_container)->smb_krb5_context = talloc_reference(*keytab_container, smb_krb5_context);
+       (*keytab_container)->keytab = keytab;
 
-       talloc_set_destructor(mem_ctx, free_keytab);
+       talloc_set_destructor(*keytab_container, free_keytab);
 
        ret = salt_principal_from_credentials(mem_ctx, machine_account, 
                                              smb_krb5_context, 
@@ -255,7 +255,7 @@ static int free_keytab(void *ptr) {
                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                    ret, mem_ctx)));
                talloc_free(mem_ctx);
-               return NT_STATUS_INTERNAL_ERROR;
+               return ret;
        }
 
        ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
@@ -264,10 +264,10 @@ static int free_keytab(void *ptr) {
                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                    ret, mem_ctx)));
                talloc_free(mem_ctx);
-               return NT_STATUS_INTERNAL_ERROR;
+               return ret;
        }
 
-       password_s = talloc_strdup(mem_ctx, cli_credentials_get_password(machine_account));
+       password_s = cli_credentials_get_password(machine_account);
        if (!password_s) {
                /* If we don't have the plaintext password, try for
                 * the MD4 password hash */
@@ -279,7 +279,7 @@ static int free_keytab(void *ptr) {
                        talloc_free(mem_ctx);
                        DEBUG(1, ("create_memory_keytab: Domain trust informaton for account %s not available\n",
                                  cli_credentials_get_principal(machine_account, mem_ctx)));
-                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+                       return EINVAL;
                }
                ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
                                         ENCTYPE_ARCFOUR_HMAC,
@@ -289,12 +289,12 @@ static int free_keytab(void *ptr) {
                        DEBUG(1, ("create_memory_keytab: krb5_keyblock_init failed: %s\n",
                                  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                             ret, mem_ctx)));
-                       return NT_STATUS_INTERNAL_ERROR;
+                       return ret;
                }
 
                entry.principal = princ;
                entry.vno       = cli_credentials_get_kvno(machine_account);
-               ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
+               ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
                if (ret) {
                        DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s",
                                  cli_credentials_get_principal(machine_account, mem_ctx), 
@@ -302,11 +302,14 @@ static int free_keytab(void *ptr) {
                                                             ret, mem_ctx)));
                        talloc_free(mem_ctx);
                        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
-                       return NT_STATUS_INTERNAL_ERROR;
+                       return ret;
                }
                
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
-               return NT_STATUS_OK;
+
+               talloc_steal(parent_ctx, *keytab_container);
+               talloc_free(mem_ctx);
+               return 0;
        }
                
        /* good, we actually have the real plaintext */
@@ -317,24 +320,25 @@ static int free_keytab(void *ptr) {
                DEBUG(1,("create_memory_keytab: getting encrption types failed (%s)\n",
                         error_message(ret)));
                talloc_free(mem_ctx);
-               return NT_STATUS_INTERNAL_ERROR;
+               return ret;
        }
 
        password.data = discard_const_p(char *, password_s);
        password.length = strlen(password_s);
-       
+       kvno = cli_credentials_get_kvno(machine_account);
+
        for (i=0; enctypes[i]; i++) {
                krb5_keytab_entry entry;
                ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context, 
                                                      salt_princ, &password, &entry.keyblock, enctypes[i]);
                if (ret) {
                        talloc_free(mem_ctx);
-                       return NT_STATUS_INTERNAL_ERROR;
+                       return ret;
                }
 
                 entry.principal = princ;
-                entry.vno       = cli_credentials_get_kvno(machine_account);
-               ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
+                entry.vno       = kvno;
+               ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
                if (ret) {
                        DEBUG(1, ("Failed to add entry for %s to keytab: %s",
                                  cli_credentials_get_principal(machine_account, mem_ctx), 
@@ -342,15 +346,48 @@ static int free_keytab(void *ptr) {
                                                             ret, mem_ctx)));
                        talloc_free(mem_ctx);
                        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
-                       return NT_STATUS_INTERNAL_ERROR;
+                       return ret;
                }
                
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
        }
 
+       old_secret = cli_credentials_get_old_password(machine_account);
+       if (kvno != 0 && old_secret) {
+               password.data = discard_const_p(char *, old_secret);
+               password.length = strlen(old_secret);
+               
+               for (i=0; enctypes[i]; i++) {
+                       krb5_keytab_entry entry;
+                       ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context, 
+                                                             salt_princ, &password, &entry.keyblock, enctypes[i]);
+                       if (ret) {
+                               talloc_free(mem_ctx);
+                               return ret;
+                       }
+                       
+                       entry.principal = princ;
+                       entry.vno       = kvno - 1;
+                       ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
+                       if (ret) {
+                               DEBUG(1, ("Failed to add 'old password' entry for %s to keytab: %s",
+                                         cli_credentials_get_principal(machine_account, mem_ctx), 
+                                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                                    ret, mem_ctx)));
+                               talloc_free(mem_ctx);
+                               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
+                               return ret;
+                       }
+                       
+                       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
+               }
+       }
+
        free_kerberos_etypes(smb_krb5_context->krb5_context, enctypes);
 
-       return NT_STATUS_OK;
+       talloc_steal(parent_ctx, *keytab_container);
+       talloc_free(mem_ctx);
+       return 0;
 }
 
 
index 514acde5ebad150fb195a41d3609208e3daa9043..13d2c9fc263b812e55ee9d448099d5ed8c5151ef 100644 (file)
@@ -63,156 +63,6 @@ DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
        return out;
 }
 
-/**********************************************************************************
- 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 krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_context context, 
-                                               krb5_auth_context *auth_context,
-                                               const char *service,
-                                               const krb5_data *p_packet, 
-                                               krb5_flags *ap_req_options,
-                                               krb5_ticket **pp_tkt,
-                                               krb5_keyblock **keyblock)
-{
-       krb5_error_code ret = 0;
-       krb5_keytab keytab = NULL;
-       krb5_kt_cursor kt_cursor;
-       krb5_keytab_entry kt_entry;
-       char *valid_princ_formats[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-       char *entry_princ_s = NULL;
-       const char *my_name, *my_fqdn;
-       int i;
-       int number_matched_principals = 0;
-       const char *last_error_message;
-
-       /* Generate the list of principal names which we expect
-        * clients might want to use for authenticating to the file
-        * service.  We allow name$,{host,service}/{name,fqdn,name.REALM}.
-        * (where service is specified by the caller) */
-
-       my_name = lp_netbios_name();
-
-       my_fqdn = name_to_fqdn(mem_ctx, my_name);
-
-       asprintf(&valid_princ_formats[0], "%s$@%s", my_name, lp_realm());
-       asprintf(&valid_princ_formats[1], "host/%s@%s", my_name, lp_realm());
-       asprintf(&valid_princ_formats[2], "host/%s@%s", my_fqdn, lp_realm());
-       asprintf(&valid_princ_formats[3], "host/%s.%s@%s", my_name, lp_realm(), lp_realm());
-       asprintf(&valid_princ_formats[4], "%s/%s@%s", service, my_name, lp_realm());
-       asprintf(&valid_princ_formats[5], "%s/%s@%s", service, my_fqdn, lp_realm());
-       asprintf(&valid_princ_formats[6], "%s/%s.%s@%s", service, my_name, lp_realm(), lp_realm());
-
-       ZERO_STRUCT(kt_entry);
-       ZERO_STRUCT(kt_cursor);
-
-       ret = krb5_kt_default(context, &keytab);
-       if (ret) {
-               last_error_message = smb_get_krb5_error_message(context, ret, mem_ctx);
-               DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_default failed (%s)\n", 
-                         last_error_message));
-               goto out;
-       }
-
-       /* Iterate through the keytab.  For each key, if the principal
-        * name case-insensitively matches one of the allowed formats,
-        * try verifying the ticket using that principal. */
-
-       ret = krb5_kt_start_seq_get(context, keytab, &kt_cursor);
-       if (ret == KRB5_KT_END || ret == ENOENT ) {
-               last_error_message = smb_get_krb5_error_message(context, ret, mem_ctx);
-       } else if (ret) {
-               last_error_message = smb_get_krb5_error_message(context, ret, mem_ctx);
-               DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s)\n", 
-                         last_error_message));
-       } else {
-               ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; /* Pick an error... */
-               last_error_message = "No principals in Keytab";
-               while (ret && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
-                       krb5_error_code upn_ret;
-                       upn_ret = krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
-                       if (upn_ret) {
-                               last_error_message = smb_get_krb5_error_message(context, ret, mem_ctx);
-                               DEBUG(1, ("ads_keytab_verify_ticket: krb5_unparse_name failed (%s)\n", 
-                                         last_error_message));
-                               ret = upn_ret;
-                               break;
-                       }
-                       for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
-                               if (!strequal(entry_princ_s, valid_princ_formats[i])) {
-                                       continue;
-                               }
-
-                               number_matched_principals++;
-                               *pp_tkt = NULL;
-                               ret = krb5_rd_req_return_keyblock(context, auth_context, p_packet, 
-                                                                 kt_entry.principal, keytab, 
-                                                                 ap_req_options, pp_tkt, keyblock);
-                               if (ret) {
-                                       last_error_message = smb_get_krb5_error_message(context, ret, mem_ctx);
-                                       DEBUG(10, ("ads_keytab_verify_ticket: krb5_rd_req(%s) failed: %s\n",
-                                                  entry_princ_s, last_error_message));
-                               } else {
-                                       DEBUG(3,("ads_keytab_verify_ticket: krb5_rd_req succeeded for principal %s\n",
-                                                entry_princ_s));
-                                       break;
-                               }
-                       }
-
-                       /* Free the name we parsed. */
-                       krb5_free_unparsed_name(context, entry_princ_s);
-                       entry_princ_s = NULL;
-
-                       /* Free the entry we just read. */
-                       smb_krb5_kt_free_entry(context, &kt_entry);
-                       ZERO_STRUCT(kt_entry);
-               }
-               krb5_kt_end_seq_get(context, keytab, &kt_cursor);
-       }
-
-       ZERO_STRUCT(kt_cursor);
-
-  out:
-
-       if (ret) {
-               if (!number_matched_principals) {
-                       DEBUG(3, ("ads_keytab_verify_ticket: no keytab principals matched expected file service name.\n"));
-               } else {
-                       DEBUG(3, ("ads_keytab_verify_ticket: krb5_rd_req failed for all %d matched keytab principals\n",
-                               number_matched_principals));
-               }
-               DEBUG(3, ("ads_keytab_verify_ticket: last error: %s\n", last_error_message));
-       }
-
-       if (entry_princ_s) {
-               krb5_free_unparsed_name(context, entry_princ_s);
-       }
-
-       {
-               krb5_keytab_entry zero_kt_entry;
-               ZERO_STRUCT(zero_kt_entry);
-               if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
-                       smb_krb5_kt_free_entry(context, &kt_entry);
-               }
-       }
-
-       {
-               krb5_kt_cursor zero_csr;
-               ZERO_STRUCT(zero_csr);
-               if ((memcmp(&kt_cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
-                       krb5_kt_end_seq_get(context, keytab, &kt_cursor);
-               }
-       }
-
-       if (keytab) {
-               krb5_kt_close(context, keytab);
-       }
-
-       return ret;
-}
-
 /**********************************************************************************
  Verify an incoming ticket and parse out the principal name and 
  authorization_data if available.
@@ -221,7 +71,8 @@ static krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_contex
  NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, 
                            struct smb_krb5_context *smb_krb5_context,
                            krb5_auth_context *auth_context,
-                           const char *realm, const char *service, 
+                           struct cli_credentials *machine_account,
+                           const char *service, 
                            const DATA_BLOB *enc_ticket, 
                            krb5_ticket **tkt,
                            DATA_BLOB *ap_rep,
@@ -229,32 +80,12 @@ static krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_contex
 {
        krb5_keyblock *local_keyblock;
        krb5_data packet;
-       krb5_principal salt_princ;
        int ret;
        krb5_flags ap_req_options = 0;
+       krb5_principal server;
 
-       NTSTATUS creds_nt_status, status;
-       struct cli_credentials *machine_account;
+       struct keytab_container *keytab_container;
 
-       machine_account = cli_credentials_init(mem_ctx);
-       cli_credentials_set_conf(machine_account);
-       creds_nt_status = cli_credentials_set_machine_account(machine_account);
-       
-       if (!NT_STATUS_IS_OK(creds_nt_status)) {
-               DEBUG(3, ("Could not obtain machine account credentials from the local database\n"));
-               talloc_free(machine_account);
-               machine_account = NULL;
-       } else {
-               ret = salt_principal_from_credentials(mem_ctx, machine_account, 
-                                                     smb_krb5_context, 
-                                                     &salt_princ);
-               if (ret) {
-                       DEBUG(1,("ads_verify_ticket: maksing salt principal failed (%s)\n",
-                                error_message(ret)));
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-       }
-       
        /* This whole process is far more complex than I would
            like. We have to go through all this to allow us to store
            the secret internally, instead of using /etc/krb5.keytab */
@@ -268,24 +99,18 @@ static krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_contex
        packet.length = enc_ticket->length;
        packet.data = (krb5_pointer)enc_ticket->data;
 
-       ret = ads_keytab_verify_ticket(mem_ctx, smb_krb5_context->krb5_context, auth_context, 
-                                      service, &packet, &ap_req_options, tkt, &local_keyblock);
-       if (ret && machine_account) {
-               krb5_keytab keytab;
-               krb5_principal server;
-               status = create_memory_keytab(mem_ctx, machine_account, smb_krb5_context, 
-                                             &keytab);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-               ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, 
-                                                &server);
-               if (ret == 0) {
-                       ret = krb5_rd_req_return_keyblock(smb_krb5_context->krb5_context, auth_context, &packet,
-                                                         server,
-                                                         keytab, &ap_req_options, tkt,
-                                                         &local_keyblock);
-               }
+       ret = cli_credentials_get_keytab(machine_account, &keytab_container);
+       if (ret) {
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
+       ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, 
+                                        &server);
+       if (ret == 0) {
+               ret = krb5_rd_req_return_keyblock(smb_krb5_context->krb5_context, auth_context, &packet,
+                                                 server,
+                                                 keytab_container->keytab, &ap_req_options, tkt,
+                                                 &local_keyblock);
        }
 
        if (ret) {
index e9d38ad93b0d023785f95332d087b66250aab0a4..7a296d01ac1b54b6c0a32e7b18c4b2f46e47e967 100644 (file)
@@ -63,6 +63,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
        DEBUG(10, ("BindSASL dn: %s\n",req->dn));
 
        if (!call->conn->gensec) {
+               struct cli_credentials *server_credentials;
                call->conn->session_info = NULL;
 
                status = gensec_server_start(call->conn, &call->conn->gensec,
@@ -74,6 +75,23 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
                
                gensec_set_target_service(call->conn->gensec, "ldap");
 
+               server_credentials 
+                       = cli_credentials_init(call);
+               if (!server_credentials) {
+                       DEBUG(1, ("Failed to init server credentials\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+               
+               cli_credentials_set_conf(server_credentials);
+               status = cli_credentials_set_machine_account(server_credentials);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
+                       talloc_free(server_credentials);
+                       server_credentials = NULL;
+               }
+               
+               gensec_set_credentials(call->conn->gensec, server_credentials);
+
                gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_SIGN);
                gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_SEAL);
                gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_ASYNC_REPLIES);
index a2ba709f561c43a03a9fba1c8f277899aaeeee6a..6caef7424d8a9499ad03eef24d81600f07135203 100644 (file)
@@ -32,6 +32,7 @@
 */
 BOOL dcesrv_auth_bind(struct dcesrv_call_state *call)
 {
+       struct cli_credentials *server_credentials;
        struct ncacn_packet *pkt = &call->pkt;
        struct dcesrv_connection *dce_conn = call->conn;
        struct dcesrv_auth *auth = &dce_conn->auth_state;
@@ -61,6 +62,23 @@ BOOL dcesrv_auth_bind(struct dcesrv_call_state *call)
                return False;
        }
 
+       server_credentials 
+               = cli_credentials_init(call);
+       if (!server_credentials) {
+               DEBUG(1, ("Failed to init server credentials\n"));
+               return False;
+       }
+       
+       cli_credentials_set_conf(server_credentials);
+       status = cli_credentials_set_machine_account(server_credentials);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
+               talloc_free(server_credentials);
+               server_credentials = NULL;
+       }
+
+       gensec_set_credentials(auth->gensec_security, server_credentials);
+
        status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_info->auth_type, 
                                               auth->auth_info->auth_level);
 
index 3dcb82dbddeb4d642cbe1b38a4380bce163a2b98..eccb768db5cbb7c6693f8173279e941d66f6e202 100644 (file)
@@ -35,3 +35,16 @@ whenCreated: ${LDAPTIME}
 whenChanged: ${LDAPTIME}
 msDS-KeyVersionNumber: 1
 objectSid: ${DOMAINSID}
+
+dn: samAccountName=krbtgt,flatname=${DOMAIN},CN=Principals
+objectClass: top
+objectClass: secret
+flatname: ${DOMAIN}
+realm: ${REALM}
+secret: ${KRBTGTPASS}
+sAMAccountName: krbtgt
+whenCreated: ${LDAPTIME}
+whenChanged: ${LDAPTIME}
+msDS-KeyVersionNumber: 1
+objectSid: ${DOMAINSID}
+servicePrincipalName: kadmin/changepw
index 31f31272e0f7dc9fab03b2e4a6cc8a37b2dbac65..a9cc05e25111877c13fc577575e2d37f940680f6 100644 (file)
@@ -326,6 +326,7 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
                req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
                DEBUG(3,("not using SPNEGO\n"));
        } else {
+               struct cli_credentials *server_credentials;
                struct gensec_security *gensec_security;
                DATA_BLOB null_data_blob = data_blob(NULL, 0);
                DATA_BLOB blob;
@@ -333,19 +334,38 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
                                                         &gensec_security,
                                                         req->smb_conn->connection->event.ctx);
                
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       DEBUG(0, ("Failed to start GENSEC: %s\n", nt_errstr(nt_status)));
+                       smbsrv_terminate_connection(req->smb_conn, "Failed to start GENSEC\n");
+                       return;
+               }
+
                if (req->smb_conn->negotiate.auth_context) {
                        smbsrv_terminate_connection(req->smb_conn, "reply_nt1: is this a secondary negprot?  auth_context is non-NULL!\n");
                        return;
                }
 
-               req->smb_conn->negotiate.auth_context = NULL;
+               server_credentials 
+                       = cli_credentials_init(req);
+               if (!server_credentials) {
+                       smbsrv_terminate_connection(req->smb_conn, "Failed to init server credentials\n");
+                       return;
+               }
                
+               cli_credentials_set_conf(server_credentials);
+               nt_status = cli_credentials_set_machine_account(server_credentials);
                if (!NT_STATUS_IS_OK(nt_status)) {
-                       DEBUG(0, ("Failed to start GENSEC: %s\n", nt_errstr(nt_status)));
-                       smbsrv_terminate_connection(req->smb_conn, "Failed to start GENSEC\n");
-                       return;
+                       DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(nt_status)));
+                       talloc_free(server_credentials);
+                       server_credentials = NULL;
                }
 
+               req->smb_conn->negotiate.server_credentials = talloc_steal(req->smb_conn, server_credentials);
+
+               gensec_set_target_service(gensec_security, "cifs");
+
+               gensec_set_credentials(gensec_security, server_credentials);
+
                nt_status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
                
                if (!NT_STATUS_IS_OK(nt_status)) {
index 1fa04b99e5ec5ef0dd96efbe559f6c6137b4598d..bdd4a3fab24e01322c27af33e514f69165d54882 100644 (file)
@@ -293,6 +293,8 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
                        return status;
                }
 
+               gensec_set_credentials(gensec_ctx, req->smb_conn->negotiate.server_credentials);
+
                gensec_set_target_service(gensec_ctx, "cifs");
 
                gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
index 01fb1e26a3178a1dfcc3f15ca34b7760d360c76b..360ea7ddfb90441ea23292ff27ae275fd5d00514 100644 (file)
@@ -194,8 +194,8 @@ struct smbsrv_connection {
                /* authentication context for multi-part negprot */
                struct auth_context *auth_context;
        
-               /* state of NTLMSSP auth */
-               struct auth_ntlmssp_state *ntlmssp_state;
+               /* reference to the kerberos keytab, or machine trust account */
+               struct cli_credentials *server_credentials;
        
                /* did we tell the client we support encrypted passwords? */
                BOOL encrypted_passwords;
index 3b94640f227cfecc7c7204ecbf45b7b12aad42a8..7072262653b1b65fc7ee8ad3043a3fb0086b650a 100644 (file)
@@ -392,6 +392,16 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
                if (opt_workstation) {
                        cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED);
                }
+               
+               switch (stdio_helper_mode) {
+               case GSS_SPNEGO_SERVER:
+               case SQUID_2_5_NTLMSSP:
+                       cli_credentials_set_machine_account(creds);
+                       break;
+               default:
+                       break;
+               }
+
                gensec_set_credentials(state->gensec_state, creds);
 
                switch (stdio_helper_mode) {