Added a warning debug if cli_samr_lookup_rids is called with more than 1000
[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         struct in_addr dest_ip;
34         struct nmb_name calling, called;
35         fstring dest_host;
36         extern pstring global_myname;
37         struct ntuser_creds anon;
38
39         /* Initialise cli_state information */
40
41         if (!cli_initialise(cli)) {
42                 return NULL;
43         }
44
45         if (!creds) {
46                 ZERO_STRUCT(anon);
47                 anon.pwd.null_pwd = 1;
48                 creds = &anon;
49         }
50
51         cli_init_creds(cli, creds);
52
53         /* Establish a SMB connection */
54
55         if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
56                 return NULL;
57         }
58
59         make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
60         make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
61
62         if (!cli_establish_connection(cli, dest_host, &dest_ip, &calling, 
63                                       &called, "IPC$", "IPC", False, True)) {
64                 return NULL;
65         }
66
67         /* Open a NT session thingy */
68
69         if (!cli_nt_session_open(cli, PIPE_SAMR)) {
70                 cli_shutdown(cli);
71                 return NULL;
72         }
73
74         return cli;
75 }
76
77 /* Shut down a SMB connection to the SAMR pipe */
78
79 void cli_samr_shutdown(struct cli_state *cli)
80 {
81         if (cli->fd != -1) cli_ulogoff(cli);
82         cli_shutdown(cli);
83 }
84
85 /* Connect to SAMR database */
86
87 uint32 cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
88                         uint32 access_mask, POLICY_HND *connect_pol)
89 {
90         prs_struct qbuf, rbuf;
91         SAMR_Q_CONNECT q;
92         SAMR_R_CONNECT r;
93         uint32 result = NT_STATUS_UNSUCCESSFUL;
94
95         ZERO_STRUCT(q);
96         ZERO_STRUCT(r);
97
98         /* Initialise parse structures */
99
100         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
101         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
102
103         /* Marshall data and send request */
104
105         init_samr_q_connect(&q, cli->desthost, access_mask);
106
107         if (!samr_io_q_connect("", &q, &qbuf, 0) ||
108             !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) {
109                 goto done;
110         }
111
112         /* Unmarshall response */
113
114         if (!samr_io_r_connect("", &r, &rbuf, 0)) {
115                 goto done;
116         }
117
118         /* Return output parameters */
119
120         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
121                 *connect_pol = r.connect_pol;
122         }
123
124  done:
125         prs_mem_free(&qbuf);
126         prs_mem_free(&rbuf);
127
128         return result;
129 }
130
131 /* Close SAMR handle */
132
133 uint32 cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
134                       POLICY_HND *connect_pol)
135 {
136         prs_struct qbuf, rbuf;
137         SAMR_Q_CLOSE_HND q;
138         SAMR_R_CLOSE_HND r;
139         uint32 result = NT_STATUS_UNSUCCESSFUL;
140
141         ZERO_STRUCT(q);
142         ZERO_STRUCT(r);
143
144         /* Initialise parse structures */
145
146         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
147         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
148
149         /* Marshall data and send request */
150
151         init_samr_q_close_hnd(&q, connect_pol);
152
153         if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
154             !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) {
155                 goto done;
156         }
157
158         /* Unmarshall response */
159
160         if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) {
161                 goto done;
162         }
163
164         /* Return output parameters */
165
166         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
167                 *connect_pol = r.pol;
168         }
169
170  done:
171         prs_mem_free(&qbuf);
172         prs_mem_free(&rbuf);
173
174         return result;
175 }
176
177 /* Open handle on a domain */
178
179 uint32 cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
180                             POLICY_HND *connect_pol, uint32 access_mask, 
181                             DOM_SID *domain_sid, POLICY_HND *domain_pol)
182 {
183         prs_struct qbuf, rbuf;
184         SAMR_Q_OPEN_DOMAIN q;
185         SAMR_R_OPEN_DOMAIN r;
186         uint32 result = NT_STATUS_UNSUCCESSFUL;
187
188         ZERO_STRUCT(q);
189         ZERO_STRUCT(r);
190
191         /* Initialise parse structures */
192
193         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
194         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
195
196         /* Marshall data and send request */
197
198         init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid);
199
200         if (!samr_io_q_open_domain("", &q, &qbuf, 0) ||
201             !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) {
202                 goto done;
203         }
204
205         /* Unmarshall response */
206
207         if (!samr_io_r_open_domain("", &r, &rbuf, 0)) {
208                 goto done;
209         }
210
211         /* Return output parameters */
212
213         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
214                 *domain_pol = r.domain_pol;
215         }
216
217  done:
218         prs_mem_free(&qbuf);
219         prs_mem_free(&rbuf);
220
221         return result;
222 }
223
224 /* Open handle on a user */
225
226 uint32 cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
227                           POLICY_HND *domain_pol, uint32 access_mask, 
228                           uint32 user_rid, POLICY_HND *user_pol)
229 {
230         prs_struct qbuf, rbuf;
231         SAMR_Q_OPEN_USER q;
232         SAMR_R_OPEN_USER r;
233         uint32 result = NT_STATUS_UNSUCCESSFUL;
234
235         ZERO_STRUCT(q);
236         ZERO_STRUCT(r);
237
238         /* Initialise parse structures */
239
240         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
241         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
242
243         /* Marshall data and send request */
244
245         init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
246
247         if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
248             !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) {
249                 goto done;
250         }
251
252         /* Unmarshall response */
253
254         if (!samr_io_r_open_user("", &r, &rbuf, 0)) {
255                 goto done;
256         }
257
258         /* Return output parameters */
259
260         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
261                 *user_pol = r.user_pol;
262         }
263
264  done:
265         prs_mem_free(&qbuf);
266         prs_mem_free(&rbuf);
267
268         return result;
269 }
270
271 /* Open handle on a group */
272
273 uint32 cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
274                            POLICY_HND *domain_pol, uint32 access_mask, 
275                            uint32 group_rid, POLICY_HND *group_pol)
276 {
277         prs_struct qbuf, rbuf;
278         SAMR_Q_OPEN_GROUP q;
279         SAMR_R_OPEN_GROUP r;
280         uint32 result =  NT_STATUS_UNSUCCESSFUL;
281
282         ZERO_STRUCT(q);
283         ZERO_STRUCT(r);
284
285         /* Initialise parse structures */
286
287         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
288         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
289
290         /* Marshall data and send request */
291
292         init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
293
294         if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
295             !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) {
296                 goto done;
297         }
298
299         /* Unmarshall response */
300
301         if (!samr_io_r_open_group("", &r, &rbuf, 0)) {
302                 goto done;
303         }
304
305         /* Return output parameters */
306
307         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
308                 *group_pol = r.pol;
309         }
310
311  done:
312         prs_mem_free(&qbuf);
313         prs_mem_free(&rbuf);
314
315         return result;
316 }
317
318 /* Query user info */
319
320 uint32 cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
321                                POLICY_HND *user_pol, uint16 switch_value, 
322                                SAM_USERINFO_CTR **ctr)
323 {
324         prs_struct qbuf, rbuf;
325         SAMR_Q_QUERY_USERINFO q;
326         SAMR_R_QUERY_USERINFO r;
327         uint32 result = NT_STATUS_UNSUCCESSFUL;
328
329         ZERO_STRUCT(q);
330         ZERO_STRUCT(r);
331
332         /* Initialise parse structures */
333
334         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
335         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
336
337         /* Marshall data and send request */
338
339         init_samr_q_query_userinfo(&q, user_pol, switch_value);
340
341         if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
342             !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) {
343                 goto done;
344         }
345
346         /* Unmarshall response */
347
348         if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) {
349                 goto done;
350         }
351
352         /* Return output parameters */
353
354         result = r.status;
355         *ctr = r.ctr;
356
357  done:
358         prs_mem_free(&qbuf);
359         prs_mem_free(&rbuf);
360
361         return result;
362 }
363
364 /* Query group info */
365
366 uint32 cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
367                                 POLICY_HND *group_pol, uint32 info_level, 
368                                 GROUP_INFO_CTR *ctr)
369 {
370         prs_struct qbuf, rbuf;
371         SAMR_Q_QUERY_GROUPINFO q;
372         SAMR_R_QUERY_GROUPINFO r;
373         uint32 result = NT_STATUS_UNSUCCESSFUL;
374
375         ZERO_STRUCT(q);
376         ZERO_STRUCT(r);
377
378         /* Initialise parse structures */
379
380         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
381         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
382
383         /* Marshall data and send request */
384
385         init_samr_q_query_groupinfo(&q, group_pol, info_level);
386
387         if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
388             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) {
389                 goto done;
390         }
391
392         /* Unmarshall response */
393
394         r.ctr = ctr;
395
396         if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) {
397                 goto done;
398         }
399
400         /* Return output parameters */
401
402         result = r.status;
403
404  done:
405         prs_mem_free(&qbuf);
406         prs_mem_free(&rbuf);
407
408         return result;
409 }
410
411 /* Query user groups */
412
413 uint32 cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
414                                  POLICY_HND *user_pol, uint32 *num_groups, 
415                                  DOM_GID **gid)
416 {
417         prs_struct qbuf, rbuf;
418         SAMR_Q_QUERY_USERGROUPS q;
419         SAMR_R_QUERY_USERGROUPS r;
420         uint32 result = NT_STATUS_UNSUCCESSFUL;
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_usergroups(&q, user_pol);
433
434         if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
435             !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) {
436                 goto done;
437         }
438
439         /* Unmarshall response */
440
441         if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) {
442                 goto done;
443         }
444
445         /* Return output parameters */
446
447         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
448                 *num_groups = r.num_entries;
449                 *gid = r.gid;
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 uint32 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         uint32 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 ((result = r.status) == NT_STATUS_NOPROBLEMO) {
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 uint32 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         uint32 result = NT_STATUS_UNSUCCESSFUL, name_idx, i;
519
520         ZERO_STRUCT(q);
521         ZERO_STRUCT(r);
522
523         /* Initialise parse structures */
524
525         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
526         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
527
528         /* Marshall data and send request */
529
530         init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
531
532         if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
533             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) {
534                 goto done;
535         }
536
537         /* Unmarshall response */
538
539         if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) {
540                 goto done;
541         }
542
543         /* Return output parameters */
544
545         result = r.status;
546
547         if (result != NT_STATUS_NOPROBLEMO &&
548             result != STATUS_MORE_ENTRIES) {
549                 goto done;
550         }
551
552         *num_dom_groups = r.num_entries2;
553
554         if (!((*dom_groups) = (struct acct_info *)
555               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
556                 result = NT_STATUS_UNSUCCESSFUL;
557                 goto done;
558         }
559
560         memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups);
561
562         name_idx = 0;
563
564         for (i = 0; i < *num_dom_groups; i++) {
565
566                 (*dom_groups)[i].rid = r.sam[i].rid;
567
568                 if (r.sam[i].hdr_name.buffer) {
569                         unistr2_to_ascii((*dom_groups)[i].acct_name,
570                                          &r.uni_grp_name[name_idx],
571                                          sizeof(fstring) - 1);
572                         name_idx++;
573                 }
574
575                 *start_idx = r.next_idx;
576         }
577
578  done:
579         prs_mem_free(&qbuf);
580         prs_mem_free(&rbuf);
581
582         return result;
583 }
584
585 /* Query alias members */
586
587 uint32 cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
588                                POLICY_HND *alias_pol, uint32 *num_mem, 
589                                DOM_SID **sids)
590 {
591         prs_struct qbuf, rbuf;
592         SAMR_Q_QUERY_ALIASMEM q;
593         SAMR_R_QUERY_ALIASMEM r;
594         uint32 result = NT_STATUS_UNSUCCESSFUL, i;
595
596         ZERO_STRUCT(q);
597         ZERO_STRUCT(r);
598
599         /* Initialise parse structures */
600
601         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
602         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
603
604         /* Marshall data and send request */
605
606         init_samr_q_query_aliasmem(&q, alias_pol);
607
608         if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
609             !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
610                 goto done;
611         }
612
613         /* Unmarshall response */
614
615         if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
616                 goto done;
617         }
618
619         /* Return output parameters */
620
621         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
622                 goto done;
623         }
624
625         *num_mem = r.num_sids;
626
627         if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) {
628                 result = NT_STATUS_UNSUCCESSFUL;
629                 goto done;
630         }
631
632         for (i = 0; i < *num_mem; i++) {
633                 (*sids)[i] = r.sid[i].sid;
634         }
635
636  done:
637         prs_mem_free(&qbuf);
638         prs_mem_free(&rbuf);
639
640         return result;
641 }
642
643 /* Open handle on an alias */
644
645 uint32 cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
646                            POLICY_HND *domain_pol, uint32 access_mask, 
647                            uint32 alias_rid, POLICY_HND *alias_pol)
648 {
649         prs_struct qbuf, rbuf;
650         SAMR_Q_OPEN_ALIAS q;
651         SAMR_R_OPEN_ALIAS r;
652         uint32 result;
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_open_alias(&q, domain_pol, access_mask, alias_rid);
665
666         if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
667             !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
668                 result = NT_STATUS_UNSUCCESSFUL;
669                 goto done;
670         }
671
672         /* Unmarshall response */
673
674         if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
675                 result = NT_STATUS_UNSUCCESSFUL;
676                 goto done;
677         }
678
679         /* Return output parameters */
680
681         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
682                 *alias_pol = r.pol;
683         }
684
685  done:
686         prs_mem_free(&qbuf);
687         prs_mem_free(&rbuf);
688
689         return result;
690 }
691
692 /* Query domain info */
693
694 uint32 cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
695                                POLICY_HND *domain_pol, uint16 switch_value,
696                                SAM_UNK_CTR *ctr)
697 {
698         prs_struct qbuf, rbuf;
699         SAMR_Q_QUERY_DOMAIN_INFO q;
700         SAMR_R_QUERY_DOMAIN_INFO r;
701         uint32 result = NT_STATUS_UNSUCCESSFUL;
702
703         ZERO_STRUCT(q);
704         ZERO_STRUCT(r);
705
706         /* Initialise parse structures */
707
708         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
709         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
710
711         /* Marshall data and send request */
712
713         init_samr_q_query_dom_info(&q, domain_pol, switch_value);
714
715         if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) ||
716             !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) {
717                 goto done;
718         }
719
720         /* Unmarshall response */
721
722         r.ctr = ctr;
723
724         if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) {
725                 goto done;
726         }
727
728         /* Return output parameters */
729
730         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
731                 goto done;
732         }
733
734  done:
735         prs_mem_free(&qbuf);
736         prs_mem_free(&rbuf);
737
738         return result;
739 }
740
741 /* Query display info */
742
743 uint32 cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
744                                POLICY_HND *domain_pol, uint32 *start_idx,
745                                uint16 switch_value, uint32 *num_entries,
746                                uint32 max_entries, SAM_DISPINFO_CTR *ctr)
747 {
748         prs_struct qbuf, rbuf;
749         SAMR_Q_QUERY_DISPINFO q;
750         SAMR_R_QUERY_DISPINFO r;
751         uint32 result = NT_STATUS_UNSUCCESSFUL;
752
753         ZERO_STRUCT(q);
754         ZERO_STRUCT(r);
755
756         /* Initialise parse structures */
757
758         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
759         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
760
761         /* Marshall data and send request */
762
763         init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
764                                    *start_idx, max_entries);
765
766         if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) ||
767             !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) {
768                 goto done;
769         }
770
771         /* Unmarshall response */
772
773         r.ctr = ctr;
774
775         if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) {
776                 goto done;
777         }
778
779         /* Return output parameters */
780
781         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
782                 goto done;
783         }
784
785         *num_entries = r.num_entries;
786         *start_idx += r.num_entries;  /* No next_idx in this structure! */
787
788  done:
789         prs_mem_free(&qbuf);
790         prs_mem_free(&rbuf);
791
792         return result;
793 }
794
795 /* Lookup rids.  Note that NT4 seems to crash if more than ~1000 rids are
796    looked up in one packet. */
797
798 uint32 cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
799                             POLICY_HND *domain_pol, uint32 flags,
800                             uint32 num_rids, uint32 *rids, 
801                             uint32 *num_names, char ***names,
802                             uint32 **name_types)
803 {
804         prs_struct qbuf, rbuf;
805         SAMR_Q_LOOKUP_RIDS q;
806         SAMR_R_LOOKUP_RIDS r;
807         uint32 result = NT_STATUS_UNSUCCESSFUL, i;
808
809         if (num_rids > 1000) {
810                 DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if "
811                           "more than ~1000 rids are looked up at once.\n"));
812         }
813
814         ZERO_STRUCT(q);
815         ZERO_STRUCT(r);
816
817         /* Initialise parse structures */
818
819         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
820         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
821
822         /* Marshall data and send request */
823
824         init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags,
825                                 num_rids, rids);
826
827         if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
828             !rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
829                 goto done;
830         }
831
832         /* Unmarshall response */
833
834         if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) {
835                 goto done;
836         }
837
838         /* Return output parameters */
839
840         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
841                 goto done;
842         }
843
844         if (r.num_names1 == 0) {
845                 *num_names = 0;
846                 *names = NULL;
847                 goto done;
848         }
849
850         *num_names = r.num_names1;
851         *names = talloc(mem_ctx, sizeof(char *) * r.num_names1);
852         *name_types = talloc(mem_ctx, sizeof(uint32) * r.num_names1);
853
854         for (i = 0; i < r.num_names1; i++) {
855                 fstring tmp;
856
857                 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp) - 1);
858                 (*names)[i] = talloc_strdup(mem_ctx, tmp);
859                 (*name_types)[i] = r.type[i];
860         }
861
862  done:
863         prs_mem_free(&qbuf);
864         prs_mem_free(&rbuf);
865
866         return result;
867 }
868
869 /* Lookup names */
870
871 uint32 cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
872                              POLICY_HND *domain_pol, uint32 flags,
873                              uint32 num_names, char **names,
874                              uint32 *num_rids, uint32 **rids,
875                              uint32 **rid_types)
876 {
877         prs_struct qbuf, rbuf;
878         SAMR_Q_LOOKUP_NAMES q;
879         SAMR_R_LOOKUP_NAMES r;
880         uint32 result = NT_STATUS_UNSUCCESSFUL, i;
881
882         ZERO_STRUCT(q);
883         ZERO_STRUCT(r);
884
885         /* Initialise parse structures */
886
887         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
888         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
889
890         /* Marshall data and send request */
891
892         init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags,
893                                  num_names, names);
894
895         if (!samr_io_q_lookup_names("", &q, &qbuf, 0) ||
896             !rpc_api_pipe_req(cli, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) {
897                 goto done;
898         }
899
900         /* Unmarshall response */
901
902         if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) {
903                 goto done;
904         }
905
906         /* Return output parameters */
907
908         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
909                 goto done;
910         }
911
912         if (r.num_rids1 == 0) {
913                 *num_rids = 0;
914                 goto done;
915         }
916
917         *num_rids = r.num_rids1;
918         *rids = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
919         *rid_types = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
920
921         for (i = 0; i < r.num_rids1; i++) {
922                 (*rids)[i] = r.rids[i];
923                 (*rid_types)[i] = r.types[i];
924         }
925
926  done:
927         prs_mem_free(&qbuf);
928         prs_mem_free(&rbuf);
929
930         return result;
931 }
932
933 /* Create a domain user */
934
935 uint32 cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
936                                 POLICY_HND *domain_pol, char *acct_name,
937                                 uint32 acb_info, uint32 unknown, 
938                                 POLICY_HND *user_pol, uint32 *rid)
939 {
940         prs_struct qbuf, rbuf;
941         SAMR_Q_CREATE_USER q;
942         SAMR_R_CREATE_USER r;
943         uint32 result = NT_STATUS_UNSUCCESSFUL;
944
945         ZERO_STRUCT(q);
946         ZERO_STRUCT(r);
947
948         /* Initialise parse structures */
949
950         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
951         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
952
953         /* Marshall data and send request */
954
955         init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown);
956
957         if (!samr_io_q_create_user("", &q, &qbuf, 0) ||
958             !rpc_api_pipe_req(cli, SAMR_CREATE_USER, &qbuf, &rbuf)) {
959                 goto done;
960         }
961
962         /* Unmarshall response */
963
964         if (!samr_io_r_create_user("", &r, &rbuf, 0)) {
965                 goto done;
966         }
967
968         /* Return output parameters */
969
970         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
971                 goto done;
972         }
973
974         if (user_pol)
975                 *user_pol = r.user_pol;
976
977         if (rid)
978                 *rid = r.user_rid;
979
980  done:
981         prs_mem_free(&qbuf);
982         prs_mem_free(&rbuf);
983
984         return result;
985 }
986
987 /* Set userinfo */
988
989 uint32 cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
990                              POLICY_HND *user_pol, uint16 switch_value,
991                              uchar sess_key[16], SAM_USERINFO_CTR *ctr)
992 {
993         prs_struct qbuf, rbuf;
994         SAMR_Q_SET_USERINFO q;
995         SAMR_R_SET_USERINFO r;
996         uint32 result = NT_STATUS_UNSUCCESSFUL;
997
998         ZERO_STRUCT(q);
999         ZERO_STRUCT(r);
1000
1001         /* Initialise parse structures */
1002
1003         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1004         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1005
1006         /* Marshall data and send request */
1007
1008         q.ctr = ctr;
1009
1010         init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, 
1011                                  ctr->info.id);
1012
1013         if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) ||
1014             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO, &qbuf, &rbuf)) {
1015                 goto done;
1016         }
1017
1018         /* Unmarshall response */
1019
1020         if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) {
1021                 goto done;
1022         }
1023
1024         /* Return output parameters */
1025
1026         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
1027                 goto done;
1028         }
1029
1030  done:
1031         prs_mem_free(&qbuf);
1032         prs_mem_free(&rbuf);
1033
1034         return result;
1035 }
1036
1037 /* Set userinfo2 */
1038
1039 uint32 cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1040                               POLICY_HND *user_pol, uint16 switch_value,
1041                               uchar sess_key[16], SAM_USERINFO_CTR *ctr)
1042 {
1043         prs_struct qbuf, rbuf;
1044         SAMR_Q_SET_USERINFO2 q;
1045         SAMR_R_SET_USERINFO2 r;
1046         uint32 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_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
1059
1060         if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) ||
1061             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO2, &qbuf, &rbuf)) {
1062                 goto done;
1063         }
1064
1065         /* Unmarshall response */
1066
1067         if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) {
1068                 goto done;
1069         }
1070
1071         /* Return output parameters */
1072
1073         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
1074                 goto done;
1075         }
1076
1077  done:
1078         prs_mem_free(&qbuf);
1079         prs_mem_free(&rbuf);
1080
1081         return result;
1082 }
1083
1084 /* Delete domain user */
1085
1086 uint32 cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1087                                 POLICY_HND *user_pol)
1088 {
1089         prs_struct qbuf, rbuf;
1090         SAMR_Q_DELETE_DOM_USER q;
1091         SAMR_R_DELETE_DOM_USER r;
1092         uint32 result = NT_STATUS_UNSUCCESSFUL;
1093
1094         ZERO_STRUCT(q);
1095         ZERO_STRUCT(r);
1096
1097         /* Initialise parse structures */
1098
1099         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1100         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1101
1102         /* Marshall data and send request */
1103
1104         init_samr_q_delete_dom_user(&q, user_pol);
1105
1106         if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) ||
1107             !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) {
1108                 goto done;
1109         }
1110
1111         /* Unmarshall response */
1112
1113         if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) {
1114                 goto done;
1115         }
1116
1117         /* Return output parameters */
1118
1119         result = r.status;
1120
1121  done:
1122         prs_mem_free(&qbuf);
1123         prs_mem_free(&rbuf);
1124
1125         return result;
1126 }