Remove unused marshalling for LSA_QUERY_INFO.
[ira/wip.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    Copyright (C) Michael Adam                           2007.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
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         NTSTATUS result = NT_STATUS_OK;
149         TALLOC_CTX *tmp_ctx = NULL;
150         int i;
151
152         tmp_ctx = talloc_new(mem_ctx);
153         if (!tmp_ctx) {
154                 DEBUG(0, ("rpccli_lsa_lookup_sids_noalloc: out of memory!\n"));
155                 result = NT_STATUS_UNSUCCESSFUL;
156                 goto done;
157         }
158
159         ZERO_STRUCT(q);
160         ZERO_STRUCT(r);
161
162         init_q_lookup_sids(tmp_ctx, &q, pol, num_sids, sids, 1);
163
164         ZERO_STRUCT(ref);
165
166         r.dom_ref = &ref;
167
168         CLI_DO_RPC( cli, tmp_ctx, PI_LSARPC, LSA_LOOKUPSIDS,
169                         q, r,
170                         qbuf, rbuf,
171                         lsa_io_q_lookup_sids,
172                         lsa_io_r_lookup_sids,
173                         NT_STATUS_UNSUCCESSFUL );
174
175         DEBUG(10, ("LSA_LOOKUPSIDS returned '%s', mapped count = %d'\n",
176                    nt_errstr(r.status), r.mapped_count));
177
178         if (!NT_STATUS_IS_OK(r.status) &&
179             !NT_STATUS_EQUAL(r.status, NT_STATUS_NONE_MAPPED) &&
180             !NT_STATUS_EQUAL(r.status, STATUS_SOME_UNMAPPED))
181         {
182                 /* An actual error occured */
183                 result = r.status;
184                 goto done;
185         }
186
187         /* Return output parameters */
188
189         if (NT_STATUS_EQUAL(r.status, NT_STATUS_NONE_MAPPED) ||
190             (r.mapped_count == 0))
191         {
192                 for (i = 0; i < num_sids; i++) {
193                         (names)[i] = NULL;
194                         (domains)[i] = NULL;
195                         (types)[i] = SID_NAME_UNKNOWN;
196                 }
197                 result = NT_STATUS_NONE_MAPPED;
198                 goto done;
199         }
200
201         for (i = 0; i < num_sids; i++) {
202                 fstring name, dom_name;
203                 uint32 dom_idx = r.names.name[i].domain_idx;
204
205                 /* Translate optimised name through domain index array */
206
207                 if (dom_idx != 0xffffffff) {
208
209                         rpcstr_pull_unistr2_fstring(
210                                 dom_name, &ref.ref_dom[dom_idx].uni_dom_name);
211                         rpcstr_pull_unistr2_fstring(
212                                 name, &r.names.uni_name[i]);
213
214                         (names)[i] = talloc_strdup(mem_ctx, name);
215                         (domains)[i] = talloc_strdup(mem_ctx, dom_name);
216                         (types)[i] = r.names.name[i].sid_name_use;
217
218                         if (((names)[i] == NULL) || ((domains)[i] == NULL)) {
219                                 DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n"));
220                                 result = NT_STATUS_UNSUCCESSFUL;
221                                 goto done;
222                         }
223
224                 } else {
225                         (names)[i] = NULL;
226                         (domains)[i] = NULL;
227                         (types)[i] = SID_NAME_UNKNOWN;
228                 }
229         }
230
231 done:
232         TALLOC_FREE(tmp_ctx);
233         return result;
234 }
235
236 /* Lookup a list of sids
237  *
238  * do it the right way: there is a limit (of 20480 for w2k3) entries
239  * returned by this call. when the sids list contains more entries,
240  * empty lists are returned. This version of lsa_lookup_sids passes
241  * the list of sids in hunks of LOOKUP_SIDS_HUNK_SIZE to the lsa call. */
242
243 /* This constant defines the limit of how many sids to look up
244  * in one call (maximum). the limit from the server side is
245  * at 20480 for win2k3, but we keep it at a save 1000 for now. */
246 #define LOOKUP_SIDS_HUNK_SIZE 1000
247
248 NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
249                                 TALLOC_CTX *mem_ctx,
250                                 POLICY_HND *pol,
251                                 int num_sids,
252                                 const DOM_SID *sids,
253                                 char ***domains,
254                                 char ***names,
255                                 enum lsa_SidType **types)
256 {
257         NTSTATUS result = NT_STATUS_OK;
258         int sids_left = 0;
259         int sids_processed = 0;
260         const DOM_SID *hunk_sids = sids;
261         char **hunk_domains = NULL;
262         char **hunk_names = NULL;
263         enum lsa_SidType *hunk_types = NULL;
264
265         if (num_sids) {
266                 if (!((*domains) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
267                         DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
268                         result = NT_STATUS_NO_MEMORY;
269                         goto fail;
270                 }
271
272                 if (!((*names) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
273                         DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
274                         result = NT_STATUS_NO_MEMORY;
275                         goto fail;
276                 }
277
278                 if (!((*types) = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_sids))) {
279                         DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
280                         result = NT_STATUS_NO_MEMORY;
281                         goto fail;
282                 }
283         } else {
284                 (*domains) = NULL;
285                 (*names) = NULL;
286                 (*types) = NULL;
287         }
288
289         sids_left = num_sids;
290         hunk_domains = *domains;
291         hunk_names = *names;
292         hunk_types = *types;
293
294         while (sids_left > 0) {
295                 int hunk_num_sids;
296                 NTSTATUS hunk_result = NT_STATUS_OK;
297
298                 hunk_num_sids = ((sids_left > LOOKUP_SIDS_HUNK_SIZE)
299                                 ? LOOKUP_SIDS_HUNK_SIZE
300                                 : sids_left);
301
302                 DEBUG(10, ("rpccli_lsa_lookup_sids: processing items "
303                            "%d -- %d of %d.\n",
304                            sids_processed,
305                            sids_processed + hunk_num_sids - 1,
306                            num_sids));
307
308                 hunk_result = rpccli_lsa_lookup_sids_noalloc(cli,
309                                                              mem_ctx,
310                                                              pol,
311                                                              hunk_num_sids,
312                                                              hunk_sids,
313                                                              hunk_domains,
314                                                              hunk_names,
315                                                              hunk_types);
316
317                 if (!NT_STATUS_IS_OK(hunk_result) &&
318                     !NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED) &&
319                     !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED))
320                 {
321                         /* An actual error occured */
322                         result = hunk_result;
323                         goto fail;
324                 }
325
326                 /* adapt overall result */
327                 if (( NT_STATUS_IS_OK(result) &&
328                      !NT_STATUS_IS_OK(hunk_result))
329                     ||
330                     ( NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) &&
331                      !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED)))
332                 {
333                         result = STATUS_SOME_UNMAPPED;
334                 }
335
336                 sids_left -= hunk_num_sids;
337                 sids_processed += hunk_num_sids; /* only used in DEBUG */
338                 hunk_sids += hunk_num_sids;
339                 hunk_domains += hunk_num_sids;
340                 hunk_names += hunk_num_sids;
341                 hunk_types += hunk_num_sids;
342         }
343
344         return result;
345
346 fail:
347         TALLOC_FREE(*domains);
348         TALLOC_FREE(*names);
349         TALLOC_FREE(*types);
350         return result;
351 }
352
353 /** Lookup a list of names */
354
355 NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
356                                  TALLOC_CTX *mem_ctx,
357                                  POLICY_HND *pol, int num_names,
358                                  const char **names,
359                                  const char ***dom_names,
360                                  int level,
361                                  DOM_SID **sids,
362                                  enum lsa_SidType **types)
363 {
364         prs_struct qbuf, rbuf;
365         LSA_Q_LOOKUP_NAMES q;
366         LSA_R_LOOKUP_NAMES r;
367         DOM_R_REF ref;
368         NTSTATUS result;
369         int i;
370
371         ZERO_STRUCT(q);
372         ZERO_STRUCT(r);
373
374         ZERO_STRUCT(ref);
375         r.dom_ref = &ref;
376
377         init_q_lookup_names(mem_ctx, &q, pol, num_names, names, level);
378
379         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPNAMES,
380                         q, r,
381                         qbuf, rbuf,
382                         lsa_io_q_lookup_names,
383                         lsa_io_r_lookup_names,
384                         NT_STATUS_UNSUCCESSFUL);
385
386         result = r.status;
387
388         if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) !=
389             NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
390
391                 /* An actual error occured */
392
393                 goto done;
394         }
395
396         /* Return output parameters */
397
398         if (r.mapped_count == 0) {
399                 result = NT_STATUS_NONE_MAPPED;
400                 goto done;
401         }
402
403         if (num_names) {
404                 if (!((*sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_names)))) {
405                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
406                         result = NT_STATUS_NO_MEMORY;
407                         goto done;
408                 }
409
410                 if (!((*types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_names)))) {
411                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
412                         result = NT_STATUS_NO_MEMORY;
413                         goto done;
414                 }
415
416                 if (dom_names != NULL) {
417                         *dom_names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
418                         if (*dom_names == NULL) {
419                                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
420                                 result = NT_STATUS_NO_MEMORY;
421                                 goto done;
422                         }
423                 }
424         } else {
425                 *sids = NULL;
426                 *types = NULL;
427                 if (dom_names != NULL) {
428                         *dom_names = NULL;
429                 }
430         }
431
432         for (i = 0; i < num_names; i++) {
433                 DOM_RID *t_rids = r.dom_rid;
434                 uint32 dom_idx = t_rids[i].rid_idx;
435                 uint32 dom_rid = t_rids[i].rid;
436                 DOM_SID *sid = &(*sids)[i];
437
438                 /* Translate optimised sid through domain index array */
439
440                 if (dom_idx == 0xffffffff) {
441                         /* Nothing to do, this is unknown */
442                         ZERO_STRUCTP(sid);
443                         (*types)[i] = SID_NAME_UNKNOWN;
444                         continue;
445                 }
446
447                 sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
448
449                 if (dom_rid != 0xffffffff) {
450                         sid_append_rid(sid, dom_rid);
451                 }
452
453                 (*types)[i] = t_rids[i].type;
454
455                 if (dom_names == NULL) {
456                         continue;
457                 }
458
459                 (*dom_names)[i] = rpcstr_pull_unistr2_talloc(
460                         *dom_names, &ref.ref_dom[dom_idx].uni_dom_name);
461         }
462
463  done:
464
465         return result;
466 }
467
468 /**
469  * Enumerate list of trusted domains
470  *
471  * @param cli client state (cli_state) structure of the connection
472  * @param mem_ctx memory context
473  * @param pol opened lsa policy handle
474  * @param enum_ctx enumeration context ie. index of first returned domain entry
475  * @param pref_num_domains preferred max number of entries returned in one response
476  * @param num_domains total number of trusted domains returned by response
477  * @param domain_names returned trusted domain names
478  * @param domain_sids returned trusted domain sids
479  *
480  * @return nt status code of response
481  **/
482
483 NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli,
484                                    TALLOC_CTX *mem_ctx,
485                                    POLICY_HND *pol, uint32 *enum_ctx,
486                                    uint32 *num_domains,
487                                    char ***domain_names, DOM_SID **domain_sids)
488 {
489         prs_struct qbuf, rbuf;
490         LSA_Q_ENUM_TRUST_DOM in;
491         LSA_R_ENUM_TRUST_DOM out;
492         int i;
493         fstring tmp;
494
495         ZERO_STRUCT(in);
496         ZERO_STRUCT(out);
497
498         /* 64k is enough for about 2000 trusted domains */
499
500         init_q_enum_trust_dom(&in, pol, *enum_ctx, 0x10000);
501
502         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM,
503                     in, out,
504                     qbuf, rbuf,
505                     lsa_io_q_enum_trust_dom,
506                     lsa_io_r_enum_trust_dom,
507                     NT_STATUS_UNSUCCESSFUL );
508
509
510         /* check for an actual error */
511
512         if ( !NT_STATUS_IS_OK(out.status)
513                 && !NT_STATUS_EQUAL(out.status, NT_STATUS_NO_MORE_ENTRIES)
514                 && !NT_STATUS_EQUAL(out.status, STATUS_MORE_ENTRIES) )
515         {
516                 return out.status;
517         }
518
519         /* Return output parameters */
520
521         *num_domains  = out.count;
522         *enum_ctx     = out.enum_context;
523
524         if ( out.count ) {
525
526                 /* Allocate memory for trusted domain names and sids */
527
528                 if ( !(*domain_names = TALLOC_ARRAY(mem_ctx, char *, out.count)) ) {
529                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
530                         return NT_STATUS_NO_MEMORY;
531                 }
532
533                 if ( !(*domain_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, out.count)) ) {
534                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
535                         return NT_STATUS_NO_MEMORY;
536                 }
537
538                 /* Copy across names and sids */
539
540                 for (i = 0; i < out.count; i++) {
541
542                         rpcstr_pull( tmp, out.domlist->domains[i].name.string->buffer,
543                                 sizeof(tmp), out.domlist->domains[i].name.length, 0);
544                         (*domain_names)[i] = talloc_strdup(mem_ctx, tmp);
545
546                         sid_copy(&(*domain_sids)[i], &out.domlist->domains[i].sid->sid );
547                 }
548         }
549
550         return out.status;
551 }
552
553 /** Enumerate privileges*/
554
555 NTSTATUS rpccli_lsa_enum_privilege(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
556                                 POLICY_HND *pol, uint32 *enum_context, uint32 pref_max_length,
557                                 uint32 *count, char ***privs_name, uint32 **privs_high, uint32 **privs_low)
558 {
559         prs_struct qbuf, rbuf;
560         LSA_Q_ENUM_PRIVS q;
561         LSA_R_ENUM_PRIVS r;
562         NTSTATUS result;
563         int i;
564
565         ZERO_STRUCT(q);
566         ZERO_STRUCT(r);
567
568         init_q_enum_privs(&q, pol, *enum_context, pref_max_length);
569
570         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_PRIVS,
571                 q, r,
572                 qbuf, rbuf,
573                 lsa_io_q_enum_privs,
574                 lsa_io_r_enum_privs,
575                 NT_STATUS_UNSUCCESSFUL);
576
577         result = r.status;
578
579         if (!NT_STATUS_IS_OK(result)) {
580                 goto done;
581         }
582
583         /* Return output parameters */
584
585         *enum_context = r.enum_context;
586         *count = r.count;
587
588         if (r.count) {
589                 if (!((*privs_name = TALLOC_ARRAY(mem_ctx, char *, r.count)))) {
590                         DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
591                         result = NT_STATUS_UNSUCCESSFUL;
592                         goto done;
593                 }
594
595                 if (!((*privs_high = TALLOC_ARRAY(mem_ctx, uint32, r.count)))) {
596                         DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
597                         result = NT_STATUS_UNSUCCESSFUL;
598                         goto done;
599                 }
600
601                 if (!((*privs_low = TALLOC_ARRAY(mem_ctx, uint32, r.count)))) {
602                         DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
603                         result = NT_STATUS_UNSUCCESSFUL;
604                         goto done;
605                 }
606         } else {
607                 *privs_name = NULL;
608                 *privs_high = NULL;
609                 *privs_low = NULL;
610         }
611
612         for (i = 0; i < r.count; i++) {
613                 fstring name;
614
615                 rpcstr_pull_unistr2_fstring( name, &r.privs[i].name);
616
617                 (*privs_name)[i] = talloc_strdup(mem_ctx, name);
618
619                 (*privs_high)[i] = r.privs[i].luid_high;
620                 (*privs_low)[i] = r.privs[i].luid_low;
621         }
622
623  done:
624
625         return result;
626 }
627
628 /** Get privilege name */
629
630 NTSTATUS rpccli_lsa_get_dispname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
631                               POLICY_HND *pol, const char *name,
632                               uint16 lang_id, uint16 lang_id_sys,
633                               fstring description, uint16 *lang_id_desc)
634 {
635         prs_struct qbuf, rbuf;
636         LSA_Q_PRIV_GET_DISPNAME q;
637         LSA_R_PRIV_GET_DISPNAME r;
638         NTSTATUS result;
639
640         ZERO_STRUCT(q);
641         ZERO_STRUCT(r);
642
643         init_lsa_priv_get_dispname(&q, pol, name, lang_id, lang_id_sys);
644
645         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_PRIV_GET_DISPNAME,
646                 q, r,
647                 qbuf, rbuf,
648                 lsa_io_q_priv_get_dispname,
649                 lsa_io_r_priv_get_dispname,
650                 NT_STATUS_UNSUCCESSFUL);
651
652         result = r.status;
653
654         if (!NT_STATUS_IS_OK(result)) {
655                 goto done;
656         }
657
658         /* Return output parameters */
659
660         rpcstr_pull_unistr2_fstring(description , &r.desc);
661         *lang_id_desc = r.lang_id;
662
663  done:
664
665         return result;
666 }
667
668 /** Enumerate list of SIDs  */
669
670 NTSTATUS rpccli_lsa_enum_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
671                                 POLICY_HND *pol, uint32 *enum_ctx, uint32 pref_max_length,
672                                 uint32 *num_sids, DOM_SID **sids)
673 {
674         prs_struct qbuf, rbuf;
675         LSA_Q_ENUM_ACCOUNTS q;
676         LSA_R_ENUM_ACCOUNTS r;
677         NTSTATUS result;
678         int i;
679
680         ZERO_STRUCT(q);
681         ZERO_STRUCT(r);
682
683         init_lsa_q_enum_accounts(&q, pol, *enum_ctx, pref_max_length);
684
685         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_ACCOUNTS,
686                 q, r,
687                 qbuf, rbuf,
688                 lsa_io_q_enum_accounts,
689                 lsa_io_r_enum_accounts,
690                 NT_STATUS_UNSUCCESSFUL);
691
692         result = r.status;
693
694         if (!NT_STATUS_IS_OK(result)) {
695                 goto done;
696         }
697
698         if (r.sids.num_entries==0)
699                 goto done;
700
701         /* Return output parameters */
702
703         *sids = TALLOC_ARRAY(mem_ctx, DOM_SID, r.sids.num_entries);
704         if (!*sids) {
705                 DEBUG(0, ("(cli_lsa_enum_sids): out of memory\n"));
706                 result = NT_STATUS_UNSUCCESSFUL;
707                 goto done;
708         }
709
710         /* Copy across names and sids */
711
712         for (i = 0; i < r.sids.num_entries; i++) {
713                 sid_copy(&(*sids)[i], &r.sids.sid[i].sid);
714         }
715
716         *num_sids= r.sids.num_entries;
717         *enum_ctx = r.enum_context;
718
719  done:
720
721         return result;
722 }
723
724 /** Create a LSA user handle
725  *
726  * @param cli Handle on an initialised SMB connection
727  *
728  * FIXME: The code is actually identical to open account
729  * TODO: Check and code what the function should exactly do
730  *
731  * */
732
733 NTSTATUS rpccli_lsa_create_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
734                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 desired_access,
735                              POLICY_HND *user_pol)
736 {
737         prs_struct qbuf, rbuf;
738         LSA_Q_CREATEACCOUNT q;
739         LSA_R_CREATEACCOUNT r;
740         NTSTATUS result;
741
742         ZERO_STRUCT(q);
743         ZERO_STRUCT(r);
744
745         /* Initialise input parameters */
746
747         init_lsa_q_create_account(&q, dom_pol, sid, desired_access);
748
749         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_CREATEACCOUNT,
750                 q, r,
751                 qbuf, rbuf,
752                 lsa_io_q_create_account,
753                 lsa_io_r_create_account,
754                 NT_STATUS_UNSUCCESSFUL);
755
756         /* Return output parameters */
757
758         result = r.status;
759
760         if (NT_STATUS_IS_OK(result)) {
761                 *user_pol = r.pol;
762         }
763
764         return result;
765 }
766
767 /** Open a LSA user handle
768  *
769  * @param cli Handle on an initialised SMB connection */
770
771 NTSTATUS rpccli_lsa_open_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
772                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 des_access,
773                              POLICY_HND *user_pol)
774 {
775         prs_struct qbuf, rbuf;
776         LSA_Q_OPENACCOUNT q;
777         LSA_R_OPENACCOUNT r;
778         NTSTATUS result;
779
780         ZERO_STRUCT(q);
781         ZERO_STRUCT(r);
782
783         /* Initialise input parameters */
784
785         init_lsa_q_open_account(&q, dom_pol, sid, des_access);
786
787         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENACCOUNT,
788                 q, r,
789                 qbuf, rbuf,
790                 lsa_io_q_open_account,
791                 lsa_io_r_open_account,
792                 NT_STATUS_UNSUCCESSFUL);
793
794         /* Return output parameters */
795
796         result = r.status;
797
798         if (NT_STATUS_IS_OK(result)) {
799                 *user_pol = r.pol;
800         }
801
802         return result;
803 }
804
805 /** Enumerate user privileges
806  *
807  * @param cli Handle on an initialised SMB connection */
808
809 NTSTATUS rpccli_lsa_enum_privsaccount(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
810                              POLICY_HND *pol, uint32 *count, LUID_ATTR **set)
811 {
812         prs_struct qbuf, rbuf;
813         LSA_Q_ENUMPRIVSACCOUNT q;
814         LSA_R_ENUMPRIVSACCOUNT r;
815         NTSTATUS result;
816         int i;
817
818         ZERO_STRUCT(q);
819         ZERO_STRUCT(r);
820
821         /* Initialise input parameters */
822
823         init_lsa_q_enum_privsaccount(&q, pol);
824
825         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMPRIVSACCOUNT,
826                 q, r,
827                 qbuf, rbuf,
828                 lsa_io_q_enum_privsaccount,
829                 lsa_io_r_enum_privsaccount,
830                 NT_STATUS_UNSUCCESSFUL);
831
832         /* Return output parameters */
833
834         result = r.status;
835
836         if (!NT_STATUS_IS_OK(result)) {
837                 goto done;
838         }
839
840         if (r.count == 0)
841                 goto done;
842
843         if (!((*set = TALLOC_ARRAY(mem_ctx, LUID_ATTR, r.count)))) {
844                 DEBUG(0, ("(cli_lsa_enum_privsaccount): out of memory\n"));
845                 result = NT_STATUS_UNSUCCESSFUL;
846                 goto done;
847         }
848
849         for (i=0; i<r.count; i++) {
850                 (*set)[i].luid.low = r.set.set[i].luid.low;
851                 (*set)[i].luid.high = r.set.set[i].luid.high;
852                 (*set)[i].attr = r.set.set[i].attr;
853         }
854
855         *count=r.count;
856  done:
857
858         return result;
859 }
860
861 /** Get a privilege value given its name */
862
863 NTSTATUS rpccli_lsa_lookup_priv_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
864                                  POLICY_HND *pol, const char *name, LUID *luid)
865 {
866         prs_struct qbuf, rbuf;
867         LSA_Q_LOOKUP_PRIV_VALUE q;
868         LSA_R_LOOKUP_PRIV_VALUE r;
869         NTSTATUS result;
870
871         ZERO_STRUCT(q);
872         ZERO_STRUCT(r);
873
874         /* Marshall data and send request */
875
876         init_lsa_q_lookup_priv_value(&q, pol, name);
877
878         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPPRIVVALUE,
879                 q, r,
880                 qbuf, rbuf,
881                 lsa_io_q_lookup_priv_value,
882                 lsa_io_r_lookup_priv_value,
883                 NT_STATUS_UNSUCCESSFUL);
884
885         result = r.status;
886
887         if (!NT_STATUS_IS_OK(result)) {
888                 goto done;
889         }
890
891         /* Return output parameters */
892
893         (*luid).low=r.luid.low;
894         (*luid).high=r.luid.high;
895
896  done:
897
898         return result;
899 }
900
901 /* Enumerate account rights This is similar to enum_privileges but
902    takes a SID directly, avoiding the open_account call.
903 */
904
905 NTSTATUS rpccli_lsa_enum_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
906                                      POLICY_HND *pol, DOM_SID *sid,
907                                      uint32 *count, char ***priv_names)
908 {
909         prs_struct qbuf, rbuf;
910         LSA_Q_ENUM_ACCT_RIGHTS q;
911         LSA_R_ENUM_ACCT_RIGHTS r;
912         NTSTATUS result;
913         int i;
914         fstring *privileges;
915         char **names;
916
917         ZERO_STRUCT(q);
918         ZERO_STRUCT(r);
919
920         /* Marshall data and send request */
921         init_q_enum_acct_rights(&q, pol, 2, sid);
922
923         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMACCTRIGHTS,
924                 q, r,
925                 qbuf, rbuf,
926                 lsa_io_q_enum_acct_rights,
927                 lsa_io_r_enum_acct_rights,
928                 NT_STATUS_UNSUCCESSFUL);
929
930         result = r.status;
931
932         if (!NT_STATUS_IS_OK(result)) {
933                 goto done;
934         }
935
936         *count = r.count;
937         if (! *count) {
938                 goto done;
939         }
940
941
942         privileges = TALLOC_ARRAY( mem_ctx, fstring, *count );
943         names      = TALLOC_ARRAY( mem_ctx, char *, *count );
944
945         if ((privileges == NULL) || (names == NULL)) {
946                 TALLOC_FREE(privileges);
947                 TALLOC_FREE(names);
948                 return NT_STATUS_NO_MEMORY;
949         }
950
951         for ( i=0; i<*count; i++ ) {
952                 UNISTR4 *uni_string = &r.rights->strings[i];
953
954                 if ( !uni_string->string )
955                         continue;
956
957                 rpcstr_pull( privileges[i], uni_string->string->buffer, sizeof(privileges[i]), -1, STR_TERMINATE );
958
959                 /* now copy to the return array */
960                 names[i] = talloc_strdup( mem_ctx, privileges[i] );
961         }
962
963         *priv_names = names;
964
965 done:
966
967         return result;
968 }
969
970
971
972 /* add account rights to an account. */
973
974 NTSTATUS rpccli_lsa_add_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
975                                     POLICY_HND *pol, DOM_SID sid,
976                                         uint32 count, const char **privs_name)
977 {
978         prs_struct qbuf, rbuf;
979         LSA_Q_ADD_ACCT_RIGHTS q;
980         LSA_R_ADD_ACCT_RIGHTS r;
981         NTSTATUS result;
982
983         ZERO_STRUCT(q);
984         ZERO_STRUCT(r);
985
986         /* Marshall data and send request */
987         init_q_add_acct_rights(&q, pol, &sid, count, privs_name);
988
989         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ADDACCTRIGHTS,
990                 q, r,
991                 qbuf, rbuf,
992                 lsa_io_q_add_acct_rights,
993                 lsa_io_r_add_acct_rights,
994                 NT_STATUS_UNSUCCESSFUL);
995
996         result = r.status;
997
998         if (!NT_STATUS_IS_OK(result)) {
999                 goto done;
1000         }
1001 done:
1002
1003         return result;
1004 }
1005
1006
1007 /* remove account rights for an account. */
1008
1009 NTSTATUS rpccli_lsa_remove_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1010                                        POLICY_HND *pol, DOM_SID sid, bool removeall,
1011                                        uint32 count, const char **privs_name)
1012 {
1013         prs_struct qbuf, rbuf;
1014         LSA_Q_REMOVE_ACCT_RIGHTS q;
1015         LSA_R_REMOVE_ACCT_RIGHTS r;
1016         NTSTATUS result;
1017
1018         ZERO_STRUCT(q);
1019         ZERO_STRUCT(r);
1020
1021         /* Marshall data and send request */
1022         init_q_remove_acct_rights(&q, pol, &sid, removeall?1:0, count, privs_name);
1023
1024         CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_REMOVEACCTRIGHTS,
1025                 q, r,
1026                 qbuf, rbuf,
1027                 lsa_io_q_remove_acct_rights,
1028                 lsa_io_r_remove_acct_rights,
1029                 NT_STATUS_UNSUCCESSFUL);
1030
1031         result = r.status;
1032
1033         if (!NT_STATUS_IS_OK(result)) {
1034                 goto done;
1035         }
1036 done:
1037
1038         return result;
1039 }
1040
1041
1042 #if 0
1043
1044 /** An example of how to use the routines in this file.  Fetch a DOMAIN
1045     sid. Does complete cli setup / teardown anonymously. */
1046
1047 bool fetch_domain_sid( char *domain, char *remote_machine, DOM_SID *psid)
1048 {
1049         struct cli_state cli;
1050         NTSTATUS result;
1051         POLICY_HND lsa_pol;
1052         bool ret = False;
1053
1054         ZERO_STRUCT(cli);
1055         if(cli_initialise(&cli) == False) {
1056                 DEBUG(0,("fetch_domain_sid: unable to initialize client connection.\n"));
1057                 return False;
1058         }
1059
1060         if(!resolve_name( remote_machine, &cli.dest_ip, 0x20)) {
1061                 DEBUG(0,("fetch_domain_sid: Can't resolve address for %s\n", remote_machine));
1062                 goto done;
1063         }
1064
1065         if (!cli_connect(&cli, remote_machine, &cli.dest_ip)) {
1066                 DEBUG(0,("fetch_domain_sid: unable to connect to SMB server on \
1067 machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1068                 goto done;
1069         }
1070
1071         if (!attempt_netbios_session_request(&cli, global_myname(), remote_machine, &cli.dest_ip)) {
1072                 DEBUG(0,("fetch_domain_sid: machine %s rejected the NetBIOS session request.\n",
1073                         remote_machine));
1074                 goto done;
1075         }
1076
1077         cli.protocol = PROTOCOL_NT1;
1078
1079         if (!cli_negprot(&cli)) {
1080                 DEBUG(0,("fetch_domain_sid: machine %s rejected the negotiate protocol. \
1081 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1082                 goto done;
1083         }
1084
1085         if (cli.protocol != PROTOCOL_NT1) {
1086                 DEBUG(0,("fetch_domain_sid: machine %s didn't negotiate NT protocol.\n",
1087                         remote_machine));
1088                 goto done;
1089         }
1090
1091         /*
1092          * Do an anonymous session setup.
1093          */
1094
1095         if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
1096                 DEBUG(0,("fetch_domain_sid: machine %s rejected the session setup. \
1097 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1098                 goto done;
1099         }
1100
1101         if (!(cli.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
1102                 DEBUG(0,("fetch_domain_sid: machine %s isn't in user level security mode\n",
1103                         remote_machine));
1104                 goto done;
1105         }
1106
1107         if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
1108                 DEBUG(0,("fetch_domain_sid: machine %s rejected the tconX on the IPC$ share. \
1109 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1110                 goto done;
1111         }
1112
1113         /* Fetch domain sid */
1114
1115         if (!cli_nt_session_open(&cli, PI_LSARPC)) {
1116                 DEBUG(0, ("fetch_domain_sid: Error connecting to SAM pipe\n"));
1117                 goto done;
1118         }
1119
1120         result = cli_lsa_open_policy(&cli, cli.mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol);
1121         if (!NT_STATUS_IS_OK(result)) {
1122                 DEBUG(0, ("fetch_domain_sid: Error opening lsa policy handle. %s\n",
1123                         nt_errstr(result) ));
1124                 goto done;
1125         }
1126
1127         result = cli_lsa_query_info_policy(&cli, cli.mem_ctx, &lsa_pol, 5, domain, psid);
1128         if (!NT_STATUS_IS_OK(result)) {
1129                 DEBUG(0, ("fetch_domain_sid: Error querying lsa policy handle. %s\n",
1130                         nt_errstr(result) ));
1131                 goto done;
1132         }
1133
1134         ret = True;
1135
1136   done:
1137
1138         cli_shutdown(&cli);
1139         return ret;
1140 }
1141
1142 #endif