2 Unix SMB/CIFS implementation.
4 Copyright (C) Rafal Szczesniak <mimir@samba.org> 2005
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "libnet/libnet.h"
24 #include "libcli/composite/composite.h"
25 #include "auth/credentials/credentials.h"
26 #include "librpc/ndr/libndr.h"
27 #include "librpc/gen_ndr/samr.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
32 * Verify, before actually doing anything with user accounts, whether
33 * required domain is already opened and thus ready for operation.
34 * If it is not, or if the opened domain is not the one requested, open
35 * the requested domain.
37 static struct composite_context
* domain_opened(struct libnet_context
*ctx
,
38 const char *domain_name
,
39 struct composite_context
*parent_ctx
,
40 struct libnet_DomainOpen
*domain_open
,
41 void (*continue_fn
)(struct composite_context
*),
42 void (*monitor
)(struct monitor_msg
*))
44 struct composite_context
*domopen_req
;
46 if (domain_name
== NULL
) {
48 * Try to guess the domain name from credentials,
49 * if it's not been explicitly specified.
52 if (policy_handle_empty(&ctx
->samr
.handle
)) {
53 domain_open
->in
.domain_name
= cli_credentials_get_domain(ctx
->cred
);
54 domain_open
->in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
57 composite_error(parent_ctx
, NT_STATUS_INVALID_PARAMETER
);
63 * The domain name has been specified, so check whether the same
64 * domain is already opened. If it is - just return NULL. Start
65 * opening a new domain otherwise.
68 if (policy_handle_empty(&ctx
->samr
.handle
) ||
69 !strequal(domain_name
, ctx
->samr
.name
)) {
70 domain_open
->in
.domain_name
= domain_name
;
71 domain_open
->in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
74 /* domain has already been opened and it's the same domain
80 /* send request to open the domain */
81 domopen_req
= libnet_DomainOpen_send(ctx
, domain_open
, monitor
);
82 if (composite_nomem(domopen_req
, parent_ctx
)) return parent_ctx
;
84 composite_continue(parent_ctx
, domopen_req
, continue_fn
, parent_ctx
);
89 struct create_user_state
{
90 struct libnet_CreateUser r
;
91 struct libnet_DomainOpen domain_open
;
92 struct libnet_rpc_useradd user_add
;
93 struct libnet_context
*ctx
;
95 /* information about the progress */
96 void (*monitor_fn
)(struct monitor_msg
*);
100 static void continue_rpc_useradd(struct composite_context
*ctx
);
101 static void continue_domain_open_create(struct composite_context
*ctx
);
105 * Sends request to create user account
107 * @param ctx initialised libnet context
108 * @param mem_ctx memory context of this call
109 * @param r pointer to a structure containing arguments and results of this call
110 * @param monitor function pointer for receiving monitor messages
111 * @return compostite context of this request
113 struct composite_context
* libnet_CreateUser_send(struct libnet_context
*ctx
,
115 struct libnet_CreateUser
*r
,
116 void (*monitor
)(struct monitor_msg
*))
118 struct composite_context
*c
;
119 struct create_user_state
*s
;
120 struct composite_context
*create_req
;
121 struct composite_context
*prereq_ctx
;
123 /* composite context allocation and setup */
124 c
= talloc_zero(mem_ctx
, struct composite_context
);
125 if (c
== NULL
) return NULL
;
127 s
= talloc_zero(c
, struct create_user_state
);
128 if (composite_nomem(s
, c
)) return c
;
130 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
132 c
->event_ctx
= ctx
->event_ctx
;
134 /* store arguments in the state structure */
137 ZERO_STRUCT(s
->r
.out
);
139 /* prerequisite: make sure the domain is opened */
140 prereq_ctx
= domain_opened(ctx
, s
->r
.in
.domain_name
, c
, &s
->domain_open
,
141 continue_domain_open_create
, monitor
);
142 if (prereq_ctx
) return prereq_ctx
;
144 /* prepare arguments for useradd call */
145 s
->user_add
.in
.username
= r
->in
.user_name
;
146 s
->user_add
.in
.domain_handle
= ctx
->samr
.handle
;
148 /* send the request */
149 create_req
= libnet_rpc_useradd_send(ctx
->samr
.pipe
, &s
->user_add
, monitor
);
150 if (composite_nomem(create_req
, c
)) return c
;
152 /* set the next stage */
153 composite_continue(c
, create_req
, continue_rpc_useradd
, c
);
159 * Stage 0.5 (optional): receive result of domain open request
160 * and send useradd request
162 static void continue_domain_open_create(struct composite_context
*ctx
)
164 struct composite_context
*c
;
165 struct create_user_state
*s
;
166 struct composite_context
*create_req
;
167 struct monitor_msg msg
;
169 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
170 s
= talloc_get_type(c
->private_data
, struct create_user_state
);
172 /* receive result of DomainOpen call */
173 c
->status
= libnet_DomainOpen_recv(ctx
, s
->ctx
, c
, &s
->domain_open
);
174 if (!composite_is_ok(c
)) return;
176 /* send monitor message */
177 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
179 /* prepare arguments for useradd call */
180 s
->user_add
.in
.username
= s
->r
.in
.user_name
;
181 s
->user_add
.in
.domain_handle
= s
->ctx
->samr
.handle
;
183 /* send the request */
184 create_req
= libnet_rpc_useradd_send(s
->ctx
->samr
.pipe
, &s
->user_add
, s
->monitor_fn
);
185 if (composite_nomem(create_req
, c
)) return;
187 /* set the next stage */
188 composite_continue(c
, create_req
, continue_rpc_useradd
, c
);
193 * Stage 1: receive result of useradd call
195 static void continue_rpc_useradd(struct composite_context
*ctx
)
197 struct composite_context
*c
;
198 struct create_user_state
*s
;
199 struct monitor_msg msg
;
201 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
202 s
= talloc_get_type(c
->private_data
, struct create_user_state
);
204 /* receive result of the call */
205 c
->status
= libnet_rpc_useradd_recv(ctx
, c
, &s
->user_add
);
206 if (!composite_is_ok(c
)) return;
208 /* send monitor message */
209 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
217 * Receive result of CreateUser call
219 * @param c composite context returned by send request routine
220 * @param mem_ctx memory context of this call
221 * @param r pointer to a structure containing arguments and result of this call
224 NTSTATUS
libnet_CreateUser_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
225 struct libnet_CreateUser
*r
)
228 struct create_user_state
*s
;
230 r
->out
.error_string
= NULL
;
232 /* wait for result of async request and check status code */
233 status
= composite_wait(c
);
234 if (!NT_STATUS_IS_OK(status
)) {
235 s
= talloc_get_type(c
->private_data
, struct create_user_state
);
236 r
->out
.error_string
= talloc_strdup(mem_ctx
, nt_errstr(status
));
244 * Synchronous version of CreateUser call
246 * @param ctx initialised libnet context
247 * @param mem_ctx memory context of this call
248 * @param r pointer to a structure containing arguments and result of this call
251 NTSTATUS
libnet_CreateUser(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
252 struct libnet_CreateUser
*r
)
254 struct composite_context
*c
;
256 c
= libnet_CreateUser_send(ctx
, mem_ctx
, r
, NULL
);
257 return libnet_CreateUser_recv(c
, mem_ctx
, r
);
261 struct delete_user_state
{
262 struct libnet_DeleteUser r
;
263 struct libnet_context
*ctx
;
264 struct libnet_DomainOpen domain_open
;
265 struct libnet_rpc_userdel user_del
;
267 /* information about the progress */
268 void (*monitor_fn
)(struct monitor_msg
*);
272 static void continue_rpc_userdel(struct composite_context
*ctx
);
273 static void continue_domain_open_delete(struct composite_context
*ctx
);
277 * Sends request to delete user account
279 * @param ctx initialised libnet context
280 * @param mem_ctx memory context of this call
281 * @param r pointer to structure containing arguments and result of this call
282 * @param monitor function pointer for receiving monitor messages
284 struct composite_context
*libnet_DeleteUser_send(struct libnet_context
*ctx
,
286 struct libnet_DeleteUser
*r
,
287 void (*monitor
)(struct monitor_msg
*))
289 struct composite_context
*c
;
290 struct delete_user_state
*s
;
291 struct composite_context
*delete_req
;
292 struct composite_context
*prereq_ctx
;
294 /* composite context allocation and setup */
295 c
= talloc_zero(mem_ctx
, struct composite_context
);
296 if (c
== NULL
) return NULL
;
298 s
= talloc_zero(c
, struct delete_user_state
);
299 if (composite_nomem(s
, c
)) return c
;
302 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
303 c
->event_ctx
= ctx
->event_ctx
;
305 /* store arguments in state structure */
308 ZERO_STRUCT(s
->r
.out
);
310 /* prerequisite: make sure the domain is opened before proceeding */
311 prereq_ctx
= domain_opened(ctx
, s
->r
.in
.domain_name
, c
, &s
->domain_open
,
312 continue_domain_open_delete
, monitor
);
313 if (prereq_ctx
) return prereq_ctx
;
315 /* prepare arguments for userdel call */
316 s
->user_del
.in
.username
= r
->in
.user_name
;
317 s
->user_del
.in
.domain_handle
= ctx
->samr
.handle
;
320 delete_req
= libnet_rpc_userdel_send(ctx
->samr
.pipe
, &s
->user_del
, monitor
);
321 if (composite_nomem(delete_req
, c
)) return c
;
323 /* set the next stage */
324 composite_continue(c
, delete_req
, continue_rpc_userdel
, c
);
330 * Stage 0.5 (optional): receive result of domain open request
331 * and send useradd request
333 static void continue_domain_open_delete(struct composite_context
*ctx
)
335 struct composite_context
*c
;
336 struct delete_user_state
*s
;
337 struct composite_context
*delete_req
;
338 struct monitor_msg msg
;
340 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
341 s
= talloc_get_type(c
->private_data
, struct delete_user_state
);
343 /* receive result of DomainOpen call */
344 c
->status
= libnet_DomainOpen_recv(ctx
, s
->ctx
, c
, &s
->domain_open
);
345 if (!composite_is_ok(c
)) return;
347 /* send monitor message */
348 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
350 /* prepare arguments for userdel call */
351 s
->user_del
.in
.username
= s
->r
.in
.user_name
;
352 s
->user_del
.in
.domain_handle
= s
->ctx
->samr
.handle
;
355 delete_req
= libnet_rpc_userdel_send(s
->ctx
->samr
.pipe
, &s
->user_del
, s
->monitor_fn
);
356 if (composite_nomem(delete_req
, c
)) return;
358 /* set the next stage */
359 composite_continue(c
, delete_req
, continue_rpc_userdel
, c
);
363 static void continue_rpc_userdel(struct composite_context
*ctx
)
365 struct composite_context
*c
;
366 struct delete_user_state
*s
;
367 struct monitor_msg msg
;
369 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
370 s
= talloc_get_type(c
->private_data
, struct delete_user_state
);
372 /* receive result of userdel call */
373 c
->status
= libnet_rpc_userdel_recv(ctx
, c
, &s
->user_del
);
374 if (!composite_is_ok(c
)) return;
376 /* send monitor message */
377 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
385 * Receives result of asynchronous DeleteUser call
387 * @param c composite context returned by async DeleteUser call
388 * @param mem_ctx memory context of this call
389 * @param r pointer to structure containing arguments and result
391 NTSTATUS
libnet_DeleteUser_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
392 struct libnet_DeleteUser
*r
)
395 struct delete_user_state
*s
;
397 r
->out
.error_string
= NULL
;
399 /* wait for result of async request and check status code */
400 status
= composite_wait(c
);
401 if (!NT_STATUS_IS_OK(status
)) {
402 s
= talloc_get_type(c
->private_data
, struct delete_user_state
);
403 r
->out
.error_string
= talloc_steal(mem_ctx
, s
->r
.out
.error_string
);
411 * Synchronous version of DeleteUser call
413 * @param ctx initialised libnet context
414 * @param mem_ctx memory context of this call
415 * @param r pointer to structure containing arguments and result
417 NTSTATUS
libnet_DeleteUser(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
418 struct libnet_DeleteUser
*r
)
420 struct composite_context
*c
;
422 c
= libnet_DeleteUser_send(ctx
, mem_ctx
, r
, NULL
);
423 return libnet_DeleteUser_recv(c
, mem_ctx
, r
);
427 struct modify_user_state
{
428 struct libnet_ModifyUser r
;
429 struct libnet_context
*ctx
;
430 struct libnet_DomainOpen domain_open
;
431 struct libnet_rpc_userinfo user_info
;
432 struct libnet_rpc_usermod user_mod
;
434 void (*monitor_fn
)(struct monitor_msg
*);
438 static void continue_rpc_usermod(struct composite_context
*ctx
);
439 static void continue_domain_open_modify(struct composite_context
*ctx
);
440 static NTSTATUS
set_user_changes(TALLOC_CTX
*mem_ctx
, struct usermod_change
*mod
,
441 struct libnet_rpc_userinfo
*info
, struct libnet_ModifyUser
*r
);
442 static void continue_rpc_userinfo(struct composite_context
*ctx
);
445 struct composite_context
*libnet_ModifyUser_send(struct libnet_context
*ctx
,
447 struct libnet_ModifyUser
*r
,
448 void (*monitor
)(struct monitor_msg
*))
450 struct composite_context
*c
;
451 struct modify_user_state
*s
;
452 struct composite_context
*prereq_ctx
;
453 struct composite_context
*userinfo_req
;
455 c
= talloc_zero(mem_ctx
, struct composite_context
);
456 if (c
== NULL
) return NULL
;
458 s
= talloc_zero(c
, struct modify_user_state
);
459 if (composite_nomem(s
, c
)) return c
;
461 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
463 c
->event_ctx
= ctx
->event_ctx
;
468 prereq_ctx
= domain_opened(ctx
, s
->r
.in
.domain_name
, c
, &s
->domain_open
,
469 continue_domain_open_modify
, monitor
);
470 if (prereq_ctx
) return prereq_ctx
;
472 s
->user_mod
.in
.username
= r
->in
.user_name
;
473 s
->user_mod
.in
.domain_handle
= ctx
->samr
.handle
;
475 userinfo_req
= libnet_rpc_userinfo_send(ctx
->samr
.pipe
, &s
->user_info
, monitor
);
476 if (composite_nomem(userinfo_req
, c
)) return c
;
478 composite_continue(c
, userinfo_req
, continue_rpc_userinfo
, c
);
483 static void continue_domain_open_modify(struct composite_context
*ctx
)
485 const uint16_t level
= 21;
486 struct composite_context
*c
;
487 struct modify_user_state
*s
;
488 struct composite_context
*userinfo_req
;
489 struct monitor_msg msg
;
491 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
492 s
= talloc_get_type(c
->private_data
, struct modify_user_state
);
494 c
->status
= libnet_DomainOpen_recv(ctx
, s
->ctx
, c
, &s
->domain_open
);
495 if (!composite_is_ok(c
)) return;
497 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
499 s
->user_info
.in
.domain_handle
= s
->ctx
->samr
.handle
;
500 s
->user_info
.in
.username
= s
->r
.in
.user_name
;
501 s
->user_info
.in
.level
= level
;
503 userinfo_req
= libnet_rpc_userinfo_send(s
->ctx
->samr
.pipe
, &s
->user_info
, s
->monitor_fn
);
504 if (composite_nomem(userinfo_req
, c
)) return;
506 composite_continue(c
, userinfo_req
, continue_rpc_userinfo
, c
);
510 static void continue_rpc_userinfo(struct composite_context
*ctx
)
512 struct composite_context
*c
;
513 struct modify_user_state
*s
;
514 struct composite_context
*usermod_req
;
516 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
517 s
= talloc_get_type(c
->private_data
, struct modify_user_state
);
519 c
->status
= libnet_rpc_userinfo_recv(ctx
, c
, &s
->user_info
);
520 if (!composite_is_ok(c
)) return;
522 s
->user_mod
.in
.domain_handle
= s
->ctx
->samr
.handle
;
523 s
->user_mod
.in
.username
= s
->r
.in
.user_name
;
525 c
->status
= set_user_changes(c
, &s
->user_mod
.in
.change
, &s
->user_info
, &s
->r
);
527 usermod_req
= libnet_rpc_usermod_send(s
->ctx
->samr
.pipe
, &s
->user_mod
, s
->monitor_fn
);
528 if (composite_nomem(usermod_req
, c
)) return;
530 composite_continue(c
, usermod_req
, continue_rpc_usermod
, c
);
534 static NTSTATUS
set_user_changes(TALLOC_CTX
*mem_ctx
, struct usermod_change
*mod
,
535 struct libnet_rpc_userinfo
*info
, struct libnet_ModifyUser
*r
)
537 struct samr_UserInfo21
*user
;
539 if (mod
== NULL
|| info
== NULL
|| r
== NULL
|| info
->in
.level
!= 21) {
540 return NT_STATUS_INVALID_PARAMETER
;
543 user
= &info
->out
.info
.info21
;
544 mod
->fields
= 0; /* reset flag field before setting individual flags */
546 /* account name change */
547 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, account_name
, USERMOD_FIELD_ACCOUNT_NAME
);
549 /* full name change */
550 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, full_name
, USERMOD_FIELD_FULL_NAME
);
552 /* description change */
553 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, comment
, USERMOD_FIELD_DESCRIPTION
);
556 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, comment
, USERMOD_FIELD_COMMENT
);
558 /* home directory change */
559 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, home_directory
, USERMOD_FIELD_HOME_DIRECTORY
);
561 /* home drive change */
562 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, home_drive
, USERMOD_FIELD_HOME_DRIVE
);
564 /* logon script change */
565 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, logon_script
, USERMOD_FIELD_LOGON_SCRIPT
);
567 /* profile path change */
568 SET_FIELD_LSA_STRING(r
->in
, user
, mod
, profile_path
, USERMOD_FIELD_PROFILE_PATH
);
570 /* allow password change time */
571 SET_FIELD_NTTIME(r
->in
, user
, mod
, allow_password_change
, USERMOD_FIELD_ALLOW_PASS_CHG
);
573 /* force password change time */
574 SET_FIELD_NTTIME(r
->in
, user
, mod
, force_password_change
, USERMOD_FIELD_FORCE_PASS_CHG
);
576 /* account expiry change */
577 SET_FIELD_NTTIME(r
->in
, user
, mod
, acct_expiry
, USERMOD_FIELD_ACCT_EXPIRY
);
583 static void continue_rpc_usermod(struct composite_context
*ctx
)
585 struct composite_context
*c
;
586 struct modify_user_state
*s
;
587 struct monitor_msg msg
;
589 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
590 s
= talloc_get_type(c
->private_data
, struct modify_user_state
);
592 c
->status
= libnet_rpc_usermod_recv(ctx
, c
, &s
->user_mod
);
593 if (!composite_is_ok(c
)) return;
595 if (s
->monitor_fn
) s
->monitor_fn(&msg
);
600 NTSTATUS
libnet_ModifyUser_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
601 struct libnet_ModifyUser
*r
)
603 NTSTATUS status
= composite_wait(c
);
608 NTSTATUS
libnet_ModifyUser(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
609 struct libnet_ModifyUser
*r
)
611 struct composite_context
*c
;
613 c
= libnet_ModifyUser_send(ctx
, mem_ctx
, r
, NULL
);
614 return libnet_ModifyUser_recv(c
, mem_ctx
, r
);
618 struct user_info_state
{
619 struct libnet_context
*ctx
;
620 const char *domain_name
;
621 struct libnet_LookupName lookup
;
622 struct libnet_DomainOpen domopen
;
623 struct libnet_rpc_userinfo userinfo
;
625 /* information about the progress */
626 void (*monitor_fn
)(struct monitor_msg
*);
630 static void continue_name_found(struct composite_context
*ctx
);
631 static void continue_domain_opened(struct composite_context
*ctx
);
632 static void continue_info_received(struct composite_context
*ctx
);
635 struct composite_context
* libnet_UserInfo_send(struct libnet_context
*ctx
,
637 struct libnet_UserInfo
*r
,
638 void (*monitor
)(struct monitor_msg
*))
640 struct composite_context
*c
;
641 struct user_info_state
*s
;
642 struct composite_context
*lookup_req
;
644 c
= composite_create(mem_ctx
, ctx
->event_ctx
);
645 if (c
== NULL
) return NULL
;
647 s
= talloc_zero(c
, struct user_info_state
);
648 if (composite_nomem(s
, c
)) return c
;
652 s
->monitor_fn
= monitor
;
654 s
->domain_name
= talloc_strdup(c
, r
->in
.domain_name
);
656 s
->lookup
.in
.domain_name
= s
->domain_name
;
657 s
->lookup
.in
.name
= talloc_strdup(c
, r
->in
.user_name
);
659 lookup_req
= libnet_LookupName_send(ctx
, c
, &s
->lookup
, s
->monitor_fn
);
660 if (composite_nomem(lookup_req
, c
)) return c
;
662 composite_continue(c
, lookup_req
, continue_name_found
, c
);
667 static void continue_name_found(struct composite_context
*ctx
)
669 struct composite_context
*c
;
670 struct user_info_state
*s
;
671 struct composite_context
*domopen_req
;
673 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
674 s
= talloc_get_type(c
->private_data
, struct user_info_state
);
676 c
->status
= libnet_LookupName_recv(ctx
, c
, &s
->lookup
);
677 if (!composite_is_ok(c
)) return;
679 if (s
->lookup
.out
.sid_type
!= SID_NAME_USER
) {
680 composite_error(c
, NT_STATUS_NO_SUCH_USER
);
684 s
->domopen
.in
.type
= DOMAIN_SAMR
;
685 s
->domopen
.in
.domain_name
= s
->domain_name
;
686 s
->domopen
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
688 domopen_req
= libnet_DomainOpen_send(s
->ctx
, &s
->domopen
, s
->monitor_fn
);
689 if (composite_nomem(domopen_req
, c
)) return;
691 composite_continue(c
, domopen_req
, continue_domain_opened
, c
);
695 static void continue_domain_opened(struct composite_context
*ctx
)
697 struct composite_context
*c
;
698 struct user_info_state
*s
;
699 struct composite_context
*info_req
;
701 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
702 s
= talloc_get_type(c
->private_data
, struct user_info_state
);
704 c
->status
= libnet_DomainOpen_recv(ctx
, s
->ctx
, c
, &s
->domopen
);
705 if (!composite_is_ok(c
)) return;
707 s
->userinfo
.in
.domain_handle
= s
->ctx
->samr
.handle
;
708 s
->userinfo
.in
.sid
= s
->lookup
.out
.sidstr
;
709 s
->userinfo
.in
.level
= 21;
711 info_req
= libnet_rpc_userinfo_send(s
->ctx
->samr
.pipe
, &s
->userinfo
, s
->monitor_fn
);
712 if (composite_nomem(info_req
, c
)) return;
714 composite_continue(c
, info_req
, continue_info_received
, c
);
718 static void continue_info_received(struct composite_context
*ctx
)
720 struct composite_context
*c
;
721 struct user_info_state
*s
;
723 c
= talloc_get_type(ctx
->async
.private_data
, struct composite_context
);
724 s
= talloc_get_type(c
->private_data
, struct user_info_state
);
726 c
->status
= libnet_rpc_userinfo_recv(ctx
, c
, &s
->userinfo
);
727 if (!composite_is_ok(c
)) return;
733 NTSTATUS
libnet_UserInfo_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
734 struct libnet_UserInfo
*r
)
737 struct user_info_state
*s
;
739 status
= composite_wait(c
);
741 if (NT_STATUS_IS_OK(status
) && r
!= NULL
) {
742 struct samr_UserInfo21
*info
;
744 s
= talloc_get_type(c
->private_data
, struct user_info_state
);
745 info
= &s
->userinfo
.out
.info
.info21
;
747 r
->out
.account_name
= talloc_steal(mem_ctx
, info
->account_name
.string
);
748 r
->out
.full_name
= talloc_steal(mem_ctx
, info
->full_name
.string
);
749 r
->out
.description
= talloc_steal(mem_ctx
, info
->description
.string
);
750 r
->out
.home_directory
= talloc_steal(mem_ctx
, info
->home_directory
.string
);
751 r
->out
.home_drive
= talloc_steal(mem_ctx
, info
->home_drive
.string
);
752 r
->out
.comment
= talloc_steal(mem_ctx
, info
->comment
.string
);
753 r
->out
.logon_script
= talloc_steal(mem_ctx
, info
->logon_script
.string
);
754 r
->out
.profile_path
= talloc_steal(mem_ctx
, info
->profile_path
.string
);
756 r
->out
.error_string
= talloc_strdup(mem_ctx
, "Success");
765 NTSTATUS
libnet_UserInfo(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
766 struct libnet_UserInfo
*r
)
768 struct composite_context
*c
;
770 c
= libnet_UserInfo_send(ctx
, mem_ctx
, r
, NULL
);
771 return libnet_UserInfo_recv(c
, mem_ctx
, r
);