Doxygen demo for Tim.
[kai/samba.git] / source3 / libsmb / cli_lsarpc.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2
4    RPC pipe client
5    Copyright (C) Tim Potter                        2000-2001,
6    Copyright (C) Andrew Tridgell              1992-1997,2000,
7    Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
8    Copyright (C) Paul Ashton                       1997,2000,
9    Copyright (C) Elrond                                 2000.
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 /** @defgroup rpc_client 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 to the lsa pipe
41  *
42  * @param system_name NETBIOS name of the machine to connect to. */
43 struct cli_state *cli_lsa_initialise(struct cli_state *cli, char *system_name,
44                                      struct ntuser_creds *creds)
45 {
46         return cli_pipe_initialise(cli, system_name, PIPE_LSASS, creds);
47 }
48
49 /** Open a LSA policy handle */
50
51 NTSTATUS cli_lsa_open_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
52                              BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
53 {
54         prs_struct qbuf, rbuf;
55         LSA_Q_OPEN_POL q;
56         LSA_R_OPEN_POL r;
57         LSA_SEC_QOS qos;
58         NTSTATUS result;
59
60         ZERO_STRUCT(q);
61         ZERO_STRUCT(r);
62
63         /* Initialise parse structures */
64
65         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
66         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
67
68         /* Initialise input parameters */
69
70         if (sec_qos) {
71                 init_lsa_sec_qos(&qos, 2, 1, 0, des_access);
72                 init_q_open_pol(&q, '\\', 0, des_access, &qos);
73         } else {
74                 init_q_open_pol(&q, '\\', 0, des_access, NULL);
75         }
76
77         /* Marshall data and send request */
78
79         if (!lsa_io_q_open_pol("", &q, &qbuf, 0) ||
80             !rpc_api_pipe_req(cli, LSA_OPENPOLICY, &qbuf, &rbuf)) {
81                 result = NT_STATUS_UNSUCCESSFUL;
82                 goto done;
83         }
84
85         /* Unmarshall response */
86
87         if (!lsa_io_r_open_pol("", &r, &rbuf, 0)) {
88                 result = NT_STATUS_UNSUCCESSFUL;
89                 goto done;
90         }
91
92         /* Return output parameters */
93
94         if (NT_STATUS_IS_OK(result = r.status)) {
95                 *pol = r.pol;
96         }
97
98  done:
99         prs_mem_free(&qbuf);
100         prs_mem_free(&rbuf);
101
102         return result;
103 }
104
105 /** Open a LSA policy handle */
106
107 NTSTATUS cli_lsa_open_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
108                               BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
109 {
110         prs_struct qbuf, rbuf;
111         LSA_Q_OPEN_POL2 q;
112         LSA_R_OPEN_POL2 r;
113         LSA_SEC_QOS qos;
114         NTSTATUS result;
115
116         ZERO_STRUCT(q);
117         ZERO_STRUCT(r);
118
119         /* Initialise parse structures */
120
121         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
122         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
123
124         /* Initialise input parameters */
125
126         if (sec_qos) {
127                 init_lsa_sec_qos(&qos, 2, 1, 0, des_access);
128                 init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access, 
129                                  &qos);
130         } else {
131                 init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access, 
132                                  NULL);
133         }
134
135         /* Marshall data and send request */
136
137         if (!lsa_io_q_open_pol2("", &q, &qbuf, 0) ||
138             !rpc_api_pipe_req(cli, LSA_OPENPOLICY2, &qbuf, &rbuf)) {
139                 result = NT_STATUS_UNSUCCESSFUL;
140                 goto done;
141         }
142
143         /* Unmarshall response */
144
145         if (!lsa_io_r_open_pol2("", &r, &rbuf, 0)) {
146                 result = NT_STATUS_UNSUCCESSFUL;
147                 goto done;
148         }
149
150         /* Return output parameters */
151
152         if (NT_STATUS_IS_OK(result = r.status)) {
153                 *pol = r.pol;
154         }
155
156  done:
157         prs_mem_free(&qbuf);
158         prs_mem_free(&rbuf);
159
160         return result;
161 }
162
163 /** Close a LSA policy handle */
164
165 NTSTATUS cli_lsa_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
166                        POLICY_HND *pol)
167 {
168         prs_struct qbuf, rbuf;
169         LSA_Q_CLOSE q;
170         LSA_R_CLOSE r;
171         NTSTATUS result;
172
173         ZERO_STRUCT(q);
174         ZERO_STRUCT(r);
175
176         /* Initialise parse structures */
177
178         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
179         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
180
181         /* Marshall data and send request */
182
183         init_lsa_q_close(&q, pol);
184
185         if (!lsa_io_q_close("", &q, &qbuf, 0) ||
186             !rpc_api_pipe_req(cli, LSA_CLOSE, &qbuf, &rbuf)) {
187                 result = NT_STATUS_UNSUCCESSFUL;
188                 goto done;
189         }
190
191         /* Unmarshall response */
192
193         if (!lsa_io_r_close("", &r, &rbuf, 0)) {
194                 result = NT_STATUS_UNSUCCESSFUL;
195                 goto done;
196         }
197
198         /* Return output parameters */
199
200         if (NT_STATUS_IS_OK(result = r.status)) {
201                 *pol = r.pol;
202         }
203
204  done:
205         prs_mem_free(&qbuf);
206         prs_mem_free(&rbuf);
207
208         return result;
209 }
210
211 /** Lookup a list of sids */
212
213 NTSTATUS cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
214                              POLICY_HND *pol, int num_sids, DOM_SID *sids, 
215                              char ***names, uint32 **types, int *num_names)
216 {
217         prs_struct qbuf, rbuf;
218         LSA_Q_LOOKUP_SIDS q;
219         LSA_R_LOOKUP_SIDS r;
220         DOM_R_REF ref;
221         LSA_TRANS_NAME_ENUM t_names;
222         NTSTATUS result;
223         int i;
224
225         ZERO_STRUCT(q);
226         ZERO_STRUCT(r);
227
228         /* Initialise parse structures */
229
230         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
231         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
232
233         /* Marshall data and send request */
234
235         init_q_lookup_sids(mem_ctx, &q, pol, num_sids, sids, 1);
236
237         if (!lsa_io_q_lookup_sids("", &q, &qbuf, 0) ||
238             !rpc_api_pipe_req(cli, LSA_LOOKUPSIDS, &qbuf, &rbuf)) {
239                 result = NT_STATUS_UNSUCCESSFUL;
240                 goto done;
241         }
242
243         /* Unmarshall response */
244
245         ZERO_STRUCT(ref);
246         ZERO_STRUCT(t_names);
247
248         r.dom_ref = &ref;
249         r.names = &t_names;
250
251         if (!lsa_io_r_lookup_sids("", &r, &rbuf, 0)) {
252                 result = NT_STATUS_UNSUCCESSFUL;
253                 goto done;
254         }
255
256         result = r.status;
257
258         if (!NT_STATUS_IS_OK(result) && 
259             NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_FILES_OPEN) &&
260             NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_NONE_MAPPED)) {
261                 
262                 /* An actual error occured */
263
264                 goto done;
265         }
266
267         result = NT_STATUS_OK;
268
269         /* Return output parameters */
270
271         (*num_names) = r.names->num_entries;
272         
273         if (!((*names) = (char **)talloc(mem_ctx, sizeof(char *) * 
274                                          r.names->num_entries))) {
275                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
276                 result = NT_STATUS_UNSUCCESSFUL;
277                 goto done;
278         }
279
280         if (!((*types) = (uint32 *)talloc(mem_ctx, sizeof(uint32) * 
281                                       r.names->num_entries))) {
282                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
283                 result = NT_STATUS_UNSUCCESSFUL;
284                 goto done;
285         }
286                 
287         for (i = 0; i < r.names->num_entries; i++) {
288                 fstring name, dom_name, full_name;
289                 uint32 dom_idx = t_names.name[i].domain_idx;
290
291                 /* Translate optimised name through domain index array */
292
293                 if (dom_idx != 0xffffffff) {
294
295                         rpcstr_pull_unistr2_fstring(
296                                 dom_name, &ref.ref_dom[dom_idx].uni_dom_name);
297                         rpcstr_pull_unistr2_fstring(
298                                 name, &t_names.uni_name[i]);
299
300                         slprintf(full_name, sizeof(full_name) - 1,
301                                  "%s%s%s", dom_name, 
302                                  (dom_name[0] && name[0]) ? 
303                                  lp_winbind_separator() : "", name);
304
305                         (*names)[i] = talloc_strdup(mem_ctx, full_name);
306                         (*types)[i] = t_names.name[i].sid_name_use;
307
308                 } else {
309                         (*names)[i] = NULL;
310                         (*types)[i] = SID_NAME_UNKNOWN;
311                 }
312         }
313
314  done:
315         prs_mem_free(&qbuf);
316         prs_mem_free(&rbuf);
317
318         return result;
319 }
320
321 /** Lookup a list of names */
322
323 NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
324                               POLICY_HND *pol, int num_names, char **names, 
325                               DOM_SID **sids, uint32 **types, int *num_sids)
326 {
327         prs_struct qbuf, rbuf;
328         LSA_Q_LOOKUP_NAMES q;
329         LSA_R_LOOKUP_NAMES r;
330         DOM_R_REF ref;
331         NTSTATUS result;
332         int i;
333         
334         ZERO_STRUCT(q);
335         ZERO_STRUCT(r);
336
337         /* Initialise parse structures */
338
339         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
340         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
341
342         /* Marshall data and send request */
343
344         init_q_lookup_names(mem_ctx, &q, pol, num_names, names);
345
346         if (!lsa_io_q_lookup_names("", &q, &qbuf, 0) ||
347             !rpc_api_pipe_req(cli, LSA_LOOKUPNAMES, &qbuf, &rbuf)) {
348                 result = NT_STATUS_UNSUCCESSFUL;
349                 goto done;
350         }
351         
352         /* Unmarshall response */
353
354         ZERO_STRUCT(ref);
355         r.dom_ref = &ref;
356
357         if (!lsa_io_r_lookup_names("", &r, &rbuf, 0)) {
358                 result = NT_STATUS_UNSUCCESSFUL;
359                 goto done;
360         }
361
362         result = r.status;
363
364         if (!NT_STATUS_IS_OK(result) && 
365             NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_NONE_MAPPED)) {
366
367                 /* An actual error occured */
368
369                 goto done;
370         }
371
372         result = NT_STATUS_OK;
373
374         /* Return output parameters */
375
376         (*num_sids) = r.num_entries;
377
378         if (!((*sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) *
379                                          r.num_entries)))) {
380                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
381                 result = NT_STATUS_UNSUCCESSFUL;
382                 goto done;
383         }
384
385         if (!((*types = (uint32 *)talloc(mem_ctx, sizeof(uint32) *
386                                           r.num_entries)))) {
387                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
388                 result = NT_STATUS_UNSUCCESSFUL;
389                 goto done;
390         }
391
392         for (i = 0; i < r.num_entries; i++) {
393                 DOM_RID2 *t_rids = r.dom_rid;
394                 uint32 dom_idx = t_rids[i].rid_idx;
395                 uint32 dom_rid = t_rids[i].rid;
396                 DOM_SID *sid = &(*sids)[i];
397
398                 /* Translate optimised sid through domain index array */
399
400                 if (dom_idx != 0xffffffff) {
401
402                         sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
403
404                         if (dom_rid != 0xffffffff) {
405                                 sid_append_rid(sid, dom_rid);
406                         }
407
408                         (*types)[i] = t_rids[i].type;
409                 } else {
410                         ZERO_STRUCTP(sid);
411                         (*types)[i] = SID_NAME_UNKNOWN;
412                 }
413         }
414
415  done:
416         prs_mem_free(&qbuf);
417         prs_mem_free(&rbuf);
418
419         return result;
420 }
421
422 /** Query info policy */
423
424 NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
425                                    POLICY_HND *pol, uint16 info_class, 
426                                    fstring domain_name, DOM_SID *domain_sid)
427 {
428         prs_struct qbuf, rbuf;
429         LSA_Q_QUERY_INFO q;
430         LSA_R_QUERY_INFO r;
431         NTSTATUS result;
432
433         ZERO_STRUCT(q);
434         ZERO_STRUCT(r);
435
436         /* Initialise parse structures */
437
438         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
439         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
440
441         /* Marshall data and send request */
442
443         init_q_query(&q, pol, info_class);
444
445         if (!lsa_io_q_query("", &q, &qbuf, 0) ||
446             !rpc_api_pipe_req(cli, LSA_QUERYINFOPOLICY, &qbuf, &rbuf)) {
447                 result = NT_STATUS_UNSUCCESSFUL;
448                 goto done;
449         }
450
451         /* Unmarshall response */
452
453         if (!lsa_io_r_query("", &r, &rbuf, 0)) {
454                 result = NT_STATUS_UNSUCCESSFUL;
455                 goto done;
456         }
457
458         if (!NT_STATUS_IS_OK(result = r.status)) {
459                 goto done;
460         }
461
462         /* Return output parameters */
463
464         ZERO_STRUCTP(domain_sid);
465         domain_name[0] = '\0';
466
467         switch (info_class) {
468
469         case 3:
470                 if (r.dom.id3.buffer_dom_name != 0) {
471                         unistr2_to_ascii(domain_name,
472                                          &r.dom.id3.
473                                          uni_domain_name,
474                                          sizeof (fstring) - 1);
475                 }
476
477                 if (r.dom.id3.buffer_dom_sid != 0) {
478                         *domain_sid = r.dom.id3.dom_sid.sid;
479                 }
480
481                 break;
482
483         case 5:
484                 
485                 if (r.dom.id5.buffer_dom_name != 0) {
486                         unistr2_to_ascii(domain_name, &r.dom.id5.
487                                          uni_domain_name,
488                                          sizeof (fstring) - 1);
489                 }
490                         
491                 if (r.dom.id5.buffer_dom_sid != 0) {
492                         *domain_sid = r.dom.id5.dom_sid.sid;
493                 }
494
495                 break;
496                 
497         default:
498                 DEBUG(3, ("unknown info class %d\n", info_class));
499                 break;                
500         }
501         
502  done:
503         prs_mem_free(&qbuf);
504         prs_mem_free(&rbuf);
505
506         return result;
507 }
508
509 /** Enumerate list of trusted domains */
510
511 NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
512                                 POLICY_HND *pol, uint32 *enum_ctx, 
513                                 uint32 *num_domains, char ***domain_names, 
514                                 DOM_SID **domain_sids)
515 {
516         prs_struct qbuf, rbuf;
517         LSA_Q_ENUM_TRUST_DOM q;
518         LSA_R_ENUM_TRUST_DOM r;
519         NTSTATUS result;
520         int i;
521
522         ZERO_STRUCT(q);
523         ZERO_STRUCT(r);
524
525         /* Initialise parse structures */
526
527         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
528         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
529
530         /* Marshall data and send request */
531
532         init_q_enum_trust_dom(&q, pol, *enum_ctx, 0xffffffff);
533
534         if (!lsa_io_q_enum_trust_dom("", &q, &qbuf, 0) ||
535             !rpc_api_pipe_req(cli, LSA_ENUMTRUSTDOM, &qbuf, &rbuf)) {
536                 result = NT_STATUS_UNSUCCESSFUL;
537                 goto done;
538         }
539
540         /* Unmarshall response */
541
542         if (!lsa_io_r_enum_trust_dom("", &r, &rbuf, 0)) {
543                 result = NT_STATUS_UNSUCCESSFUL;
544                 goto done;
545         }
546
547         result = r.status;
548
549         /* For some undocumented reason this function sometimes returns
550            0x8000001a (NT_STATUS_UNABLE_TO_FREE_VM) so we ignore it and
551            pretend everything is OK. */
552
553         if (!NT_STATUS_IS_OK(result) && 
554             NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_UNABLE_TO_FREE_VM)) {
555
556                 /* An actual error ocured */
557
558                 goto done;
559         }
560
561         result = NT_STATUS_OK;
562
563         /* Return output parameters */
564
565         if (r.num_domains) {
566
567                 /* Allocate memory for trusted domain names and sids */
568
569                 *domain_names = (char **)talloc(mem_ctx, sizeof(char *) *
570                                                 r.num_domains);
571
572                 if (!*domain_names) {
573                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
574                         result = NT_STATUS_UNSUCCESSFUL;
575                         goto done;
576                 }
577
578                 *domain_sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) *
579                                                  r.num_domains);
580                 if (!domain_sids) {
581                         DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
582                         result = NT_STATUS_UNSUCCESSFUL;
583                         goto done;
584                 }
585
586                 /* Copy across names and sids */
587
588                 for (i = 0; i < r.num_domains; i++) {
589                         fstring tmp;
590
591                         unistr2_to_ascii(tmp, &r.uni_domain_name[i], 
592                                          sizeof(tmp) - 1);
593                         (*domain_names)[i] = strdup(tmp);
594                         sid_copy(&(*domain_sids)[i], &r.domain_sid[i].sid);
595                 }
596         }
597
598         *num_domains = r.num_domains;
599         *enum_ctx = r.enum_context;
600
601  done:
602         prs_mem_free(&qbuf);
603         prs_mem_free(&rbuf);
604
605         return result;
606 }
607
608 /** @} **/