rpc_server/srv_lsa.c: Bring into sync with 2.0.x.
[tprouty/samba.git] / source / rpc_server / srv_lsa.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                    1998.
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 extern DOM_SID global_sam_sid;
29 extern fstring global_myworkgroup;
30 extern pstring global_myname;
31
32 /***************************************************************************
33  lsa_reply_open_policy2
34  ***************************************************************************/
35
36 static BOOL lsa_reply_open_policy2(prs_struct *rdata)
37 {
38         int i;
39         LSA_R_OPEN_POL2 r_o;
40
41         ZERO_STRUCT(r_o);
42
43         /* set up the LSA QUERY INFO response */
44
45         for (i = 4; i < POL_HND_SIZE; i++)
46                 r_o.pol.data[i] = i;
47         r_o.status = 0x0;
48
49         /* store the response in the SMB stream */
50         if(!lsa_io_r_open_pol2("", &r_o, rdata, 0)) {
51                 DEBUG(0,("lsa_reply_open_policy2: unable to marshall LSA_R_OPEN_POL2.\n"));
52                 return False;
53         }
54
55         return True;
56 }
57
58 /***************************************************************************
59 lsa_reply_open_policy
60  ***************************************************************************/
61
62 static BOOL lsa_reply_open_policy(prs_struct *rdata)
63 {
64         int i;
65         LSA_R_OPEN_POL r_o;
66
67         ZERO_STRUCT(r_o);
68
69         /* set up the LSA QUERY INFO response */
70
71         for (i = 4; i < POL_HND_SIZE; i++)
72                 r_o.pol.data[i] = i;
73         r_o.status = 0x0;
74
75         /* store the response in the SMB stream */
76         if(!lsa_io_r_open_pol("", &r_o, rdata, 0)) {
77                 DEBUG(0,("lsa_reply_open_policy: unable to marshall LSA_R_OPEN_POL.\n"));
78                 return False;
79         }
80
81         return True;
82 }
83
84 /***************************************************************************
85 Init dom_query
86  ***************************************************************************/
87
88 static void init_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
89 {
90         fstring sid_str;
91         int domlen = strlen(dom_name);
92
93         *sid_str = '\0';
94
95         d_q->uni_dom_max_len = domlen * 2;
96         d_q->uni_dom_str_len = domlen * 2;
97
98         d_q->buffer_dom_name = domlen  != 0    ? 1 : 0; /* domain buffer pointer */
99         d_q->buffer_dom_sid  = dom_sid != NULL ? 1 : 0; /* domain sid pointer */
100
101         /* this string is supposed to be character short */
102         init_unistr2(&d_q->uni_domain_name, dom_name, domlen);
103
104         if(dom_sid) {
105                 sid_to_string(sid_str, dom_sid);
106                 init_dom_sid2(&d_q->dom_sid, dom_sid);
107         }
108 }
109
110 /***************************************************************************
111  lsa_reply_enum_trust_dom
112  ***************************************************************************/
113
114 static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e,
115                                 prs_struct *rdata,
116                                 uint32 enum_context, char *dom_name, DOM_SID *dom_sid)
117 {
118         LSA_R_ENUM_TRUST_DOM r_e;
119
120         ZERO_STRUCT(r_e);
121
122         /* set up the LSA QUERY INFO response */
123         init_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid,
124               dom_name != NULL ? 0x0 : 0x80000000 | NT_STATUS_UNABLE_TO_FREE_VM);
125
126         /* store the response in the SMB stream */
127         lsa_io_r_enum_trust_dom("", &r_e, rdata, 0);
128 }
129
130 /***************************************************************************
131 lsa_reply_query_info
132  ***************************************************************************/
133
134 static BOOL lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata,
135                                 char *dom_name, DOM_SID *dom_sid, uint32 status_code)
136 {
137         LSA_R_QUERY_INFO r_q;
138
139         ZERO_STRUCT(r_q);
140
141         /* set up the LSA QUERY INFO response */
142
143         if(status_code == 0) {
144                 r_q.undoc_buffer = 0x22000000; /* bizarre */
145                 r_q.info_class = q_q->info_class;
146
147                 init_dom_query(&r_q.dom.id5, dom_name, dom_sid);
148         }
149
150         r_q.status = status_code;
151
152         /* store the response in the SMB stream */
153         if(!lsa_io_r_query("", &r_q, rdata, 0)) {
154                 DEBUG(0,("lsa_reply_query_info: failed to marshall LSA_R_QUERY_INFO.\n"));
155                 return False;
156         }
157
158         return True;
159 }
160
161 /***************************************************************************
162  init_dom_ref - adds a domain if it's not already in, returns the index.
163 ***************************************************************************/
164
165 static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
166 {
167         int num = 0;
168         int len;
169
170         if (dom_name != NULL) {
171                 for (num = 0; num < ref->num_ref_doms_1; num++) {
172                         fstring domname;
173                         fstrcpy(domname, dos_unistr2_to_str(&ref->ref_dom[num].uni_dom_name));
174                         if (strequal(domname, dom_name))
175                                 return num;
176                 }
177         } else {
178                 num = ref->num_ref_doms_1;
179         }
180
181         if (num >= MAX_REF_DOMAINS) {
182                 /* index not found, already at maximum domain limit */
183                 return -1;
184         }
185
186         ref->num_ref_doms_1 = num+1;
187         ref->ptr_ref_dom  = 1;
188         ref->max_entries = MAX_REF_DOMAINS;
189         ref->num_ref_doms_2 = num+1;
190
191         len = (dom_name != NULL) ? strlen(dom_name) : 0;
192         if(dom_name != NULL && len == 0)
193                 len = 1;
194
195         init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, len);
196         ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0;
197
198         init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, len);
199         init_dom_sid2(&ref->ref_dom[num].ref_dom, dom_sid );
200
201         return num;
202 }
203
204 /***************************************************************************
205  init_lsa_rid2s
206  ***************************************************************************/
207
208 static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
209                                 int num_entries, UNISTR2 name[MAX_LOOKUP_SIDS],
210                                 uint32 *mapped_count)
211 {
212         int i;
213         int total = 0;
214         *mapped_count = 0;
215
216         SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
217
218         for (i = 0; i < num_entries; i++) {
219                 BOOL status = False;
220                 DOM_SID dom_sid;
221                 DOM_SID sid;
222                 uint32 rid = 0xffffffff;
223                 int dom_idx = -1;
224                 pstring full_name;
225                 fstring dom_name;
226                 fstring user;
227                 uint8 sid_name_use = SID_NAME_UNKNOWN;
228
229                 pstrcpy(full_name, dos_unistr2_to_str(&name[i]));
230
231                 /*
232                  * Try and split the name into a DOMAIN and
233                  * user component.
234                  */
235
236                 split_domain_name(full_name, dom_name, user);
237
238                 /*
239                  * We only do anything with this name if we
240                  * can map the Domain into a SID we know.
241                  */
242
243                 if (map_domain_name_to_sid(&dom_sid, dom_name)) {
244                         dom_idx = init_dom_ref(ref, dom_name, &dom_sid);
245
246                         if (lookup_local_name(dom_name, user, &sid, &sid_name_use) && sid_split_rid(&sid, &rid)) 
247                                 status = True;
248                 }
249
250                 if (status)
251                         (*mapped_count)++;
252                 else {
253                         dom_idx = -1;
254                         rid = 0xffffffff;
255                         sid_name_use = SID_NAME_UNKNOWN;
256                 }
257
258                 init_dom_rid2(&rid2[total], rid, sid_name_use, dom_idx);
259                 total++;
260         }
261 }
262
263 /***************************************************************************
264  init_reply_lookup_names
265  ***************************************************************************/
266
267 static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
268                 DOM_R_REF *ref, uint32 num_entries,
269                 DOM_RID2 *rid2, uint32 mapped_count)
270 {
271         r_l->ptr_dom_ref  = 1;
272         r_l->dom_ref      = ref;
273
274         r_l->num_entries  = num_entries;
275         r_l->ptr_entries  = 1;
276         r_l->num_entries2 = num_entries;
277         r_l->dom_rid      = rid2;
278
279         r_l->mapped_count = mapped_count;
280
281         if (mapped_count == 0)
282                 r_l->status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
283         else
284                 r_l->status = 0x0;
285 }
286
287 /***************************************************************************
288  Init lsa_trans_names.
289  ***************************************************************************/
290
291 static void init_lsa_trans_names(DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn,
292                                 int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], uint32 *mapped_count)
293 {
294         extern DOM_SID global_sid_S_1_5_0x20; /* BUILTIN sid. */
295         int i;
296         int total = 0;
297         *mapped_count = 0;
298
299         SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
300
301         for (i = 0; i < num_entries; i++) {
302                 BOOL status = False;
303                 DOM_SID find_sid = sid[i].sid;
304                 uint32 rid = 0xffffffff;
305                 int dom_idx = -1;
306                 fstring name;
307                 fstring dom_name;
308                 uint8 sid_name_use = 0;
309
310                 memset(dom_name, '\0', sizeof(dom_name));
311                 memset(name, '\0', sizeof(name));
312
313                 /*
314                  * First, check to see if the SID is one of the well
315                  * known ones (this includes our own domain SID).
316                  * Next, check if the domain prefix is one of the
317                  * well known ones. If so and the domain prefix was
318                  * either BUILTIN or our own global sid, then lookup
319                  * the RID as a user or group id and translate to
320                  * a name.
321                  */
322
323                 if (map_domain_sid_to_name(&find_sid, dom_name)) {
324                         sid_name_use = SID_NAME_DOMAIN;
325                 } else if (sid_split_rid(&find_sid, &rid) && map_domain_sid_to_name(&find_sid, dom_name)) {
326                         if (sid_equal(&find_sid, &global_sam_sid) ||
327                                 sid_equal(&find_sid, &global_sid_S_1_5_0x20)) {
328                                 status = lookup_local_rid(rid, name, &sid_name_use);
329                         } else  {
330                                 status = lookup_known_rid(&find_sid, rid, name, &sid_name_use);
331                         }
332                 }
333
334                 DEBUG(10,("init_lsa_trans_names: adding domain '%s' sid %s to referenced list.\n",
335                                 dom_name, name ));
336
337                 dom_idx = init_dom_ref(ref, dom_name, &find_sid);
338
339                 if(!status) {
340                         slprintf(name, sizeof(name)-1, "unix.%08x", rid);
341                         sid_name_use = SID_NAME_UNKNOWN;
342                 }
343
344                 DEBUG(10,("init_lsa_trans_names: added user '%s\\%s' to referenced list.\n", dom_name, name ));
345
346                 (*mapped_count)++;
347
348                 init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
349                                         sid_name_use, name, dom_idx);
350                 total++;
351         }
352
353         trn->num_entries = total;
354         trn->ptr_trans_names = 1;
355         trn->num_entries2 = total;
356 }
357
358 /***************************************************************************
359  Init_reply_lookup_sids.
360  ***************************************************************************/
361
362 static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
363                 DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
364                 uint32 mapped_count)
365 {
366         r_l->ptr_dom_ref  = 1;
367         r_l->dom_ref      = ref;
368         r_l->names        = names;
369         r_l->mapped_count = mapped_count;
370
371         if (mapped_count == 0)
372                 r_l->status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
373         else
374                 r_l->status = 0x0;
375 }
376
377 /***************************************************************************
378 lsa_reply_lookup_sids
379  ***************************************************************************/
380
381 static BOOL lsa_reply_lookup_sids(prs_struct *rdata, DOM_SID2 *sid, int num_entries)
382 {
383         LSA_R_LOOKUP_SIDS r_l;
384         DOM_R_REF ref;
385         LSA_TRANS_NAME_ENUM names;
386         uint32 mapped_count = 0;
387
388         ZERO_STRUCT(r_l);
389         ZERO_STRUCT(ref);
390         ZERO_STRUCT(names);
391
392         /* set up the LSA Lookup SIDs response */
393         init_lsa_trans_names(&ref, &names, num_entries, sid, &mapped_count);
394         init_reply_lookup_sids(&r_l, &ref, &names, mapped_count);
395
396         /* store the response in the SMB stream */
397         if(!lsa_io_r_lookup_sids("", &r_l, rdata, 0)) {
398                 DEBUG(0,("lsa_reply_lookup_sids: Failed to marshall LSA_R_LOOKUP_SIDS.\n"));
399                 return False;
400         }
401
402         return True;
403 }
404
405 /***************************************************************************
406 lsa_reply_lookup_names
407  ***************************************************************************/
408
409 static BOOL lsa_reply_lookup_names(prs_struct *rdata,
410                 UNISTR2 names[MAX_LOOKUP_SIDS], int num_entries)
411 {
412         LSA_R_LOOKUP_NAMES r_l;
413         DOM_R_REF ref;
414         DOM_RID2 rids[MAX_LOOKUP_SIDS];
415         uint32 mapped_count = 0;
416
417         ZERO_STRUCT(r_l);
418         ZERO_STRUCT(ref);
419         ZERO_ARRAY(rids);
420
421         /* set up the LSA Lookup RIDs response */
422         init_lsa_rid2s(&ref, rids, num_entries, names, &mapped_count);
423         init_reply_lookup_names(&r_l, &ref, num_entries, rids, mapped_count);
424
425         /* store the response in the SMB stream */
426         if(!lsa_io_r_lookup_names("", &r_l, rdata, 0)) {
427                 DEBUG(0,("lsa_reply_lookup_names: Failed to marshall LSA_R_LOOKUP_NAMES.\n"));
428                 return False;
429         }
430
431         return True;
432 }
433
434 /***************************************************************************
435  api_lsa_open_policy2
436  ***************************************************************************/
437
438 static BOOL api_lsa_open_policy2(prs_struct *data, prs_struct *rdata)
439 {
440         LSA_Q_OPEN_POL2 q_o;
441
442         ZERO_STRUCT(q_o);
443
444         /* grab the server, object attributes and desired access flag...*/
445         if(!lsa_io_q_open_pol2("", &q_o, data, 0)) {
446                 DEBUG(0,("api_lsa_open_policy2: unable to unmarshall LSA_Q_OPEN_POL2.\n"));
447                 return False;
448         }
449
450         /* lkclXXXX having decoded it, ignore all fields in the open policy! */
451
452         /* return a 20 byte policy handle */
453         if(!lsa_reply_open_policy2(rdata))
454                 return False;
455
456         return True;
457 }
458
459 /***************************************************************************
460 api_lsa_open_policy
461  ***************************************************************************/
462 static BOOL api_lsa_open_policy(prs_struct *data, prs_struct *rdata)
463 {
464         LSA_Q_OPEN_POL q_o;
465
466         ZERO_STRUCT(q_o);
467
468         /* grab the server, object attributes and desired access flag...*/
469         if(!lsa_io_q_open_pol("", &q_o, data, 0)) {
470                 DEBUG(0,("api_lsa_open_policy: unable to unmarshall LSA_Q_OPEN_POL.\n"));
471                 return False;
472         }
473
474         /* lkclXXXX having decoded it, ignore all fields in the open policy! */
475
476         /* return a 20 byte policy handle */
477         if(!lsa_reply_open_policy(rdata))
478                 return False;
479
480         return True;
481 }
482
483 /***************************************************************************
484 api_lsa_enum_trust_dom
485  ***************************************************************************/
486 static BOOL api_lsa_enum_trust_dom(prs_struct *data, prs_struct *rdata)
487 {
488         LSA_Q_ENUM_TRUST_DOM q_e;
489
490         ZERO_STRUCT(q_e);
491
492         /* grab the enum trust domain context etc. */
493         if(!lsa_io_q_enum_trust_dom("", &q_e, data, 0))
494                 return False;
495
496         /* construct reply.  return status is always 0x0 */
497         lsa_reply_enum_trust_dom(&q_e, rdata, 0, NULL, NULL);
498
499         return True;
500 }
501
502 /***************************************************************************
503 api_lsa_query_info
504  ***************************************************************************/
505 static BOOL api_lsa_query_info(prs_struct *data, prs_struct *rdata)
506 {
507         LSA_Q_QUERY_INFO q_i;
508         fstring name;
509         DOM_SID *sid = NULL;
510         uint32 status_code = 0;
511
512         memset(name, 0, sizeof(name));
513
514         ZERO_STRUCT(q_i);
515
516         /* grab the info class and policy handle */
517         if(!lsa_io_q_query("", &q_i, data, 0)) {
518                 DEBUG(0,("api_lsa_query_info: failed to unmarshall LSA_Q_QUERY_INFO.\n"));
519                 return False;
520         }
521
522         switch (q_i.info_class) {
523         case 0x03:
524                 if(lp_domain_logons()) {
525                         fstrcpy(name, global_myworkgroup);
526                         sid = &global_sam_sid;
527                 } else {
528                         *name = '\0';
529                 }
530                 break;
531         case 0x05:
532                 fstrcpy(name, global_myname);
533                 sid = &global_sam_sid;
534                 break;
535         default:
536                 DEBUG(0,("api_lsa_query_info: unknown info level in Lsa Query: %d\n", q_i.info_class));
537                 status_code = (NT_STATUS_INVALID_INFO_CLASS | 0xC0000000);
538                 break;
539         }
540
541         /* construct reply.  return status is always 0x0 */
542         if(!lsa_reply_query_info(&q_i, rdata, name, sid, status_code))
543                 return False;
544
545         return True;
546 }
547
548 /***************************************************************************
549  api_lsa_lookup_sids
550  ***************************************************************************/
551
552 static BOOL api_lsa_lookup_sids(prs_struct *data, prs_struct *rdata)
553 {
554         LSA_Q_LOOKUP_SIDS q_l;
555         ZERO_STRUCT(q_l);
556
557         /* grab the info class and policy handle */
558         if(!lsa_io_q_lookup_sids("", &q_l, data, 0)) {
559                 DEBUG(0,("api_lsa_lookup_sids: failed to unmarshall LSA_Q_LOOKUP_SIDS.\n"));
560                 return False;
561         }
562
563         /* construct reply.  return status is always 0x0 */
564         if(!lsa_reply_lookup_sids(rdata, q_l.sids.sid, q_l.sids.num_entries))
565                 return False;
566
567         return True;
568 }
569
570 /***************************************************************************
571  api_lsa_lookup_names
572  ***************************************************************************/
573
574 static BOOL api_lsa_lookup_names(prs_struct *data, prs_struct *rdata)
575 {
576         LSA_Q_LOOKUP_NAMES q_l;
577         ZERO_STRUCT(q_l);
578
579         /* grab the info class and policy handle */
580         if(!lsa_io_q_lookup_names("", &q_l, data, 0)) {
581                 DEBUG(0,("api_lsa_lookup_names: failed to unmarshall LSA_Q_LOOKUP_NAMES.\n"));
582                 return False;
583         }
584
585         SMB_ASSERT_ARRAY(q_l.uni_name, q_l.num_entries);
586
587         return lsa_reply_lookup_names(rdata, q_l.uni_name, q_l.num_entries);
588 }
589
590 /***************************************************************************
591  api_lsa_close
592  ***************************************************************************/
593 static BOOL api_lsa_close(prs_struct *data, prs_struct *rdata)
594 {
595         LSA_R_CLOSE r_c;
596
597         ZERO_STRUCT(r_c);
598
599         /* store the response in the SMB stream */
600         if (!lsa_io_r_close("", &r_c, rdata, 0)) {
601                 DEBUG(0,("api_lsa_close: lsa_io_r_close failed.\n"));
602                 return False;
603         }
604
605         return True;
606 }
607
608 /***************************************************************************
609  api_lsa_open_secret
610  ***************************************************************************/
611 static BOOL api_lsa_open_secret(prs_struct *data, prs_struct *rdata)
612 {
613         /* XXXX this is NOT good */
614         size_t i;
615         uint32 dummy = 0;
616
617         for(i =0; i < 4; i++) {
618                 if(!prs_uint32("api_lsa_close", rdata, 1, &dummy)) {
619                         DEBUG(0,("api_lsa_open_secret: prs_uint32 %d failed.\n",
620                                 (int)i ));
621                         return False;
622                 }
623         }
624
625         dummy = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
626         if(!prs_uint32("api_lsa_close", rdata, 1, &dummy)) {
627                 DEBUG(0,("api_lsa_open_secret: prs_uint32 status failed.\n"));
628                 return False;
629         }
630
631         return True;
632 }
633
634 /***************************************************************************
635  \PIPE\ntlsa commands
636  ***************************************************************************/
637 static struct api_struct api_lsa_cmds[] =
638 {
639         { "LSA_OPENPOLICY2"     , LSA_OPENPOLICY2     , api_lsa_open_policy2   },
640         { "LSA_OPENPOLICY"      , LSA_OPENPOLICY      , api_lsa_open_policy    },
641         { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info     },
642         { "LSA_ENUMTRUSTDOM"    , LSA_ENUMTRUSTDOM    , api_lsa_enum_trust_dom },
643         { "LSA_CLOSE"           , LSA_CLOSE           , api_lsa_close          },
644         { "LSA_OPENSECRET"      , LSA_OPENSECRET      , api_lsa_open_secret    },
645         { "LSA_LOOKUPSIDS"      , LSA_LOOKUPSIDS      , api_lsa_lookup_sids    },
646         { "LSA_LOOKUPNAMES"     , LSA_LOOKUPNAMES     , api_lsa_lookup_names   },
647         { NULL                  , 0                   , NULL                   }
648 };
649
650 /***************************************************************************
651  api_ntLsarpcTNP
652  ***************************************************************************/
653 BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data)
654 {
655         return api_rpcTNP(p, "api_ntlsa_rpc", api_lsa_cmds, data);
656 }