Fixed W2K SP2 joining a Samba PDC hosted domain.
authorJeremy Allison <jra@samba.org>
Wed, 20 Jun 2001 19:55:59 +0000 (19:55 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 20 Jun 2001 19:55:59 +0000 (19:55 +0000)
Jermey.

source/include/rpc_samr.h
source/libsmb/smbdes.c
source/libsmb/smbencrypt.c
source/rpc_parse/parse_net.c
source/rpc_parse/parse_samr.c
source/rpc_server/srv_netlog_nt.c
source/rpc_server/srv_samr_nt.c
source/smbd/chgpasswd.c

index d996170200cdac4a95595a0b7087fa88c99a37a1..cfe856b07fe6f5dc73b3b5c2a482b7d9ac7e6182 100644 (file)
@@ -219,6 +219,58 @@ typedef struct sam_user_info_24
        uint8 pass[516];
 } SAM_USER_INFO_24;
 
+/*
+ * NB. This structure is *definately* incorrect. It's my best guess
+ * currently for W2K SP2. The password field is encrypted in a different
+ * way than normal... And there are definately other problems. JRA.
+ */
+
+/* SAM_USER_INFO_25 */
+typedef struct sam_user_info_25
+{
+       /* TIMES MAY NOT IN RIGHT ORDER!!!! */
+       NTTIME logon_time;            /* logon time */
+       NTTIME logoff_time;           /* logoff time */
+       NTTIME kickoff_time;          /* kickoff time */
+       NTTIME pass_last_set_time;    /* password last set time */
+       NTTIME pass_can_change_time;  /* password can change time */
+       NTTIME pass_must_change_time; /* password must change time */
+
+       UNIHDR hdr_user_name;    /* NULL - user name unicode string header */
+       UNIHDR hdr_full_name;    /* user's full name unicode string header */
+       UNIHDR hdr_home_dir;     /* home directory unicode string header */
+       UNIHDR hdr_dir_drive;    /* home drive unicode string header */
+       UNIHDR hdr_logon_script; /* logon script unicode string header */
+       UNIHDR hdr_profile_path; /* profile path unicode string header */
+       UNIHDR hdr_acct_desc  ;  /* user description */
+       UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
+       UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+       UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
+
+       uint8 lm_pwd[16];    /* lm user passwords */
+       uint8 nt_pwd[16];    /* nt user passwords */
+
+       uint32 user_rid;      /* Primary User ID */
+       uint32 group_rid;     /* Primary Group ID */
+
+       uint32 acb_info; /* account info (ACB_xxxx bit-mask) */
+
+       uint32 unknown_6[6];
+
+       uint8 pass[532];
+
+       UNISTR2 uni_user_name;    /* NULL - username unicode string */
+       UNISTR2 uni_full_name;    /* user's full name unicode string */
+       UNISTR2 uni_home_dir;     /* home directory unicode string */
+       UNISTR2 uni_dir_drive;    /* home directory drive unicode string */
+       UNISTR2 uni_logon_script; /* logon script unicode string */
+       UNISTR2 uni_profile_path; /* profile path unicode string */
+       UNISTR2 uni_acct_desc  ;  /* user description unicode string */
+       UNISTR2 uni_workstations; /* login from workstations unicode string */
+       UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+       UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
+} SAM_USER_INFO_25;
+
 
 /* SAM_USER_INFO_21 */
 typedef struct sam_user_info_21
@@ -1140,6 +1192,7 @@ typedef struct sam_userinfo_ctr_info
                SAM_USER_INFO_21 *id21; /* auth-level 21 */
                SAM_USER_INFO_23 *id23; /* auth-level 0x17 */
                SAM_USER_INFO_24 *id24; /* auth-level 0x18 */
+               SAM_USER_INFO_25 *id25; /* auth-level 0x19 */
                void* id; /* to make typecasting easy */
 
        } info;
index d0e1c6e85fb00d0c91c0af57f5f1d74dc018f04e..7e8a9a5b89e11bbd8e27a21118f6fc953579a206 100644 (file)
@@ -381,7 +381,7 @@ void SamOEMhash( unsigned char *data, unsigned char *key, int val)
      s_box[ind] = s_box[j];
      s_box[j] = tc;
   }
-  for( ind = 0; ind < (val ? 516 : 16); ind++)
+  for( ind = 0; ind < val; ind++)
   {
     unsigned char tc;
     unsigned char t;
index 68af1b4941bf3f0ab5f9bad9ae4b0b0b062590ab..b9827333d8b99b009e618baddcc6b938b49e5656 100644 (file)
@@ -223,7 +223,7 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
        DEBUG(100,("make_oem_passwd_hash\n"));
        dump_data(100, data, 516);
 #endif
-       SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
+       SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
 
        return True;
 }
index 85de667b009678d42b8e234f596909eee67e91b2..c0d9544ba8b139e98b517a3662a99d89b092a736 100644 (file)
@@ -883,9 +883,9 @@ void init_id_info1(NET_ID_INFO_1 *id, char *domain_name,
                memcpy(key, sess_key, 8);
 
                memcpy(lm_owf, lm_cypher, 16);
-               SamOEMhash(lm_owf, key, False);
+               SamOEMhash(lm_owf, key, 16);
                memcpy(nt_owf, nt_cypher, 16);
-               SamOEMhash(nt_owf, key, False);
+               SamOEMhash(nt_owf, key, 16);
 
 #ifdef DEBUG_PASSWORD
                DEBUG(100,("encrypt of lm owf password:"));
index 6e94b62d40e201dd31d58f5983441266f0736f89..395931edd9d616ea6f36a227718532841e8a04b2 100644 (file)
@@ -5340,6 +5340,126 @@ static BOOL sam_io_user_info23(char *desc, SAM_USER_INFO_23 * usr,
        return True;
 }
 
+/*******************************************************************
+ reads or writes a structure.
+ NB. This structure is *definately* incorrect. It's my best guess
+ currently for W2K SP2. The password field is encrypted in a different
+ way than normal... And there are definately other problems. JRA.
+********************************************************************/
+
+static BOOL sam_io_user_info25(char *desc, SAM_USER_INFO_25 * usr, prs_struct *ps, int depth)
+{
+       if (usr == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "sam_io_user_info23");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_time("logon_time           ", &usr->logon_time, ps, depth))
+               return False;
+       if(!smb_io_time("logoff_time          ", &usr->logoff_time, ps, depth))
+               return False;
+       if(!smb_io_time("kickoff_time         ", &usr->kickoff_time, ps, depth))
+               return False;
+       if(!smb_io_time("pass_last_set_time   ", &usr->pass_last_set_time, ps, depth))
+               return False;
+       if(!smb_io_time("pass_can_change_time ", &usr->pass_can_change_time, ps, depth))
+               return False;
+       if(!smb_io_time("pass_must_change_time", &usr->pass_must_change_time, ps, depth))
+               return False;
+
+       if(!smb_io_unihdr("hdr_user_name   ", &usr->hdr_user_name, ps, depth))  /* username unicode string header */
+               return False;
+       if(!smb_io_unihdr("hdr_full_name   ", &usr->hdr_full_name, ps, depth))  /* user's full name unicode string header */
+               return False;
+       if(!smb_io_unihdr("hdr_home_dir    ", &usr->hdr_home_dir, ps, depth))   /* home directory unicode string header */
+               return False;
+       if(!smb_io_unihdr("hdr_dir_drive   ", &usr->hdr_dir_drive, ps, depth))  /* home directory drive */
+               return False;
+       if(!smb_io_unihdr("hdr_logon_script", &usr->hdr_logon_script, ps, depth))       /* logon script unicode string header */
+               return False;
+       if(!smb_io_unihdr("hdr_profile_path", &usr->hdr_profile_path, ps, depth))       /* profile path unicode string header */
+               return False;
+       if(!smb_io_unihdr("hdr_acct_desc   ", &usr->hdr_acct_desc, ps, depth))  /* account desc */
+               return False;
+       if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
+               return False;
+       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+               return False;
+       if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
+               return False;
+
+       if(!prs_uint8s(False, "lm_pwd        ", ps, depth, usr->lm_pwd, sizeof(usr->lm_pwd)))
+               return False;
+       if(!prs_uint8s(False, "nt_pwd        ", ps, depth, usr->nt_pwd, sizeof(usr->nt_pwd)))
+               return False;
+
+       if(!prs_uint32("user_rid      ", ps, depth, &usr->user_rid))    /* User ID */
+               return False;
+       if(!prs_uint32("group_rid     ", ps, depth, &usr->group_rid))   /* Group ID */
+               return False;
+       if(!prs_uint32("acb_info      ", ps, depth, &usr->acb_info))
+               return False;
+
+       if(!prs_uint32s(False, "unknown_6      ", ps, depth, usr->unknown_6, 6))
+               return False;
+
+       if(!prs_uint8s(False, "password      ", ps, depth, usr->pass, sizeof(usr->pass)))
+               return False;
+
+       /* here begins pointed-to data */
+
+       if(!smb_io_unistr2("uni_user_name   ", &usr->uni_user_name, usr->hdr_user_name.buffer, ps, depth))      /* username unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_full_name   ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth))      /* user's full name unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_home_dir    ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth))        /* home directory unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_dir_drive   ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth))      /* home directory drive unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth))        /* logon script unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth))        /* profile path unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_acct_desc   ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth))      /* user desc unicode string */
+               return False;
+
+       if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
+               return False;
+
+       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+               return False;
+
+       if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
+               return False;
+
+#if 0 /* JRA - unknown... */
+       /* ok, this is only guess-work (as usual) */
+       if (usr->ptr_logon_hrs) {
+               if(!prs_uint32("unknown_6     ", ps, depth, &usr->unknown_6))
+                       return False;
+               if(!prs_uint32("padding4      ", ps, depth, &usr->padding4))
+                       return False;
+               if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
+                       return False;
+       } else if (UNMARSHALLING(ps)) {
+               usr->unknown_6 = 0;
+               usr->padding4 = 0;
+       }
+#endif
+
+       return True;
+}
+
 
 /*************************************************************************
  init_sam_user_info21W
@@ -5740,12 +5860,12 @@ void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, uchar * sess_key,
 
        switch (switch_value) {
        case 0x18:
-               SamOEMhash(ctr->info.id24->pass, sess_key, 1);
+               SamOEMhash(ctr->info.id24->pass, sess_key, 516);
                dump_data(100, (char *)sess_key, 16);
                dump_data(100, (char *)ctr->info.id24->pass, 516);
                break;
        case 0x17:
-               SamOEMhash(ctr->info.id23->pass, sess_key, 1);
+               SamOEMhash(ctr->info.id23->pass, sess_key, 516);
                dump_data(100, (char *)sess_key, 16);
                dump_data(100, (char *)ctr->info.id23->pass, 516);
                break;
@@ -5845,6 +5965,16 @@ static BOOL samr_io_userinfo_ctr(char *desc, SAM_USERINFO_CTR **ppctr,
                }
                ret = sam_io_user_info24("", ctr->info.id24, ps,  depth);
                break;
+       case 25:
+               if (UNMARSHALLING(ps))
+                       ctr->info.id25 = (SAM_USER_INFO_25 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_25));
+
+               if (ctr->info.id25 == NULL) {
+                       DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
+                       return False;
+               }
+               ret = sam_io_user_info25("", ctr->info.id25, ps, depth);
+               break;
        default:
                DEBUG(2, ("samr_io_userinfo_ctr: unknown switch level 0x%x\n", ctr->switch_value));
                ret = False;
@@ -5999,8 +6129,8 @@ void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
 
        switch (switch_value) {
        case 0x12:
-               SamOEMhash(ctr->info.id12->lm_pwd, sess_key, 0);
-               SamOEMhash(ctr->info.id12->nt_pwd, sess_key, 0);
+               SamOEMhash(ctr->info.id12->lm_pwd, sess_key, 16);
+               SamOEMhash(ctr->info.id12->nt_pwd, sess_key, 16);
                dump_data(100, (char *)sess_key, 16);
                dump_data(100, (char *)ctr->info.id12->lm_pwd, 16);
                dump_data(100, (char *)ctr->info.id12->nt_pwd, 16);
index eb026a1f98930143e55c985dd5b5a68fcacc1a38..bbda4060f291a21bd4fe8178bfb71b8bcdae2673 100644 (file)
@@ -470,8 +470,8 @@ static uint32 net_login_interactive(NET_ID_INFO_1 *id1, SAM_ACCOUNT *sampass, pi
        dump_data(100, nt_pwd, 16);
 #endif
 
-       SamOEMhash((uchar *)lm_pwd, key, False);
-       SamOEMhash((uchar *)nt_pwd, key, False);
+       SamOEMhash((uchar *)lm_pwd, key, 16);
+       SamOEMhash((uchar *)nt_pwd, key, 16);
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100,("decrypt of lm owf password:"));
index 0a82c90a1d8504cda67be5f16e9ca45023beaa30..502774e986ed84876f06e57c31c0e79bbcda204a 100644 (file)
@@ -2259,10 +2259,10 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
 }
 
 /*******************************************************************
- set_user_info_24
+ set_user_info_pw
  ********************************************************************/
 
-static BOOL set_user_info_24(SAM_USER_INFO_24 *id24, uint32 rid)
+static BOOL set_user_info_pw(char *pass, uint32 rid)
 {
        SAM_ACCOUNT *pwd = NULL;
        uchar nt_hash[16];
@@ -2282,7 +2282,7 @@ static BOOL set_user_info_24(SAM_USER_INFO_24 *id24, uint32 rid)
 
        memset(buf, 0, sizeof(buf));
  
-       if (!decode_pw_buffer((char*)id24->pass, buf, 256, &len, nt_hash, lm_hash)) {
+       if (!decode_pw_buffer(pass, buf, 256, &len, nt_hash, lm_hash)) {
                pdb_free_sam(pwd);
                return False;
        }
@@ -2306,7 +2306,7 @@ static BOOL set_user_info_24(SAM_USER_INFO_24 *id24, uint32 rid)
  
        memset(buf, 0, sizeof(buf));
  
-       DEBUG(0,("set_user_info_24: pdb_update_sam_account()\n"));
+       DEBUG(5,("set_user_info_pw: pdb_update_sam_account()\n"));
  
        /* update the SAMBA password */
        if(!pdb_update_sam_account(pwd, True)) {
@@ -2390,13 +2390,39 @@ uint32 _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_
                        break;
 
                case 24:
-                       SamOEMhash(ctr->info.id24->pass, sess_key, 1);
-                       if (!set_user_info_24(ctr->info.id24, rid))
+                       SamOEMhash(ctr->info.id24->pass, sess_key, 516);
+
+                       dump_data(100, (char *)ctr->info.id24->pass, 516);
+
+                       if (!set_user_info_pw(ctr->info.id24->pass, rid))
                                return NT_STATUS_ACCESS_DENIED;
                        break;
 
+               case 25:
+#if 0
+                       /*
+                        * Currently we don't really know how to unmarshall
+                        * the level 25 struct, and the password encryption
+                        * is different. This is a placeholder for when we
+                        * do understand it. In the meantime just return INVALID
+                        * info level and W2K SP2 drops down to level 23... JRA.
+                        */
+
+                       SamOEMhash(ctr->info.id25->pass, sess_key, 532);
+
+                       dump_data(100, (char *)ctr->info.id25->pass, 532);
+
+                       if (!set_user_info_pw(ctr->info.id25->pass, rid))
+                               return NT_STATUS_ACCESS_DENIED;
+                       break;
+#endif
+                       return NT_STATUS_INVALID_INFO_CLASS;
+
                case 23:
-                       SamOEMhash(ctr->info.id23->pass, sess_key, 1);
+                       SamOEMhash(ctr->info.id23->pass, sess_key, 516);
+
+                       dump_data(100, (char *)ctr->info.id23->pass, 516);
+
                        if (!set_user_info_23(ctr->info.id23, rid))
                                return NT_STATUS_ACCESS_DENIED;
                        break;
index cf1fca405af1248c3a599fd8339538a35aac9ec6..c6f6eca0bae676715f61e86ed0f78134099a2c1b 100644 (file)
@@ -776,7 +776,7 @@ BOOL check_oem_password(char *user,
        /* 
         * Call the hash function to get the new password.
         */
-       SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, True);
+       SamOEMhash((uchar *) lmdata, (uchar *)lanman_pw, 516);
 
        /* 
         * The length of the new password is in the last 4 bytes of