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