updated rpc header reply: callid wrong; alloc hint a uint32 not a uint16.
[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 #if NTDOMAIN
57   "NETLOGON",
58   "srvsvc",
59 #endif
60   "lsarpc",
61   NULL
62 };
63
64 /****************************************************************************
65   reply to an open and X on a named pipe
66
67   In fact what we do is to open a regular file with the same name in
68   /tmp. This can then be closed as normal. Reading and writing won't
69   make much sense, but will do *something*. The real reason for this
70   support is to be able to do transactions on them (well, on lsarpc
71   for domain login purposes...).
72
73   This code is basically stolen from reply_open_and_X with some
74   wrinkles to handle pipes.
75 ****************************************************************************/
76 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
77 {
78   pstring fname;
79   int cnum = SVAL(inbuf,smb_tid);
80   int fnum = -1;
81   int smb_mode = SVAL(inbuf,smb_vwv3);
82   int smb_attr = SVAL(inbuf,smb_vwv5);
83 #if 0
84   int open_flags = SVAL(inbuf,smb_vwv2);
85   int smb_sattr = SVAL(inbuf,smb_vwv4); 
86   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
87 #endif
88   int smb_ofun = SVAL(inbuf,smb_vwv8);
89   int unixmode;
90   int size=0,fmode=0,mtime=0,rmode=0;
91   struct stat sbuf;
92   int smb_action = 0;
93   int i;
94   BOOL bad_path = False;
95
96   /* XXXX we need to handle passed times, sattr and flags */
97   pstrcpy(fname,smb_buf(inbuf));
98
99   /* If the name doesn't start \PIPE\ then this is directed */
100   /* at a mailslot or something we really, really don't understand, */
101   /* not just something we really don't understand. */
102   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
103     return(ERROR(ERRSRV,ERRaccess));
104
105   DEBUG(4,("Opening pipe %s.\n", fname));
106
107   /* Strip \PIPE\ off the name. */
108   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
109
110   /* See if it is one we want to handle. */
111   for( i = 0; known_pipes[i] ; i++ )
112     if( strcmp(fname,known_pipes[i]) == 0 )
113       break;
114
115   if ( known_pipes[i] == NULL )
116     return(ERROR(ERRSRV,ERRaccess));
117
118   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
119   /* can be opened and add it in after the open. */
120   DEBUG(3,("Known pipe %s opening.\n",fname));
121   smb_attr &= ~aDIR;
122   Connections[cnum].read_only = 0;
123   smb_ofun |= 0x10;             /* Add Create it not exists flag */
124
125   unix_convert(fname,cnum,0,&bad_path);
126     
127   fnum = find_free_file();
128   if (fnum < 0)
129     return(ERROR(ERRSRV,ERRnofids));
130
131   if (!check_name(fname,cnum))
132     return(UNIXERROR(ERRDOS,ERRnoaccess));
133
134   unixmode = unix_mode(cnum,smb_attr);
135       
136   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
137                    0, &rmode,&smb_action);
138       
139   if (!Files[fnum].open)
140   {
141     /* Change the error code if bad_path was set. */
142     if((errno == ENOENT) && bad_path)
143     {
144       unix_ERR_class = ERRDOS;
145       unix_ERR_code = ERRbadpath;
146     }
147     return(UNIXERROR(ERRDOS,ERRnoaccess));
148   }
149
150   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
151     close_file(fnum);
152     return(ERROR(ERRDOS,ERRnoaccess));
153   }
154
155   size = sbuf.st_size;
156   fmode = dos_mode(cnum,fname,&sbuf);
157   mtime = sbuf.st_mtime;
158   if (fmode & aDIR) {
159     close_file(fnum);
160     return(ERROR(ERRDOS,ERRnoaccess));
161   }
162
163   /* Prepare the reply */
164   set_message(outbuf,15,0,True);
165
166   /* Put things back the way they were. */
167   Connections[cnum].read_only = 1;
168
169   /* Mark the opened file as an existing named pipe in message mode. */
170   SSVAL(outbuf,smb_vwv9,2);
171   SSVAL(outbuf,smb_vwv10,0xc700);
172   if (rmode == 2)
173   {
174     DEBUG(4,("Resetting open result to open from create.\n"));
175     rmode = 1;
176   }
177
178   SSVAL(outbuf,smb_vwv2,fnum);
179   SSVAL(outbuf,smb_vwv3,fmode);
180   put_dos_date3(outbuf,smb_vwv4,mtime);
181   SIVAL(outbuf,smb_vwv6,size);
182   SSVAL(outbuf,smb_vwv8,rmode);
183   SSVAL(outbuf,smb_vwv11,smb_action);
184
185   chain_fnum = fnum;
186
187   DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
188            fname, fnum, Files[fnum].name));
189   
190   return chain_reply(inbuf,outbuf,length,bufsize);
191 }
192
193
194 /****************************************************************************
195  api_LsarpcSNPHS
196
197  SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
198  so just blithely return True. This is really only for NT domain stuff,
199  we we're only handling that - don't assume Samba now does complete
200  named pipe handling.
201 ****************************************************************************/
202 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
203                      int mdrcnt,int mprcnt,
204                      char **rdata,char **rparam,
205                      int *rdata_len,int *rparam_len)
206 {
207   uint16 id;
208
209   id = param[0] + (param[1] << 8);
210   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
211   return(True);
212 }
213
214
215 /****************************************************************************
216  api_LsarpcTNP
217
218  TransactNamedPipe on \PIPE\lsarpc.
219 ****************************************************************************/
220 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
221 {
222   uint32 dword1, dword2;
223   char pname[] = "\\PIPE\\lsass";
224
225   /* All kinds of mysterious numbers here */
226   *rdata_len = 68;
227   *rdata = REALLOC(*rdata,*rdata_len);
228
229   dword1 = IVAL(data,0xC);
230   dword2 = IVAL(data,0x10);
231
232   SIVAL(*rdata,0,0xc0005);
233   SIVAL(*rdata,4,0x10);
234   SIVAL(*rdata,8,0x44);
235   SIVAL(*rdata,0xC,dword1);
236   
237   SIVAL(*rdata,0x10,dword2);
238   SIVAL(*rdata,0x14,0x15);
239   SSVAL(*rdata,0x18,sizeof(pname));
240   strcpy(*rdata + 0x1a,pname);
241   SIVAL(*rdata,0x28,1);
242   memcpy(*rdata + 0x30, data + 0x34, 0x14);
243 }
244
245 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
246 {
247   uint32 dword1;
248
249   /* All kinds of mysterious numbers here */
250   *rdata_len = 48;
251   *rdata = REALLOC(*rdata,*rdata_len);
252
253   dword1 = IVAL(data,0xC);
254
255   SIVAL(*rdata,0,0x03020005);
256   SIVAL(*rdata,4,0x10);
257   SIVAL(*rdata,8,0x30);
258   SIVAL(*rdata,0xC,dword1);
259   SIVAL(*rdata,0x10,0x18);
260   SIVAL(*rdata,0x1c,0x44332211);
261   SIVAL(*rdata,0x20,0x88776655);
262   SIVAL(*rdata,0x24,0xCCBBAA99);
263   SIVAL(*rdata,0x28,0x11FFEEDD);
264 }
265
266 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
267 {
268   uint32 dword1;
269   uint16 word1;
270   char * workgroup = myworkgroup;
271   int wglen = strlen(workgroup);
272   int i;
273
274   /* All kinds of mysterious numbers here */
275   *rdata_len = 90 + 2 * wglen;
276   *rdata = REALLOC(*rdata,*rdata_len);
277
278   dword1 = IVAL(data,0xC);
279   word1 = SVAL(data,0x2C);
280
281   SIVAL(*rdata,0,0x03020005);
282   SIVAL(*rdata,4,0x10);
283   SIVAL(*rdata,8,0x60);
284   SIVAL(*rdata,0xC,dword1);
285   SIVAL(*rdata,0x10,0x48);
286   SSVAL(*rdata,0x18,0x5988);    /* This changes */
287   SSVAL(*rdata,0x1A,0x15);
288   SSVAL(*rdata,0x1C,word1);
289   SSVAL(*rdata,0x20,6);
290   SSVAL(*rdata,0x22,8);
291   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
292   SSVAL(*rdata,0x26,0x15);
293   SSVAL(*rdata,0x28,0x4D48);    /* And this */
294   SSVAL(*rdata,0x2A,0x15);
295   SIVAL(*rdata,0x2C,4);
296   SIVAL(*rdata,0x34,wglen);
297   for ( i = 0 ; i < wglen ; i++ )
298     (*rdata)[0x38 + i * 2] = workgroup[i];
299    
300   /* Now fill in the rest */
301   i = 0x38 + wglen * 2;
302   SSVAL(*rdata,i,0x648);
303   SIVAL(*rdata,i+2,4);
304   SIVAL(*rdata,i+6,0x401);
305   SSVAL(*rdata,i+0xC,0x500);
306   SIVAL(*rdata,i+0xE,0x15);
307   SIVAL(*rdata,i+0x12,0x2372FE1);
308   SIVAL(*rdata,i+0x16,0x7E831BEF);
309   SIVAL(*rdata,i+0x1A,0x4B454B2);
310 }
311
312 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
313 {
314   uint32 dword1;
315
316   /* All kinds of mysterious numbers here */
317   *rdata_len = 48;
318   *rdata = REALLOC(*rdata,*rdata_len);
319
320   dword1 = IVAL(data,0xC);
321
322   SIVAL(*rdata,0,0x03020005);
323   SIVAL(*rdata,4,0x10);
324   SIVAL(*rdata,8,0x30);
325   SIVAL(*rdata,0xC,dword1);
326   SIVAL(*rdata,0x10,0x18);
327 }
328
329
330 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
331                      int mdrcnt,int mprcnt,
332                      char **rdata,char **rparam,
333                      int *rdata_len,int *rparam_len)
334 {
335   uint32 id,id2;
336
337   id = IVAL(data,0);
338
339   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
340   switch (id)
341   {
342     case 0xb0005:
343       LsarpcTNP1(data,rdata,rdata_len);
344       break;
345
346     case 0x03000005:
347       id2 = IVAL(data,8);
348       DEBUG(4,("\t- Suboperation %lx\n",id2));
349       switch (id2 & 0xF)
350       {
351         case 8:
352           LsarpcTNP2(data,rdata,rdata_len);
353           break;
354
355         case 0xC:
356           LsarpcTNP4(data,rdata,rdata_len);
357           break;
358
359         case 0xE:
360           LsarpcTNP3(data,rdata,rdata_len);
361           break;
362       }
363       break;
364   }
365   return(True);
366 }
367
368
369 #ifdef NTDOMAIN
370 /*
371    PAXX: Someone fix above.
372    The above API is indexing RPC calls based on RPC flags and 
373    fragment length. I've decided to do it based on operation number :-)
374 */
375
376 /* this function is due to be replaced */
377 static void initrpcreply(char *inbuf, char *q)
378 {
379         uint32 callid;
380
381         SCVAL(q, 0, 5); q++; /* RPC version 5 */
382         SCVAL(q, 0, 0); q++; /* minor version 0 */
383         SCVAL(q, 0, 2); q++; /* RPC response packet */
384         SCVAL(q, 0, 3); q++; /* first frag + last frag */
385         RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */
386         RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */
387         SSVAL(q, 0, 0); q += 2; /* authentication length */
388         callid = RIVAL(inbuf, 12);
389         RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */
390         SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */
391         SSVAL(q, 0, 0); q += 2; /* presentation context identifier */
392         SCVAL(q, 0, 0); q++; /* cancel count */
393         SCVAL(q, 0, 0); q++; /* reserved */
394 }
395
396 /* this function is due to be replaced */
397 static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
398 {
399         SSVAL(q, 8, datalen + 4);
400         SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
401         SIVAL(q, datalen, rtnval);
402         *rlen = datalen + 4;
403         { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); }
404 }
405
406 /* RID username mapping function.  just for fun, it maps to the unix uid */
407 static uint32 name_to_rid(char *user_name)
408 {
409     struct passwd *pw = Get_Pwnam(user_name, False);
410     if (!pw)
411         {
412       DEBUG(1,("Username %s is invalid on this system\n", user_name));
413       return (uint32)(-1);
414     }
415
416     return (uint32)(pw->pw_uid);
417 }
418
419
420 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
421 char *dom_sid_to_string(DOM_SID *sid)
422 {
423   static pstring sidstr;
424   char subauth[16];
425   int i;
426   uint32 ia = (sid->id_auth[0]) +
427               (sid->id_auth[1] << 8 ) +
428               (sid->id_auth[2] << 16) +
429               (sid->id_auth[3] << 24);
430
431   sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
432
433   for (i = 0; i < sid->num_auths; i++)
434   {
435     sprintf(subauth, "-%d", sid->sub_auths[i]);
436     strcat(sidstr, subauth);
437   }
438
439   DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
440   return sidstr;
441 }
442
443 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
444 /* identauth >= 2^32 can be detected because it will be specified in hex */
445 static void make_dom_sid(DOM_SID *sid, char *domsid)
446 {
447         int identauth;
448         char *p;
449
450         DEBUG(4,("netlogon domain SID: %s\n", domsid));
451
452         /* assume, but should check, that domsid starts "S-" */
453         p = strtok(domsid+2,"-");
454         sid->sid_no = atoi(p);
455
456         /* identauth in decimal should be <  2^32 */
457         /* identauth in hex     should be >= 2^32 */
458         identauth = atoi(strtok(0,"-"));
459
460         DEBUG(4,("netlogon rev %d\n", sid->sid_no));
461         DEBUG(4,("netlogon %s ia %d\n", p, identauth));
462
463         sid->id_auth[0] = 0;
464         sid->id_auth[1] = 0;
465         sid->id_auth[2] = (identauth & 0xff000000) >> 24;
466         sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
467         sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
468         sid->id_auth[5] = (identauth & 0x000000ff);
469
470         sid->num_auths = 0;
471
472         while ((p = strtok(0, "-")) != NULL)
473         {
474                 sid->sub_auths[sid->num_auths++] = atoi(p);
475         }
476 }
477
478 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
479 {
480         if (hdr == NULL) return;
481
482         hdr->major        = 5;               /* RPC version 5 */
483         hdr->minor        = 0;               /* minor version 0 */
484         hdr->pkt_type     = 2;               /* RPC response packet */
485         hdr->frag         = 3;               /* first frag + last frag */
486         hdr->pack_type    = 0x10;            /* packed data representation */
487         hdr->frag_len     = data_len;        /* fragment length, fill in later */
488         hdr->auth_len     = 0;               /* authentication length */
489         hdr->call_id      = call_id;         /* call identifier - match incoming RPC */
490         hdr->alloc_hint   = data_len - 0x18; /* allocation hint (no idea) */
491         hdr->context_id   = 0;               /* presentation context identifier */
492         hdr->cancel_count = 0;               /* cancel count */
493         hdr->reserved     = 0;               /* reserved */
494 }
495
496 static int make_rpc_reply(char *inbuf, char *q, int data_len)
497 {
498         uint32 callid = IVAL(inbuf, 12);
499         RPC_HDR hdr;
500
501         DEBUG(5,("make_rpc_reply.  callid: %x\n", callid));
502
503         create_rpc_reply(&hdr, callid, data_len);
504         return PTR_DIFF(smb_io_rpc_hdr(False, &hdr, q, q, 4), q);
505 }
506
507 static int lsa_reply_open_policy(char *q, char *base)
508 {
509         int i;
510         LSA_R_OPEN_POL r_o;
511
512         static char handle[20] =
513         { 0x00, 0x00, 0x00, 0x00,
514       0x2f, 0x79, 0x0a, 0x81,
515       0xd5, 0x17, 0xd1, 0x11,
516       0x80, 0xaf, 0x96, 0xcd,
517       0x50, 0xf8, 0xbc, 0x6c
518     };
519         /* set up the LSA QUERY INFO response */
520         /* bzero(&(r_o.pol.data), POL_HND_SIZE); */
521         for (i = 0; i < POL_HND_SIZE; i++)
522         {
523                 r_o.pol.data[i] = handle[i];
524         }
525         r_o.status = 0x0;
526
527         /* store the response in the SMB stream */
528         q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0);
529
530         /* return length of SMB data stored */
531         return PTR_DIFF(q, base); 
532 }
533
534 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
535 {
536         hdr->uni_max_len = max_len;
537         hdr->uni_str_len = len;
538         hdr->undoc       = terminate;
539 }
540
541 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
542 {
543         make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
544         hdr->undoc_buffer = len > 0 ? 1 : 0;
545 }
546
547 static void make_unistr(UNISTR *str, char *buf)
548 {
549         /* store the string (null-terminated copy) */
550         PutUniCode((char *)(str->buffer), buf);
551 }
552
553 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
554 {
555         /* set up string lengths. add one if string is not null-terminated */
556         str->uni_max_len = len + (terminate != 0 ? 1 : 0);
557         str->undoc       = 0;
558         str->uni_str_len = len;
559
560         /* store the string (null-terminated copy) */
561         PutUniCode((char *)str->buffer, buf);
562
563         /* overwrite the last character: some strings are terminated with 4 not 0 */
564         str->buffer[len] = (uint16)terminate;
565 }
566
567 static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
568 {
569         rid2->type    = 0x5;
570         rid2->undoc   = 0x5;
571         rid2->rid     = rid;
572         rid2->rid_idx = 0;
573 }
574
575 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
576 {
577         int len_sid_str = strlen(sid_str);
578
579         sid2->type = 0x5;
580         sid2->undoc = 0;
581         make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
582         make_unistr  (&(sid2->str), sid_str);
583 }
584
585 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
586 {
587         int domlen = strlen(dom_name);
588
589         d_q->uni_dom_max_len = domlen * 2;
590         d_q->padding = 0;
591         d_q->uni_dom_str_len = domlen * 2;
592
593         d_q->buffer_dom_name = 0; /* domain buffer pointer */
594         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
595
596         /* NOT null-terminated: 4-terminated instead! */
597         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
598
599         make_dom_sid(&(d_q->dom_sid), dom_sid);
600 }
601
602 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
603                                 char *dom_name, char *dom_sid)
604 {
605         LSA_R_QUERY_INFO r_q;
606
607         /* set up the LSA QUERY INFO response */
608
609         r_q.undoc_buffer = 1; /* not null */
610         r_q.info_class = q_q->info_class;
611
612         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
613
614         r_q.status = 0x0;
615
616         /* store the response in the SMB stream */
617         q = lsa_io_r_query(False, &r_q, q, base, 4, 0);
618
619         /* return length of SMB data stored */
620         return PTR_DIFF(q, base); 
621 }
622
623 /* pretty much hard-coded choice of "other" sids, unfortunately... */
624 static void make_dom_ref(DOM_R_REF *ref,
625                                 char *dom_name, char *dom_sid,
626                                 char *other_sid1, char *other_sid2, char *other_sid3)
627 {
628         int len_dom_name   = strlen(dom_name);
629         int len_other_sid1 = strlen(other_sid1);
630         int len_other_sid2 = strlen(other_sid2);
631         int len_other_sid3 = strlen(other_sid3);
632
633         ref->undoc_buffer = 1;
634         ref->num_ref_doms_1 = 4;
635         ref->buffer_dom_name = 1;
636         ref->max_entries = 32;
637         ref->num_ref_doms_2 = 4;
638
639         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
640         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
641         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
642         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
643
644         if (dom_name != NULL)
645         {
646                 make_unistr(&(ref->uni_dom_name), dom_name);
647         }
648
649         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
650         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
651         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
652         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
653 }
654
655 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
656                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
657                                 char *dom_name, char *dom_sid,
658                                 char *other_sid1, char *other_sid2, char *other_sid3)
659 {
660         int i;
661
662         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
663                      other_sid1, other_sid2, other_sid3);
664
665         r_l->num_entries = num_entries;
666         r_l->undoc_buffer = 1;
667         r_l->num_entries2 = num_entries;
668
669         for (i = 0; i < num_entries; i++)
670         {
671                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
672         }
673
674         r_l->num_entries3 = num_entries;
675 }
676
677 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
678                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
679                                 char *dom_name, char *dom_sid,
680                                 char *other_sid1, char *other_sid2, char *other_sid3)
681 {
682         int i;
683
684         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
685                      other_sid1, other_sid2, other_sid3);
686
687         r_l->num_entries = num_entries;
688         r_l->undoc_buffer = 1;
689         r_l->num_entries2 = num_entries;
690
691         for (i = 0; i < num_entries; i++)
692         {
693                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
694         }
695
696         r_l->num_entries3 = num_entries;
697 }
698
699 static int lsa_reply_lookup_sids(char *q, char *base,
700                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
701                                 char *dom_name, char *dom_sid,
702                                 char *other_sid1, char *other_sid2, char *other_sid3)
703 {
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 PTR_DIFF(q, base); 
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         LSA_R_LOOKUP_RIDS r_l;
724
725         /* set up the LSA Lookup RIDs response */
726         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
727                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
728         r_l.status = 0x0;
729
730         /* store the response in the SMB stream */
731         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0);
732
733         /* return length of SMB data stored */
734         return PTR_DIFF(q, base); 
735 }
736
737 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c,
738                                 DOM_CHAL *srv_chal, int status)
739 {
740         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data));
741         r_c->status = status;
742 }
743
744 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
745                                         DOM_CHAL *srv_chal)
746 {
747         LSA_R_REQ_CHAL r_c;
748
749         /* set up the LSA REQUEST CHALLENGE response */
750
751         make_lsa_r_req_chal(&r_c, srv_chal, 0);
752
753         /* store the response in the SMB stream */
754         q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0);
755
756         /* return length of SMB data stored */
757         return PTR_DIFF(q, base); 
758 }
759
760 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
761                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
762 {
763         memcpy(  r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
764         memcpy(&(r_a->srv_flgs)    , flgs           , sizeof(r_a->srv_flgs));
765         r_a->status = status;
766 }
767
768 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
769                                 DOM_CHAL *resp_cred, int status)
770 {
771         LSA_R_AUTH_2 r_a;
772
773         /* set up the LSA AUTH 2 response */
774
775         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
776
777         /* store the response in the SMB stream */
778         q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0);
779
780         /* return length of SMB data stored */
781         return PTR_DIFF(q, base); 
782 }
783
784 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
785                              DOM_CRED *srv_cred, int status)  
786 {
787         memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred));
788         r_a->status = status;
789 }
790
791 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
792                                 DOM_CRED *srv_cred, int status)
793 {
794         LSA_R_SRV_PWSET r_s;
795
796         /* set up the LSA Server Password Set response */
797         make_lsa_r_srv_pwset(&r_s, srv_cred, status);
798
799         /* store the response in the SMB stream */
800         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0);
801
802         /* return length of SMB data stored */
803         return PTR_DIFF(q, base); 
804 }
805
806 static void make_lsa_user_info(LSA_USER_INFO *usr,
807
808         NTTIME *logon_time,
809         NTTIME *logoff_time,
810         NTTIME *kickoff_time,
811         NTTIME *pass_last_set_time,
812         NTTIME *pass_can_change_time,
813         NTTIME *pass_must_change_time,
814
815         char *user_name,
816         char *full_name,
817         char *logon_script,
818         char *profile_path,
819         char *home_dir,
820         char *dir_drive,
821
822         uint16 logon_count,
823         uint16 bad_pw_count,
824
825         uint32 user_id,
826         uint32 group_id,
827         uint32 num_groups,
828         DOM_GID *gids,
829         uint32 user_flgs,
830
831         char sess_key[16],
832
833         char *logon_srv,
834         char *logon_dom,
835
836         char *dom_sid,
837         char *other_sids) /* space-delimited set of SIDs */ 
838 {
839         /* only cope with one "other" sid, right now. */
840         /* need to count the number of space-delimited sids */
841         int i;
842         int num_other_sids = other_sids != NULL ? 1 : 0;
843
844         int len_user_name    = strlen(user_name   );
845         int len_full_name    = strlen(full_name   );
846         int len_logon_script = strlen(logon_script);
847         int len_profile_path = strlen(profile_path);
848         int len_home_dir     = strlen(home_dir    );
849         int len_dir_drive    = strlen(dir_drive   );
850
851         int len_logon_srv    = strlen(logon_srv);
852         int len_logon_dom    = strlen(logon_dom);
853
854         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
855
856         usr->logon_time            = *logon_time;
857         usr->logoff_time           = *logoff_time;
858         usr->kickoff_time          = *kickoff_time;
859         usr->pass_last_set_time    = *pass_last_set_time;
860         usr->pass_can_change_time  = *pass_can_change_time;
861         usr->pass_must_change_time = *pass_must_change_time;
862
863         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
864         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
865         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
866         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
867         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
868         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
869
870         usr->logon_count = logon_count;
871         usr->bad_pw_count = bad_pw_count;
872
873         usr->user_id = user_id;
874         usr->group_id = group_id;
875         usr->num_groups = num_groups;
876         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
877         usr->user_flgs = user_flgs;
878
879         if (sess_key != NULL)
880         {
881                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
882         }
883         else
884         {
885                 bzero(usr->sess_key, sizeof(usr->sess_key));
886         }
887
888         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
889         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
890
891         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
892
893         bzero(usr->padding, sizeof(usr->padding));
894
895         usr->num_other_sids = num_other_sids;
896         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
897         
898         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
899         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
900         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
901         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
902         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
903         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
904
905         usr->num_groups2 = num_groups;
906         for (i = 0; i < num_groups; i++)
907         {
908                 usr->gids[i] = gids[i];
909         }
910
911         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
912         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
913
914         make_dom_sid(&(usr->dom_sid), dom_sid);
915         make_dom_sid(&(usr->other_sids[0]), other_sids);
916 }
917
918
919 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
920                                 DOM_CRED *srv_cred, LSA_USER_INFO *user_info)
921 {
922         LSA_R_SAM_LOGON r_s;
923
924         /* XXXX maybe we want to say 'no', reject the client's credentials */
925         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
926         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
927
928         /* store the user information, if there is any. */
929         r_s.user = user_info;
930         r_s.buffer_user = user_info != NULL ? 1 : 0;
931         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
932
933         /* store the response in the SMB stream */
934         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0);
935
936         /* return length of SMB data stored */
937         return PTR_DIFF(q, base); 
938 }
939
940
941 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
942                                 DOM_CRED *srv_cred, 
943                                 uint32 status)
944 {
945         LSA_R_SAM_LOGOFF r_s;
946
947         /* XXXX maybe we want to say 'no', reject the client's credentials */
948         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
949         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
950
951         r_s.status = status;
952
953         /* store the response in the SMB stream */
954         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0);
955
956         /* return length of SMB data stored */
957         return PTR_DIFF(q, base); 
958 }
959
960
961 static void api_lsa_open_policy( char *param, char *data,
962                              char **rdata, int *rdata_len )
963 {
964         /* we might actually want to decode the query, but it's not necessary */
965         /* lsa_io_q_open_policy(...); */
966
967         /* construct a 20 byte policy handle. return length*/
968         *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata);
969 }
970
971 static int api_lsa_query_info( char *param, char *data,
972                                 char **rdata, int *rdata_len )
973 {
974         LSA_Q_QUERY_INFO q_i;
975         pstring dom_name;
976         pstring dom_sid;
977
978         /* grab the info class and policy handle */
979         lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4, 0);
980
981         pstrcpy(dom_name, lp_workgroup());
982         pstrcpy(dom_sid , lp_domainsid());
983
984         /* construct reply.  return status is always 0x0 */
985         return lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, 
986                                                                          dom_name, dom_sid);
987 }
988
989 static void api_lsa_lookup_sids( char *param, char *data,
990                                  char **rdata, int *rdata_len )
991 {
992         int i;
993         LSA_Q_LOOKUP_SIDS q_l;
994         pstring dom_name;
995         pstring dom_sid;
996         fstring dom_sids[MAX_LOOKUP_SIDS];
997
998         /* grab the info class and policy handle */
999         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1000
1001         pstrcpy(dom_name, lp_workgroup());
1002         pstrcpy(dom_sid , lp_domainsid());
1003
1004         /* convert received SIDs to strings, so we can do them. */
1005         for (i = 0; i < q_l.num_entries; i++)
1006         {
1007                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1008         }
1009
1010         /* construct reply.  return status is always 0x0 */
1011         *rdata_len =  lsa_reply_lookup_sids(*rdata + 0x18, *rdata,
1012                     q_l.num_entries, dom_sids, /* text-converted SIDs */
1013                                 dom_name, dom_sid, /* domain name, domain SID */
1014                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1015 }
1016
1017 static void api_lsa_lookup_names( char *param, char *data,
1018                                   char **rdata, int *rdata_len )
1019 {
1020         int i;
1021         LSA_Q_LOOKUP_RIDS q_l;
1022         pstring dom_name;
1023         pstring dom_sid;
1024         uint32 dom_rids[MAX_LOOKUP_SIDS];
1025
1026         /* grab the info class and policy handle */
1027         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1028
1029         pstrcpy(dom_name, lp_workgroup());
1030         pstrcpy(dom_sid , lp_domainsid());
1031
1032         /* convert received RIDs to strings, so we can do them. */
1033         for (i = 0; i < q_l.num_entries; i++)
1034         {
1035                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1036                 dom_rids[i] = name_to_rid(user_name);
1037         }
1038
1039         /* construct reply.  return status is always 0x0 */
1040         *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata,
1041                     q_l.num_entries, dom_rids, /* text-converted SIDs */
1042                                 dom_name, dom_sid, /* domain name, domain SID */
1043                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1044 }
1045
1046 BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
1047                      int mdrcnt,int mprcnt,
1048                      char **rdata,char **rparam,
1049                      int *rdata_len,int *rparam_len)
1050 {
1051         uint16 opnum = SVAL(data,22);
1052
1053         int pkttype = CVAL(data, 2);
1054         if (pkttype == 0x0b) /* RPC BIND */
1055         {
1056                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1057                 LsarpcTNP1(data,rdata,rdata_len);
1058                 return True;
1059         }
1060
1061         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1062         switch (opnum)
1063         {
1064                 case LSA_OPENPOLICY:
1065                 {
1066                         DEBUG(3,("LSA_OPENPOLICY\n"));
1067                         api_lsa_open_policy(param, data, rdata, rdata_len);
1068                         make_rpc_reply(data, *rdata, *rdata_len);
1069
1070                         break;
1071                 }
1072
1073                 case LSA_QUERYINFOPOLICY:
1074                 {
1075                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
1076
1077                         api_lsa_query_info(param, data, rdata, rdata_len);
1078                         make_rpc_reply(data, *rdata, *rdata_len);
1079
1080                         break;
1081                 }
1082
1083                 case LSA_ENUMTRUSTDOM:
1084                 {
1085                         char *q = *rdata + 0x18;
1086
1087                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
1088
1089                         initrpcreply(data, *rdata);
1090
1091                         SIVAL(q, 0, 0); /* enumeration context */
1092                         SIVAL(q, 0, 4); /* entries read */
1093                         SIVAL(q, 0, 8); /* trust information */
1094
1095                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1096
1097                         break;
1098                 }
1099
1100                 case LSA_CLOSE:
1101                 {
1102                         char *q = *rdata + 0x18;
1103
1104                         DEBUG(3,("LSA_CLOSE\n"));
1105
1106                         initrpcreply(data, *rdata);
1107
1108                         SIVAL(q, 0, 0);
1109                         SIVAL(q, 0, 4);
1110                         SIVAL(q, 0, 8);
1111                         SIVAL(q, 0, 12);
1112                         SIVAL(q, 0, 16);
1113
1114                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1115
1116                         break;
1117                 }
1118
1119                 case LSA_OPENSECRET:
1120                 {
1121                         char *q = *rdata + 0x18;
1122                         DEBUG(3,("LSA_OPENSECRET\n"));
1123
1124                         initrpcreply(data, *rdata);
1125
1126                         SIVAL(q, 0, 0);
1127                         SIVAL(q, 0, 4);
1128                         SIVAL(q, 0, 8);
1129                         SIVAL(q, 0, 12);
1130                         SIVAL(q, 0, 16);
1131
1132                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1133
1134                         break;
1135                 }
1136
1137                 case LSA_LOOKUPSIDS:
1138                 {
1139                         DEBUG(3,("LSA_OPENSECRET\n"));
1140                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
1141                         make_rpc_reply(data, *rdata, *rdata_len);
1142
1143                         break;
1144                 }
1145
1146                 case LSA_LOOKUPNAMES:
1147                 {
1148                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
1149                         api_lsa_lookup_names(param, data, rdata, rdata_len);
1150                         make_rpc_reply(data, *rdata, *rdata_len);
1151
1152                         break;
1153                 }
1154
1155                 default:
1156                 {
1157                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1158                         break;
1159                 }
1160         }
1161         return True;
1162 }
1163
1164 static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct)
1165 {
1166     struct smb_passwd *smb_pass = get_smbpwnam(mach_acct);
1167         int i;
1168
1169         if (smb_pass != NULL)
1170         {
1171                 memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw));
1172         }
1173         else
1174         {
1175                 /* No such machine account. Should error out here, but we'll
1176                    print and carry on */
1177                 DEBUG(1,("No account in domain for %s\n", mach_acct));
1178                 return False;
1179         }
1180
1181         {
1182                 char foo[16];
1183                 for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]);
1184                 DEBUG(4,("pass %s %s\n", mach_acct, foo));
1185         }
1186
1187         /* from client / server challenges and md4 password, generate sess key */
1188         cred_session_key(&(dc->clnt_chal), &(dc->srv_chal),
1189                            dc->md4pw, dc->sess_key);
1190
1191         /* copy the client credentials for later use */
1192         memcpy(dc->srv_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
1193         memcpy(dc->srv_cred.data, clnt_chal->data, sizeof(clnt_chal->data));
1194
1195         /* create a server challenge for the client */
1196         /* PAXX: set these to random values. */
1197         /* lkcl: paul, you mentioned that it doesn't really matter much */
1198         for (i = 0; i < 8; i++)
1199         {
1200                 dc->srv_chal.data[i] = 0xA5;
1201         }
1202
1203         return True;
1204 }
1205
1206 static void api_lsa_req_chal( user_struct *vuser,
1207                               char *param, char *data,
1208                               char **rdata, int *rdata_len )
1209 {
1210         int reply_len;
1211
1212         LSA_Q_REQ_CHAL q_r;
1213
1214         fstring mach_acct;
1215
1216         /* grab the challenge... */
1217         lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4, 0);
1218
1219         fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer));
1220
1221         strcat(mach_acct, "$");
1222
1223         update_dcinfo(&(vuser->dc), &(q_r.clnt_chal), mach_acct);
1224
1225         /* construct reply.  return status is always 0x0 */
1226         reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18,
1227                                         &(vuser->dc.srv_chal));
1228
1229         /* construct header, now that we know the reply length */
1230         reply_len += make_rpc_reply(data, *rdata, reply_len);
1231
1232         *rdata_len = reply_len;
1233 }
1234
1235 static void api_lsa_auth_2( user_struct *vuser,
1236                             char *param, char *data,
1237                             char **rdata, int *rdata_len )
1238 {
1239         int reply_len;
1240         LSA_Q_AUTH_2 q_a;
1241
1242         DOM_CHAL srv_chal;
1243         UTIME srv_time;
1244
1245         srv_time.time = 0;
1246
1247         /* grab the challenge... */
1248         lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4, 0);
1249
1250         /* check that the client credentials are valid */
1251         cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
1252                 &(vuser->dc.srv_cred), srv_time);
1253
1254         /* create server credentials for inclusion in the reply */
1255         cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal);
1256
1257         /* construct reply.  */
1258         reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18,
1259                                         &srv_chal, 0x0);
1260
1261         /* construct header, now that we know the reply length */
1262         reply_len += make_rpc_reply(data, *rdata, reply_len);
1263
1264         *rdata_len = reply_len;
1265 }
1266
1267
1268 static BOOL deal_with_credentials(user_struct *vuser,
1269                         DOM_CRED *clnt_cred, DOM_CRED *srv_cred)
1270 {
1271         UTIME new_clnt_time;
1272
1273         /* doesn't matter that server time is 0 */
1274         srv_cred->timestamp.time = 0;
1275
1276         /* check that the client credentials are valid */
1277         if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key,
1278                     &(vuser->dc.srv_cred), clnt_cred->timestamp))
1279         {
1280                 return False;
1281         }
1282
1283         /* increment client time by one second */
1284         new_clnt_time.time = clnt_cred->timestamp.time + 1;
1285
1286         /* create server credentials for inclusion in the reply */
1287         cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time,
1288                     &(srv_cred->challenge));
1289
1290         /* update the client and server credentials, for use next time... */
1291         *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time );
1292
1293         return True;
1294 }
1295
1296 static void api_lsa_srv_pwset( user_struct *vuser,
1297                                char *param, char *data,
1298                                char **rdata, int *rdata_len )
1299 {
1300         int reply_len;
1301         LSA_Q_SRV_PWSET q_a;
1302
1303         DOM_CRED srv_cred;
1304
1305         /* grab the challenge and encrypted password ... */
1306         lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4, 0);
1307
1308         /* checks and updates credentials.  creates reply credentials */
1309         deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred);
1310
1311         /* construct reply.  always indicate failure.  nt keeps going... */
1312         reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18,
1313                                         &srv_cred,
1314                         NT_STATUS_WRONG_PASSWORD|0xC000000);
1315
1316         /* construct header, now that we know the reply length */
1317         reply_len += make_rpc_reply(data, *rdata, reply_len);
1318
1319         *rdata_len = reply_len;
1320 }
1321
1322
1323 static void api_lsa_sam_logoff( user_struct *vuser,
1324                                char *param, char *data,
1325                                char **rdata, int *rdata_len )
1326 {
1327         int reply_len;
1328         LSA_Q_SAM_LOGOFF q_l;
1329
1330         DOM_CRED srv_cred;
1331
1332         /* grab the challenge... */
1333         lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1334
1335         /* checks and updates credentials.  creates reply credentials */
1336         deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred);
1337
1338         /* construct reply.  always indicate success */
1339         reply_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata + 0x18,
1340                                         &srv_cred,
1341                         0x0);
1342
1343         /* construct header, now that we know the reply length */
1344         reply_len += make_rpc_reply(data, *rdata, reply_len);
1345
1346         *rdata_len = reply_len;
1347 }
1348
1349
1350 static void api_lsa_sam_logon( user_struct *vuser,
1351                                char *param, char *data,
1352                                char **rdata, int *rdata_len )
1353 {
1354         int reply_len;
1355         LSA_Q_SAM_LOGON q_l;
1356         LSA_USER_INFO usr_info;
1357         LSA_USER_INFO *p_usr_info = NULL;
1358
1359         DOM_CRED srv_creds;
1360
1361         lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4, 0);
1362
1363         /* checks and updates credentials.  creates reply credentials */
1364         deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds);
1365
1366         if (vuser != NULL)
1367         {
1368                 NTTIME dummy_time;
1369                 pstring logon_script;
1370                 pstring profile_path;
1371                 pstring home_dir;
1372                 pstring home_drive;
1373                 pstring my_name;
1374                 pstring my_workgroup;
1375                 pstring dom_sid;
1376                 pstring username;
1377                 extern pstring myname;
1378
1379                 dummy_time.low  = 0xffffffff;
1380                 dummy_time.high = 0x7fffffff;
1381
1382                 get_myname(myname, NULL);
1383
1384                 pstrcpy(logon_script, lp_logon_script());
1385                 pstrcpy(profile_path, lp_logon_path  ());
1386                 pstrcpy(dom_sid     , lp_domainsid   ());
1387                 pstrcpy(my_workgroup, lp_workgroup   ());
1388
1389                 pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer));
1390                 pstrcpy(my_name     , myname           );
1391                 strupper(my_name);
1392
1393                 pstrcpy(home_drive  , "a:"             );
1394
1395 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1396                 pstrcpy(home_dir    , vuser->home_share);
1397 #else
1398                 pstrcpy(home_dir    , "\\\\%L\\%U");
1399                 standard_sub_basic(home_dir);
1400 #endif
1401
1402                 p_usr_info = &usr_info;
1403
1404                 make_lsa_user_info(p_usr_info,
1405
1406                                &dummy_time, /* logon_time */
1407                                &dummy_time, /* logoff_time */
1408                                &dummy_time, /* kickoff_time */
1409                                &dummy_time, /* pass_last_set_time */
1410                                &dummy_time, /* pass_can_change_time */
1411                                &dummy_time, /* pass_must_change_time */
1412
1413                                username, /* user_name */
1414                                vuser->real_name, /* full_name */
1415                                logon_script, /* logon_script */
1416                                profile_path, /* profile_path */
1417                                home_dir, /* home_dir */
1418                                home_drive, /* dir_drive */
1419
1420                                0, /* logon_count */
1421                                0, /* bad_pw_count */
1422
1423                                vuser->uid, /* uint32 user_id */
1424                                vuser->gid, /* uint32 group_id */
1425                                0,    /* uint32 num_groups */
1426                                NULL, /* DOM_GID *gids */
1427                                0x20, /* uint32 user_flgs */
1428
1429                                NULL, /* char sess_key[16] */
1430
1431                                my_name, /* char *logon_srv */
1432                                my_workgroup, /* char *logon_dom */
1433
1434                                dom_sid, /* char *dom_sid */
1435                                NULL); /* char *other_sids */
1436         }
1437
1438         reply_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata + 0x18,
1439                                         &srv_creds, p_usr_info);
1440
1441         /* construct header, now that we know the reply length */
1442         reply_len += make_rpc_reply(data, *rdata, reply_len);
1443
1444         *rdata_len = reply_len;
1445 }
1446
1447
1448 #if 0
1449 case LSASAMLOGON:
1450         DEBUG(1,("LSASAMLOGON\n"));
1451         dump_data(1,data,128);
1452         q = data + 0x18;
1453         logonsrv = q + 16;
1454         DEBUG(1,("SMLOG %d\n", __LINE__));
1455         q = skip_unicode_string(logonsrv,1)+16;
1456         q = align4(q, data);
1457         unicomp = q;
1458         q = skip_unicode_string(unicomp,1)+4;
1459         DEBUG(1,("SMLOG %d  logonsrv=%s unicomp=%s\n", 
1460                  __LINE__, unistr(logonsrv), unistr(unicomp)));
1461         q = align4(q, data);
1462         rcvcred[0] = qIVAL;
1463         DEBUG(1,("SMLOG %d\n", __LINE__));
1464         rcvcred[1] = qIVAL;
1465         DEBUG(1,("SMLOG %d\n", __LINE__));
1466         clnttime = qIVAL;
1467         checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1468         q += 2;
1469         rtncred[0] = qIVAL; /* all these are ignored */
1470         DEBUG(1,("SMLOG %d\n", __LINE__));
1471         rtncred[1] = qIVAL;
1472         rtntime = qIVAL;
1473         logonlevel = qSVAL;
1474         DEBUG(1,("SMLOG %d\n", __LINE__));
1475         switchval = qSVAL;
1476         switch (switchval)
1477                 {
1478                 case 1:
1479                         
1480                         q += 6;
1481                         domlen = qSVAL;
1482                         dommaxlen = qSVAL; q += 4;
1483                         paramcontrol = qIVAL;
1484                         logonid[0] = qIVAL; /* low part */
1485                         logonid[1] = qIVAL; /* high part */
1486                         
1487                         usernamelen = qSVAL;
1488                         
1489                         DEBUG(1,("SMLOG %d\n", __LINE__));
1490                         usernamemaxlen = qSVAL; q += 4;
1491                         
1492                         DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", 
1493                                  usernamelen, usernamemaxlen, dommaxlen));
1494                         
1495                         dump_data(1,q,128);
1496                         
1497                         wslen = qSVAL;
1498                         wsmaxlen = qSVAL; q += 4;
1499                         rc4lmowfpass = q; q += 16;
1500                         rc4ntowfpass = q; q += 16;
1501                         
1502                         q += 12; domain = q; q += dommaxlen + 12;
1503                         q = align4(q, data);
1504                         username = q; q += usernamemaxlen + 12; 
1505                         q = align4(q, data);
1506                         ws = q;
1507                         DEBUG(1,("domain=%s username=%s ws=%s\n",
1508                                  unistr(domain), unistr(username),
1509                                  unistr(ws)));
1510                         break;
1511                 default: 
1512                         DEBUG(0,("unknown switch in SAMLOGON %d\n",
1513                                  switchval));
1514                 }
1515         for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]);
1516         DEBUG(1,("userNAME %s  [%s]\n", foo, username));
1517         DEBUG(1,("SMLOG %d\n", __LINE__));
1518         q = *rdata + 0x18;
1519         qSIVAL(0x16a4b4); /* magic buffer pointer ? */
1520         makecred(cnum, clnttime+1, q);
1521         dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1522         q += 8;
1523         qSIVAL(0); /* timestamp. client doesn't care */
1524         qSSVAL(3); /* switch value 3. May be others? */
1525         qSSVAL(0); /* undocumented */
1526         DEBUG(1,("SMLOG %d\n", __LINE__));
1527         
1528         memset(rc4key, 0, sizeof rc4key);
1529         SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]);
1530         SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]);
1531         for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]);
1532         DEBUG(1,("rc4ntowf %s\n", foo));
1533         arcfour_init(&c, rc4key, sizeof rc4key);
1534         arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass);
1535         for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]);
1536         DEBUG(1,("ntowf %s\n", foo));
1537         
1538         if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) {
1539                 qSIVAL(0); /* no buffer */
1540                 qSCVAL(1); /* Authoratitive. Change if passthrough? */
1541                 qSCVAL(0); /* pad for above boolean */
1542                 qSSVAL(0); /* pad for above boolean */
1543                 
1544                 endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len);
1545                 break;
1546         }
1547
1548         qSIVAL(2); /* another magic bufptr? */
1549   DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo));
1550   qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]);
1551   qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]);
1552   DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1]));
1553   qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]);
1554   qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]);
1555   qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]);
1556   qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]);
1557   DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename));
1558   qunihdr(userinfo->effectivename);
1559   qunihdr(userinfo->fullname);
1560   DEBUG(1,("SMLOG %d\n", __LINE__));
1561   qunihdr(userinfo->logonscript);
1562   qunihdr(userinfo->profilepath);
1563   qunihdr(userinfo->homedirectory);
1564   qunihdr(userinfo->homedirectorydrive);
1565   DEBUG(1,("SMLOG %d\n", __LINE__));
1566   qSSVAL(userinfo->logoncount);
1567   qSSVAL(userinfo->badpwcount);
1568   qSIVAL(userinfo->uid);
1569   qSIVAL(userinfo->gid);
1570   DEBUG(1,("SMLOG %d\n", __LINE__));
1571   qSIVAL(userinfo->ngroups);
1572   qSIVAL(8); /* ptr to groups */
1573   qSIVAL(userinfo->userflags);
1574   DEBUG(1,("SMLOG %d\n", __LINE__));
1575   qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */
1576   qunihdr(userinfo->logonserver);
1577   qunihdr(userinfo->logondomain);
1578   DEBUG(1,("SMLOG %d\n", __LINE__));
1579   qSIVAL(2); /* logon domain id ptr */
1580   DEBUG(1,("SMLOG %d\n", __LINE__));
1581   memset(q,0,40); q += 40; /* expansion room */
1582   DEBUG(1,("SMLOG %d\n", __LINE__));
1583   qSIVAL(userinfo->nsids);
1584   DEBUG(1,("SMLOG %d\n", __LINE__));
1585   qSIVAL(0); /* ptr to sids and values */
1586   DEBUG(1,("SMLOG %d\n", __LINE__));
1587   qunistr(userinfo->effectivename);
1588   DEBUG(1,("SMLOG %d\n", __LINE__));
1589   qunistr(userinfo->fullname);
1590   DEBUG(1,("SMLOG %d\n", __LINE__));
1591   qunistr(userinfo->logonscript);
1592   DEBUG(1,("SMLOG %d\n", __LINE__));
1593   qunistr(userinfo->profilepath);
1594   qunistr(userinfo->homedirectory);
1595   qunistr(userinfo->homedirectorydrive);
1596   DEBUG(1,("SMLOG %d\n", __LINE__));
1597   qSIVAL(userinfo->ngroups);
1598   for (i = 0; i < userinfo->ngroups; i++)
1599   {
1600         qSIVAL(userinfo->groups[i].gid);
1601         qSIVAL(userinfo->groups[i].attr);
1602   }
1603   qunistr(userinfo->logonserver);
1604   qunistr(userinfo->logondomain);
1605   for (i = 0; i < userinfo->nsids; i++)
1606   {
1607         /* put the extra sids: PAXX: TODO */
1608   }
1609   /* Assumption. This is the only domain, sending our SID */
1610   /* PAXX: may want to do passthrough later */
1611   strcpy(domsid,lp_domainsid());
1612 DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1613   /* assume, but should check, that domsid starts "S-" */
1614   p = strtok(domsid+2,"-");
1615   revision = atoi(p);
1616 DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1617   identauth = atoi(strtok(0,"-"));
1618 DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1619   numsubauths = 0;
1620   while (p = strtok(0, "-"))
1621         subauths[numsubauths++] = atoi(p);
1622   qSIVAL(numsubauths);
1623   qSCVAL(revision);
1624   qSCVAL(numsubauths);
1625   qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */
1626   qRSIVAL(identauth); /* next 4 bytes */
1627   DEBUG(1,("SMLOG %d\n", __LINE__));
1628   for (i = 0; i < numsubauths; i++)
1629   {
1630         qSIVAL(subauths[i]);
1631   }
1632   qSCVAL(1); /* Authoratitive. Change if passthrough? */
1633   qSCVAL(0); /* pad for above boolean */
1634   qSSVAL(0); /* pad for above boolean */
1635
1636   endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1637   break;
1638 #endif
1639
1640 BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
1641                      int mdrcnt,int mprcnt,
1642                      char **rdata,char **rparam,
1643                      int *rdata_len,int *rparam_len)
1644 {
1645         uint16 opnum;
1646         char pkttype;
1647         user_struct *vuser;
1648
1649         DEBUG(5,("api_netlogrpcTNP data:%x\n", data));
1650
1651         if (data == NULL) return False;
1652
1653         opnum = SVAL(data,22);
1654         pkttype = CVAL(data, 2);
1655
1656         if (pkttype == 0x0b) /* RPC BIND */
1657         {
1658                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1659                 LsarpcTNP1(data,rdata,rdata_len);
1660                 return True;
1661         }
1662
1663         DEBUG(4,("netlogon TransactNamedPipe op %x\n", opnum));
1664
1665         if ((vuser = get_valid_user_struct(uid)) == NULL) return False;
1666
1667         DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name));
1668 #if defined(NETGROUP) && defined(AUTOMOUNT)
1669         DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1670 #endif
1671
1672         switch (opnum)
1673         {
1674                 case LSA_REQCHAL:
1675                 {
1676                         DEBUG(3,("LSA_REQCHAL\n"));
1677                         api_lsa_req_chal(vuser, param, data, rdata, rdata_len);
1678                         break;
1679                 }
1680
1681                 case LSA_AUTH2:
1682                 {
1683                         DEBUG(3,("LSA_AUTH2\n"));
1684                         api_lsa_auth_2(vuser, param, data, rdata, rdata_len);
1685                         break;
1686                 }
1687
1688                 case LSA_SRVPWSET:
1689                 {
1690                         DEBUG(3,("LSA_SRVPWSET\n"));
1691                         api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len);
1692                         break;
1693                 }
1694
1695                 case LSA_SAMLOGON:
1696                 {
1697                         DEBUG(3,("LSA_SAMLOGON\n"));
1698                         api_lsa_sam_logon(vuser, param, data, rdata, rdata_len);
1699                         break;
1700                 }
1701
1702                 case LSA_SAMLOGOFF:
1703                 {
1704                         DEBUG(3,("LSA_SAMLOGOFF\n"));
1705                         api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len);
1706                         break;
1707                 }
1708
1709                 default:
1710                 {
1711                         DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
1712                         break;
1713                 }
1714         }
1715
1716         return True;
1717 }
1718
1719 #endif /* NTDOMAIN */