general sorting out, from crashes generated by do_lsa_req_chal() in client.c
[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 = 4; 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_domain_sid());
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_domain_sid());
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         uint32 dummy_g_rid;
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_domain_sid());
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                 if (!name_to_rid(user_name, &dom_rids[i], &dummy_g_rid))
285                 {
286                         /* WHOOPS!  we should really do something about this... */
287                         dom_rids[i] = 0;
288                 }
289         }
290
291         /* construct reply.  return status is always 0x0 */
292         *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata,
293                     q_l.num_entries, dom_rids, /* text-converted SIDs */
294                                 dom_name, dom_sid, /* domain name, domain SID */
295                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
296 }
297
298 BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
299                      int mdrcnt,int mprcnt,
300                      char **rdata,char **rparam,
301                      int *rdata_len,int *rparam_len)
302 {
303         int    pkttype;
304         uint32 call_id;
305         uint16 opnum;
306
307         if (data == NULL)
308         {
309                 DEBUG(2, ("api_ntLsarpcTNP: NULL data parameter\n"));
310                 return False;
311         }
312
313         /* really should decode these using an RPC_HDR structure */
314         pkttype = CVAL(data,  2);
315         call_id = CVAL(data, 12);
316         opnum   = SVAL(data, 22);
317
318         if (pkttype == RPC_BIND) /* RPC BIND */
319         {
320                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
321                 LsarpcTNP1(data,rdata,rdata_len);
322                 return True;
323         }
324
325         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
326         switch (opnum)
327         {
328                 case LSA_OPENPOLICY:
329                 {
330                         DEBUG(3,("LSA_OPENPOLICY\n"));
331                         api_lsa_open_policy(param, data, rdata, rdata_len);
332                         create_rpc_reply(call_id, *rdata, *rdata_len);
333                         break;
334                 }
335
336                 case LSA_QUERYINFOPOLICY:
337                 {
338                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
339
340                         api_lsa_query_info(param, data, rdata, rdata_len);
341                         create_rpc_reply(call_id, *rdata, *rdata_len);
342                         break;
343                 }
344
345                 case LSA_ENUMTRUSTDOM:
346                 {
347                         char *q = *rdata + 0x18;
348
349                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
350
351                         initrpcreply(data, *rdata);
352
353                         SIVAL(q, 0, 0); /* enumeration context */
354                         SIVAL(q, 0, 4); /* entries read */
355                         SIVAL(q, 0, 8); /* trust information */
356
357                         q += 12;
358
359                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
360
361                         break;
362                 }
363
364                 case LSA_CLOSE:
365                 {
366                         char *q;
367
368                         DEBUG(3,("LSA_CLOSE\n"));
369
370                         initrpcreply(data, *rdata);
371
372                         q = *rdata + 0x18;
373
374                         SIVAL(q, 0, 0); q += 4;
375                         SIVAL(q, 0, 0); q += 4;
376                         SIVAL(q, 0, 0); q += 4;
377                         SIVAL(q, 0, 0); q += 4;
378                         SIVAL(q, 0, 0); q += 4;
379
380                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
381
382                         break;
383                 }
384
385                 case LSA_OPENSECRET:
386                 {
387                         char *q = *rdata + 0x18;
388                         DEBUG(3,("LSA_OPENSECRET\n"));
389
390                         initrpcreply(data, *rdata);
391
392                         SIVAL(q, 0, 0);
393                         SIVAL(q, 0, 4);
394                         SIVAL(q, 0, 8);
395                         SIVAL(q, 0, 12);
396                         SIVAL(q, 0, 16);
397
398                         q += 20;
399
400                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
401
402                         break;
403                 }
404
405                 case LSA_LOOKUPSIDS:
406                 {
407                         DEBUG(3,("LSA_OPENSECRET\n"));
408                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
409                         create_rpc_reply(call_id, *rdata, *rdata_len);
410                         break;
411                 }
412
413                 case LSA_LOOKUPNAMES:
414                 {
415                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
416                         api_lsa_lookup_names(param, data, rdata, rdata_len);
417                         create_rpc_reply(call_id, *rdata, *rdata_len);
418                         break;
419                 }
420
421                 default:
422                 {
423                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
424                         break;
425                 }
426         }
427         return True;
428 }
429
430 #endif /* NTDOMAIN */