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