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