#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
+#include "libcli/composite/monitor.h"
#include "librpc/gen_ndr/ndr_samr.h"
#include "libnet/composite.h"
{
struct composite_context *c = req->async.private;
struct useradd_state *s = talloc_get_type(c->private, struct useradd_state);
+ struct monitor_msg msg;
switch (s->stage) {
case USERADD_CREATE:
c->status = useradd_create(c, s);
+ msg.type = rpc_create_user;
+ msg.data.rpc_create_user.rid = *s->createuser.out.rid;
break;
}
c->state = SMBCLI_REQUEST_ERROR;
}
+ if (c->monitor_fn) {
+ c->monitor_fn(&msg);
+ }
+
if (c->state >= SMBCLI_REQUEST_DONE &&
c->async.fn) {
c->async.fn(c);
* @param io arguments and results of the call
*/
-struct composite_context *rpc_composite_useradd_send(struct dcerpc_pipe *p,
- struct rpc_composite_useradd *io)
+struct composite_context *libnet_rpc_useradd_send(struct dcerpc_pipe *p,
+ struct libnet_rpc_useradd *io,
+ void (*monitor)(struct monitor_msg*))
{
struct composite_context *c;
struct useradd_state *s;
- struct dom_sid *sid;
c = talloc_zero(p, struct composite_context);
if (c == NULL) goto failure;
s->domain_handle = io->in.domain_handle;
s->pipe = p;
- c->state = SMBCLI_REQUEST_SEND;
- c->private = s;
- c->event_ctx = dcerpc_event_context(p);
+ c->state = SMBCLI_REQUEST_SEND;
+ c->private = s;
+ c->event_ctx = dcerpc_event_context(p);
+ c->monitor_fn = monitor;
/* preparing parameters to send rpc request */
s->createuser.in.domain_handle = &io->in.domain_handle;
- s->createuser.in.account_name = talloc_zero(c, struct samr_String);
+ s->createuser.in.account_name = talloc_zero(c, struct lsa_String);
s->createuser.in.account_name->string = talloc_strdup(c, io->in.username);
s->createuser.out.user_handle = &s->user_handle;
s->createuser.out.rid = &s->user_rid;
* @return nt status code of execution
*/
-NTSTATUS rpc_composite_useradd_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
- struct rpc_composite_useradd *io)
+NTSTATUS libnet_rpc_useradd_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
+ struct libnet_rpc_useradd *io)
{
NTSTATUS status;
struct useradd_state *s;
* @return nt status code of execution
*/
-NTSTATUS rpc_composite_useradd(struct dcerpc_pipe *pipe,
+NTSTATUS libnet_rpc_useradd(struct dcerpc_pipe *pipe,
TALLOC_CTX *mem_ctx,
- struct rpc_composite_useradd *io)
+ struct libnet_rpc_useradd *io)
{
- struct composite_context *c = rpc_composite_useradd_send(pipe, io);
- return rpc_composite_useradd_recv(c, mem_ctx, io);
+ struct composite_context *c = libnet_rpc_useradd_send(pipe, io, NULL);
+ return libnet_rpc_useradd_recv(c, mem_ctx, io);
}
s->stage = USERDEL_OPEN;
return NT_STATUS_OK;
-failure:
- talloc_free(c);
- return status;
}
static NTSTATUS userdel_open(struct composite_context *c,
struct userdel_state *s)
{
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-
c->status = dcerpc_ndr_request_recv(s->req);
NT_STATUS_NOT_OK_RETURN(c->status);
static NTSTATUS userdel_delete(struct composite_context *c,
struct userdel_state *s)
{
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-
c->status = dcerpc_ndr_request_recv(s->req);
NT_STATUS_NOT_OK_RETURN(c->status);
{
struct composite_context *c = req->async.private;
struct userdel_state *s = talloc_get_type(c->private, struct userdel_state);
+ struct monitor_msg msg;
switch (s->stage) {
case USERDEL_LOOKUP:
c->state = SMBCLI_REQUEST_ERROR;
}
+ if (c->monitor_fn) {
+ c->monitor_fn(&msg);
+ }
+
if (c->state >= SMBCLI_REQUEST_DONE &&
c->async.fn) {
c->async.fn(c);
* @param io arguments and results of the call
*/
-struct composite_context *rpc_composite_userdel_send(struct dcerpc_pipe *p,
- struct rpc_composite_userdel *io)
+struct composite_context *libnet_rpc_userdel_send(struct dcerpc_pipe *p,
+ struct libnet_rpc_userdel *io)
{
struct composite_context *c;
struct userdel_state *s;
/* preparing parameters to send rpc request */
s->lookupname.in.domain_handle = &io->in.domain_handle;
s->lookupname.in.num_names = 1;
- s->lookupname.in.names = talloc_zero(s, struct samr_String);
+ s->lookupname.in.names = talloc_zero(s, struct lsa_String);
s->lookupname.in.names->string = io->in.username;
/* send the request */
* @return nt status code of execution
*/
-NTSTATUS rpc_composite_userdel_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
- struct rpc_composite_userdel *io)
+NTSTATUS libnet_rpc_userdel_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
+ struct libnet_rpc_userdel *io)
{
NTSTATUS status;
struct userdel_state *s;
}
-NTSTATUS rpc_composite_userdel(struct dcerpc_pipe *pipe,
- TALLOC_CTX *mem_ctx,
- struct rpc_composite_userdel *io)
+/**
+ * Synchronous version of userdel call
+ *
+ * @param pipe dce/rpc call pipe
+ * @param mem_ctx memory context for the call
+ * @param io arguments and results of the call
+ * @return nt status code of execution
+ */
+
+NTSTATUS libnet_rpc_userdel(struct dcerpc_pipe *pipe,
+ TALLOC_CTX *mem_ctx,
+ struct libnet_rpc_userdel *io)
+{
+ struct composite_context *c = libnet_rpc_userdel_send(pipe, io);
+ return libnet_rpc_userdel_recv(c, mem_ctx, io);
+}
+
+
+static void usermod_handler(struct rpc_request*);
+
+enum usermod_stage { USERMOD_LOOKUP, USERMOD_OPEN, 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;
+};
+
+
+static NTSTATUS usermod_lookup(struct composite_context *c,
+ struct usermod_state *s)
+{
+ NTSTATUS status;
+
+ c->status = dcerpc_ndr_request_recv(s->req);
+ NT_STATUS_NOT_OK_RETURN(c->status);
+
+ if (!s->lookupname.out.rids.count) {
+ /* TODO: no such user */
+ status = NT_STATUS_NO_SUCH_USER;
+
+ } else if (!s->lookupname.out.rids.count > 1) {
+ /* TODO: ambiguous username */
+ status = NT_STATUS_INVALID_ACCOUNT_NAME;
+ }
+
+ s->openuser.in.domain_handle = &s->domain_handle;
+ s->openuser.in.rid = s->lookupname.out.rids.ids[0];
+ s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ s->openuser.out.user_handle = &s->user_handle;
+
+ s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser);
+
+ s->req->async.callback = usermod_handler;
+ s->req->async.private = c;
+ s->stage = USERMOD_OPEN;
+
+ return NT_STATUS_OK;
+}
+
+
+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);
+
+ 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;
+ i->info7.account_name.length = 2*strlen_m(s->change.account_name);
+ i->info7.account_name.size = 2*strlen_m(s->change.account_name);
+ 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;
+ i->info8.full_name.length = 2*strlen_m(s->change.full_name);
+ i->info8.full_name.size = 2*strlen_m(s->change.full_name);
+ i->info8.full_name.string = s->change.full_name;
+
+ s->change.fields ^= USERMOD_FIELD_FULL_NAME;
+ }
+ }
+
+ 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 */
+ if (s->change.fields) {
+ s->stage = USERMOD_OPEN;
+ } else {
+ s->stage = USERMOD_MODIFY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS usermod_modify(struct composite_context *c,
+ struct usermod_state *s)
+{
+ c->status = dcerpc_ndr_request_recv(s->req);
+ NT_STATUS_NOT_OK_RETURN(c->status);
+
+ c->state = SMBCLI_REQUEST_DONE;
+
+ return NT_STATUS_OK;
+}
+
+
+static void usermod_handler(struct rpc_request *req)
+{
+ struct composite_context *c = req->async.private;
+ struct usermod_state *s = talloc_get_type(c->private, struct usermod_state);
+ struct monitor_msg msg;
+
+ switch (s->stage) {
+ case USERMOD_LOOKUP:
+ c->status = usermod_lookup(c, s);
+ break;
+ case USERMOD_OPEN:
+ c->status = usermod_open(c, s);
+ break;
+ case USERMOD_MODIFY:
+ c->status = usermod_modify(c, s);
+ break;
+ }
+
+ if (!NT_STATUS_IS_OK(c->status)) {
+ c->state = SMBCLI_REQUEST_ERROR;
+ }
+
+ if (c->monitor_fn) {
+ c->monitor_fn(&msg);
+ }
+
+ if (c->state >= SMBCLI_REQUEST_DONE &&
+ c->async.fn) {
+ c->async.fn(c);
+ }
+}
+
+
+struct composite_context *libnet_rpc_usermod_send(struct dcerpc_pipe *p,
+ struct libnet_rpc_usermod *io)
+{
+ struct composite_context *c;
+ struct usermod_state *s;
+
+ c = talloc_zero(p, struct composite_context);
+ if (c == NULL) goto failure;
+
+ s = talloc_zero(c, struct usermod_state);
+ if (s == NULL) goto failure;
+
+ c->state = SMBCLI_REQUEST_SEND;
+ c->private = s;
+ c->event_ctx = dcerpc_event_context(p);
+
+ s->pipe = p;
+ s->domain_handle = io->in.domain_handle;
+ s->change = io->in.change;
+
+ s->lookupname.in.domain_handle = &io->in.domain_handle;
+ s->lookupname.in.num_names = 1;
+ s->lookupname.in.names = talloc_zero(s, struct lsa_String);
+ s->lookupname.in.names->string = io->in.username;
+
+ s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname);
+
+ s->req->async.callback = usermod_handler;
+ s->req->async.private = c;
+ s->stage = USERMOD_LOOKUP;
+
+ return c;
+
+failure:
+ talloc_free(c);
+ return NULL;
+}
+
+
+NTSTATUS libnet_rpc_usermod_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
+ struct libnet_rpc_usermod *io)
+{
+ NTSTATUS status;
+ struct usermod_state *s;
+
+ status = composite_wait(c);
+
+ talloc_free(c);
+ return status;
+}
+
+
+NTSTATUS libnet_rpc_usermod(struct dcerpc_pipe *pipe,
+ TALLOC_CTX *mem_ctx,
+ struct libnet_rpc_usermod *io)
{
- struct composite_context *c = rpc_composite_userdel_send(pipe, io);
- return rpc_composite_userdel_recv(c, mem_ctx, io);
+ struct composite_context *c = libnet_rpc_usermod_send(pipe, io);
+ return libnet_rpc_usermod_recv(c, mem_ctx, io);
}