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