ipc.c:
[kai/samba.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    = 0x10;            /* 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 int 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         return smb_io_rpc_hdr(False, &hdr, q, q, 4) - q;
502 }
503
504 static int lsa_reply_open_policy(char *q, char *base)
505 {
506         int i;
507         char *start = q;
508         LSA_R_OPEN_POL r_o;
509
510         static char handle[20] =
511         { 0x00, 0x00, 0x00, 0x00,
512       0x2f, 0x79, 0x0a, 0x81,
513       0xd5, 0x17, 0xd1, 0x11,
514       0x80, 0xaf, 0x96, 0xcd,
515       0x50, 0xf8, 0xbc, 0x6c
516     };
517         /* set up the LSA QUERY INFO response */
518         /* bzero(&(r_o.pol.data), POL_HND_SIZE); */
519         for (i = 0; i < POL_HND_SIZE; i++)
520         {
521                 r_o.pol.data[i] = handle[i];
522         }
523         r_o.status = 0x0;
524
525         /* store the response in the SMB stream */
526         q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0);
527
528         /* return length of SMB data stored */
529         return q - start; 
530 }
531
532 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
533 {
534         hdr->uni_max_len = max_len;
535         hdr->uni_str_len = len;
536         hdr->undoc       = terminate;
537 }
538
539 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
540 {
541         make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
542         hdr->undoc_buffer = len > 0 ? 1 : 0;
543 }
544
545 static void make_unistr(UNISTR *str, char *buf)
546 {
547         /* store the string (null-terminated copy) */
548         PutUniCode((char *)(str->buffer), buf);
549 }
550
551 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
552 {
553         /* set up string lengths. add one if string is not null-terminated */
554         str->uni_max_len = len + (terminate != 0 ? 1 : 0);
555         str->undoc       = 0;
556         str->uni_str_len = len;
557
558         /* store the string (null-terminated copy) */
559         PutUniCode((char *)str->buffer, buf);
560
561         /* overwrite the last character: some strings are terminated with 4 not 0 */
562         str->buffer[len] = (uint16)terminate;
563 }
564
565 static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
566 {
567         rid2->type    = 0x5;
568         rid2->undoc   = 0x5;
569         rid2->rid     = rid;
570         rid2->rid_idx = 0;
571 }
572
573 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
574 {
575         int len_sid_str = strlen(sid_str);
576
577         sid2->type = 0x5;
578         sid2->undoc = 0;
579         make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
580         make_unistr  (&(sid2->str), sid_str);
581 }
582
583 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
584 {
585         int domlen = strlen(dom_name);
586
587         d_q->uni_dom_max_len = domlen * 2;
588         d_q->padding = 0;
589         d_q->uni_dom_str_len = domlen * 2;
590
591         d_q->buffer_dom_name = 0; /* domain buffer pointer */
592         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
593
594         /* NOT null-terminated: 4-terminated instead! */
595         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
596
597         make_dom_sid(&(d_q->dom_sid), dom_sid);
598 }
599
600 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
601                                 char *dom_name, char *dom_sid)
602 {
603         char *start = q;
604         LSA_R_QUERY_INFO r_q;
605
606         /* set up the LSA QUERY INFO response */
607
608         r_q.undoc_buffer = 1; /* not null */
609         r_q.info_class = q_q->info_class;
610
611         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
612
613         r_q.status = 0x0;
614
615         /* store the response in the SMB stream */
616         q = lsa_io_r_query(False, &r_q, q, base, 4, 0);
617
618         /* return length of SMB data stored */
619         return q - start; 
620 }
621
622 /* pretty much hard-coded choice of "other" sids, unfortunately... */
623 static void make_dom_ref(DOM_R_REF *ref,
624                                 char *dom_name, char *dom_sid,
625                                 char *other_sid1, char *other_sid2, char *other_sid3)
626 {
627         int len_dom_name   = strlen(dom_name);
628         int len_other_sid1 = strlen(other_sid1);
629         int len_other_sid2 = strlen(other_sid2);
630         int len_other_sid3 = strlen(other_sid3);
631
632         ref->undoc_buffer = 1;
633         ref->num_ref_doms_1 = 4;
634         ref->buffer_dom_name = 1;
635         ref->max_entries = 32;
636         ref->num_ref_doms_2 = 4;
637
638         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
639         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
640         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
641         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
642
643         if (dom_name != NULL)
644         {
645                 make_unistr(&(ref->uni_dom_name), dom_name);
646         }
647
648         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
649         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
650         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
651         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
652 }
653
654 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
655                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
656                                 char *dom_name, char *dom_sid,
657                                 char *other_sid1, char *other_sid2, char *other_sid3)
658 {
659         int i;
660
661         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
662                      other_sid1, other_sid2, other_sid3);
663
664         r_l->num_entries = num_entries;
665         r_l->undoc_buffer = 1;
666         r_l->num_entries2 = num_entries;
667
668         for (i = 0; i < num_entries; i++)
669         {
670                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
671         }
672
673         r_l->num_entries3 = num_entries;
674 }
675
676 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
677                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
678                                 char *dom_name, char *dom_sid,
679                                 char *other_sid1, char *other_sid2, char *other_sid3)
680 {
681         int i;
682
683         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
684                      other_sid1, other_sid2, other_sid3);
685
686         r_l->num_entries = num_entries;
687         r_l->undoc_buffer = 1;
688         r_l->num_entries2 = num_entries;
689
690         for (i = 0; i < num_entries; i++)
691         {
692                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
693         }
694
695         r_l->num_entries3 = num_entries;
696 }
697
698 static int lsa_reply_lookup_sids(char *q, char *base,
699                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
700                                 char *dom_name, char *dom_sid,
701                                 char *other_sid1, char *other_sid2, char *other_sid3)
702 {
703         char *start = q;
704         LSA_R_LOOKUP_SIDS r_l;
705
706         /* set up the LSA Lookup SIDs response */
707         make_reply_lookup_sids(&r_l, num_entries, dom_sids,
708                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
709         r_l.status = 0x0;
710
711         /* store the response in the SMB stream */
712         q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0);
713
714         /* return length of SMB data stored */
715         return q - start; 
716 }
717
718 static int lsa_reply_lookup_rids(char *q, char *base,
719                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
720                                 char *dom_name, char *dom_sid,
721                                 char *other_sid1, char *other_sid2, char *other_sid3)
722 {
723         char *start = q;
724         LSA_R_LOOKUP_RIDS r_l;
725
726         /* set up the LSA Lookup RIDs response */
727         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
728                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
729         r_l.status = 0x0;
730
731         /* store the response in the SMB stream */
732         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0);
733
734         /* return length of SMB data stored */
735         return q - start; 
736 }
737
738 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c,
739                                 DOM_CHAL *srv_chal, int status)
740 {
741         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data));
742         r_c->status = status;
743 }
744
745 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
746                                         DOM_CHAL *srv_chal)
747 {
748         char *start = q;
749         LSA_R_REQ_CHAL r_c;
750
751         /* set up the LSA REQUEST CHALLENGE response */
752
753         make_lsa_r_req_chal(&r_c, srv_chal, 0);
754
755         /* store the response in the SMB stream */
756         q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0);
757
758         /* return length of SMB data stored */
759         return q - start; 
760 }
761
762 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
763                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
764 {
765         memcpy(  r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
766         memcpy(&(r_a->srv_flgs)    , flgs           , sizeof(r_a->srv_flgs));
767         r_a->status = status;
768 }
769
770 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
771                                 DOM_CHAL *resp_cred, int status)
772 {
773         char *start = q;
774         LSA_R_AUTH_2 r_a;
775
776         /* set up the LSA AUTH 2 response */
777
778         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
779
780         /* store the response in the SMB stream */
781         q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0);
782
783         /* return length of SMB data stored */
784         return q - start; 
785 }
786
787 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
788                              DOM_CRED *srv_cred, int status)  
789 {
790         memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred));
791         r_a->status = status;
792 }
793
794 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
795                                 DOM_CRED *srv_cred, int status)
796 {
797         char *start = q;
798         LSA_R_SRV_PWSET r_s;
799
800         /* set up the LSA Server Password Set response */
801         make_lsa_r_srv_pwset(&r_s, srv_cred, status);
802
803         /* store the response in the SMB stream */
804         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0);
805
806         /* return length of SMB data stored */
807         return q - start; 
808 }
809
810 static void make_lsa_user_info(LSA_USER_INFO *usr,
811
812         NTTIME *logon_time,
813         NTTIME *logoff_time,
814         NTTIME *kickoff_time,
815         NTTIME *pass_last_set_time,
816         NTTIME *pass_can_change_time,
817         NTTIME *pass_must_change_time,
818
819         char *user_name,
820         char *full_name,
821         char *logon_script,
822         char *profile_path,
823         char *home_dir,
824         char *dir_drive,
825
826         uint16 logon_count,
827         uint16 bad_pw_count,
828
829         uint32 user_id,
830         uint32 group_id,
831         uint32 num_groups,
832         DOM_GID *gids,
833         uint32 user_flgs,
834
835         char sess_key[16],
836
837         char *logon_srv,
838         char *logon_dom,
839
840         char *dom_sid,
841         char *other_sids) /* space-delimited set of SIDs */ 
842 {
843         /* only cope with one "other" sid, right now. */
844         /* need to count the number of space-delimited sids */
845         int i;
846         int num_other_sids = other_sids != NULL ? 1 : 0;
847
848         int len_user_name    = strlen(user_name   );
849         int len_full_name    = strlen(full_name   );
850         int len_logon_script = strlen(logon_script);
851         int len_profile_path = strlen(profile_path);
852         int len_home_dir     = strlen(home_dir    );
853         int len_dir_drive    = strlen(dir_drive   );
854
855         int len_logon_srv    = strlen(logon_srv);
856         int len_logon_dom    = strlen(logon_dom);
857
858         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
859
860         usr->logon_time            = *logon_time;
861         usr->logoff_time           = *logoff_time;
862         usr->kickoff_time          = *kickoff_time;
863         usr->pass_last_set_time    = *pass_last_set_time;
864         usr->pass_can_change_time  = *pass_can_change_time;
865         usr->pass_must_change_time = *pass_must_change_time;
866
867         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
868         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
869         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
870         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
871         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
872         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
873
874         usr->logon_count = logon_count;
875         usr->bad_pw_count = bad_pw_count;
876
877         usr->user_id = user_id;
878         usr->group_id = group_id;
879         usr->num_groups = num_groups;
880         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
881         usr->user_flgs = user_flgs;
882
883         if (sess_key != NULL)
884         {
885                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
886         }
887         else
888         {
889                 bzero(usr->sess_key, sizeof(usr->sess_key));
890         }
891
892         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
893         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
894
895         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
896
897         bzero(usr->padding, sizeof(usr->padding));
898
899         usr->num_other_sids = num_other_sids;
900         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
901         
902         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
903         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
904         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
905         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
906         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
907         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
908
909         usr->num_groups2 = num_groups;
910         for (i = 0; i < num_groups; i++)
911         {
912                 usr->gids[i] = gids[i];
913         }
914
915         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
916         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
917
918         make_dom_sid(&(usr->dom_sid), dom_sid);
919         make_dom_sid(&(usr->other_sids[0]), other_sids);
920 }
921
922
923 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
924                                 DOM_CRED *srv_cred, LSA_USER_INFO *user_info)
925 {
926         char *start = q;
927         LSA_R_SAM_LOGON r_s;
928
929         /* XXXX maybe we want to say 'no', reject the client's credentials */
930         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
931         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
932
933         /* store the user information, if there is any. */
934         r_s.user = user_info;
935         r_s.buffer_user = user_info != NULL ? 1 : 0;
936         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
937
938         /* store the response in the SMB stream */
939         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0);
940
941         /* return length of SMB data stored */
942         return q - start; 
943 }
944
945
946 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
947                                 DOM_CRED *srv_cred, 
948                                 uint32 status)
949 {
950         char *start = q;
951         LSA_R_SAM_LOGOFF r_s;
952
953         /* XXXX maybe we want to say 'no', reject the client's credentials */
954         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
955         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
956
957         r_s.status = status;
958
959         /* store the response in the SMB stream */
960         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0);
961
962         /* return length of SMB data stored */
963         return q - start; 
964 }
965
966
967 static void api_lsa_open_policy( char *param, char *data,
968                              char **rdata, int *rdata_len )
969 {
970         /* we might actually want to decode the query, but it's not necessary */
971         /* lsa_io_q_open_policy(...); */
972
973         /* construct a 20 byte policy handle. return length*/
974         *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata);
975 }
976
977 static int api_lsa_query_info( char *param, char *data,
978                                 char **rdata, int *rdata_len )
979 {
980         LSA_Q_QUERY_INFO q_i;
981         pstring dom_name;
982         pstring dom_sid;
983
984         /* grab the info class and policy handle */
985         lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4, 0);
986
987         pstrcpy(dom_name, lp_workgroup());
988         pstrcpy(dom_sid , lp_domainsid());
989
990         /* construct reply.  return status is always 0x0 */
991         return lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, 
992                                                                          dom_name, dom_sid);
993 }
994
995 static void api_lsa_lookup_sids( char *param, char *data,
996                                  char **rdata, int *rdata_len )
997 {
998         int i;
999         LSA_Q_LOOKUP_SIDS q_l;
1000         pstring dom_name;
1001         pstring dom_sid;
1002         fstring dom_sids[MAX_LOOKUP_SIDS];
1003
1004         /* grab the info class and policy handle */
1005         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1006
1007         pstrcpy(dom_name, lp_workgroup());
1008         pstrcpy(dom_sid , lp_domainsid());
1009
1010         /* convert received SIDs to strings, so we can do them. */
1011         for (i = 0; i < q_l.num_entries; i++)
1012         {
1013                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1014         }
1015
1016         /* construct reply.  return status is always 0x0 */
1017         *rdata_len =  lsa_reply_lookup_sids(*rdata + 0x18, *rdata,
1018                     q_l.num_entries, dom_sids, /* text-converted SIDs */
1019                                 dom_name, dom_sid, /* domain name, domain SID */
1020                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1021 }
1022
1023 static void api_lsa_lookup_names( char *param, char *data,
1024                                   char **rdata, int *rdata_len )
1025 {
1026         int i;
1027         LSA_Q_LOOKUP_RIDS q_l;
1028         pstring dom_name;
1029         pstring dom_sid;
1030         uint32 dom_rids[MAX_LOOKUP_SIDS];
1031
1032         /* grab the info class and policy handle */
1033         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1034
1035         pstrcpy(dom_name, lp_workgroup());
1036         pstrcpy(dom_sid , lp_domainsid());
1037
1038         /* convert received RIDs to strings, so we can do them. */
1039         for (i = 0; i < q_l.num_entries; i++)
1040         {
1041                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1042                 dom_rids[i] = name_to_rid(user_name);
1043         }
1044
1045         /* construct reply.  return status is always 0x0 */
1046         *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata,
1047                     q_l.num_entries, dom_rids, /* text-converted SIDs */
1048                                 dom_name, dom_sid, /* domain name, domain SID */
1049                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1050 }
1051
1052 BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
1053                      int mdrcnt,int mprcnt,
1054                      char **rdata,char **rparam,
1055                      int *rdata_len,int *rparam_len)
1056 {
1057         uint16 opnum = SVAL(data,22);
1058
1059         int pkttype = CVAL(data, 2);
1060         if (pkttype == 0x0b) /* RPC BIND */
1061         {
1062                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1063                 LsarpcTNP1(data,rdata,rdata_len);
1064                 return True;
1065         }
1066
1067         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1068         switch (opnum)
1069         {
1070                 case LSA_OPENPOLICY:
1071                 {
1072                         DEBUG(3,("LSA_OPENPOLICY\n"));
1073                         api_lsa_open_policy(param, data, rdata, rdata_len);
1074                         make_rpc_reply(data, *rdata, *rdata_len);
1075
1076                         break;
1077                 }
1078
1079                 case LSA_QUERYINFOPOLICY:
1080                 {
1081                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
1082
1083                         api_lsa_query_info(param, data, rdata, rdata_len);
1084                         make_rpc_reply(data, *rdata, *rdata_len);
1085
1086                         break;
1087                 }
1088
1089                 case LSA_ENUMTRUSTDOM:
1090                 {
1091                         char *q = *rdata + 0x18;
1092
1093                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
1094
1095                         initrpcreply(data, *rdata);
1096
1097                         SIVAL(q, 0, 0); /* enumeration context */
1098                         SIVAL(q, 0, 4); /* entries read */
1099                         SIVAL(q, 0, 8); /* trust information */
1100
1101                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1102
1103                         break;
1104                 }
1105
1106                 case LSA_CLOSE:
1107                 {
1108                         char *q = *rdata + 0x18;
1109
1110                         DEBUG(3,("LSA_CLOSE\n"));
1111
1112                         initrpcreply(data, *rdata);
1113
1114                         SIVAL(q, 0, 0);
1115                         SIVAL(q, 0, 4);
1116                         SIVAL(q, 0, 8);
1117                         SIVAL(q, 0, 12);
1118                         SIVAL(q, 0, 16);
1119
1120                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1121
1122                         break;
1123                 }
1124
1125                 case LSA_OPENSECRET:
1126                 {
1127                         char *q = *rdata + 0x18;
1128                         DEBUG(3,("LSA_OPENSECRET\n"));
1129
1130                         initrpcreply(data, *rdata);
1131
1132                         SIVAL(q, 0, 0);
1133                         SIVAL(q, 0, 4);
1134                         SIVAL(q, 0, 8);
1135                         SIVAL(q, 0, 12);
1136                         SIVAL(q, 0, 16);
1137
1138                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1139
1140                         break;
1141                 }
1142
1143                 case LSA_LOOKUPSIDS:
1144                 {
1145                         DEBUG(3,("LSA_OPENSECRET\n"));
1146                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
1147                         make_rpc_reply(data, *rdata, *rdata_len);
1148
1149                         break;
1150                 }
1151
1152                 case LSA_LOOKUPNAMES:
1153                 {
1154                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
1155                         api_lsa_lookup_names(param, data, rdata, rdata_len);
1156                         make_rpc_reply(data, *rdata, *rdata_len);
1157
1158                         break;
1159                 }
1160
1161                 default:
1162                 {
1163                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1164                         break;
1165                 }
1166         }
1167         return True;
1168 }
1169
1170 static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct)
1171 {
1172     struct smb_passwd *smb_pass = get_smbpwnam(mach_acct);
1173         int i;
1174
1175         if (smb_pass != NULL)
1176         {
1177                 memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw));
1178         }
1179         else
1180         {
1181                 /* No such machine account. Should error out here, but we'll
1182                    print and carry on */
1183                 DEBUG(1,("No account in domain for %s\n", mach_acct));
1184                 return False;
1185         }
1186
1187         {
1188                 char foo[16];
1189                 for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]);
1190                 DEBUG(4,("pass %s %s\n", mach_acct, foo));
1191         }
1192
1193         /* from client / server challenges and md4 password, generate sess key */
1194         cred_session_key(&(dc->clnt_chal), &(dc->srv_chal),
1195                            dc->md4pw, dc->sess_key);
1196
1197         /* copy the client credentials for later use */
1198         memcpy(dc->srv_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
1199         memcpy(dc->srv_cred.data, clnt_chal->data, sizeof(clnt_chal->data));
1200
1201         /* create a server challenge for the client */
1202         /* PAXX: set these to random values. */
1203         /* lkcl: paul, you mentioned that it doesn't really matter much */
1204         for (i = 0; i < 8; i++)
1205         {
1206                 dc->srv_chal.data[i] = 0xA5;
1207         }
1208
1209         return True;
1210 }
1211
1212 static void api_lsa_req_chal( user_struct *vuser,
1213                               char *param, char *data,
1214                               char **rdata, int *rdata_len )
1215 {
1216         int reply_len;
1217
1218         LSA_Q_REQ_CHAL q_r;
1219
1220         fstring mach_acct;
1221
1222         /* grab the challenge... */
1223         lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4, 0);
1224
1225         fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer));
1226
1227         strcat(mach_acct, "$");
1228
1229         update_dcinfo(&(vuser->dc), &(q_r.clnt_chal), mach_acct);
1230
1231         /* construct reply.  return status is always 0x0 */
1232         reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18,
1233                                         &(vuser->dc.srv_chal));
1234
1235         /* construct header, now that we know the reply length */
1236         reply_len += make_rpc_reply(data, *rdata, reply_len);
1237
1238         *rdata_len = reply_len;
1239 }
1240
1241 static void api_lsa_auth_2( user_struct *vuser,
1242                             char *param, char *data,
1243                             char **rdata, int *rdata_len )
1244 {
1245         int reply_len;
1246         LSA_Q_AUTH_2 q_a;
1247
1248         DOM_CHAL srv_chal;
1249         UTIME srv_time;
1250
1251         srv_time.time = 0;
1252
1253         /* grab the challenge... */
1254         lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4, 0);
1255
1256         /* check that the client credentials are valid */
1257         cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
1258                 &(vuser->dc.srv_cred), srv_time);
1259
1260         /* create server credentials for inclusion in the reply */
1261         cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal);
1262
1263         /* construct reply.  */
1264         reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18,
1265                                         &srv_chal, 0x0);
1266
1267         /* construct header, now that we know the reply length */
1268         reply_len += make_rpc_reply(data, *rdata, reply_len);
1269
1270         *rdata_len = reply_len;
1271 }
1272
1273
1274 static BOOL deal_with_credentials(user_struct *vuser,
1275                         DOM_CRED *clnt_cred, DOM_CRED *srv_cred)
1276 {
1277         UTIME new_clnt_time;
1278
1279         /* doesn't matter that server time is 0 */
1280         srv_cred->timestamp.time = 0;
1281
1282         /* check that the client credentials are valid */
1283         if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key,
1284                     &(vuser->dc.srv_cred), clnt_cred->timestamp))
1285         {
1286                 return False;
1287         }
1288
1289         /* increment client time by one second */
1290         new_clnt_time.time = clnt_cred->timestamp.time + 1;
1291
1292         /* create server credentials for inclusion in the reply */
1293         cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time,
1294                     &(srv_cred->challenge));
1295
1296         /* update the client and server credentials, for use next time... */
1297         *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time );
1298
1299         return True;
1300 }
1301
1302 static void api_lsa_srv_pwset( user_struct *vuser,
1303                                char *param, char *data,
1304                                char **rdata, int *rdata_len )
1305 {
1306         int reply_len;
1307         LSA_Q_SRV_PWSET q_a;
1308
1309         DOM_CRED srv_cred;
1310
1311         /* grab the challenge and encrypted password ... */
1312         lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4, 0);
1313
1314         /* checks and updates credentials.  creates reply credentials */
1315         deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred);
1316
1317         /* construct reply.  always indicate failure.  nt keeps going... */
1318         reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18,
1319                                         &srv_cred,
1320                         NT_STATUS_WRONG_PASSWORD|0xC000000);
1321
1322         /* construct header, now that we know the reply length */
1323         reply_len += make_rpc_reply(data, *rdata, reply_len);
1324
1325         *rdata_len = reply_len;
1326 }
1327
1328
1329 static void api_lsa_sam_logoff( user_struct *vuser,
1330                                char *param, char *data,
1331                                char **rdata, int *rdata_len )
1332 {
1333         int reply_len;
1334         LSA_Q_SAM_LOGOFF q_l;
1335
1336         DOM_CRED srv_cred;
1337
1338         /* grab the challenge... */
1339         lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1340
1341         /* checks and updates credentials.  creates reply credentials */
1342         deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred);
1343
1344         /* construct reply.  always indicate success */
1345         reply_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata + 0x18,
1346                                         &srv_cred,
1347                         0x0);
1348
1349         /* construct header, now that we know the reply length */
1350         reply_len += make_rpc_reply(data, *rdata, reply_len);
1351
1352         *rdata_len = reply_len;
1353 }
1354
1355
1356 static void api_lsa_sam_logon( user_struct *vuser,
1357                                char *param, char *data,
1358                                char **rdata, int *rdata_len )
1359 {
1360         int reply_len;
1361         LSA_Q_SAM_LOGON q_l;
1362         LSA_USER_INFO usr_info;
1363         LSA_USER_INFO *p_usr_info = NULL;
1364
1365         DOM_CRED srv_creds;
1366
1367         lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1368
1369         /* checks and updates credentials.  creates reply credentials */
1370         deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds);
1371
1372         if (vuser != NULL)
1373         {
1374                 NTTIME dummy_time;
1375                 pstring logon_script;
1376                 pstring profile_path;
1377                 pstring home_dir;
1378                 pstring home_drive;
1379                 pstring my_name;
1380                 pstring my_workgroup;
1381                 pstring dom_sid;
1382                 pstring username;
1383                 extern pstring myname;
1384
1385                 dummy_time.low  = 0xffffffff;
1386                 dummy_time.high = 0x7fffffff;
1387
1388                 get_myname(myname, NULL);
1389
1390                 pstrcpy(logon_script, lp_logon_script());
1391                 pstrcpy(profile_path, lp_logon_path  ());
1392                 pstrcpy(dom_sid     , lp_domainsid   ());
1393                 pstrcpy(my_workgroup, lp_workgroup   ());
1394
1395                 pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer));
1396                 pstrcpy(my_name     , myname           );
1397                 strupper(my_name);
1398
1399                 pstrcpy(home_drive  , "a:"             );
1400
1401 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1402                 pstrcpy(home_dir    , vuser->home_share);
1403 #else
1404                 pstrcpy(home_dir    , "\\\\%L\\%U");
1405                 standard_sub_basic(home_dir);
1406 #endif
1407
1408                 p_usr_info = &usr_info;
1409
1410                 make_lsa_user_info(p_usr_info,
1411
1412                                &dummy_time, /* logon_time */
1413                                &dummy_time, /* logoff_time */
1414                                &dummy_time, /* kickoff_time */
1415                                &dummy_time, /* pass_last_set_time */
1416                                &dummy_time, /* pass_can_change_time */
1417                                &dummy_time, /* pass_must_change_time */
1418
1419                                username, /* user_name */
1420                                vuser->real_name, /* full_name */
1421                                logon_script, /* logon_script */
1422                                profile_path, /* profile_path */
1423                                home_dir, /* home_dir */
1424                                home_drive, /* dir_drive */
1425
1426                                0, /* logon_count */
1427                                0, /* bad_pw_count */
1428
1429                                vuser->uid, /* uint32 user_id */
1430                                vuser->gid, /* uint32 group_id */
1431                                0,    /* uint32 num_groups */
1432                                NULL, /* DOM_GID *gids */
1433                                0x20, /* uint32 user_flgs */
1434
1435                                NULL, /* char sess_key[16] */
1436
1437                                my_name, /* char *logon_srv */
1438                                my_workgroup, /* char *logon_dom */
1439
1440                                dom_sid, /* char *dom_sid */
1441                                NULL); /* char *other_sids */
1442         }
1443
1444         reply_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata + 0x18,
1445                                         &srv_creds, p_usr_info);
1446
1447         /* construct header, now that we know the reply length */
1448         reply_len += make_rpc_reply(data, *rdata, reply_len);
1449
1450         *rdata_len = reply_len;
1451 }
1452
1453
1454 #if 0
1455 case LSASAMLOGON:
1456         DEBUG(1,("LSASAMLOGON\n"));
1457         dump_data(1,data,128);
1458         q = data + 0x18;
1459         logonsrv = q + 16;
1460         DEBUG(1,("SMLOG %d\n", __LINE__));
1461         q = skip_unicode_string(logonsrv,1)+16;
1462         q = align4(q, data);
1463         unicomp = q;
1464         q = skip_unicode_string(unicomp,1)+4;
1465         DEBUG(1,("SMLOG %d  logonsrv=%s unicomp=%s\n", 
1466                  __LINE__, unistr(logonsrv), unistr(unicomp)));
1467         q = align4(q, data);
1468         rcvcred[0] = qIVAL;
1469         DEBUG(1,("SMLOG %d\n", __LINE__));
1470         rcvcred[1] = qIVAL;
1471         DEBUG(1,("SMLOG %d\n", __LINE__));
1472         clnttime = qIVAL;
1473         checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1474         q += 2;
1475         rtncred[0] = qIVAL; /* all these are ignored */
1476         DEBUG(1,("SMLOG %d\n", __LINE__));
1477         rtncred[1] = qIVAL;
1478         rtntime = qIVAL;
1479         logonlevel = qSVAL;
1480         DEBUG(1,("SMLOG %d\n", __LINE__));
1481         switchval = qSVAL;
1482         switch (switchval)
1483                 {
1484                 case 1:
1485                         
1486                         q += 6;
1487                         domlen = qSVAL;
1488                         dommaxlen = qSVAL; q += 4;
1489                         paramcontrol = qIVAL;
1490                         logonid[0] = qIVAL; /* low part */
1491                         logonid[1] = qIVAL; /* high part */
1492                         
1493                         usernamelen = qSVAL;
1494                         
1495                         DEBUG(1,("SMLOG %d\n", __LINE__));
1496                         usernamemaxlen = qSVAL; q += 4;
1497                         
1498                         DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", 
1499                                  usernamelen, usernamemaxlen, dommaxlen));
1500                         
1501                         dump_data(1,q,128);
1502                         
1503                         wslen = qSVAL;
1504                         wsmaxlen = qSVAL; q += 4;
1505                         rc4lmowfpass = q; q += 16;
1506                         rc4ntowfpass = q; q += 16;
1507                         
1508                         q += 12; domain = q; q += dommaxlen + 12;
1509                         q = align4(q, data);
1510                         username = q; q += usernamemaxlen + 12; 
1511                         q = align4(q, data);
1512                         ws = q;
1513                         DEBUG(1,("domain=%s username=%s ws=%s\n",
1514                                  unistr(domain), unistr(username),
1515                                  unistr(ws)));
1516                         break;
1517                 default: 
1518                         DEBUG(0,("unknown switch in SAMLOGON %d\n",
1519                                  switchval));
1520                 }
1521         for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]);
1522         DEBUG(1,("userNAME %s  [%s]\n", foo, username));
1523         DEBUG(1,("SMLOG %d\n", __LINE__));
1524         q = *rdata + 0x18;
1525         qSIVAL(0x16a4b4); /* magic buffer pointer ? */
1526         makecred(cnum, clnttime+1, q);
1527         dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1528         q += 8;
1529         qSIVAL(0); /* timestamp. client doesn't care */
1530         qSSVAL(3); /* switch value 3. May be others? */
1531         qSSVAL(0); /* undocumented */
1532         DEBUG(1,("SMLOG %d\n", __LINE__));
1533         
1534         memset(rc4key, 0, sizeof rc4key);
1535         SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]);
1536         SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]);
1537         for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]);
1538         DEBUG(1,("rc4ntowf %s\n", foo));
1539         arcfour_init(&c, rc4key, sizeof rc4key);
1540         arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass);
1541         for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]);
1542         DEBUG(1,("ntowf %s\n", foo));
1543         
1544         if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) {
1545                 qSIVAL(0); /* no buffer */
1546                 qSCVAL(1); /* Authoratitive. Change if passthrough? */
1547                 qSCVAL(0); /* pad for above boolean */
1548                 qSSVAL(0); /* pad for above boolean */
1549                 
1550                 endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len);
1551                 break;
1552         }
1553
1554         qSIVAL(2); /* another magic bufptr? */
1555   DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo));
1556   qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]);
1557   qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]);
1558   DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1]));
1559   qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]);
1560   qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]);
1561   qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]);
1562   qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]);
1563   DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename));
1564   qunihdr(userinfo->effectivename);
1565   qunihdr(userinfo->fullname);
1566   DEBUG(1,("SMLOG %d\n", __LINE__));
1567   qunihdr(userinfo->logonscript);
1568   qunihdr(userinfo->profilepath);
1569   qunihdr(userinfo->homedirectory);
1570   qunihdr(userinfo->homedirectorydrive);
1571   DEBUG(1,("SMLOG %d\n", __LINE__));
1572   qSSVAL(userinfo->logoncount);
1573   qSSVAL(userinfo->badpwcount);
1574   qSIVAL(userinfo->uid);
1575   qSIVAL(userinfo->gid);
1576   DEBUG(1,("SMLOG %d\n", __LINE__));
1577   qSIVAL(userinfo->ngroups);
1578   qSIVAL(8); /* ptr to groups */
1579   qSIVAL(userinfo->userflags);
1580   DEBUG(1,("SMLOG %d\n", __LINE__));
1581   qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */
1582   qunihdr(userinfo->logonserver);
1583   qunihdr(userinfo->logondomain);
1584   DEBUG(1,("SMLOG %d\n", __LINE__));
1585   qSIVAL(2); /* logon domain id ptr */
1586   DEBUG(1,("SMLOG %d\n", __LINE__));
1587   memset(q,0,40); q += 40; /* expansion room */
1588   DEBUG(1,("SMLOG %d\n", __LINE__));
1589   qSIVAL(userinfo->nsids);
1590   DEBUG(1,("SMLOG %d\n", __LINE__));
1591   qSIVAL(0); /* ptr to sids and values */
1592   DEBUG(1,("SMLOG %d\n", __LINE__));
1593   qunistr(userinfo->effectivename);
1594   DEBUG(1,("SMLOG %d\n", __LINE__));
1595   qunistr(userinfo->fullname);
1596   DEBUG(1,("SMLOG %d\n", __LINE__));
1597   qunistr(userinfo->logonscript);
1598   DEBUG(1,("SMLOG %d\n", __LINE__));
1599   qunistr(userinfo->profilepath);
1600   qunistr(userinfo->homedirectory);
1601   qunistr(userinfo->homedirectorydrive);
1602   DEBUG(1,("SMLOG %d\n", __LINE__));
1603   qSIVAL(userinfo->ngroups);
1604   for (i = 0; i < userinfo->ngroups; i++)
1605   {
1606         qSIVAL(userinfo->groups[i].gid);
1607         qSIVAL(userinfo->groups[i].attr);
1608   }
1609   qunistr(userinfo->logonserver);
1610   qunistr(userinfo->logondomain);
1611   for (i = 0; i < userinfo->nsids; i++)
1612   {
1613         /* put the extra sids: PAXX: TODO */
1614   }
1615   /* Assumption. This is the only domain, sending our SID */
1616   /* PAXX: may want to do passthrough later */
1617   strcpy(domsid,lp_domainsid());
1618 DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1619   /* assume, but should check, that domsid starts "S-" */
1620   p = strtok(domsid+2,"-");
1621   revision = atoi(p);
1622 DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1623   identauth = atoi(strtok(0,"-"));
1624 DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1625   numsubauths = 0;
1626   while (p = strtok(0, "-"))
1627         subauths[numsubauths++] = atoi(p);
1628   qSIVAL(numsubauths);
1629   qSCVAL(revision);
1630   qSCVAL(numsubauths);
1631   qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */
1632   qRSIVAL(identauth); /* next 4 bytes */
1633   DEBUG(1,("SMLOG %d\n", __LINE__));
1634   for (i = 0; i < numsubauths; i++)
1635   {
1636         qSIVAL(subauths[i]);
1637   }
1638   qSCVAL(1); /* Authoratitive. Change if passthrough? */
1639   qSCVAL(0); /* pad for above boolean */
1640   qSSVAL(0); /* pad for above boolean */
1641
1642   endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1643   break;
1644 #endif
1645
1646 BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
1647                      int mdrcnt,int mprcnt,
1648                      char **rdata,char **rparam,
1649                      int *rdata_len,int *rparam_len)
1650 {
1651         uint16 opnum;
1652         char pkttype;
1653         user_struct *vuser;
1654
1655         DEBUG(5,("api_netlogrpcTNP data:%x\n", data));
1656
1657         if (data == NULL) return False;
1658
1659         opnum = SVAL(data,22);
1660         pkttype = CVAL(data, 2);
1661
1662         if (pkttype == 0x0b) /* RPC BIND */
1663         {
1664                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1665                 LsarpcTNP1(data,rdata,rdata_len);
1666                 return True;
1667         }
1668
1669         DEBUG(4,("netlogon TransactNamedPipe op %x\n", opnum));
1670
1671         if ((vuser = get_valid_user_struct(uid)) == NULL) return False;
1672
1673         DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name));
1674 #if defined(NETGROUP) && defined(AUTOMOUNT)
1675         DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1676 #endif
1677
1678         switch (opnum)
1679         {
1680                 case LSA_REQCHAL:
1681                 {
1682                         DEBUG(3,("LSA_REQCHAL\n"));
1683                         api_lsa_req_chal(vuser, param, data, rdata, rdata_len);
1684                         break;
1685                 }
1686
1687                 case LSA_AUTH2:
1688                 {
1689                         DEBUG(3,("LSA_AUTH2\n"));
1690                         api_lsa_auth_2(vuser, param, data, rdata, rdata_len);
1691                         break;
1692                 }
1693
1694                 case LSA_SRVPWSET:
1695                 {
1696                         DEBUG(3,("LSA_SRVPWSET\n"));
1697                         api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len);
1698                         break;
1699                 }
1700
1701                 case LSA_SAMLOGON:
1702                 {
1703                         DEBUG(3,("LSA_SAMLOGON\n"));
1704                         api_lsa_sam_logon(vuser, param, data, rdata, rdata_len);
1705                         break;
1706                 }
1707
1708                 case LSA_SAMLOGOFF:
1709                 {
1710                         DEBUG(3,("LSA_SAMLOGOFF\n"));
1711                         api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len);
1712                         break;
1713                 }
1714
1715                 default:
1716                 {
1717                         DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
1718                         break;
1719                 }
1720         }
1721
1722         return True;
1723 }
1724
1725 #endif /* NTDOMAIN */