added #ifdef NTDOMAIN. added call to api_ntLsarpc instead of api_Lsarpc
[sfrench/samba-autobuild/.git] / source3 / smbd / pipes.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 #define PIPE            "\\PIPE\\"
34 #define PIPELEN         strlen(PIPE)
35
36 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
37
38 /* look in server.c for some explanation of these variables */
39 extern int Protocol;
40 extern int DEBUGLEVEL;
41 extern int chain_fnum;
42 extern char magic_char;
43 extern connection_struct Connections[];
44 extern files_struct Files[];
45 extern BOOL case_sensitive;
46 extern pstring sesssetup_user;
47 extern int Client;
48 extern fstring myworkgroup;
49
50 /* this macro should always be used to extract an fnum (smb_fid) from
51 a packet to ensure chaining works correctly */
52 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
53
54 char * known_pipes [] =
55 {
56   "lsarpc",
57 #if NTDOMAIN
58   "NETLOGON",
59 #endif
60   NULL
61 };
62
63 /****************************************************************************
64   reply to an open and X on a named pipe
65
66   In fact what we do is to open a regular file with the same name in
67   /tmp. This can then be closed as normal. Reading and writing won't
68   make much sense, but will do *something*. The real reason for this
69   support is to be able to do transactions on them (well, on lsarpc
70   for domain login purposes...).
71
72   This code is basically stolen from reply_open_and_X with some
73   wrinkles to handle pipes.
74 ****************************************************************************/
75 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
76 {
77   pstring fname;
78   int cnum = SVAL(inbuf,smb_tid);
79   int fnum = -1;
80   int smb_mode = SVAL(inbuf,smb_vwv3);
81   int smb_attr = SVAL(inbuf,smb_vwv5);
82 #if 0
83   int open_flags = SVAL(inbuf,smb_vwv2);
84   int smb_sattr = SVAL(inbuf,smb_vwv4); 
85   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
86 #endif
87   int smb_ofun = SVAL(inbuf,smb_vwv8);
88   int unixmode;
89   int size=0,fmode=0,mtime=0,rmode=0;
90   struct stat sbuf;
91   int smb_action = 0;
92   int i;
93   BOOL bad_path = False;
94
95   /* XXXX we need to handle passed times, sattr and flags */
96   pstrcpy(fname,smb_buf(inbuf));
97
98   /* If the name doesn't start \PIPE\ then this is directed */
99   /* at a mailslot or something we really, really don't understand, */
100   /* not just something we really don't understand. */
101   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
102     return(ERROR(ERRSRV,ERRaccess));
103
104   DEBUG(4,("Opening pipe %s.\n", fname));
105
106   /* Strip \PIPE\ off the name. */
107   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
108
109   /* See if it is one we want to handle. */
110   for( i = 0; known_pipes[i] ; i++ )
111     if( strcmp(fname,known_pipes[i]) == 0 )
112       break;
113
114   if ( known_pipes[i] == NULL )
115     return(ERROR(ERRSRV,ERRaccess));
116
117   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
118   /* can be opened and add it in after the open. */
119   DEBUG(3,("Known pipe %s opening.\n",fname));
120   smb_attr &= ~aDIR;
121   Connections[cnum].read_only = 0;
122   smb_ofun |= 0x10;             /* Add Create it not exists flag */
123
124   unix_convert(fname,cnum,0,&bad_path);
125     
126   fnum = find_free_file();
127   if (fnum < 0)
128     return(ERROR(ERRSRV,ERRnofids));
129
130   if (!check_name(fname,cnum))
131     return(UNIXERROR(ERRDOS,ERRnoaccess));
132
133   unixmode = unix_mode(cnum,smb_attr);
134       
135   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
136                    0, &rmode,&smb_action);
137       
138   if (!Files[fnum].open)
139   {
140     /* Change the error code if bad_path was set. */
141     if((errno == ENOENT) && bad_path)
142     {
143       unix_ERR_class = ERRDOS;
144       unix_ERR_code = ERRbadpath;
145     }
146     return(UNIXERROR(ERRDOS,ERRnoaccess));
147   }
148
149   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
150     close_file(fnum);
151     return(ERROR(ERRDOS,ERRnoaccess));
152   }
153
154   size = sbuf.st_size;
155   fmode = dos_mode(cnum,fname,&sbuf);
156   mtime = sbuf.st_mtime;
157   if (fmode & aDIR) {
158     close_file(fnum);
159     return(ERROR(ERRDOS,ERRnoaccess));
160   }
161
162   /* Prepare the reply */
163   set_message(outbuf,15,0,True);
164
165   /* Put things back the way they were. */
166   Connections[cnum].read_only = 1;
167
168   /* Mark the opened file as an existing named pipe in message mode. */
169   SSVAL(outbuf,smb_vwv9,2);
170   SSVAL(outbuf,smb_vwv10,0xc700);
171   if (rmode == 2)
172   {
173     DEBUG(4,("Resetting open result to open from create.\n"));
174     rmode = 1;
175   }
176
177   SSVAL(outbuf,smb_vwv2,fnum);
178   SSVAL(outbuf,smb_vwv3,fmode);
179   put_dos_date3(outbuf,smb_vwv4,mtime);
180   SIVAL(outbuf,smb_vwv6,size);
181   SSVAL(outbuf,smb_vwv8,rmode);
182   SSVAL(outbuf,smb_vwv11,smb_action);
183
184   chain_fnum = fnum;
185
186   DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
187            fname, fnum, Files[fnum].name));
188   
189   return chain_reply(inbuf,outbuf,length,bufsize);
190 }
191
192
193 /****************************************************************************
194  api_LsarpcSNPHS
195
196  SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
197  so just blithely return True. This is really only for NT domain stuff,
198  we we're only handling that - don't assume Samba now does complete
199  named pipe handling.
200 ****************************************************************************/
201 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
202                      int mdrcnt,int mprcnt,
203                      char **rdata,char **rparam,
204                      int *rdata_len,int *rparam_len)
205 {
206   uint16 id;
207
208   id = param[0] + (param[1] << 8);
209   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
210   return(True);
211 }
212
213
214 /****************************************************************************
215  api_LsarpcTNP
216
217  TransactNamedPipe on \PIPE\lsarpc.
218 ****************************************************************************/
219 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
220 {
221   uint32 dword1, dword2;
222   char pname[] = "\\PIPE\\lsass";
223
224   /* All kinds of mysterious numbers here */
225   *rdata_len = 68;
226   *rdata = REALLOC(*rdata,*rdata_len);
227
228   dword1 = IVAL(data,0xC);
229   dword2 = IVAL(data,0x10);
230
231   SIVAL(*rdata,0,0xc0005);
232   SIVAL(*rdata,4,0x10);
233   SIVAL(*rdata,8,0x44);
234   SIVAL(*rdata,0xC,dword1);
235   
236   SIVAL(*rdata,0x10,dword2);
237   SIVAL(*rdata,0x14,0x15);
238   SSVAL(*rdata,0x18,sizeof(pname));
239   strcpy(*rdata + 0x1a,pname);
240   SIVAL(*rdata,0x28,1);
241   memcpy(*rdata + 0x30, data + 0x34, 0x14);
242 }
243
244 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
245 {
246   uint32 dword1;
247
248   /* All kinds of mysterious numbers here */
249   *rdata_len = 48;
250   *rdata = REALLOC(*rdata,*rdata_len);
251
252   dword1 = IVAL(data,0xC);
253
254   SIVAL(*rdata,0,0x03020005);
255   SIVAL(*rdata,4,0x10);
256   SIVAL(*rdata,8,0x30);
257   SIVAL(*rdata,0xC,dword1);
258   SIVAL(*rdata,0x10,0x18);
259   SIVAL(*rdata,0x1c,0x44332211);
260   SIVAL(*rdata,0x20,0x88776655);
261   SIVAL(*rdata,0x24,0xCCBBAA99);
262   SIVAL(*rdata,0x28,0x11FFEEDD);
263 }
264
265 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
266 {
267   uint32 dword1;
268   uint16 word1;
269   char * workgroup = myworkgroup;
270   int wglen = strlen(workgroup);
271   int i;
272
273   /* All kinds of mysterious numbers here */
274   *rdata_len = 90 + 2 * wglen;
275   *rdata = REALLOC(*rdata,*rdata_len);
276
277   dword1 = IVAL(data,0xC);
278   word1 = SVAL(data,0x2C);
279
280   SIVAL(*rdata,0,0x03020005);
281   SIVAL(*rdata,4,0x10);
282   SIVAL(*rdata,8,0x60);
283   SIVAL(*rdata,0xC,dword1);
284   SIVAL(*rdata,0x10,0x48);
285   SSVAL(*rdata,0x18,0x5988);    /* This changes */
286   SSVAL(*rdata,0x1A,0x15);
287   SSVAL(*rdata,0x1C,word1);
288   SSVAL(*rdata,0x20,6);
289   SSVAL(*rdata,0x22,8);
290   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
291   SSVAL(*rdata,0x26,0x15);
292   SSVAL(*rdata,0x28,0x4D48);    /* And this */
293   SSVAL(*rdata,0x2A,0x15);
294   SIVAL(*rdata,0x2C,4);
295   SIVAL(*rdata,0x34,wglen);
296   for ( i = 0 ; i < wglen ; i++ )
297     (*rdata)[0x38 + i * 2] = workgroup[i];
298    
299   /* Now fill in the rest */
300   i = 0x38 + wglen * 2;
301   SSVAL(*rdata,i,0x648);
302   SIVAL(*rdata,i+2,4);
303   SIVAL(*rdata,i+6,0x401);
304   SSVAL(*rdata,i+0xC,0x500);
305   SIVAL(*rdata,i+0xE,0x15);
306   SIVAL(*rdata,i+0x12,0x2372FE1);
307   SIVAL(*rdata,i+0x16,0x7E831BEF);
308   SIVAL(*rdata,i+0x1A,0x4B454B2);
309 }
310
311 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
312 {
313   uint32 dword1;
314
315   /* All kinds of mysterious numbers here */
316   *rdata_len = 48;
317   *rdata = REALLOC(*rdata,*rdata_len);
318
319   dword1 = IVAL(data,0xC);
320
321   SIVAL(*rdata,0,0x03020005);
322   SIVAL(*rdata,4,0x10);
323   SIVAL(*rdata,8,0x30);
324   SIVAL(*rdata,0xC,dword1);
325   SIVAL(*rdata,0x10,0x18);
326 }
327
328
329 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
330                      int mdrcnt,int mprcnt,
331                      char **rdata,char **rparam,
332                      int *rdata_len,int *rparam_len)
333 {
334   uint32 id,id2;
335
336   id = IVAL(data,0);
337
338   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
339   switch (id)
340   {
341     case 0xb0005:
342       LsarpcTNP1(data,rdata,rdata_len);
343       break;
344
345     case 0x03000005:
346       id2 = IVAL(data,8);
347       DEBUG(4,("\t- Suboperation %lx\n",id2));
348       switch (id2 & 0xF)
349       {
350         case 8:
351           LsarpcTNP2(data,rdata,rdata_len);
352           break;
353
354         case 0xC:
355           LsarpcTNP4(data,rdata,rdata_len);
356           break;
357
358         case 0xE:
359           LsarpcTNP3(data,rdata,rdata_len);
360           break;
361       }
362       break;
363   }
364   return(True);
365 }
366
367
368 #ifdef NTDOMAIN
369 /*
370    PAXX: Someone fix above.
371    The above API is indexing RPC calls based on RPC flags and 
372    fragment length. I've decided to do it based on operation number :-)
373 */
374
375 /* this function is due to be replaced */
376 static void initrpcreply(char *inbuf, char *q)
377 {
378         uint32 callid;
379
380         SCVAL(q, 0, 5); q++; /* RPC version 5 */
381         SCVAL(q, 0, 0); q++; /* minor version 0 */
382         SCVAL(q, 0, 2); q++; /* RPC response packet */
383         SCVAL(q, 0, 3); q++; /* first frag + last frag */
384         RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */
385         RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */
386         SSVAL(q, 0, 0); q += 2; /* authentication length */
387         callid = RIVAL(inbuf, 12);
388         RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */
389         SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */
390         SSVAL(q, 0, 0); q += 2; /* presentation context identifier */
391         SCVAL(q, 0, 0); q++; /* cancel count */
392         SCVAL(q, 0, 0); q++; /* reserved */
393 }
394
395 /* this function is due to be replaced */
396 static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
397 {
398         SSVAL(q, 8, datalen + 4);
399         SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
400         SIVAL(q, datalen, rtnval);
401         *rlen = datalen + 4;
402         { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); }
403 }
404
405 /* RID username mapping function.  just for fun, it maps to the unix uid */
406 static uint32 name_to_rid(char *user_name)
407 {
408     struct passwd *pw = Get_Pwnam(user_name, False);
409     if (!pw)
410         {
411       DEBUG(1,("Username %s is invalid on this system\n", user_name));
412       return (uint32)(-1);
413     }
414
415     return (uint32)(pw->pw_uid);
416 }
417
418
419 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
420 char *dom_sid_to_string(DOM_SID *sid)
421 {
422   static pstring sidstr;
423   char subauth[16];
424   int i;
425   uint32 ia = (sid->id_auth[0]) +
426               (sid->id_auth[1] << 8 ) +
427               (sid->id_auth[2] << 16) +
428               (sid->id_auth[3] << 24);
429
430   sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
431
432   for (i = 0; i < sid->num_auths; i++)
433   {
434     sprintf(subauth, "-%d", sid->sub_auths[i]);
435     strcat(sidstr, subauth);
436   }
437
438   DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
439   return sidstr;
440 }
441
442 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
443 /* identauth >= 2^32 can be detected because it will be specified in hex */
444 static void make_dom_sid(DOM_SID *sid, char *domsid)
445 {
446         int identauth;
447         char *p;
448
449         DEBUG(4,("netlogon domain SID: %s\n", domsid));
450
451         /* assume, but should check, that domsid starts "S-" */
452         p = strtok(domsid+2,"-");
453         sid->sid_no = atoi(p);
454
455         /* identauth in decimal should be <  2^32 */
456         /* identauth in hex     should be >= 2^32 */
457         identauth = atoi(strtok(0,"-"));
458
459         DEBUG(4,("netlogon rev %d\n", sid->sid_no));
460         DEBUG(4,("netlogon %s ia %d\n", p, identauth));
461
462         sid->id_auth[0] = 0;
463         sid->id_auth[1] = 0;
464         sid->id_auth[2] = (identauth & 0xff000000) >> 24;
465         sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
466         sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
467         sid->id_auth[5] = (identauth & 0x000000ff);
468
469         sid->num_auths = 0;
470
471         while ((p = strtok(0, "-")) != NULL)
472         {
473                 sid->sub_auths[sid->num_auths++] = atoi(p);
474         }
475 }
476
477 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
478 {
479         if (hdr == NULL) return;
480
481         hdr->major        = 5;               /* RPC version 5 */
482         hdr->minor        = 0;               /* minor version 0 */
483         hdr->pkt_type     = 2;               /* RPC response packet */
484         hdr->frag         = 3;               /* first frag + last frag */
485         hdr->pack_type    = 1;               /* packed data representation */
486         hdr->frag_len     = data_len;        /* fragment length, fill in later */
487         hdr->auth_len     = 0;               /* authentication length */
488         hdr->call_id      = call_id;         /* call identifier - match incoming RPC */
489         hdr->alloc_hint   = data_len - 0x18; /* allocation hint (no idea) */
490         hdr->context_id   = 0;               /* presentation context identifier */
491         hdr->cancel_count = 0;               /* cancel count */
492         hdr->reserved     = 0;               /* reserved */
493 }
494
495 static void make_rpc_reply(char *inbuf, char *q, int data_len)
496 {
497         uint32 callid = RIVAL(inbuf, 12);
498         RPC_HDR hdr;
499
500         create_rpc_reply(&hdr, callid, data_len);
501         smb_io_rpc_hdr(False, &hdr, q, q, 4);
502 }
503
504 static int lsa_reply_open_policy(char *q, char *base)
505 {
506         char *start = q;
507         LSA_R_OPEN_POL r_o;
508
509         /* set up the LSA QUERY INFO response */
510         bzero(&(r_o.pol.data), POL_HND_SIZE);
511         r_o.status = 0x0;
512
513         /* store the response in the SMB stream */
514         q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
515
516         /* return length of SMB data stored */
517         return q - start; 
518 }
519
520 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
521 {
522         hdr->uni_max_len = max_len;
523         hdr->uni_str_len = len;
524         hdr->undoc       = terminate;
525 }
526
527 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
528 {
529         make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
530         hdr->undoc_buffer = len > 0 ? 1 : 0;
531 }
532
533 static void make_unistr(UNISTR *str, char *buf)
534 {
535         /* store the string (null-terminated copy) */
536         PutUniCode((char *)(str->buffer), buf);
537 }
538
539 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
540 {
541         /* set up string lengths. add one if string is not null-terminated */
542         str->uni_max_len = len + (terminate != 0 ? 1 : 0);
543         str->undoc       = 0;
544         str->uni_str_len = len;
545
546         /* store the string (null-terminated copy) */
547         PutUniCode((char *)str->buffer, buf);
548
549         /* overwrite the last character: some strings are terminated with 4 not 0 */
550         str->buffer[len] = (uint16)terminate;
551 }
552
553 static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
554 {
555         rid2->type    = 0x5;
556         rid2->undoc   = 0x5;
557         rid2->rid     = rid;
558         rid2->rid_idx = 0;
559 }
560
561 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
562 {
563         int len_sid_str = strlen(sid_str);
564
565         sid2->type = 0x5;
566         sid2->undoc = 0;
567         make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
568         make_unistr  (&(sid2->str), sid_str);
569 }
570
571 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
572 {
573         int domlen = strlen(dom_name);
574
575         d_q->uni_dom_max_len = domlen * 2;
576         d_q->padding = 0;
577         d_q->uni_dom_str_len = domlen * 2;
578
579         d_q->buffer_dom_name = 0; /* domain buffer pointer */
580         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
581
582         /* NOT null-terminated: 4-terminated instead! */
583         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
584
585         make_dom_sid(&(d_q->dom_sid), dom_sid);
586 }
587
588 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
589                                 char *dom_name, char *dom_sid)
590 {
591         char *start = q;
592         LSA_R_QUERY_INFO r_q;
593
594         /* set up the LSA QUERY INFO response */
595
596         r_q.undoc_buffer = 1; /* not null */
597         r_q.info_class = q_q->info_class;
598
599         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
600
601         r_q.status = 0x0;
602
603         /* store the response in the SMB stream */
604         q = lsa_io_r_query(False, &r_q, q, base, 4);
605
606         /* return length of SMB data stored */
607         return q - start; 
608 }
609
610 /* pretty much hard-coded choice of "other" sids, unfortunately... */
611 static void make_dom_ref(DOM_R_REF *ref,
612                                 char *dom_name, char *dom_sid,
613                                 char *other_sid1, char *other_sid2, char *other_sid3)
614 {
615         int len_dom_name   = strlen(dom_name);
616         int len_other_sid1 = strlen(other_sid1);
617         int len_other_sid2 = strlen(other_sid2);
618         int len_other_sid3 = strlen(other_sid3);
619
620         ref->undoc_buffer = 1;
621         ref->num_ref_doms_1 = 4;
622         ref->buffer_dom_name = 1;
623         ref->max_entries = 32;
624         ref->num_ref_doms_2 = 4;
625
626         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
627         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
628         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
629         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
630
631         if (dom_name != NULL)
632         {
633                 make_unistr(&(ref->uni_dom_name), dom_name);
634         }
635
636         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
637         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
638         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
639         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
640 }
641
642 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
643                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
644                                 char *dom_name, char *dom_sid,
645                                 char *other_sid1, char *other_sid2, char *other_sid3)
646 {
647         int i;
648
649         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
650                      other_sid1, other_sid2, other_sid3);
651
652         r_l->num_entries = num_entries;
653         r_l->undoc_buffer = 1;
654         r_l->num_entries2 = num_entries;
655
656         for (i = 0; i < num_entries; i++)
657         {
658                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
659         }
660
661         r_l->num_entries3 = num_entries;
662 }
663
664 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
665                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
666                                 char *dom_name, char *dom_sid,
667                                 char *other_sid1, char *other_sid2, char *other_sid3)
668 {
669         int i;
670
671         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
672                      other_sid1, other_sid2, other_sid3);
673
674         r_l->num_entries = num_entries;
675         r_l->undoc_buffer = 1;
676         r_l->num_entries2 = num_entries;
677
678         for (i = 0; i < num_entries; i++)
679         {
680                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
681         }
682
683         r_l->num_entries3 = num_entries;
684 }
685
686 static int lsa_reply_lookup_sids(char *q, char *base,
687                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
688                                 char *dom_name, char *dom_sid,
689                                 char *other_sid1, char *other_sid2, char *other_sid3)
690 {
691         char *start = q;
692         LSA_R_LOOKUP_SIDS r_l;
693
694         /* set up the LSA Lookup SIDs response */
695         make_reply_lookup_sids(&r_l, num_entries, dom_sids,
696                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
697         r_l.status = 0x0;
698
699         /* store the response in the SMB stream */
700         q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4);
701
702         /* return length of SMB data stored */
703         return q - start; 
704 }
705
706 static int lsa_reply_lookup_rids(char *q, char *base,
707                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
708                                 char *dom_name, char *dom_sid,
709                                 char *other_sid1, char *other_sid2, char *other_sid3)
710 {
711         char *start = q;
712         LSA_R_LOOKUP_RIDS r_l;
713
714         /* set up the LSA Lookup RIDs response */
715         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
716                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
717         r_l.status = 0x0;
718
719         /* store the response in the SMB stream */
720         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4);
721
722         /* return length of SMB data stored */
723         return q - start; 
724 }
725
726 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
727 {
728         memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
729         r_c->status = status;
730 }
731
732 #if 0
733         char chal[8];
734         /* PAXX: set these to random values */
735         for (int i = 0; i < 8; i+++)
736         {
737                 chal[i] = 0xA5;
738         }
739 #endif
740
741 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
742                                         char chal[8])
743 {
744         char *start = q;
745         LSA_R_REQ_CHAL r_c;
746
747         /* set up the LSA REQUEST CHALLENGE response */
748
749         make_lsa_r_req_chal(&r_c, chal, 0);
750
751         /* store the response in the SMB stream */
752         q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
753
754         /* return length of SMB data stored */
755         return q - start; 
756 }
757
758 static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
759 {
760         memcpy(cred->data, resp_cred, sizeof(cred->data));
761 }
762
763 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
764                               char resp_cred[8], NEG_FLAGS *flgs, int status)
765 {
766         make_lsa_chal(&(r_a->srv_chal), resp_cred);
767         memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
768         r_a->status = status;
769 }
770
771 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
772                                 char resp_cred[8], int status)
773 {
774         char *start = q;
775         LSA_R_AUTH_2 r_a;
776
777         /* set up the LSA AUTH 2 response */
778
779         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
780
781         /* store the response in the SMB stream */
782         q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
783
784         /* return length of SMB data stored */
785         return q - start; 
786 }
787
788 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
789 {
790         make_lsa_chal(&(cred->challenge), srv_chal);
791         cred->timestamp = srv_time;
792 }
793         
794
795 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
796                               char srv_chal[8], UTIME srv_time, int status)
797 {
798         make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
799         r_a->status = status;
800 }
801
802 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
803                                 char srv_cred[8], UTIME srv_time,
804                                 int status)
805 {
806         char *start = q;
807         LSA_R_SRV_PWSET r_s;
808
809         /* set up the LSA Server Password Set response */
810         make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
811
812         /* store the response in the SMB stream */
813         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
814
815         /* return length of SMB data stored */
816         return q - start; 
817 }
818
819 static void make_lsa_user_info(LSA_USER_INFO *usr,
820
821         NTTIME *logon_time,
822         NTTIME *logoff_time,
823         NTTIME *kickoff_time,
824         NTTIME *pass_last_set_time,
825         NTTIME *pass_can_change_time,
826         NTTIME *pass_must_change_time,
827
828         char *user_name,
829         char *full_name,
830         char *logon_script,
831         char *profile_path,
832         char *home_dir,
833         char *dir_drive,
834
835         uint16 logon_count,
836         uint16 bad_pw_count,
837
838         uint32 user_id,
839         uint32 group_id,
840         uint32 num_groups,
841         DOM_GID *gids,
842         uint32 user_flgs,
843
844         char sess_key[16],
845
846         char *logon_srv,
847         char *logon_dom,
848
849         char *dom_sid,
850         char *other_sids) /* space-delimited set of SIDs */ 
851 {
852         /* only cope with one "other" sid, right now. */
853         /* need to count the number of space-delimited sids */
854         int i;
855         int num_other_sids = other_sids != NULL ? 1 : 0;
856
857         int len_user_name    = strlen(user_name   );
858         int len_full_name    = strlen(full_name   );
859         int len_logon_script = strlen(logon_script);
860         int len_profile_path = strlen(profile_path);
861         int len_home_dir     = strlen(home_dir    );
862         int len_dir_drive    = strlen(dir_drive   );
863
864         int len_logon_srv    = strlen(logon_srv);
865         int len_logon_dom    = strlen(logon_dom);
866
867         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
868
869         usr->logon_time            = *logon_time;
870         usr->logoff_time           = *logoff_time;
871         usr->kickoff_time          = *kickoff_time;
872         usr->pass_last_set_time    = *pass_last_set_time;
873         usr->pass_can_change_time  = *pass_can_change_time;
874         usr->pass_must_change_time = *pass_must_change_time;
875
876         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
877         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
878         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
879         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
880         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
881         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
882
883         usr->logon_count = logon_count;
884         usr->bad_pw_count = bad_pw_count;
885
886         usr->user_id = user_id;
887         usr->group_id = group_id;
888         usr->num_groups = num_groups;
889         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
890         usr->user_flgs = user_flgs;
891
892         if (sess_key != NULL)
893         {
894                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
895         }
896         else
897         {
898                 bzero(usr->sess_key, sizeof(usr->sess_key));
899         }
900
901         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
902         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
903
904         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
905
906         bzero(usr->padding, sizeof(usr->padding));
907
908         usr->num_other_sids = num_other_sids;
909         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
910         
911         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
912         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
913         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
914         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
915         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
916         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
917
918         usr->num_groups2 = num_groups;
919         for (i = 0; i < num_groups; i++)
920         {
921                 usr->gids[i] = gids[i];
922         }
923
924         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
925         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
926
927         make_dom_sid(&(usr->dom_sid), dom_sid);
928         make_dom_sid(&(usr->other_sids[0]), other_sids);
929 }
930
931
932 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
933                                 char srv_cred[8], UTIME srv_time,
934                                 LSA_USER_INFO *user_info)
935 {
936         char *start = q;
937         LSA_R_SAM_LOGON r_s;
938
939         /* XXXX maybe we want to say 'no', reject the client's credentials */
940         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
941         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
942
943         /* store the user information, if there is any. */
944         r_s.user = user_info;
945         r_s.buffer_user = user_info != NULL ? 1 : 0;
946         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
947
948         /* store the response in the SMB stream */
949         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
950
951         /* return length of SMB data stored */
952         return q - start; 
953 }
954
955
956 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
957                                 char srv_cred[8], UTIME srv_time,
958                                 uint32 status)
959 {
960         char *start = q;
961         LSA_R_SAM_LOGOFF r_s;
962
963         /* XXXX maybe we want to say 'no', reject the client's credentials */
964         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
965         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
966
967         r_s.status = status;
968
969         /* store the response in the SMB stream */
970         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
971
972         /* return length of SMB data stored */
973         return q - start; 
974 }
975
976
977 static void api_lsa_open_policy( char *param, char *data,
978                              char **rdata, int *rdata_len )
979 {
980         int reply_len;
981
982         /* we might actually want to decode the query, but it's not necessary */
983         /* lsa_io_q_open_policy(...); */
984
985         /* return a 20 byte policy handle */
986         reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18);
987
988         /* construct header, now that we know the reply length */
989         make_rpc_reply(data, *rdata, reply_len);
990         *rdata_len = reply_len + 0x18;
991 }
992
993 static void api_lsa_query_info( char *param, char *data,
994                                 char **rdata, int *rdata_len )
995 {
996         int reply_len;
997
998         LSA_Q_QUERY_INFO q_i;
999         pstring dom_name;
1000         pstring dom_sid;
1001
1002         /* grab the info class and policy handle */
1003         lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4);
1004
1005         pstrcpy(dom_name, lp_workgroup());
1006         pstrcpy(dom_sid , lp_domainsid());
1007
1008         /* construct reply.  return status is always 0x0 */
1009         reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, 
1010                                                                          dom_name, dom_sid);
1011
1012         /* construct header, now that we know the reply length */
1013         make_rpc_reply(data, *rdata, reply_len);
1014         *rdata_len = reply_len + 0x18;
1015 }
1016
1017 static void api_lsa_lookup_sids( char *param, char *data,
1018                                  char **rdata, int *rdata_len )
1019 {
1020         int reply_len;
1021
1022         int i;
1023         LSA_Q_LOOKUP_SIDS q_l;
1024         pstring dom_name;
1025         pstring dom_sid;
1026         fstring dom_sids[MAX_LOOKUP_SIDS];
1027
1028         /* grab the info class and policy handle */
1029         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4);
1030
1031         pstrcpy(dom_name, lp_workgroup());
1032         pstrcpy(dom_sid , lp_domainsid());
1033
1034         /* convert received SIDs to strings, so we can do them. */
1035         for (i = 0; i < q_l.num_entries; i++)
1036         {
1037                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1038         }
1039
1040         /* construct reply.  return status is always 0x0 */
1041         reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18,
1042                     q_l.num_entries, dom_sids, /* text-converted SIDs */
1043                                 dom_name, dom_sid, /* domain name, domain SID */
1044                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1045
1046         /* construct header, now that we know the reply length */
1047         make_rpc_reply(data, *rdata, reply_len);
1048         *rdata_len = reply_len + 0x18;
1049 }
1050
1051 static void api_lsa_lookup_names( char *param, char *data,
1052                                   char **rdata, int *rdata_len )
1053 {
1054         int reply_len;
1055
1056         int i;
1057         LSA_Q_LOOKUP_RIDS q_l;
1058         pstring dom_name;
1059         pstring dom_sid;
1060         uint32 dom_rids[MAX_LOOKUP_SIDS];
1061
1062         /* grab the info class and policy handle */
1063         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4);
1064
1065         pstrcpy(dom_name, lp_workgroup());
1066         pstrcpy(dom_sid , lp_domainsid());
1067
1068         /* convert received RIDs to strings, so we can do them. */
1069         for (i = 0; i < q_l.num_entries; i++)
1070         {
1071                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1072                 dom_rids[i] = name_to_rid(user_name);
1073         }
1074
1075         /* construct reply.  return status is always 0x0 */
1076         reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18,
1077                     q_l.num_entries, dom_rids, /* text-converted SIDs */
1078                                 dom_name, dom_sid, /* domain name, domain SID */
1079                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1080
1081         /* construct header, now that we know the reply length */
1082         make_rpc_reply(data, *rdata, reply_len);
1083         *rdata_len = reply_len + 0x18;
1084 }
1085
1086 BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
1087                      int mdrcnt,int mprcnt,
1088                      char **rdata,char **rparam,
1089                      int *rdata_len,int *rparam_len)
1090 {
1091         uint16 opnum = SVAL(data,22);
1092
1093         int pkttype = CVAL(data, 2);
1094         if (pkttype == 0x0b) /* RPC BIND */
1095         {
1096                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1097                 LsarpcTNP1(data,rdata,rdata_len);
1098                 return True;
1099         }
1100
1101         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1102         switch (opnum)
1103         {
1104                 case LSA_OPENPOLICY:
1105                 {
1106                         DEBUG(3,("LSA_OPENPOLICY\n"));
1107                         api_lsa_open_policy(param, data, rdata, rdata_len);
1108                         break;
1109                 }
1110
1111                 case LSA_QUERYINFOPOLICY:
1112                 {
1113                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
1114
1115                         api_lsa_query_info(param, data, rdata, rdata_len);
1116                         break;
1117                 }
1118
1119                 case LSA_ENUMTRUSTDOM:
1120                 {
1121                         char *q = *rdata + 0x18;
1122
1123                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
1124
1125                         initrpcreply(data, *rdata);
1126
1127                         SIVAL(q, 0, 0); /* enumeration context */
1128                         SIVAL(q, 0, 4); /* entries read */
1129                         SIVAL(q, 0, 8); /* trust information */
1130
1131                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1132
1133                         break;
1134                 }
1135
1136                 case LSA_CLOSE:
1137                 {
1138                         char *q = *rdata + 0x18;
1139
1140                         DEBUG(3,("LSA_CLOSE\n"));
1141
1142                         initrpcreply(data, *rdata);
1143
1144                         SIVAL(q, 0, 0);
1145                         SIVAL(q, 0, 4);
1146                         SIVAL(q, 0, 8);
1147                         SIVAL(q, 0, 12);
1148                         SIVAL(q, 0, 16);
1149
1150                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1151
1152                         break;
1153                 }
1154
1155                 case LSA_OPENSECRET:
1156                 {
1157                         char *q = *rdata + 0x18;
1158                         DEBUG(3,("LSA_OPENSECRET\n"));
1159
1160                         initrpcreply(data, *rdata);
1161
1162                         SIVAL(q, 0, 0);
1163                         SIVAL(q, 0, 4);
1164                         SIVAL(q, 0, 8);
1165                         SIVAL(q, 0, 12);
1166                         SIVAL(q, 0, 16);
1167
1168                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1169
1170                         break;
1171                 }
1172
1173                 case LSA_LOOKUPSIDS:
1174                 {
1175                         DEBUG(3,("LSA_OPENSECRET\n"));
1176                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
1177                         break;
1178                 }
1179
1180                 case LSA_LOOKUPNAMES:
1181                 {
1182                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
1183                         api_lsa_lookup_names(param, data, rdata, rdata_len);
1184                         break;
1185                 }
1186
1187                 default:
1188                 {
1189                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1190                         break;
1191                 }
1192         }
1193         return True;
1194 }
1195
1196 #endif /* NTDOMAIN */