9e401358013d5cf0fe632b4b149e056ab30bcad6
[metze/samba/wip.git] / source3 / libsmb / cli_samr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2
4    RPC pipe client
5    Copyright (C) Tim Potter                        2000-2001,
6    Copyright (C) Andrew Tridgell              1992-1997,2000,
7    Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
8    Copyright (C) Paul Ashton                       1997,2000,
9    Copyright (C) Elrond                                 2000.
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 /* Opens a SMB connection to the SAMR pipe */
29
30 struct cli_state *cli_samr_initialise(struct cli_state *cli, char *system_name,
31                                       struct ntuser_creds *creds)
32 {
33         return cli_pipe_initialise(cli, system_name, PIPE_SAMR, creds);
34 }
35
36 /* Connect to SAMR database */
37
38 NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
39                           uint32 access_mask, POLICY_HND *connect_pol)
40 {
41         prs_struct qbuf, rbuf;
42         SAMR_Q_CONNECT q;
43         SAMR_R_CONNECT r;
44         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
45
46         ZERO_STRUCT(q);
47         ZERO_STRUCT(r);
48
49         /* Initialise parse structures */
50
51         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
52         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
53
54         /* Marshall data and send request */
55
56         init_samr_q_connect(&q, cli->desthost, access_mask);
57
58         if (!samr_io_q_connect("", &q, &qbuf, 0) ||
59             !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) {
60                 goto done;
61         }
62
63         /* Unmarshall response */
64
65         if (!samr_io_r_connect("", &r, &rbuf, 0)) {
66                 goto done;
67         }
68
69         /* Return output parameters */
70
71         if ((result = r.status) == NT_STATUS_OK) {
72                 *connect_pol = r.connect_pol;
73         }
74
75  done:
76         prs_mem_free(&qbuf);
77         prs_mem_free(&rbuf);
78
79         return result;
80 }
81
82 /* Close SAMR handle */
83
84 NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
85                         POLICY_HND *connect_pol)
86 {
87         prs_struct qbuf, rbuf;
88         SAMR_Q_CLOSE_HND q;
89         SAMR_R_CLOSE_HND r;
90         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
91
92         ZERO_STRUCT(q);
93         ZERO_STRUCT(r);
94
95         /* Initialise parse structures */
96
97         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
98         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
99
100         /* Marshall data and send request */
101
102         init_samr_q_close_hnd(&q, connect_pol);
103
104         if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
105             !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) {
106                 goto done;
107         }
108
109         /* Unmarshall response */
110
111         if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) {
112                 goto done;
113         }
114
115         /* Return output parameters */
116
117         if ((result = r.status) == NT_STATUS_OK) {
118                 *connect_pol = r.pol;
119         }
120
121  done:
122         prs_mem_free(&qbuf);
123         prs_mem_free(&rbuf);
124
125         return result;
126 }
127
128 /* Open handle on a domain */
129
130 NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
131                               POLICY_HND *connect_pol, uint32 access_mask, 
132                               DOM_SID *domain_sid, POLICY_HND *domain_pol)
133 {
134         prs_struct qbuf, rbuf;
135         SAMR_Q_OPEN_DOMAIN q;
136         SAMR_R_OPEN_DOMAIN r;
137         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
138
139         ZERO_STRUCT(q);
140         ZERO_STRUCT(r);
141
142         /* Initialise parse structures */
143
144         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
145         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
146
147         /* Marshall data and send request */
148
149         init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid);
150
151         if (!samr_io_q_open_domain("", &q, &qbuf, 0) ||
152             !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) {
153                 goto done;
154         }
155
156         /* Unmarshall response */
157
158         if (!samr_io_r_open_domain("", &r, &rbuf, 0)) {
159                 goto done;
160         }
161
162         /* Return output parameters */
163
164         if ((result = r.status) == NT_STATUS_OK) {
165                 *domain_pol = r.domain_pol;
166         }
167
168  done:
169         prs_mem_free(&qbuf);
170         prs_mem_free(&rbuf);
171
172         return result;
173 }
174
175 /* Open handle on a user */
176
177 NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
178                             POLICY_HND *domain_pol, uint32 access_mask, 
179                             uint32 user_rid, POLICY_HND *user_pol)
180 {
181         prs_struct qbuf, rbuf;
182         SAMR_Q_OPEN_USER q;
183         SAMR_R_OPEN_USER r;
184         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
185
186         ZERO_STRUCT(q);
187         ZERO_STRUCT(r);
188
189         /* Initialise parse structures */
190
191         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
192         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
193
194         /* Marshall data and send request */
195
196         init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
197
198         if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
199             !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) {
200                 goto done;
201         }
202
203         /* Unmarshall response */
204
205         if (!samr_io_r_open_user("", &r, &rbuf, 0)) {
206                 goto done;
207         }
208
209         /* Return output parameters */
210
211         if ((result = r.status) == NT_STATUS_OK) {
212                 *user_pol = r.user_pol;
213         }
214
215  done:
216         prs_mem_free(&qbuf);
217         prs_mem_free(&rbuf);
218
219         return result;
220 }
221
222 /* Open handle on a group */
223
224 NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
225                              POLICY_HND *domain_pol, uint32 access_mask, 
226                              uint32 group_rid, POLICY_HND *group_pol)
227 {
228         prs_struct qbuf, rbuf;
229         SAMR_Q_OPEN_GROUP q;
230         SAMR_R_OPEN_GROUP r;
231         NTSTATUS result =  NT_STATUS_UNSUCCESSFUL;
232
233         ZERO_STRUCT(q);
234         ZERO_STRUCT(r);
235
236         /* Initialise parse structures */
237
238         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
239         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
240
241         /* Marshall data and send request */
242
243         init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
244
245         if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
246             !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) {
247                 goto done;
248         }
249
250         /* Unmarshall response */
251
252         if (!samr_io_r_open_group("", &r, &rbuf, 0)) {
253                 goto done;
254         }
255
256         /* Return output parameters */
257
258         if ((result = r.status) == NT_STATUS_OK) {
259                 *group_pol = r.pol;
260         }
261
262  done:
263         prs_mem_free(&qbuf);
264         prs_mem_free(&rbuf);
265
266         return result;
267 }
268
269 /* Query user info */
270
271 NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
272                                  POLICY_HND *user_pol, uint16 switch_value, 
273                                  SAM_USERINFO_CTR **ctr)
274 {
275         prs_struct qbuf, rbuf;
276         SAMR_Q_QUERY_USERINFO q;
277         SAMR_R_QUERY_USERINFO r;
278         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
279
280         ZERO_STRUCT(q);
281         ZERO_STRUCT(r);
282
283         /* Initialise parse structures */
284
285         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
286         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
287
288         /* Marshall data and send request */
289
290         init_samr_q_query_userinfo(&q, user_pol, switch_value);
291
292         if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
293             !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) {
294                 goto done;
295         }
296
297         /* Unmarshall response */
298
299         if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) {
300                 goto done;
301         }
302
303         /* Return output parameters */
304
305         result = r.status;
306         *ctr = r.ctr;
307
308  done:
309         prs_mem_free(&qbuf);
310         prs_mem_free(&rbuf);
311
312         return result;
313 }
314
315 /* Query group info */
316
317 NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
318                                   POLICY_HND *group_pol, uint32 info_level, 
319                                   GROUP_INFO_CTR *ctr)
320 {
321         prs_struct qbuf, rbuf;
322         SAMR_Q_QUERY_GROUPINFO q;
323         SAMR_R_QUERY_GROUPINFO r;
324         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
325
326         ZERO_STRUCT(q);
327         ZERO_STRUCT(r);
328
329         /* Initialise parse structures */
330
331         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
332         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
333
334         /* Marshall data and send request */
335
336         init_samr_q_query_groupinfo(&q, group_pol, info_level);
337
338         if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
339             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) {
340                 goto done;
341         }
342
343         /* Unmarshall response */
344
345         r.ctr = ctr;
346
347         if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) {
348                 goto done;
349         }
350
351         /* Return output parameters */
352
353         result = r.status;
354
355  done:
356         prs_mem_free(&qbuf);
357         prs_mem_free(&rbuf);
358
359         return result;
360 }
361
362 /* Query user groups */
363
364 NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
365                                    POLICY_HND *user_pol, uint32 *num_groups, 
366                                    DOM_GID **gid)
367 {
368         prs_struct qbuf, rbuf;
369         SAMR_Q_QUERY_USERGROUPS q;
370         SAMR_R_QUERY_USERGROUPS r;
371         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
372
373         ZERO_STRUCT(q);
374         ZERO_STRUCT(r);
375
376         /* Initialise parse structures */
377
378         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
379         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
380
381         /* Marshall data and send request */
382
383         init_samr_q_query_usergroups(&q, user_pol);
384
385         if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
386             !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) {
387                 goto done;
388         }
389
390         /* Unmarshall response */
391
392         if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) {
393                 goto done;
394         }
395
396         /* Return output parameters */
397
398         if ((result = r.status) == NT_STATUS_OK) {
399                 *num_groups = r.num_entries;
400                 *gid = r.gid;
401         }
402
403  done:
404         prs_mem_free(&qbuf);
405         prs_mem_free(&rbuf);
406
407         return result;
408 }
409
410 /* Query user groups */
411
412 NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
413                                  POLICY_HND *group_pol, uint32 *num_mem, 
414                                  uint32 **rid, uint32 **attr)
415 {
416         prs_struct qbuf, rbuf;
417         SAMR_Q_QUERY_GROUPMEM q;
418         SAMR_R_QUERY_GROUPMEM r;
419         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
420
421         ZERO_STRUCT(q);
422         ZERO_STRUCT(r);
423
424         /* Initialise parse structures */
425
426         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
427         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
428
429         /* Marshall data and send request */
430
431         init_samr_q_query_groupmem(&q, group_pol);
432
433         if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
434             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) {
435                 goto done;
436         }
437
438         /* Unmarshall response */
439
440         if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) {
441                 goto done;
442         }
443
444         /* Return output parameters */
445
446         if ((result = r.status) == NT_STATUS_OK) {
447                 *num_mem = r.num_entries;
448                 *rid = r.rid;
449                 *attr = r.attr;
450         }
451
452  done:
453         prs_mem_free(&qbuf);
454         prs_mem_free(&rbuf);
455
456         return result;
457 }
458
459 /* Enumerate domain groups */
460
461 NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
462                                   POLICY_HND *pol, uint32 *start_idx, 
463                                   uint32 size, struct acct_info **dom_groups,
464                                   uint32 *num_dom_groups)
465 {
466         prs_struct qbuf, rbuf;
467         SAMR_Q_ENUM_DOM_GROUPS q;
468         SAMR_R_ENUM_DOM_GROUPS r;
469         NTSTATUS result = NT_STATUS_UNSUCCESSFUL, name_idx, i;
470
471         ZERO_STRUCT(q);
472         ZERO_STRUCT(r);
473
474         /* Initialise parse structures */
475
476         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
477         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
478
479         /* Marshall data and send request */
480
481         init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
482
483         if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
484             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) {
485                 goto done;
486         }
487
488         /* Unmarshall response */
489
490         if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) {
491                 goto done;
492         }
493
494         /* Return output parameters */
495
496         result = r.status;
497
498         if (result != NT_STATUS_OK &&
499             result != STATUS_MORE_ENTRIES) {
500                 goto done;
501         }
502
503         *num_dom_groups = r.num_entries2;
504
505         if (!((*dom_groups) = (struct acct_info *)
506               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
507                 result = NT_STATUS_UNSUCCESSFUL;
508                 goto done;
509         }
510
511         memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups);
512
513         name_idx = 0;
514
515         for (i = 0; i < *num_dom_groups; i++) {
516
517                 (*dom_groups)[i].rid = r.sam[i].rid;
518
519                 if (r.sam[i].hdr_name.buffer) {
520                         unistr2_to_ascii((*dom_groups)[i].acct_name,
521                                          &r.uni_grp_name[name_idx],
522                                          sizeof(fstring) - 1);
523                         name_idx++;
524                 }
525
526                 *start_idx = r.next_idx;
527         }
528
529  done:
530         prs_mem_free(&qbuf);
531         prs_mem_free(&rbuf);
532
533         return result;
534 }
535
536 /* Query alias members */
537
538 NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
539                                  POLICY_HND *alias_pol, uint32 *num_mem, 
540                                  DOM_SID **sids)
541 {
542         prs_struct qbuf, rbuf;
543         SAMR_Q_QUERY_ALIASMEM q;
544         SAMR_R_QUERY_ALIASMEM r;
545         NTSTATUS result = NT_STATUS_UNSUCCESSFUL, i;
546
547         ZERO_STRUCT(q);
548         ZERO_STRUCT(r);
549
550         /* Initialise parse structures */
551
552         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
553         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
554
555         /* Marshall data and send request */
556
557         init_samr_q_query_aliasmem(&q, alias_pol);
558
559         if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
560             !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
561                 goto done;
562         }
563
564         /* Unmarshall response */
565
566         if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
567                 goto done;
568         }
569
570         /* Return output parameters */
571
572         if ((result = r.status) != NT_STATUS_OK) {
573                 goto done;
574         }
575
576         *num_mem = r.num_sids;
577
578         if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) {
579                 result = NT_STATUS_UNSUCCESSFUL;
580                 goto done;
581         }
582
583         for (i = 0; i < *num_mem; i++) {
584                 (*sids)[i] = r.sid[i].sid;
585         }
586
587  done:
588         prs_mem_free(&qbuf);
589         prs_mem_free(&rbuf);
590
591         return result;
592 }
593
594 /* Open handle on an alias */
595
596 NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
597                              POLICY_HND *domain_pol, uint32 access_mask, 
598                              uint32 alias_rid, POLICY_HND *alias_pol)
599 {
600         prs_struct qbuf, rbuf;
601         SAMR_Q_OPEN_ALIAS q;
602         SAMR_R_OPEN_ALIAS r;
603         NTSTATUS result;
604
605         ZERO_STRUCT(q);
606         ZERO_STRUCT(r);
607
608         /* Initialise parse structures */
609
610         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
611         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
612
613         /* Marshall data and send request */
614
615         init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid);
616
617         if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
618             !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
619                 result = NT_STATUS_UNSUCCESSFUL;
620                 goto done;
621         }
622
623         /* Unmarshall response */
624
625         if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
626                 result = NT_STATUS_UNSUCCESSFUL;
627                 goto done;
628         }
629
630         /* Return output parameters */
631
632         if ((result = r.status) == NT_STATUS_OK) {
633                 *alias_pol = r.pol;
634         }
635
636  done:
637         prs_mem_free(&qbuf);
638         prs_mem_free(&rbuf);
639
640         return result;
641 }
642
643 /* Query domain info */
644
645 NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
646                                  POLICY_HND *domain_pol, uint16 switch_value,
647                                  SAM_UNK_CTR *ctr)
648 {
649         prs_struct qbuf, rbuf;
650         SAMR_Q_QUERY_DOMAIN_INFO q;
651         SAMR_R_QUERY_DOMAIN_INFO r;
652         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
653
654         ZERO_STRUCT(q);
655         ZERO_STRUCT(r);
656
657         /* Initialise parse structures */
658
659         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
660         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
661
662         /* Marshall data and send request */
663
664         init_samr_q_query_dom_info(&q, domain_pol, switch_value);
665
666         if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) ||
667             !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) {
668                 goto done;
669         }
670
671         /* Unmarshall response */
672
673         r.ctr = ctr;
674
675         if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) {
676                 goto done;
677         }
678
679         /* Return output parameters */
680
681         if ((result = r.status) != NT_STATUS_OK) {
682                 goto done;
683         }
684
685  done:
686         prs_mem_free(&qbuf);
687         prs_mem_free(&rbuf);
688
689         return result;
690 }
691
692 /* Query display info */
693
694 NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
695                                  POLICY_HND *domain_pol, uint32 *start_idx,
696                                  uint16 switch_value, uint32 *num_entries,
697                                  uint32 max_entries, SAM_DISPINFO_CTR *ctr)
698 {
699         prs_struct qbuf, rbuf;
700         SAMR_Q_QUERY_DISPINFO q;
701         SAMR_R_QUERY_DISPINFO r;
702         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
703
704         ZERO_STRUCT(q);
705         ZERO_STRUCT(r);
706
707         /* Initialise parse structures */
708
709         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
710         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
711
712         /* Marshall data and send request */
713
714         init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
715                                    *start_idx, max_entries);
716
717         if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) ||
718             !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) {
719                 goto done;
720         }
721
722         /* Unmarshall response */
723
724         r.ctr = ctr;
725
726         if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) {
727                 goto done;
728         }
729
730         /* Return output parameters */
731
732         result = r.status;
733
734         if (result != NT_STATUS_OK &&
735             result != STATUS_MORE_ENTRIES) {
736                 goto done;
737         }
738
739         *num_entries = r.num_entries;
740         *start_idx += r.num_entries;  /* No next_idx in this structure! */
741
742  done:
743         prs_mem_free(&qbuf);
744         prs_mem_free(&rbuf);
745
746         return result;
747 }
748
749 /* Lookup rids.  Note that NT4 seems to crash if more than ~1000 rids are
750    looked up in one packet. */
751
752 NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
753                               POLICY_HND *domain_pol, uint32 flags,
754                               uint32 num_rids, uint32 *rids, 
755                               uint32 *num_names, char ***names,
756                               uint32 **name_types)
757 {
758         prs_struct qbuf, rbuf;
759         SAMR_Q_LOOKUP_RIDS q;
760         SAMR_R_LOOKUP_RIDS r;
761         NTSTATUS result = NT_STATUS_UNSUCCESSFUL, i;
762
763         if (num_rids > 1000) {
764                 DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if "
765                           "more than ~1000 rids are looked up at once.\n"));
766         }
767
768         ZERO_STRUCT(q);
769         ZERO_STRUCT(r);
770
771         /* Initialise parse structures */
772
773         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
774         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
775
776         /* Marshall data and send request */
777
778         init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags,
779                                 num_rids, rids);
780
781         if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
782             !rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
783                 goto done;
784         }
785
786         /* Unmarshall response */
787
788         if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) {
789                 goto done;
790         }
791
792         /* Return output parameters */
793
794         if ((result = r.status) != NT_STATUS_OK) {
795                 goto done;
796         }
797
798         if (r.num_names1 == 0) {
799                 *num_names = 0;
800                 *names = NULL;
801                 goto done;
802         }
803
804         *num_names = r.num_names1;
805         *names = talloc(mem_ctx, sizeof(char *) * r.num_names1);
806         *name_types = talloc(mem_ctx, sizeof(uint32) * r.num_names1);
807
808         for (i = 0; i < r.num_names1; i++) {
809                 fstring tmp;
810
811                 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp) - 1);
812                 (*names)[i] = talloc_strdup(mem_ctx, tmp);
813                 (*name_types)[i] = r.type[i];
814         }
815
816  done:
817         prs_mem_free(&qbuf);
818         prs_mem_free(&rbuf);
819
820         return result;
821 }
822
823 /* Lookup names */
824
825 NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
826                                POLICY_HND *domain_pol, uint32 flags,
827                                uint32 num_names, char **names,
828                                uint32 *num_rids, uint32 **rids,
829                                uint32 **rid_types)
830 {
831         prs_struct qbuf, rbuf;
832         SAMR_Q_LOOKUP_NAMES q;
833         SAMR_R_LOOKUP_NAMES r;
834         NTSTATUS result = NT_STATUS_UNSUCCESSFUL, i;
835
836         ZERO_STRUCT(q);
837         ZERO_STRUCT(r);
838
839         /* Initialise parse structures */
840
841         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
842         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
843
844         /* Marshall data and send request */
845
846         init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags,
847                                  num_names, names);
848
849         if (!samr_io_q_lookup_names("", &q, &qbuf, 0) ||
850             !rpc_api_pipe_req(cli, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) {
851                 goto done;
852         }
853
854         /* Unmarshall response */
855
856         if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) {
857                 goto done;
858         }
859
860         /* Return output parameters */
861
862         if ((result = r.status) != NT_STATUS_OK) {
863                 goto done;
864         }
865
866         if (r.num_rids1 == 0) {
867                 *num_rids = 0;
868                 goto done;
869         }
870
871         *num_rids = r.num_rids1;
872         *rids = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
873         *rid_types = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
874
875         for (i = 0; i < r.num_rids1; i++) {
876                 (*rids)[i] = r.rids[i];
877                 (*rid_types)[i] = r.types[i];
878         }
879
880  done:
881         prs_mem_free(&qbuf);
882         prs_mem_free(&rbuf);
883
884         return result;
885 }
886
887 /* Create a domain user */
888
889 NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
890                                   POLICY_HND *domain_pol, char *acct_name,
891                                   uint32 acb_info, uint32 unknown, 
892                                   POLICY_HND *user_pol, uint32 *rid)
893 {
894         prs_struct qbuf, rbuf;
895         SAMR_Q_CREATE_USER q;
896         SAMR_R_CREATE_USER r;
897         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
898
899         ZERO_STRUCT(q);
900         ZERO_STRUCT(r);
901
902         /* Initialise parse structures */
903
904         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
905         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
906
907         /* Marshall data and send request */
908
909         init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown);
910
911         if (!samr_io_q_create_user("", &q, &qbuf, 0) ||
912             !rpc_api_pipe_req(cli, SAMR_CREATE_USER, &qbuf, &rbuf)) {
913                 goto done;
914         }
915
916         /* Unmarshall response */
917
918         if (!samr_io_r_create_user("", &r, &rbuf, 0)) {
919                 goto done;
920         }
921
922         /* Return output parameters */
923
924         if ((result = r.status) != NT_STATUS_OK) {
925                 goto done;
926         }
927
928         if (user_pol)
929                 *user_pol = r.user_pol;
930
931         if (rid)
932                 *rid = r.user_rid;
933
934  done:
935         prs_mem_free(&qbuf);
936         prs_mem_free(&rbuf);
937
938         return result;
939 }
940
941 /* Set userinfo */
942
943 NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
944                                POLICY_HND *user_pol, uint16 switch_value,
945                                uchar sess_key[16], SAM_USERINFO_CTR *ctr)
946 {
947         prs_struct qbuf, rbuf;
948         SAMR_Q_SET_USERINFO q;
949         SAMR_R_SET_USERINFO r;
950         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
951
952         ZERO_STRUCT(q);
953         ZERO_STRUCT(r);
954
955         /* Initialise parse structures */
956
957         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
958         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
959
960         /* Marshall data and send request */
961
962         q.ctr = ctr;
963
964         init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, 
965                                  ctr->info.id);
966
967         if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) ||
968             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO, &qbuf, &rbuf)) {
969                 goto done;
970         }
971
972         /* Unmarshall response */
973
974         if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) {
975                 goto done;
976         }
977
978         /* Return output parameters */
979
980         if ((result = r.status) != NT_STATUS_OK) {
981                 goto done;
982         }
983
984  done:
985         prs_mem_free(&qbuf);
986         prs_mem_free(&rbuf);
987
988         return result;
989 }
990
991 /* Set userinfo2 */
992
993 NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
994                                 POLICY_HND *user_pol, uint16 switch_value,
995                                 uchar sess_key[16], SAM_USERINFO_CTR *ctr)
996 {
997         prs_struct qbuf, rbuf;
998         SAMR_Q_SET_USERINFO2 q;
999         SAMR_R_SET_USERINFO2 r;
1000         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1001
1002         ZERO_STRUCT(q);
1003         ZERO_STRUCT(r);
1004
1005         /* Initialise parse structures */
1006
1007         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1008         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1009
1010         /* Marshall data and send request */
1011
1012         init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
1013
1014         if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) ||
1015             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO2, &qbuf, &rbuf)) {
1016                 goto done;
1017         }
1018
1019         /* Unmarshall response */
1020
1021         if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) {
1022                 goto done;
1023         }
1024
1025         /* Return output parameters */
1026
1027         if ((result = r.status) != NT_STATUS_OK) {
1028                 goto done;
1029         }
1030
1031  done:
1032         prs_mem_free(&qbuf);
1033         prs_mem_free(&rbuf);
1034
1035         return result;
1036 }
1037
1038 /* Delete domain user */
1039
1040 NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1041                                   POLICY_HND *user_pol)
1042 {
1043         prs_struct qbuf, rbuf;
1044         SAMR_Q_DELETE_DOM_USER q;
1045         SAMR_R_DELETE_DOM_USER r;
1046         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1047
1048         ZERO_STRUCT(q);
1049         ZERO_STRUCT(r);
1050
1051         /* Initialise parse structures */
1052
1053         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1054         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1055
1056         /* Marshall data and send request */
1057
1058         init_samr_q_delete_dom_user(&q, user_pol);
1059
1060         if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) ||
1061             !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) {
1062                 goto done;
1063         }
1064
1065         /* Unmarshall response */
1066
1067         if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) {
1068                 goto done;
1069         }
1070
1071         /* Return output parameters */
1072
1073         result = r.status;
1074
1075  done:
1076         prs_mem_free(&qbuf);
1077         prs_mem_free(&rbuf);
1078
1079         return result;
1080 }