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