r23082: Ooops - that portion of the last checkin was by accident.
[samba.git] / source3 / rpc_client / cli_lsarpc.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) Rafal Szczesniak                       2002
7    Copyright (C) Jeremy Allison                         2005.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 /** @defgroup lsa LSA - Local Security Architecture
27  *  @ingroup rpc_client
28  *
29  * @{
30  **/
31
32 /**
33  * @file cli_lsarpc.c
34  *
35  * RPC client routines for the LSA RPC pipe.  LSA means "local
36  * security authority", which is half of a password database.
37  **/
38
39 /** Open a LSA policy handle
40  *
41  * @param cli Handle on an initialised SMB connection */
42
43 NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli,
44                                 TALLOC_CTX *mem_ctx,
45                                 BOOL sec_qos, uint32 des_access,
46                                 POLICY_HND *pol)
47 {
48         prs_struct qbuf, rbuf;
49         LSA_Q_OPEN_POL q;
50         LSA_R_OPEN_POL r;
51         LSA_SEC_QOS qos;
52         NTSTATUS result;
53
54         ZERO_STRUCT(q);
55         ZERO_STRUCT(r);
56
57         /* Initialise input parameters */
58
59         if (sec_qos) {
60                 init_lsa_sec_qos(&qos, 2, 1, 0);
61                 init_q_open_pol(&q, '\\', 0, des_access, &qos);
62         } else {
63                 init_q_open_pol(&q, '\\', 0, des_access, NULL);
64         }
65
66         /* Marshall data and send request */
67
68         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENPOLICY,
69                         q, r,
70                         qbuf, rbuf,
71                         lsa_io_q_open_pol,
72                         lsa_io_r_open_pol,
73                         NT_STATUS_UNSUCCESSFUL );
74
75         /* Return output parameters */
76
77         result = r.status;
78
79         if (NT_STATUS_IS_OK(result)) {
80                 *pol = r.pol;
81         }
82
83         return result;
84 }
85
86 /** Open a LSA policy handle
87   *
88   * @param cli Handle on an initialised SMB connection 
89   */
90
91 NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli,
92                                  TALLOC_CTX *mem_ctx, BOOL sec_qos,
93                                  uint32 des_access, POLICY_HND *pol)
94 {
95         prs_struct qbuf, rbuf;
96         LSA_Q_OPEN_POL2 q;
97         LSA_R_OPEN_POL2 r;
98         LSA_SEC_QOS qos;
99         NTSTATUS result;
100         char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
101
102         ZERO_STRUCT(q);
103         ZERO_STRUCT(r);
104
105         if (sec_qos) {
106                 init_lsa_sec_qos(&qos, 2, 1, 0);
107                 init_q_open_pol2(&q, srv_name_slash, 0, des_access, &qos);
108         } else {
109                 init_q_open_pol2(&q, srv_name_slash, 0, des_access, NULL);
110         }
111
112         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENPOLICY2,
113                         q, r,
114                         qbuf, rbuf,
115                         lsa_io_q_open_pol2,
116                         lsa_io_r_open_pol2,
117                         NT_STATUS_UNSUCCESSFUL );
118
119         /* Return output parameters */
120
121         result = r.status;
122
123         if (NT_STATUS_IS_OK(result)) {
124                 *pol = r.pol;
125         }
126
127         return result;
128 }
129
130 /* Lookup a list of sids
131  *
132  * internal version withOUT memory allocation of the target arrays.
133  * this assumes suffciently sized arrays to store domains, names and types. */
134
135 static NTSTATUS rpccli_lsa_lookup_sids_noalloc(struct rpc_pipe_client *cli,
136                                                TALLOC_CTX *mem_ctx,
137                                                POLICY_HND *pol,
138                                                int num_sids,
139                                                const DOM_SID *sids,
140                                                char **domains,
141                                                char **names,
142                                                enum lsa_SidType *types)
143 {
144         prs_struct qbuf, rbuf;
145         LSA_Q_LOOKUP_SIDS q;
146         LSA_R_LOOKUP_SIDS r;
147         DOM_R_REF ref;
148         LSA_TRANS_NAME_ENUM t_names;
149         NTSTATUS result = NT_STATUS_OK;
150         TALLOC_CTX *tmp_ctx = NULL;
151         int i;
152
153         tmp_ctx = talloc_new(mem_ctx);
154         if (!tmp_ctx) {
155                 DEBUG(0, ("rpccli_lsa_lookup_sids_noalloc: out of memory!\n"));
156                 result = NT_STATUS_UNSUCCESSFUL;
157                 goto done;
158         }
159
160         ZERO_STRUCT(q);
161         ZERO_STRUCT(r);
162
163         init_q_lookup_sids(tmp_ctx, &q, pol, num_sids, sids, 1);
164
165         ZERO_STRUCT(ref);
166         ZERO_STRUCT(t_names);
167
168         r.dom_ref = &ref;
169         r.names = &t_names;
170
171         CLI_DO_RPC( cli, tmp_ctx, PI_LSARPC, LSA_LOOKUPSIDS,
172                         q, r,
173                         qbuf, rbuf,
174                         lsa_io_q_lookup_sids,
175                         lsa_io_r_lookup_sids,
176                         NT_STATUS_UNSUCCESSFUL );
177
178         if (!NT_STATUS_IS_OK(r.status) &&
179             !NT_STATUS_EQUAL(r.status, STATUS_SOME_UNMAPPED)) 
180         {
181                 /* An actual error occured */
182                 result = r.status;
183                 goto done;
184         }
185
186         /* Return output parameters */
187
188         if (r.mapped_count == 0) {
189                 result = NT_STATUS_NONE_MAPPED;
190                 goto done;
191         }
192
193         for (i = 0; i < num_sids; i++) {
194                 fstring name, dom_name;
195                 uint32 dom_idx = t_names.name[i].domain_idx;
196
197                 /* Translate optimised name through domain index array */
198
199                 if (dom_idx != 0xffffffff) {
200
201                         rpcstr_pull_unistr2_fstring(
202                                 dom_name, &ref.ref_dom[dom_idx].uni_dom_name);
203                         rpcstr_pull_unistr2_fstring(
204                                 name, &t_names.uni_name[i]);
205
206                         (names)[i] = talloc_strdup(mem_ctx, name);
207                         (domains)[i] = talloc_strdup(mem_ctx, dom_name);
208                         (types)[i] = (enum lsa_SidType)t_names.name[i].sid_name_use;
209                         
210                         if (((names)[i] == NULL) || ((domains)[i] == NULL)) {
211                                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
212                                 result = NT_STATUS_UNSUCCESSFUL;
213                                 goto done;
214                         }
215
216                 } else {
217                         (names)[i] = NULL;
218                         (domains)[i] = NULL;
219                         (types)[i] = SID_NAME_UNKNOWN;
220                 }
221         }
222
223 done:
224         TALLOC_FREE(tmp_ctx);
225         return result;
226 }
227
228 /* Lookup a list of sids 
229  *
230  * do it the right way: there is a limit (of 20480 for w2k3) entries
231  * returned by this call. when the sids list contains more entries,
232  * empty lists are returned. This version of lsa_lookup_sids passes
233  * the list of sids in hunks of LOOKUP_SIDS_HUNK_SIZE to the lsa call. */
234
235 /* This constant defines the limit of how many sids to look up
236  * in one call (maximum). the limit from the server side is
237  * at 20480 for win2k3, but we keep it at a save 1000 for now. */
238 #define LOOKUP_SIDS_HUNK_SIZE 1000
239
240 NTSTATUS rpccli_lsa_lookup_sids_all(struct rpc_pipe_client *cli,
241                                     TALLOC_CTX *mem_ctx,
242                                     POLICY_HND *pol, 
243                                     int num_sids,
244                                     const DOM_SID *sids, 
245                                     char ***domains,
246                                     char ***names,
247                                     enum lsa_SidType **types)
248 {
249         NTSTATUS result = NT_STATUS_OK;
250         int sids_left = 0;
251         int sids_processed = 0;
252         const DOM_SID *hunk_sids = sids;
253         char **hunk_domains = NULL;
254         char **hunk_names = NULL;
255         enum lsa_SidType *hunk_types = NULL;
256
257         if (num_sids) {
258                 if (!((*domains) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
259                         DEBUG(0, ("rpccli_lsa_lookup_sids_all(): out of memory\n"));
260                         result = NT_STATUS_NO_MEMORY;
261                         goto done;
262                 }
263
264                 if (!((*names) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
265                         DEBUG(0, ("rpccli_lsa_lookup_sids_all(): out of memory\n"));
266                         result = NT_STATUS_NO_MEMORY;
267                         goto done;
268                 }
269
270                 if (!((*types) = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_sids))) {
271                         DEBUG(0, ("rpccli_lsa_lookup_sids_all(): out of memory\n"));
272                         result = NT_STATUS_NO_MEMORY;
273                         goto done;
274                 }
275         } else {
276                 (*domains) = NULL;
277                 (*names) = NULL;
278                 (*types) = NULL;
279         }
280         
281         sids_left = num_sids;
282         hunk_domains = *domains;
283         hunk_names = *names;
284         hunk_types = *types;
285
286         while (sids_left > 0) {
287                 int hunk_num_sids;
288                 NTSTATUS hunk_result = NT_STATUS_OK;
289
290                 hunk_num_sids = ((sids_left > LOOKUP_SIDS_HUNK_SIZE) 
291                                 ? LOOKUP_SIDS_HUNK_SIZE 
292                                 : sids_left);
293
294                 DEBUG(10, ("rpccli_lsa_lookup_sids_all: processing items "
295                            "%d -- %d of %d.\n", 
296                            sids_processed, 
297                            sids_processed + hunk_num_sids - 1,
298                            num_sids));
299
300                 hunk_result = rpccli_lsa_lookup_sids_noalloc(cli,
301                                                              mem_ctx,
302                                                              pol,
303                                                              hunk_num_sids, 
304                                                              hunk_sids,
305                                                              hunk_domains,
306                                                              hunk_names,
307                                                              hunk_types);
308
309                 if (!NT_STATUS_IS_OK(hunk_result) &&
310                     !NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED) &&
311                     !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED)) 
312                 {
313                         /* An actual error occured */
314                         goto done;
315                 }
316
317                 /* adapt overall result */
318                 if (( NT_STATUS_IS_OK(result) && 
319                      !NT_STATUS_IS_OK(hunk_result)) 
320                     ||
321                     ( NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) &&
322                      !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED)))
323                 {
324                         result = STATUS_SOME_UNMAPPED;
325                 }
326
327                 sids_left -= hunk_num_sids;
328                 sids_processed += hunk_num_sids; /* only used in DEBUG */
329                 hunk_sids += hunk_num_sids;
330                 hunk_domains += hunk_num_sids;
331                 hunk_names += hunk_num_sids;
332                 hunk_types += hunk_num_sids;
333         }
334
335 done:
336         return result;
337 }
338
339 /** Lookup a list of sids */
340
341 NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
342                                 TALLOC_CTX *mem_ctx,
343                                 POLICY_HND *pol, int num_sids,
344                                 const DOM_SID *sids, 
345                                 char ***domains,
346                                 char ***names,
347                                 enum lsa_SidType **types)
348 {
349         prs_struct qbuf, rbuf;
350         LSA_Q_LOOKUP_SIDS q;
351         LSA_R_LOOKUP_SIDS r;
352         DOM_R_REF ref;
353         LSA_TRANS_NAME_ENUM t_names;
354         NTSTATUS result = NT_STATUS_OK;
355         int i;
356
357         ZERO_STRUCT(q);
358         ZERO_STRUCT(r);
359
360         init_q_lookup_sids(mem_ctx, &q, pol, num_sids, sids, 1);
361
362         ZERO_STRUCT(ref);
363         ZERO_STRUCT(t_names);
364
365         r.dom_ref = &ref;
366         r.names = &t_names;
367
368         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPSIDS,
369                         q, r,
370                         qbuf, rbuf,
371                         lsa_io_q_lookup_sids,
372                         lsa_io_r_lookup_sids,
373                         NT_STATUS_UNSUCCESSFUL );
374
375         if (!NT_STATUS_IS_OK(r.status) &&
376             !NT_STATUS_EQUAL(r.status, STATUS_SOME_UNMAPPED)) {
377           
378                 /* An actual error occured */
379                 result = r.status;
380
381                 goto done;
382         }
383
384         /* Return output parameters */
385
386         if (r.mapped_count == 0) {
387                 result = NT_STATUS_NONE_MAPPED;
388                 goto done;
389         }
390
391         if (num_sids) {
392                 if (!((*domains) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
393                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
394                         result = NT_STATUS_NO_MEMORY;
395                         goto done;
396                 }
397
398                 if (!((*names) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
399                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
400                         result = NT_STATUS_NO_MEMORY;
401                         goto done;
402                 }
403
404                 if (!((*types) = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_sids))) {
405                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
406                         result = NT_STATUS_NO_MEMORY;
407                         goto done;
408                 }
409         } else {
410                 (*domains) = NULL;
411                 (*names) = NULL;
412                 (*types) = NULL;
413         }
414                 
415         for (i = 0; i < num_sids; i++) {
416                 fstring name, dom_name;
417                 uint32 dom_idx = t_names.name[i].domain_idx;
418
419                 /* Translate optimised name through domain index array */
420
421                 if (dom_idx != 0xffffffff) {
422
423                         rpcstr_pull_unistr2_fstring(
424                                 dom_name, &ref.ref_dom[dom_idx].uni_dom_name);
425                         rpcstr_pull_unistr2_fstring(
426                                 name, &t_names.uni_name[i]);
427
428                         (*names)[i] = talloc_strdup(mem_ctx, name);
429                         (*domains)[i] = talloc_strdup(mem_ctx, dom_name);
430                         (*types)[i] = (enum lsa_SidType)t_names.name[i].sid_name_use;
431                         
432                         if (((*names)[i] == NULL) || ((*domains)[i] == NULL)) {
433                                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
434                                 result = NT_STATUS_UNSUCCESSFUL;
435                                 goto done;
436                         }
437
438                 } else {
439                         (*names)[i] = NULL;
440                         (*domains)[i] = NULL;
441                         (*types)[i] = SID_NAME_UNKNOWN;
442                 }
443         }
444
445  done:
446
447         return result;
448 }
449
450 /** Lookup a list of names */
451
452 NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
453                                  TALLOC_CTX *mem_ctx,
454                                  POLICY_HND *pol, int num_names, 
455                                  const char **names,
456                                  const char ***dom_names,
457                                  DOM_SID **sids,
458                                  enum lsa_SidType **types)
459 {
460         prs_struct qbuf, rbuf;
461         LSA_Q_LOOKUP_NAMES q;
462         LSA_R_LOOKUP_NAMES r;
463         DOM_R_REF ref;
464         NTSTATUS result;
465         int i;
466         
467         ZERO_STRUCT(q);
468         ZERO_STRUCT(r);
469
470         ZERO_STRUCT(ref);
471         r.dom_ref = &ref;
472
473         init_q_lookup_names(mem_ctx, &q, pol, num_names, names);
474
475         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPNAMES,
476                         q, r,
477                         qbuf, rbuf,
478                         lsa_io_q_lookup_names,
479                         lsa_io_r_lookup_names,
480                         NT_STATUS_UNSUCCESSFUL);
481
482         result = r.status;
483
484         if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) !=
485             NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
486
487                 /* An actual error occured */
488
489                 goto done;
490         }
491
492         /* Return output parameters */
493
494         if (r.mapped_count == 0) {
495                 result = NT_STATUS_NONE_MAPPED;
496                 goto done;
497         }
498
499         if (num_names) {
500                 if (!((*sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_names)))) {
501                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
502                         result = NT_STATUS_NO_MEMORY;
503                         goto done;
504                 }
505
506                 if (!((*types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_names)))) {
507                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
508                         result = NT_STATUS_NO_MEMORY;
509                         goto done;
510                 }
511
512                 if (dom_names != NULL) {
513                         *dom_names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
514                         if (*dom_names == NULL) {
515                                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
516                                 result = NT_STATUS_NO_MEMORY;
517                                 goto done;
518                         }
519                 }
520         } else {
521                 *sids = NULL;
522                 *types = NULL;
523                 if (dom_names != NULL) {
524                         *dom_names = NULL;
525                 }
526         }
527
528         for (i = 0; i < num_names; i++) {
529                 DOM_RID *t_rids = r.dom_rid;
530                 uint32 dom_idx = t_rids[i].rid_idx;
531                 uint32 dom_rid = t_rids[i].rid;
532                 DOM_SID *sid = &(*sids)[i];
533
534                 /* Translate optimised sid through domain index array */
535
536                 if (dom_idx == 0xffffffff) {
537                         /* Nothing to do, this is unknown */
538                         ZERO_STRUCTP(sid);
539                         (*types)[i] = SID_NAME_UNKNOWN;
540                         continue;
541                 }
542
543                 sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
544
545                 if (dom_rid != 0xffffffff) {
546                         sid_append_rid(sid, dom_rid);
547                 }
548
549                 (*types)[i] = (enum lsa_SidType)t_rids[i].type;
550
551                 if (dom_names == NULL) {
552                         continue;
553                 }
554
555                 (*dom_names)[i] = rpcstr_pull_unistr2_talloc(
556                         *dom_names, &ref.ref_dom[dom_idx].uni_dom_name);
557         }
558
559  done:
560
561         return result;
562 }
563
564 NTSTATUS rpccli_lsa_query_info_policy_new(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
565                                           POLICY_HND *pol, uint16 info_class,
566                                           LSA_INFO_CTR *ctr) 
567 {
568         prs_struct qbuf, rbuf;
569         LSA_Q_QUERY_INFO q;
570         LSA_R_QUERY_INFO r;
571         NTSTATUS result;
572
573         ZERO_STRUCT(q);
574         ZERO_STRUCT(r);
575
576         init_q_query(&q, pol, info_class);
577
578         CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFOPOLICY,
579                 q, r,
580                 qbuf, rbuf,
581                 lsa_io_q_query,
582                 lsa_io_r_query,
583                 NT_STATUS_UNSUCCESSFUL);
584
585         result = r.status;
586
587         if (!NT_STATUS_IS_OK(result)) {
588                 goto done;
589         }
590
591  done:
592
593         *ctr = r.ctr;
594         
595         return result;
596 }
597
598 NTSTATUS rpccli_lsa_query_info_policy2_new(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
599                                           POLICY_HND *pol, uint16 info_class,
600                                           LSA_INFO_CTR2 *ctr) 
601 {
602         prs_struct qbuf, rbuf;
603         LSA_Q_QUERY_INFO2 q;
604         LSA_R_QUERY_INFO2 r;
605         NTSTATUS result;
606
607         ZERO_STRUCT(q);
608         ZERO_STRUCT(r);
609
610         init_q_query2(&q, pol, info_class);
611
612         CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFO2,
613                 q, r,
614                 qbuf, rbuf,
615                 lsa_io_q_query_info2,
616                 lsa_io_r_query_info2,
617                 NT_STATUS_UNSUCCESSFUL);
618
619         result = r.status;
620
621         if (!NT_STATUS_IS_OK(result)) {
622                 goto done;
623         }
624
625  done:
626
627         *ctr = r.ctr;
628         
629         return result;
630 }
631
632
633
634 /** Query info policy
635  *
636  *  @param domain_sid - returned remote server's domain sid */
637
638 NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli,
639                                       TALLOC_CTX *mem_ctx,
640                                       POLICY_HND *pol, uint16 info_class, 
641                                       char **domain_name, DOM_SID **domain_sid)
642 {
643         prs_struct qbuf, rbuf;
644         LSA_Q_QUERY_INFO q;
645         LSA_R_QUERY_INFO r;
646         NTSTATUS result;
647
648         ZERO_STRUCT(q);
649         ZERO_STRUCT(r);
650
651         init_q_query(&q, pol, info_class);
652
653         CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFOPOLICY,
654                 q, r,
655                 qbuf, rbuf,
656                 lsa_io_q_query,
657                 lsa_io_r_query,
658                 NT_STATUS_UNSUCCESSFUL);
659
660         result = r.status;
661
662         if (!NT_STATUS_IS_OK(result)) {
663                 goto done;
664         }
665
666         /* Return output parameters */
667
668         switch (info_class) {
669
670         case 3:
671                 if (domain_name && (r.ctr.info.id3.buffer_dom_name != 0)) {
672                         *domain_name = unistr2_tdup(mem_ctx, 
673                                                    &r.ctr.info.id3.
674                                                    uni_domain_name);
675                         if (!*domain_name) {
676                                 return NT_STATUS_NO_MEMORY;
677                         }
678                 }
679
680                 if (domain_sid && (r.ctr.info.id3.buffer_dom_sid != 0)) {
681                         *domain_sid = TALLOC_P(mem_ctx, DOM_SID);
682                         if (!*domain_sid) {
683                                 return NT_STATUS_NO_MEMORY;
684                         }
685                         sid_copy(*domain_sid, &r.ctr.info.id3.dom_sid.sid);
686                 }
687
688                 break;
689
690         case 5:
691                 
692                 if (domain_name && (r.ctr.info.id5.buffer_dom_name != 0)) {
693                         *domain_name = unistr2_tdup(mem_ctx, 
694                                                    &r.ctr.info.id5.
695                                                    uni_domain_name);
696                         if (!*domain_name) {
697                                 return NT_STATUS_NO_MEMORY;
698                         }
699                 }
700                         
701                 if (domain_sid && (r.ctr.info.id5.buffer_dom_sid != 0)) {
702                         *domain_sid = TALLOC_P(mem_ctx, DOM_SID);
703                         if (!*domain_sid) {
704                                 return NT_STATUS_NO_MEMORY;
705                         }
706                         sid_copy(*domain_sid, &r.ctr.info.id5.dom_sid.sid);
707                 }
708                 break;
709                         
710         default:
711                 DEBUG(3, ("unknown info class %d\n", info_class));
712                 break;                
713         }
714         
715  done:
716
717         return result;
718 }
719
720 /** Query info policy2
721  *
722  *  @param domain_name - returned remote server's domain name
723  *  @param dns_name - returned remote server's dns domain name
724  *  @param forest_name - returned remote server's forest name
725  *  @param domain_guid - returned remote server's domain guid
726  *  @param domain_sid - returned remote server's domain sid */
727
728 NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
729                                        TALLOC_CTX *mem_ctx,
730                                        POLICY_HND *pol, uint16 info_class, 
731                                        char **domain_name, char **dns_name,
732                                        char **forest_name,
733                                        struct GUID **domain_guid,
734                                        DOM_SID **domain_sid)
735 {
736         prs_struct qbuf, rbuf;
737         LSA_Q_QUERY_INFO2 q;
738         LSA_R_QUERY_INFO2 r;
739         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
740
741         if (info_class != 12)
742                 goto done;
743
744         ZERO_STRUCT(q);
745         ZERO_STRUCT(r);
746
747         init_q_query2(&q, pol, info_class);
748
749         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYINFO2,
750                 q, r,
751                 qbuf, rbuf,
752                 lsa_io_q_query_info2,
753                 lsa_io_r_query_info2,
754                 NT_STATUS_UNSUCCESSFUL);
755
756         result = r.status;
757
758         if (!NT_STATUS_IS_OK(result)) {
759                 goto done;
760         }
761
762         /* Return output parameters */
763
764         ZERO_STRUCTP(domain_guid);
765
766         if (domain_name && r.ctr.info.id12.hdr_nb_dom_name.buffer) {
767                 *domain_name = unistr2_tdup(mem_ctx, 
768                                             &r.ctr.info.id12
769                                             .uni_nb_dom_name);
770                 if (!*domain_name) {
771                         return NT_STATUS_NO_MEMORY;
772                 }
773         }
774         if (dns_name && r.ctr.info.id12.hdr_dns_dom_name.buffer) {
775                 *dns_name = unistr2_tdup(mem_ctx, 
776                                          &r.ctr.info.id12
777                                          .uni_dns_dom_name);
778                 if (!*dns_name) {
779                         return NT_STATUS_NO_MEMORY;
780                 }
781         }
782         if (forest_name && r.ctr.info.id12.hdr_forest_name.buffer) {
783                 *forest_name = unistr2_tdup(mem_ctx, 
784                                             &r.ctr.info.id12
785                                             .uni_forest_name);
786                 if (!*forest_name) {
787                         return NT_STATUS_NO_MEMORY;
788                 }
789         }
790         
791         if (domain_guid) {
792                 *domain_guid = TALLOC_P(mem_ctx, struct GUID);
793                 if (!*domain_guid) {
794                         return NT_STATUS_NO_MEMORY;
795                 }
796                 memcpy(*domain_guid, 
797                        &r.ctr.info.id12.dom_guid, 
798                        sizeof(struct GUID));
799         }
800
801         if (domain_sid && r.ctr.info.id12.ptr_dom_sid != 0) {
802                 *domain_sid = TALLOC_P(mem_ctx, DOM_SID);
803                 if (!*domain_sid) {
804                         return NT_STATUS_NO_MEMORY;
805                 }
806                 sid_copy(*domain_sid, 
807                          &r.ctr.info.id12.dom_sid.sid);
808         }
809         
810  done:
811
812         return result;
813 }
814
815 NTSTATUS rpccli_lsa_set_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
816                                     POLICY_HND *pol, uint16 info_class,
817                                     LSA_INFO_CTR ctr) 
818 {
819         prs_struct qbuf, rbuf;
820         LSA_Q_SET_INFO q;
821         LSA_R_SET_INFO r;
822         NTSTATUS result;
823
824         ZERO_STRUCT(q);
825         ZERO_STRUCT(r);
826
827         init_q_set(&q, pol, info_class, ctr);
828
829         CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_SETINFOPOLICY,
830                 q, r,
831                 qbuf, rbuf,
832                 lsa_io_q_set,
833                 lsa_io_r_set,
834                 NT_STATUS_UNSUCCESSFUL);
835
836         result = r.status;
837
838         if (!NT_STATUS_IS_OK(result)) {
839                 goto done;
840         }
841
842         /* Return output parameters */
843
844  done:
845
846         return result;
847 }
848
849
850 /**
851  * Enumerate list of trusted domains
852  *
853  * @param cli client state (cli_state) structure of the connection
854  * @param mem_ctx memory context
855  * @param pol opened lsa policy handle
856  * @param enum_ctx enumeration context ie. index of first returned domain entry
857  * @param pref_num_domains preferred max number of entries returned in one response
858  * @param num_domains total number of trusted domains returned by response
859  * @param domain_names returned trusted domain names
860  * @param domain_sids returned trusted domain sids
861  *
862  * @return nt status code of response
863  **/
864
865 NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli,
866                                    TALLOC_CTX *mem_ctx,
867                                    POLICY_HND *pol, uint32 *enum_ctx, 
868                                    uint32 *num_domains,
869                                    char ***domain_names, DOM_SID **domain_sids)
870 {
871         prs_struct qbuf, rbuf;
872         LSA_Q_ENUM_TRUST_DOM in;
873         LSA_R_ENUM_TRUST_DOM out;
874         int i;
875         fstring tmp;
876
877         ZERO_STRUCT(in);
878         ZERO_STRUCT(out);
879
880         /* 64k is enough for about 2000 trusted domains */
881         
882         init_q_enum_trust_dom(&in, pol, *enum_ctx, 0x10000);
883
884         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM, 
885                     in, out, 
886                     qbuf, rbuf,
887                     lsa_io_q_enum_trust_dom,
888                     lsa_io_r_enum_trust_dom, 
889                     NT_STATUS_UNSUCCESSFUL );
890
891
892         /* check for an actual error */
893
894         if ( !NT_STATUS_IS_OK(out.status) 
895                 && !NT_STATUS_EQUAL(out.status, NT_STATUS_NO_MORE_ENTRIES) 
896                 && !NT_STATUS_EQUAL(out.status, STATUS_MORE_ENTRIES) )
897         {
898                 return out.status;
899         }
900                 
901         /* Return output parameters */
902
903         *num_domains  = out.count;
904         *enum_ctx     = out.enum_context;
905         
906         if ( out.count ) {
907
908                 /* Allocate memory for trusted domain names and sids */
909
910                 if ( !(*domain_names = TALLOC_ARRAY(mem_ctx, char *, out.count)) ) {
911                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
912                         return NT_STATUS_NO_MEMORY;
913                 }
914
915                 if ( !(*domain_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, out.count)) ) {
916                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
917                         return NT_STATUS_NO_MEMORY;
918                 }
919
920                 /* Copy across names and sids */
921
922                 for (i = 0; i < out.count; i++) {
923
924                         rpcstr_pull( tmp, out.domlist->domains[i].name.string->buffer, 
925                                 sizeof(tmp), out.domlist->domains[i].name.length, 0);
926                         (*domain_names)[i] = talloc_strdup(mem_ctx, tmp);
927
928                         sid_copy(&(*domain_sids)[i], &out.domlist->domains[i].sid->sid );
929                 }
930         }
931
932         return out.status;
933 }
934
935 /** Enumerate privileges*/
936
937 NTSTATUS rpccli_lsa_enum_privilege(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
938                                 POLICY_HND *pol, uint32 *enum_context, uint32 pref_max_length,
939                                 uint32 *count, char ***privs_name, uint32 **privs_high, uint32 **privs_low)
940 {
941         prs_struct qbuf, rbuf;
942         LSA_Q_ENUM_PRIVS q;
943         LSA_R_ENUM_PRIVS r;
944         NTSTATUS result;
945         int i;
946
947         ZERO_STRUCT(q);
948         ZERO_STRUCT(r);
949
950         init_q_enum_privs(&q, pol, *enum_context, pref_max_length);
951
952         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_PRIVS,
953                 q, r,
954                 qbuf, rbuf,
955                 lsa_io_q_enum_privs,
956                 lsa_io_r_enum_privs,
957                 NT_STATUS_UNSUCCESSFUL);
958
959         result = r.status;
960
961         if (!NT_STATUS_IS_OK(result)) {
962                 goto done;
963         }
964
965         /* Return output parameters */
966
967         *enum_context = r.enum_context;
968         *count = r.count;
969
970         if (r.count) {
971                 if (!((*privs_name = TALLOC_ARRAY(mem_ctx, char *, r.count)))) {
972                         DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
973                         result = NT_STATUS_UNSUCCESSFUL;
974                         goto done;
975                 }
976
977                 if (!((*privs_high = TALLOC_ARRAY(mem_ctx, uint32, r.count)))) {
978                         DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
979                         result = NT_STATUS_UNSUCCESSFUL;
980                         goto done;
981                 }
982
983                 if (!((*privs_low = TALLOC_ARRAY(mem_ctx, uint32, r.count)))) {
984                         DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
985                         result = NT_STATUS_UNSUCCESSFUL;
986                         goto done;
987                 }
988         } else {
989                 *privs_name = NULL;
990                 *privs_high = NULL;
991                 *privs_low = NULL;
992         }
993
994         for (i = 0; i < r.count; i++) {
995                 fstring name;
996
997                 rpcstr_pull_unistr2_fstring( name, &r.privs[i].name);
998
999                 (*privs_name)[i] = talloc_strdup(mem_ctx, name);
1000
1001                 (*privs_high)[i] = r.privs[i].luid_high;
1002                 (*privs_low)[i] = r.privs[i].luid_low;
1003         }
1004
1005  done:
1006
1007         return result;
1008 }
1009
1010 /** Get privilege name */
1011
1012 NTSTATUS rpccli_lsa_get_dispname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1013                               POLICY_HND *pol, const char *name, 
1014                               uint16 lang_id, uint16 lang_id_sys,
1015                               fstring description, uint16 *lang_id_desc)
1016 {
1017         prs_struct qbuf, rbuf;
1018         LSA_Q_PRIV_GET_DISPNAME q;
1019         LSA_R_PRIV_GET_DISPNAME r;
1020         NTSTATUS result;
1021
1022         ZERO_STRUCT(q);
1023         ZERO_STRUCT(r);
1024
1025         init_lsa_priv_get_dispname(&q, pol, name, lang_id, lang_id_sys);
1026
1027         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_PRIV_GET_DISPNAME,
1028                 q, r,
1029                 qbuf, rbuf,
1030                 lsa_io_q_priv_get_dispname,
1031                 lsa_io_r_priv_get_dispname,
1032                 NT_STATUS_UNSUCCESSFUL);
1033
1034         result = r.status;
1035
1036         if (!NT_STATUS_IS_OK(result)) {
1037                 goto done;
1038         }
1039
1040         /* Return output parameters */
1041         
1042         rpcstr_pull_unistr2_fstring(description , &r.desc);
1043         *lang_id_desc = r.lang_id;
1044
1045  done:
1046
1047         return result;
1048 }
1049
1050 /** Enumerate list of SIDs  */
1051
1052 NTSTATUS rpccli_lsa_enum_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1053                                 POLICY_HND *pol, uint32 *enum_ctx, uint32 pref_max_length, 
1054                                 uint32 *num_sids, DOM_SID **sids)
1055 {
1056         prs_struct qbuf, rbuf;
1057         LSA_Q_ENUM_ACCOUNTS q;
1058         LSA_R_ENUM_ACCOUNTS r;
1059         NTSTATUS result;
1060         int i;
1061
1062         ZERO_STRUCT(q);
1063         ZERO_STRUCT(r);
1064
1065         init_lsa_q_enum_accounts(&q, pol, *enum_ctx, pref_max_length);
1066
1067         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_ACCOUNTS,
1068                 q, r,
1069                 qbuf, rbuf,
1070                 lsa_io_q_enum_accounts,
1071                 lsa_io_r_enum_accounts,
1072                 NT_STATUS_UNSUCCESSFUL);
1073
1074         result = r.status;
1075
1076         if (!NT_STATUS_IS_OK(result)) {
1077                 goto done;
1078         }
1079
1080         if (r.sids.num_entries==0)
1081                 goto done;
1082
1083         /* Return output parameters */
1084
1085         *sids = TALLOC_ARRAY(mem_ctx, DOM_SID, r.sids.num_entries);
1086         if (!*sids) {
1087                 DEBUG(0, ("(cli_lsa_enum_sids): out of memory\n"));
1088                 result = NT_STATUS_UNSUCCESSFUL;
1089                 goto done;
1090         }
1091
1092         /* Copy across names and sids */
1093
1094         for (i = 0; i < r.sids.num_entries; i++) {
1095                 sid_copy(&(*sids)[i], &r.sids.sid[i].sid);
1096         }
1097
1098         *num_sids= r.sids.num_entries;
1099         *enum_ctx = r.enum_context;
1100
1101  done:
1102
1103         return result;
1104 }
1105
1106 /** Create a LSA user handle
1107  *
1108  * @param cli Handle on an initialised SMB connection
1109  *
1110  * FIXME: The code is actually identical to open account
1111  * TODO: Check and code what the function should exactly do
1112  *
1113  * */
1114
1115 NTSTATUS rpccli_lsa_create_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1116                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 desired_access, 
1117                              POLICY_HND *user_pol)
1118 {
1119         prs_struct qbuf, rbuf;
1120         LSA_Q_CREATEACCOUNT q;
1121         LSA_R_CREATEACCOUNT r;
1122         NTSTATUS result;
1123
1124         ZERO_STRUCT(q);
1125         ZERO_STRUCT(r);
1126
1127         /* Initialise input parameters */
1128
1129         init_lsa_q_create_account(&q, dom_pol, sid, desired_access);
1130
1131         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_CREATEACCOUNT,
1132                 q, r,
1133                 qbuf, rbuf,
1134                 lsa_io_q_create_account,
1135                 lsa_io_r_create_account,
1136                 NT_STATUS_UNSUCCESSFUL);
1137
1138         /* Return output parameters */
1139
1140         result = r.status;
1141
1142         if (NT_STATUS_IS_OK(result)) {
1143                 *user_pol = r.pol;
1144         }
1145
1146         return result;
1147 }
1148
1149 /** Open a LSA user handle
1150  *
1151  * @param cli Handle on an initialised SMB connection */
1152
1153 NTSTATUS rpccli_lsa_open_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1154                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 des_access, 
1155                              POLICY_HND *user_pol)
1156 {
1157         prs_struct qbuf, rbuf;
1158         LSA_Q_OPENACCOUNT q;
1159         LSA_R_OPENACCOUNT r;
1160         NTSTATUS result;
1161
1162         ZERO_STRUCT(q);
1163         ZERO_STRUCT(r);
1164
1165         /* Initialise input parameters */
1166
1167         init_lsa_q_open_account(&q, dom_pol, sid, des_access);
1168
1169         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENACCOUNT,
1170                 q, r,
1171                 qbuf, rbuf,
1172                 lsa_io_q_open_account,
1173                 lsa_io_r_open_account,
1174                 NT_STATUS_UNSUCCESSFUL);
1175
1176         /* Return output parameters */
1177
1178         result = r.status;
1179
1180         if (NT_STATUS_IS_OK(result)) {
1181                 *user_pol = r.pol;
1182         }
1183
1184         return result;
1185 }
1186
1187 /** Enumerate user privileges
1188  *
1189  * @param cli Handle on an initialised SMB connection */
1190
1191 NTSTATUS rpccli_lsa_enum_privsaccount(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1192                              POLICY_HND *pol, uint32 *count, LUID_ATTR **set)
1193 {
1194         prs_struct qbuf, rbuf;
1195         LSA_Q_ENUMPRIVSACCOUNT q;
1196         LSA_R_ENUMPRIVSACCOUNT r;
1197         NTSTATUS result;
1198         int i;
1199
1200         ZERO_STRUCT(q);
1201         ZERO_STRUCT(r);
1202
1203         /* Initialise input parameters */
1204
1205         init_lsa_q_enum_privsaccount(&q, pol);
1206
1207         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMPRIVSACCOUNT,
1208                 q, r,
1209                 qbuf, rbuf,
1210                 lsa_io_q_enum_privsaccount,
1211                 lsa_io_r_enum_privsaccount,
1212                 NT_STATUS_UNSUCCESSFUL);
1213
1214         /* Return output parameters */
1215
1216         result = r.status;
1217
1218         if (!NT_STATUS_IS_OK(result)) {
1219                 goto done;
1220         }
1221
1222         if (r.count == 0)
1223                 goto done;
1224
1225         if (!((*set = TALLOC_ARRAY(mem_ctx, LUID_ATTR, r.count)))) {
1226                 DEBUG(0, ("(cli_lsa_enum_privsaccount): out of memory\n"));
1227                 result = NT_STATUS_UNSUCCESSFUL;
1228                 goto done;
1229         }
1230
1231         for (i=0; i<r.count; i++) {
1232                 (*set)[i].luid.low = r.set.set[i].luid.low;
1233                 (*set)[i].luid.high = r.set.set[i].luid.high;
1234                 (*set)[i].attr = r.set.set[i].attr;
1235         }
1236
1237         *count=r.count;
1238  done:
1239
1240         return result;
1241 }
1242
1243 /** Get a privilege value given its name */
1244
1245 NTSTATUS rpccli_lsa_lookup_priv_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1246                                  POLICY_HND *pol, const char *name, LUID *luid)
1247 {
1248         prs_struct qbuf, rbuf;
1249         LSA_Q_LOOKUP_PRIV_VALUE q;
1250         LSA_R_LOOKUP_PRIV_VALUE r;
1251         NTSTATUS result;
1252
1253         ZERO_STRUCT(q);
1254         ZERO_STRUCT(r);
1255
1256         /* Marshall data and send request */
1257
1258         init_lsa_q_lookup_priv_value(&q, pol, name);
1259
1260         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPPRIVVALUE,
1261                 q, r,
1262                 qbuf, rbuf,
1263                 lsa_io_q_lookup_priv_value,
1264                 lsa_io_r_lookup_priv_value,
1265                 NT_STATUS_UNSUCCESSFUL);
1266
1267         result = r.status;
1268
1269         if (!NT_STATUS_IS_OK(result)) {
1270                 goto done;
1271         }
1272
1273         /* Return output parameters */
1274
1275         (*luid).low=r.luid.low;
1276         (*luid).high=r.luid.high;
1277
1278  done:
1279
1280         return result;
1281 }
1282
1283 /** Query LSA security object */
1284
1285 NTSTATUS rpccli_lsa_query_secobj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1286                               POLICY_HND *pol, uint32 sec_info, 
1287                               SEC_DESC_BUF **psdb)
1288 {
1289         prs_struct qbuf, rbuf;
1290         LSA_Q_QUERY_SEC_OBJ q;
1291         LSA_R_QUERY_SEC_OBJ r;
1292         NTSTATUS result;
1293
1294         ZERO_STRUCT(q);
1295         ZERO_STRUCT(r);
1296
1297         /* Marshall data and send request */
1298
1299         init_q_query_sec_obj(&q, pol, sec_info);
1300
1301         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYSECOBJ,
1302                 q, r,
1303                 qbuf, rbuf,
1304                 lsa_io_q_query_sec_obj,
1305                 lsa_io_r_query_sec_obj,
1306                 NT_STATUS_UNSUCCESSFUL);
1307
1308         result = r.status;
1309
1310         if (!NT_STATUS_IS_OK(result)) {
1311                 goto done;
1312         }
1313
1314         /* Return output parameters */
1315
1316         if (psdb)
1317                 *psdb = r.buf;
1318
1319  done:
1320
1321         return result;
1322 }
1323
1324
1325 /* Enumerate account rights This is similar to enum_privileges but
1326    takes a SID directly, avoiding the open_account call.
1327 */
1328
1329 NTSTATUS rpccli_lsa_enum_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1330                                      POLICY_HND *pol, DOM_SID *sid,
1331                                      uint32 *count, char ***priv_names)
1332 {
1333         prs_struct qbuf, rbuf;
1334         LSA_Q_ENUM_ACCT_RIGHTS q;
1335         LSA_R_ENUM_ACCT_RIGHTS r;
1336         NTSTATUS result;
1337         int i;
1338         fstring *privileges;
1339         char **names;
1340
1341         ZERO_STRUCT(q);
1342         ZERO_STRUCT(r);
1343
1344         /* Marshall data and send request */
1345         init_q_enum_acct_rights(&q, pol, 2, sid);
1346
1347         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMACCTRIGHTS,
1348                 q, r,
1349                 qbuf, rbuf,
1350                 lsa_io_q_enum_acct_rights,
1351                 lsa_io_r_enum_acct_rights,
1352                 NT_STATUS_UNSUCCESSFUL);
1353
1354         result = r.status;
1355
1356         if (!NT_STATUS_IS_OK(result)) {
1357                 goto done;
1358         }
1359
1360         *count = r.count;
1361         if (! *count) {
1362                 goto done;
1363         }
1364
1365         
1366         privileges = TALLOC_ARRAY( mem_ctx, fstring, *count );
1367         names      = TALLOC_ARRAY( mem_ctx, char *, *count );
1368
1369         if ((privileges == NULL) || (names == NULL)) {
1370                 TALLOC_FREE(privileges);
1371                 TALLOC_FREE(names);
1372                 return NT_STATUS_NO_MEMORY;
1373         }
1374
1375         for ( i=0; i<*count; i++ ) {
1376                 UNISTR4 *uni_string = &r.rights->strings[i];
1377
1378                 if ( !uni_string->string )
1379                         continue;
1380
1381                 rpcstr_pull( privileges[i], uni_string->string->buffer, sizeof(privileges[i]), -1, STR_TERMINATE );
1382                         
1383                 /* now copy to the return array */
1384                 names[i] = talloc_strdup( mem_ctx, privileges[i] );
1385         }
1386         
1387         *priv_names = names;
1388
1389 done:
1390
1391         return result;
1392 }
1393
1394
1395
1396 /* add account rights to an account. */
1397
1398 NTSTATUS rpccli_lsa_add_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1399                                     POLICY_HND *pol, DOM_SID sid,
1400                                         uint32 count, const char **privs_name)
1401 {
1402         prs_struct qbuf, rbuf;
1403         LSA_Q_ADD_ACCT_RIGHTS q;
1404         LSA_R_ADD_ACCT_RIGHTS r;
1405         NTSTATUS result;
1406
1407         ZERO_STRUCT(q);
1408         ZERO_STRUCT(r);
1409
1410         /* Marshall data and send request */
1411         init_q_add_acct_rights(&q, pol, &sid, count, privs_name);
1412
1413         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ADDACCTRIGHTS,
1414                 q, r,
1415                 qbuf, rbuf,
1416                 lsa_io_q_add_acct_rights,
1417                 lsa_io_r_add_acct_rights,
1418                 NT_STATUS_UNSUCCESSFUL);
1419
1420         result = r.status;
1421
1422         if (!NT_STATUS_IS_OK(result)) {
1423                 goto done;
1424         }
1425 done:
1426
1427         return result;
1428 }
1429
1430
1431 /* remove account rights for an account. */
1432
1433 NTSTATUS rpccli_lsa_remove_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1434                                        POLICY_HND *pol, DOM_SID sid, BOOL removeall,
1435                                        uint32 count, const char **privs_name)
1436 {
1437         prs_struct qbuf, rbuf;
1438         LSA_Q_REMOVE_ACCT_RIGHTS q;
1439         LSA_R_REMOVE_ACCT_RIGHTS r;
1440         NTSTATUS result;
1441
1442         ZERO_STRUCT(q);
1443         ZERO_STRUCT(r);
1444
1445         /* Marshall data and send request */
1446         init_q_remove_acct_rights(&q, pol, &sid, removeall?1:0, count, privs_name);
1447
1448         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_REMOVEACCTRIGHTS,
1449                 q, r,
1450                 qbuf, rbuf,
1451                 lsa_io_q_remove_acct_rights,
1452                 lsa_io_r_remove_acct_rights,
1453                 NT_STATUS_UNSUCCESSFUL);
1454
1455         result = r.status;
1456
1457         if (!NT_STATUS_IS_OK(result)) {
1458                 goto done;
1459         }
1460 done:
1461
1462         return result;
1463 }
1464
1465
1466 #if 0
1467
1468 /** An example of how to use the routines in this file.  Fetch a DOMAIN
1469     sid. Does complete cli setup / teardown anonymously. */
1470
1471 BOOL fetch_domain_sid( char *domain, char *remote_machine, DOM_SID *psid)
1472 {
1473         extern pstring global_myname;
1474         struct cli_state *cli;
1475         NTSTATUS result;
1476         POLICY_HND lsa_pol;
1477         BOOL ret = False;
1478  
1479         ZERO_STRUCT(cli);
1480         if((cli = cli_initialise()) == NULL) {
1481                 DEBUG(0,("fetch_domain_sid: unable to initialize client connection.\n"));
1482                 return False;
1483         }
1484  
1485         if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) {
1486                 DEBUG(0,("fetch_domain_sid: Can't resolve address for %s\n", remote_machine));
1487                 goto done;
1488         }
1489  
1490         if (!cli_connect(cli, remote_machine, &cli->dest_ip)) {
1491                 DEBUG(0,("fetch_domain_sid: unable to connect to SMB server on \
1492 machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
1493                 goto done;
1494         }
1495
1496         if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) {
1497                 DEBUG(0,("fetch_domain_sid: machine %s rejected the NetBIOS session request.\n", 
1498                         remote_machine));
1499                 goto done;
1500         }
1501  
1502         cli->protocol = PROTOCOL_NT1;
1503  
1504         if (!cli_negprot(cli)) {
1505                 DEBUG(0,("fetch_domain_sid: machine %s rejected the negotiate protocol. \
1506 Error was : %s.\n", remote_machine, cli_errstr(cli) ));
1507                 goto done;
1508         }
1509  
1510         if (cli->protocol != PROTOCOL_NT1) {
1511                 DEBUG(0,("fetch_domain_sid: machine %s didn't negotiate NT protocol.\n",
1512                         remote_machine));
1513                 goto done;
1514         }
1515  
1516         /*
1517          * Do an anonymous session setup.
1518          */
1519  
1520         if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
1521                 DEBUG(0,("fetch_domain_sid: machine %s rejected the session setup. \
1522 Error was : %s.\n", remote_machine, cli_errstr(cli) ));
1523                 goto done;
1524         }
1525  
1526         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
1527                 DEBUG(0,("fetch_domain_sid: machine %s isn't in user level security mode\n",
1528                         remote_machine));
1529                 goto done;
1530         }
1531
1532         if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
1533                 DEBUG(0,("fetch_domain_sid: machine %s rejected the tconX on the IPC$ share. \
1534 Error was : %s.\n", remote_machine, cli_errstr(cli) ));
1535                 goto done;
1536         }
1537
1538         /* Fetch domain sid */
1539  
1540         if (!cli_nt_session_open(cli, PI_LSARPC)) {
1541                 DEBUG(0, ("fetch_domain_sid: Error connecting to SAM pipe\n"));
1542                 goto done;
1543         }
1544  
1545         result = cli_lsa_open_policy(cli, cli->mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol);
1546         if (!NT_STATUS_IS_OK(result)) {
1547                 DEBUG(0, ("fetch_domain_sid: Error opening lsa policy handle. %s\n",
1548                         nt_errstr(result) ));
1549                 goto done;
1550         }
1551  
1552         result = cli_lsa_query_info_policy(cli, cli->mem_ctx, &lsa_pol, 5, domain, psid);
1553         if (!NT_STATUS_IS_OK(result)) {
1554                 DEBUG(0, ("fetch_domain_sid: Error querying lsa policy handle. %s\n",
1555                         nt_errstr(result) ));
1556                 goto done;
1557         }
1558  
1559         ret = True;
1560
1561   done:
1562
1563         cli_shutdown(cli);
1564         return ret;
1565 }
1566
1567 #endif
1568
1569 NTSTATUS rpccli_lsa_open_trusted_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1570                                      POLICY_HND *pol, DOM_SID *dom_sid, uint32 access_mask,
1571                                      POLICY_HND *trustdom_pol)
1572 {
1573         prs_struct qbuf, rbuf;
1574         LSA_Q_OPEN_TRUSTED_DOMAIN q;
1575         LSA_R_OPEN_TRUSTED_DOMAIN r;
1576         NTSTATUS result;
1577
1578         ZERO_STRUCT(q);
1579         ZERO_STRUCT(r);
1580
1581         /* Initialise input parameters */
1582
1583         init_lsa_q_open_trusted_domain(&q, pol, dom_sid, access_mask);
1584
1585         /* Marshall data and send request */
1586
1587         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENTRUSTDOM,
1588                 q, r,
1589                 qbuf, rbuf,
1590                 lsa_io_q_open_trusted_domain,
1591                 lsa_io_r_open_trusted_domain,
1592                 NT_STATUS_UNSUCCESSFUL);
1593
1594         /* Return output parameters */
1595         
1596         result = r.status;
1597
1598         if (NT_STATUS_IS_OK(result)) {
1599                 *trustdom_pol = r.handle;
1600         }
1601
1602         return result;
1603 }
1604
1605 NTSTATUS rpccli_lsa_query_trusted_domain_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1606                                            POLICY_HND *pol, 
1607                                            uint16 info_class,  
1608                                            LSA_TRUSTED_DOMAIN_INFO **info)
1609 {
1610         prs_struct qbuf, rbuf;
1611         LSA_Q_QUERY_TRUSTED_DOMAIN_INFO q;
1612         LSA_R_QUERY_TRUSTED_DOMAIN_INFO r;
1613         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1614
1615         ZERO_STRUCT(q);
1616         ZERO_STRUCT(r);
1617
1618         /* Marshall data and send request */
1619
1620         init_q_query_trusted_domain_info(&q, pol, info_class); 
1621
1622         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFO,
1623                 q, r,
1624                 qbuf, rbuf,
1625                 lsa_io_q_query_trusted_domain_info,
1626                 lsa_io_r_query_trusted_domain_info,
1627                 NT_STATUS_UNSUCCESSFUL);
1628
1629         result = r.status;
1630
1631         if (!NT_STATUS_IS_OK(result)) {
1632                 goto done;
1633         }
1634
1635         *info = r.info;
1636                 
1637 done:
1638         return result;
1639 }
1640
1641 NTSTATUS rpccli_lsa_open_trusted_domain_by_name(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1642                                                 POLICY_HND *pol, const char *name, uint32 access_mask,
1643                                                 POLICY_HND *trustdom_pol)
1644 {
1645         prs_struct qbuf, rbuf;
1646         LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME q;
1647         LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME r;
1648         NTSTATUS result;
1649
1650         ZERO_STRUCT(q);
1651         ZERO_STRUCT(r);
1652
1653         /* Initialise input parameters */
1654
1655         init_lsa_q_open_trusted_domain_by_name(&q, pol, name, access_mask);
1656
1657         /* Marshall data and send request */
1658
1659         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENTRUSTDOMBYNAME,
1660                 q, r,
1661                 qbuf, rbuf,
1662                 lsa_io_q_open_trusted_domain_by_name,
1663                 lsa_io_r_open_trusted_domain_by_name,
1664                 NT_STATUS_UNSUCCESSFUL);
1665
1666         /* Return output parameters */
1667         
1668         result = r.status;
1669
1670         if (NT_STATUS_IS_OK(result)) {
1671                 *trustdom_pol = r.handle;
1672         }
1673
1674         return result;
1675 }
1676
1677
1678 NTSTATUS rpccli_lsa_query_trusted_domain_info_by_sid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1679                                                   POLICY_HND *pol, 
1680                                                   uint16 info_class, DOM_SID *dom_sid, 
1681                                                   LSA_TRUSTED_DOMAIN_INFO **info)
1682 {
1683         prs_struct qbuf, rbuf;
1684         LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID q;
1685         LSA_R_QUERY_TRUSTED_DOMAIN_INFO r;
1686         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1687
1688         ZERO_STRUCT(q);
1689         ZERO_STRUCT(r);
1690
1691         /* Marshall data and send request */
1692
1693         init_q_query_trusted_domain_info_by_sid(&q, pol, info_class, dom_sid); 
1694
1695         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID,
1696                 q, r,
1697                 qbuf, rbuf,
1698                 lsa_io_q_query_trusted_domain_info_by_sid,
1699                 lsa_io_r_query_trusted_domain_info,
1700                 NT_STATUS_UNSUCCESSFUL);
1701
1702         result = r.status;
1703
1704         if (!NT_STATUS_IS_OK(result)) {
1705                 goto done;
1706         }
1707
1708         *info = r.info;
1709
1710 done:
1711
1712         return result;
1713 }
1714
1715 NTSTATUS rpccli_lsa_query_trusted_domain_info_by_name(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1716                                                    POLICY_HND *pol, 
1717                                                    uint16 info_class, const char *domain_name, 
1718                                                    LSA_TRUSTED_DOMAIN_INFO **info)
1719 {
1720         prs_struct qbuf, rbuf;
1721         LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME q;
1722         LSA_R_QUERY_TRUSTED_DOMAIN_INFO r;
1723         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1724
1725         ZERO_STRUCT(q);
1726         ZERO_STRUCT(r);
1727
1728         /* Marshall data and send request */
1729
1730         init_q_query_trusted_domain_info_by_name(&q, pol, info_class, domain_name); 
1731
1732         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME,
1733                 q, r,
1734                 qbuf, rbuf,
1735                 lsa_io_q_query_trusted_domain_info_by_name,
1736                 lsa_io_r_query_trusted_domain_info,
1737                 NT_STATUS_UNSUCCESSFUL);
1738
1739         result = r.status;
1740
1741         if (!NT_STATUS_IS_OK(result)) {
1742                 goto done;
1743         }
1744
1745         *info = r.info;
1746
1747 done:
1748         
1749         return result;
1750 }
1751
1752 NTSTATUS cli_lsa_query_domain_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1753                                           POLICY_HND *pol, 
1754                                           uint16 info_class, LSA_DOM_INFO_UNION **info)
1755 {
1756         prs_struct qbuf, rbuf;
1757         LSA_Q_QUERY_DOM_INFO_POLICY q;
1758         LSA_R_QUERY_DOM_INFO_POLICY r;
1759         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1760
1761         ZERO_STRUCT(q);
1762         ZERO_STRUCT(r);
1763
1764         /* Marshall data and send request */
1765
1766         init_q_query_dom_info(&q, pol, info_class); 
1767
1768         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYDOMINFOPOL, 
1769                 q, r,
1770                 qbuf, rbuf,
1771                 lsa_io_q_query_dom_info,
1772                 lsa_io_r_query_dom_info,
1773                 NT_STATUS_UNSUCCESSFUL);
1774
1775         result = r.status;
1776
1777         if (!NT_STATUS_IS_OK(result)) {
1778                 goto done;
1779         }
1780
1781         *info = r.info;
1782
1783 done:
1784         return result;
1785 }
1786