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