Removed version number from file header.
[samba.git] / source3 / libsmb / 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) Luke Kenneth Casson Leighton 1996-1997,2000,
7    Copyright (C) Paul Ashton                       1997,2000,
8    Copyright (C) Elrond                                 2000.
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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
27 /** @defgroup lsa LSA - Local Security Architecture
28  *  @ingroup rpc_client
29  *
30  * @{
31  **/
32
33 /**
34  * @file cli_lsarpc.c
35  *
36  * RPC client routines for the LSA RPC pipe.  LSA means "local
37  * security authority", which is half of a password database.
38  **/
39
40 /** Opens a SMB connection and connects to the LSARPC pipe.
41  *
42  * @param cli Uninitialised client handle.
43  * @param system_name NETBIOS name of the machine to connect to.
44  * @param creds User credentials to connect as.
45  * @returns Initialised client handle.
46  */
47 struct cli_state *cli_lsa_initialise(struct cli_state *cli, char *system_name,
48                                      struct ntuser_creds *creds)
49 {
50         return cli_pipe_initialise(cli, system_name, PIPE_LSARPC, creds);
51 }
52
53 /** Open a LSA policy handle
54  *
55  * @param cli Handle on an initialised SMB connection */
56
57 NTSTATUS cli_lsa_open_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
58                              BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
59 {
60         prs_struct qbuf, rbuf;
61         LSA_Q_OPEN_POL q;
62         LSA_R_OPEN_POL r;
63         LSA_SEC_QOS qos;
64         NTSTATUS result;
65
66         ZERO_STRUCT(q);
67         ZERO_STRUCT(r);
68
69         /* Initialise parse structures */
70
71         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
72         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
73
74         /* Initialise input parameters */
75
76         if (sec_qos) {
77                 init_lsa_sec_qos(&qos, 2, 1, 0);
78                 init_q_open_pol(&q, '\\', 0, des_access, &qos);
79         } else {
80                 init_q_open_pol(&q, '\\', 0, des_access, NULL);
81         }
82
83         /* Marshall data and send request */
84
85         if (!lsa_io_q_open_pol("", &q, &qbuf, 0) ||
86             !rpc_api_pipe_req(cli, LSA_OPENPOLICY, &qbuf, &rbuf)) {
87                 result = NT_STATUS_UNSUCCESSFUL;
88                 goto done;
89         }
90
91         /* Unmarshall response */
92
93         if (!lsa_io_r_open_pol("", &r, &rbuf, 0)) {
94                 result = NT_STATUS_UNSUCCESSFUL;
95                 goto done;
96         }
97
98         /* Return output parameters */
99
100         if (NT_STATUS_IS_OK(result = r.status)) {
101                 *pol = r.pol;
102         }
103
104  done:
105         prs_mem_free(&qbuf);
106         prs_mem_free(&rbuf);
107
108         return result;
109 }
110
111 /** Open a LSA policy handle */
112
113 NTSTATUS cli_lsa_open_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
114                               BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
115 {
116         prs_struct qbuf, rbuf;
117         LSA_Q_OPEN_POL2 q;
118         LSA_R_OPEN_POL2 r;
119         LSA_SEC_QOS qos;
120         NTSTATUS result;
121
122         ZERO_STRUCT(q);
123         ZERO_STRUCT(r);
124
125         /* Initialise parse structures */
126
127         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
128         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
129
130         /* Initialise input parameters */
131
132         if (sec_qos) {
133                 init_lsa_sec_qos(&qos, 2, 1, 0);
134                 init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access, 
135                                  &qos);
136         } else {
137                 init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access, 
138                                  NULL);
139         }
140
141         /* Marshall data and send request */
142
143         if (!lsa_io_q_open_pol2("", &q, &qbuf, 0) ||
144             !rpc_api_pipe_req(cli, LSA_OPENPOLICY2, &qbuf, &rbuf)) {
145                 result = NT_STATUS_UNSUCCESSFUL;
146                 goto done;
147         }
148
149         /* Unmarshall response */
150
151         if (!lsa_io_r_open_pol2("", &r, &rbuf, 0)) {
152                 result = NT_STATUS_UNSUCCESSFUL;
153                 goto done;
154         }
155
156         /* Return output parameters */
157
158         if (NT_STATUS_IS_OK(result = r.status)) {
159                 *pol = r.pol;
160         }
161
162  done:
163         prs_mem_free(&qbuf);
164         prs_mem_free(&rbuf);
165
166         return result;
167 }
168
169 /** Close a LSA policy handle */
170
171 NTSTATUS cli_lsa_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
172                        POLICY_HND *pol)
173 {
174         prs_struct qbuf, rbuf;
175         LSA_Q_CLOSE q;
176         LSA_R_CLOSE r;
177         NTSTATUS result;
178
179         ZERO_STRUCT(q);
180         ZERO_STRUCT(r);
181
182         /* Initialise parse structures */
183
184         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
185         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
186
187         /* Marshall data and send request */
188
189         init_lsa_q_close(&q, pol);
190
191         if (!lsa_io_q_close("", &q, &qbuf, 0) ||
192             !rpc_api_pipe_req(cli, LSA_CLOSE, &qbuf, &rbuf)) {
193                 result = NT_STATUS_UNSUCCESSFUL;
194                 goto done;
195         }
196
197         /* Unmarshall response */
198
199         if (!lsa_io_r_close("", &r, &rbuf, 0)) {
200                 result = NT_STATUS_UNSUCCESSFUL;
201                 goto done;
202         }
203
204         /* Return output parameters */
205
206         if (NT_STATUS_IS_OK(result = r.status)) {
207                 *pol = r.pol;
208         }
209
210  done:
211         prs_mem_free(&qbuf);
212         prs_mem_free(&rbuf);
213
214         return result;
215 }
216
217 /** Lookup a list of sids */
218
219 NTSTATUS cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
220                              POLICY_HND *pol, int num_sids, DOM_SID *sids, 
221                              char ***domains, char ***names, uint32 **types, int *num_names)
222 {
223         prs_struct qbuf, rbuf;
224         LSA_Q_LOOKUP_SIDS q;
225         LSA_R_LOOKUP_SIDS r;
226         DOM_R_REF ref;
227         LSA_TRANS_NAME_ENUM t_names;
228         NTSTATUS result;
229         int i;
230
231         ZERO_STRUCT(q);
232         ZERO_STRUCT(r);
233
234         /* Initialise parse structures */
235
236         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
237         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
238
239         /* Marshall data and send request */
240
241         init_q_lookup_sids(mem_ctx, &q, pol, num_sids, sids, 1);
242
243         if (!lsa_io_q_lookup_sids("", &q, &qbuf, 0) ||
244             !rpc_api_pipe_req(cli, LSA_LOOKUPSIDS, &qbuf, &rbuf)) {
245                 result = NT_STATUS_UNSUCCESSFUL;
246                 goto done;
247         }
248
249         /* Unmarshall response */
250
251         ZERO_STRUCT(ref);
252         ZERO_STRUCT(t_names);
253
254         r.dom_ref = &ref;
255         r.names = &t_names;
256
257         if (!lsa_io_r_lookup_sids("", &r, &rbuf, 0)) {
258                 result = NT_STATUS_UNSUCCESSFUL;
259                 goto done;
260         }
261
262         result = r.status;
263
264         if (!NT_STATUS_IS_OK(result) &&
265                 NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_FILES_OPEN)) {
266                 /* An actual error occured */
267
268                 goto done;
269         }
270
271
272         /* Return output parameters */
273
274         if (r.mapped_count == 0) {
275                 result = NT_STATUS_NONE_MAPPED;
276                 goto done;
277         }
278
279         (*num_names) = r.mapped_count;
280         result = NT_STATUS_OK;
281
282         if (!((*domains) = (char **)talloc(mem_ctx, sizeof(char *) * r.mapped_count))) {
283                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
284                 result = NT_STATUS_UNSUCCESSFUL;
285                 goto done;
286         }
287
288         if (!((*names) = (char **)talloc(mem_ctx, sizeof(char *) * r.mapped_count))) {
289                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
290                 result = NT_STATUS_UNSUCCESSFUL;
291                 goto done;
292         }
293
294         if (!((*types) = (uint32 *)talloc(mem_ctx, sizeof(uint32) * r.mapped_count))) {
295                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
296                 result = NT_STATUS_UNSUCCESSFUL;
297                 goto done;
298         }
299                 
300         for (i = 0; i < r.mapped_count; i++) {
301                 fstring name, dom_name;
302                 uint32 dom_idx = t_names.name[i].domain_idx;
303
304                 /* Translate optimised name through domain index array */
305
306                 if (dom_idx != 0xffffffff) {
307
308                         rpcstr_pull_unistr2_fstring(
309                                 dom_name, &ref.ref_dom[dom_idx].uni_dom_name);
310                         rpcstr_pull_unistr2_fstring(
311                                 name, &t_names.uni_name[i]);
312
313                         (*names)[i] = talloc_strdup(mem_ctx, name);
314                         (*domains)[i] = talloc_strdup(mem_ctx, dom_name);
315                         (*types)[i] = t_names.name[i].sid_name_use;
316                         
317                         if (((*names)[i] == NULL) || ((*domains)[i] == NULL)) {
318                                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
319                                 result = NT_STATUS_UNSUCCESSFUL;
320                                 goto done;
321                         }
322
323                 } else {
324                         (*names)[i] = NULL;
325                         (*types)[i] = SID_NAME_UNKNOWN;
326                 }
327         }
328
329  done:
330         prs_mem_free(&qbuf);
331         prs_mem_free(&rbuf);
332
333         return result;
334 }
335
336 /** Lookup a list of names */
337
338 NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
339                               POLICY_HND *pol, int num_names, const char **names, 
340                               DOM_SID **sids, uint32 **types, int *num_sids)
341 {
342         prs_struct qbuf, rbuf;
343         LSA_Q_LOOKUP_NAMES q;
344         LSA_R_LOOKUP_NAMES r;
345         DOM_R_REF ref;
346         NTSTATUS result;
347         int i;
348         
349         ZERO_STRUCT(q);
350         ZERO_STRUCT(r);
351
352         /* Initialise parse structures */
353
354         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
355         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
356
357         /* Marshall data and send request */
358
359         init_q_lookup_names(mem_ctx, &q, pol, num_names, names);
360
361         if (!lsa_io_q_lookup_names("", &q, &qbuf, 0) ||
362             !rpc_api_pipe_req(cli, LSA_LOOKUPNAMES, &qbuf, &rbuf)) {
363                 result = NT_STATUS_UNSUCCESSFUL;
364                 goto done;
365         }
366         
367         /* Unmarshall response */
368
369         ZERO_STRUCT(ref);
370         r.dom_ref = &ref;
371
372         if (!lsa_io_r_lookup_names("", &r, &rbuf, 0)) {
373                 result = NT_STATUS_UNSUCCESSFUL;
374                 goto done;
375         }
376
377         result = r.status;
378
379         if (!NT_STATUS_IS_OK(result)) {
380                 /* An actual error occured */
381
382                 goto done;
383         }
384
385
386         /* Return output parameters */
387
388         if (r.mapped_count == 0) {
389                 result = NT_STATUS_NONE_MAPPED;
390                 goto done;
391         }
392
393         (*num_sids) = r.mapped_count;
394         result = NT_STATUS_OK;
395
396         if (!((*sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * r.mapped_count)))) {
397                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
398                 result = NT_STATUS_UNSUCCESSFUL;
399                 goto done;
400         }
401
402         if (!((*types = (uint32 *)talloc(mem_ctx, sizeof(uint32) * r.mapped_count)))) {
403                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
404                 result = NT_STATUS_UNSUCCESSFUL;
405                 goto done;
406         }
407
408         for (i = 0; i < r.mapped_count; i++) {
409                 DOM_RID2 *t_rids = r.dom_rid;
410                 uint32 dom_idx = t_rids[i].rid_idx;
411                 uint32 dom_rid = t_rids[i].rid;
412                 DOM_SID *sid = &(*sids)[i];
413
414                 /* Translate optimised sid through domain index array */
415
416                 if (dom_idx != 0xffffffff) {
417
418                         sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
419
420                         if (dom_rid != 0xffffffff) {
421                                 sid_append_rid(sid, dom_rid);
422                         }
423
424                         (*types)[i] = t_rids[i].type;
425                 } else {
426                         ZERO_STRUCTP(sid);
427                         (*types)[i] = SID_NAME_UNKNOWN;
428                 }
429         }
430
431  done:
432         prs_mem_free(&qbuf);
433         prs_mem_free(&rbuf);
434
435         return result;
436 }
437
438 /** Query info policy */
439
440 NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
441                                    POLICY_HND *pol, uint16 info_class, 
442                                    fstring domain_name, DOM_SID *domain_sid)
443 {
444         prs_struct qbuf, rbuf;
445         LSA_Q_QUERY_INFO q;
446         LSA_R_QUERY_INFO r;
447         NTSTATUS result;
448
449         ZERO_STRUCT(q);
450         ZERO_STRUCT(r);
451
452         /* Initialise parse structures */
453
454         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
455         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
456
457         /* Marshall data and send request */
458
459         init_q_query(&q, pol, info_class);
460
461         if (!lsa_io_q_query("", &q, &qbuf, 0) ||
462             !rpc_api_pipe_req(cli, LSA_QUERYINFOPOLICY, &qbuf, &rbuf)) {
463                 result = NT_STATUS_UNSUCCESSFUL;
464                 goto done;
465         }
466
467         /* Unmarshall response */
468
469         if (!lsa_io_r_query("", &r, &rbuf, 0)) {
470                 result = NT_STATUS_UNSUCCESSFUL;
471                 goto done;
472         }
473
474         if (!NT_STATUS_IS_OK(result = r.status)) {
475                 goto done;
476         }
477
478         /* Return output parameters */
479
480         ZERO_STRUCTP(domain_sid);
481         domain_name[0] = '\0';
482
483         switch (info_class) {
484
485         case 3:
486                 if (r.dom.id3.buffer_dom_name != 0) {
487                         unistr2_to_ascii(domain_name,
488                                          &r.dom.id3.
489                                          uni_domain_name,
490                                          sizeof (fstring) - 1);
491                 }
492
493                 if (r.dom.id3.buffer_dom_sid != 0) {
494                         *domain_sid = r.dom.id3.dom_sid.sid;
495                 }
496
497                 break;
498
499         case 5:
500                 
501                 if (r.dom.id5.buffer_dom_name != 0) {
502                         unistr2_to_ascii(domain_name, &r.dom.id5.
503                                          uni_domain_name,
504                                          sizeof (fstring) - 1);
505                 }
506                         
507                 if (r.dom.id5.buffer_dom_sid != 0) {
508                         *domain_sid = r.dom.id5.dom_sid.sid;
509                 }
510
511                 break;
512                 
513         default:
514                 DEBUG(3, ("unknown info class %d\n", info_class));
515                 break;                
516         }
517         
518  done:
519         prs_mem_free(&qbuf);
520         prs_mem_free(&rbuf);
521
522         return result;
523 }
524
525 /** Enumerate list of trusted domains */
526
527 NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
528                                 POLICY_HND *pol, uint32 *enum_ctx, 
529                                 uint32 *num_domains, char ***domain_names, 
530                                 DOM_SID **domain_sids)
531 {
532         prs_struct qbuf, rbuf;
533         LSA_Q_ENUM_TRUST_DOM q;
534         LSA_R_ENUM_TRUST_DOM r;
535         NTSTATUS result;
536         int i;
537
538         ZERO_STRUCT(q);
539         ZERO_STRUCT(r);
540
541         /* Initialise parse structures */
542
543         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
544         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
545
546         /* Marshall data and send request */
547
548         init_q_enum_trust_dom(&q, pol, *enum_ctx, 0xffffffff);
549
550         if (!lsa_io_q_enum_trust_dom("", &q, &qbuf, 0) ||
551             !rpc_api_pipe_req(cli, LSA_ENUMTRUSTDOM, &qbuf, &rbuf)) {
552                 result = NT_STATUS_UNSUCCESSFUL;
553                 goto done;
554         }
555
556         /* Unmarshall response */
557
558         if (!lsa_io_r_enum_trust_dom("", &r, &rbuf, 0)) {
559                 result = NT_STATUS_UNSUCCESSFUL;
560                 goto done;
561         }
562
563         result = r.status;
564
565         if (!NT_STATUS_IS_OK(result) && 
566             NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_NO_MORE_ENTRIES)) {
567
568                 /* An actual error ocured */
569
570                 goto done;
571         }
572
573         result = NT_STATUS_OK;
574
575         /* Return output parameters */
576
577         if (r.num_domains) {
578
579                 /* Allocate memory for trusted domain names and sids */
580
581                 *domain_names = (char **)talloc(mem_ctx, sizeof(char *) *
582                                                 r.num_domains);
583
584                 if (!*domain_names) {
585                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
586                         result = NT_STATUS_UNSUCCESSFUL;
587                         goto done;
588                 }
589
590                 *domain_sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) *
591                                                  r.num_domains);
592                 if (!domain_sids) {
593                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
594                         result = NT_STATUS_UNSUCCESSFUL;
595                         goto done;
596                 }
597
598                 /* Copy across names and sids */
599
600                 for (i = 0; i < r.num_domains; i++) {
601                         fstring tmp;
602
603                         unistr2_to_ascii(tmp, &r.uni_domain_name[i], 
604                                          sizeof(tmp) - 1);
605                         (*domain_names)[i] = strdup(tmp);
606                         sid_copy(&(*domain_sids)[i], &r.domain_sid[i].sid);
607                 }
608         }
609
610         *num_domains = r.num_domains;
611         *enum_ctx = r.enum_context;
612
613  done:
614         prs_mem_free(&qbuf);
615         prs_mem_free(&rbuf);
616
617         return result;
618 }
619
620 /** Enumerate privileges*/
621
622 NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx,
623                                 POLICY_HND *pol, uint32 *enum_context, uint32 pref_max_length,
624                                 uint32 *count, char ***privs_name, uint32 **privs_high, uint32 **privs_low)
625 {
626         prs_struct qbuf, rbuf;
627         LSA_Q_ENUM_PRIVS q;
628         LSA_R_ENUM_PRIVS r;
629         NTSTATUS result;
630         int i;
631
632         ZERO_STRUCT(q);
633         ZERO_STRUCT(r);
634
635         /* Initialise parse structures */
636
637         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
638         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
639
640         /* Marshall data and send request */
641
642         init_q_enum_privs(&q, pol, *enum_context, pref_max_length);
643
644         if (!lsa_io_q_enum_privs("", &q, &qbuf, 0) ||
645             !rpc_api_pipe_req(cli, LSA_ENUM_PRIVS, &qbuf, &rbuf)) {
646                 result = NT_STATUS_UNSUCCESSFUL;
647                 goto done;
648         }
649
650         /* Unmarshall response */
651
652         if (!lsa_io_r_enum_privs("", &r, &rbuf, 0)) {
653                 result = NT_STATUS_UNSUCCESSFUL;
654                 goto done;
655         }
656
657         if (!NT_STATUS_IS_OK(result = r.status)) {
658                 goto done;
659         }
660
661         /* Return output parameters */
662
663         *enum_context = r.enum_context;
664         *count = r.count;
665
666         if (!((*privs_name = (char **)talloc(mem_ctx, sizeof(char *) * r.count)))) {
667                 DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
668                 result = NT_STATUS_UNSUCCESSFUL;
669                 goto done;
670         }
671
672         if (!((*privs_high = (uint32 *)talloc(mem_ctx, sizeof(uint32) * r.count)))) {
673                 DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
674                 result = NT_STATUS_UNSUCCESSFUL;
675                 goto done;
676         }
677
678         if (!((*privs_low = (uint32 *)talloc(mem_ctx, sizeof(uint32) * r.count)))) {
679                 DEBUG(0, ("(cli_lsa_enum_privilege): out of memory\n"));
680                 result = NT_STATUS_UNSUCCESSFUL;
681                 goto done;
682         }
683
684         for (i = 0; i < r.count; i++) {
685                 fstring name;
686
687                 rpcstr_pull_unistr2_fstring( name, &r.privs[i].name);
688
689                 (*privs_name)[i] = talloc_strdup(mem_ctx, name);
690
691                 (*privs_high)[i] = r.privs[i].luid_high;
692                 (*privs_low)[i] = r.privs[i].luid_low;
693         }
694
695  done:
696         prs_mem_free(&qbuf);
697         prs_mem_free(&rbuf);
698
699         return result;
700 }
701
702 /** Get privilege name */
703
704 NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx,
705                               POLICY_HND *pol, char *name, uint16 lang_id, uint16 lang_id_sys,
706                               fstring description, uint16 *lang_id_desc)
707 {
708         prs_struct qbuf, rbuf;
709         LSA_Q_PRIV_GET_DISPNAME q;
710         LSA_R_PRIV_GET_DISPNAME r;
711         NTSTATUS result;
712
713         ZERO_STRUCT(q);
714         ZERO_STRUCT(r);
715
716         /* Initialise parse structures */
717
718         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
719         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
720
721         /* Marshall data and send request */
722
723         init_lsa_priv_get_dispname(&q, pol, name, lang_id, lang_id_sys);
724
725         if (!lsa_io_q_priv_get_dispname("", &q, &qbuf, 0) ||
726             !rpc_api_pipe_req(cli, LSA_PRIV_GET_DISPNAME, &qbuf, &rbuf)) {
727                 result = NT_STATUS_UNSUCCESSFUL;
728                 goto done;
729         }
730
731         /* Unmarshall response */
732
733         if (!lsa_io_r_priv_get_dispname("", &r, &rbuf, 0)) {
734                 result = NT_STATUS_UNSUCCESSFUL;
735                 goto done;
736         }
737
738         if (!NT_STATUS_IS_OK(result = r.status)) {
739                 goto done;
740         }
741
742         /* Return output parameters */
743         
744         rpcstr_pull_unistr2_fstring(description , &r.desc);
745         *lang_id_desc = r.lang_id;
746
747  done:
748         prs_mem_free(&qbuf);
749         prs_mem_free(&rbuf);
750
751         return result;
752 }
753
754 /** Enumerate list of SIDs  */
755
756 NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
757                                 POLICY_HND *pol, uint32 *enum_ctx, uint32 pref_max_length, 
758                                 uint32 *num_sids, DOM_SID **sids)
759 {
760         prs_struct qbuf, rbuf;
761         LSA_Q_ENUM_ACCOUNTS q;
762         LSA_R_ENUM_ACCOUNTS r;
763         NTSTATUS result;
764         int i;
765
766         ZERO_STRUCT(q);
767         ZERO_STRUCT(r);
768
769         /* Initialise parse structures */
770
771         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
772         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
773
774         /* Marshall data and send request */
775
776         init_lsa_q_enum_accounts(&q, pol, *enum_ctx, pref_max_length);
777
778         if (!lsa_io_q_enum_accounts("", &q, &qbuf, 0) ||
779             !rpc_api_pipe_req(cli, LSA_ENUM_ACCOUNTS, &qbuf, &rbuf)) {
780                 result = NT_STATUS_UNSUCCESSFUL;
781                 goto done;
782         }
783
784         /* Unmarshall response */
785
786         if (!lsa_io_r_enum_accounts("", &r, &rbuf, 0)) {
787                 result = NT_STATUS_UNSUCCESSFUL;
788                 goto done;
789         }
790
791         result = r.status;
792
793         if (!NT_STATUS_IS_OK(result = r.status)) {
794                 goto done;
795         }
796
797         if (r.sids.num_entries==0)
798                 goto done;
799
800         /* Return output parameters */
801
802         *sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * r.sids.num_entries);
803         if (!*sids) {
804                 DEBUG(0, ("(cli_lsa_enum_sids): out of memory\n"));
805                 result = NT_STATUS_UNSUCCESSFUL;
806                 goto done;
807         }
808
809         /* Copy across names and sids */
810
811         for (i = 0; i < r.sids.num_entries; i++) {
812                 sid_copy(&(*sids)[i], &r.sids.sid[i].sid);
813         }
814
815         *num_sids= r.sids.num_entries;
816         *enum_ctx = r.enum_context;
817
818  done:
819         prs_mem_free(&qbuf);
820         prs_mem_free(&rbuf);
821
822         return result;
823 }
824
825 /** Open a LSA user handle
826  *
827  * @param cli Handle on an initialised SMB connection */
828
829 NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
830                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 des_access, 
831                              POLICY_HND *user_pol)
832 {
833         prs_struct qbuf, rbuf;
834         LSA_Q_OPENACCOUNT q;
835         LSA_R_OPENACCOUNT r;
836         NTSTATUS result;
837
838         ZERO_STRUCT(q);
839         ZERO_STRUCT(r);
840
841         /* Initialise parse structures */
842
843         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
844         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
845
846         /* Initialise input parameters */
847
848         init_lsa_q_open_account(&q, dom_pol, sid, des_access);
849
850         /* Marshall data and send request */
851
852         if (!lsa_io_q_open_account("", &q, &qbuf, 0) ||
853             !rpc_api_pipe_req(cli, LSA_OPENACCOUNT, &qbuf, &rbuf)) {
854                 result = NT_STATUS_UNSUCCESSFUL;
855                 goto done;
856         }
857
858         /* Unmarshall response */
859
860         if (!lsa_io_r_open_account("", &r, &rbuf, 0)) {
861                 result = NT_STATUS_UNSUCCESSFUL;
862                 goto done;
863         }
864
865         /* Return output parameters */
866
867         if (NT_STATUS_IS_OK(result = r.status)) {
868                 *user_pol = r.pol;
869         }
870
871  done:
872         prs_mem_free(&qbuf);
873         prs_mem_free(&rbuf);
874
875         return result;
876 }
877
878 /** Enumerate user privileges
879  *
880  * @param cli Handle on an initialised SMB connection */
881
882 NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx,
883                              POLICY_HND *pol, uint32 *count, LUID_ATTR **set)
884 {
885         prs_struct qbuf, rbuf;
886         LSA_Q_ENUMPRIVSACCOUNT q;
887         LSA_R_ENUMPRIVSACCOUNT r;
888         NTSTATUS result;
889         int i;
890
891         ZERO_STRUCT(q);
892         ZERO_STRUCT(r);
893
894         /* Initialise parse structures */
895
896         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
897         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
898
899         /* Initialise input parameters */
900
901         init_lsa_q_enum_privsaccount(&q, pol);
902
903         /* Marshall data and send request */
904
905         if (!lsa_io_q_enum_privsaccount("", &q, &qbuf, 0) ||
906             !rpc_api_pipe_req(cli, LSA_ENUMPRIVSACCOUNT, &qbuf, &rbuf)) {
907                 result = NT_STATUS_UNSUCCESSFUL;
908                 goto done;
909         }
910
911         /* Unmarshall response */
912
913         if (!lsa_io_r_enum_privsaccount("", &r, &rbuf, 0)) {
914                 result = NT_STATUS_UNSUCCESSFUL;
915                 goto done;
916         }
917
918         /* Return output parameters */
919
920         if (!NT_STATUS_IS_OK(result = r.status)) {
921                 goto done;
922         }
923
924         if (r.count == 0)
925                 goto done;
926
927         if (!((*set = (LUID_ATTR *)talloc(mem_ctx, sizeof(LUID_ATTR) * r.count)))) {
928                 DEBUG(0, ("(cli_lsa_enum_privsaccount): out of memory\n"));
929                 result = NT_STATUS_UNSUCCESSFUL;
930                 goto done;
931         }
932
933         for (i=0; i<r.count; i++) {
934                 (*set)[i].luid.low = r.set.set[i].luid.low;
935                 (*set)[i].luid.high = r.set.set[i].luid.high;
936                 (*set)[i].attr = r.set.set[i].attr;
937         }
938
939         *count=r.count;
940  done:
941         prs_mem_free(&qbuf);
942         prs_mem_free(&rbuf);
943
944         return result;
945 }
946
947 /** Get a privilege value given its name */
948
949 NTSTATUS cli_lsa_lookupprivvalue(struct cli_state *cli, TALLOC_CTX *mem_ctx,
950                               POLICY_HND *pol, char *name, LUID *luid)
951 {
952         prs_struct qbuf, rbuf;
953         LSA_Q_LOOKUPPRIVVALUE q;
954         LSA_R_LOOKUPPRIVVALUE r;
955         NTSTATUS result;
956
957         ZERO_STRUCT(q);
958         ZERO_STRUCT(r);
959
960         /* Initialise parse structures */
961
962         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
963         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
964
965         /* Marshall data and send request */
966
967         init_lsa_q_lookupprivvalue(&q, pol, name);
968
969         if (!lsa_io_q_lookupprivvalue("", &q, &qbuf, 0) ||
970             !rpc_api_pipe_req(cli, LSA_LOOKUPPRIVVALUE, &qbuf, &rbuf)) {
971                 result = NT_STATUS_UNSUCCESSFUL;
972                 goto done;
973         }
974
975         /* Unmarshall response */
976
977         if (!lsa_io_r_lookupprivvalue("", &r, &rbuf, 0)) {
978                 result = NT_STATUS_UNSUCCESSFUL;
979                 goto done;
980         }
981
982         if (!NT_STATUS_IS_OK(result = r.status)) {
983                 goto done;
984         }
985
986         /* Return output parameters */
987
988         (*luid).low=r.luid.low;
989         (*luid).high=r.luid.high;
990
991  done:
992         prs_mem_free(&qbuf);
993         prs_mem_free(&rbuf);
994
995         return result;
996 }
997
998 /** Query LSA security object */
999
1000 NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1001                               POLICY_HND *pol, uint32 sec_info, 
1002                               SEC_DESC_BUF **psdb)
1003 {
1004         prs_struct qbuf, rbuf;
1005         LSA_Q_QUERY_SEC_OBJ q;
1006         LSA_R_QUERY_SEC_OBJ r;
1007         NTSTATUS result;
1008
1009         ZERO_STRUCT(q);
1010         ZERO_STRUCT(r);
1011
1012         /* Initialise parse structures */
1013
1014         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
1015         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
1016
1017         /* Marshall data and send request */
1018
1019         init_q_query_sec_obj(&q, pol, sec_info);
1020
1021         if (!lsa_io_q_query_sec_obj("", &q, &qbuf, 0) ||
1022             !rpc_api_pipe_req(cli, LSA_QUERYSECOBJ, &qbuf, &rbuf)) {
1023                 result = NT_STATUS_UNSUCCESSFUL;
1024                 goto done;
1025         }
1026
1027         /* Unmarshall response */
1028
1029         if (!lsa_io_r_query_sec_obj("", &r, &rbuf, 0)) {
1030                 result = NT_STATUS_UNSUCCESSFUL;
1031                 goto done;
1032         }
1033
1034         if (!NT_STATUS_IS_OK(result = r.status)) {
1035                 goto done;
1036         }
1037
1038         /* Return output parameters */
1039
1040         if (psdb)
1041                 *psdb = r.buf;
1042
1043  done:
1044         prs_mem_free(&qbuf);
1045         prs_mem_free(&rbuf);
1046
1047         return result;
1048 }
1049
1050 /** Fetch a DOMAIN sid. Does complete cli setup / teardown anonymously. */
1051
1052 BOOL fetch_domain_sid( char *domain, char *remote_machine, DOM_SID *psid)
1053 {
1054         extern pstring global_myname;
1055         struct cli_state cli;
1056         NTSTATUS result;
1057         POLICY_HND lsa_pol;
1058         BOOL ret = False;
1059  
1060         ZERO_STRUCT(cli);
1061         if(cli_initialise(&cli) == False) {
1062                 DEBUG(0,("fetch_domain_sid: unable to initialize client connection.\n"));
1063                 return False;
1064         }
1065  
1066         if(!resolve_name( remote_machine, &cli.dest_ip, 0x20)) {
1067                 DEBUG(0,("fetch_domain_sid: Can't resolve address for %s\n", remote_machine));
1068                 goto done;
1069         }
1070  
1071         if (!cli_connect(&cli, remote_machine, &cli.dest_ip)) {
1072                 DEBUG(0,("fetch_domain_sid: unable to connect to SMB server on \
1073 machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1074                 goto done;
1075         }
1076
1077         if (!attempt_netbios_session_request(&cli, global_myname, remote_machine, &cli.dest_ip)) {
1078                 DEBUG(0,("fetch_domain_sid: machine %s rejected the NetBIOS \
1079 session request. Error was %s\n", remote_machine, cli_errstr(&cli) ));
1080                 goto done;
1081         }
1082  
1083         cli.protocol = PROTOCOL_NT1;
1084  
1085         if (!cli_negprot(&cli)) {
1086                 DEBUG(0,("fetch_domain_sid: machine %s rejected the negotiate protocol. \
1087 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1088                 goto done;
1089         }
1090  
1091         if (cli.protocol != PROTOCOL_NT1) {
1092                 DEBUG(0,("fetch_domain_sid: machine %s didn't negotiate NT protocol.\n",
1093                         remote_machine));
1094                 goto done;
1095         }
1096  
1097         /*
1098          * Do an anonymous session setup.
1099          */
1100  
1101         if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
1102                 DEBUG(0,("fetch_domain_sid: machine %s rejected the session setup. \
1103 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1104                 goto done;
1105         }
1106  
1107         if (!(cli.sec_mode & 1)) {
1108                 DEBUG(0,("fetch_domain_sid: machine %s isn't in user level security mode\n",
1109                         remote_machine));
1110                 goto done;
1111         }
1112
1113         if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
1114                 DEBUG(0,("fetch_domain_sid: machine %s rejected the tconX on the IPC$ share. \
1115 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
1116                 goto done;
1117         }
1118
1119         /* Fetch domain sid */
1120  
1121         if (!cli_nt_session_open(&cli, PIPE_LSARPC)) {
1122                 DEBUG(0, ("fetch_domain_sid: Error connecting to SAM pipe\n"));
1123                 goto done;
1124         }
1125  
1126         result = cli_lsa_open_policy(&cli, cli.mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &lsa_pol);
1127         if (!NT_STATUS_IS_OK(result)) {
1128                 DEBUG(0, ("fetch_domain_sid: Error opening lsa policy handle. %s\n",
1129                         get_nt_error_msg(result) ));
1130                 goto done;
1131         }
1132  
1133         result = cli_lsa_query_info_policy(&cli, cli.mem_ctx, &lsa_pol, 5, domain, psid);
1134         if (!NT_STATUS_IS_OK(result)) {
1135                 DEBUG(0, ("fetch_domain_sid: Error querying lsa policy handle. %s\n",
1136                         get_nt_error_msg(result) ));
1137                 goto done;
1138         }
1139  
1140         ret = True;
1141
1142   done:
1143
1144         cli_shutdown(&cli);
1145         return ret;
1146 }
1147
1148 /** @} **/