030e00e87abea1aa21a28c8d93ef95d191864012
[samba.git] / source / pipentlsa.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Pipe SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1997,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
7    Copyright (C) Paul Ashton  1997.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 /*
24    This file handles reply_ calls on named pipes that the server
25    makes to handle specific protocols
26 */
27
28
29 #include "includes.h"
30 #include "trans2.h"
31 #include "nterr.h"
32
33 extern int DEBUGLEVEL;
34
35 #ifdef NTDOMAIN
36
37 static int lsa_reply_open_policy(char *q, char *base)
38 {
39         int i;
40         LSA_R_OPEN_POL r_o;
41
42         /* set up the LSA QUERY INFO response */
43         /* bzero(&(r_o.pol.data), POL_HND_SIZE); */
44         for (i = 0; i < POL_HND_SIZE; i++)
45         {
46                 r_o.pol.data[i] = i;
47         }
48         r_o.status = 0x0;
49
50         /* store the response in the SMB stream */
51         q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0);
52
53         /* return length of SMB data stored */
54         return PTR_DIFF(q, base);
55 }
56
57 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
58 {
59         int domlen = strlen(dom_name);
60
61         d_q->uni_dom_max_len = domlen * 2;
62         d_q->uni_dom_str_len = domlen * 2;
63
64         d_q->buffer_dom_name = 4; /* domain buffer pointer */
65         d_q->buffer_dom_sid  = 2; /* domain sid pointer */
66
67         /* this string is supposed to be character short */
68         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
69
70         make_dom_sid(&(d_q->dom_sid), dom_sid);
71 }
72
73 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
74                                 char *dom_name, char *dom_sid)
75 {
76         LSA_R_QUERY_INFO r_q;
77
78         /* set up the LSA QUERY INFO response */
79
80         r_q.undoc_buffer = 0x22000000; /* bizarre */
81         r_q.info_class = q_q->info_class;
82
83         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
84
85         r_q.status = 0x0;
86
87         /* store the response in the SMB stream */
88         q = lsa_io_r_query(False, &r_q, q, base, 4, 0);
89
90         /* return length of SMB data stored */
91         return PTR_DIFF(q, base);
92 }
93
94 /* pretty much hard-coded choice of "other" sids, unfortunately... */
95 static void make_dom_ref(DOM_R_REF *ref,
96                                 char *dom_name, char *dom_sid,
97                                 char *other_sid1, char *other_sid2, char *other_sid3)
98 {
99         int len_dom_name   = strlen(dom_name);
100         int len_other_sid1 = strlen(other_sid1);
101         int len_other_sid2 = strlen(other_sid2);
102         int len_other_sid3 = strlen(other_sid3);
103
104         ref->undoc_buffer = 1;
105         ref->num_ref_doms_1 = 4;
106         ref->buffer_dom_name = 1;
107         ref->max_entries = 32;
108         ref->num_ref_doms_2 = 4;
109
110         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
111         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
112         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
113         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
114
115         if (dom_name != NULL)
116         {
117                 make_unistr(&(ref->uni_dom_name), dom_name);
118         }
119
120         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
121         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
122         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
123         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
124 }
125
126 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
127                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
128                                 char *dom_name, char *dom_sid,
129                                 char *other_sid1, char *other_sid2, char *other_sid3)
130 {
131         int i;
132
133         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
134                      other_sid1, other_sid2, other_sid3);
135
136         r_l->num_entries = num_entries;
137         r_l->undoc_buffer = 1;
138         r_l->num_entries2 = num_entries;
139
140         for (i = 0; i < num_entries; i++)
141         {
142                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
143         }
144
145         r_l->num_entries3 = num_entries;
146 }
147
148 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
149                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
150                                 char *dom_name, char *dom_sid,
151                                 char *other_sid1, char *other_sid2, char *other_sid3)
152 {
153         int i;
154
155         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
156                      other_sid1, other_sid2, other_sid3);
157
158         r_l->num_entries = num_entries;
159         r_l->undoc_buffer = 1;
160         r_l->num_entries2 = num_entries;
161
162         for (i = 0; i < num_entries; i++)
163         {
164                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
165         }
166
167         r_l->num_entries3 = num_entries;
168 }
169
170 static int lsa_reply_lookup_sids(char *q, char *base,
171                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
172                                 char *dom_name, char *dom_sid,
173                                 char *other_sid1, char *other_sid2, char *other_sid3)
174 {
175         LSA_R_LOOKUP_SIDS r_l;
176
177         /* set up the LSA Lookup SIDs response */
178         make_reply_lookup_sids(&r_l, num_entries, dom_sids,
179                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
180         r_l.status = 0x0;
181
182         /* store the response in the SMB stream */
183         q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0);
184
185         /* return length of SMB data stored */
186         return PTR_DIFF(q, base);
187 }
188
189 static int lsa_reply_lookup_rids(char *q, char *base,
190                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
191                                 char *dom_name, char *dom_sid,
192                                 char *other_sid1, char *other_sid2, char *other_sid3)
193 {
194         LSA_R_LOOKUP_RIDS r_l;
195
196         /* set up the LSA Lookup RIDs response */
197         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
198                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
199         r_l.status = 0x0;
200
201         /* store the response in the SMB stream */
202         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0);
203
204         /* return length of SMB data stored */
205         return PTR_DIFF(q, base);
206 }
207
208 static void api_lsa_open_policy( char *param, char *data,
209                              char **rdata, int *rdata_len )
210 {
211         /* we might actually want to decode the query, but it's not necessary */
212         /* lsa_io_q_open_policy(...); */
213
214         /* return a 20 byte policy handle */
215         *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata);
216 }
217
218 static void api_lsa_query_info( char *param, char *data,
219                                 char **rdata, int *rdata_len )
220 {
221         LSA_Q_QUERY_INFO q_i;
222         pstring dom_name;
223         pstring dom_sid;
224
225         /* grab the info class and policy handle */
226         lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0);
227
228         pstrcpy(dom_name, lp_workgroup());
229         pstrcpy(dom_sid , lp_domainsid());
230
231         /* construct reply.  return status is always 0x0 */
232         *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, 
233                                                                          dom_name, dom_sid);
234 }
235
236 static void api_lsa_lookup_sids( char *param, char *data,
237                                  char **rdata, int *rdata_len )
238 {
239         int i;
240         LSA_Q_LOOKUP_SIDS q_l;
241         pstring dom_name;
242         pstring dom_sid;
243         fstring dom_sids[MAX_LOOKUP_SIDS];
244
245         /* grab the info class and policy handle */
246         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0);
247
248         pstrcpy(dom_name, lp_workgroup());
249         pstrcpy(dom_sid , lp_domainsid());
250
251         /* convert received SIDs to strings, so we can do them. */
252         for (i = 0; i < q_l.num_entries; i++)
253         {
254                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
255         }
256
257         /* construct reply.  return status is always 0x0 */
258         *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata,
259                     q_l.num_entries, dom_sids, /* text-converted SIDs */
260                                 dom_name, dom_sid, /* domain name, domain SID */
261                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
262 }
263
264 static void api_lsa_lookup_names( char *param, char *data,
265                                   char **rdata, int *rdata_len )
266 {
267         int i;
268         LSA_Q_LOOKUP_RIDS q_l;
269         pstring dom_name;
270         pstring dom_sid;
271         uint32 dom_rids[MAX_LOOKUP_SIDS];
272
273         /* grab the info class and policy handle */
274         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0);
275
276         pstrcpy(dom_name, lp_workgroup());
277         pstrcpy(dom_sid , lp_domainsid());
278
279         /* convert received RIDs to strings, so we can do them. */
280         for (i = 0; i < q_l.num_entries; i++)
281         {
282                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
283                 dom_rids[i] = name_to_rid(user_name);
284         }
285
286         /* construct reply.  return status is always 0x0 */
287         *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata,
288                     q_l.num_entries, dom_rids, /* text-converted SIDs */
289                                 dom_name, dom_sid, /* domain name, domain SID */
290                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
291 }
292
293 BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
294                      int mdrcnt,int mprcnt,
295                      char **rdata,char **rparam,
296                      int *rdata_len,int *rparam_len)
297 {
298         uint16 opnum = SVAL(data,22);
299
300         int pkttype = CVAL(data, 2);
301         if (pkttype == 0x0b) /* RPC BIND */
302         {
303                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
304                 LsarpcTNP1(data,rdata,rdata_len);
305                 return True;
306         }
307
308         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
309         switch (opnum)
310         {
311                 case LSA_OPENPOLICY:
312                 {
313                         DEBUG(3,("LSA_OPENPOLICY\n"));
314                         api_lsa_open_policy(param, data, rdata, rdata_len);
315                         make_rpc_reply(data, *rdata, *rdata_len);
316                         break;
317                 }
318
319                 case LSA_QUERYINFOPOLICY:
320                 {
321                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
322
323                         api_lsa_query_info(param, data, rdata, rdata_len);
324                         make_rpc_reply(data, *rdata, *rdata_len);
325                         break;
326                 }
327
328                 case LSA_ENUMTRUSTDOM:
329                 {
330                         char *q = *rdata + 0x18;
331
332                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
333
334                         initrpcreply(data, *rdata);
335
336                         SIVAL(q, 0, 0); /* enumeration context */
337                         SIVAL(q, 0, 4); /* entries read */
338                         SIVAL(q, 0, 8); /* trust information */
339
340                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
341
342                         break;
343                 }
344
345                 case LSA_CLOSE:
346                 {
347                         char *q = *rdata + 0x18;
348
349                         DEBUG(3,("LSA_CLOSE\n"));
350
351                         initrpcreply(data, *rdata);
352
353                         SIVAL(q, 0, 0);
354                         SIVAL(q, 0, 4);
355                         SIVAL(q, 0, 8);
356                         SIVAL(q, 0, 12);
357                         SIVAL(q, 0, 16);
358
359                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
360
361                         break;
362                 }
363
364                 case LSA_OPENSECRET:
365                 {
366                         char *q = *rdata + 0x18;
367                         DEBUG(3,("LSA_OPENSECRET\n"));
368
369                         initrpcreply(data, *rdata);
370
371                         SIVAL(q, 0, 0);
372                         SIVAL(q, 0, 4);
373                         SIVAL(q, 0, 8);
374                         SIVAL(q, 0, 12);
375                         SIVAL(q, 0, 16);
376
377                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
378
379                         break;
380                 }
381
382                 case LSA_LOOKUPSIDS:
383                 {
384                         DEBUG(3,("LSA_OPENSECRET\n"));
385                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
386                         make_rpc_reply(data, *rdata, *rdata_len);
387                         break;
388                 }
389
390                 case LSA_LOOKUPNAMES:
391                 {
392                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
393                         api_lsa_lookup_names(param, data, rdata, rdata_len);
394                         make_rpc_reply(data, *rdata, *rdata_len);
395                         break;
396                 }
397
398                 default:
399                 {
400                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
401                         break;
402                 }
403         }
404         return True;
405 }
406
407 #endif /* NTDOMAIN */