summaryrefslogtreecommitdiff
path: root/source4/libnet
diff options
context:
space:
mode:
authorRafal Szczesniak <mimir@samba.org>2005-08-01 20:47:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:30:16 -0500
commitaff62e9ee2f15d92e5331afe9ff942e449a25d8e (patch)
tree8d8f0ab5187236c9afb29dcb02f61653d3ec3ea0 /source4/libnet
parent67de5725bc28129fa942c7d014c9722d0e906dea (diff)
downloadsamba-aff62e9ee2f15d92e5331afe9ff942e449a25d8e.tar.gz
samba-aff62e9ee2f15d92e5331afe9ff942e449a25d8e.tar.bz2
samba-aff62e9ee2f15d92e5331afe9ff942e449a25d8e.zip
r8896: 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 (This used to be commit 59769977e8ebc54be7fa80f19638b634f52df515)
Diffstat (limited to 'source4/libnet')
-rw-r--r--source4/libnet/composite.h5
-rw-r--r--source4/libnet/userman.c129
2 files changed, 94 insertions, 40 deletions
diff --git a/source4/libnet/composite.h b/source4/libnet/composite.h
index 256590bc5b..169b65f215 100644
--- a/source4/libnet/composite.h
+++ b/source4/libnet/composite.h
@@ -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;
};
diff --git a/source4/libnet/userman.c b/source4/libnet/userman.c
index 6bb0ad4939..f57b5c55f9 100644
--- a/source4/libnet/userman.c
+++ b/source4/libnet/userman.c
@@ -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;