r8896: Handle more complex case where field being changed doesn't appear
authorRafal Szczesniak <mimir@samba.org>
Mon, 1 Aug 2005 20:47:26 +0000 (20:47 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:30:16 +0000 (13:30 -0500)
alone in any of userinfo levels. What's needed is extra query step
to fill the userinfo structure and then modify a single field.
The other way to do it is userinfo level 21 with bitmap flags set,
but first all field flags need to be found.

rafal
(This used to be commit 59769977e8ebc54be7fa80f19638b634f52df515)

source4/libnet/composite.h
source4/libnet/userman.c

index 256590bc5b74166cbd28be2f536afd53197bb896..169b65f2150107e6cacd6271ebf36687209d3155 100644 (file)
@@ -62,9 +62,12 @@ struct libnet_rpc_userdel {
 #define USERMOD_FIELD_ACCOUNT_NAME    ( 0x00000001 )
 #define USERMOD_FIELD_FULL_NAME       ( 0x00000002 )
 #define USERMOD_FIELD_DESCRIPTION     ( 0x00000010 )
+#define USERMOD_FIELD_COMMENT         ( 0x00000020 )
 #define USERMOD_FIELD_LOGON_SCRIPT    ( 0x00000100 )
 #define USERMOD_FIELD_PROFILE_PATH    ( 0x00000200 )
 #define USERMOD_FIELD_ACCT_EXPIRY     ( 0x00004000 )
+#define USERMOD_FIELD_ALLOW_PASS_CHG  ( 0x00008000 )
+#define USERMOD_FIELD_ACCT_FLAGS      ( 0x00100000 )
 
 struct libnet_rpc_usermod {
        struct {
@@ -77,9 +80,11 @@ struct libnet_rpc_usermod {
                        const char *account_name;
                        const char *full_name;
                        const char *description;
+                       const char *comment;
                        const char *logon_script;
                        const char *profile_path;
                        struct timeval *acct_expiry;
+                       struct timeval *allow_password_change;
                } change;
        } in;
 };
index 6bb0ad493920e9bfa9a259ea47c72d0798cf27d9..f57b5c55f929023d1a793bca33fa8eb545e53743 100644 (file)
@@ -449,19 +449,20 @@ NTSTATUS libnet_rpc_userdel(struct dcerpc_pipe *pipe,
 
 static void usermod_handler(struct rpc_request*);
 
-enum usermod_stage { USERMOD_LOOKUP, USERMOD_OPEN, USERMOD_MODIFY };
+enum usermod_stage { USERMOD_LOOKUP, USERMOD_OPEN, USERMOD_QUERY, USERMOD_MODIFY };
 
 struct usermod_state {
-       enum usermod_stage        stage;
-       struct dcerpc_pipe        *pipe;
-       struct rpc_request        *req;
-       struct policy_handle      domain_handle;
-       struct policy_handle      user_handle;
-       struct usermod_change     change;
-       union  samr_UserInfo      info;
-       struct samr_LookupNames   lookupname;
-       struct samr_OpenUser      openuser;
-       struct samr_SetUserInfo   setuser;
+       enum usermod_stage         stage;
+       struct dcerpc_pipe         *pipe;
+       struct rpc_request         *req;
+       struct policy_handle       domain_handle;
+       struct policy_handle       user_handle;
+       struct usermod_change      change;
+       union  samr_UserInfo       info;
+       struct samr_LookupNames    lookupname;
+       struct samr_OpenUser       openuser;
+       struct samr_SetUserInfo    setuser;
+       struct samr_QueryUserInfo  queryuser;
 };
 
 
@@ -500,75 +501,120 @@ static NTSTATUS usermod_lookup(struct composite_context *c,
 }
 
 
-/**
- * Stage 2: Open user account
- */
-static NTSTATUS usermod_open(struct composite_context *c,
-                            struct usermod_state *s)
+static uint32_t usermod_setfields(struct usermod_state *s, uint16_t *level,
+                                 union samr_UserInfo *i)
 {
-       union samr_UserInfo *i = &s->info;
-       uint16_t level;
-
-       c->status = dcerpc_ndr_request_recv(s->req);
-       NT_STATUS_NOT_OK_RETURN(c->status);
-
-       s->setuser.in.user_handle  = &s->user_handle;
-
-       /* Prepare UserInfo level and data based on bitmask field */
        if (s->change.fields) {
                if (s->change.fields & USERMOD_FIELD_ACCOUNT_NAME) {
-                       level = 7;
+                       *level = 7;
                        i->info7.account_name.string = s->change.account_name;
 
                        s->change.fields ^= USERMOD_FIELD_ACCOUNT_NAME;
 
                } else if (s->change.fields & USERMOD_FIELD_FULL_NAME) {
-                       level = 8;
+                       *level = 8;
                        i->info8.full_name.string = s->change.full_name;
                        
                        s->change.fields ^= USERMOD_FIELD_FULL_NAME;
 
                } else if (s->change.fields & USERMOD_FIELD_DESCRIPTION) {
-                       level = 13;
+                       *level = 13;
                        i->info13.description.string = s->change.description;
                        
                        s->change.fields ^= USERMOD_FIELD_DESCRIPTION;
 
+               } else if (s->change.fields & USERMOD_FIELD_COMMENT) {
+                       *level = 2;
+
+                       if (s->stage == USERMOD_QUERY) {
+                               /* the user info is obtained, so now set the required field */
+                               i->info2.comment.string = s->change.comment;
+                               s->change.fields ^= USERMOD_FIELD_COMMENT;
+
+                       } else {
+                               /* we need to query the user info before setting one field in it */
+                               s->stage = USERMOD_QUERY;
+                               return s->change.fields;
+                       }
+
+               } else if (s->change.fields & USERMOD_FIELD_ALLOW_PASS_CHG) {
+                       *level = 3;
+                       
+                       if (s->stage == USERMOD_QUERY) {
+                               i->info3.allow_password_change = timeval_to_nttime(s->change.allow_password_change);
+                               s->change.fields ^= USERMOD_FIELD_ALLOW_PASS_CHG;
+
+                       } else {
+                               s->stage = USERMOD_QUERY;
+                       }
+
                } else if (s->change.fields & USERMOD_FIELD_LOGON_SCRIPT) {
-                       level = 11;
+                       *level = 11;
                        i->info11.logon_script.string = s->change.logon_script;
                        
                        s->change.fields ^= USERMOD_FIELD_LOGON_SCRIPT;
 
                } else if (s->change.fields & USERMOD_FIELD_PROFILE_PATH) {
-                       level = 12;
+                       *level = 12;
                        i->info12.profile_path.string = s->change.profile_path;
 
                        s->change.fields ^= USERMOD_FIELD_PROFILE_PATH;
 
                } else if (s->change.fields & USERMOD_FIELD_ACCT_EXPIRY) {
-                       level = 17;
+                       *level = 17;
                        i->info17.acct_expiry = timeval_to_nttime(s->change.acct_expiry);
 
                        s->change.fields ^= USERMOD_FIELD_ACCT_EXPIRY;
                }
        }
 
-       s->setuser.in.level  = level;
-       s->setuser.in.info   = i;
-
-       s->req = dcerpc_samr_SetUserInfo_send(s->pipe, c, &s->setuser);
-
-       s->req->async.callback = usermod_handler;
-       s->req->async.private  = c;
-
-       /* Get back here again unless all fields have been set */
+       /* We're going to be back here again soon unless all fields have been set */
        if (s->change.fields) {
                s->stage = USERMOD_OPEN;
        } else {
                s->stage = USERMOD_MODIFY;
        }
 
+       return s->change.fields;
+}
+
+
+/**
+ * Stage 2: Open user account
+ */
+static NTSTATUS usermod_open(struct composite_context *c,
+                            struct usermod_state *s)
+{
+       union samr_UserInfo *i = &s->info;
+       uint16_t level;
+
+       c->status = dcerpc_ndr_request_recv(s->req);
+       NT_STATUS_NOT_OK_RETURN(c->status);
+
+       if (s->stage == USERMOD_QUERY) {
+               s->info = *s->queryuser.out.info;
+       }
+
+       /* Prepare UserInfo level and data based on bitmask field */
+       s->change.fields = usermod_setfields(s, &level, i);
+
+       if (s->stage == USERMOD_QUERY) {
+               s->queryuser.in.user_handle = &s->user_handle;
+               s->queryuser.in.level       = level;
+
+               s->req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuser);
+
+       } else {
+               s->setuser.in.user_handle  = &s->user_handle;
+               s->setuser.in.level        = level;
+               s->setuser.in.info         = i;
+
+               s->req = dcerpc_samr_SetUserInfo_send(s->pipe, c, &s->setuser);
+       }
+
+       s->req->async.callback = usermod_handler;
+       s->req->async.private  = c;
+
        return NT_STATUS_OK;
 }
 
@@ -605,9 +651,12 @@ static void usermod_handler(struct rpc_request *req)
        case USERMOD_LOOKUP:
                c->status = usermod_lookup(c, s);
                break;
+
        case USERMOD_OPEN:
+       case USERMOD_QUERY:
                c->status = usermod_open(c, s);
                break;
+
        case USERMOD_MODIFY:
                c->status = usermod_modify(c, s);
                break;