Author: mimir
Date: 2005-08-01 20:47:26 +0000 (Mon, 01 Aug 2005)
New Revision: 8896

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=8896

Log:
Handle more complex case where field being changed doesn't appear
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


Modified:
   branches/SAMBA_4_0/source/libnet/composite.h
   branches/SAMBA_4_0/source/libnet/userman.c


Changeset:
Modified: branches/SAMBA_4_0/source/libnet/composite.h
===================================================================
--- branches/SAMBA_4_0/source/libnet/composite.h        2005-08-01 20:41:48 UTC 
(rev 8895)
+++ branches/SAMBA_4_0/source/libnet/composite.h        2005-08-01 20:47:26 UTC 
(rev 8896)
@@ -62,9 +62,12 @@
 #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 @@
                        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;
 };

Modified: branches/SAMBA_4_0/source/libnet/userman.c
===================================================================
--- branches/SAMBA_4_0/source/libnet/userman.c  2005-08-01 20:41:48 UTC (rev 
8895)
+++ branches/SAMBA_4_0/source/libnet/userman.c  2005-08-01 20:47:26 UTC (rev 
8896)
@@ -449,19 +449,20 @@
 
 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 @@
 }
 
 
-/**
- * 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 @@
        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;

Reply via email to