RPC fix from Ronan Waide <waider@waider.ie>. Tested with rpcecho.
[tprouty/samba.git] / source / rpc_client / cli_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4    Copyright (C) Tim Potter                        2000-2001,
5    Copyright (C) Andrew Tridgell              1992-1997,2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
7    Copyright (C) Paul Ashton                       1997,2000,
8    Copyright (C) Elrond                                 2000,
9    Copyright (C) Rafal Szczesniak                       2002.
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 /* Connect to SAMR database */
29
30 NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
31                           uint32 access_mask, POLICY_HND *connect_pol)
32 {
33         prs_struct qbuf, rbuf;
34         SAMR_Q_CONNECT q;
35         SAMR_R_CONNECT r;
36         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
37
38         DEBUG(10,("cli_samr_connect to %s\n", cli->desthost));
39
40         ZERO_STRUCT(q);
41         ZERO_STRUCT(r);
42
43         /* Initialise parse structures */
44
45         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
46         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
47
48         /* Marshall data and send request */
49
50         init_samr_q_connect(&q, cli->desthost, access_mask);
51
52         if (!samr_io_q_connect("", &q, &qbuf, 0) ||
53             !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf))
54                 goto done;
55
56         /* Unmarshall response */
57
58         if (!samr_io_r_connect("", &r, &rbuf, 0))
59                 goto done;
60
61         /* Return output parameters */
62
63         if (NT_STATUS_IS_OK(result = r.status)) {
64                 *connect_pol = r.connect_pol;
65 #ifdef __INSURE__
66                 connect_pol->marker = malloc(1);
67 #endif
68         }
69
70  done:
71         prs_mem_free(&qbuf);
72         prs_mem_free(&rbuf);
73
74         return result;
75 }
76
77 /* Connect to SAMR database */
78
79 NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
80                            uint32 access_mask, POLICY_HND *connect_pol)
81 {
82         prs_struct qbuf, rbuf;
83         SAMR_Q_CONNECT4 q;
84         SAMR_R_CONNECT4 r;
85         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
86
87         DEBUG(10,("cli_samr_connect4 to %s\n", cli->desthost));
88
89         ZERO_STRUCT(q);
90         ZERO_STRUCT(r);
91
92         /* Initialise parse structures */
93
94         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
95         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
96
97         /* Marshall data and send request */
98
99         init_samr_q_connect4(&q, cli->desthost, access_mask);
100
101         if (!samr_io_q_connect4("", &q, &qbuf, 0) ||
102             !rpc_api_pipe_req(cli, SAMR_CONNECT4, &qbuf, &rbuf))
103                 goto done;
104
105         /* Unmarshall response */
106
107         if (!samr_io_r_connect4("", &r, &rbuf, 0))
108                 goto done;
109
110         /* Return output parameters */
111
112         if (NT_STATUS_IS_OK(result = r.status)) {
113                 *connect_pol = r.connect_pol;
114 #ifdef __INSURE__
115                 connect_pol->marker = malloc(1);
116 #endif
117         }
118
119  done:
120         prs_mem_free(&qbuf);
121         prs_mem_free(&rbuf);
122
123         return result;
124 }
125
126 /* Close SAMR handle */
127
128 NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
129                         POLICY_HND *connect_pol)
130 {
131         prs_struct qbuf, rbuf;
132         SAMR_Q_CLOSE_HND q;
133         SAMR_R_CLOSE_HND r;
134         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
135
136         DEBUG(10,("cli_samr_close\n"));
137
138         ZERO_STRUCT(q);
139         ZERO_STRUCT(r);
140
141         /* Initialise parse structures */
142
143         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
144         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
145
146         /* Marshall data and send request */
147
148         init_samr_q_close_hnd(&q, connect_pol);
149
150         if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
151             !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf))
152                 goto done;
153
154         /* Unmarshall response */
155
156         if (!samr_io_r_close_hnd("", &r, &rbuf, 0))
157                 goto done;
158
159         /* Return output parameters */
160
161         if (NT_STATUS_IS_OK(result = r.status)) {
162 #ifdef __INSURE__
163                 SAFE_FREE(connect_pol->marker);
164 #endif
165                 *connect_pol = r.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 domain */
176
177 NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
178                               POLICY_HND *connect_pol, uint32 access_mask, 
179                               const DOM_SID *domain_sid, POLICY_HND *domain_pol)
180 {
181         prs_struct qbuf, rbuf;
182         SAMR_Q_OPEN_DOMAIN q;
183         SAMR_R_OPEN_DOMAIN r;
184         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
185
186         DEBUG(10,("cli_samr_open_domain with sid %s\n", sid_string_static(domain_sid) ));
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         /* Unmarshall response */
205
206         if (!samr_io_r_open_domain("", &r, &rbuf, 0))
207                 goto done;
208
209         /* Return output parameters */
210
211         if (NT_STATUS_IS_OK(result = r.status)) {
212                 *domain_pol = r.domain_pol;
213 #ifdef __INSURE__
214                 domain_pol->marker = malloc(1);
215 #endif
216         }
217
218  done:
219         prs_mem_free(&qbuf);
220         prs_mem_free(&rbuf);
221
222         return result;
223 }
224
225 /* Open handle on a user */
226
227 NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
228                             POLICY_HND *domain_pol, uint32 access_mask, 
229                             uint32 user_rid, POLICY_HND *user_pol)
230 {
231         prs_struct qbuf, rbuf;
232         SAMR_Q_OPEN_USER q;
233         SAMR_R_OPEN_USER r;
234         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
235
236         DEBUG(10,("cli_samr_open_user with rid 0x%x\n", user_rid ));
237
238         ZERO_STRUCT(q);
239         ZERO_STRUCT(r);
240
241         /* Initialise parse structures */
242
243         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
244         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
245
246         /* Marshall data and send request */
247
248         init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
249
250         if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
251             !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf))
252                 goto done;
253
254         /* Unmarshall response */
255
256         if (!samr_io_r_open_user("", &r, &rbuf, 0))
257                 goto done;
258
259         /* Return output parameters */
260
261         if (NT_STATUS_IS_OK(result = r.status)) {
262                 *user_pol = r.user_pol;
263 #ifdef __INSURE__
264                 user_pol->marker = malloc(1);
265 #endif
266         }
267
268  done:
269         prs_mem_free(&qbuf);
270         prs_mem_free(&rbuf);
271
272         return result;
273 }
274
275 /* Open handle on a group */
276
277 NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
278                              POLICY_HND *domain_pol, uint32 access_mask, 
279                              uint32 group_rid, POLICY_HND *group_pol)
280 {
281         prs_struct qbuf, rbuf;
282         SAMR_Q_OPEN_GROUP q;
283         SAMR_R_OPEN_GROUP r;
284         NTSTATUS result =  NT_STATUS_UNSUCCESSFUL;
285
286         DEBUG(10,("cli_samr_open_group with rid 0x%x\n", group_rid ));
287
288         ZERO_STRUCT(q);
289         ZERO_STRUCT(r);
290
291         /* Initialise parse structures */
292
293         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
294         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
295
296         /* Marshall data and send request */
297
298         init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
299
300         if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
301             !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf))
302                 goto done;
303
304         /* Unmarshall response */
305
306         if (!samr_io_r_open_group("", &r, &rbuf, 0))
307                 goto done;
308
309         /* Return output parameters */
310
311         if (NT_STATUS_IS_OK(result = r.status)) {
312                 *group_pol = r.pol;
313 #ifdef __INSURE__
314                 group_pol->marker = malloc(1);
315 #endif
316         }
317
318  done:
319         prs_mem_free(&qbuf);
320         prs_mem_free(&rbuf);
321
322         return result;
323 }
324
325 /* Query user info */
326
327 NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
328                                  POLICY_HND *user_pol, uint16 switch_value, 
329                                  SAM_USERINFO_CTR **ctr)
330 {
331         prs_struct qbuf, rbuf;
332         SAMR_Q_QUERY_USERINFO q;
333         SAMR_R_QUERY_USERINFO r;
334         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
335
336         DEBUG(10,("cli_samr_query_userinfo\n"));
337
338         ZERO_STRUCT(q);
339         ZERO_STRUCT(r);
340
341         /* Initialise parse structures */
342
343         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
344         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
345
346         /* Marshall data and send request */
347
348         init_samr_q_query_userinfo(&q, user_pol, switch_value);
349
350         if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
351             !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf))
352                 goto done;
353
354         /* Unmarshall response */
355
356         if (!samr_io_r_query_userinfo("", &r, &rbuf, 0))
357                 goto done;
358
359         /* Return output parameters */
360
361         result = r.status;
362         *ctr = r.ctr;
363
364  done:
365         prs_mem_free(&qbuf);
366         prs_mem_free(&rbuf);
367
368         return result;
369 }
370
371 /* Query group info */
372
373 NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
374                                   POLICY_HND *group_pol, uint32 info_level, 
375                                   GROUP_INFO_CTR **ctr)
376 {
377         prs_struct qbuf, rbuf;
378         SAMR_Q_QUERY_GROUPINFO q;
379         SAMR_R_QUERY_GROUPINFO r;
380         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
381
382         DEBUG(10,("cli_samr_query_groupinfo\n"));
383
384         ZERO_STRUCT(q);
385         ZERO_STRUCT(r);
386
387         /* Initialise parse structures */
388
389         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
390         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
391
392         /* Marshall data and send request */
393
394         init_samr_q_query_groupinfo(&q, group_pol, info_level);
395
396         if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
397             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf))
398                 goto done;
399
400         /* Unmarshall response */
401
402         if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0))
403                 goto done;
404
405         *ctr = r.ctr;
406
407         /* Return output parameters */
408
409         result = r.status;
410
411  done:
412         prs_mem_free(&qbuf);
413         prs_mem_free(&rbuf);
414
415         return result;
416 }
417
418 /* Query user groups */
419
420 NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
421                                    POLICY_HND *user_pol, uint32 *num_groups, 
422                                    DOM_GID **gid)
423 {
424         prs_struct qbuf, rbuf;
425         SAMR_Q_QUERY_USERGROUPS q;
426         SAMR_R_QUERY_USERGROUPS r;
427         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
428
429         DEBUG(10,("cli_samr_query_usergroups\n"));
430
431         ZERO_STRUCT(q);
432         ZERO_STRUCT(r);
433
434         /* Initialise parse structures */
435
436         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
437         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
438
439         /* Marshall data and send request */
440
441         init_samr_q_query_usergroups(&q, user_pol);
442
443         if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
444             !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf))
445                 goto done;
446
447         /* Unmarshall response */
448
449         if (!samr_io_r_query_usergroups("", &r, &rbuf, 0))
450                 goto done;
451
452         /* Return output parameters */
453
454         if (NT_STATUS_IS_OK(result = r.status)) {
455                 *num_groups = r.num_entries;
456                 *gid = r.gid;
457         }
458
459  done:
460         prs_mem_free(&qbuf);
461         prs_mem_free(&rbuf);
462
463         return result;
464 }
465
466 /* Query user aliases */
467
468 NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
469                                    POLICY_HND *user_pol, uint32 num_sids, DOM_SID2 *sid,
470                                    uint32 *num_aliases, uint32 **als_rids)
471 {
472         prs_struct qbuf, rbuf;
473         SAMR_Q_QUERY_USERALIASES q;
474         SAMR_R_QUERY_USERALIASES r;
475         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
476         unsigned int ptr=1;
477         
478         DEBUG(10,("cli_samr_query_useraliases\n"));
479
480         ZERO_STRUCT(q);
481         ZERO_STRUCT(r);
482
483         /* Initialise parse structures */
484
485         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
486         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
487
488         /* Marshall data and send request */
489
490         init_samr_q_query_useraliases(&q, user_pol, num_sids, &ptr, sid);
491
492         if (!samr_io_q_query_useraliases("", &q, &qbuf, 0) ||
493             !rpc_api_pipe_req(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf))
494                 goto done;
495
496         /* Unmarshall response */
497
498         if (!samr_io_r_query_useraliases("", &r, &rbuf, 0))
499                 goto done;
500
501         /* Return output parameters */
502
503         if (NT_STATUS_IS_OK(result = r.status)) {
504                 *num_aliases = r.num_entries;
505                 *als_rids = r.rid;
506         }
507
508  done:
509         prs_mem_free(&qbuf);
510         prs_mem_free(&rbuf);
511
512         return result;
513 }
514
515 /* Query user groups */
516
517 NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
518                                  POLICY_HND *group_pol, uint32 *num_mem, 
519                                  uint32 **rid, uint32 **attr)
520 {
521         prs_struct qbuf, rbuf;
522         SAMR_Q_QUERY_GROUPMEM q;
523         SAMR_R_QUERY_GROUPMEM r;
524         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
525
526         DEBUG(10,("cli_samr_query_groupmem\n"));
527
528         ZERO_STRUCT(q);
529         ZERO_STRUCT(r);
530
531         /* Initialise parse structures */
532
533         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
534         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
535
536         /* Marshall data and send request */
537
538         init_samr_q_query_groupmem(&q, group_pol);
539
540         if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
541             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf))
542                 goto done;
543
544         /* Unmarshall response */
545
546         if (!samr_io_r_query_groupmem("", &r, &rbuf, 0))
547                 goto done;
548
549         /* Return output parameters */
550
551         if (NT_STATUS_IS_OK(result = r.status)) {
552                 *num_mem = r.num_entries;
553                 *rid = r.rid;
554                 *attr = r.attr;
555         }
556
557  done:
558         prs_mem_free(&qbuf);
559         prs_mem_free(&rbuf);
560
561         return result;
562 }
563
564 /**
565  * Enumerate domain users
566  *
567  * @param cli client state structure
568  * @param mem_ctx talloc context
569  * @param pol opened domain policy handle
570  * @param start_idx starting index of enumeration, returns context for
571                     next enumeration
572  * @param acb_mask account control bit mask (to enumerate some particular
573  *                 kind of accounts)
574  * @param size max acceptable size of response
575  * @param dom_users returned array of domain user names
576  * @param rids returned array of domain user RIDs
577  * @param num_dom_users numer returned entries
578  * 
579  * @return NTSTATUS returned in rpc response
580  **/
581 NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx,
582                                  POLICY_HND *pol, uint32 *start_idx, uint16 acb_mask,
583                                  uint32 size, char ***dom_users, uint32 **rids,
584                                  uint32 *num_dom_users)
585 {
586         prs_struct qbuf;
587         prs_struct rbuf;
588         SAMR_Q_ENUM_DOM_USERS q;
589         SAMR_R_ENUM_DOM_USERS r;
590         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
591         int i;
592         
593         DEBUG(10,("cli_samr_enum_dom_users starting at index %u\n", (unsigned int)*start_idx));
594
595         ZERO_STRUCT(q);
596         ZERO_STRUCT(r);
597         
598         /* always init this */
599         *num_dom_users = 0;
600         
601         /* Initialise parse structures */
602
603         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
604         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
605         
606         /* Fill query structure with parameters */
607
608         init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, 0, size);
609         
610         if (!samr_io_q_enum_dom_users("", &q, &qbuf, 0) ||
611             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &qbuf, &rbuf)) {
612                 goto done;
613         }
614
615         /* unpack received stream */
616
617         if(!samr_io_r_enum_dom_users("", &r, &rbuf, 0))
618                 goto done;
619         
620         result = r.status;
621
622         if (!NT_STATUS_IS_OK(result) &&
623             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES))
624                 goto done;
625         
626         *start_idx = r.next_idx;
627         *num_dom_users = r.num_entries2;
628
629         if (r.num_entries2) {
630                 /* allocate memory needed to return received data */    
631                 *rids = (uint32*)talloc(mem_ctx, sizeof(uint32) * r.num_entries2);
632                 if (!*rids) {
633                         DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n"));
634                         return NT_STATUS_NO_MEMORY;
635                 }
636                 
637                 *dom_users = (char**)talloc(mem_ctx, sizeof(char*) * r.num_entries2);
638                 if (!*dom_users) {
639                         DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n"));
640                         return NT_STATUS_NO_MEMORY;
641                 }
642                 
643                 /* fill output buffers with rpc response */
644                 for (i = 0; i < r.num_entries2; i++) {
645                         fstring conv_buf;
646                         
647                         (*rids)[i] = r.sam[i].rid;
648                         unistr2_to_ascii(conv_buf, &(r.uni_acct_name[i]), sizeof(conv_buf) - 1);
649                         (*dom_users)[i] = talloc_strdup(mem_ctx, conv_buf);
650                 }
651         }
652         
653 done:
654         prs_mem_free(&qbuf);
655         prs_mem_free(&rbuf);
656         
657         return result;
658 };
659
660 /* Enumerate domain groups */
661
662 NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
663                                   POLICY_HND *pol, uint32 *start_idx, 
664                                   uint32 size, struct acct_info **dom_groups,
665                                   uint32 *num_dom_groups)
666 {
667         prs_struct qbuf, rbuf;
668         SAMR_Q_ENUM_DOM_GROUPS q;
669         SAMR_R_ENUM_DOM_GROUPS r;
670         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
671         uint32 name_idx, i;
672
673         DEBUG(10,("cli_samr_enum_dom_groups starting at index %u\n", (unsigned int)*start_idx));
674
675         ZERO_STRUCT(q);
676         ZERO_STRUCT(r);
677
678         /* Initialise parse structures */
679
680         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
681         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
682
683         /* Marshall data and send request */
684
685         init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
686
687         if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
688             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf))
689                 goto done;
690
691         /* Unmarshall response */
692
693         if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0))
694                 goto done;
695
696         /* Return output parameters */
697
698         result = r.status;
699
700         if (!NT_STATUS_IS_OK(result) &&
701             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES))
702                 goto done;
703
704         *num_dom_groups = r.num_entries2;
705
706         if (*num_dom_groups == 0)
707                 goto done;
708
709         if (!((*dom_groups) = (struct acct_info *)
710               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
711                 result = NT_STATUS_NO_MEMORY;
712                 goto done;
713         }
714
715         memset(*dom_groups, 0, sizeof(struct acct_info) * (*num_dom_groups));
716
717         name_idx = 0;
718
719         for (i = 0; i < *num_dom_groups; i++) {
720
721                 (*dom_groups)[i].rid = r.sam[i].rid;
722
723                 if (r.sam[i].hdr_name.buffer) {
724                         unistr2_to_ascii((*dom_groups)[i].acct_name,
725                                          &r.uni_grp_name[name_idx],
726                                          sizeof(fstring) - 1);
727                         name_idx++;
728                 }
729
730                 *start_idx = r.next_idx;
731         }
732
733  done:
734         prs_mem_free(&qbuf);
735         prs_mem_free(&rbuf);
736
737         return result;
738 }
739
740 /* Enumerate domain groups */
741
742 NTSTATUS cli_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
743                                   POLICY_HND *pol, uint32 *start_idx, 
744                                   uint32 size, struct acct_info **dom_aliases,
745                                   uint32 *num_dom_aliases)
746 {
747         prs_struct qbuf, rbuf;
748         SAMR_Q_ENUM_DOM_ALIASES q;
749         SAMR_R_ENUM_DOM_ALIASES r;
750         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
751         uint32 name_idx, i;
752
753         DEBUG(10,("cli_samr_enum_als_groups starting at index %u\n", (unsigned int)*start_idx));
754
755         ZERO_STRUCT(q);
756         ZERO_STRUCT(r);
757
758         /* Initialise parse structures */
759
760         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
761         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
762
763         /* Marshall data and send request */
764
765         init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size);
766
767         if (!samr_io_q_enum_dom_aliases("", &q, &qbuf, 0) ||
768             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_ALIASES, &qbuf, &rbuf)) {
769                 goto done;
770         }
771
772         /* Unmarshall response */
773
774         if (!samr_io_r_enum_dom_aliases("", &r, &rbuf, 0)) {
775                 goto done;
776         }
777
778         /* Return output parameters */
779
780         result = r.status;
781
782         if (!NT_STATUS_IS_OK(result) &&
783             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
784                 goto done;
785         }
786
787         *num_dom_aliases = r.num_entries2;
788
789         if (*num_dom_aliases == 0)
790                 goto done;
791
792         if (!((*dom_aliases) = (struct acct_info *)
793               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_aliases))) {
794                 result = NT_STATUS_NO_MEMORY;
795                 goto done;
796         }
797
798         memset(*dom_aliases, 0, sizeof(struct acct_info) * *num_dom_aliases);
799
800         name_idx = 0;
801
802         for (i = 0; i < *num_dom_aliases; i++) {
803
804                 (*dom_aliases)[i].rid = r.sam[i].rid;
805
806                 if (r.sam[i].hdr_name.buffer) {
807                         unistr2_to_ascii((*dom_aliases)[i].acct_name,
808                                          &r.uni_grp_name[name_idx],
809                                          sizeof(fstring) - 1);
810                         name_idx++;
811                 }
812
813                 *start_idx = r.next_idx;
814         }
815
816  done:
817         prs_mem_free(&qbuf);
818         prs_mem_free(&rbuf);
819
820         return result;
821 }
822
823 /* Query alias members */
824
825 NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
826                                  POLICY_HND *alias_pol, uint32 *num_mem, 
827                                  DOM_SID **sids)
828 {
829         prs_struct qbuf, rbuf;
830         SAMR_Q_QUERY_ALIASMEM q;
831         SAMR_R_QUERY_ALIASMEM r;
832         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
833         uint32 i;
834
835         DEBUG(10,("cli_samr_query_aliasmem\n"));
836
837         ZERO_STRUCT(q);
838         ZERO_STRUCT(r);
839
840         /* Initialise parse structures */
841
842         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
843         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
844
845         /* Marshall data and send request */
846
847         init_samr_q_query_aliasmem(&q, alias_pol);
848
849         if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
850             !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
851                 goto done;
852         }
853
854         /* Unmarshall response */
855
856         if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
857                 goto done;
858         }
859
860         /* Return output parameters */
861
862         if (!NT_STATUS_IS_OK(result = r.status)) {
863                 goto done;
864         }
865
866         *num_mem = r.num_sids;
867
868         if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) {
869                 result = NT_STATUS_UNSUCCESSFUL;
870                 goto done;
871         }
872
873         for (i = 0; i < *num_mem; i++) {
874                 (*sids)[i] = r.sid[i].sid;
875         }
876
877  done:
878         prs_mem_free(&qbuf);
879         prs_mem_free(&rbuf);
880
881         return result;
882 }
883
884 /* Open handle on an alias */
885
886 NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
887                              POLICY_HND *domain_pol, uint32 access_mask, 
888                              uint32 alias_rid, POLICY_HND *alias_pol)
889 {
890         prs_struct qbuf, rbuf;
891         SAMR_Q_OPEN_ALIAS q;
892         SAMR_R_OPEN_ALIAS r;
893         NTSTATUS result;
894
895         DEBUG(10,("cli_samr_open_alias with rid 0x%x\n", alias_rid));
896
897         ZERO_STRUCT(q);
898         ZERO_STRUCT(r);
899
900         /* Initialise parse structures */
901
902         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
903         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
904
905         /* Marshall data and send request */
906
907         init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid);
908
909         if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
910             !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
911                 result = NT_STATUS_UNSUCCESSFUL;
912                 goto done;
913         }
914
915         /* Unmarshall response */
916
917         if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
918                 result = NT_STATUS_UNSUCCESSFUL;
919                 goto done;
920         }
921
922         /* Return output parameters */
923
924         if (NT_STATUS_IS_OK(result = r.status)) {
925                 *alias_pol = r.pol;
926 #ifdef __INSURE__
927                 alias_pol->marker = malloc(1);
928 #endif
929         }
930
931  done:
932         prs_mem_free(&qbuf);
933         prs_mem_free(&rbuf);
934
935         return result;
936 }
937
938 /* Query alias info */
939
940 NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
941                                    POLICY_HND *alias_pol, uint16 switch_value,
942                                    ALIAS_INFO_CTR *ctr)
943 {
944         prs_struct qbuf, rbuf;
945         SAMR_Q_QUERY_ALIASINFO q;
946         SAMR_R_QUERY_ALIASINFO r;
947         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
948
949         DEBUG(10,("cli_samr_query_dom_info\n"));
950
951         ZERO_STRUCT(q);
952         ZERO_STRUCT(r);
953
954         /* Initialise parse structures */
955
956         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
957         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
958
959         /* Marshall data and send request */
960
961         init_samr_q_query_aliasinfo(&q, alias_pol, switch_value);
962
963         if (!samr_io_q_query_aliasinfo("", &q, &qbuf, 0) ||
964             !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASINFO, &qbuf, &rbuf)) {
965                 goto done;
966         }
967
968         /* Unmarshall response */
969
970         if (!samr_io_r_query_aliasinfo("", &r, &rbuf, 0)) {
971                 goto done;
972         }
973
974         /* Return output parameters */
975
976         if (!NT_STATUS_IS_OK(result = r.status)) {
977                 goto done;
978         }
979
980         *ctr = r.ctr;
981
982  done:
983         prs_mem_free(&qbuf);
984         prs_mem_free(&rbuf);
985
986         return result;
987 }
988
989 /* Query domain info */
990
991 NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
992                                  POLICY_HND *domain_pol, uint16 switch_value,
993                                  SAM_UNK_CTR *ctr)
994 {
995         prs_struct qbuf, rbuf;
996         SAMR_Q_QUERY_DOMAIN_INFO q;
997         SAMR_R_QUERY_DOMAIN_INFO r;
998         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
999
1000         DEBUG(10,("cli_samr_query_dom_info\n"));
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_query_dom_info(&q, domain_pol, switch_value);
1013
1014         if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) ||
1015             !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) {
1016                 goto done;
1017         }
1018
1019         /* Unmarshall response */
1020
1021         r.ctr = ctr;
1022
1023         if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) {
1024                 goto done;
1025         }
1026
1027         /* Return output parameters */
1028
1029         if (!NT_STATUS_IS_OK(result = r.status)) {
1030                 goto done;
1031         }
1032
1033  done:
1034         prs_mem_free(&qbuf);
1035         prs_mem_free(&rbuf);
1036
1037         return result;
1038 }
1039
1040 /* This function returns the bizzare set of (max_entries, max_size) required
1041    for the QueryDisplayInfo RPC to actually work against a domain controller
1042    with large (10k and higher) numbers of users.  These values were 
1043    obtained by inspection using ethereal and NT4 running User Manager. */
1044
1045 void get_query_dispinfo_params(int loop_count, uint32 *max_entries,
1046                                uint32 *max_size)
1047 {
1048         switch(loop_count) {
1049         case 0:
1050                 *max_entries = 512;
1051                 *max_size = 16383;
1052                 break;
1053         case 1:
1054                 *max_entries = 1024;
1055                 *max_size = 32766;
1056                 break;
1057         case 2:
1058                 *max_entries = 2048;
1059                 *max_size = 65532;
1060                 break;
1061         case 3:
1062                 *max_entries = 4096;
1063                 *max_size = 131064;
1064                 break;
1065         default:              /* loop_count >= 4 */
1066                 *max_entries = 4096;
1067                 *max_size = 131071;
1068                 break;
1069         }
1070 }                    
1071
1072 /* Query display info */
1073
1074 NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1075                                  POLICY_HND *domain_pol, uint32 *start_idx,
1076                                  uint16 switch_value, uint32 *num_entries,
1077                                  uint32 max_entries, uint32 max_size,
1078                                  SAM_DISPINFO_CTR *ctr)
1079 {
1080         prs_struct qbuf, rbuf;
1081         SAMR_Q_QUERY_DISPINFO q;
1082         SAMR_R_QUERY_DISPINFO r;
1083         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1084
1085         DEBUG(10,("cli_samr_query_dispinfo for start_idx = %u\n", *start_idx));
1086
1087         ZERO_STRUCT(q);
1088         ZERO_STRUCT(r);
1089
1090         *num_entries = 0;
1091
1092         /* Initialise parse structures */
1093
1094         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1095         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1096
1097         /* Marshall data and send request */
1098
1099         init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
1100                                    *start_idx, max_entries, max_size);
1101
1102         if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) ||
1103             !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) {
1104                 goto done;
1105         }
1106
1107         /* Unmarshall response */
1108
1109         r.ctr = ctr;
1110
1111         if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) {
1112                 goto done;
1113         }
1114
1115         /* Return output parameters */
1116
1117         result = r.status;
1118
1119         if (!NT_STATUS_IS_OK(result) &&
1120             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1121                 goto done;
1122         }
1123
1124         *num_entries = r.num_entries;
1125         *start_idx += r.num_entries;  /* No next_idx in this structure! */
1126
1127  done:
1128         prs_mem_free(&qbuf);
1129         prs_mem_free(&rbuf);
1130
1131         return result;
1132 }
1133
1134 /* Lookup rids.  Note that NT4 seems to crash if more than ~1000 rids are
1135    looked up in one packet. */
1136
1137 NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1138                               POLICY_HND *domain_pol, uint32 flags,
1139                               uint32 num_rids, uint32 *rids, 
1140                               uint32 *num_names, char ***names,
1141                               uint32 **name_types)
1142 {
1143         prs_struct qbuf, rbuf;
1144         SAMR_Q_LOOKUP_RIDS q;
1145         SAMR_R_LOOKUP_RIDS r;
1146         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1147         uint32 i;
1148
1149         DEBUG(10,("cli_samr_lookup_rids\n"));
1150
1151         if (num_rids > 1000) {
1152                 DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if "
1153                           "more than ~1000 rids are looked up at once.\n"));
1154         }
1155
1156         ZERO_STRUCT(q);
1157         ZERO_STRUCT(r);
1158
1159         /* Initialise parse structures */
1160
1161         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1162         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1163
1164         /* Marshall data and send request */
1165
1166         init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags,
1167                                 num_rids, rids);
1168
1169         if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
1170             !rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
1171                 goto done;
1172         }
1173
1174         /* Unmarshall response */
1175
1176         if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) {
1177                 goto done;
1178         }
1179
1180         /* Return output parameters */
1181
1182         if (!NT_STATUS_IS_OK(result = r.status)) {
1183                 goto done;
1184         }
1185
1186         if (r.num_names1 == 0) {
1187                 *num_names = 0;
1188                 *names = NULL;
1189                 goto done;
1190         }
1191
1192         *num_names = r.num_names1;
1193         *names = talloc(mem_ctx, sizeof(char *) * r.num_names1);
1194         *name_types = talloc(mem_ctx, sizeof(uint32) * r.num_names1);
1195
1196         for (i = 0; i < r.num_names1; i++) {
1197                 fstring tmp;
1198
1199                 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp) - 1);
1200                 (*names)[i] = talloc_strdup(mem_ctx, tmp);
1201                 (*name_types)[i] = r.type[i];
1202         }
1203
1204  done:
1205         prs_mem_free(&qbuf);
1206         prs_mem_free(&rbuf);
1207
1208         return result;
1209 }
1210
1211 /* Lookup names */
1212
1213 NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1214                                POLICY_HND *domain_pol, uint32 flags,
1215                                uint32 num_names, const char **names,
1216                                uint32 *num_rids, uint32 **rids,
1217                                uint32 **rid_types)
1218 {
1219         prs_struct qbuf, rbuf;
1220         SAMR_Q_LOOKUP_NAMES q;
1221         SAMR_R_LOOKUP_NAMES r;
1222         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1223         uint32 i;
1224
1225         DEBUG(10,("cli_samr_lookup_names\n"));
1226
1227         ZERO_STRUCT(q);
1228         ZERO_STRUCT(r);
1229
1230         /* Initialise parse structures */
1231
1232         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1233         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1234
1235         /* Marshall data and send request */
1236
1237         init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags,
1238                                  num_names, names);
1239
1240         if (!samr_io_q_lookup_names("", &q, &qbuf, 0) ||
1241             !rpc_api_pipe_req(cli, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) {
1242                 goto done;
1243         }
1244
1245         /* Unmarshall response */
1246
1247         if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) {
1248                 goto done;
1249         }
1250
1251         /* Return output parameters */
1252
1253         if (!NT_STATUS_IS_OK(result = r.status)) {
1254                 goto done;
1255         }
1256
1257         if (r.num_rids1 == 0) {
1258                 *num_rids = 0;
1259                 goto done;
1260         }
1261
1262         *num_rids = r.num_rids1;
1263         *rids = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
1264         *rid_types = talloc(mem_ctx, sizeof(uint32) * r.num_rids1);
1265
1266         for (i = 0; i < r.num_rids1; i++) {
1267                 (*rids)[i] = r.rids[i];
1268                 (*rid_types)[i] = r.types[i];
1269         }
1270
1271  done:
1272         prs_mem_free(&qbuf);
1273         prs_mem_free(&rbuf);
1274
1275         return result;
1276 }
1277
1278 /* Create a domain user */
1279
1280 NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1281                                   POLICY_HND *domain_pol, const char *acct_name,
1282                                   uint32 acb_info, uint32 unknown, 
1283                                   POLICY_HND *user_pol, uint32 *rid)
1284 {
1285         prs_struct qbuf, rbuf;
1286         SAMR_Q_CREATE_USER q;
1287         SAMR_R_CREATE_USER r;
1288         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1289
1290         DEBUG(10,("cli_samr_create_dom_user %s\n", acct_name));
1291
1292         ZERO_STRUCT(q);
1293         ZERO_STRUCT(r);
1294
1295         /* Initialise parse structures */
1296
1297         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1298         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1299
1300         /* Marshall data and send request */
1301
1302         init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown);
1303
1304         if (!samr_io_q_create_user("", &q, &qbuf, 0) ||
1305             !rpc_api_pipe_req(cli, SAMR_CREATE_USER, &qbuf, &rbuf)) {
1306                 goto done;
1307         }
1308
1309         /* Unmarshall response */
1310
1311         if (!samr_io_r_create_user("", &r, &rbuf, 0)) {
1312                 goto done;
1313         }
1314
1315         /* Return output parameters */
1316
1317         if (!NT_STATUS_IS_OK(result = r.status)) {
1318                 goto done;
1319         }
1320
1321         if (user_pol)
1322                 *user_pol = r.user_pol;
1323
1324         if (rid)
1325                 *rid = r.user_rid;
1326
1327  done:
1328         prs_mem_free(&qbuf);
1329         prs_mem_free(&rbuf);
1330
1331         return result;
1332 }
1333
1334 /* Set userinfo */
1335
1336 NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1337                                POLICY_HND *user_pol, uint16 switch_value,
1338                                uchar sess_key[16], SAM_USERINFO_CTR *ctr)
1339 {
1340         prs_struct qbuf, rbuf;
1341         SAMR_Q_SET_USERINFO q;
1342         SAMR_R_SET_USERINFO r;
1343         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1344
1345         DEBUG(10,("cli_samr_set_userinfo\n"));
1346
1347         ZERO_STRUCT(q);
1348         ZERO_STRUCT(r);
1349
1350         /* Initialise parse structures */
1351
1352         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1353         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1354
1355         /* Marshall data and send request */
1356
1357         q.ctr = ctr;
1358
1359         init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, 
1360                                  ctr->info.id);
1361
1362         if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) ||
1363             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO, &qbuf, &rbuf)) {
1364                 goto done;
1365         }
1366
1367         /* Unmarshall response */
1368
1369         if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) {
1370                 goto done;
1371         }
1372
1373         /* Return output parameters */
1374
1375         if (!NT_STATUS_IS_OK(result = r.status)) {
1376                 goto done;
1377         }
1378
1379  done:
1380         prs_mem_free(&qbuf);
1381         prs_mem_free(&rbuf);
1382
1383         return result;
1384 }
1385
1386 /* Set userinfo2 */
1387
1388 NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1389                                 POLICY_HND *user_pol, uint16 switch_value,
1390                                 uchar sess_key[16], SAM_USERINFO_CTR *ctr)
1391 {
1392         prs_struct qbuf, rbuf;
1393         SAMR_Q_SET_USERINFO2 q;
1394         SAMR_R_SET_USERINFO2 r;
1395         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1396
1397         DEBUG(10,("cli_samr_set_userinfo2\n"));
1398
1399         ZERO_STRUCT(q);
1400         ZERO_STRUCT(r);
1401
1402         /* Initialise parse structures */
1403
1404         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1405         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1406
1407         /* Marshall data and send request */
1408
1409         init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
1410
1411         if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) ||
1412             !rpc_api_pipe_req(cli, SAMR_SET_USERINFO2, &qbuf, &rbuf)) {
1413                 goto done;
1414         }
1415
1416         /* Unmarshall response */
1417
1418         if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) {
1419                 goto done;
1420         }
1421
1422         /* Return output parameters */
1423
1424         if (!NT_STATUS_IS_OK(result = r.status)) {
1425                 goto done;
1426         }
1427
1428  done:
1429         prs_mem_free(&qbuf);
1430         prs_mem_free(&rbuf);
1431
1432         return result;
1433 }
1434
1435 /* Delete domain user */
1436
1437 NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1438                                   POLICY_HND *user_pol)
1439 {
1440         prs_struct qbuf, rbuf;
1441         SAMR_Q_DELETE_DOM_USER q;
1442         SAMR_R_DELETE_DOM_USER r;
1443         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1444
1445         DEBUG(10,("cli_samr_delete_dom_user\n"));
1446
1447         ZERO_STRUCT(q);
1448         ZERO_STRUCT(r);
1449
1450         /* Initialise parse structures */
1451
1452         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1453         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1454
1455         /* Marshall data and send request */
1456
1457         init_samr_q_delete_dom_user(&q, user_pol);
1458
1459         if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) ||
1460             !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) {
1461                 goto done;
1462         }
1463
1464         /* Unmarshall response */
1465
1466         if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) {
1467                 goto done;
1468         }
1469
1470         /* Return output parameters */
1471
1472         result = r.status;
1473
1474  done:
1475         prs_mem_free(&qbuf);
1476         prs_mem_free(&rbuf);
1477
1478         return result;
1479 }
1480
1481 /* Query user security object */
1482
1483 NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1484                                  POLICY_HND *user_pol, uint16 switch_value, 
1485                                  TALLOC_CTX *ctx, SEC_DESC_BUF **sec_desc_buf)
1486 {
1487         prs_struct qbuf, rbuf;
1488         SAMR_Q_QUERY_SEC_OBJ q;
1489         SAMR_R_QUERY_SEC_OBJ r;
1490         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1491
1492         DEBUG(10,("cli_samr_query_sec_obj\n"));
1493
1494         ZERO_STRUCT(q);
1495         ZERO_STRUCT(r);
1496
1497         /* Initialise parse structures */
1498
1499         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1500         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1501
1502         /* Marshall data and send request */
1503
1504         init_samr_q_query_sec_obj(&q, user_pol, switch_value);
1505
1506         if (!samr_io_q_query_sec_obj("", &q, &qbuf, 0) ||
1507             !rpc_api_pipe_req(cli, SAMR_QUERY_SEC_OBJECT, &qbuf, &rbuf)) {
1508                 goto done;
1509         }
1510
1511         /* Unmarshall response */
1512
1513         if (!samr_io_r_query_sec_obj("", &r, &rbuf, 0)) {
1514                 goto done;
1515         }
1516
1517         /* Return output parameters */
1518
1519         result = r.status;
1520         *sec_desc_buf=dup_sec_desc_buf(ctx, r.buf);
1521
1522  done:
1523         prs_mem_free(&qbuf);
1524         prs_mem_free(&rbuf);
1525
1526         return result;
1527 }
1528
1529 /* Get domain password info */
1530
1531 NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1532                                  uint16 *unk_0, uint16 *unk_1, uint16 *unk_2)
1533 {
1534         prs_struct qbuf, rbuf;
1535         SAMR_Q_GET_DOM_PWINFO q;
1536         SAMR_R_GET_DOM_PWINFO r;
1537         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1538
1539         DEBUG(10,("cli_samr_get_dom_pwinfo\n"));
1540
1541         ZERO_STRUCT(q);
1542         ZERO_STRUCT(r);
1543
1544         /* Initialise parse structures */
1545
1546         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1547         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1548
1549         /* Marshall data and send request */
1550
1551         init_samr_q_get_dom_pwinfo(&q, cli->desthost);
1552
1553         if (!samr_io_q_get_dom_pwinfo("", &q, &qbuf, 0) ||
1554             !rpc_api_pipe_req(cli, SAMR_GET_DOM_PWINFO, &qbuf, &rbuf))
1555                 goto done;
1556
1557         /* Unmarshall response */
1558
1559         if (!samr_io_r_get_dom_pwinfo("", &r, &rbuf, 0))
1560                 goto done;
1561
1562         /* Return output parameters */
1563
1564         result = r.status;
1565
1566         if (NT_STATUS_IS_OK(result)) {
1567                 if (unk_0)
1568                         *unk_0 = r.unk_0;
1569                 if (unk_1)
1570                         *unk_1 = r.unk_1;
1571                 if (unk_2)
1572                         *unk_2 = r.unk_2;
1573         }
1574
1575  done:
1576         prs_mem_free(&qbuf);
1577         prs_mem_free(&rbuf);
1578
1579         return result;
1580 }
1581
1582 /* Lookup Domain Name */
1583
1584 NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1585                                 POLICY_HND *user_pol, char *domain_name, 
1586                                 DOM_SID *sid)
1587 {
1588         prs_struct qbuf, rbuf;
1589         SAMR_Q_LOOKUP_DOMAIN q;
1590         SAMR_R_LOOKUP_DOMAIN r;
1591         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1592
1593         DEBUG(10,("cli_samr_lookup_domain\n"));
1594
1595         ZERO_STRUCT(q);
1596         ZERO_STRUCT(r);
1597
1598         /* Initialise parse structures */
1599
1600         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1601         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1602
1603         /* Marshall data and send request */
1604
1605         init_samr_q_lookup_domain(&q, user_pol, domain_name);
1606
1607         if (!samr_io_q_lookup_domain("", &q, &qbuf, 0) ||
1608             !rpc_api_pipe_req(cli, SAMR_LOOKUP_DOMAIN, &qbuf, &rbuf))
1609                 goto done;
1610
1611         /* Unmarshall response */
1612
1613         if (!samr_io_r_lookup_domain("", &r, &rbuf, 0))
1614                 goto done;
1615
1616         /* Return output parameters */
1617
1618         result = r.status;
1619
1620         if (NT_STATUS_IS_OK(result))
1621                 sid_copy(sid, &r.dom_sid.sid);
1622
1623  done:
1624         prs_mem_free(&qbuf);
1625         prs_mem_free(&rbuf);
1626
1627         return result;
1628 }