When re-writing tdb version numbers as little endian int32, we must
[ira/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 (NT_STATUS_IS_OK(result = r.status)) {
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 (NT_STATUS_IS_OK(result = r.status)) {
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                               const 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 (NT_STATUS_IS_OK(result = r.status)) {
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 (NT_STATUS_IS_OK(result = r.status)) {
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 (NT_STATUS_IS_OK(result = r.status)) {
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 (NT_STATUS_IS_OK(result = r.status)) {
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 aliases */
411
412 NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
413                                    POLICY_HND *user_pol, uint32 num_sids, DOM_SID2 *sid,
414                                    uint32 *num_aliases, uint32 **als_rids)
415 {
416         prs_struct qbuf, rbuf;
417         SAMR_Q_QUERY_USERALIASES q;
418         SAMR_R_QUERY_USERALIASES r;
419         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
420         uint ptr=1;
421         
422         ZERO_STRUCT(q);
423         ZERO_STRUCT(r);
424
425         /* Initialise parse structures */
426
427         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
428         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
429
430         /* Marshall data and send request */
431
432         init_samr_q_query_useraliases(&q, user_pol, num_sids, &ptr, sid);
433
434         if (!samr_io_q_query_useraliases("", &q, &qbuf, 0) ||
435             !rpc_api_pipe_req(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf)) {
436                 goto done;
437         }
438
439         /* Unmarshall response */
440
441         if (!samr_io_r_query_useraliases("", &r, &rbuf, 0)) {
442                 goto done;
443         }
444
445         /* Return output parameters */
446
447         if (NT_STATUS_IS_OK(result = r.status)) {
448                 *num_aliases = r.num_entries;
449                 *als_rids = r.rid;
450         }
451
452  done:
453         prs_mem_free(&qbuf);
454         prs_mem_free(&rbuf);
455
456         return result;
457 }
458
459 /* Query user groups */
460
461 NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
462                                  POLICY_HND *group_pol, uint32 *num_mem, 
463                                  uint32 **rid, uint32 **attr)
464 {
465         prs_struct qbuf, rbuf;
466         SAMR_Q_QUERY_GROUPMEM q;
467         SAMR_R_QUERY_GROUPMEM r;
468         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
469
470         ZERO_STRUCT(q);
471         ZERO_STRUCT(r);
472
473         /* Initialise parse structures */
474
475         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
476         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
477
478         /* Marshall data and send request */
479
480         init_samr_q_query_groupmem(&q, group_pol);
481
482         if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
483             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) {
484                 goto done;
485         }
486
487         /* Unmarshall response */
488
489         if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) {
490                 goto done;
491         }
492
493         /* Return output parameters */
494
495         if (NT_STATUS_IS_OK(result = r.status)) {
496                 *num_mem = r.num_entries;
497                 *rid = r.rid;
498                 *attr = r.attr;
499         }
500
501  done:
502         prs_mem_free(&qbuf);
503         prs_mem_free(&rbuf);
504
505         return result;
506 }
507
508 /* Enumerate domain groups */
509
510 NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
511                                   POLICY_HND *pol, uint32 *start_idx, 
512                                   uint32 size, struct acct_info **dom_groups,
513                                   uint32 *num_dom_groups)
514 {
515         prs_struct qbuf, rbuf;
516         SAMR_Q_ENUM_DOM_GROUPS q;
517         SAMR_R_ENUM_DOM_GROUPS r;
518         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
519         uint32 name_idx, i;
520
521         ZERO_STRUCT(q);
522         ZERO_STRUCT(r);
523
524         /* Initialise parse structures */
525
526         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
527         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
528
529         /* Marshall data and send request */
530
531         init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
532
533         if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
534             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) {
535                 goto done;
536         }
537
538         /* Unmarshall response */
539
540         if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) {
541                 goto done;
542         }
543
544         /* Return output parameters */
545
546         result = r.status;
547
548         if (!NT_STATUS_IS_OK(result) &&
549             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
550                 goto done;
551         }
552
553         *num_dom_groups = r.num_entries2;
554
555         if (!((*dom_groups) = (struct acct_info *)
556               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
557                 result = NT_STATUS_UNSUCCESSFUL;
558                 goto done;
559         }
560
561         memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups);
562
563         name_idx = 0;
564
565         for (i = 0; i < *num_dom_groups; i++) {
566
567                 (*dom_groups)[i].rid = r.sam[i].rid;
568
569                 if (r.sam[i].hdr_name.buffer) {
570                         unistr2_to_ascii((*dom_groups)[i].acct_name,
571                                          &r.uni_grp_name[name_idx],
572                                          sizeof(fstring) - 1);
573                         name_idx++;
574                 }
575
576                 *start_idx = r.next_idx;
577         }
578
579  done:
580         prs_mem_free(&qbuf);
581         prs_mem_free(&rbuf);
582
583         return result;
584 }
585
586 /* Enumerate domain groups */
587
588 NTSTATUS cli_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
589                                   POLICY_HND *pol, uint32 *start_idx, 
590                                   uint32 size, struct acct_info **dom_groups,
591                                   uint32 *num_dom_groups)
592 {
593         prs_struct qbuf, rbuf;
594         SAMR_Q_ENUM_DOM_ALIASES q;
595         SAMR_R_ENUM_DOM_ALIASES r;
596         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
597         uint32 name_idx, i;
598
599         ZERO_STRUCT(q);
600         ZERO_STRUCT(r);
601
602         /* Initialise parse structures */
603
604         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
605         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
606
607         /* Marshall data and send request */
608
609         init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size);
610
611         if (!samr_io_q_enum_dom_aliases("", &q, &qbuf, 0) ||
612             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_ALIASES, &qbuf, &rbuf)) {
613                 goto done;
614         }
615
616         /* Unmarshall response */
617
618         if (!samr_io_r_enum_dom_aliases("", &r, &rbuf, 0)) {
619                 goto done;
620         }
621
622         /* Return output parameters */
623
624         result = r.status;
625
626         if (!NT_STATUS_IS_OK(result) &&
627             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
628                 goto done;
629         }
630
631         *num_dom_groups = r.num_entries2;
632
633         if (!((*dom_groups) = (struct acct_info *)
634               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
635                 result = NT_STATUS_UNSUCCESSFUL;
636                 goto done;
637         }
638
639         memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups);
640
641         name_idx = 0;
642
643         for (i = 0; i < *num_dom_groups; i++) {
644
645                 (*dom_groups)[i].rid = r.sam[i].rid;
646
647                 if (r.sam[i].hdr_name.buffer) {
648                         unistr2_to_ascii((*dom_groups)[i].acct_name,
649                                          &r.uni_grp_name[name_idx],
650                                          sizeof(fstring) - 1);
651                         name_idx++;
652                 }
653
654                 *start_idx = r.next_idx;
655         }
656
657  done:
658         prs_mem_free(&qbuf);
659         prs_mem_free(&rbuf);
660
661         return result;
662 }
663
664 /* Query alias members */
665
666 NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
667                                  POLICY_HND *alias_pol, uint32 *num_mem, 
668                                  DOM_SID **sids)
669 {
670         prs_struct qbuf, rbuf;
671         SAMR_Q_QUERY_ALIASMEM q;
672         SAMR_R_QUERY_ALIASMEM r;
673         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
674         uint32 i;
675
676         ZERO_STRUCT(q);
677         ZERO_STRUCT(r);
678
679         /* Initialise parse structures */
680
681         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
682         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
683
684         /* Marshall data and send request */
685
686         init_samr_q_query_aliasmem(&q, alias_pol);
687
688         if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
689             !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
690                 goto done;
691         }
692
693         /* Unmarshall response */
694
695         if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
696                 goto done;
697         }
698
699         /* Return output parameters */
700
701         if (!NT_STATUS_IS_OK(result = r.status)) {
702                 goto done;
703         }
704
705         *num_mem = r.num_sids;
706
707         if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) {
708                 result = NT_STATUS_UNSUCCESSFUL;
709                 goto done;
710         }
711
712         for (i = 0; i < *num_mem; i++) {
713                 (*sids)[i] = r.sid[i].sid;
714         }
715
716  done:
717         prs_mem_free(&qbuf);
718         prs_mem_free(&rbuf);
719
720         return result;
721 }
722
723 /* Open handle on an alias */
724
725 NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
726                              POLICY_HND *domain_pol, uint32 access_mask, 
727                              uint32 alias_rid, POLICY_HND *alias_pol)
728 {
729         prs_struct qbuf, rbuf;
730         SAMR_Q_OPEN_ALIAS q;
731         SAMR_R_OPEN_ALIAS r;
732         NTSTATUS result;
733
734         ZERO_STRUCT(q);
735         ZERO_STRUCT(r);
736
737         /* Initialise parse structures */
738
739         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
740         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
741
742         /* Marshall data and send request */
743
744         init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid);
745
746         if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
747             !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
748                 result = NT_STATUS_UNSUCCESSFUL;
749                 goto done;
750         }
751
752         /* Unmarshall response */
753
754         if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
755                 result = NT_STATUS_UNSUCCESSFUL;
756                 goto done;
757         }
758
759         /* Return output parameters */
760
761         if (NT_STATUS_IS_OK(result = r.status)) {
762                 *alias_pol = r.pol;
763         }
764
765  done:
766         prs_mem_free(&qbuf);
767         prs_mem_free(&rbuf);
768
769         return result;
770 }
771
772 /* Query domain info */
773
774 NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
775                                  POLICY_HND *domain_pol, uint16 switch_value,
776                                  SAM_UNK_CTR *ctr)
777 {
778         prs_struct qbuf, rbuf;
779         SAMR_Q_QUERY_DOMAIN_INFO q;
780         SAMR_R_QUERY_DOMAIN_INFO r;
781         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
782
783         ZERO_STRUCT(q);
784         ZERO_STRUCT(r);
785
786         /* Initialise parse structures */
787
788         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
789         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
790
791         /* Marshall data and send request */
792
793         init_samr_q_query_dom_info(&q, domain_pol, switch_value);
794
795         if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) ||
796             !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) {
797                 goto done;
798         }
799
800         /* Unmarshall response */
801
802         r.ctr = ctr;
803
804         if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) {
805                 goto done;
806         }
807
808         /* Return output parameters */
809
810         if (!NT_STATUS_IS_OK(result = r.status)) {
811                 goto done;
812         }
813
814  done:
815         prs_mem_free(&qbuf);
816         prs_mem_free(&rbuf);
817
818         return result;
819 }
820
821 /* Query display info */
822
823 NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
824                                  POLICY_HND *domain_pol, uint32 *start_idx,
825                                  uint16 switch_value, uint32 *num_entries,
826                                  uint32 max_entries, SAM_DISPINFO_CTR *ctr)
827 {
828         prs_struct qbuf, rbuf;
829         SAMR_Q_QUERY_DISPINFO q;
830         SAMR_R_QUERY_DISPINFO r;
831         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
832
833         ZERO_STRUCT(q);
834         ZERO_STRUCT(r);
835
836         /* Initialise parse structures */
837
838         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
839         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
840
841         /* Marshall data and send request */
842
843         init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
844                                    *start_idx, max_entries);
845
846         if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) ||
847             !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) {
848                 goto done;
849         }
850
851         /* Unmarshall response */
852
853         r.ctr = ctr;
854
855         if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) {
856                 goto done;
857         }
858
859         /* Return output parameters */
860
861         result = r.status;
862
863         if (!NT_STATUS_IS_OK(result) &&
864             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
865                 goto done;
866         }
867
868         *num_entries = r.num_entries;
869         *start_idx += r.num_entries;  /* No next_idx in this structure! */
870
871  done:
872         prs_mem_free(&qbuf);
873         prs_mem_free(&rbuf);
874
875         return result;
876 }
877
878 /* Lookup rids.  Note that NT4 seems to crash if more than ~1000 rids are
879    looked up in one packet. */
880
881 NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
882                               POLICY_HND *domain_pol, uint32 flags,
883                               uint32 num_rids, uint32 *rids, 
884                               uint32 *num_names, char ***names,
885                               uint32 **name_types)
886 {
887         prs_struct qbuf, rbuf;
888         SAMR_Q_LOOKUP_RIDS q;
889         SAMR_R_LOOKUP_RIDS r;
890         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
891         uint32 i;
892
893         if (num_rids > 1000) {
894                 DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if "
895                           "more than ~1000 rids are looked up at once.\n"));
896         }
897
898         ZERO_STRUCT(q);
899         ZERO_STRUCT(r);
900
901         /* Initialise parse structures */
902
903         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
904         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
905
906         /* Marshall data and send request */
907
908         init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags,
909                                 num_rids, rids);
910
911         if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
912             !rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
913                 goto done;
914         }
915
916         /* Unmarshall response */
917
918         if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) {
919                 goto done;
920         }
921
922         /* Return output parameters */
923
924         if (!NT_STATUS_IS_OK(result = r.status)) {
925                 goto done;
926         }
927
928         if (r.num_names1 == 0) {
929                 *num_names = 0;
930                 *names = NULL;
931                 goto done;
932         }
933
934         *num_names = r.num_names1;
935         *names = talloc(mem_ctx, sizeof(char *) * r.num_names1);
936         *name_types = talloc(mem_ctx, sizeof(uint32) * r.num_names1);
937
938         for (i = 0; i < r.num_names1; i++) {
939                 fstring tmp;
940
941                 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp) - 1);
942                 (*names)[i] = talloc_strdup(mem_ctx, tmp);
943                 (*name_types)[i] = r.type[i];
944         }
945
946  done:
947         prs_mem_free(&qbuf);
948         prs_mem_free(&rbuf);
949
950         return result;
951 }
952
953 /* Lookup names */
954
955 NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
956                                POLICY_HND *domain_pol, uint32 flags,
957                                uint32 num_names, char **names,
958                                uint32 *num_rids, uint32 **rids,
959                                uint32 **rid_types)
960 {
961         prs_struct qbuf, rbuf;
962         SAMR_Q_LOOKUP_NAMES q;
963         SAMR_R_LOOKUP_NAMES r;
964         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
965         uint32 i;
966
967         ZERO_STRUCT(q);
968         ZERO_STRUCT(r);
969
970         /* Initialise parse structures */
971
972         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
973         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
974
975         /* Marshall data and send request */
976
977         init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags,
978                                  num_names, names);
979
980         if (!samr_io_q_lookup_names("", &q, &qbuf, 0) ||
981             !rpc_api_pipe_req(cli, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) {
982                 goto done;
983         }
984
985         /* Unmarshall response */
986
987         if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) {
988                 goto done;
989         }
990
991         /* Return output parameters */
992
993         if (!NT_STATUS_IS_OK(result = r.status)) {
994                 goto done;
995         }
996
997         if (r.num_rids1 == 0) {
998                 *num_rids = 0;
999                 goto done;
1000         }
1001
1002         *num_rids = r.num_rids1;
1003         *rids = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
1004         *rid_types = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
1005
1006         for (i = 0; i < r.num_rids1; i++) {
1007                 (*rids)[i] = r.rids[i];
1008                 (*rid_types)[i] = r.types[i];
1009         }
1010
1011  done:
1012         prs_mem_free(&qbuf);
1013         prs_mem_free(&rbuf);
1014
1015         return result;
1016 }
1017
1018 /* Create a domain user */
1019
1020 NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1021                                   POLICY_HND *domain_pol, const char *acct_name,
1022                                   uint32 acb_info, uint32 unknown, 
1023                                   POLICY_HND *user_pol, uint32 *rid)
1024 {
1025         prs_struct qbuf, rbuf;
1026         SAMR_Q_CREATE_USER q;
1027         SAMR_R_CREATE_USER r;
1028         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1029
1030         ZERO_STRUCT(q);
1031         ZERO_STRUCT(r);
1032
1033         /* Initialise parse structures */
1034
1035         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1036         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1037
1038         /* Marshall data and send request */
1039
1040         init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown);
1041
1042         if (!samr_io_q_create_user("", &q, &qbuf, 0) ||
1043             !rpc_api_pipe_req(cli, SAMR_CREATE_USER, &qbuf, &rbuf)) {
1044                 goto done;
1045         }
1046
1047         /* Unmarshall response */
1048
1049         if (!samr_io_r_create_user("", &r, &rbuf, 0)) {
1050                 goto done;
1051         }
1052
1053         /* Return output parameters */
1054
1055         if (!NT_STATUS_IS_OK(result = r.status)) {
1056                 goto done;
1057         }
1058
1059         if (user_pol)
1060                 *user_pol = r.user_pol;
1061
1062         if (rid)
1063                 *rid = r.user_rid;
1064
1065  done:
1066         prs_mem_free(&qbuf);
1067         prs_mem_free(&rbuf);
1068
1069         return result;
1070 }
1071
1072 /* Set userinfo */
1073
1074 NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1075                                POLICY_HND *user_pol, uint16 switch_value,
1076                                uchar sess_key[16], SAM_USERINFO_CTR *ctr)
1077 {
1078         prs_struct qbuf, rbuf;
1079         SAMR_Q_SET_USERINFO q;
1080         SAMR_R_SET_USERINFO r;
1081         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1082
1083         ZERO_STRUCT(q);
1084         ZERO_STRUCT(r);
1085
1086         /* Initialise parse structures */
1087
1088         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1089         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1090
1091         /* Marshall data and send request */
1092
1093         q.ctr = ctr;
1094
1095         init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, 
1096                                  ctr->info.id);
1097
1098         if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) ||
1099             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO, &qbuf, &rbuf)) {
1100                 goto done;
1101         }
1102
1103         /* Unmarshall response */
1104
1105         if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) {
1106                 goto done;
1107         }
1108
1109         /* Return output parameters */
1110
1111         if (!NT_STATUS_IS_OK(result = r.status)) {
1112                 goto done;
1113         }
1114
1115  done:
1116         prs_mem_free(&qbuf);
1117         prs_mem_free(&rbuf);
1118
1119         return result;
1120 }
1121
1122 /* Set userinfo2 */
1123
1124 NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1125                                 POLICY_HND *user_pol, uint16 switch_value,
1126                                 uchar sess_key[16], SAM_USERINFO_CTR *ctr)
1127 {
1128         prs_struct qbuf, rbuf;
1129         SAMR_Q_SET_USERINFO2 q;
1130         SAMR_R_SET_USERINFO2 r;
1131         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1132
1133         ZERO_STRUCT(q);
1134         ZERO_STRUCT(r);
1135
1136         /* Initialise parse structures */
1137
1138         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1139         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1140
1141         /* Marshall data and send request */
1142
1143         init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
1144
1145         if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) ||
1146             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO2, &qbuf, &rbuf)) {
1147                 goto done;
1148         }
1149
1150         /* Unmarshall response */
1151
1152         if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) {
1153                 goto done;
1154         }
1155
1156         /* Return output parameters */
1157
1158         if (!NT_STATUS_IS_OK(result = r.status)) {
1159                 goto done;
1160         }
1161
1162  done:
1163         prs_mem_free(&qbuf);
1164         prs_mem_free(&rbuf);
1165
1166         return result;
1167 }
1168
1169 /* Delete domain user */
1170
1171 NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1172                                   POLICY_HND *user_pol)
1173 {
1174         prs_struct qbuf, rbuf;
1175         SAMR_Q_DELETE_DOM_USER q;
1176         SAMR_R_DELETE_DOM_USER r;
1177         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1178
1179         ZERO_STRUCT(q);
1180         ZERO_STRUCT(r);
1181
1182         /* Initialise parse structures */
1183
1184         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1185         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1186
1187         /* Marshall data and send request */
1188
1189         init_samr_q_delete_dom_user(&q, user_pol);
1190
1191         if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) ||
1192             !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) {
1193                 goto done;
1194         }
1195
1196         /* Unmarshall response */
1197
1198         if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) {
1199                 goto done;
1200         }
1201
1202         /* Return output parameters */
1203
1204         result = r.status;
1205
1206  done:
1207         prs_mem_free(&qbuf);
1208         prs_mem_free(&rbuf);
1209
1210         return result;
1211 }
1212
1213 /* Query user security object */
1214
1215 NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1216                                  POLICY_HND *user_pol, uint16 switch_value, 
1217                                  TALLOC_CTX *ctx, SEC_DESC_BUF **sec_desc_buf)
1218 {
1219         prs_struct qbuf, rbuf;
1220         SAMR_Q_QUERY_SEC_OBJ q;
1221         SAMR_R_QUERY_SEC_OBJ r;
1222         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1223
1224         ZERO_STRUCT(q);
1225         ZERO_STRUCT(r);
1226
1227         /* Initialise parse structures */
1228
1229         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1230         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1231
1232         /* Marshall data and send request */
1233
1234         init_samr_q_query_sec_obj(&q, user_pol, switch_value);
1235
1236         if (!samr_io_q_query_sec_obj("", &q, &qbuf, 0) ||
1237             !rpc_api_pipe_req(cli, SAMR_QUERY_SEC_OBJECT, &qbuf, &rbuf)) {
1238                 goto done;
1239         }
1240
1241         /* Unmarshall response */
1242
1243         if (!samr_io_r_query_sec_obj("", &r, &rbuf, 0)) {
1244                 goto done;
1245         }
1246
1247         /* Return output parameters */
1248
1249         result = r.status;
1250         *sec_desc_buf=dup_sec_desc_buf(ctx, r.buf);
1251
1252  done:
1253         prs_mem_free(&qbuf);
1254         prs_mem_free(&rbuf);
1255
1256         return result;
1257 }