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