Added fixes for become_user braindamage.
[kai/samba.git] / source3 / 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->padding = 0;
63         d_q->uni_dom_str_len = domlen * 2;
64
65         d_q->buffer_dom_name = 0; /* domain buffer pointer */
66         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
67
68         /* NOT null-terminated: 4-terminated instead! */
69         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
70
71         make_dom_sid(&(d_q->dom_sid), dom_sid);
72 }
73
74 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
75                                 char *dom_name, char *dom_sid)
76 {
77         LSA_R_QUERY_INFO r_q;
78
79         /* set up the LSA QUERY INFO response */
80
81         r_q.undoc_buffer = 1; /* not null */
82         r_q.info_class = q_q->info_class;
83
84         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
85
86         r_q.status = 0x0;
87
88         /* store the response in the SMB stream */
89         q = lsa_io_r_query(False, &r_q, q, base, 4, 0);
90
91         /* return length of SMB data stored */
92         return PTR_DIFF(q, base);
93 }
94
95 /* pretty much hard-coded choice of "other" sids, unfortunately... */
96 static void make_dom_ref(DOM_R_REF *ref,
97                                 char *dom_name, char *dom_sid,
98                                 char *other_sid1, char *other_sid2, char *other_sid3)
99 {
100         int len_dom_name   = strlen(dom_name);
101         int len_other_sid1 = strlen(other_sid1);
102         int len_other_sid2 = strlen(other_sid2);
103         int len_other_sid3 = strlen(other_sid3);
104
105         ref->undoc_buffer = 1;
106         ref->num_ref_doms_1 = 4;
107         ref->buffer_dom_name = 1;
108         ref->max_entries = 32;
109         ref->num_ref_doms_2 = 4;
110
111         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
112         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
113         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
114         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
115
116         if (dom_name != NULL)
117         {
118                 make_unistr(&(ref->uni_dom_name), dom_name);
119         }
120
121         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
122         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
123         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
124         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
125 }
126
127 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
128                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
129                                 char *dom_name, char *dom_sid,
130                                 char *other_sid1, char *other_sid2, char *other_sid3)
131 {
132         int i;
133
134         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
135                      other_sid1, other_sid2, other_sid3);
136
137         r_l->num_entries = num_entries;
138         r_l->undoc_buffer = 1;
139         r_l->num_entries2 = num_entries;
140
141         for (i = 0; i < num_entries; i++)
142         {
143                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
144         }
145
146         r_l->num_entries3 = num_entries;
147 }
148
149 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
150                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
151                                 char *dom_name, char *dom_sid,
152                                 char *other_sid1, char *other_sid2, char *other_sid3)
153 {
154         int i;
155
156         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
157                      other_sid1, other_sid2, other_sid3);
158
159         r_l->num_entries = num_entries;
160         r_l->undoc_buffer = 1;
161         r_l->num_entries2 = num_entries;
162
163         for (i = 0; i < num_entries; i++)
164         {
165                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
166         }
167
168         r_l->num_entries3 = num_entries;
169 }
170
171 static int lsa_reply_lookup_sids(char *q, char *base,
172                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
173                                 char *dom_name, char *dom_sid,
174                                 char *other_sid1, char *other_sid2, char *other_sid3)
175 {
176         LSA_R_LOOKUP_SIDS r_l;
177
178         /* set up the LSA Lookup SIDs response */
179         make_reply_lookup_sids(&r_l, num_entries, dom_sids,
180                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
181         r_l.status = 0x0;
182
183         /* store the response in the SMB stream */
184         q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0);
185
186         /* return length of SMB data stored */
187         return PTR_DIFF(q, base);
188 }
189
190 static int lsa_reply_lookup_rids(char *q, char *base,
191                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
192                                 char *dom_name, char *dom_sid,
193                                 char *other_sid1, char *other_sid2, char *other_sid3)
194 {
195         LSA_R_LOOKUP_RIDS r_l;
196
197         /* set up the LSA Lookup RIDs response */
198         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
199                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
200         r_l.status = 0x0;
201
202         /* store the response in the SMB stream */
203         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0);
204
205         /* return length of SMB data stored */
206         return PTR_DIFF(q, base);
207 }
208
209 static void api_lsa_open_policy( char *param, char *data,
210                              char **rdata, int *rdata_len )
211 {
212         /* we might actually want to decode the query, but it's not necessary */
213         /* lsa_io_q_open_policy(...); */
214
215         /* return a 20 byte policy handle */
216         *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata);
217 }
218
219 static void api_lsa_query_info( char *param, char *data,
220                                 char **rdata, int *rdata_len )
221 {
222         LSA_Q_QUERY_INFO q_i;
223         pstring dom_name;
224         pstring dom_sid;
225
226         /* grab the info class and policy handle */
227         lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0);
228
229         pstrcpy(dom_name, lp_workgroup());
230         pstrcpy(dom_sid , lp_domainsid());
231
232         /* construct reply.  return status is always 0x0 */
233         *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, 
234                                                                          dom_name, dom_sid);
235 }
236
237 static void api_lsa_lookup_sids( char *param, char *data,
238                                  char **rdata, int *rdata_len )
239 {
240         int i;
241         LSA_Q_LOOKUP_SIDS q_l;
242         pstring dom_name;
243         pstring dom_sid;
244         fstring dom_sids[MAX_LOOKUP_SIDS];
245
246         /* grab the info class and policy handle */
247         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0);
248
249         pstrcpy(dom_name, lp_workgroup());
250         pstrcpy(dom_sid , lp_domainsid());
251
252         /* convert received SIDs to strings, so we can do them. */
253         for (i = 0; i < q_l.num_entries; i++)
254         {
255                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
256         }
257
258         /* construct reply.  return status is always 0x0 */
259         *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata,
260                     q_l.num_entries, dom_sids, /* text-converted SIDs */
261                                 dom_name, dom_sid, /* domain name, domain SID */
262                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
263 }
264
265 static void api_lsa_lookup_names( char *param, char *data,
266                                   char **rdata, int *rdata_len )
267 {
268         int i;
269         LSA_Q_LOOKUP_RIDS q_l;
270         pstring dom_name;
271         pstring dom_sid;
272         uint32 dom_rids[MAX_LOOKUP_SIDS];
273
274         /* grab the info class and policy handle */
275         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0);
276
277         pstrcpy(dom_name, lp_workgroup());
278         pstrcpy(dom_sid , lp_domainsid());
279
280         /* convert received RIDs to strings, so we can do them. */
281         for (i = 0; i < q_l.num_entries; i++)
282         {
283                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
284                 dom_rids[i] = name_to_rid(user_name);
285         }
286
287         /* construct reply.  return status is always 0x0 */
288         *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata,
289                     q_l.num_entries, dom_rids, /* text-converted SIDs */
290                                 dom_name, dom_sid, /* domain name, domain SID */
291                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
292 }
293
294 BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
295                      int mdrcnt,int mprcnt,
296                      char **rdata,char **rparam,
297                      int *rdata_len,int *rparam_len)
298 {
299         uint16 opnum = SVAL(data,22);
300
301         int pkttype = CVAL(data, 2);
302         if (pkttype == 0x0b) /* RPC BIND */
303         {
304                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
305                 LsarpcTNP1(data,rdata,rdata_len);
306                 return True;
307         }
308
309         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
310         switch (opnum)
311         {
312                 case LSA_OPENPOLICY:
313                 {
314                         DEBUG(3,("LSA_OPENPOLICY\n"));
315                         api_lsa_open_policy(param, data, rdata, rdata_len);
316                         make_rpc_reply(data, *rdata, *rdata_len);
317                         break;
318                 }
319
320                 case LSA_QUERYINFOPOLICY:
321                 {
322                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
323
324                         api_lsa_query_info(param, data, rdata, rdata_len);
325                         make_rpc_reply(data, *rdata, *rdata_len);
326                         break;
327                 }
328
329                 case LSA_ENUMTRUSTDOM:
330                 {
331                         char *q = *rdata + 0x18;
332
333                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
334
335                         initrpcreply(data, *rdata);
336
337                         SIVAL(q, 0, 0); /* enumeration context */
338                         SIVAL(q, 0, 4); /* entries read */
339                         SIVAL(q, 0, 8); /* trust information */
340
341                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
342
343                         break;
344                 }
345
346                 case LSA_CLOSE:
347                 {
348                         char *q = *rdata + 0x18;
349
350                         DEBUG(3,("LSA_CLOSE\n"));
351
352                         initrpcreply(data, *rdata);
353
354                         SIVAL(q, 0, 0);
355                         SIVAL(q, 0, 4);
356                         SIVAL(q, 0, 8);
357                         SIVAL(q, 0, 12);
358                         SIVAL(q, 0, 16);
359
360                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
361
362                         break;
363                 }
364
365                 case LSA_OPENSECRET:
366                 {
367                         char *q = *rdata + 0x18;
368                         DEBUG(3,("LSA_OPENSECRET\n"));
369
370                         initrpcreply(data, *rdata);
371
372                         SIVAL(q, 0, 0);
373                         SIVAL(q, 0, 4);
374                         SIVAL(q, 0, 8);
375                         SIVAL(q, 0, 12);
376                         SIVAL(q, 0, 16);
377
378                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
379
380                         break;
381                 }
382
383                 case LSA_LOOKUPSIDS:
384                 {
385                         DEBUG(3,("LSA_OPENSECRET\n"));
386                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
387                         make_rpc_reply(data, *rdata, *rdata_len);
388                         break;
389                 }
390
391                 case LSA_LOOKUPNAMES:
392                 {
393                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
394                         api_lsa_lookup_names(param, data, rdata, rdata_len);
395                         make_rpc_reply(data, *rdata, *rdata_len);
396                         break;
397                 }
398
399                 default:
400                 {
401                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
402                         break;
403                 }
404         }
405         return True;
406 }
407
408 #endif /* NTDOMAIN */