Merge from HEAD client-side authentication changes:
authorAndrew Bartlett <abartlet@samba.org>
Mon, 24 Feb 2003 02:55:00 +0000 (02:55 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 24 Feb 2003 02:55:00 +0000 (02:55 +0000)
 - new kerberos code, allowing the account to change it's own password
   without special SD settings required
 - NTLMSSP client code, now seperated from cliconnect.c
 - NTLMv2 client code
 - SMB signing fixes

Andrew Bartlett
(This used to be commit 837680ca517982f2e5944730581a83012d4181ae)

16 files changed:
source3/include/ads.h
source3/include/client.h
source3/include/ntlmssp.h
source3/lib/data_blob.c
source3/libads/krb5_setpw.c
source3/libads/ldap.c
source3/libads/sasl.c
source3/libads/util.c
source3/libsmb/cliconnect.c
source3/libsmb/clientgen.c
source3/libsmb/clispnego.c
source3/libsmb/ntlmssp.c
source3/libsmb/smbencrypt.c
source3/nsswitch/winbindd_ads.c
source3/param/loadparm.c
source3/utils/net_rpc_join.c

index 7f23e6506b133676ea9b5328f8a74fc67a687f63..304a997b2ce7dca3f5ff2f9a9328ec877791588c 100644 (file)
@@ -205,3 +205,6 @@ typedef void **ADS_MODLIST;
 #define ADS_AUTH_NO_BIND          0x02
 #define ADS_AUTH_ANON_BIND        0x04
 #define ADS_AUTH_SIMPLE_BIND      0x08
+
+/* Kerberos environment variable names */
+#define KRB5_ENV_CCNAME "KRB5CCNAME"
index 853ee7ae42b1c1fd17466bdadadb955971c509ba..73e29a1fff8079931f550d3b3aeedebc73076ed2 100644 (file)
@@ -62,9 +62,10 @@ typedef struct smb_sign_info {
        BOOL negotiated_smb_signing;
        BOOL temp_smb_signing;
        size_t mac_key_len;
-       uint8 mac_key[44];
+       uint8 mac_key[64];
        uint32 send_seq_num;
        uint32 reply_seq_num;
+       BOOL allow_smb_signing;
 } smb_sign_info;
 
 struct cli_state {
@@ -121,6 +122,10 @@ struct cli_state {
 
        smb_sign_info sign_info;
 
+       /* the session key for this CLI, outside 
+          any per-pipe authenticaion */
+       unsigned char user_session_key[16];
+
        /*
         * Only used in NT domain calls.
         */
index 79d0446a77131d57506e416823d5c4c314e687af..4fa4259a6a5055cc791453145dd4217f1bf6bd30 100644 (file)
@@ -86,5 +86,25 @@ typedef struct ntlmssp_state
        const char *(*get_domain)(void);
 
        int server_role;
+       uint32 expected_state;
 } NTLMSSP_STATE;
 
+typedef struct ntlmssp_client_state 
+{
+       TALLOC_CTX *mem_ctx;
+       BOOL unicode;
+       BOOL use_ntlmv2;
+       char *user;
+       char *domain;
+       char *workstation;
+       char *password;
+
+       const char *(*get_global_myname)(void);
+       const char *(*get_domain)(void);
+
+       DATA_BLOB session_key;
+       
+       uint32 neg_flags;
+
+} NTLMSSP_CLIENT_STATE;
+
index 250c3ade88e57eb9ab375db1ad6c88dbaabece03..4056212fc5637247cd40504bc9a8dd829f507de9 100644 (file)
@@ -84,6 +84,7 @@ void data_blob_free(DATA_BLOB *d)
                if (d->free) {
                        (d->free)(d);
                }
+               d->length = 0;
        }
 }
 
index 087b0e9a7156d99061d751b87535e02c66a14221..9d8fb8d24cb9f807fac97896bb488da46a621341 100644 (file)
 #ifdef HAVE_KRB5
 
 #define DEFAULT_KPASSWD_PORT   464
-#define KRB5_KPASSWD_VERS_CHANGEPW     1
-#define KRB5_KPASSWD_VERS_SETPW                0xff80
-#define KRB5_KPASSWD_ACCESSDENIED      5
-#define KRB5_KPASSWD_BAD_VERSION       6
-
-/* This implements the Kerb password change protocol as specifed in
- * kerb-chg-password-02.txt
+#define KRB5_KPASSWD_VERS_CHANGEPW             1
+#define KRB5_KPASSWD_VERS_SETPW                        2
+#define KRB5_KPASSWD_VERS_SETPW_MS             0xff80
+#define KRB5_KPASSWD_ACCESSDENIED              5
+#define KRB5_KPASSWD_BAD_VERSION               6
+#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED       7
+
+/* Those are defined by kerberos-set-passwd-02.txt and are probably 
+ * not supported by M$ implementation */
+#define KRB5_KPASSWD_POLICY_REJECT             8
+#define KRB5_KPASSWD_BAD_PRINCIPAL             9
+#define KRB5_KPASSWD_ETYPE_NOSUPP              10
+
+/* This implements kerberos password change protocol as specified in 
+ * kerb-chg-password-02.txt and kerberos-set-passwd-02.txt
+ * as well as microsoft version of the protocol 
+ * as specified in kerberos-set-passwd-00.txt
  */
 static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
 {
@@ -101,7 +111,8 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
        return ret;
 }      
 
-static krb5_error_code build_setpw_request(krb5_context context,
+static krb5_error_code build_kpasswd_request(uint16 pversion,
+                                          krb5_context context,
                                           krb5_auth_context auth_context,
                                           krb5_data *ap_req,
                                           const char *princ,
@@ -123,7 +134,14 @@ static krb5_error_code build_setpw_request(krb5_context context,
                return ret;
        }
 
-       setpw = encode_krb5_setpw(princ, passwd);
+       /* handle protocol differences in chpw and setpw */
+       if (pversion  == KRB5_KPASSWD_VERS_CHANGEPW)
+               setpw = data_blob(passwd, strlen(passwd));
+       else if (pversion == KRB5_KPASSWD_VERS_SETPW ||
+                pversion == KRB5_KPASSWD_VERS_SETPW_MS)
+               setpw = encode_krb5_setpw(princ, passwd);
+       else
+               return EINVAL;
 
        encoded_setpw.data = setpw.data;
        encoded_setpw.length = setpw.length;
@@ -144,7 +162,7 @@ static krb5_error_code build_setpw_request(krb5_context context,
 
        /* see the RFC for details */
        p = ((char *)packet->data) + 2;
-       RSSVAL(p, 0, 0xff80);
+       RSSVAL(p, 0, pversion);
        p += 2;
        RSSVAL(p, 0, ap_req->length);
        p += 2;
@@ -160,6 +178,49 @@ static krb5_error_code build_setpw_request(krb5_context context,
        return 0;
 }
 
+static krb5_error_code krb5_setpw_result_code_string(krb5_context context,
+                                                    int result_code,
+                                                    char **code_string)
+{
+   switch (result_code) {
+   case KRB5_KPASSWD_MALFORMED:
+      *code_string = "Malformed request error";
+      break;
+   case KRB5_KPASSWD_HARDERROR:
+      *code_string = "Server error";
+      break;
+   case KRB5_KPASSWD_AUTHERROR:
+      *code_string = "Authentication error";
+      break;
+   case KRB5_KPASSWD_SOFTERROR:
+      *code_string = "Password change rejected";
+      break;
+   case KRB5_KPASSWD_ACCESSDENIED:
+      *code_string = "Client does not have proper authorization";
+      break;
+   case KRB5_KPASSWD_BAD_VERSION:
+      *code_string = "Protocol version not supported";
+      break;
+   case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+      *code_string = "Authorization ticket must have initial flag set";
+      break;
+   case KRB5_KPASSWD_POLICY_REJECT:
+      *code_string = "Password rejected due to policy requirements";
+      break;
+   case KRB5_KPASSWD_BAD_PRINCIPAL:
+      *code_string = "Target principal does not exist";
+      break;
+   case KRB5_KPASSWD_ETYPE_NOSUPP:
+      *code_string = "Unsupported encryption type";
+      break;
+   default:
+      *code_string = "Password change failed";
+      break;
+   }
+
+   return(0);
+}
+
 static krb5_error_code parse_setpw_reply(krb5_context context, 
                                         krb5_auth_context auth_context,
                                         krb5_data *packet)
@@ -194,8 +255,11 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
        p += 2;
 
        vnum = RSVAL(p, 0); p += 2;
-       
-       if (vnum != KRB5_KPASSWD_VERS_SETPW && vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
+
+       /* FIXME: According to standard there is only one type of reply */      
+       if (vnum != KRB5_KPASSWD_VERS_SETPW && 
+           vnum != KRB5_KPASSWD_VERS_SETPW_MS && 
+           vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
                DEBUG(1,("Bad vnum (%d) from kpasswd server\n", vnum));
                return KRB5KDC_ERR_BAD_PVNO;
        }
@@ -247,96 +311,57 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
        free(clearresult.data);
 
        if ((res_code < KRB5_KPASSWD_SUCCESS) || 
-           (res_code >= KRB5_KPASSWD_ACCESSDENIED)) {
+           (res_code > KRB5_KPASSWD_ETYPE_NOSUPP)) {
                return KRB5KRB_AP_ERR_MODIFIED;
        }
-       
-       return 0;
+
+       if(res_code == KRB5_KPASSWD_SUCCESS)
+                       return 0;
+       else {
+               char *errstr;
+               krb5_setpw_result_code_string(context, res_code, &errstr);
+               DEBUG(1, ("Error changing password: %s\n", errstr));
+
+               switch(res_code) {
+                       case KRB5_KPASSWD_ACCESSDENIED:
+                               return KRB5KDC_ERR_BADOPTION;
+                               break;
+                       case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+                               return KRB5KDC_ERR_BADOPTION;
+                               /* return KV5M_ALT_METHOD; MIT-only define */
+                               break;
+                       case KRB5_KPASSWD_ETYPE_NOSUPP:
+                               return KRB5KDC_ERR_ETYPE_NOSUPP;
+                               break;
+                       case KRB5_KPASSWD_BAD_PRINCIPAL:
+                               return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+                               break;
+                       case KRB5_KPASSWD_POLICY_REJECT:
+                               return KRB5KDC_ERR_POLICY;
+                               break;
+                       default:
+                               return KRB5KRB_ERR_GENERIC;
+                               break;
+               }
+       }
 }
 
-ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, 
-                            int time_offset)
+static ADS_STATUS do_krb5_kpasswd_request(krb5_context context,
+                                         const char *kdc_host,
+                                         uint16 pversion,
+                                         krb5_creds *credsp,
+                                         const char *princ,
+                                         const char *newpw)
 {
-       krb5_context context;
        krb5_auth_context auth_context = NULL;
-       krb5_principal principal;
-       char *princ_name;
-       char *realm;
-       krb5_creds creds, *credsp;
-       krb5_ccache ccache;
        krb5_data ap_req, chpw_req, chpw_rep;
        int ret, sock, addr_len;
        struct sockaddr remote_addr, local_addr;
        krb5_address local_kaddr, remote_kaddr;
 
-       ret = krb5_init_context(&context);
-       if (ret) {
-               DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
-       }
-       
-       if (time_offset != 0) {
-               krb5_set_real_time(context, time(NULL) + time_offset, 0);
-       }
-
-       ret = krb5_cc_default(context, &ccache);
-       if (ret) {
-               krb5_free_context(context);
-               DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
-       }
-
-       ZERO_STRUCT(creds);
-       
-       realm = strchr(princ, '@');
-       realm++;
-
-       asprintf(&princ_name, "kadmin/changepw@%s", realm);
-       ret = krb5_parse_name(context, princ_name, &creds.server);
-       if (ret) {
-                krb5_free_context(context);
-               DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
-       }
-       free(princ_name);
-
-       /* parse the principal we got as a function argument */
-       ret = krb5_parse_name(context, princ, &principal);
-       if (ret) {
-                krb5_free_context(context);
-               DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
-       }
-
-       krb5_princ_set_realm(context, creds.server,
-                            krb5_princ_realm(context, principal));
-       
-       ret = krb5_cc_get_principal(context, ccache, &creds.client);
-       if (ret) {
-               krb5_free_principal(context, principal);
-                krb5_free_context(context);
-               DEBUG(1,("Failed to get principal from ccache (%s)\n", 
-                        error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
-       }
-       
-       ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
-       if (ret) {
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
-               DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
-       }
-       
-       /* we might have to call krb5_free_creds(...) from now on ... */
        ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
                                   NULL, credsp, &ap_req);
        if (ret) {
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
                DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret)));
                return ADS_ERROR_KRB5(ret);
        }
@@ -345,10 +370,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
        if (sock == -1) {
                int rc = errno;
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("failed to open kpasswd socket to %s (%s)\n", 
                         kdc_host, strerror(errno)));
                return ADS_ERROR_SYSTEM(rc);
@@ -366,23 +388,17 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
        if (ret) {
                close(sock);
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret)));
                return ADS_ERROR_KRB5(ret);
        }
 
-       ret = build_setpw_request(context, auth_context, &ap_req,
+       ret = build_kpasswd_request(pversion, context, auth_context, &ap_req,
                                  princ, newpw, &chpw_req);
        if (ret) {
                close(sock);
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret)));
                return ADS_ERROR_KRB5(ret);
        }
@@ -391,10 +407,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
                close(sock);
                free(chpw_req.data);
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
                return ADS_ERROR_SYSTEM(errno);
        }
@@ -406,10 +419,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
        if (!chpw_rep.data) {
                close(sock);
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
                errno = ENOMEM;
                return ADS_ERROR_SYSTEM(errno);
@@ -420,10 +430,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
                close(sock);
                free(chpw_rep.data);
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno)));
                return ADS_ERROR_SYSTEM(errno);
        }
@@ -435,10 +442,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
        if (ret) {
                free(chpw_rep.data);
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n", 
                         error_message(ret)));
                return ADS_ERROR_KRB5(ret);
@@ -449,22 +453,194 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
 
        if (ret) {
                free(ap_req.data);
-               krb5_free_creds(context, credsp);
-               krb5_free_principal(context, creds.client);
-               krb5_free_principal(context, principal);
-               krb5_free_context(context);
+               krb5_auth_con_free(context, auth_context);
                DEBUG(1,("parse_setpw_reply failed (%s)\n", 
                         error_message(ret)));
                return ADS_ERROR_KRB5(ret);
        }
 
        free(ap_req.data);
+       krb5_auth_con_free(context, auth_context);
+
+       return ADS_SUCCESS;
+}
+
+ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, 
+                            int time_offset)
+{
+
+       ADS_STATUS aret;
+       krb5_error_code ret;
+       krb5_context context;
+       krb5_principal principal;
+       char *princ_name;
+       char *realm;
+       krb5_creds creds, *credsp;
+       krb5_ccache ccache;
+
+       ret = krb5_init_context(&context);
+       if (ret) {
+               DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
+               return ADS_ERROR_KRB5(ret);
+       }
+       
+       if (time_offset != 0) {
+               krb5_set_real_time(context, time(NULL) + time_offset, 0);
+       }
+
+       ret = krb5_cc_default(context, &ccache);
+       if (ret) {
+               krb5_free_context(context);
+               DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
+               return ADS_ERROR_KRB5(ret);
+       }
+
+       ZERO_STRUCT(creds);
+       
+       realm = strchr(princ, '@');
+       realm++;
+
+       asprintf(&princ_name, "kadmin/changepw@%s", realm);
+       ret = krb5_parse_name(context, princ_name, &creds.server);
+       if (ret) {
+                krb5_free_context(context);
+               DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
+               return ADS_ERROR_KRB5(ret);
+       }
+       free(princ_name);
+
+       /* parse the principal we got as a function argument */
+       ret = krb5_parse_name(context, princ, &principal);
+       if (ret) {
+                krb5_free_context(context);
+               DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
+               return ADS_ERROR_KRB5(ret);
+       }
+
+       krb5_princ_set_realm(context, creds.server,
+                            krb5_princ_realm(context, principal));
+       
+       ret = krb5_cc_get_principal(context, ccache, &creds.client);
+       if (ret) {
+               krb5_free_principal(context, principal);
+                krb5_free_context(context);
+               DEBUG(1,("Failed to get principal from ccache (%s)\n", 
+                        error_message(ret)));
+               return ADS_ERROR_KRB5(ret);
+       }
+       
+       ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); 
+       if (ret) {
+               krb5_free_principal(context, creds.client);
+               krb5_free_principal(context, principal);
+               krb5_free_context(context);
+               DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
+               return ADS_ERROR_KRB5(ret);
+       }
+       
+       /* we might have to call krb5_free_creds(...) from now on ... */
+
+       aret = do_krb5_kpasswd_request(context, kdc_host,
+                                      KRB5_KPASSWD_VERS_SETPW_MS,
+                                      credsp, princ, newpw);
+
        krb5_free_creds(context, credsp);
        krb5_free_principal(context, creds.client);
+       krb5_free_principal(context, creds.server);
        krb5_free_principal(context, principal);
        krb5_free_context(context);
 
-       return ADS_SUCCESS;
+       return aret;
+}
+
+/*
+  we use a prompter to avoid a crash bug in the kerberos libs when 
+  dealing with empty passwords
+  this prompter is just a string copy ...
+*/
+static krb5_error_code 
+kerb_prompter(krb5_context ctx, void *data,
+              const char *name,
+              const char *banner,
+              int num_prompts,
+              krb5_prompt prompts[])
+{
+       if (num_prompts == 0) return 0;
+
+       memset(prompts[0].reply->data, 0, prompts[0].reply->length);
+       if (prompts[0].reply->length > 0) {
+               if (data) {
+                       strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);
+                       prompts[0].reply->length = strlen(prompts[0].reply->data);
+               } else {
+                       prompts[0].reply->length = 0;
+               }
+       }
+       return 0;
+}
+
+ADS_STATUS krb5_chg_password(const char *kdc_host,
+                               const char *principal,
+                               const char *oldpw, 
+                               const char *newpw, 
+                               int time_offset)
+{
+    ADS_STATUS aret;
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_principal princ;
+    krb5_get_init_creds_opt opts;
+    krb5_creds creds;
+    char *chpw_princ = NULL, *password;
+
+    ret = krb5_init_context(&context);
+    if (ret) {
+       DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
+       return ADS_ERROR_KRB5(ret);
+    }
+
+    if ((ret = krb5_parse_name(context, principal,
+                                    &princ))) {
+       krb5_free_context(context);
+       DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret)));
+       return ADS_ERROR_KRB5(ret);
+    }
+
+    krb5_get_init_creds_opt_init(&opts);
+    krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+    krb5_get_init_creds_opt_set_renew_life(&opts, 0);
+    krb5_get_init_creds_opt_set_forwardable(&opts, 0);
+    krb5_get_init_creds_opt_set_proxiable(&opts, 0);
+
+    /* We have to obtain an INITIAL changepw ticket for changing password */
+    asprintf(&chpw_princ, "kadmin/changepw@%s",
+                               (char *) krb5_princ_realm(context, princ));
+    password = strdup(oldpw);
+    ret = krb5_get_init_creds_password(context, &creds, princ, password,
+                                          kerb_prompter, NULL, 
+                                          0, chpw_princ, &opts);
+    SAFE_FREE(chpw_princ);
+    SAFE_FREE(password);
+
+    if (ret) {
+      if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+       DEBUG(1,("Password incorrect while getting initial ticket"));
+      else
+       DEBUG(1,("krb5_get_init_creds_password failed (%s)\n", error_message(ret)));
+
+       krb5_free_principal(context, princ);
+       krb5_free_context(context);
+       return ADS_ERROR_KRB5(ret);
+    }
+
+    aret = do_krb5_kpasswd_request(context, kdc_host,
+                                  KRB5_KPASSWD_VERS_CHANGEPW,
+                                  &creds, principal, newpw);
+
+    krb5_free_principal(context, princ);
+    krb5_free_context(context);
+
+    return aret;
 }
 
 
@@ -480,7 +656,12 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
        return ADS_ERROR_KRB5(ret);
     }
 
-    return krb5_set_password(kpasswd_server, target_principal, new_password, time_offset);
+    if (!strcmp(auth_principal, target_principal))
+       return krb5_chg_password(kpasswd_server, target_principal,
+                                   auth_password, new_password, time_offset);
+    else
+       return krb5_set_password(kpasswd_server, target_principal,
+                                new_password, time_offset);
 }
 
 
@@ -515,4 +696,6 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
        return status;
 }
 
+
+
 #endif
index 67669fc0783ae8bd80332eca64d3ddd3189e6f66..bc90e90ea0180f6820484b6cbd89987f3c8fcd53 100644 (file)
@@ -816,18 +816,18 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 {
        int curmod;
        LDAPMod **modlist = (LDAPMod **) *mods;
-       void **values;
+       struct berval **ber_values;
+       char **char_values;
 
        if (!invals) {
-               values = NULL;
                mod_op = LDAP_MOD_DELETE;
        } else {
                if (mod_op & LDAP_MOD_BVALUES)
-                       values = (void **) ads_dup_values(ctx, 
-                                          (const struct berval **)invals);
+                       ber_values = ads_dup_values(ctx, 
+                                               (const struct berval **)invals);
                else
-                       values = (void **) ads_push_strvals(ctx, 
-                                                  (const char **) invals);
+                       char_values = ads_push_strvals(ctx, 
+                                                 (const char **) invals);
        }
 
        /* find the first empty slot */
@@ -846,10 +846,14 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
        if (!(modlist[curmod] = talloc_zero(ctx, sizeof(LDAPMod))))
                return ADS_ERROR(LDAP_NO_MEMORY);
        modlist[curmod]->mod_type = talloc_strdup(ctx, name);
-       if (mod_op & LDAP_MOD_BVALUES)
-               modlist[curmod]->mod_bvalues = (struct berval **) values;
-       else
-               modlist[curmod]->mod_values = (char **) values;
+       if (mod_op & LDAP_MOD_BVALUES) {
+               modlist[curmod]->mod_bvalues = ber_values;
+       } else if (mod_op & LDAP_MOD_DELETE) {
+               modlist[curmod]->mod_values = NULL;
+       } else {
+               modlist[curmod]->mod_values = char_values;
+       }
+
        modlist[curmod]->mod_op = mod_op;
        return ADS_ERROR(LDAP_SUCCESS);
 }
@@ -1500,16 +1504,24 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
 #endif
        if (!(mods = ads_init_mods(ctx))) return ADS_ERROR(LDAP_NO_MEMORY);
 
-       bval.bv_len = sd_size;
-       bval.bv_val = talloc(ctx, sd_size);
+       bval.bv_len = prs_offset(&ps_wire);
+       bval.bv_val = talloc(ctx, bval.bv_len);
        if (!bval.bv_val) {
                ret = ADS_ERROR(LDAP_NO_MEMORY);
                goto ads_set_sd_error;
        }
-       prs_copy_all_data_out(bval.bv_val, &ps_wire);
 
-       ads_mod_ber(ctx, &mods, attrs[0], &bval);
-       ret = ads_gen_mod(ads, dn, mods);
+       prs_set_offset(&ps_wire, 0);
+
+       if (!prs_copy_data_out(bval.bv_val, &ps_wire, bval.bv_len)) {
+               ret = ADS_ERROR(LDAP_NO_MEMORY);
+               goto ads_set_sd_error;          
+       }
+
+       ret = ads_mod_ber(ctx, &mods, attrs[0], &bval);
+       if (ADS_ERR_OK(ret)) {
+               ret = ads_gen_mod(ads, dn, mods);
+       }
 
 ads_set_sd_error:
        ads_msgfree(ads, res);
@@ -1554,7 +1566,7 @@ char *ads_pull_string(ADS_STRUCT *ads,
        char **values;
        char *ret = NULL;
        char *ux_string;
-       int rc;
+       size_t rc;
 
        values = ldap_get_values(ads->ld, msg, field);
        if (!values)
@@ -1563,7 +1575,7 @@ char *ads_pull_string(ADS_STRUCT *ads,
        if (values[0]) {
                rc = pull_utf8_talloc(mem_ctx, &ux_string, 
                                      values[0]);
-               if (rc != -1)
+               if (rc != (size_t)-1)
                        ret = ux_string;
                
        }
@@ -1725,8 +1737,11 @@ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
        count = 0;
        for (i=0; values[i]; i++) {
                ret = sid_parse(values[i]->bv_val, values[i]->bv_len, &(*sids)[count]);
-               if (ret)
+               if (ret) {
+                       fstring sid;
+                       DEBUG(10, ("pulling SID: %s\n", sid_to_string(sid, &(*sids)[count])));
                        count++;
+               }
        }
        
        ldap_value_free_len(values);
index 7aa77bf2a240405251323fd24561777d9a00fd77..29d4533a54fa056357e72184c1594114a95e63ee 100644 (file)
@@ -241,7 +241,12 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        ADS_STATUS status;
        krb5_principal principal;
        krb5_context ctx;
-       krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL};
+       krb5_enctype enc_types[] = {
+#ifdef ENCTYPE_ARCFOUR_HMAC
+                       ENCTYPE_ARCFOUR_HMAC,
+#endif
+                       ENCTYPE_DES_CBC_MD5,
+                       ENCTYPE_NULL};
        gss_OID_desc nt_principal = 
        {10, "\052\206\110\206\367\022\001\002\002\002"};
 
index 021f2d93e4aad7039beb1d7524513e8645d19f47..335cabc95261429172f0255b421f05553721292b 100644 (file)
@@ -29,7 +29,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
     char *new_password;
     char *service_principal;
     ADS_STATUS ret;
-     
+
     if ((password = secrets_fetch_machine_password()) == NULL) {
        DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
        return ADS_ERROR_SYSTEM(ENOENT);
@@ -38,15 +38,17 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
     tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
     new_password = strdup(tmp_password);
     asprintf(&service_principal, "HOST/%s", host_principal);
-    
-    ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, 
-                               service_principal, new_password, ads->auth.time_offset);
+
+    ret = kerberos_set_password(ads->auth.kdc_server, service_principal, password, service_principal, new_password, ads->auth.time_offset);
+
+    if (!ADS_ERR_OK(ret)) goto failed;
 
     if (!secrets_store_machine_password(new_password)) {
            DEBUG(1,("Failed to save machine password\n"));
            return ADS_ERROR_SYSTEM(EACCES);
     }
 
+failed:
     SAFE_FREE(service_principal);
     SAFE_FREE(new_password);
 
index 389b7a1733218222b0a3f1413bd20f6e567ee15c..4962ffa3c9ecad67c57617c53bfc9e048d681415 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    client connect/disconnect routines
    Copyright (C) Andrew Tridgell 1994-1998
-   Copyright (C) Andrew Barteltt 2001-2002
+   Copyright (C) Andrew Bartlett 2001-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ static const struct {
 ****************************************************************************/
 
 static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, 
-                                     const char *pass, int passlen, const char *workgroup)
+                                     const char *pass, size_t passlen, const char *workgroup)
 {
        fstring pword;
        char *p;
@@ -228,7 +228,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
        return True;
 }
 
-static void set_signing_on_cli (struct cli_state *cli, const char* pass, uint8 response[24]
+static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16], DATA_BLOB response
 {
        uint8 zero_sig[8];
        ZERO_STRUCT(zero_sig);
@@ -242,12 +242,18 @@ static void set_signing_on_cli (struct cli_state *cli, const char* pass, uint8 r
 
                DEBUG(3, ("smb signing enabled!\n"));
                cli->sign_info.use_smb_signing = True;
-               cli_calculate_mac_key(cli, pass, response);
+               cli_calculate_mac_key(cli, user_session_key, response);
        } else {
                DEBUG(5, ("smb signing NOT enabled!\n"));
        }
 }
 
+static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key) 
+{
+       memcpy(cli->user_session_key, session_key.data, MIN(session_key.length, sizeof(cli->user_session_key)));
+}
+
+
 static void set_temp_signing_on_cli(struct cli_state *cli) 
 {
        if (cli->sign_info.negotiated_smb_signing)
@@ -265,37 +271,54 @@ static void set_temp_signing_on_cli(struct cli_state *cli)
 ****************************************************************************/
 
 static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, 
-                                 const char *pass, int passlen,
-                                 const char *ntpass, int ntpasslen,
+                                 const char *pass, size_t passlen,
+                                 const char *ntpass, size_t ntpasslen,
                                  const char *workgroup)
 {
        uint32 capabilities = cli_session_setup_capabilities(cli);
-       uchar pword[24];
-       uchar ntpword[24];
+       DATA_BLOB lm_response = data_blob(NULL, 0);
+       DATA_BLOB nt_response = data_blob(NULL, 0);
+       DATA_BLOB session_key = data_blob(NULL, 0);
+       BOOL ret = False;
        char *p;
-       BOOL have_plaintext = False;
-
-       if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword))
-               return False;
 
        if (passlen != 24) {
-               /* non encrypted password supplied. Ignore ntpass. */
-               passlen = 24;
-               ntpasslen = 24;
-               SMBencrypt(pass,cli->secblob.data,pword);
-               SMBNTencrypt(pass,cli->secblob.data,ntpword);
+               if (lp_client_ntlmv2_auth()) {
+                       DATA_BLOB server_chal;
+
+                       server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 
+
+                       if (!SMBNTLMv2encrypt(user, workgroup, pass, server_chal, 
+                                             &lm_response, &nt_response, &session_key)) {
+                               data_blob_free(&server_chal);
+                               return False;
+                       }
+                       data_blob_free(&server_chal);
+
+               } else {
+                       uchar nt_hash[16];
+                       E_md4hash(pass, nt_hash);
+
+                       /* non encrypted password supplied. Ignore ntpass. */
+                       if (lp_client_lanman_auth()) {
+                               lm_response = data_blob(NULL, 24);
+                               SMBencrypt(pass,cli->secblob.data,lm_response.data);
+                       }
+
+                       nt_response = data_blob(NULL, 24);
+                       SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
+                       session_key = data_blob(NULL, 16);
+                       SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+               }
 
-               have_plaintext = True;
                set_temp_signing_on_cli(cli);
        } else {
                /* pre-encrypted password supplied.  Only used for 
                   security=server, can't do
                   signing becouse we don't have oringial key */
-               memcpy(pword, pass, 24);
-               if (ntpasslen == 24)
-                       memcpy(ntpword, ntpass, 24);
-               else
-                       ZERO_STRUCT(ntpword);
+
+               lm_response = data_blob(pass, passlen);
+               nt_response = data_blob(ntpass, ntpasslen);
        }
 
        /* send a session setup command */
@@ -310,28 +333,33 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
        SSVAL(cli->outbuf,smb_vwv3,2);
        SSVAL(cli->outbuf,smb_vwv4,cli->pid);
        SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
-       SSVAL(cli->outbuf,smb_vwv7,passlen);
-       SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
+       SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
+       SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
        SIVAL(cli->outbuf,smb_vwv11,capabilities); 
        p = smb_buf(cli->outbuf);
-       memcpy(p,pword,passlen); p += passlen;
-       memcpy(p,ntpword,ntpasslen); p += ntpasslen;
+       if (lm_response.length) {
+               memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
+       }
+       if (nt_response.length) {
+               memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
+       }
        p += clistr_push(cli, p, user, -1, STR_TERMINATE);
        p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
        p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
        p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
        cli_setup_bcc(cli, p);
 
-       if (!cli_send_smb(cli))
-               return False;
-
-       if (!cli_receive_smb(cli))
-               return False;
+       if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
+               ret = False;
+               goto end;
+       }
 
        show_msg(cli->inbuf);
 
-       if (cli_is_error(cli))
-               return False;
+       if (cli_is_error(cli)) {
+               ret = False;
+               goto end;
+       }
 
        /* use the returned vuid from now on */
        cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -343,11 +371,16 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
 
        fstrcpy(cli->user_name, user);
 
-       if (have_plaintext) {
+       if (session_key.data) {
                /* Have plaintext orginal */
-               set_signing_on_cli(cli, pass, ntpword);
+               set_cli_session_key(cli, session_key);
+               set_signing_on_cli(cli, session_key.data, nt_response);
        }
-       
+
+end:   
+       data_blob_free(&lm_response);
+       data_blob_free(&nt_response);
+       data_blob_free(&session_key);
        return True;
 }
 
@@ -359,11 +392,9 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
 {
        uint32 capabilities = cli_session_setup_capabilities(cli);
        char *p;
-       DATA_BLOB blob2;
+       DATA_BLOB blob2 = data_blob(NULL, 0);
        uint32 len;
 
-       blob2 = data_blob(NULL, 0);
-
        capabilities |= CAP_EXTENDED_SECURITY;
 
        /* send a session setup command */
@@ -419,6 +450,13 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
 }
 
 #ifdef HAVE_KRB5
+/****************************************************************************
+ Use in-memory credentials cache
+****************************************************************************/
+static void use_in_memory_ccache(void) {
+       setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
+}
+
 /****************************************************************************
  Do a spnego/kerberos encrypted session setup.
 ****************************************************************************/
@@ -456,126 +494,87 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *princi
 static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, 
                                      const char *pass, const char *workgroup)
 {
-       DATA_BLOB msg1, struct_blob;
-       DATA_BLOB blob, chal1, chal2, auth, challenge_blob;
-       uint8 challenge[8];
-       uint8 nthash[24], lmhash[24], sess_key[16];
-       uint32 neg_flags, chal_flags, ntlmssp_command, unkn1, unkn2;
-       pstring server_domain;  /* FIX THIS, SHOULD be UCS2-LE */
-
-       neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
-               NTLMSSP_NEGOTIATE_128 | 
-               NTLMSSP_NEGOTIATE_NTLM |
-               NTLMSSP_REQUEST_TARGET;
-
-       memset(sess_key, 0, 16);
-
-       DEBUG(10, ("sending NTLMSSP_NEGOTIATE\n"));
-
-       /* generate the ntlmssp negotiate packet */
-       msrpc_gen(&blob, "CddAA",
-                 "NTLMSSP",
-                 NTLMSSP_NEGOTIATE,
-                 neg_flags,
-                 workgroup, 
-                 cli->calling.name);
-       DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n",
-                 neg_flags, workgroup, cli->calling.name));
-       /* and wrap it in a SPNEGO wrapper */
-       msg1 = gen_negTokenInit(OID_NTLMSSP, blob);
-       data_blob_free(&blob);
-
-       /* now send that blob on its way */
-       blob = cli_session_setup_blob(cli, msg1);
-
-       data_blob_free(&msg1);
+       struct ntlmssp_client_state *ntlmssp_state;
+       NTSTATUS nt_status;
+       int turn = 1;
+       DATA_BLOB msg1;
+       DATA_BLOB blob;
+       DATA_BLOB blob_in = data_blob(NULL, 0);
+       DATA_BLOB blob_out;
 
-       if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED))
+       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
                return False;
+       }
 
-#if 0
-       file_save("chal.dat", blob.data, blob.length);
-#endif
-
-       /* the server gives us back two challenges */
-       if (!spnego_parse_challenge(blob, &chal1, &chal2)) {
-               DEBUG(3,("Failed to parse challenges\n"));
+       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
                return False;
        }
-
-       data_blob_free(&blob);
-
-       /*
-        * Ok, chal1 and chal2 are actually two identical copies of
-        * the NTLMSSP Challenge BLOB, and they contain, encoded in them
-        * the challenge to use.
-        */
-
-       if (!msrpc_parse(&chal1, "CdUdbddB",
-                        "NTLMSSP",
-                        &ntlmssp_command, 
-                        &server_domain,
-                        &chal_flags,
-                        &challenge_blob, 8,
-                        &unkn1, &unkn2,
-                        &struct_blob)) {
-         DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
-         return False;
+       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
+               return False;
        }
-                       
-       if (ntlmssp_command != NTLMSSP_CHALLENGE) {
-               DEBUG(0, ("NTLMSSP Response != NTLMSSP_CHALLENGE. Got %0X\n", 
-                       ntlmssp_command));
+       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
                return False;
        }
-       DEBUG(10, ("Challenge:\n"));
-       dump_data(10, challenge_blob.data, 8);
-
-       /* encrypt the password with the challenge which is in the blob */
-       memcpy(challenge, challenge_blob.data, 8); 
-       SMBencrypt(pass, challenge,lmhash);
-       SMBNTencrypt(pass, challenge,nthash);
-       data_blob_free(&challenge_blob);
-
-#if 0
-       file_save("nthash.dat", nthash, 24);
-       file_save("lmhash.dat", lmhash, 24);
-       file_save("chal1.dat", chal1.data, chal1.length);
-#endif
-
-       data_blob_free(&chal1);
-       data_blob_free(&chal2);
 
-       /* this generates the actual auth packet */
-       msrpc_gen(&blob, "CdBBUUUBd", 
-                 "NTLMSSP", 
-                 NTLMSSP_AUTH, 
-                 lmhash, 24,
-                 nthash, 24,
-                 workgroup, 
-                 user, 
-                 cli->calling.name,
-                 sess_key, 0,
-                 neg_flags);
-
-       /* wrap it in SPNEGO */
-       auth = spnego_gen_auth(blob);
-
-       data_blob_free(&blob);
-
-       /* now send the auth packet and we should be done */
-       blob = cli_session_setup_blob(cli, auth);
+       ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth();
+
+       do {
+               nt_status = ntlmssp_client_update(ntlmssp_state, 
+                                                 blob_in, &blob_out);
+               data_blob_free(&blob_in);
+               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+                       if (turn == 1) {
+                               /* and wrap it in a SPNEGO wrapper */
+                               msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
+                       } else {
+                               /* wrap it in SPNEGO */
+                               msg1 = spnego_gen_auth(blob_out);
+                       }
+               
+                       /* now send that blob on its way */
+                       blob = cli_session_setup_blob(cli, msg1);
+                       data_blob_free(&msg1);
+                       nt_status = cli_nt_error(cli);
+               }
+               
+               if (!blob.length) {
+                       if (NT_STATUS_IS_OK(nt_status)) {
+                               nt_status = NT_STATUS_UNSUCCESSFUL;
+                       }
+               } else if ((turn == 1) && 
+                          NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+                       DATA_BLOB tmp_blob = data_blob(NULL, 0);
+                       /* the server might give us back two challenges */
+                       if (!spnego_parse_challenge(blob, &blob_in, 
+                                                   &tmp_blob)) {
+                               DEBUG(3,("Failed to parse challenges\n"));
+                               nt_status = NT_STATUS_INVALID_PARAMETER;
+                       }
+                       data_blob_free(&tmp_blob);
+               } else {
+                       /* the server might give us back two challenges */
+                       if (!spnego_parse_auth_response(blob, nt_status, 
+                                                       &blob_in)) {
+                               DEBUG(3,("Failed to parse auth response\n"));
+                               if (NT_STATUS_IS_OK(nt_status) 
+                                   || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) 
+                                       nt_status = NT_STATUS_INVALID_PARAMETER;
+                       }
+               }
+               data_blob_free(&blob);
+               data_blob_free(&blob_out);
+               turn++;
+       } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 
-       data_blob_free(&auth);
-       data_blob_free(&blob);
+       if (NT_STATUS_IS_OK(nt_status)) {
+               set_cli_session_key(cli, ntlmssp_state->session_key);
+       }
 
-       if (cli_is_error(cli))
+       if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
                return False;
+       }
 
-       set_signing_on_cli(cli, pass, nthash);
-
-       return True;
+       return (NT_STATUS_IS_OK(nt_status));
 }
 
 /****************************************************************************
@@ -628,7 +627,22 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
        fstrcpy(cli->user_name, user);
 
 #ifdef HAVE_KRB5
+       /* If password is set we reauthenticate to kerberos server
+        * and do not store results */
+
        if (got_kerberos_mechanism && cli->use_kerberos) {
+               if (*pass) {
+                       int ret;
+                       
+                       use_in_memory_ccache();
+                       ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
+                       
+                       if (ret){
+                               DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
+                               return False;
+                       }
+               }
+               
                return cli_session_setup_kerberos(cli, principal, workgroup);
        }
 #endif
@@ -942,7 +956,10 @@ BOOL cli_negprot(struct cli_state *cli)
                                    smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
                }
 
-               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
+               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED))
+                       cli->sign_info.negotiated_smb_signing = True;
+
+               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
                        cli->sign_info.negotiated_smb_signing = True;
 
        } else if (cli->protocol >= PROTOCOL_LANMAN1) {
index ed1286d627dee2dd60fe411e444340ec6200a6e1..9598f4ac9642da4c55b72b72e8bd64f12e7e72b1 100644 (file)
@@ -114,9 +114,14 @@ BOOL cli_receive_smb(struct cli_state *cli)
                cli->smb_rw_error = smb_read_error;
                close(cli->fd);
                cli->fd = -1;
+               return ret;
        }
 
-       return ret;
+       if (!cli_check_sign_mac(cli)) {
+               DEBUG(0, ("SMB Signiture verification failed on incoming packet!\n"));
+               return False;
+       };
+       return True;
 }
 
 /****************************************************************************
@@ -246,8 +251,10 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        cli->outbuf = (char *)malloc(cli->bufsize);
        cli->inbuf = (char *)malloc(cli->bufsize);
        cli->oplock_handler = cli_oplock_ack;
-       if (lp_use_spnego())
-               cli->use_spnego = True;
+
+       cli->use_spnego = lp_client_use_spnego();
+
+       cli->capabilities = CAP_UNICODE | CAP_STATUS32;
 
        /* Set the CLI_FORCE_DOSERR environment variable to test
           client routines using DOS errors instead of STATUS32
@@ -255,9 +262,8 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        if (getenv("CLI_FORCE_DOSERR"))
                cli->force_dos_errors = True;
 
-       /* A way to attempt to force SMB signing */
-       if (getenv("CLI_FORCE_SMB_SIGNING"))
-               cli->sign_info.negotiated_smb_signing = True;
+       if (lp_client_signing()) 
+               cli->sign_info.allow_smb_signing = True;
                                    
        if (!cli->outbuf || !cli->inbuf)
                 goto error;
index 41b5c3f99089e1024716b7ddbbe38bd552b94b7d..e93f1855ddd9100af1528733ed0b3742ca968fd7 100644 (file)
@@ -481,297 +481,50 @@ DATA_BLOB spnego_gen_auth_response(DATA_BLOB *ntlmssp_reply, NTSTATUS nt_status)
 }
 
 /*
-  this is a tiny msrpc packet generator. I am only using this to
-  avoid tying this code to a particular varient of our rpc code. This
-  generator is not general enough for all our rpc needs, its just
-  enough for the spnego/ntlmssp code
-
-  format specifiers are:
-
-  U = unicode string (input is unix string)
-  a = address (input is BOOL unicode, char *unix_string)
-      (1 byte type, 1 byte length, unicode/ASCII string, all inline)
-  A = ASCII string (input is unix string)
-  B = data blob (pointer + length)
-  b = data blob in header (pointer + length)
-  D
-  d = word (4 bytes)
-  C = constant ascii string
- */
-BOOL msrpc_gen(DATA_BLOB *blob,
-              const char *format, ...)
+ parse a SPNEGO NTLMSSP auth packet. This contains the encrypted passwords
+*/
+BOOL spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status, 
+                               DATA_BLOB *auth)
 {
-       int i, n;
-       va_list ap;
-       char *s;
-       uint8 *b;
-       int head_size=0, data_size=0;
-       int head_ofs, data_ofs;
-       BOOL unicode;
-
-       /* first scan the format to work out the header and body size */
-       va_start(ap, format);
-       for (i=0; format[i]; i++) {
-               switch (format[i]) {
-               case 'U':
-                       s = va_arg(ap, char *);
-                       head_size += 8;
-                       data_size += str_charnum(s) * 2;
-                       break;
-               case 'A':
-                       s = va_arg(ap, char *);
-                       head_size += 8;
-                       data_size += str_ascii_charnum(s);
-                       break;
-               case 'a':
-                       unicode = va_arg(ap, BOOL);
-                       n = va_arg(ap, int);
-                       s = va_arg(ap, char *);
-                       if (unicode) {
-                               data_size += (str_charnum(s) * 2) + 4;
-                       } else {
-                               data_size += (str_ascii_charnum(s)) + 4;
-                       }
-                       break;
-               case 'B':
-                       b = va_arg(ap, uint8 *);
-                       head_size += 8;
-                       data_size += va_arg(ap, int);
-                       break;
-               case 'b':
-                       b = va_arg(ap, uint8 *);
-                       head_size += va_arg(ap, int);
-                       break;
-               case 'd':
-                       n = va_arg(ap, int);
-                       head_size += 4;
-                       break;
-               case 'C':
-                       s = va_arg(ap, char *);
-                       head_size += str_charnum(s) + 1;
-                       break;
-               }
-       }
-       va_end(ap);
-
-       /* allocate the space, then scan the format again to fill in the values */
-       *blob = data_blob(NULL, head_size + data_size);
-
-       head_ofs = 0;
-       data_ofs = head_size;
-
-       va_start(ap, format);
-       for (i=0; format[i]; i++) {
-               switch (format[i]) {
-               case 'U':
-                       s = va_arg(ap, char *);
-                       n = str_charnum(s);
-                       SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
-                       SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
-                       SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
-                       push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN);
-                       data_ofs += n*2;
-                       break;
-               case 'A':
-                       s = va_arg(ap, char *);
-                       n = str_ascii_charnum(s);
-                       SSVAL(blob->data, head_ofs, n); head_ofs += 2;
-                       SSVAL(blob->data, head_ofs, n); head_ofs += 2;
-                       SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
-                       push_string(NULL, blob->data+data_ofs, s, n, STR_ASCII|STR_NOALIGN);
-                       data_ofs += n;
-                       break;
-               case 'a':
-                       unicode = va_arg(ap, BOOL);
-                       n = va_arg(ap, int);
-                       SSVAL(blob->data, data_ofs, n); data_ofs += 2;
-                       s = va_arg(ap, char *);
-                       if (unicode) {
-                               n = str_charnum(s);
-                               SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
-                               if (0 < n) {
-                                       push_string(NULL, blob->data+data_ofs, s, n*2,
-                                                   STR_UNICODE|STR_NOALIGN);
-                               }
-                               data_ofs += n*2;
-                       } else {
-                               n = str_ascii_charnum(s);
-                               SSVAL(blob->data, data_ofs, n); data_ofs += 2;
-                               if (0 < n) {
-                                       push_string(NULL, blob->data+data_ofs, s, n,
-                                                   STR_ASCII|STR_NOALIGN);
-                               }
-                               data_ofs += n;
-                       }
-                       break;
-
-               case 'B':
-                       b = va_arg(ap, uint8 *);
-                       n = va_arg(ap, int);
-                       SSVAL(blob->data, head_ofs, n); head_ofs += 2;
-                       SSVAL(blob->data, head_ofs, n); head_ofs += 2;
-                       SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
-                       memcpy(blob->data+data_ofs, b, n);
-                       data_ofs += n;
-                       break;
-               case 'd':
-                       n = va_arg(ap, int);
-                       SIVAL(blob->data, head_ofs, n); head_ofs += 4;
-                       break;
-               case 'b':
-                       b = va_arg(ap, uint8 *);
-                       n = va_arg(ap, int);
-                       memcpy(blob->data + head_ofs, b, n);
-                       head_ofs += n;
-                       break;
-               case 'C':
-                       s = va_arg(ap, char *);
-                       head_ofs += push_string(NULL, blob->data+head_ofs, s, -1, 
-                                               STR_ASCII|STR_TERMINATE);
-                       break;
-               }
-       }
-       va_end(ap);
+       ASN1_DATA data;
+       uint8 negResult;
 
-       return True;
-}
+       if (NT_STATUS_IS_OK(nt_status)) {
+               negResult = SPNEGO_NEG_RESULT_ACCEPT;
+       } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               negResult = SPNEGO_NEG_RESULT_INCOMPLETE;
+       } else {
+               negResult = SPNEGO_NEG_RESULT_REJECT;
+       }
 
+       asn1_load(&data, blob);
+       asn1_start_tag(&data, ASN1_CONTEXT(1));
+       asn1_start_tag(&data, ASN1_SEQUENCE(0));
+       asn1_start_tag(&data, ASN1_CONTEXT(0));
+       asn1_check_enumerated(&data, negResult);
+       asn1_end_tag(&data);
 
-/*
-  this is a tiny msrpc packet parser. This the the partner of msrpc_gen
-
-  format specifiers are:
-
-  U = unicode string (output is unix string)
-  A = ascii string
-  B = data blob
-  b = data blob in header
-  d = word (4 bytes)
-  C = constant ascii string
- */
-BOOL msrpc_parse(DATA_BLOB *blob,
-                const char *format, ...)
-{
-       int i;
-       va_list ap;
-       char **ps, *s;
-       DATA_BLOB *b;
-       int head_ofs = 0;
-       uint16 len1, len2;
-       uint32 ptr;
-       uint32 *v;
-       pstring p;
-
-       va_start(ap, format);
-       for (i=0; format[i]; i++) {
-               switch (format[i]) {
-               case 'U':
-                       len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
-                       len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
-                       ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
-                       /* make sure its in the right format - be strict */
-                       if (len1 != len2 || (len1&1) || ptr + len1 > blob->length) {
-                               return False;
-                       }
-                       ps = va_arg(ap, char **);
-                       pull_string(NULL, p, blob->data + ptr, -1, len1, 
-                                   STR_UNICODE|STR_NOALIGN);
-                       (*ps) = strdup(p);
-                       break;
-               case 'A':
-                       len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
-                       len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
-                       ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
-
-                       /* make sure its in the right format - be strict */
-                       if (len1 != len2 || ptr + len1 > blob->length) {
-                               return False;
-                       }
-                       ps = va_arg(ap, char **);
-                       if (0 < len1) {
-                               pull_string(NULL, p, blob->data + ptr, -1, 
-                                           len1, STR_ASCII|STR_NOALIGN);
-                               (*ps) = strdup(p);
-                       } else {
-                               (*ps) = NULL;
-                       }
-                       break;
-               case 'B':
-                       len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
-                       len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
-                       ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
-                       /* make sure its in the right format - be strict */
-                       if (len1 != len2 || ptr + len1 > blob->length) {
-                               return False;
-                       }
-                       b = (DATA_BLOB *)va_arg(ap, void *);
-                       *b = data_blob(blob->data + ptr, len1);
-                       break;
-               case 'b':
-                       b = (DATA_BLOB *)va_arg(ap, void *);
-                       len1 = va_arg(ap, unsigned);
-                       *b = data_blob(blob->data + head_ofs, len1);
-                       head_ofs += len1;
-                       break;
-               case 'd':
-                       v = va_arg(ap, uint32 *);
-                       *v = IVAL(blob->data, head_ofs); head_ofs += 4;
-                       break;
-               case 'C':
-                       s = va_arg(ap, char *);
-                       head_ofs += pull_string(NULL, p, blob->data+head_ofs, sizeof(p), 
-                                               blob->length - head_ofs, 
-                                               STR_ASCII|STR_TERMINATE);
-                       if (strcmp(s, p) != 0) {
-                               return False;
-                       }
-                       break;
-               }
+       if (negResult == SPNEGO_NEG_RESULT_INCOMPLETE) {
+               asn1_start_tag(&data,ASN1_CONTEXT(1));
+               asn1_check_OID(&data, OID_NTLMSSP);
+               asn1_end_tag(&data);
+               
+               asn1_start_tag(&data,ASN1_CONTEXT(2));
+               asn1_read_OctetString(&data, auth);
+               asn1_end_tag(&data);
        }
-       va_end(ap);
 
-       return True;
-}
+       asn1_end_tag(&data);
+       asn1_end_tag(&data);
 
-/**
- * Print out the NTLMSSP flags for debugging 
- */
+       if (data.has_error) {
+               DEBUG(3,("spnego_parse_auth_response failed at %d\n", (int)data.ofs));
+               asn1_free(&data);
+               data_blob_free(auth);
+               return False;
+       }
 
-void debug_ntlmssp_flags(uint32 neg_flags)
-{
-       DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));
-       
-       if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_OEM) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
-       if (neg_flags & NTLMSSP_REQUEST_TARGET) 
-               DEBUGADD(4, ("  NTLMSSP_REQUEST_TARGET\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
-       if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) 
-               DEBUGADD(4, ("  NTLMSSP_CHAL_TARGET_INFO\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_128) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_128\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) 
-               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+       asn1_free(&data);
+       return True;
 }
 
index 5b608e0a7a90866135f417b312663c8646731674..e1509f6b6303a4451194b90edaebaae32983fa93 100644 (file)
 #include "includes.h"
 
 /**
- * Default challange generation code.
+ * Print out the NTLMSSP flags for debugging 
+ * @param neg_flags The flags from the packet
+ */
+
+void debug_ntlmssp_flags(uint32 neg_flags)
+{
+       DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));
+       
+       if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_OEM) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
+       if (neg_flags & NTLMSSP_REQUEST_TARGET) 
+               DEBUGADD(4, ("  NTLMSSP_REQUEST_TARGET\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
+       if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) 
+               DEBUGADD(4, ("  NTLMSSP_CHAL_TARGET_INFO\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_128) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_128\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+}
+
+/**
+ * Default challenge generation code.
  *
  */
    
-
 static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state)
 {
        static uchar chal[8];
@@ -37,71 +79,17 @@ static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state)
        return chal;
 }
 
-NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
-{
-       TALLOC_CTX *mem_ctx;
-
-       mem_ctx = talloc_init("NTLMSSP context");
-       
-       *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state));
-       if (!*ntlmssp_state) {
-               DEBUG(0,("ntlmssp_start: talloc failed!\n"));
-               talloc_destroy(mem_ctx);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ZERO_STRUCTP(*ntlmssp_state);
-
-       (*ntlmssp_state)->mem_ctx = mem_ctx;
-       (*ntlmssp_state)->get_challenge = get_challenge;
-
-       (*ntlmssp_state)->get_global_myname = global_myname;
-       (*ntlmssp_state)->get_domain = lp_workgroup;
-       (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */
-
-       return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state)
-{
-       TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
-
-       data_blob_free(&(*ntlmssp_state)->chal);
-       data_blob_free(&(*ntlmssp_state)->lm_resp);
-       data_blob_free(&(*ntlmssp_state)->nt_resp);
-
-       SAFE_FREE((*ntlmssp_state)->user);
-       SAFE_FREE((*ntlmssp_state)->domain);
-       SAFE_FREE((*ntlmssp_state)->workstation);
-
-       talloc_destroy(mem_ctx);
-       *ntlmssp_state = NULL;
-       return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, 
-                              DATA_BLOB request, DATA_BLOB *reply) 
-{
-       uint32 ntlmssp_command;
-       *reply = data_blob(NULL, 0);
-
-       if (!msrpc_parse(&request, "Cd",
-                        "NTLMSSP",
-                        &ntlmssp_command)) {
-               
-               return NT_STATUS_LOGON_FAILURE;
-       }
-
-       if (ntlmssp_command == NTLMSSP_NEGOTIATE) {
-               return ntlmssp_negotiate(ntlmssp_state, request, reply);
-       } else if (ntlmssp_command == NTLMSSP_AUTH) {
-               return ntlmssp_auth(ntlmssp_state, request, reply);
-       } else {
-               return NT_STATUS_LOGON_FAILURE;
-       }
-}
+/**
+ * Determine correct target name flags for reply, given server role 
+ * and negoitated falgs
+ * 
+ * @param ntlmssp_state NTLMSSP State
+ * @param neg_flags The flags from the packet
+ * @param chal_flags The flags to be set in the reply packet
+ * @return The 'target name' string.
+ */
 
-static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state, 
+static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
                                       uint32 neg_flags, uint32 *chal_flags) 
 {
        if (neg_flags & NTLMSSP_REQUEST_TARGET) {
@@ -119,8 +107,17 @@ static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state,
        }
 }
 
-NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, 
-                          DATA_BLOB request, DATA_BLOB *reply) 
+/**
+ * Next state function for the Negotiate packet
+ * 
+ * @param ntlmssp_state NTLMSSP State
+ * @param request The request, as a DATA_BLOB
+ * @param request The reply, as an allocated DATA_BLOB, caller to free.
+ * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent. 
+ */
+
+static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
+                                        const DATA_BLOB request, DATA_BLOB *reply) 
 {
        DATA_BLOB struct_blob;
        fstring dnsname, dnsdomname;
@@ -140,7 +137,7 @@ NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state,
                         &neg_flags,
                         &cliname,
                         &domname)) {
-               return NT_STATUS_LOGON_FAILURE;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        SAFE_FREE(cliname);
@@ -219,11 +216,22 @@ NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state,
                
        data_blob_free(&struct_blob);
 
+       ntlmssp_state->expected_state = NTLMSSP_AUTH;
+
        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, 
-                     DATA_BLOB request, DATA_BLOB *reply) 
+/**
+ * Next state function for the Authenticate packet
+ * 
+ * @param ntlmssp_state NTLMSSP State
+ * @param request The request, as a DATA_BLOB
+ * @param request The reply, as an allocated DATA_BLOB, caller to free.
+ * @return Errors or NT_STATUS_OK. 
+ */
+
+static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
+                                   const DATA_BLOB request, DATA_BLOB *reply) 
 {
        DATA_BLOB sess_key;
        uint32 ntlmssp_command, neg_flags;
@@ -260,7 +268,7 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state,
                         &ntlmssp_state->workstation,
                         &sess_key,
                         &neg_flags)) {
-               return NT_STATUS_LOGON_FAILURE;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        data_blob_free(&sess_key);
@@ -279,3 +287,339 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state,
 
        return nt_status;
 }
+
+/**
+ * Create an NTLMSSP state machine
+ * 
+ * @param ntlmssp_state NTLMSSP State, allocated by this funciton
+ */
+
+NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
+{
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_init("NTLMSSP context");
+       
+       *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state));
+       if (!*ntlmssp_state) {
+               DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
+               talloc_destroy(mem_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       (*ntlmssp_state)->mem_ctx = mem_ctx;
+       (*ntlmssp_state)->get_challenge = get_challenge;
+
+       (*ntlmssp_state)->get_global_myname = global_myname;
+       (*ntlmssp_state)->get_domain = lp_workgroup;
+       (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */
+
+       (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE;
+
+       return NT_STATUS_OK;
+}
+
+/**
+ * End an NTLMSSP state machine
+ * 
+ * @param ntlmssp_state NTLMSSP State, free()ed by this funciton
+ */
+
+NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state)
+{
+       TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
+
+       data_blob_free(&(*ntlmssp_state)->chal);
+       data_blob_free(&(*ntlmssp_state)->lm_resp);
+       data_blob_free(&(*ntlmssp_state)->nt_resp);
+
+       SAFE_FREE((*ntlmssp_state)->user);
+       SAFE_FREE((*ntlmssp_state)->domain);
+       SAFE_FREE((*ntlmssp_state)->workstation);
+
+       talloc_destroy(mem_ctx);
+       *ntlmssp_state = NULL;
+       return NT_STATUS_OK;
+}
+
+/**
+ * Next state function for the NTLMSSP state machine
+ * 
+ * @param ntlmssp_state NTLMSSP State
+ * @param request The request, as a DATA_BLOB
+ * @param request The reply, as an allocated DATA_BLOB, caller to free.
+ * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK. 
+ */
+
+NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, 
+                              const DATA_BLOB request, DATA_BLOB *reply) 
+{
+       uint32 ntlmssp_command;
+       *reply = data_blob(NULL, 0);
+
+       if (!msrpc_parse(&request, "Cd",
+                        "NTLMSSP",
+                        &ntlmssp_command)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (ntlmssp_command != ntlmssp_state->expected_state) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (ntlmssp_command == NTLMSSP_NEGOTIATE) {
+               return ntlmssp_server_negotiate(ntlmssp_state, request, reply);
+       } else if (ntlmssp_command == NTLMSSP_AUTH) {
+               return ntlmssp_server_auth(ntlmssp_state, request, reply);
+       } else {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+}
+
+/*********************************************************************
+ Client side NTLMSSP
+*********************************************************************/
+
+/**
+ * Next state function for the Initial packet
+ * 
+ * @param ntlmssp_state NTLMSSP State
+ * @param request The request, as a DATA_BLOB.  reply.data must be NULL
+ * @param request The reply, as an allocated DATA_BLOB, caller to free.
+ * @return Errors or NT_STATUS_OK. 
+ */
+
+static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_state, 
+                                 DATA_BLOB reply, DATA_BLOB *next_request) 
+{
+       if (ntlmssp_state->unicode) {
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
+       }
+       
+       /* generate the ntlmssp negotiate packet */
+       msrpc_gen(next_request, "CddAA",
+                 "NTLMSSP",
+                 NTLMSSP_NEGOTIATE,
+                 ntlmssp_state->neg_flags,
+                 ntlmssp_state->get_domain(), 
+                 ntlmssp_state->get_global_myname());
+
+       return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+/**
+ * Next state function for the Challenge Packet.  Generate an auth packet.
+ * 
+ * @param ntlmssp_state NTLMSSP State
+ * @param request The request, as a DATA_BLOB.  reply.data must be NULL
+ * @param request The reply, as an allocated DATA_BLOB, caller to free.
+ * @return Errors or NT_STATUS_OK. 
+ */
+
+static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_state, 
+                                        const DATA_BLOB reply, DATA_BLOB *next_request) 
+{
+       uint32 chal_flags, ntlmssp_command, unkn1, unkn2;
+       DATA_BLOB server_domain_blob;
+       DATA_BLOB challenge_blob;
+       DATA_BLOB struct_blob;
+       char *server_domain;
+       const char *chal_parse_string;
+       const char *auth_gen_string;
+       DATA_BLOB lm_response = data_blob(NULL, 0);
+       DATA_BLOB nt_response = data_blob(NULL, 0);
+       DATA_BLOB session_key = data_blob(NULL, 0);
+       uint8 datagram_sess_key[16];
+
+       ZERO_STRUCT(datagram_sess_key);
+
+       if (!msrpc_parse(&reply, "CdBd",
+                        "NTLMSSP",
+                        &ntlmssp_command, 
+                        &server_domain_blob,
+                        &chal_flags)) {
+               DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
+       data_blob_free(&server_domain_blob);
+
+       if (chal_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+               chal_parse_string = "CdUdbddB";
+               auth_gen_string = "CdBBUUUBd";
+               ntlmssp_state->unicode = True;
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
+               ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM;
+       } else if (chal_flags & NTLMSSP_NEGOTIATE_OEM) {
+               chal_parse_string = "CdAdbddB";
+               auth_gen_string = "CdBBAAABd";
+               ntlmssp_state->unicode = False;
+               ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
+       } else {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (!msrpc_parse(&reply, chal_parse_string,
+                        "NTLMSSP",
+                        &ntlmssp_command, 
+                        &server_domain,
+                        &chal_flags,
+                        &challenge_blob, 8,
+                        &unkn1, &unkn2,
+                        &struct_blob)) {
+               DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       SAFE_FREE(server_domain);
+       data_blob_free(&struct_blob);
+       
+       if (challenge_blob.length != 8) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (ntlmssp_state->use_ntlmv2) {
+
+               /* TODO: if the remote server is standalone, then we should replace 'domain'
+                  with the server name as supplied above */
+               
+               if (!SMBNTLMv2encrypt(ntlmssp_state->user, 
+                                     ntlmssp_state->domain, 
+                                     ntlmssp_state->password, challenge_blob, 
+                                     &lm_response, &nt_response, &session_key)) {
+                       data_blob_free(&challenge_blob);
+                       return NT_STATUS_NO_MEMORY;
+               }
+       } else {
+               uchar nt_hash[16];
+               E_md4hash(ntlmssp_state->password, nt_hash);
+               
+               /* non encrypted password supplied. Ignore ntpass. */
+               if (lp_client_lanman_auth()) {
+                       lm_response = data_blob(NULL, 24);
+                       SMBencrypt(ntlmssp_state->password,challenge_blob.data,
+                                  lm_response.data);
+               }
+               
+               nt_response = data_blob(NULL, 24);
+               SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
+                            nt_response.data);
+               session_key = data_blob(NULL, 16);
+               SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+       }
+       
+       data_blob_free(&challenge_blob);
+
+       /* this generates the actual auth packet */
+       if (!msrpc_gen(next_request, auth_gen_string, 
+                      "NTLMSSP", 
+                      NTLMSSP_AUTH, 
+                      lm_response.data, lm_response.length,
+                      nt_response.data, nt_response.length,
+                      ntlmssp_state->domain, 
+                      ntlmssp_state->user, 
+                      ntlmssp_state->get_global_myname(), 
+                      datagram_sess_key, 0,
+                      ntlmssp_state->neg_flags)) {
+               
+               data_blob_free(&lm_response);
+               data_blob_free(&nt_response);
+               data_blob_free(&session_key);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       data_blob_free(&lm_response);
+       data_blob_free(&nt_response);
+
+       ntlmssp_state->session_key = session_key;
+
+       return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
+{
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_init("NTLMSSP Client context");
+       
+       *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state));
+       if (!*ntlmssp_state) {
+               DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
+               talloc_destroy(mem_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       (*ntlmssp_state)->mem_ctx = mem_ctx;
+
+       (*ntlmssp_state)->get_global_myname = global_myname;
+       (*ntlmssp_state)->get_domain = lp_workgroup;
+
+       (*ntlmssp_state)->unicode = True;
+
+       (*ntlmssp_state)->neg_flags = 
+               NTLMSSP_NEGOTIATE_128 | 
+               NTLMSSP_NEGOTIATE_NTLM |
+               NTLMSSP_REQUEST_TARGET;
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state)
+{
+       TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
+
+       data_blob_free(&(*ntlmssp_state)->session_key);
+       talloc_destroy(mem_ctx);
+       *ntlmssp_state = NULL;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, 
+                              DATA_BLOB reply, DATA_BLOB *next_request) 
+{
+       uint32 ntlmssp_command;
+       *next_request = data_blob(NULL, 0);
+
+       if (!reply.length) {
+               return ntlmssp_client_initial(ntlmssp_state, reply, next_request);
+       }               
+
+       if (!msrpc_parse(&reply, "Cd",
+                        "NTLMSSP",
+                        &ntlmssp_command)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (ntlmssp_command == NTLMSSP_CHALLENGE) {
+               return ntlmssp_client_challenge(ntlmssp_state, reply, next_request);
+       }
+       return NT_STATUS_INVALID_PARAMETER;
+}
+
+NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *user) 
+{
+       ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user);
+       if (!ntlmssp_state->user) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ntlmssp_set_password(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *password) 
+{
+       ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
+       if (!ntlmssp_state->password) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
+
+NTSTATUS ntlmssp_set_domain(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *domain) 
+{
+       ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain);
+       if (!ntlmssp_state->domain) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
index a57a98e3ea68fc0dbd35f0cff558b0e4141591cb..aa9391325fa5fc8b75b7b0f5890e50489102e134 100644 (file)
@@ -5,6 +5,7 @@
    Modified by Jeremy Allison 1995.
    Copyright (C) Jeremy Allison 1995-2000.
    Copyright (C) Luke Kennethc Casson Leighton 1996-2000.
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -294,6 +295,64 @@ void SMBsesskeygen_ntv1(const uchar kr[16],
 #endif
 }
 
+DATA_BLOB NTLMv2_generate_response(uchar ntlm_v2_hash[16],
+                                  DATA_BLOB server_chal, size_t client_chal_length)
+{
+       uchar ntlmv2_response[16];
+       DATA_BLOB ntlmv2_client_data;
+       DATA_BLOB final_response;
+       
+       /* NTLMv2 */
+
+       /* We also get to specify some random data */
+       ntlmv2_client_data = data_blob(NULL, client_chal_length);
+       generate_random_buffer(ntlmv2_client_data.data, ntlmv2_client_data.length, False);
+       
+       /* Given that data, and the challenge from the server, generate a response */
+       SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, ntlmv2_client_data, ntlmv2_response);
+       
+       /* put it into nt_response, for the code below to put into the packet */
+       final_response = data_blob(NULL, ntlmv2_client_data.length + sizeof(ntlmv2_response));
+       memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
+       /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */
+       memcpy(final_response.data + sizeof(ntlmv2_response), ntlmv2_client_data.data, ntlmv2_client_data.length);
+       data_blob_free(&ntlmv2_client_data);
+
+       return final_response;
+}
+
+BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, 
+                     const DATA_BLOB server_chal, 
+                     DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
+                     DATA_BLOB *session_key) 
+{
+       uchar nt_hash[16];
+       uchar ntlm_v2_hash[16];
+       E_md4hash(password, nt_hash);
+
+       /* We don't use the NT# directly.  Instead we use it mashed up with
+          the username and domain.
+          This prevents username swapping during the auth exchange
+       */
+       if (!ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash)) {
+               return False;
+       }
+       
+       *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 64 /* pick a number, > 8 */);
+       
+       /* LMv2 */
+       
+       *lm_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 8);
+       
+       *session_key = data_blob(NULL, 16);
+       
+       /* The NTLMv2 calculations also provide a session key, for signing etc later */
+       /* use only the first 16 bytes of nt_response for session key */
+       SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, session_key->data);
+
+       return True;
+}
+
 /***********************************************************
  encode a password buffer.  The caller gets to figure out 
  what to put in it.
@@ -362,20 +421,20 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
  SMB signing - setup the MAC key.
 ************************************************************/
 
-void cli_calculate_mac_key(struct cli_state *cli, const char *ntpasswd, const uchar resp[24])
+void cli_calculate_mac_key(struct cli_state *cli, const uchar user_session_key[16], const DATA_BLOB response)
 {
-       /* Get first 16 bytes. */
-       E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]);
-       memcpy(&cli->sign_info.mac_key[16],resp,24);
-       cli->sign_info.mac_key_len = 40;
+       
+       memcpy(&cli->sign_info.mac_key[0], user_session_key, 16);
+       memcpy(&cli->sign_info.mac_key[16],response.data, MIN(response.length, 40 - 16));
+       cli->sign_info.mac_key_len = MIN(response.length + 16, 40);
        cli->sign_info.use_smb_signing = True;
 
        /* These calls are INCONPATIBLE with SMB signing */
        cli->readbraw_supported = False;
-       cli->writebraw_supported = False;    
+       cli->writebraw_supported = False;
 
        /* Reset the sequence number in case we had a previous (aborted) attempt */
-       cli->sign_info.send_seq_num = 0;
+       cli->sign_info.send_seq_num = 2;
 }
 
 /***********************************************************
@@ -411,9 +470,47 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
        MD5Final(calc_md5_mac, &md5_ctx);
 
        memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+
 /*     cli->outbuf[smb_ss_field+2]=0; 
        Uncomment this to test if the remote server actually verifies signitures...*/
        cli->sign_info.send_seq_num++;
        cli->sign_info.reply_seq_num = cli->sign_info.send_seq_num;
        cli->sign_info.send_seq_num++;
 }
+
+/***********************************************************
+ SMB signing - check a MAC sent by server.
+************************************************************/
+
+BOOL cli_check_sign_mac(struct cli_state *cli)
+{
+       unsigned char calc_md5_mac[16];
+       unsigned char server_sent_mac[8];
+       struct MD5Context md5_ctx;
+
+       if (cli->sign_info.temp_smb_signing) {
+               return True;
+       }
+
+       if (!cli->sign_info.use_smb_signing) {
+               return True;
+       }
+
+       /*
+        * Firstly put the sequence number into the first 4 bytes.
+        * and zero out the next 4 bytes.
+        */
+
+       memcpy(server_sent_mac, &cli->inbuf[smb_ss_field], sizeof(server_sent_mac));
+
+       SIVAL(cli->inbuf, smb_ss_field, cli->sign_info.reply_seq_num);
+       SIVAL(cli->inbuf, smb_ss_field + 4, 0);
+
+       /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
+       MD5Init(&md5_ctx);
+       MD5Update(&md5_ctx, cli->sign_info.mac_key, cli->sign_info.mac_key_len);
+       MD5Update(&md5_ctx, cli->inbuf + 4, smb_len(cli->inbuf));
+       MD5Final(calc_md5_mac, &md5_ctx);
+
+       return (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
+}
index be4ed1c667f3a8b01ce2b27d4f01944ad23e344c..f6fc3a8d6c9cf006ab2adba91e4d94351efd55d9 100644 (file)
@@ -39,7 +39,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 {
        ADS_STRUCT *ads;
        ADS_STATUS status;
-       char *ccache;
 
        if (domain->private) {
                return (ADS_STRUCT *)domain->private;
index 1455f88156909ca420c9134ae020f3209a639fb7..daea4ab94f82b3488e1b5bddf7b195c889b1016d 100644 (file)
@@ -255,6 +255,10 @@ typedef struct
        BOOL bAllowTrustedDomains;
        BOOL bLanmanAuth;
        BOOL bNTLMAuth;
+       BOOL bUseSpnego;
+       BOOL bClientLanManAuth;
+       BOOL bClientNTLMv2Auth;
+       BOOL bClientUseSpnego;
        BOOL bDebugHiresTimestamp;
        BOOL bDebugPid;
        BOOL bDebugUid;
@@ -263,12 +267,12 @@ typedef struct
        BOOL bUnicode;
        BOOL bUseMmap;
        BOOL bHostnameLookups;
-       BOOL bUseSpnego;
        BOOL bUnixExtensions;
        BOOL bDisableNetbios;
        BOOL bKernelChangeNotify;
        int restrict_anonymous;
        int name_cache_timeout;
+       BOOL client_signing;
 }
 global;
 
index 1b711f7b432a7b6907cf1f5055a86eb65e432e1d..b0eb335986942e6fe2b3f5712e60baf1acca3c49 100644 (file)
@@ -264,14 +264,8 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        ctr.switch_value = 24;
        ctr.info.id24 = &p24;
 
-       /* I don't think this is quite the right place for this
-          calculation.  It should be moved somewhere where the credentials
-          are calculated. )-: */
-
-       mdfour(sess_key, cli->pwd.smb_nt_pwd, 16);
-
        CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, 
-                                           sess_key, &ctr),
+                                           cli->user_session_key, &ctr),
                      "error setting trust account password");
 
        /* Why do we have to try to (re-)set the ACB to be the same as what