SAM database "set user info".
authorLuke Leighton <lkcl@samba.org>
Thu, 25 Mar 1999 13:54:31 +0000 (13:54 +0000)
committerLuke Leighton <lkcl@samba.org>
Thu, 25 Mar 1999 13:54:31 +0000 (13:54 +0000)
----------------------------

- removed DOM_RID4

- removed SAMR_UNKNOWN_32

- added SAMR_SET_USERINFO (opcode 0x32)

- added level 0x1 to SAMR_QUERY_DOM_INFO (needed for create user)

- fixed pwdb_gethexpwd() it was failing on XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

- added mod_sam21pwd_entry()

- preparing to call mod_sam21pwd_entry()

- added "user session key" to user_struct.dc.  this is md4(nt#) and is
  needed to decode user's clear-text passwords in SAMR_SET_USERINFO.

- split code out in chgpasswd.c to decode 516 byte password buffers.

18 files changed:
source/include/proto.h
source/include/rpc_misc.h
source/include/rpc_samr.h
source/include/smb.h
source/lib/util_pwdb.c
source/passdb/ldap.c
source/passdb/sampassdb.c
source/passdb/smbpass.c
source/passdb/smbpassfile.c
source/rpc_parse/parse_misc.c
source/rpc_parse/parse_samr.c
source/rpc_server/srv_pipe.c
source/rpc_server/srv_pipe_hnd.c
source/rpc_server/srv_samr.c
source/smbd/chgpasswd.c
source/smbd/ipc.c
source/smbd/password.c
source/smbd/reply.c

index 83bea437fad1cc5270ae21da1eb7751c3666f448..8e8e7e292a9834f3b66f84afcc20741360b3b941 100644 (file)
@@ -492,7 +492,7 @@ void pwdb_set_can_change_time(char *p, int max_len, time_t t);
 void pwdb_set_must_change_time(char *p, int max_len, time_t t);
 void pwdb_set_last_set_time(char *p, int max_len, time_t t);
 void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl);
-BOOL pwdb_gethexpwd(const char *p, char *pwd);
+BOOL pwdb_gethexpwd(const char *p, char *pwd, uint32 *acct_ctrl);
 BOOL pwdb_initialise(BOOL is_server);
 
 /*The following definitions come from  lib/util_sid.c  */
@@ -1507,6 +1507,7 @@ BOOL initialise_sam_password_db(void);
 void *startsam21pwent(BOOL update);
 void endsam21pwent(void *vp);
 struct sam_passwd *getsam21pwent(void *vp);
+BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override);
 struct sam_passwd *iterate_getsam21pwntnam(const char *ntname);
 struct sam_passwd *iterate_getsam21pwrid(uint32 rid);
 struct sam_passwd *iterate_getsam21pwuid(uid_t uid);
@@ -1973,7 +1974,6 @@ void make_dom_rid2(DOM_RID2 *rid2, uint32 rid, uint8 type, uint32 idx);
 void smb_io_dom_rid2(char *desc,  DOM_RID2 *rid2, prs_struct *ps, int depth);
 void make_dom_rid3(DOM_RID3 *rid3, uint32 rid, uint8 type);
 void smb_io_dom_rid3(char *desc,  DOM_RID3 *rid3, prs_struct *ps, int depth);
-void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid);
 void make_log_info(DOM_LOG_INFO *log,
                const char *logon_srv, const char *acct_name,
                uint16 sec_chan, const char *comp_name);
@@ -2264,6 +2264,8 @@ void make_unk_info7(SAM_UNK_INFO_7 *u_7);
 void sam_io_unk_info7(char *desc, SAM_UNK_INFO_7 *u_7, prs_struct *ps, int depth);
 void make_unk_info2(SAM_UNK_INFO_2 *u_2, char *domain, char *server);
 void sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 *u_2, prs_struct *ps, int depth);
+void make_unk_info1(SAM_UNK_INFO_1 *u_1);
+void sam_io_unk_info1(char *desc, SAM_UNK_INFO_1 *u_1, prs_struct *ps, int depth);
 void make_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO *r_u, 
                                uint16 switch_value, SAM_UNK_CTR *ctr,
                                uint32 status);
@@ -2456,6 +2458,10 @@ void make_samr_q_create_user(SAMR_Q_CREATE_USER *q_u,
                                const char *name,
                                uint16 acb_info, uint32 unk_1);
 void samr_io_q_create_user(char *desc,  SAMR_Q_CREATE_USER *q_u, prs_struct *ps, int depth);
+void make_samr_r_create_user(SAMR_R_CREATE_USER *r_u,
+                               POLICY_HND *user_pol,
+                               uint32 unk_0, uint32 user_rid,
+                               uint32 status);
 void samr_io_r_create_user(char *desc,  SAMR_R_CREATE_USER *r_u, prs_struct *ps, int depth);
 void make_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
                                POLICY_HND *hnd, uint16 switch_value);
@@ -2470,6 +2476,36 @@ void make_sam_user_info11(SAM_USER_INFO_11 *usr,
                                uint32 rid_group,
                                uint16 acct_ctrl);
 void sam_io_user_info11(char *desc,  SAM_USER_INFO_11 *usr, prs_struct *ps, int depth);
+void make_sam_user_info23(SAM_USER_INFO_23 *usr,
+
+       NTTIME *logon_time, /* all zeros */
+       NTTIME *logoff_time, /* all zeros */
+       NTTIME *kickoff_time, /* all zeros */
+       NTTIME *pass_last_set_time, /* all zeros */
+       NTTIME *pass_can_change_time, /* all zeros */
+       NTTIME *pass_must_change_time, /* all zeros */
+
+       char *user_name, /* NULL */
+       char *full_name,
+       char *home_dir,
+       char *dir_drive,
+       char *logon_script,
+       char *profile_path,
+       char *description,
+       char *workstations,
+       char *unknown_str,
+       char *munged_dial,
+
+       uint32 user_rid, /* 0x0000 0000 */
+       uint32 group_rid,
+       uint16 acb_info, 
+
+       uint32 unknown_3,
+       uint16 logon_divs,
+       LOGON_HRS *hrs,
+       uint32 unknown_5,
+       char newpass[516],
+       uint32 unknown_6);
 void make_sam_user_info21(SAM_USER_INFO_21 *usr,
 
        NTTIME *logon_time,
@@ -2502,8 +2538,12 @@ void make_sam_user_info21(SAM_USER_INFO_21 *usr,
 void make_samr_r_query_userinfo(SAMR_R_QUERY_USERINFO *r_u,
                                uint16 switch_value, void *info, uint32 status);
 void samr_io_r_query_userinfo(char *desc,  SAMR_R_QUERY_USERINFO *r_u, prs_struct *ps, int depth);
-void samr_io_q_unknown_32(char *desc,  SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth);
-void samr_io_r_unknown_32(char *desc,  SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth);
+void make_samr_q_set_userinfo(SAMR_Q_SET_USERINFO *q_u,
+                               POLICY_HND *hnd,
+                               uint16 switch_value, void *info);
+void samr_io_q_set_userinfo(char *desc, SAMR_Q_SET_USERINFO *q_u, prs_struct *ps, int depth);
+void make_samr_r_set_userinfo(SAMR_R_SET_USERINFO *r_u, uint32 status);
+void samr_io_r_set_userinfo(char *desc,  SAMR_R_SET_USERINFO *r_u, prs_struct *ps, int depth);
 void make_samr_q_connect(SAMR_Q_CONNECT *q_u,
                                char *srv_name, uint32 unknown_0);
 void samr_io_q_connect(char *desc,  SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth);
@@ -2932,6 +2972,8 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2
 BOOL pass_oem_change(char *user,
                        uchar *lmdata, uchar *lmhash,
                        uchar *ntdata, uchar *nthash);
+BOOL decode_pw_buffer(const char buffer[516], char *new_passwd,
+                       int new_passwd_size, BOOL nt_pass_set);
 BOOL check_oem_password(char *user,
                        uchar *lmdata, uchar *lmhash,
                        uchar *ntdata, uchar *nthash,
@@ -3119,15 +3161,16 @@ BOOL set_challenge(unsigned char *challenge);
 user_struct *get_valid_user_struct(uint16 vuid);
 void invalidate_vuid(uint16 vuid);
 char *validated_username(uint16 vuid);
-uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest);
+uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]);
 void add_session_user(char *user);
 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8);
 BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
                      uchar lm_pass[24], uchar nt_pass[24]);
 BOOL pass_check_smb(char *user, char *domain,
                uchar *chal, uchar *lm_pwd, uchar *nt_pwd,
-               struct passwd *pwd);
-BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd);
+               struct passwd *pwd, uchar user_sess_key[16]);
+BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
+               uchar user_sess_key[16]);
 BOOL user_ok(char *user,int snum);
 BOOL authorise_login(int snum,char *user,char *password, int pwlen, 
                     BOOL *guest,BOOL *force,uint16 vuid);
index 1c5689dd877967135bcc1a2423740d4d529f4183..3e4d52a0380fc92ec8fdf61605cd7caad7a59e66 100644 (file)
@@ -212,15 +212,6 @@ typedef struct domrid3_info
 
 } DOM_RID3;
 
-/* DOM_RID4 - rid + user attributes */
-typedef struct domrid4_info
-{
-       uint32 unknown;      
-       uint16 attr;
-       uint32 rid;  /* user RID */
-
-} DOM_RID4;
-
 /* DOM_CLNT_SRV - client / server names */
 typedef struct clnt_srv_info
 {
index 44e1c6148417cce73739e6c2e4dfffeb9a5bb62d..92125f9f2c1d578748e950692400318cd1182c3a 100644 (file)
@@ -68,7 +68,7 @@ SamrRemoveMultipleMembersFromAlias
 x SamrSetInformationAlias
 SamrSetInformationDomain
 x SamrSetInformationGroup
-SamrSetInformationUser
+SamrSetInformationUser
 SamrSetMemberAttributesOfGroup
 SamrSetSecurityObject
 SamrShutdownSamServer
@@ -114,6 +114,7 @@ SamrTestPrivateFunctionsUser
 
 #define SAMR_OPEN_USER         0x22
 #define SAMR_CREATE_USER       0x32
+#define SAMR_SET_USERINFO      0x3A
 
 #define SAMR_QUERY_USERINFO    0x24
 #define SAMR_QUERY_USERGROUPS  0x27
@@ -122,7 +123,6 @@ SamrTestPrivateFunctionsUser
 #define SAMR_UNKNOWN_2C        0x2c
 #define SAMR_QUERY_DISPINFO3   0x30 /* Alias for SAMR_QUERY_DISPINFO
                                       with info level 3 */
-#define SAMR_UNKNOWN_32        0x32
 #define SAMR_QUERY_DISPINFO4   0x33 /* Alias for SAMR_QUERY_DISPINFO
                                       with info level 4 */
 #define SAMR_UNKNOWN_34        0x34
@@ -140,6 +140,67 @@ typedef struct logon_hours_info
 
 } LOGON_HRS;
 
+/* SAM_USER_INFO_23 */
+typedef struct sam_user_info_23
+{
+       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 */
+
+       uint16 acb_info; /* account info (ACB_xxxx bit-mask) */
+       /* uint8 pad[2] */
+
+       uint32 unknown_3; /* 0x09f8 27fa */
+
+       uint16 logon_divs; /* 0x0000 00a8 which is 168 which is num hrs in a week */
+       /* uint8 pad[2] */
+       uint32 ptr_logon_hrs; /* pointer to logon hours */
+
+       uint8 padding1[8];
+
+       uint32 unknown_5;     /* 0x0001 0000 */
+
+       uint8 pass[516];
+
+       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 number */
+
+       uint32 unknown_6; /* 0x0000 04ec */
+       uint32 padding4;
+
+       LOGON_HRS logon_hrs;
+
+} SAM_USER_INFO_23;
+
+
 /* SAM_USER_INFO_21 */
 typedef struct sam_user_info_21
 {
@@ -375,7 +436,7 @@ SAMR_Q_QUERY_DOMAIN_INFO - probably a query on domain group info.
 typedef struct q_samr_query_domain_info
 {
        POLICY_HND domain_pol;   /* policy handle */
-       uint16 switch_value;     /* 0x0002 */
+       uint16 switch_value;     /* 0x0002, 0x0001 */
 
 } SAMR_Q_QUERY_DOMAIN_INFO;
 
@@ -394,7 +455,7 @@ typedef struct sam_unknown_info_7_info
 
 } SAM_UNK_INFO_7;
 
-typedef struct sam_unknown_info_2_info
+typedef struct sam_unknown_info_2_inf
 {
        uint32 unknown_0; /* 0x0000 0000 */
        uint32 unknown_1; /* 0x8000 0000 */
@@ -425,11 +486,21 @@ typedef struct sam_unknown_info_2_info
 
 } SAM_UNK_INFO_2;
 
+typedef struct sam_unknown_info_1_inf
+{
+       uint8 padding[12]; /* 12 bytes zeros */
+       uint32 unknown_1; /* 0x8000 0000 */
+       uint32 unknown_2; /* 0x0000 0000 */
+       uint32 unknown_3; /* 0x0000 0000 */
+
+} SAM_UNK_INFO_1;
+
 
 typedef struct sam_unknown_ctr_info
 {
        union
        {
+               SAM_UNK_INFO_1 inf1;
                SAM_UNK_INFO_2 inf2;
                SAM_UNK_INFO_6 inf6;
                SAM_UNK_INFO_7 inf7;
@@ -1035,6 +1106,30 @@ typedef struct r_samr_query_usergroup_info
 } SAMR_R_QUERY_USERGROUPS;
 
 
+/* SAMR_Q_SET_USERINFO - set sam info */
+typedef struct q_samr_set_user_info
+{
+       POLICY_HND pol;          /* policy handle associated with user */
+       uint16 switch_value;      /* 0x0017 */
+       uint16 switch_value2;      /* 0x0017 */
+
+       union
+       {
+               SAM_USER_INFO_23 *id23; /* auth-level 0x17 */
+               void* id; /* to make typecasting easy */
+
+       } info;
+
+} SAMR_Q_SET_USERINFO;
+
+/* SAMR_R_SET_USERINFO - set sam info */
+typedef struct r_samr_set_user_info
+{
+       uint32 status;         /* return status */
+
+} SAMR_R_SET_USERINFO;
+
+
 /* SAMR_Q_QUERY_USERINFO - probably a get sam info */
 typedef struct q_samr_query_user_info
 {
@@ -1230,33 +1325,6 @@ typedef struct r_samr_create_user_info
 
 
 
-/* SAMR_Q_UNKNOWN_32 - probably a "create SAM entry" */
-typedef struct q_samr_unknown_32_info
-{
-       POLICY_HND pol;             /* policy handle */
-
-       UNIHDR  hdr_mach_acct;       /* unicode machine account name header */
-       UNISTR2 uni_mach_acct;       /* unicode machine account name */
-
-       uint32 acct_ctrl;            /* 32 bit ACB_XXXX */
-       uint16 unknown_1;            /* 16 bit unknown - 0x00B0 */
-       uint16 unknown_2;            /* 16 bit unknown - 0xe005 */
-
-} SAMR_Q_UNKNOWN_32;
-
-
-/* SAMR_R_UNKNOWN_32 - probably a "create SAM entry" */
-typedef struct r_samr_unknown_32_info
-{
-    POLICY_HND pol;       /* policy handle */
-
-       /* rid4.unknown - fail: 0030 success: 0x03ff */
-       DOM_RID4 rid4;         /* rid and attributes */
-
-       uint32 status;         /* return status - fail: 0xC000 0099: user exists */
-
-} SAMR_R_UNKNOWN_32;
-
 /* SAMR_Q_QUERY_GROUPMEM - query group members */
 typedef struct q_samr_query_groupmem_info
 {
index 65746d219ca186f27023ff1f8b40e2bd6f63cd08..edd021f4fbb8e0ef520b02d55abc55f56e91cba2 100644 (file)
@@ -613,6 +613,7 @@ typedef struct connection_struct
        char *connectpath;
        char *origpath;
        char *user; /* name of user who *opened* this connection */
+
        uid_t uid; /* uid of user who *opened* this connection */
        gid_t gid; /* gid of user who *opened* this connection */
 
@@ -709,6 +710,7 @@ struct dcinfo
 
   uchar  sess_key[8]; /* Session key */
   uchar  md4pw[16];   /* md4(machine password) */
+  uchar  user_sess_key[16]; /* user session key (md4 nt#) */
 };
 
 typedef struct
index a678e4b0635e873143179cfdfb077e2196aa8e37..b3b638b5e63ad859f71079b961391bba49e7c249 100644 (file)
@@ -415,9 +415,26 @@ void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl)
  Routine to get the 32 hex characters and turn them
  into a 16 byte array.
 **************************************************************/
-BOOL pwdb_gethexpwd(const char *p, char *pwd)
+BOOL pwdb_gethexpwd(const char *p, char *pwd, uint32 *acct_ctrl)
 {
-       return strhex_to_str(pwd, 32, p) == 16;
+       if (strnequal(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32))
+       {
+               if (acct_ctrl != NULL)
+               {
+                       *acct_ctrl |= ACB_PWNOTREQ;
+               }
+               pwd[0] = 0;
+               return True;
+       }
+       else if (strnequal(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32))
+       {
+               pwd[0] = 0;
+               return True;
+       }
+       else
+       {
+               return strhex_to_str(pwd, 32, p) == 16;
+       }
 }
 
 
index fad67cb79f6348e2615fd2051ff9253ed3ff4e3b..7bdbdab320e6cc0e1bc4bc934b19b1f0ff178d21 100644 (file)
@@ -187,7 +187,7 @@ struct smb_passwd *ldap_getpw(void)
                smbpw.acct_ctrl = ACB_NORMAL;
 
        if(ldap_get_attribute("lmPassword", temp)) {
-               pwdb_gethexpwd(temp, smblmpwd);
+               pwdb_gethexpwd(temp, smblmpwd, NULL);
                smbpw.smb_passwd = smblmpwd;
        } else {
                smbpw.smb_passwd = NULL;
@@ -195,7 +195,7 @@ struct smb_passwd *ldap_getpw(void)
        }
 
        if(ldap_get_attribute("ntPassword", temp)) {
-               pwdb_gethexpwd(temp, smbntpwd);
+               pwdb_gethexpwd(temp, smbntpwd, NULL);
                smbpw.smb_nt_passwd = smbntpwd;
        } else {
                smbpw.smb_nt_passwd = NULL;
index e80d157ec05547111eb1fad39f21ad86d8eb2c0d..7c824cb7ca1c651a674fcbe83bdc78e29881cf7f 100644 (file)
@@ -123,6 +123,20 @@ struct sam_passwd *getsam21pwent(void *vp)
        return pwdb_sam_map_names(pwdb_ops->getsam21pwent(vp));
 }
 
+/************************************************************************
+ Routine to search the smb passwd file for an entry matching the username.
+ and then modify its password entry. We can't use the startsampwent()/
+ getsampwent()/endsampwent() interfaces here as we depend on looking
+ in the actual file to decide how much room we have to write data.
+ override = False, normal
+ override = True, override XXXXXXXX'd out password or NO PASS
+************************************************************************/
+
+BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override)
+{
+       return pwdb_ops->mod_sam21pwd_entry(pwdb_sam_map_names(pwd), override);
+}
+
 /************************************************************************
  Utility function to search sam passwd by name.  use this if your database
  does not have search facilities.
index 2985af1ff80ad0d928a832b40a997038be4c0805..464cec015c504844f18ddff4a077f2c74b0aebb7 100644 (file)
@@ -158,7 +158,7 @@ struct smb_passwd *getsmbfilepwent(void *vp)
                }
                else
                {
-                       if (!pwdb_gethexpwd(p, (char *)smbpwd))
+                       if (!pwdb_gethexpwd(p, (char *)smbpwd, NULL))
                        {
                                DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
                                continue;
@@ -178,7 +178,7 @@ struct smb_passwd *getsmbfilepwent(void *vp)
                {
                        if (*p != '*' && *p != 'X')
                        {
-                               if(pwdb_gethexpwd(p,(char *)smbntpwd))
+                               if(pwdb_gethexpwd(p,(char *)smbntpwd, NULL))
                                {
                                        pw_buf.smb_nt_passwd = smbntpwd;
                                }
index b4f8e2b869ab26f6e090b658dbd6778bc5315783..0165d76488e2099d43f6a5b1ab3956826a25e711 100644 (file)
@@ -167,7 +167,7 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t
    * Get the hex password.
    */
 
-  if (!pwdb_gethexpwd((char *)linebuf, (char *)ret_pwd) || linebuf[32] != ':' || 
+  if (!pwdb_gethexpwd((char *)linebuf, (char *)ret_pwd, NULL) || linebuf[32] != ':' || 
          strncmp(&linebuf[33], "TLC-", 4)) {
     DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n"));
 #ifdef DEBUG_PASSWORD
index 323d5f65e5c6e69c4b1c6db112c95067a75f43f5..64cbdef7169158b08a882ae6b1542388a0f778fe 100644 (file)
@@ -702,16 +702,6 @@ void smb_io_dom_rid3(char *desc,  DOM_RID3 *rid3, prs_struct *ps, int depth)
        prs_uint32("unk     ", ps, depth, &(rid3->unk     ));
 }
 
-/*******************************************************************
-creates a DOM_RID4 structure.
-********************************************************************/
-void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid)
-{
-       rid4->unknown = unknown;
-       rid4->attr    = attr;
-       rid4->rid     = rid;
-}
-
 /*******************************************************************
 makes a DOM_CLNT_SRV structure.
 ********************************************************************/
index a2fc77981ec313108e5b3bd02952838b5a7df7f4..f724535a8cfd5d50ababe3a30422dc5636d61cb5 100644 (file)
@@ -449,6 +449,38 @@ void sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 *u_2, prs_struct *ps, int depth
 
 }
 
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_unk_info1(SAM_UNK_INFO_1 *u_1)
+{
+       if (u_1 == NULL) return;
+
+       memset(u_1->padding, 0, sizeof(u_1->padding)); /* 12 bytes zeros */
+       u_1->unknown_1 = 0x80000000;
+       u_1->unknown_2 = 0x00000000;
+       u_1->unknown_3 = 0x00000000;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void sam_io_unk_info1(char *desc, SAM_UNK_INFO_1 *u_1, prs_struct *ps, int depth)
+{
+       if (u_1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_unk_info1");
+       depth++;
+
+       prs_uint8s(False, "padding", ps, depth, u_1->padding, sizeof(u_1->padding)); /* 12 bytes zeros */
+
+       prs_uint32("unknown_1", ps, depth, &u_1->unknown_1); /* 0x8000 0000 */
+       prs_uint32("unknown_2", ps, depth, &u_1->unknown_2); /* 0x0000 0000 */
+       prs_uint32("unknown_3", ps, depth, &u_1->unknown_3); /* 0x0000 0000 */
+
+       prs_align(ps);
+}
+
 /*******************************************************************
 makes a SAMR_R_QUERY_DOMAIN_INFO structure.
 ********************************************************************/
@@ -507,6 +539,11 @@ void samr_io_r_query_dom_info(char *desc, SAMR_R_QUERY_DOMAIN_INFO *r_u, prs_str
                                sam_io_unk_info2("unk_inf2", &r_u->ctr->info.inf2, ps, depth);
                                break;
                        }
+                       case 0x01:
+                       {
+                               sam_io_unk_info1("unk_inf1", &r_u->ctr->info.inf1, ps, depth);
+                               break;
+                       }
                        default:
                        {
                                DEBUG(3,("samr_io_r_query_dom_info: unknown switch level 0x%x\n",
@@ -3847,6 +3884,25 @@ void samr_io_q_create_user(char *desc,  SAMR_Q_CREATE_USER *q_u, prs_struct *ps,
        prs_align(ps);
 }
 
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_samr_r_create_user(SAMR_R_CREATE_USER *r_u,
+                               POLICY_HND *user_pol,
+                               uint32 unk_0, uint32 user_rid,
+                               uint32 status)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("samr_make_samr_r_create_user\n"));
+
+       memcpy(&r_u->user_pol, user_pol, sizeof(r_u->user_pol));
+       
+       r_u->unknown_0 = unk_0;
+       r_u->user_rid = user_rid;
+       r_u->status = status;
+}
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
@@ -4049,6 +4105,186 @@ void sam_io_user_info11(char *desc,  SAM_USER_INFO_11 *usr, prs_struct *ps, int
        prs_uint8s (False, "padding_9", ps, depth, usr->padding_9, sizeof(usr->padding_9));
 }
 
+/*************************************************************************
+ make_sam_user_info23
+
+ unknown_3 = 0x09f8 27fa
+ unknown_5 = 0x0001 0000
+ unknown_6 = 0x0000 04ec 
+
+ *************************************************************************/
+void make_sam_user_info23(SAM_USER_INFO_23 *usr,
+
+       NTTIME *logon_time, /* all zeros */
+       NTTIME *logoff_time, /* all zeros */
+       NTTIME *kickoff_time, /* all zeros */
+       NTTIME *pass_last_set_time, /* all zeros */
+       NTTIME *pass_can_change_time, /* all zeros */
+       NTTIME *pass_must_change_time, /* all zeros */
+
+       char *user_name, /* NULL */
+       char *full_name,
+       char *home_dir,
+       char *dir_drive,
+       char *logon_script,
+       char *profile_path,
+       char *description,
+       char *workstations,
+       char *unknown_str,
+       char *munged_dial,
+
+       uint32 user_rid, /* 0x0000 0000 */
+       uint32 group_rid,
+       uint16 acb_info, 
+
+       uint32 unknown_3,
+       uint16 logon_divs,
+       LOGON_HRS *hrs,
+       uint32 unknown_5,
+       char newpass[516],
+       uint32 unknown_6)
+{
+       int len_user_name    = user_name    != NULL ? strlen(user_name   ) : 0;
+       int len_full_name    = full_name    != NULL ? strlen(full_name   ) : 0;
+       int len_home_dir     = home_dir     != NULL ? strlen(home_dir    ) : 0;
+       int len_dir_drive    = dir_drive    != NULL ? strlen(dir_drive   ) : 0;
+       int len_logon_script = logon_script != NULL ? strlen(logon_script) : 0;
+       int len_profile_path = profile_path != NULL ? strlen(profile_path) : 0;
+       int len_description  = description  != NULL ? strlen(description ) : 0;
+       int len_workstations = workstations != NULL ? strlen(workstations) : 0;
+       int len_unknown_str  = unknown_str  != NULL ? strlen(unknown_str ) : 0;
+       int len_munged_dial  = munged_dial  != NULL ? strlen(munged_dial ) : 0;
+
+       usr->logon_time            = *logon_time; /* all zeros */
+       usr->logoff_time           = *logoff_time; /* all zeros */
+       usr->kickoff_time          = *kickoff_time; /* all zeros */
+       usr->pass_last_set_time    = *pass_last_set_time; /* all zeros */
+       usr->pass_can_change_time  = *pass_can_change_time; /* all zeros */
+       usr->pass_must_change_time = *pass_must_change_time; /* all zeros */
+
+       make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   ); /* NULL */
+       make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   );
+       make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    );
+       make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   );
+       make_uni_hdr(&(usr->hdr_logon_script), len_logon_script);
+       make_uni_hdr(&(usr->hdr_profile_path), len_profile_path);
+       make_uni_hdr(&(usr->hdr_acct_desc   ), len_description );
+       make_uni_hdr(&(usr->hdr_workstations), len_workstations);
+       make_uni_hdr(&(usr->hdr_unknown_str ), len_unknown_str );
+       make_uni_hdr(&(usr->hdr_munged_dial ), len_munged_dial );
+
+       bzero(usr->nt_pwd, sizeof(usr->nt_pwd));
+       bzero(usr->lm_pwd, sizeof(usr->lm_pwd));
+
+       usr->user_rid  = user_rid; /* 0x0000 0000 */
+       usr->group_rid = group_rid;
+       usr->acb_info = acb_info;
+       usr->unknown_3 = unknown_3; /* 09f8 27fa */
+
+       usr->logon_divs = logon_divs; /* should be 168 (hours/week) */
+       usr->ptr_logon_hrs = hrs ? 1 : 0;
+
+       bzero(usr->padding1, sizeof(usr->padding1));
+
+       usr->unknown_5 = unknown_5; /* 0x0001 0000 */
+
+       memcpy(usr->pass, newpass, sizeof(usr->pass));
+
+       make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   ); /* NULL */
+       make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   );
+       make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    );
+       make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   );
+       make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script);
+       make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path);
+       make_unistr2(&(usr->uni_acct_desc ), description , len_description );
+       make_unistr2(&(usr->uni_workstations), workstations, len_workstations);
+       make_unistr2(&(usr->uni_unknown_str ), unknown_str , len_unknown_str );
+       make_unistr2(&(usr->uni_munged_dial ), munged_dial , len_munged_dial );
+
+       usr->unknown_6 = unknown_6; /* 0x0000 04ec */
+       usr->padding4 = 0;
+
+       if (hrs)
+       {
+               memcpy(&(usr->logon_hrs), hrs, sizeof(usr->logon_hrs));
+       }
+       else
+       {
+               memset(&(usr->logon_hrs), 0xff, sizeof(usr->logon_hrs));
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_user_info23(char *desc,  SAM_USER_INFO_23 *usr, prs_struct *ps, int depth)
+{
+       if (usr == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_user_info");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_time("logon_time           ", &(usr->logon_time)           , ps, depth);
+       smb_io_time("logoff_time          ", &(usr->logoff_time)          , ps, depth); 
+       smb_io_time("kickoff_time         ", &(usr->kickoff_time)         , ps, depth); 
+       smb_io_time("pass_last_set_time   ", &(usr->pass_last_set_time)   , ps, depth); 
+       smb_io_time("pass_can_change_time ", &(usr->pass_can_change_time) , ps, depth); 
+       smb_io_time("pass_must_change_time", &(usr->pass_must_change_time), ps, depth); 
+
+       smb_io_unihdr("hdr_user_name   ", &(usr->hdr_user_name)   , ps, depth); /* username unicode string header */
+       smb_io_unihdr("hdr_full_name   ", &(usr->hdr_full_name)   , ps, depth); /* user's full name unicode string header */
+       smb_io_unihdr("hdr_home_dir    ", &(usr->hdr_home_dir)    , ps, depth); /* home directory unicode string header */
+       smb_io_unihdr("hdr_dir_drive   ", &(usr->hdr_dir_drive)   , ps, depth); /* home directory drive */
+       smb_io_unihdr("hdr_logon_script", &(usr->hdr_logon_script), ps, depth); /* logon script unicode string header */
+       smb_io_unihdr("hdr_profile_path", &(usr->hdr_profile_path), ps, depth); /* profile path unicode string header */
+       smb_io_unihdr("hdr_acct_desc   ", &(usr->hdr_acct_desc  ) , ps, depth); /* account description */
+       smb_io_unihdr("hdr_workstations", &(usr->hdr_workstations), ps, depth); /* workstations user can log on from */
+       smb_io_unihdr("hdr_unknown_str ", &(usr->hdr_unknown_str ), ps, depth); /* unknown string */
+       smb_io_unihdr("hdr_munged_dial ", &(usr->hdr_munged_dial ), ps, depth); /* workstations user can log on from */
+
+       prs_uint8s (False, "lm_pwd        ", ps, depth, usr->lm_pwd   , sizeof(usr->lm_pwd   ));
+       prs_uint8s (False, "nt_pwd        ", ps, depth, usr->nt_pwd   , sizeof(usr->nt_pwd   ));
+
+       prs_uint32("user_rid      ", ps, depth, &(usr->user_rid     ));       /* User ID */
+       prs_uint32("group_rid     ", ps, depth, &(usr->group_rid    ));      /* Group ID */
+       prs_uint16("acb_info      ", ps, depth, &(usr->acb_info     ));      /* Group ID */
+       prs_align(ps);
+
+       prs_uint32("unknown_3     ", ps, depth, &(usr->unknown_3    ));
+       prs_uint16("logon_divs    ", ps, depth, &(usr->logon_divs   ));     /* logon divisions per week */
+       prs_align(ps);
+       prs_uint32("ptr_logon_hrs ", ps, depth, &(usr->ptr_logon_hrs));
+       prs_uint8s (False, "padding1      ", ps, depth, usr->padding1, sizeof(usr->padding1));
+       prs_uint32("unknown_5     ", ps, depth, &(usr->unknown_5    ));
+
+       prs_uint8s (False, "password      ", ps, depth, usr->pass, sizeof(usr->pass));
+
+       /* here begins pointed-to data */
+
+       smb_io_unistr2("uni_user_name   ", &(usr->uni_user_name)   , usr->hdr_user_name   .buffer, ps, depth); /* username unicode string */
+       smb_io_unistr2("uni_full_name   ", &(usr->uni_full_name)   , usr->hdr_full_name   .buffer, ps, depth); /* user's full name unicode string */
+       smb_io_unistr2("uni_home_dir    ", &(usr->uni_home_dir)    , usr->hdr_home_dir    .buffer, ps, depth); /* home directory unicode string */
+       smb_io_unistr2("uni_dir_drive   ", &(usr->uni_dir_drive)   , usr->hdr_dir_drive   .buffer, ps, depth); /* home directory drive unicode string */
+       smb_io_unistr2("uni_logon_script", &(usr->uni_logon_script), usr->hdr_logon_script.buffer, ps, depth); /* logon script unicode string */
+       smb_io_unistr2("uni_profile_path", &(usr->uni_profile_path), usr->hdr_profile_path.buffer, ps, depth); /* profile path unicode string */
+       smb_io_unistr2("uni_acct_desc   ", &(usr->uni_acct_desc   ), usr->hdr_acct_desc   .buffer, ps, depth); /* user description unicode string */
+       smb_io_unistr2("uni_workstations", &(usr->uni_workstations), usr->hdr_workstations.buffer, ps, depth); /* worksations user can log on from */
+       smb_io_unistr2("uni_unknown_str ", &(usr->uni_unknown_str ), usr->hdr_unknown_str .buffer, ps, depth); /* unknown string */
+       smb_io_unistr2("uni_munged_dial ", &(usr->uni_munged_dial ), usr->hdr_munged_dial .buffer, ps, depth); /* worksations user can log on from */
+
+       prs_uint32("unknown_6     ", ps, depth, &(usr->unknown_6  ));
+       prs_uint32("padding4      ", ps, depth, &(usr->padding4   ));
+
+       if (usr->ptr_logon_hrs)
+       {
+               sam_io_logon_hrs("logon_hrs", &(usr->logon_hrs)   , ps, depth);
+               prs_align(ps);
+       }
+}
+
+
 /*************************************************************************
  make_sam_user_info21
 
@@ -4353,14 +4589,47 @@ void samr_io_r_query_userinfo(char *desc,  SAMR_R_QUERY_USERINFO *r_u, prs_struc
        prs_uint32("status", ps, depth, &(r_u->status));
 }
 
+/*******************************************************************
+makes a SAMR_Q_SET_USERINFO structure.
+********************************************************************/
+void make_samr_q_set_userinfo(SAMR_Q_SET_USERINFO *q_u,
+                               POLICY_HND *hnd,
+                               uint16 switch_value, void *info)
+{
+       if (q_u == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_samr_q_set_userinfo\n"));
+
+       memcpy(&(q_u->pol), hnd, sizeof(q_u->pol));
+       q_u->switch_value  = switch_value;
+       q_u->switch_value2 = switch_value;
+
+       switch (switch_value)
+       {
+               case 0x17:
+               {
+                       q_u->info.id23 = (SAM_USER_INFO_23*)info;
+
+                       break;
+               }
+
+               default:
+               {
+                       DEBUG(4,("make_samr_q_set_userinfo: unsupported switch level\n"));
+                       break;
+               }
+       }
+}
+
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_q_unknown_32(char *desc,  SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth)
+void samr_io_q_set_userinfo(char *desc, SAMR_Q_SET_USERINFO *q_u, prs_struct *ps, int depth)
 {
        if (q_u == NULL) return;
 
-       prs_debug(ps, depth, desc, "samr_io_q_unknown_32");
+       prs_debug(ps, depth, desc, "samr_io_q_set_userinfo");
        depth++;
 
        prs_align(ps);
@@ -4368,35 +4637,66 @@ void samr_io_q_unknown_32(char *desc,  SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, i
        smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
        prs_align(ps);
 
-       smb_io_unihdr ("", &(q_u->hdr_mach_acct), ps, depth); 
-       smb_io_unistr2("", &(q_u->uni_mach_acct), q_u->hdr_mach_acct.buffer, ps, depth); 
+       prs_uint16("switch_value ", ps, depth, &(q_u->switch_value )); 
+       prs_uint16("switch_value2", ps, depth, &(q_u->switch_value2)); 
 
        prs_align(ps);
 
-       prs_uint32("acct_ctrl", ps, depth, &(q_u->acct_ctrl));
-       prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1));
-       prs_uint16("unknown_2", ps, depth, &(q_u->unknown_2));
+       switch (q_u->switch_value)
+       {
+               case 0:
+               {
+                       break;
+               }
+               case 23:
+               {
+                       q_u->info.id = Realloc(NULL, sizeof(*q_u->info.id23));
+                       if (q_u->info.id == NULL)
+                       {
+                               DEBUG(2,("samr_io_q_query_userinfo: info pointer not initialised\n"));
+                               return;
+                       }
+                       sam_io_user_info23("", q_u->info.id23, ps, depth);
+                       break;
+               }
+               default:
+               {
+                       DEBUG(2,("samr_io_q_query_userinfo: unknown switch level\n"));
+                       break;
+               }
+                       
+       }
+       prs_align(ps);
+}
+
+/*******************************************************************
+makes a SAMR_R_SET_USERINFO structure.
+********************************************************************/
+void make_samr_r_set_userinfo(SAMR_R_SET_USERINFO *r_u, uint32 status)
+                               
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_set_userinfo\n"));
+
+       r_u->status = status;         /* return status */
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_r_unknown_32(char *desc,  SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth)
+void samr_io_r_set_userinfo(char *desc,  SAMR_R_SET_USERINFO *r_u, prs_struct *ps, int depth)
 {
        if (r_u == NULL) return;
 
-       prs_debug(ps, depth, desc, "samr_io_r_unknown_32");
+       prs_debug(ps, depth, desc, "samr_io_r_set_userinfo");
        depth++;
 
        prs_align(ps);
 
-       smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); 
-       prs_align(ps);
-
        prs_uint32("status", ps, depth, &(r_u->status));
 }
 
-
 /*******************************************************************
 makes a SAMR_Q_CONNECT structure.
 ********************************************************************/
index ec5b547c86cef8488831902fb4e105ad5e21b2c4..54d26650e916ddd4b1020972a6b251df0ded0bbc 100644 (file)
@@ -211,8 +211,16 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p)
        uchar nt_owf[24];
        struct smb_passwd *smb_pass = NULL;
        
+       user_struct *vuser = get_valid_user_struct(p->vuid);
+
        DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n"));
 
+       if (vuser == NULL)
+       {
+               DEBUG(0,("get user struct %d failed\n", p->vuid));
+               return False;
+       }
+
        if (p->ntlmssp_resp.hdr_lm_resp.str_str_len == 0) return False;
        if (p->ntlmssp_resp.hdr_nt_resp.str_str_len == 0) return False;
        if (p->ntlmssp_resp.hdr_usr    .str_str_len == 0) return False;
@@ -256,7 +264,7 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p)
        become_root(True);
        p->ntlmssp_validated = pass_check_smb(p->user_name, p->domain,
                              (uchar*)p->ntlmssp_chal.challenge,
-                             lm_owf, nt_owf, NULL);
+                             lm_owf, nt_owf, NULL, vuser->dc.user_sess_key);
        smb_pass = getsmbpwnam(p->user_name);
        unbecome_root(True);
 
index 531fcf6add033d5d7253d1814be8b722a22b59b1..4361c0772ee9ca1b7d9ed4ba89f9f52f971cb196 100644 (file)
@@ -140,7 +140,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
        p->ntlmssp_auth      = False;
        
        fstrcpy(p->name, pipe_name);
-       
+
        DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
                 pipe_name, i, pipes_open));
        
index 2dd7801e818a62e8df239e330d7dd325b51bc80f..2437163f2b0c9b1a362794e7203950c0c3add7d9 100644 (file)
@@ -1943,6 +1943,27 @@ static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
 
 }
 
+/*******************************************************************
+ set_user_info_23
+ ********************************************************************/
+static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
+{
+       static struct sam_passwd *pwd;
+       fstring new_pw;
+       if (!decode_pw_buffer(id23->pass, new_pw, sizeof(new_pw), True))
+       {
+               return False;
+       }
+#ifdef DEBUG_PASSWORD
+       DEBUG(0,("New Password: %s\n", new_pw));
+#endif
+#if 0
+       return mod_sam21pwd_entry(&pwd, True);
+#else
+       return True;
+#endif
+}
+
 /*******************************************************************
  api_samr_query_userinfo
  ********************************************************************/
@@ -1954,6 +1975,87 @@ static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *
 }
 
 
+/*******************************************************************
+ samr_reply_set_userinfo
+ ********************************************************************/
+static void samr_reply_set_userinfo(SAMR_Q_SET_USERINFO *q_u,
+                               prs_struct *rdata, uchar user_sess_key[16])
+{
+       SAMR_R_SET_USERINFO r_u;
+
+       uint32 status = 0x0;
+       uint32 rid = 0x0;
+
+       DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
+
+       /* search for the handle */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* find the user's rid */
+       if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
+       {
+               status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       DEBUG(5,("samr_reply_set_userinfo: rid:0x%x\n", rid));
+
+       /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
+       if (status == 0x0)
+       {
+               switch (q_u->switch_value)
+               {
+                       case 23:
+                       {
+                               SAM_USER_INFO_23 *id23 = q_u->info.id23;
+                               SamOEMhash(id23->pass, user_sess_key, True);
+                               status = set_user_info_23(id23, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
+                               break;
+                       }
+
+                       default:
+                       {
+                               status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+
+                               break;
+                       }
+               }
+       }
+
+       make_samr_r_set_userinfo(&r_u, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_set_userinfo("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_set_userinfo
+ ********************************************************************/
+static void api_samr_set_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       user_struct *vuser = get_valid_user_struct(vuid);
+       SAMR_Q_SET_USERINFO q_u;
+       ZERO_STRUCT(q_u);
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("set user info: sess_key: "));
+       dump_data(100, vuser->dc.user_sess_key, 16);
+#endif
+       samr_io_q_set_userinfo("", &q_u, data, 0);
+       samr_reply_set_userinfo(&q_u, rdata, vuser->dc.user_sess_key);
+
+       if (q_u.info.id != NULL)
+       {
+               free(q_u.info.id);
+       }
+}
+
+
 /*******************************************************************
  samr_reply_query_usergroups
  ********************************************************************/
@@ -2310,6 +2412,13 @@ static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
 
                                break;
                        }
+                       case 0x01:
+                       {
+                               switch_value = 0x1;
+                               make_unk_info1(&ctr.info.inf1);
+
+                               break;
+                       }
                        default:
                        {
                                status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
@@ -2340,50 +2449,19 @@ static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *
 
 
 /*******************************************************************
- samr_reply_unknown_32
+ samr_reply_create_user
  ********************************************************************/
-static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
-                               prs_struct *rdata,
-                               int status)
-{
-       int i;
-       SAMR_R_UNKNOWN_32 r_u;
-
-       /* set up the SAMR unknown_32 response */
-       bzero(r_u.pol.data, POL_HND_SIZE);
-       if (status == 0)
-       {
-               for (i = 4; i < POL_HND_SIZE; i++)
-               {
-                       r_u.pol.data[i] = i+1;
-               }
-       }
-
-       make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
-       r_u.status    = status;
-
-       DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
-
-       /* store the response in the SMB stream */
-       samr_io_r_unknown_32("", &r_u, rdata, 0);
-
-       DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
-
-}
-
-/*******************************************************************
- api_samr_unknown_32
- ********************************************************************/
-static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
+static void samr_reply_create_user(SAMR_Q_CREATE_USER *q_u,
+                               prs_struct *rdata)
 {
-       uint32 status = 0;
        struct sam_passwd *sam_pass;
-       fstring mach_acct;
-
-       SAMR_Q_UNKNOWN_32 q_u;
+       fstring user_name;
 
-       /* grab the samr unknown 32 */
-       samr_io_q_unknown_32("", &q_u, data, 0);
+       SAMR_R_CREATE_USER r_u;
+       POLICY_HND pol;
+       uint32 status = 0x0;
+       uint32 user_rid = 0xffffffff;
+       BOOL pol_open = False;
 
        /* find the machine account: tell the caller if it exists.
           lkclXXXX i have *no* idea if this is a problem or not
@@ -2391,26 +2469,91 @@ static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdat
           reply if the account already exists...
         */
 
-       unistr2_to_ascii(mach_acct, &q_u.uni_mach_acct, sizeof(mach_acct)-1);
+       /* find the policy handle.  open a policy on it. */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
+       {
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
 
-       become_root(True);
-       sam_pass = getsam21pwntnam(mach_acct);
-       unbecome_root(True);
+       /* get a (unique) handle.  open a policy on it. */
+       if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(&pol)))
+       {
+               status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       unistr2_to_ascii(user_name, &q_u->uni_name, sizeof(user_name)-1);
+
+       sam_pass = getsam21pwntnam(user_name);
 
        if (sam_pass != NULL)
        {
-               /* machine account exists: say so */
+               /* account exists: say so */
                status = 0xC0000000 | NT_STATUS_USER_EXISTS;
        }
        else
        {
-               /* this could cause trouble... */
-               DEBUG(0,("trouble!\n"));
-               status = 0;
+               pstring err_str;
+               pstring msg_str;
+
+               if (!local_password_change(user_name, True,
+                         q_u->acb_info | ACB_DISABLED, 0xffff,
+                         NULL,
+                         err_str, sizeof(err_str),
+                         msg_str, sizeof(msg_str)))
+               {
+                       DEBUG(0,("%s\n", err_str));
+                       status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
+               }
+               else
+               {
+                       sam_pass = getsam21pwntnam(user_name);
+                       if (sam_pass == NULL)
+                       {
+                               /* account doesn't exist: say so */
+                               status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
+                       }
+                       else
+                       {
+                               user_rid = sam_pass->user_rid;
+                       }
+               }
+       }
+
+       /* associate the RID with the (unique) handle. */
+       if (status == 0x0 && !set_lsa_policy_samr_rid(&pol, user_rid))
+       {
+               /* oh, whoops.  don't know what error message to return, here */
+               status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (status != 0 && pol_open)
+       {
+               close_lsa_policy_hnd(&pol);
        }
 
+       DEBUG(5,("samr_create_user: %d\n", __LINE__));
+
+       make_samr_r_create_user(&r_u, &pol, 0x000703ff, user_rid, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_create_user("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_create_user: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_create_user
+ ********************************************************************/
+static void api_samr_create_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_CREATE_USER q_u;
+
+       /* grab the samr unknown 32 */
+       samr_io_q_create_user("", &q_u, data, 0);
+
        /* construct reply. */
-       samr_reply_unknown_32(&q_u, rdata, status);
+       samr_reply_create_user(&q_u, rdata);
 }
 
 
@@ -2709,6 +2852,7 @@ static struct api_struct api_samr_cmds [] =
        { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
        { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
        { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
+       { "SAMR_SET_USERINFO"     , SAMR_SET_USERINFO     , api_samr_set_userinfo     },
        { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info   },
        { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
        { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
@@ -2716,7 +2860,7 @@ static struct api_struct api_samr_cmds [] =
        { "SAMR_QUERY_DISPINFO4"  , SAMR_QUERY_DISPINFO4  , api_samr_query_dispinfo   },
        { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
        { "SAMR_QUERY_GROUPINFO"  , SAMR_QUERY_GROUPINFO  , api_samr_query_groupinfo  },
-       { "SAMR_0x32"             , SAMR_UNKNOWN_32       , api_samr_unknown_32       },
+       { "SAMR_CREATE_USER"      , SAMR_CREATE_USER      , api_samr_create_user      },
        { "SAMR_LOOKUP_RIDS"      , SAMR_LOOKUP_RIDS      , api_samr_lookup_rids      },
        { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
        { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
index 852d6aa6185a1ffc5d6970112fad9d57afb96cb5..c22f26868486a9129c000761fb30ddb9ec18b8e7 100644 (file)
@@ -603,6 +603,42 @@ BOOL pass_oem_change(char *user,
        return ret;
 }
 
+/***********************************************************
+ decode a password buffer
+************************************************************/
+BOOL decode_pw_buffer(const char buffer[516], char *new_passwd,
+                       int new_passwd_size, BOOL nt_pass_set)
+{
+       /* 
+        * The length of the new password is in the last 4 bytes of
+        * the data buffer.
+        */
+
+       uint32 new_pw_len = IVAL(buffer, 512);
+       if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1)
+       {
+               DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len));
+               return False;
+       }
+
+       if (nt_pass_set)
+       {
+               /*
+                * nt passwords are in unicode
+                */
+               int uni_pw_len = new_pw_len;
+               new_pw_len /= 2;
+               unibuf_to_ascii(new_passwd, &buffer[512-uni_pw_len], new_pw_len);
+       }
+       else
+       {
+               memcpy(new_passwd, &buffer[512-new_pw_len], new_pw_len);
+               new_passwd[new_pw_len] = '\0';
+       }
+
+       return True;
+}
+
 /***********************************************************
  Code to check the OEM hashed password.
 
@@ -619,7 +655,6 @@ BOOL check_oem_password(char *user,
        static uchar null_pw[16];
        static uchar null_ntpw[16];
        struct smb_passwd *smbpw = NULL;
-       int new_pw_len;
        uchar new_ntp16[16];
        uchar unenc_old_ntpw[16];
        uchar new_p16[16];
@@ -681,33 +716,11 @@ BOOL check_oem_password(char *user,
         */
        SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True);
 
-       /* 
-        * The length of the new password is in the last 4 bytes of
-        * the data buffer.
-        */
-
-       new_pw_len = IVAL(lmdata, 512);
-       if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1)
+       if (!decode_pw_buffer(lmdata, new_passwd, new_passwd_size, nt_pass_set))
        {
-               DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len));
                return False;
        }
 
-       if (nt_pass_set)
-       {
-               /*
-                * nt passwords are in unicode
-                */
-               int uni_pw_len = new_pw_len;
-               new_pw_len /= 2;
-               unibuf_to_ascii(new_passwd, &lmdata[512-uni_pw_len], new_pw_len);
-       }
-       else
-       {
-               memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len);
-               new_passwd[new_pw_len] = '\0';
-       }
-
        /*
         * To ensure we got the correct new password, hash it and
         * use it as a key to test the passed old password.
index a4d452b2a84cc4c61b36736ea61bb382deddc381..5001b16b352be4dbbcf1d0f730ef9ef8074a5ae2 100644 (file)
@@ -1680,7 +1680,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
    * Older versions of Windows seem to do this.
    */
 
-  if (password_ok(user, pass1,strlen(pass1),NULL) &&
+  if (password_ok(user, pass1,strlen(pass1),NULL, NULL) &&
       chgpasswd(user,pass1,pass2,False))
   {
     SSVAL(*rparam,0,NERR_Success);
index 68d75b933fc9739f82171165f0460c36fcdbac48..11fe69b103b995c33219996bc10713987d83c5dc 100644 (file)
@@ -156,7 +156,7 @@ register a uid/name pair as being valid and that a valid password
 has been given. vuid is biased by an offset. This allows us to
 tell random client vuid's (normally zero) from valid vuids.
 ****************************************************************************/
-uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest)
+uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16])
 {
   user_struct *vuser;
   struct passwd *pwfile; /* for getting real name from passwd file */
@@ -205,6 +205,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
   vuser->guest = guest;
   fstrcpy(vuser->name,unix_name);
   fstrcpy(vuser->requested_name,requested_name);
+  memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key));
 
   vuser->n_sids = 0;
   vuser->sids   = NULL;
@@ -412,7 +413,7 @@ return True if the password is correct, False otherwise
 
 BOOL pass_check_smb(char *user, char *domain,
                uchar *chal, uchar *lm_pwd, uchar *nt_pwd,
-               struct passwd *pwd)
+               struct passwd *pwd, uchar user_sess_key[16])
 {
        struct passwd *pass;
        struct smb_passwd *smb_pass;
@@ -467,6 +468,14 @@ BOOL pass_check_smb(char *user, char *domain,
 
        if (smb_password_ok(smb_pass, chal, lm_pwd, nt_pwd))
        {
+               if (user_sess_key != NULL)
+               {
+                       mdfour(user_sess_key, smb_pass->smb_nt_passwd, 16);
+#ifdef DEBUG_PASSWORD
+               DEBUG(100,("user session key: "));
+               dump_data(100, user_sess_key, 16);
+#endif
+               }
                return(True);
        }
        
@@ -479,7 +488,8 @@ check if a username/password pair is OK either via the system password
 database or the encrypted SMB password database
 return True if the password is correct, False otherwise
 ****************************************************************************/
-BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd)
+BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
+               uchar user_sess_key[16])
 {
        if (pwlen == 24 || (lp_encrypted_passwords() && (pwlen == 0) && lp_null_passwords()))
        {
@@ -493,7 +503,7 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd)
                }
 
                return pass_check_smb(user, global_myworkgroup,
-                                     challenge, (uchar *)password, (uchar *)password, pwd);
+                                     challenge, (uchar *)password, (uchar *)password, pwd, user_sess_key);
        } 
 
        return pass_check(user, password, pwlen, pwd, 
@@ -536,7 +546,8 @@ BOOL user_ok(char *user,int snum)
 /****************************************************************************
 validate a group username entry. Return the username or NULL
 ****************************************************************************/
-static char *validate_group(char *group,char *password,int pwlen,int snum)
+static char *validate_group(char *group,char *password,int pwlen,int snum,
+                               uchar user_sess_key[16])
 {
 #if defined(HAVE_NETGROUP) && defined(HAVE_GETNETGRENT) && defined(HAVE_SETNETGRENT) && defined(HAVE_ENDNETGRENT)
   {
@@ -545,7 +556,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum)
     while (getnetgrent(&host, &user, &domain)) {
       if (user) {
        if (user_ok(user, snum) && 
-           password_ok(user,password,pwlen,NULL)) {
+           password_ok(user,password,pwlen,NULL, user_sess_key)) {
          endnetgrent();
          return(user);
        }
@@ -567,7 +578,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum)
            static fstring name;
            fstrcpy(name,*member);
            if (user_ok(name,snum) &&
-               password_ok(name,password,pwlen,NULL))
+               password_ok(name,password,pwlen,NULL, user_sess_key))
              return(&name[0]);
            member++;
          }
@@ -580,7 +591,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum)
          while (pwd = getpwent ()) {
            if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
              /* This Entry have PASSWORD and same GID then check pwd */
-             if (password_ok(NULL, password, pwlen, pwd)) {
+             if (password_ok(NULL, password, pwlen, pwd, user_sess_key)) {
                fstrcpy(tm, pwd->pw_name);
                endpwent ();
                return tm;
@@ -633,14 +644,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
 
       /* check the given username and password */
       if (!ok && (*user) && user_ok(user,snum)) {
-       ok = password_ok(user,password, pwlen, NULL);
+       ok = password_ok(user,password, pwlen, NULL, vuser->dc.user_sess_key);
        if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
       }
 
       /* check for a previously registered guest username */
       if (!ok && (vuser != 0) && vuser->guest) {         
        if (user_ok(vuser->name,snum) &&
-           password_ok(vuser->name, password, pwlen, NULL)) {
+           password_ok(vuser->name, password, pwlen, NULL, vuser->dc.user_sess_key)) {
          fstrcpy(user, vuser->name);
          vuser->guest = False;
          DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
@@ -664,7 +675,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
         fstrcpy(user2,auser);
         if (!user_ok(user2,snum)) continue;
                  
-        if (password_ok(user2,password, pwlen, NULL)) {
+        if (password_ok(user2,password, pwlen, NULL, vuser->dc.user_sess_key)) {
           ok = True;
           fstrcpy(user,user2);
           DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
@@ -703,7 +714,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
          {
            if (*auser == '@')
              {
-               auser = validate_group(auser+1,password,pwlen,snum);
+               auser = validate_group(auser+1,password,pwlen,snum, vuser->dc.user_sess_key);
                if (auser)
                  {
                    ok = True;
@@ -716,7 +727,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
                fstring user2;
                fstrcpy(user2,auser);
                if (user_ok(user2,snum) && 
-                   password_ok(user2,password,pwlen,NULL))
+                   password_ok(user2,password,pwlen,NULL, vuser->dc.user_sess_key))
                  {
                    ok = True;
                    fstrcpy(user,user2);
index 694cf3cdd52e5baf7c656f266e817e759fcbd69c..57742003ff6e876cfc98e7e9ea7810f0fb32caf1 100644 (file)
@@ -511,6 +511,7 @@ reply to a session setup command
 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   uint16 sess_vuid;
+  uchar user_sess_key[16];
   int gid;
   int uid;
   int   smb_bufsize;    
@@ -706,13 +707,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
 
     if(smb_ntpasslen)
     {
-      if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
+      if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
         DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
       else
         valid_nt_password = True;
     } 
 
-    if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
+    if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
     {
       if (lp_security() >= SEC_USER) 
       {
@@ -791,7 +792,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
 
   /* register the name and uid as being validated, so further connections
      to a uid can get through without a password, on the same VC */
-  sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
+  sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
  
   SSVAL(outbuf,smb_uid,sess_vuid);
   SSVAL(inbuf,smb_uid,sess_vuid);