summaryrefslogtreecommitdiff
path: root/source4/libnet
diff options
context:
space:
mode:
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;