converted another bunch of stuff to NTSTATUS
[kai/samba.git] / source3 / rpc_client / cli_lsarpc.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-1997,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7  *  Copyright (C) Paul Ashton                       1997.
8  *  Copyright (C) Jeremy Allison                    1999.
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 extern int DEBUGLEVEL;
28
29 /****************************************************************************
30 do a LSA Open Policy
31 ****************************************************************************/
32
33 BOOL do_lsa_open_policy(struct cli_state *cli,
34                         char *system_name, POLICY_HND *hnd,
35                         BOOL sec_qos)
36 {
37         prs_struct rbuf;
38         prs_struct buf; 
39         LSA_Q_OPEN_POL q_o;
40         LSA_SEC_QOS qos;
41         LSA_R_OPEN_POL r_o;
42
43         if (hnd == NULL)
44                 return False;
45
46         prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
47         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
48
49         /* create and send a MSRPC command with api LSA_OPENPOLICY */
50
51         DEBUG(4,("LSA Open Policy\n"));
52
53         /* store the parameters */
54         if (sec_qos) {
55                 init_lsa_sec_qos(&qos, 2, 1, 0, 0x20000000);
56                 init_q_open_pol(&q_o, 0x5c, 0, 0, &qos);
57         } else {
58                 init_q_open_pol(&q_o, 0x5c, 0, 0x1, NULL);
59         }
60
61         /* turn parameters into data stream */
62         if(!lsa_io_q_open_pol("", &q_o, &buf, 0)) {
63                 prs_mem_free(&buf);
64                 prs_mem_free(&rbuf);
65                 return False;
66         }
67
68         /* send the data on \PIPE\ */
69         if (!rpc_api_pipe_req(cli, LSA_OPENPOLICY, &buf, &rbuf)) {
70                 prs_mem_free(&buf);
71                 prs_mem_free(&rbuf);
72                 return False;
73         }
74
75         prs_mem_free(&buf);
76
77         if(!lsa_io_r_open_pol("", &r_o, &rbuf, 0)) {
78                 DEBUG(0,("do_lsa_open_policy: Failed to unmarshall LSA_R_OPEN_POL\n"));
79                 prs_mem_free(&rbuf);
80                 return False;
81         }
82
83         if (r_o.status != 0) {
84                 /* report error code */
85                 DEBUG(0,("LSA_OPENPOLICY: %s\n", get_nt_error_msg(r_o.status)));
86                 prs_mem_free(&rbuf);
87                 return False;
88         } else {
89                 /* ok, at last: we're happy. return the policy handle */
90                 *hnd = r_o.pol;
91         }
92
93         prs_mem_free(&rbuf);
94
95         return True;
96 }
97
98 /****************************************************************************
99 do a LSA Query Info Policy
100 ****************************************************************************/
101 BOOL do_lsa_query_info_pol(struct cli_state *cli,
102                         POLICY_HND *hnd, uint16 info_class,
103                         fstring domain_name, DOM_SID *domain_sid)
104 {
105         prs_struct rbuf;
106         prs_struct buf; 
107         LSA_Q_QUERY_INFO q_q;
108         LSA_R_QUERY_INFO r_q;
109         fstring sid_str;
110
111         ZERO_STRUCTP(domain_sid);
112         domain_name[0] = 0;
113
114         if (hnd == NULL || domain_name == NULL || domain_sid == NULL)
115                 return False;
116
117         prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
118         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
119
120         /* create and send a MSRPC command with api LSA_QUERYINFOPOLICY */
121
122         DEBUG(4,("LSA Query Info Policy\n"));
123
124         /* store the parameters */
125         init_q_query(&q_q, hnd, info_class);
126
127         /* turn parameters into data stream */
128         if(!lsa_io_q_query("", &q_q, &buf, 0)) {
129                 prs_mem_free(&buf);
130                 prs_mem_free(&rbuf);
131                 return False;
132         }
133
134         /* send the data on \PIPE\ */
135         if (!rpc_api_pipe_req(cli, LSA_QUERYINFOPOLICY, &buf, &rbuf)) {
136                 prs_mem_free(&buf);
137                 prs_mem_free(&rbuf);
138                 return False;
139         }
140
141         prs_mem_free(&buf);
142
143         if(!lsa_io_r_query("", &r_q, &rbuf, 0)) {
144                 prs_mem_free(&rbuf);
145                 return False;
146         }
147
148         if (r_q.status != 0) {
149                 /* report error code */
150                 DEBUG(0,("LSA_QUERYINFOPOLICY: %s\n", get_nt_error_msg(r_q.status)));
151                 prs_mem_free(&rbuf);
152                 return False;
153         }
154
155         if (r_q.info_class != q_q.info_class) {
156                 /* report different info classes */
157                 DEBUG(0,("LSA_QUERYINFOPOLICY: error info_class (q,r) differ - (%x,%x)\n",
158                                 q_q.info_class, r_q.info_class));
159                 prs_mem_free(&rbuf);
160                 return False;
161         }
162
163         /* ok, at last: we're happy. */
164         switch (r_q.info_class) {
165         case 3:
166                 if (r_q.dom.id3.buffer_dom_name != 0) {
167                         rpcstr_pull(domain_name, r_q.dom.id3.uni_domain_name.buffer, sizeof(domain_name), r_q.dom.id3.uni_domain_name.uni_str_len*2, 0);
168                 }
169                 if (r_q.dom.id3.buffer_dom_sid != 0)
170                         *domain_sid = r_q.dom.id3.dom_sid.sid;
171                 break;
172         case 5:
173                 if (r_q.dom.id5.buffer_dom_name != 0) {
174                         rpcstr_pull(domain_name, r_q.dom.id5.uni_domain_name.buffer, sizeof(domain_name), r_q.dom.id5.uni_domain_name.uni_str_len*2, 0);
175                 }
176                 if (r_q.dom.id5.buffer_dom_sid != 0)
177                         *domain_sid = r_q.dom.id5.dom_sid.sid;
178                 break;
179         default:
180                 DEBUG(3,("LSA_QUERYINFOPOLICY: unknown info class\n"));
181                 domain_name[0] = 0;
182
183                 prs_mem_free(&rbuf);
184                 return False;
185         }
186                 
187         sid_to_string(sid_str, domain_sid);
188         DEBUG(3,("LSA_QUERYINFOPOLICY (level %x): domain:%s  domain sid:%s\n",
189                   r_q.info_class, domain_name, sid_str));
190
191         prs_mem_free(&rbuf);
192
193         return True;
194 }
195
196 /****************************************************************************
197 do a LSA Close
198 ****************************************************************************/
199
200 BOOL do_lsa_close(struct cli_state *cli, POLICY_HND *hnd)
201 {
202         prs_struct rbuf;
203         prs_struct buf; 
204         LSA_Q_CLOSE q_c;
205         LSA_R_CLOSE r_c;
206
207         if (hnd == NULL)
208                 return False;
209
210         /* create and send a MSRPC command with api LSA_OPENPOLICY */
211
212         prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
213         prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
214
215         DEBUG(4,("LSA Close\n"));
216
217         /* store the parameters */
218         init_lsa_q_close(&q_c, hnd);
219
220         /* turn parameters into data stream */
221         if(!lsa_io_q_close("", &q_c, &buf, 0)) {
222                 prs_mem_free(&buf);
223                 prs_mem_free(&rbuf);
224                 return False;
225         }
226
227         /* send the data on \PIPE\ */
228         if (!rpc_api_pipe_req(cli, LSA_CLOSE, &buf, &rbuf)) {
229                 prs_mem_free(&buf);
230                 prs_mem_free(&rbuf);
231                 return False;
232         }
233
234         prs_mem_free(&buf);
235
236         if(!lsa_io_r_close("", &r_c, &rbuf, 0)) {
237                 prs_mem_free(&rbuf);
238                 return False;
239         }
240
241         if (r_c.status != 0) {
242                 /* report error code */
243                 DEBUG(0,("LSA_CLOSE: %s\n", get_nt_error_msg(r_c.status)));
244                 prs_mem_free(&rbuf);
245                 return False;
246         }
247
248         /* check that the returned policy handle is all zeros */
249
250         if (IVAL(&r_c.pol.data1,0) || IVAL(&r_c.pol.data2,0) || SVAL(&r_c.pol.data3,0) || 
251                 SVAL(&r_c.pol.data4,0) || IVAL(r_c.pol.data5,0) || IVAL(r_c.pol.data5,4) ) {
252                 DEBUG(0,("LSA_CLOSE: non-zero handle returned\n"));
253                 prs_mem_free(&rbuf);
254                 return False;
255         }
256
257         prs_mem_free(&rbuf);
258
259         return True;
260 }
261
262 /****************************************************************************
263 obtain a server's SAM SID and save it in the secrets database
264 ****************************************************************************/
265
266 BOOL cli_lsa_get_domain_sid(struct cli_state *cli, char *server)
267 {
268         fstring domain;
269         POLICY_HND pol;
270         DOM_SID sid;
271         BOOL res, res2, res3;
272
273         res = cli_nt_session_open(cli, PIPE_LSARPC);
274         res2 = res ? do_lsa_open_policy(cli, server, &pol, 0) : False;
275         res3 = res2 ? do_lsa_query_info_pol(cli, &pol, 5, domain, &sid) : False;
276
277         res3 = res3 ? secrets_store_domain_sid(domain, &sid) : False;
278
279         res2 = res2 ? do_lsa_close(cli, &pol) : False;
280         cli_nt_session_close(cli);
281         
282         return res3;
283 }
284
285 /****************************************************************************
286 do a LSA Open Policy
287 ****************************************************************************/
288 uint32 lsa_open_policy(const char *system_name, POLICY_HND *hnd,
289                        BOOL sec_qos, uint32 des_access)
290 {
291         prs_struct rbuf;
292         prs_struct buf;
293         LSA_Q_OPEN_POL q_o;
294         LSA_SEC_QOS qos;
295         struct cli_connection *con = NULL;
296         uint32 result = NT_STATUS_UNSUCCESSFUL;
297
298         if (!cli_connection_init(system_name, PIPE_LSARPC, &con)) {
299                 return NT_STATUS_UNSUCCESSFUL;
300         }
301
302         if (hnd == NULL) return NT_STATUS_UNSUCCESSFUL;
303
304         prs_init(&buf, MAX_PDU_FRAG_LEN, NULL, MARSHALL);
305         prs_init(&rbuf, 0, NULL, UNMARSHALL);
306
307         /* create and send a MSRPC command with api LSA_OPENPOLICY */
308
309         DEBUG(4, ("LSA Open Policy\n"));
310
311         /* store the parameters */
312         if (sec_qos) {
313                 init_lsa_sec_qos(&qos, 2, 1, 0, des_access);
314                 init_q_open_pol(&q_o, '\\', 0, des_access, &qos);
315         } else {
316                 init_q_open_pol(&q_o, '\\', 0, des_access, NULL);
317         }
318
319         /* turn parameters into data stream */
320         if (lsa_io_q_open_pol("", &q_o, &buf, 0) &&
321             rpc_con_pipe_req(con, LSA_OPENPOLICY, &buf, &rbuf)) {
322                 LSA_R_OPEN_POL r_o;
323                 BOOL p;
324
325                 lsa_io_r_open_pol("", &r_o, &rbuf, 0);
326                 p = rbuf.data_offset != 0;
327
328                 result = r_o.status;
329
330                 if (p && r_o.status != 0) {
331                         /* report error code */
332                         DEBUG(0,
333                               ("LSA_OPENPOLICY: %s\n",
334                                get_nt_error_msg(r_o.status)));
335                         p = False;
336                 }
337
338                 if (p) {
339
340                         /* Return the policy handle */
341
342                         *hnd = r_o.pol;
343
344                         if (!RpcHndList_set_connection(hnd, con)) {
345                                 result = NT_STATUS_NO_MEMORY;
346                         }
347                 }
348         }
349
350         prs_mem_free(&rbuf);
351         prs_mem_free(&buf);
352
353         return result;
354 }
355
356 /****************************************************************************
357 do a LSA Close
358 ****************************************************************************/
359 uint32 lsa_close(POLICY_HND *hnd)
360 {
361         prs_struct rbuf;
362         prs_struct buf;
363         LSA_Q_CLOSE q_c;
364         uint32 result = NT_STATUS_UNSUCCESSFUL;
365
366         if (hnd == NULL) return False;
367
368         /* Create and send a MSRPC command with api LSA_OPENPOLICY */
369
370         prs_init(&buf, MAX_PDU_FRAG_LEN, NULL, MARSHALL);
371         prs_init(&rbuf, 0, NULL, UNMARSHALL);
372
373         DEBUG(4, ("LSA Close\n"));
374
375         /* Store the parameters */
376
377         init_lsa_q_close(&q_c, hnd);
378
379         /* Turn parameters into data stream */
380
381         if (lsa_io_q_close("", &q_c, &buf, 0) &&
382             rpc_hnd_pipe_req(hnd, LSA_CLOSE, &buf, &rbuf)) {
383                 LSA_R_CLOSE r_c;
384                 BOOL p;
385
386                 lsa_io_r_close("", &r_c, &rbuf, 0);
387                 p = rbuf.data_offset != 0;
388                 result = r_c.status;
389
390                 if (p && r_c.status != 0) {
391
392                         /* Report error code */
393
394                         DEBUG(0, ("LSA_CLOSE: %s\n",
395                                   get_nt_error_msg(r_c.status)));
396
397                         p = False;
398                 }
399
400         }
401
402         prs_mem_free(&rbuf);
403         prs_mem_free(&buf);
404
405         return result;
406 }
407
408 /****************************************************************************
409 do a LSA Lookup SIDs
410 ****************************************************************************/
411 uint32 lsa_lookup_sids(POLICY_HND *hnd, int num_sids, DOM_SID *sids,
412                        char ***names, uint32 **types, int *num_names)
413 {
414         prs_struct rbuf;
415         prs_struct buf;
416         LSA_Q_LOOKUP_SIDS q_l;
417         TALLOC_CTX *ctx = talloc_init();
418         uint32 result = NT_STATUS_UNSUCCESSFUL;
419
420         ZERO_STRUCT(q_l);
421
422         if (hnd == NULL || num_sids == 0 || sids == NULL) return False;
423
424         if (num_names != NULL) {
425                 *num_names = 0;
426         }
427
428         if (types != NULL) {
429                 *types = NULL;
430         }
431
432         if (names != NULL) {
433                 *names = NULL;
434         }
435
436         prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL);
437         prs_init(&rbuf, 0, ctx, UNMARSHALL);
438
439         /* Create and send a MSRPC command with api LSA_LOOKUP_SIDS */
440
441         DEBUG(4, ("LSA Lookup SIDs\n"));
442
443         /* Store the parameters */
444
445         init_q_lookup_sids(ctx, &q_l, hnd, num_sids, sids, 1);
446
447         /* turn parameters into data stream */
448         if (lsa_io_q_lookup_sids("", &q_l, &buf, 0) &&
449             rpc_hnd_pipe_req(hnd, LSA_LOOKUPSIDS, &buf, &rbuf)) {
450                 LSA_R_LOOKUP_SIDS r_l;
451                 DOM_R_REF ref;
452                 LSA_TRANS_NAME_ENUM t_names;
453                 BOOL p, valid_response = False;
454
455                 r_l.dom_ref = &ref;
456                 r_l.names = &t_names;
457
458                 lsa_io_r_lookup_sids("", &r_l, &rbuf, 0);
459                 p = rbuf.data_offset != 0;
460                 result = r_l.status;
461
462                 if (p && r_l.status != 0 &&
463                     r_l.status != 0x107 &&
464                     r_l.status != (0xC0000000 | NT_STATUS_NONE_MAPPED)) {
465
466                         /* Report error code */
467
468                         DEBUG(1, ("LSA_LOOKUP_SIDS: %s\n",
469                                   get_nt_error_msg(r_l.status)));
470
471                         return r_l.status;
472                 }
473
474                 result = NT_STATUS_OK;
475
476                 if (p) {
477                         if (t_names.ptr_trans_names != 0
478                             && r_l.ptr_dom_ref != 0) {
479                                 valid_response = True;
480                         }
481                 }
482
483                 if (num_names != NULL && valid_response) {
484                         (*num_names) = t_names.num_entries;
485                 }
486
487                 if (valid_response) {
488                         uint32 i;
489
490                         for (i = 0; i < t_names.num_entries; i++) {
491                                 if ((t_names.name[i].domain_idx >=
492                                      ref.num_ref_doms_1)
493                                     && (t_names.name[i].domain_idx !=
494                                         0xffffffff)) {
495                                         DEBUG(0,
496                                               ("LSA_LOOKUP_SIDS: domain index out of bounds\n"));
497                                         valid_response = False;
498                                         break;
499                                 }
500                         }
501                 }
502
503                 if (types != NULL && valid_response && (*num_names) != 0) {
504                         (*types) = (uint32 *) malloc((*num_names) * 
505                                                      sizeof(uint32));
506                 }
507
508                 if (names != NULL && valid_response && (*num_names) != 0) {
509                         (*names) = (char **)malloc((*num_names) * 
510                                                    sizeof(char *));
511                 }
512
513                 if (names != NULL && (*names) != NULL) {
514                         int i;
515
516                         /* Take each name, construct a \DOMAIN\name string */
517
518                         for (i = 0; i < (*num_names); i++) {
519                                 fstring name;
520                                 fstring dom_name;
521                                 fstring full_name;
522                                 uint32 dom_idx = t_names.name[i].domain_idx;
523
524                                 if (dom_idx != 0xffffffff) {
525                                         unistr2_to_ascii(dom_name,
526                                                          &ref.
527                                                          ref_dom[dom_idx].
528                                                          uni_dom_name,
529                                                          sizeof(dom_name) -
530                                                          1);
531                                         unistr2_to_ascii(name,
532                                                          &t_names.uni_name[i],
533                                                          sizeof(name) - 1);
534
535                                         memset(full_name, 0,
536                                                sizeof(full_name));
537
538                                         slprintf(full_name,
539                                                  sizeof(full_name) - 1,
540                                                  "%s\\%s", dom_name, name);
541
542                                         (*names)[i] = strdup(full_name);
543                                         if (types != NULL && 
544                                             (*types) != NULL) {
545                                                 (*types)[i] = t_names.name[i].sid_name_use;
546                                         }
547                                 } else {
548                                         (*names)[i] = NULL;
549                                         if (types != NULL && 
550                                             (*types) != NULL) {
551                                                 (*types)[i] = SID_NAME_UNKNOWN;
552                                         }
553                                 }
554                         }
555                 }
556         }
557
558         prs_mem_free(&rbuf);
559         prs_mem_free(&buf);
560
561         return result;
562 }
563
564 /****************************************************************************
565 do a LSA Lookup Names
566 ****************************************************************************/
567 uint32 lsa_lookup_names(POLICY_HND *hnd, int num_names, char **names,
568                         DOM_SID **sids, uint32 **types, int *num_sids)
569 {
570         prs_struct rbuf;
571         prs_struct buf;
572         LSA_Q_LOOKUP_NAMES q_l;
573         BOOL valid_response = False;
574         TALLOC_CTX *ctx = talloc_init();
575         uint32 result = NT_STATUS_UNSUCCESSFUL;
576
577         if (hnd == NULL || num_sids == 0 || sids == NULL) return False;
578
579         prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL);
580         prs_init(&rbuf, 0, ctx, UNMARSHALL);
581
582         /* create and send a MSRPC command with api LSA_LOOKUP_NAMES */
583
584         DEBUG(4, ("LSA Lookup NAMEs\n"));
585
586         /* store the parameters */
587         init_q_lookup_names(ctx, &q_l, hnd, num_names, names);
588
589         /* turn parameters into data stream */
590         if (lsa_io_q_lookup_names("", &q_l, &buf, 0) &&
591             rpc_hnd_pipe_req(hnd, LSA_LOOKUPNAMES, &buf, &rbuf)) {
592                 LSA_R_LOOKUP_NAMES r_l;
593                 DOM_R_REF ref;
594                 DOM_RID2 t_rids[MAX_LOOKUP_SIDS];
595                 BOOL p;
596
597                 ZERO_STRUCT(ref);
598                 ZERO_STRUCT(t_rids);
599
600                 r_l.dom_ref = &ref;
601                 r_l.dom_rid = t_rids;
602
603                 lsa_io_r_lookup_names("", &r_l, &rbuf, 0);
604                 p = rbuf.data_offset != 0;
605
606                 if (p && r_l.status != 0) {
607                         /* report error code */
608                         DEBUG(1,
609                               ("LSA_LOOKUP_NAMES: %s\n",
610                                get_nt_error_msg(r_l.status)));
611                         p = False;
612
613                         return r_l.status;
614                 }
615
616                 result = r_l.status;
617
618                 if (p) {
619                         if (r_l.ptr_dom_ref != 0 && r_l.ptr_entries != 0) {
620                                 valid_response = True;
621                         }
622                 }
623
624                 if (num_sids != NULL && valid_response) {
625                         (*num_sids) = r_l.num_entries;
626                 }
627
628                 if (valid_response) {
629                         uint32 i;
630
631                         for (i = 0; i < r_l.num_entries; i++) {
632                                 if (t_rids[i].rid_idx >= ref.num_ref_doms_1 &&
633                                     t_rids[i].rid_idx != 0xffffffff) {
634                                         DEBUG(0,
635                                               ("LSA_LOOKUP_NAMES: domain index %d out of bounds\n",
636                                                t_rids[i].rid_idx));
637                                         valid_response = False;
638                                         break;
639                                 }
640                         }
641                 }
642
643                 if (types != NULL && valid_response && r_l.num_entries != 0) {
644                         (*types) = (uint32 *) malloc((*num_sids) * 
645                                                      sizeof(uint32));
646                 }
647
648                 if (sids != NULL && valid_response && r_l.num_entries != 0) {
649                         (*sids) = (DOM_SID *) malloc((*num_sids) * 
650                                                      sizeof(DOM_SID));
651                 }
652
653                 if (sids != NULL && (*sids) != NULL) {
654                         int i;
655
656                         /* Take each name, construct a SID */
657
658                         for (i = 0; i < (*num_sids); i++) {
659                                 uint32 dom_idx = t_rids[i].rid_idx;
660                                 uint32 dom_rid = t_rids[i].rid;
661                                 DOM_SID *sid = &(*sids)[i];
662
663                                 if (dom_idx != 0xffffffff) {
664
665                                         sid_copy(sid,
666                                                  &ref.ref_dom[dom_idx].
667                                                  ref_dom.sid);
668
669                                         if (dom_rid != 0xffffffff) {
670                                                 sid_append_rid(sid, dom_rid);
671                                         }
672
673                                         if (types != NULL && 
674                                             (*types) != NULL) {
675                                                 (*types)[i] = t_rids[i].type;
676                                         }
677
678                                 } else {
679                                         ZERO_STRUCTP(sid);
680
681                                         if (types != NULL && 
682                                             (*types) != NULL) {
683                                                 (*types)[i] = SID_NAME_UNKNOWN;
684                                         }
685                                 }
686                         }
687                 }
688         }
689
690         prs_mem_free(&rbuf);
691         prs_mem_free(&buf);
692
693         return result;
694 }