5a6da643d98e3342fd795679682fa8b2b9b55812
[kai/samba.git] / source3 / smbd / pipes.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Pipe SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1997,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
7    Copyright (C) Paul Ashton  1997.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 /*
24    This file handles reply_ calls on named pipes that the server
25    makes to handle specific protocols
26 */
27
28
29 #include "includes.h"
30 #include "trans2.h"
31 #include "nterr.h"
32
33 #define PIPE            "\\PIPE\\"
34 #define PIPELEN         strlen(PIPE)
35
36 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
37
38 /* look in server.c for some explanation of these variables */
39 extern int Protocol;
40 extern int DEBUGLEVEL;
41 extern int chain_fnum;
42 extern char magic_char;
43 extern connection_struct Connections[];
44 extern files_struct Files[];
45 extern BOOL case_sensitive;
46 extern pstring sesssetup_user;
47 extern int Client;
48 extern fstring myworkgroup;
49
50 /* this macro should always be used to extract an fnum (smb_fid) from
51 a packet to ensure chaining works correctly */
52 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
53
54 char * known_pipes [] =
55 {
56   "lsarpc",
57 #if NTDOMAIN
58   "NETLOGON",
59 #endif
60   NULL
61 };
62
63 /****************************************************************************
64   reply to an open and X on a named pipe
65
66   In fact what we do is to open a regular file with the same name in
67   /tmp. This can then be closed as normal. Reading and writing won't
68   make much sense, but will do *something*. The real reason for this
69   support is to be able to do transactions on them (well, on lsarpc
70   for domain login purposes...).
71
72   This code is basically stolen from reply_open_and_X with some
73   wrinkles to handle pipes.
74 ****************************************************************************/
75 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
76 {
77   pstring fname;
78   int cnum = SVAL(inbuf,smb_tid);
79   int fnum = -1;
80   int smb_mode = SVAL(inbuf,smb_vwv3);
81   int smb_attr = SVAL(inbuf,smb_vwv5);
82 #if 0
83   int open_flags = SVAL(inbuf,smb_vwv2);
84   int smb_sattr = SVAL(inbuf,smb_vwv4); 
85   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
86 #endif
87   int smb_ofun = SVAL(inbuf,smb_vwv8);
88   int unixmode;
89   int size=0,fmode=0,mtime=0,rmode=0;
90   struct stat sbuf;
91   int smb_action = 0;
92   int i;
93   BOOL bad_path = False;
94
95   /* XXXX we need to handle passed times, sattr and flags */
96   pstrcpy(fname,smb_buf(inbuf));
97
98   /* If the name doesn't start \PIPE\ then this is directed */
99   /* at a mailslot or something we really, really don't understand, */
100   /* not just something we really don't understand. */
101   if ( strncmp(fname,PIPE,PIPELEN) != 0 )
102     return(ERROR(ERRSRV,ERRaccess));
103
104   DEBUG(4,("Opening pipe %s.\n", fname));
105
106   /* Strip \PIPE\ off the name. */
107   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
108
109   /* See if it is one we want to handle. */
110   for( i = 0; known_pipes[i] ; i++ )
111     if( strcmp(fname,known_pipes[i]) == 0 )
112       break;
113
114   if ( known_pipes[i] == NULL )
115     return(ERROR(ERRSRV,ERRaccess));
116
117   /* Known pipes arrive with DIR attribs. Remove it so a regular file */
118   /* can be opened and add it in after the open. */
119   DEBUG(3,("Known pipe %s opening.\n",fname));
120   smb_attr &= ~aDIR;
121   Connections[cnum].read_only = 0;
122   smb_ofun |= 0x10;             /* Add Create it not exists flag */
123
124   unix_convert(fname,cnum,0,&bad_path);
125     
126   fnum = find_free_file();
127   if (fnum < 0)
128     return(ERROR(ERRSRV,ERRnofids));
129
130   if (!check_name(fname,cnum))
131     return(UNIXERROR(ERRDOS,ERRnoaccess));
132
133   unixmode = unix_mode(cnum,smb_attr);
134       
135   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
136                    0, &rmode,&smb_action);
137       
138   if (!Files[fnum].open)
139   {
140     /* Change the error code if bad_path was set. */
141     if((errno == ENOENT) && bad_path)
142     {
143       unix_ERR_class = ERRDOS;
144       unix_ERR_code = ERRbadpath;
145     }
146     return(UNIXERROR(ERRDOS,ERRnoaccess));
147   }
148
149   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
150     close_file(fnum);
151     return(ERROR(ERRDOS,ERRnoaccess));
152   }
153
154   size = sbuf.st_size;
155   fmode = dos_mode(cnum,fname,&sbuf);
156   mtime = sbuf.st_mtime;
157   if (fmode & aDIR) {
158     close_file(fnum);
159     return(ERROR(ERRDOS,ERRnoaccess));
160   }
161
162   /* Prepare the reply */
163   set_message(outbuf,15,0,True);
164
165   /* Put things back the way they were. */
166   Connections[cnum].read_only = 1;
167
168   /* Mark the opened file as an existing named pipe in message mode. */
169   SSVAL(outbuf,smb_vwv9,2);
170   SSVAL(outbuf,smb_vwv10,0xc700);
171   if (rmode == 2)
172   {
173     DEBUG(4,("Resetting open result to open from create.\n"));
174     rmode = 1;
175   }
176
177   SSVAL(outbuf,smb_vwv2,fnum);
178   SSVAL(outbuf,smb_vwv3,fmode);
179   put_dos_date3(outbuf,smb_vwv4,mtime);
180   SIVAL(outbuf,smb_vwv6,size);
181   SSVAL(outbuf,smb_vwv8,rmode);
182   SSVAL(outbuf,smb_vwv11,smb_action);
183
184   chain_fnum = fnum;
185
186   DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
187            fname, fnum, Files[fnum].name));
188   
189   return chain_reply(inbuf,outbuf,length,bufsize);
190 }
191
192
193 /****************************************************************************
194  api_LsarpcSNPHS
195
196  SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
197  so just blithely return True. This is really only for NT domain stuff,
198  we we're only handling that - don't assume Samba now does complete
199  named pipe handling.
200 ****************************************************************************/
201 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
202                      int mdrcnt,int mprcnt,
203                      char **rdata,char **rparam,
204                      int *rdata_len,int *rparam_len)
205 {
206   uint16 id;
207
208   id = param[0] + (param[1] << 8);
209   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
210   return(True);
211 }
212
213
214 /****************************************************************************
215  api_LsarpcTNP
216
217  TransactNamedPipe on \PIPE\lsarpc.
218 ****************************************************************************/
219 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
220 {
221   uint32 dword1, dword2;
222   char pname[] = "\\PIPE\\lsass";
223
224   /* All kinds of mysterious numbers here */
225   *rdata_len = 68;
226   *rdata = REALLOC(*rdata,*rdata_len);
227
228   dword1 = IVAL(data,0xC);
229   dword2 = IVAL(data,0x10);
230
231   SIVAL(*rdata,0,0xc0005);
232   SIVAL(*rdata,4,0x10);
233   SIVAL(*rdata,8,0x44);
234   SIVAL(*rdata,0xC,dword1);
235   
236   SIVAL(*rdata,0x10,dword2);
237   SIVAL(*rdata,0x14,0x15);
238   SSVAL(*rdata,0x18,sizeof(pname));
239   strcpy(*rdata + 0x1a,pname);
240   SIVAL(*rdata,0x28,1);
241   memcpy(*rdata + 0x30, data + 0x34, 0x14);
242 }
243
244 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
245 {
246   uint32 dword1;
247
248   /* All kinds of mysterious numbers here */
249   *rdata_len = 48;
250   *rdata = REALLOC(*rdata,*rdata_len);
251
252   dword1 = IVAL(data,0xC);
253
254   SIVAL(*rdata,0,0x03020005);
255   SIVAL(*rdata,4,0x10);
256   SIVAL(*rdata,8,0x30);
257   SIVAL(*rdata,0xC,dword1);
258   SIVAL(*rdata,0x10,0x18);
259   SIVAL(*rdata,0x1c,0x44332211);
260   SIVAL(*rdata,0x20,0x88776655);
261   SIVAL(*rdata,0x24,0xCCBBAA99);
262   SIVAL(*rdata,0x28,0x11FFEEDD);
263 }
264
265 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
266 {
267   uint32 dword1;
268   uint16 word1;
269   char * workgroup = myworkgroup;
270   int wglen = strlen(workgroup);
271   int i;
272
273   /* All kinds of mysterious numbers here */
274   *rdata_len = 90 + 2 * wglen;
275   *rdata = REALLOC(*rdata,*rdata_len);
276
277   dword1 = IVAL(data,0xC);
278   word1 = SVAL(data,0x2C);
279
280   SIVAL(*rdata,0,0x03020005);
281   SIVAL(*rdata,4,0x10);
282   SIVAL(*rdata,8,0x60);
283   SIVAL(*rdata,0xC,dword1);
284   SIVAL(*rdata,0x10,0x48);
285   SSVAL(*rdata,0x18,0x5988);    /* This changes */
286   SSVAL(*rdata,0x1A,0x15);
287   SSVAL(*rdata,0x1C,word1);
288   SSVAL(*rdata,0x20,6);
289   SSVAL(*rdata,0x22,8);
290   SSVAL(*rdata,0x24,0x8E8);     /* So does this */
291   SSVAL(*rdata,0x26,0x15);
292   SSVAL(*rdata,0x28,0x4D48);    /* And this */
293   SSVAL(*rdata,0x2A,0x15);
294   SIVAL(*rdata,0x2C,4);
295   SIVAL(*rdata,0x34,wglen);
296   for ( i = 0 ; i < wglen ; i++ )
297     (*rdata)[0x38 + i * 2] = workgroup[i];
298    
299   /* Now fill in the rest */
300   i = 0x38 + wglen * 2;
301   SSVAL(*rdata,i,0x648);
302   SIVAL(*rdata,i+2,4);
303   SIVAL(*rdata,i+6,0x401);
304   SSVAL(*rdata,i+0xC,0x500);
305   SIVAL(*rdata,i+0xE,0x15);
306   SIVAL(*rdata,i+0x12,0x2372FE1);
307   SIVAL(*rdata,i+0x16,0x7E831BEF);
308   SIVAL(*rdata,i+0x1A,0x4B454B2);
309 }
310
311 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
312 {
313   uint32 dword1;
314
315   /* All kinds of mysterious numbers here */
316   *rdata_len = 48;
317   *rdata = REALLOC(*rdata,*rdata_len);
318
319   dword1 = IVAL(data,0xC);
320
321   SIVAL(*rdata,0,0x03020005);
322   SIVAL(*rdata,4,0x10);
323   SIVAL(*rdata,8,0x30);
324   SIVAL(*rdata,0xC,dword1);
325   SIVAL(*rdata,0x10,0x18);
326 }
327
328
329 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
330                      int mdrcnt,int mprcnt,
331                      char **rdata,char **rparam,
332                      int *rdata_len,int *rparam_len)
333 {
334   uint32 id,id2;
335
336   id = IVAL(data,0);
337
338   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
339   switch (id)
340   {
341     case 0xb0005:
342       LsarpcTNP1(data,rdata,rdata_len);
343       break;
344
345     case 0x03000005:
346       id2 = IVAL(data,8);
347       DEBUG(4,("\t- Suboperation %lx\n",id2));
348       switch (id2 & 0xF)
349       {
350         case 8:
351           LsarpcTNP2(data,rdata,rdata_len);
352           break;
353
354         case 0xC:
355           LsarpcTNP4(data,rdata,rdata_len);
356           break;
357
358         case 0xE:
359           LsarpcTNP3(data,rdata,rdata_len);
360           break;
361       }
362       break;
363   }
364   return(True);
365 }
366
367
368 #ifdef NTDOMAIN
369 /*
370    PAXX: Someone fix above.
371    The above API is indexing RPC calls based on RPC flags and 
372    fragment length. I've decided to do it based on operation number :-)
373 */
374
375 /* this function is due to be replaced */
376 static void initrpcreply(char *inbuf, char *q)
377 {
378         uint32 callid;
379
380         SCVAL(q, 0, 5); q++; /* RPC version 5 */
381         SCVAL(q, 0, 0); q++; /* minor version 0 */
382         SCVAL(q, 0, 2); q++; /* RPC response packet */
383         SCVAL(q, 0, 3); q++; /* first frag + last frag */
384         RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */
385         RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */
386         SSVAL(q, 0, 0); q += 2; /* authentication length */
387         callid = RIVAL(inbuf, 12);
388         RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */
389         SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */
390         SSVAL(q, 0, 0); q += 2; /* presentation context identifier */
391         SCVAL(q, 0, 0); q++; /* cancel count */
392         SCVAL(q, 0, 0); q++; /* reserved */
393 }
394
395 /* this function is due to be replaced */
396 static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
397 {
398         SSVAL(q, 8, datalen + 4);
399         SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
400         SIVAL(q, datalen, rtnval);
401         *rlen = datalen + 4;
402         { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); }
403 }
404
405 /* RID username mapping function.  just for fun, it maps to the unix uid */
406 static uint32 name_to_rid(char *user_name)
407 {
408     struct passwd *pw = Get_Pwnam(user_name, False);
409     if (!pw)
410         {
411       DEBUG(1,("Username %s is invalid on this system\n", user_name));
412       return (uint32)(-1);
413     }
414
415     return (uint32)(pw->pw_uid);
416 }
417
418
419 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
420 char *dom_sid_to_string(DOM_SID *sid)
421 {
422   static pstring sidstr;
423   char subauth[16];
424   int i;
425   uint32 ia = (sid->id_auth[0]) +
426               (sid->id_auth[1] << 8 ) +
427               (sid->id_auth[2] << 16) +
428               (sid->id_auth[3] << 24);
429
430   sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
431
432   for (i = 0; i < sid->num_auths; i++)
433   {
434     sprintf(subauth, "-%d", sid->sub_auths[i]);
435     strcat(sidstr, subauth);
436   }
437
438   DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
439   return sidstr;
440 }
441
442 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
443 /* identauth >= 2^32 can be detected because it will be specified in hex */
444 static void make_dom_sid(DOM_SID *sid, char *domsid)
445 {
446         int identauth;
447         char *p;
448
449         DEBUG(4,("netlogon domain SID: %s\n", domsid));
450
451         /* assume, but should check, that domsid starts "S-" */
452         p = strtok(domsid+2,"-");
453         sid->sid_no = atoi(p);
454
455         /* identauth in decimal should be <  2^32 */
456         /* identauth in hex     should be >= 2^32 */
457         identauth = atoi(strtok(0,"-"));
458
459         DEBUG(4,("netlogon rev %d\n", sid->sid_no));
460         DEBUG(4,("netlogon %s ia %d\n", p, identauth));
461
462         sid->id_auth[0] = 0;
463         sid->id_auth[1] = 0;
464         sid->id_auth[2] = (identauth & 0xff000000) >> 24;
465         sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
466         sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
467         sid->id_auth[5] = (identauth & 0x000000ff);
468
469         sid->num_auths = 0;
470
471         while ((p = strtok(0, "-")) != NULL)
472         {
473                 sid->sub_auths[sid->num_auths++] = atoi(p);
474         }
475 }
476
477 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
478 {
479         if (hdr == NULL) return;
480
481         hdr->major        = 5;               /* RPC version 5 */
482         hdr->minor        = 0;               /* minor version 0 */
483         hdr->pkt_type     = 2;               /* RPC response packet */
484         hdr->frag         = 3;               /* first frag + last frag */
485         hdr->pack_type    = 1;               /* packed data representation */
486         hdr->frag_len     = data_len;        /* fragment length, fill in later */
487         hdr->auth_len     = 0;               /* authentication length */
488         hdr->call_id      = call_id;         /* call identifier - match incoming RPC */
489         hdr->alloc_hint   = data_len - 0x18; /* allocation hint (no idea) */
490         hdr->context_id   = 0;               /* presentation context identifier */
491         hdr->cancel_count = 0;               /* cancel count */
492         hdr->reserved     = 0;               /* reserved */
493 }
494
495 static int make_rpc_reply(char *inbuf, char *q, int data_len)
496 {
497         uint32 callid = RIVAL(inbuf, 12);
498         RPC_HDR hdr;
499
500         create_rpc_reply(&hdr, callid, data_len);
501         return smb_io_rpc_hdr(False, &hdr, q, q, 4) - q;
502 }
503
504 static int lsa_reply_open_policy(char *q, char *base)
505 {
506         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_chal(DOM_CHAL *cred, char resp_cred[8])
751 {
752         memcpy(cred->data, resp_cred, sizeof(cred->data));
753 }
754
755 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
756                               char resp_cred[8], NEG_FLAGS *flgs, int status)
757 {
758         make_lsa_chal(&(r_a->srv_chal), resp_cred);
759         memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
760         r_a->status = status;
761 }
762
763 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
764                                 char resp_cred[8], int status)
765 {
766         char *start = q;
767         LSA_R_AUTH_2 r_a;
768
769         /* set up the LSA AUTH 2 response */
770
771         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
772
773         /* store the response in the SMB stream */
774         q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
775
776         /* return length of SMB data stored */
777         return q - start; 
778 }
779
780 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
781 {
782         make_lsa_chal(&(cred->challenge), srv_chal);
783         cred->timestamp = srv_time;
784 }
785         
786
787 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
788                               char srv_chal[8], UTIME srv_time, int status)
789 {
790         make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
791         r_a->status = status;
792 }
793
794 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
795                                 char srv_cred[8], UTIME srv_time,
796                                 int status)
797 {
798         char *start = q;
799         LSA_R_SRV_PWSET r_s;
800
801         /* set up the LSA Server Password Set response */
802         make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
803
804         /* store the response in the SMB stream */
805         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
806
807         /* return length of SMB data stored */
808         return q - start; 
809 }
810
811 static void make_lsa_user_info(LSA_USER_INFO *usr,
812
813         NTTIME *logon_time,
814         NTTIME *logoff_time,
815         NTTIME *kickoff_time,
816         NTTIME *pass_last_set_time,
817         NTTIME *pass_can_change_time,
818         NTTIME *pass_must_change_time,
819
820         char *user_name,
821         char *full_name,
822         char *logon_script,
823         char *profile_path,
824         char *home_dir,
825         char *dir_drive,
826
827         uint16 logon_count,
828         uint16 bad_pw_count,
829
830         uint32 user_id,
831         uint32 group_id,
832         uint32 num_groups,
833         DOM_GID *gids,
834         uint32 user_flgs,
835
836         char sess_key[16],
837
838         char *logon_srv,
839         char *logon_dom,
840
841         char *dom_sid,
842         char *other_sids) /* space-delimited set of SIDs */ 
843 {
844         /* only cope with one "other" sid, right now. */
845         /* need to count the number of space-delimited sids */
846         int i;
847         int num_other_sids = other_sids != NULL ? 1 : 0;
848
849         int len_user_name    = strlen(user_name   );
850         int len_full_name    = strlen(full_name   );
851         int len_logon_script = strlen(logon_script);
852         int len_profile_path = strlen(profile_path);
853         int len_home_dir     = strlen(home_dir    );
854         int len_dir_drive    = strlen(dir_drive   );
855
856         int len_logon_srv    = strlen(logon_srv);
857         int len_logon_dom    = strlen(logon_dom);
858
859         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
860
861         usr->logon_time            = *logon_time;
862         usr->logoff_time           = *logoff_time;
863         usr->kickoff_time          = *kickoff_time;
864         usr->pass_last_set_time    = *pass_last_set_time;
865         usr->pass_can_change_time  = *pass_can_change_time;
866         usr->pass_must_change_time = *pass_must_change_time;
867
868         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
869         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
870         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
871         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
872         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
873         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
874
875         usr->logon_count = logon_count;
876         usr->bad_pw_count = bad_pw_count;
877
878         usr->user_id = user_id;
879         usr->group_id = group_id;
880         usr->num_groups = num_groups;
881         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
882         usr->user_flgs = user_flgs;
883
884         if (sess_key != NULL)
885         {
886                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
887         }
888         else
889         {
890                 bzero(usr->sess_key, sizeof(usr->sess_key));
891         }
892
893         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
894         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
895
896         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
897
898         bzero(usr->padding, sizeof(usr->padding));
899
900         usr->num_other_sids = num_other_sids;
901         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
902         
903         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
904         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
905         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
906         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
907         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
908         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
909
910         usr->num_groups2 = num_groups;
911         for (i = 0; i < num_groups; i++)
912         {
913                 usr->gids[i] = gids[i];
914         }
915
916         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
917         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
918
919         make_dom_sid(&(usr->dom_sid), dom_sid);
920         make_dom_sid(&(usr->other_sids[0]), other_sids);
921 }
922
923
924 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
925                                 char srv_cred[8], UTIME srv_time,
926                                 LSA_USER_INFO *user_info)
927 {
928         char *start = q;
929         LSA_R_SAM_LOGON r_s;
930
931         /* XXXX maybe we want to say 'no', reject the client's credentials */
932         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
933         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
934
935         /* store the user information, if there is any. */
936         r_s.user = user_info;
937         r_s.buffer_user = user_info != NULL ? 1 : 0;
938         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
939
940         /* store the response in the SMB stream */
941         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
942
943         /* return length of SMB data stored */
944         return q - start; 
945 }
946
947
948 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
949                                 char srv_cred[8], UTIME srv_time,
950                                 uint32 status)
951 {
952         char *start = q;
953         LSA_R_SAM_LOGOFF r_s;
954
955         /* XXXX maybe we want to say 'no', reject the client's credentials */
956         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
957         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
958
959         r_s.status = status;
960
961         /* store the response in the SMB stream */
962         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
963
964         /* return length of SMB data stored */
965         return q - start; 
966 }
967
968
969 static void api_lsa_open_policy( char *param, char *data,
970                              char **rdata, int *rdata_len )
971 {
972         int reply_len;
973
974         /* we might actually want to decode the query, but it's not necessary */
975         /* lsa_io_q_open_policy(...); */
976
977         /* return a 20 byte policy handle */
978         reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18);
979
980         /* construct header, now that we know the reply length */
981         make_rpc_reply(data, *rdata, reply_len);
982         *rdata_len = reply_len + 0x18;
983 }
984
985 static void api_lsa_query_info( char *param, char *data,
986                                 char **rdata, int *rdata_len )
987 {
988         int reply_len;
989
990         LSA_Q_QUERY_INFO q_i;
991         pstring dom_name;
992         pstring dom_sid;
993
994         /* grab the info class and policy handle */
995         lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4);
996
997         pstrcpy(dom_name, lp_workgroup());
998         pstrcpy(dom_sid , lp_domainsid());
999
1000         /* construct reply.  return status is always 0x0 */
1001         reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, 
1002                                                                          dom_name, dom_sid);
1003
1004         /* construct header, now that we know the reply length */
1005         make_rpc_reply(data, *rdata, reply_len);
1006         *rdata_len = reply_len + 0x18;
1007 }
1008
1009 static void api_lsa_lookup_sids( char *param, char *data,
1010                                  char **rdata, int *rdata_len )
1011 {
1012         int reply_len;
1013
1014         int i;
1015         LSA_Q_LOOKUP_SIDS q_l;
1016         pstring dom_name;
1017         pstring dom_sid;
1018         fstring dom_sids[MAX_LOOKUP_SIDS];
1019
1020         /* grab the info class and policy handle */
1021         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4);
1022
1023         pstrcpy(dom_name, lp_workgroup());
1024         pstrcpy(dom_sid , lp_domainsid());
1025
1026         /* convert received SIDs to strings, so we can do them. */
1027         for (i = 0; i < q_l.num_entries; i++)
1028         {
1029                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1030         }
1031
1032         /* construct reply.  return status is always 0x0 */
1033         reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18,
1034                     q_l.num_entries, dom_sids, /* text-converted SIDs */
1035                                 dom_name, dom_sid, /* domain name, domain SID */
1036                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1037
1038         /* construct header, now that we know the reply length */
1039         make_rpc_reply(data, *rdata, reply_len);
1040         *rdata_len = reply_len + 0x18;
1041 }
1042
1043 static void api_lsa_lookup_names( char *param, char *data,
1044                                   char **rdata, int *rdata_len )
1045 {
1046         int reply_len;
1047
1048         int i;
1049         LSA_Q_LOOKUP_RIDS q_l;
1050         pstring dom_name;
1051         pstring dom_sid;
1052         uint32 dom_rids[MAX_LOOKUP_SIDS];
1053
1054         /* grab the info class and policy handle */
1055         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4);
1056
1057         pstrcpy(dom_name, lp_workgroup());
1058         pstrcpy(dom_sid , lp_domainsid());
1059
1060         /* convert received RIDs to strings, so we can do them. */
1061         for (i = 0; i < q_l.num_entries; i++)
1062         {
1063                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1064                 dom_rids[i] = name_to_rid(user_name);
1065         }
1066
1067         /* construct reply.  return status is always 0x0 */
1068         reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18,
1069                     q_l.num_entries, dom_rids, /* text-converted SIDs */
1070                                 dom_name, dom_sid, /* domain name, domain SID */
1071                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1072
1073         /* construct header, now that we know the reply length */
1074         make_rpc_reply(data, *rdata, reply_len);
1075         *rdata_len = reply_len + 0x18;
1076 }
1077
1078 BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
1079                      int mdrcnt,int mprcnt,
1080                      char **rdata,char **rparam,
1081                      int *rdata_len,int *rparam_len)
1082 {
1083         uint16 opnum = SVAL(data,22);
1084
1085         int pkttype = CVAL(data, 2);
1086         if (pkttype == 0x0b) /* RPC BIND */
1087         {
1088                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1089                 LsarpcTNP1(data,rdata,rdata_len);
1090                 return True;
1091         }
1092
1093         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1094         switch (opnum)
1095         {
1096                 case LSA_OPENPOLICY:
1097                 {
1098                         DEBUG(3,("LSA_OPENPOLICY\n"));
1099                         api_lsa_open_policy(param, data, rdata, rdata_len);
1100                         break;
1101                 }
1102
1103                 case LSA_QUERYINFOPOLICY:
1104                 {
1105                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
1106
1107                         api_lsa_query_info(param, data, rdata, rdata_len);
1108                         break;
1109                 }
1110
1111                 case LSA_ENUMTRUSTDOM:
1112                 {
1113                         char *q = *rdata + 0x18;
1114
1115                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
1116
1117                         initrpcreply(data, *rdata);
1118
1119                         SIVAL(q, 0, 0); /* enumeration context */
1120                         SIVAL(q, 0, 4); /* entries read */
1121                         SIVAL(q, 0, 8); /* trust information */
1122
1123                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1124
1125                         break;
1126                 }
1127
1128                 case LSA_CLOSE:
1129                 {
1130                         char *q = *rdata + 0x18;
1131
1132                         DEBUG(3,("LSA_CLOSE\n"));
1133
1134                         initrpcreply(data, *rdata);
1135
1136                         SIVAL(q, 0, 0);
1137                         SIVAL(q, 0, 4);
1138                         SIVAL(q, 0, 8);
1139                         SIVAL(q, 0, 12);
1140                         SIVAL(q, 0, 16);
1141
1142                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1143
1144                         break;
1145                 }
1146
1147                 case LSA_OPENSECRET:
1148                 {
1149                         char *q = *rdata + 0x18;
1150                         DEBUG(3,("LSA_OPENSECRET\n"));
1151
1152                         initrpcreply(data, *rdata);
1153
1154                         SIVAL(q, 0, 0);
1155                         SIVAL(q, 0, 4);
1156                         SIVAL(q, 0, 8);
1157                         SIVAL(q, 0, 12);
1158                         SIVAL(q, 0, 16);
1159
1160                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1161
1162                         break;
1163                 }
1164
1165                 case LSA_LOOKUPSIDS:
1166                 {
1167                         DEBUG(3,("LSA_OPENSECRET\n"));
1168                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
1169                         break;
1170                 }
1171
1172                 case LSA_LOOKUPNAMES:
1173                 {
1174                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
1175                         api_lsa_lookup_names(param, data, rdata, rdata_len);
1176                         break;
1177                 }
1178
1179                 default:
1180                 {
1181                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1182                         break;
1183                 }
1184         }
1185         return True;
1186 }
1187
1188 static void api_lsa_req_chal( user_struct *vuser,
1189                               char *param, char *data,
1190                               char **rdata, int *rdata_len )
1191 {
1192         int reply_len;
1193
1194         int i;
1195         LSA_Q_REQ_CHAL q_r;
1196
1197         fstring mach_acct;
1198         struct smb_passwd *smb_pass;
1199
1200         /* grab the challenge... */
1201         lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4);
1202
1203         fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer));
1204
1205         DEBUG(1,("logonsrv=%s unicomp=%s\n", 
1206                  unistr2(q_r.uni_logon_srv .buffer), 
1207                  mach_acct));
1208   
1209         strcat(mach_acct, "$");
1210
1211     smb_pass = get_smbpwnam(mach_acct);
1212         if (smb_pass != NULL)
1213         {
1214                 memcpy(vuser->dc.md4pw, smb_pass->smb_nt_passwd, sizeof(vuser->dc.md4pw));
1215         }
1216         else
1217         {
1218                 /* No such machine account. Should error out here, but we'll
1219                    print and carry on */
1220                 DEBUG(1,("No account in domain at REQCHAL for %s\n", mach_acct));
1221         }
1222
1223         {
1224                 char foo[16];
1225                 for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", vuser->dc.md4pw[i]);
1226                 DEBUG(1,("pass %s %s\n", mach_acct, foo));
1227         }
1228
1229         /* from client / server challenges and md4 password, generate sess key */
1230         cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
1231                            vuser->dc.md4pw, vuser->dc.sess_key);
1232
1233         /* copy the client credentials for later use */
1234         memcpy(vuser->dc.srv_chal.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
1235         memcpy(vuser->dc.srv_cred.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
1236
1237         /* create a server challenge for the client */
1238         /* PAXX: set these to random values. */
1239         /* lkcl: paul, you mentioned that it doesn't really matter much */
1240         for (i = 0; i < 8; i++)
1241         {
1242                 vuser->dc.srv_chal.data[i] = 0xA5;
1243         }
1244
1245         /* construct reply.  return status is always 0x0 */
1246         reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18,
1247                                         &(vuser->dc.srv_chal));
1248
1249         /* construct header, now that we know the reply length */
1250         reply_len += make_rpc_reply(data, *rdata, reply_len);
1251
1252         *rdata_len = reply_len;
1253 }
1254
1255 void no_fn(uint uid)
1256 {
1257         user_struct *vuser = get_valid_user_struct(uid);
1258         DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name));
1259 #if defined(NETGROUP) && defined(AUTOMOUNT)
1260         DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1261 #endif
1262 }
1263
1264 #endif /* NTDOMAIN */
1265
1266 #ifdef UNDEFINED_NTDOMAIN
1267 /*
1268    PAXX: Someone fix above.
1269    The above API is indexing RPC calls based on RPC flags and 
1270    fragment length. I've decided to do it based on operation number :-)
1271 */
1272
1273  BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
1274                      int mdrcnt,int mprcnt,
1275                      char **rdata,char **rparam,
1276                      int *rdata_len,int *rparam_len)
1277 {
1278         uint16 opnum;
1279         char *q;
1280         char *domainname;
1281         int domlen;
1282         pstring domsid;
1283         char *p;
1284         int numsubauths;
1285         int subauths[MAXSUBAUTHS];
1286         struct smb_passwd *smb_pass; /* To check if machine account exists */
1287         pstring machacct;
1288         pstring foo;
1289         uint16 infoclass;
1290         uint16 revision; /* Domain sid revision */
1291         int identauth;
1292         int i;
1293         char *logonsrv;
1294         char *unicomp;
1295         char *accountname;
1296         uint16 secchanneltype;
1297         uint32 negflags;
1298         char netcred[8];
1299         uint32 rcvcred[8];
1300         char rtncred[8];
1301         uint32 clnttime;
1302         uint32 rtntime;
1303         char *newpass;
1304         uint16 logonlevel;
1305         uint16 switchval;
1306         uint16 dommaxlen;
1307         uint16 paramcontrol;
1308         uint32 logonid[2];
1309         uint16 usernamelen;
1310         uint16 usernamemaxlen;
1311         uint16 wslen;
1312         uint16 wsmaxlen;
1313         uchar *rc4lmowfpass;
1314         uchar *rc4ntowfpass;
1315         char *domain;
1316         char *username;
1317         char *ws;
1318         struct uinfo *userinfo;
1319         int pkttype;
1320         uchar rc4key[16];
1321         uchar ntowfpass[16];
1322         uint32 nentries;
1323         char *policyhandle;
1324         #define MAXSIDS 64
1325         uchar *sids[MAXSIDS]; /* for lookup SID */
1326         int nsids;
1327         #define MAXNAMES 64
1328         uchar *names[MAXNAMES];
1329
1330   opnum = SVAL(data,22);
1331
1332   pkttype = CVAL(data, 2);
1333   if (pkttype == 0x0b) /* RPC BIND */
1334   {
1335     DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1336     LsarpcTNP1(data,rdata,rdata_len);
1337     return True;
1338   }
1339
1340   DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1341   initrpcreply(data, *rdata);
1342   DEBUG(4,("netlogon LINE %d\n",__LINE__));
1343   switch (opnum)
1344   {
1345     case LSAOPENPOLICY:
1346             DEBUG(1,("LSAOPENPOLICY\n"));
1347             char *q = *rdata + 0x18;
1348             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1349             /* return a 20 byte policy handle */
1350             /* here's a pretty handle:- */
1351             qSIVAL(time(NULL));
1352             qSIVAL(0x810a792f);
1353             qSIVAL(0x11d107d5);
1354             qSIVAL(time(NULL));
1355             qSIVAL(0x6cbcf800);
1356             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1357             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */
1358             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1359             break;
1360
1361     case LSAQUERYINFOPOLICY:
1362             DEBUG(1,("LSAQUERYINFOPOLICY\n"));
1363             dump_data(1,data,128);
1364             infoclass = SVAL(data, 44); /* also a policy handle but who cares? */
1365             q = *rdata + 0x18;
1366             qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose
1367                                     value is ignored */
1368             qSSVAL(infoclass);
1369             domainname = lp_workgroup();
1370             domlen = strlen(domainname);
1371             strcpy(domsid,lp_domainsid());
1372             DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1373             /* assume, but should check, that domsid starts "S-" */
1374             p = strtok(domsid+2,"-");
1375             revision = atoi(p);
1376             DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1377             identauth = atoi(strtok(0,"-"));
1378             DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1379             numsubauths = 0;
1380             while (p = strtok(0, "-"))
1381                     subauths[numsubauths++] = atoi(p);
1382             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1383             
1384             switch (infoclass)
1385                     {
1386                     case 5:
1387                     case 3:
1388                     default:
1389                             qSSVAL(0); /* 2 undocumented bytes */
1390                             qSSVAL(domlen*2);
1391                             qSSVAL(domlen*2); /* unicode domain len and maxlen */
1392                             qSIVAL(4); /* domain buffer pointer */
1393                             qSIVAL(2); /* domain sid pointer */
1394                             qunistr(domainname);
1395                             qSIVAL(numsubauths);
1396                             qSCVAL(revision);
1397                             qSCVAL(numsubauths);
1398                             qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1399                             qRSIVAL(identauth); /* next 4 bytes */
1400                             for (i = 0; i < numsubauths; i++)
1401                                     {
1402                                             qSIVAL(subauths[i]);
1403                                     }
1404                     }
1405             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1406             break;
1407
1408     case LSAENUMTRUSTDOM:
1409             DEBUG(1,("LSAENUMTRUSTDOM\n"));
1410             q = *rdata + 0x18;
1411             qSIVAL(0); /* enumeration context */
1412             qSIVAL(0); /* entries read */
1413             qSIVAL(0); /* trust information */
1414             endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1415             break;
1416
1417     case LSACLOSE:
1418             DEBUG(1,("LSACLOSE\n"));
1419             q = *rdata + 0x18;
1420             qSIVAL(0);
1421             qSIVAL(0);
1422             qSIVAL(0);
1423             qSIVAL(0);
1424             qSIVAL(0);
1425             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1426       break;
1427
1428     case LSAOPENSECRET:
1429             DEBUG(1,("LSAOPENSECRET\n"));
1430             q = *rdata + 0x18;
1431             qSIVAL(0);
1432             qSIVAL(0);
1433             qSIVAL(0);
1434             qSIVAL(0);
1435             qSIVAL(0);
1436             endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1437       break;
1438
1439     case LSALOOKUPSIDS:
1440             DEBUG(1,("LSAOPENSECRET\n"));
1441             q = data + 0x18;
1442             policyhandle = q; q += 20;
1443             nentries = qIVAL;
1444             DEBUG(4,("lookupsid entries %d\n",nentries));
1445             q += (2+nentries) * 4; /* skip bufptrs */
1446             /* now we have nentries sids of the form:
1447                uint32  Subauthority count (SAC)
1448                char    Revision
1449                char    Subaurity count again
1450                char[6] Identifier authority
1451                [uint32  subauthority] * SAC
1452                */
1453             for (nsids = 0; nsids < nentries; nsids++)
1454                     {
1455                             DEBUG(4,("lookupsid q in %lx\n",q));
1456                             sids[nsids] = q;
1457                             DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0)));
1458                             q += 4+1+1+6+IVAL(q,0)*4;
1459                             DEBUG(4,("lookupsid q %lx\n",q));
1460                     }
1461       /* There's 16 bytes of something after all of that, don't know
1462          what it is though - incorrectly documented */
1463
1464       DEBUG(4,("lookupsid line %d\n",__LINE__));
1465       /* formulate reply */
1466       q = *rdata + 0x18;
1467       qSIVAL(2); /* bufptr */
1468       qSIVAL(4); /* number of referenced domains
1469                      - need one per each identifier authority in call */
1470       qSIVAL(2); /* dom bufptr */
1471       qSIVAL(32); /* max entries */
1472       qSIVAL(4); /* number of reference domains? */
1473
1474       qunihdr(lp_workgroup()); /* reference domain */
1475       qSIVAL(2); /* sid bufptr */
1476
1477       qunihdr("S-1-1");
1478       qSIVAL(2); /* sid bufptr */
1479
1480       qunihdr("S-1-5");
1481       qSIVAL(2); /* sid bufptr */
1482
1483       qunihdr("S-1-3");
1484       qSIVAL(2); /* sid bufptr */
1485
1486       qunistr(lp_workgroup());
1487       DEBUG(4,("lookupsid line %d\n",__LINE__));
1488
1489       strcpy(domsid,lp_domainsid());
1490       p = strtok(domsid+2,"-");
1491       revision = atoi(p);
1492       identauth = atoi(strtok(0,"-"));
1493       numsubauths = 0;
1494       while (p = strtok(0, "-"))
1495         subauths[numsubauths++] = atoi(p);
1496       qSIVAL(numsubauths);
1497       qSCVAL(revision);
1498       qSCVAL(numsubauths);
1499       qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1500       qRSIVAL(identauth); /* next 4 bytes */
1501       DEBUG(4,("lookupsid line %d\n",__LINE__));
1502       for (i = 0; i < numsubauths; i++)
1503       {
1504         qSIVAL(subauths[i]);
1505       }
1506       DEBUG(4,("lookupsid line %d\n",__LINE__));
1507
1508       qunistr("S-1-1");
1509       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1510       DEBUG(4,("lookupsid line %d\n",__LINE__));
1511
1512       qunistr("S-1-5");
1513       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1514
1515       qunistr("S-1-3");
1516       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1517
1518       qSIVAL(nentries);
1519       qSIVAL(2); /* bufptr */
1520       qSIVAL(nentries);
1521       DEBUG(4,("lookupsid line %d\n",__LINE__));
1522       for (i = 0; i < nentries; i++)
1523       {
1524         qSSVAL(5); /* SID name use ?! */
1525         qSSVAL(0); /* undocumented */
1526       DEBUG(4,("lookupsid line %d\n",__LINE__));
1527         qunihdr(sidtostring(sids[i]));
1528       DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i])));
1529         qSIVAL(0); /* domain index out of above reference domains */
1530       }
1531       DEBUG(4,("lookupsid line %d\n",__LINE__));
1532       for (i = 0; i < nentries; i++)
1533       {
1534         qunistr(sidtostring(sids[i]));
1535       }
1536       qSIVAL(nentries); /* mapped count */
1537       endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1538       break;
1539
1540     case LSALOOKUPNAMES:
1541             DEBUG(1,("LSALOOKUPNAMES\n"));
1542       q = data + 0x18;
1543       policyhandle = q; q += 20;
1544       nentries = qIVAL;
1545       DEBUG(4,("lookupnames entries %d\n",nentries));
1546       q += 4; /* skip second count */
1547       q += 8 * nentries; /* skip pointers */
1548       for (nnames = 0; nnames < nentries; nnames++)
1549       {
1550               names[nnames] = q; /* set name string to unicode header */
1551               q += IVAL(q,0)*2; /* guessing here */
1552       }
1553       /* There's a translated sids structure next but it looks fals */
1554
1555       DEBUG(4,("lookupnames line %d\n",__LINE__));
1556       /* formulate reply */
1557       q = *rdata + 0x18;
1558       qSIVAL(2); /* bufptr */
1559       qSIVAL(4); /* number of referenced domains
1560                      - need one per each identifier authority in call */
1561       qSIVAL(2); /* dom bufptr */
1562       qSIVAL(32); /* max entries */
1563       qSIVAL(4); /* number of reference domains? */
1564
1565       qunihdr(lp_workgroup()); /* reference domain */
1566       qSIVAL(2); /* sid bufptr */
1567
1568       qunihdr("S-1-1");
1569       qSIVAL(2); /* sid bufptr */
1570
1571       qunihdr("S-1-5");
1572       qSIVAL(2); /* sid bufptr */
1573
1574       qunihdr("S-1-3");
1575       qSIVAL(2); /* sid bufptr */
1576
1577       qunistr(lp_workgroup());
1578       DEBUG(4,("lookupnames line %d\n",__LINE__));
1579
1580       strcpy(domsid,lp_domainsid());
1581       p = strtok(domsid+2,"-");
1582       revision = atoi(p);
1583       identauth = atoi(strtok(0,"-"));
1584       numsubauths = 0;
1585       while (p = strtok(0, "-"))
1586         subauths[numsubauths++] = atoi(p);
1587       qSIVAL(numsubauths);
1588       qSCVAL(revision);
1589       qSCVAL(numsubauths);
1590       qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1591       qRSIVAL(identauth); /* next 4 bytes */
1592       DEBUG(4,("lookupsid line %d\n",__LINE__));
1593       for (i = 0; i < numsubauths; i++)
1594       {
1595         qSIVAL(subauths[i]);
1596       }
1597       DEBUG(4,("lookupsid line %d\n",__LINE__));
1598
1599       qunistr("S-1-1");
1600       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1601       DEBUG(4,("lookupsid line %d\n",__LINE__));
1602
1603       qunistr("S-1-5");
1604       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1605
1606       qunistr("S-1-3");
1607       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1608
1609       qSIVAL(nentries);
1610       qSIVAL(2); /* bufptr */
1611       qSIVAL(nentries);
1612       DEBUG(4,("lookupnames line %d\n",__LINE__));
1613       for (i = 0; i < nentries; i++)
1614       {
1615         qSSVAL(5); /* SID name use  5 == well known sid, 1 == user sid see showacls */
1616         qSSVAL(5); /* undocumented */
1617       DEBUG(4,("lookupnames line %d\n",__LINE__));
1618         qSIVAL(nametorid(names[i]));
1619       DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i])));
1620         qSIVAL(0); /* domain index out of above reference domains */
1621       }
1622       qSIVAL(nentries); /* mapped count */
1623       endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1624       break;
1625
1626     default:
1627       DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1628   }
1629   return(True);
1630 }
1631
1632  BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
1633                      int mdrcnt,int mprcnt,
1634                      char **rdata,char **rparam,
1635                      int *rdata_len,int *rparam_len)
1636 {
1637   uint16 opnum;
1638   char *q;
1639   char *domainname;
1640   int domlen;
1641   pstring domsid;
1642   char *p;
1643   int numsubauths;
1644   int subauths[MAXSUBAUTHS];
1645   struct smb_passwd *smb_pass; /* To check if machine account exists */
1646   pstring machacct;
1647   pstring foo;
1648   uint16 infoclass;
1649   uint16 revision; /* Domain sid revision */
1650   int identauth;
1651   int i;
1652   char *logonsrv;
1653   char *unicomp;
1654   char *accountname;
1655   uint16 secchanneltype;
1656   uint32 negflags;
1657   char netcred[8];
1658   uint32 rcvcred[8];
1659   char rtncred[8];
1660   uint32 clnttime;
1661   uint32 rtntime;
1662   char *newpass;
1663   uint16 logonlevel;
1664   uint16 switchval;
1665   uint16 dommaxlen;
1666   uint16 paramcontrol;
1667   uint32 logonid[2];
1668   uint16 usernamelen;
1669   uint16 usernamemaxlen;
1670   uint16 wslen;
1671   uint16 wsmaxlen;
1672   uchar *rc4lmowfpass;
1673   uchar *rc4ntowfpass;
1674   char *domain;
1675   char *username;
1676   char *ws;
1677   struct uinfo *userinfo;
1678   int pkttype;
1679   ArcfourContext c;
1680   uchar rc4key[16];
1681   uchar ntowfpass[16];
1682
1683   opnum = SVAL(data,22);
1684
1685   pkttype = CVAL(data, 2);
1686   if (pkttype == 0x0b) /* RPC BIND */
1687   {
1688     DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1689     LsarpcTNP1(data,rdata,rdata_len);
1690     return True;
1691   }
1692
1693   DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum));
1694   initrpcreply(data, *rdata);
1695   DEBUG(4,("netlogon LINE %d\n",__LINE__));
1696   switch (opnum)
1697   {
1698     case LSAREQCHAL:
1699             DEBUG(1,("LSAREQCHAL\n"));
1700             q = data + 0x18;
1701             dump_data(1,q,128);
1702             logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */
1703             q = skip_unicode_string(logonsrv,1) + 12;
1704             q = align4(q, data);
1705             unicomp = q;
1706             q = skip_unicode_string(unicomp,1);
1707             
1708       
1709             DEBUG(1,("logonsrv=%s unicomp=%s\n", 
1710                      unistr(logonsrv), 
1711                      unistr(unicomp)));
1712       
1713             dcauth[cnum].chal[0] = IVAL(q, 0);
1714             dcauth[cnum].chal[1] = IVAL(q, 4);
1715             dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */
1716             dcauth[cnum].cred[1] = IVAL(q, 4);
1717
1718 DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1]));
1719
1720             /* PAXX: set these to random values */
1721             dcauth[cnum].svrchal[0] = 0x11111111;
1722             dcauth[cnum].svrchal[1] = 0x22222222;
1723             dcauth[cnum].svrcred[0] = 0x11111111;
1724             dcauth[cnum].svrcred[1] = 0x22222222;
1725             strcpy(machacct,unistr(unicomp));
1726             strcat(machacct, "$");
1727             smb_pass = get_smbpwnam(machacct);
1728             if(smb_pass)
1729                     memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16);
1730             else
1731                     {
1732                             /* No such machine account. Should error out here, but we'll
1733                                print and carry on */
1734                             DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct));
1735                     }
1736             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]);
1737             DEBUG(1,("pass %s %s\n", machacct, foo));
1738             setsesskey(cnum);
1739             q = *rdata + 0x18;
1740             qSIVAL(dcauth[cnum].svrchal[0]);
1741             qSIVAL(dcauth[cnum].svrchal[1]);
1742
1743 DEBUG(1,("NL: server challenge %08x %08x\n", 
1744          dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1]));
1745
1746             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1747             break;
1748
1749     case LSAAUTH2:
1750             DEBUG(1,("LSAAUTH2\n"));
1751             dump_data(1,q,128);
1752             q = data + 0x18;
1753             logonsrv = q + 16;
1754             q = skip_unicode_string(logonsrv,1)+12;
1755             q = align4(q, data);
1756             accountname = q;
1757
1758             q = skip_unicode_string(accountname,1);
1759             secchanneltype = qSVAL;
1760             q += 12;
1761             q = align4(q, data);
1762             unicomp = q;
1763             dump_data(1,unicomp,32);
1764             q = skip_unicode_string(unicomp,1);
1765             rcvcred[0] = qIVAL;
1766             rcvcred[1] = qIVAL;
1767             q = align4(q, data);
1768             negflags = qIVAL;
1769             DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", 
1770                      unistr(logonsrv), unistr(accountname), unistr(unicomp),
1771                      rcvcred[0], rcvcred[1], negflags));
1772
1773 DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", 
1774          rcvcred[0], rcvcred[1], negflags));
1775
1776             checkcred(cnum, rcvcred[0], rcvcred[1], 0);
1777             q = *rdata + 0x18;
1778             makecred(cnum, 0, q);
1779             q += 8;
1780
1781             qSIVAL(negflags);
1782             /* update stored client credentials */
1783             dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0];
1784             dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1];
1785             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1786             break;
1787
1788     case LSASVRPWSET:
1789             DEBUG(1,("LSASVRPWSET\n"));
1790             q = data + 0x18;
1791             dump_data(1,q,128);
1792             logonsrv = q + 16;
1793             q = skip_unicode_string(logonsrv,1)+12;
1794             q = align4(q, data);
1795             accountname = q;
1796             q = skip_unicode_string(accountname,1);
1797             secchanneltype = qSVAL;
1798             q += 12;
1799             q = align4(q, data);
1800             unicomp = q;
1801             q = skip_unicode_string(unicomp,1);
1802             rcvcred[0] = qIVAL;
1803             rcvcred[1] = qIVAL;
1804             clnttime = qIVAL;
1805
1806             DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n",
1807                      unistr(logonsrv), unistr(accountname), unistr(unicomp)));
1808
1809             checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1810             DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags));
1811             newpass = q;
1812
1813             DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n",
1814                      unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass));
1815
1816             /* PAXX: For the moment we'll reject these */
1817             /* TODO Need to set newpass in smbpasswd file for accountname */
1818             q = *rdata + 0x18;
1819             makecred(cnum, clnttime+1, q);
1820             q += 8;
1821             qSIVAL(0); /* timestamp. Seems to be ignored */
1822             
1823             dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1824
1825             endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len);
1826             break;
1827
1828     case LSASAMLOGON:
1829             DEBUG(1,("LSASAMLOGON\n"));
1830             dump_data(1,data,128);
1831             q = data + 0x18;
1832             logonsrv = q + 16;
1833             DEBUG(1,("SMLOG %d\n", __LINE__));
1834             q = skip_unicode_string(logonsrv,1)+16;
1835             q = align4(q, data);
1836             unicomp = q;
1837             q = skip_unicode_string(unicomp,1)+4;
1838             DEBUG(1,("SMLOG %d  logonsrv=%s unicomp=%s\n", 
1839                      __LINE__, unistr(logonsrv), unistr(unicomp)));
1840             q = align4(q, data);
1841             rcvcred[0] = qIVAL;
1842             DEBUG(1,("SMLOG %d\n", __LINE__));
1843             rcvcred[1] = qIVAL;
1844             DEBUG(1,("SMLOG %d\n", __LINE__));
1845             clnttime = qIVAL;
1846             checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1847             q += 2;
1848             rtncred[0] = qIVAL; /* all these are ignored */
1849             DEBUG(1,("SMLOG %d\n", __LINE__));
1850             rtncred[1] = qIVAL;
1851             rtntime = qIVAL;
1852             logonlevel = qSVAL;
1853             DEBUG(1,("SMLOG %d\n", __LINE__));
1854             switchval = qSVAL;
1855             switch (switchval)
1856                     {
1857                     case 1:
1858                             
1859                             q += 6;
1860                             domlen = qSVAL;
1861                             dommaxlen = qSVAL; q += 4;
1862                             paramcontrol = qIVAL;
1863                             logonid[0] = qIVAL; /* low part */
1864                             logonid[1] = qIVAL; /* high part */
1865                             
1866                             usernamelen = qSVAL;
1867                             
1868                             DEBUG(1,("SMLOG %d\n", __LINE__));
1869                             usernamemaxlen = qSVAL; q += 4;
1870                             
1871                             DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", 
1872                                      usernamelen, usernamemaxlen, dommaxlen));
1873                             
1874                             dump_data(1,q,128);
1875                             
1876                             wslen = qSVAL;
1877                             wsmaxlen = qSVAL; q += 4;
1878                             rc4lmowfpass = q; q += 16;
1879                             rc4ntowfpass = q; q += 16;
1880                             
1881                             q += 12; domain = q; q += dommaxlen + 12;
1882                             q = align4(q, data);
1883                             username = q; q += usernamemaxlen + 12; 
1884                             q = align4(q, data);
1885                             ws = q;
1886                             DEBUG(1,("domain=%s username=%s ws=%s\n",
1887                                      unistr(domain), unistr(username),
1888                                      unistr(ws)));
1889                             break;
1890                     default: 
1891                             DEBUG(0,("unknown switch in SAMLOGON %d\n",
1892                                      switchval));
1893                     }
1894             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]);
1895             DEBUG(1,("userNAME %s  [%s]\n", foo, username));
1896             DEBUG(1,("SMLOG %d\n", __LINE__));
1897             q = *rdata + 0x18;
1898             qSIVAL(0x16a4b4); /* magic buffer pointer ? */
1899             makecred(cnum, clnttime+1, q);
1900             dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1901             q += 8;
1902             qSIVAL(0); /* timestamp. client doesn't care */
1903             qSSVAL(3); /* switch value 3. May be others? */
1904             qSSVAL(0); /* undocumented */
1905             DEBUG(1,("SMLOG %d\n", __LINE__));
1906             
1907             memset(rc4key, 0, sizeof rc4key);
1908             SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]);
1909             SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]);
1910             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]);
1911             DEBUG(1,("rc4ntowf %s\n", foo));
1912             arcfour_init(&c, rc4key, sizeof rc4key);
1913             arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass);
1914             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]);
1915             DEBUG(1,("ntowf %s\n", foo));
1916             
1917             if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) {
1918                     qSIVAL(0); /* no buffer */
1919                     qSCVAL(1); /* Authoratitive. Change if passthrough? */
1920                     qSCVAL(0); /* pad for above boolean */
1921                     qSSVAL(0); /* pad for above boolean */
1922                     
1923                     endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len);
1924                     break;
1925             }
1926
1927             qSIVAL(2); /* another magic bufptr? */
1928       DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo));
1929       qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]);
1930       qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]);
1931       DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1]));
1932       qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]);
1933       qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]);
1934       qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]);
1935       qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]);
1936       DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename));
1937       qunihdr(userinfo->effectivename);
1938       qunihdr(userinfo->fullname);
1939       DEBUG(1,("SMLOG %d\n", __LINE__));
1940       qunihdr(userinfo->logonscript);
1941       qunihdr(userinfo->profilepath);
1942       qunihdr(userinfo->homedirectory);
1943       qunihdr(userinfo->homedirectorydrive);
1944       DEBUG(1,("SMLOG %d\n", __LINE__));
1945       qSSVAL(userinfo->logoncount);
1946       qSSVAL(userinfo->badpwcount);
1947       qSIVAL(userinfo->uid);
1948       qSIVAL(userinfo->gid);
1949       DEBUG(1,("SMLOG %d\n", __LINE__));
1950       qSIVAL(userinfo->ngroups);
1951       qSIVAL(8); /* ptr to groups */
1952       qSIVAL(userinfo->userflags);
1953       DEBUG(1,("SMLOG %d\n", __LINE__));
1954       qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */
1955       qunihdr(userinfo->logonserver);
1956       qunihdr(userinfo->logondomain);
1957       DEBUG(1,("SMLOG %d\n", __LINE__));
1958       qSIVAL(2); /* logon domain id ptr */
1959       DEBUG(1,("SMLOG %d\n", __LINE__));
1960       memset(q,0,40); q += 40; /* expansion room */
1961       DEBUG(1,("SMLOG %d\n", __LINE__));
1962       qSIVAL(userinfo->nsids);
1963       DEBUG(1,("SMLOG %d\n", __LINE__));
1964       qSIVAL(0); /* ptr to sids and values */
1965       DEBUG(1,("SMLOG %d\n", __LINE__));
1966       qunistr(userinfo->effectivename);
1967       DEBUG(1,("SMLOG %d\n", __LINE__));
1968       qunistr(userinfo->fullname);
1969       DEBUG(1,("SMLOG %d\n", __LINE__));
1970       qunistr(userinfo->logonscript);
1971       DEBUG(1,("SMLOG %d\n", __LINE__));
1972       qunistr(userinfo->profilepath);
1973       qunistr(userinfo->homedirectory);
1974       qunistr(userinfo->homedirectorydrive);
1975       DEBUG(1,("SMLOG %d\n", __LINE__));
1976       qSIVAL(userinfo->ngroups);
1977       for (i = 0; i < userinfo->ngroups; i++)
1978       {
1979         qSIVAL(userinfo->groups[i].gid);
1980         qSIVAL(userinfo->groups[i].attr);
1981       }
1982       qunistr(userinfo->logonserver);
1983       qunistr(userinfo->logondomain);
1984       for (i = 0; i < userinfo->nsids; i++)
1985       {
1986         /* put the extra sids: PAXX: TODO */
1987       }
1988       /* Assumption. This is the only domain, sending our SID */
1989       /* PAXX: may want to do passthrough later */
1990       strcpy(domsid,lp_domainsid());
1991   DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1992       /* assume, but should check, that domsid starts "S-" */
1993       p = strtok(domsid+2,"-");
1994       revision = atoi(p);
1995   DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1996       identauth = atoi(strtok(0,"-"));
1997   DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1998       numsubauths = 0;
1999       while (p = strtok(0, "-"))
2000         subauths[numsubauths++] = atoi(p);
2001       qSIVAL(numsubauths);
2002       qSCVAL(revision);
2003       qSCVAL(numsubauths);
2004       qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */
2005       qRSIVAL(identauth); /* next 4 bytes */
2006       DEBUG(1,("SMLOG %d\n", __LINE__));
2007       for (i = 0; i < numsubauths; i++)
2008       {
2009         qSIVAL(subauths[i]);
2010       }
2011       qSCVAL(1); /* Authoratitive. Change if passthrough? */
2012       qSCVAL(0); /* pad for above boolean */
2013       qSSVAL(0); /* pad for above boolean */
2014
2015       endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
2016       break;
2017
2018     case LSASAMLOGOFF:
2019             DEBUG(1,("LSASAMLOGOFF\n"));
2020       q = data + 0x18;
2021       logonsrv = q + 16;
2022       DEBUG(1,("SAMLOGOFF %d\n", __LINE__));
2023       unicomp = skip_unicode_string(logonsrv,1)+16;
2024       if (strlen(unistr(logonsrv)) % 2 == 0)
2025         q += 2;
2026       DEBUG(1,("SMLOG %d\n", __LINE__));
2027       q = skip_unicode_string(unicomp,1)+4;
2028       if (strlen(unistr(unicomp)) % 2 == 0)
2029         q += 2;
2030       DEBUG(1,("SMLOG %d\n", __LINE__));
2031       rcvcred[0] = qIVAL;
2032       DEBUG(1,("SMLOG %d\n", __LINE__));
2033       rcvcred[1] = qIVAL;
2034       DEBUG(1,("SMLOG %d\n", __LINE__));
2035       clnttime = qIVAL;
2036       checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
2037       q += 4;
2038       rtncred[0] = qIVAL; /* all these are ignored */
2039       DEBUG(1,("SMLOG %d\n", __LINE__));
2040       rtncred[1] = qIVAL;
2041       rtntime = qIVAL;
2042       logonlevel = qSVAL;
2043       DEBUG(1,("SMLOG %d\n", __LINE__));
2044       switchval = qSVAL;
2045       switch (switchval)
2046       {
2047         case 1:
2048           q += 4;
2049           domlen = qSVAL;
2050           dommaxlen = qSVAL; q += 4;
2051           paramcontrol = qIVAL;
2052           logonid[0] = qIVAL; /* low part */
2053           logonid[1] = qIVAL; /* high part */
2054           usernamelen = qSVAL;
2055       DEBUG(1,("SMLOG %d\n", __LINE__));
2056           usernamemaxlen = qSVAL; q += 4;
2057           wslen = qSVAL;
2058           wsmaxlen = qSVAL; q += 4;
2059           rc4lmowfpass = q; q += 16;
2060           rc4ntowfpass = q; q += 16;
2061           q += 12; domain = q; q += dommaxlen + 12;
2062           if ((domlen/2) % 2 != 0) q += 2;
2063           username = q; q += usernamemaxlen + 12; /* PAXX: HACK */
2064           if ((usernamelen/2) % 2 != 0) q += 2;
2065           ws = q;
2066           break;
2067         default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval));
2068       }
2069       DEBUG(1,("SAMLOGOFF %s\n", unistr(username)));
2070     default:
2071       DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
2072   }
2073   return(True);
2074 }
2075
2076 static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time)
2077 {
2078         uint32 sum[2];
2079         char netdata[8];
2080         char netsesskey[8];
2081         char calccred[8];
2082         char icv[8];
2083         char key2[7];
2084
2085         SIVAL(netdata, 0, dcauth[cnum].cred[0]+time);
2086         SIVAL(netdata, 4, dcauth[cnum].cred[1]);
2087         SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
2088         SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
2089         E1(netsesskey,netdata,icv);
2090         memset(key2, 0, sizeof key2);
2091         key2[0] = netsesskey[7];
2092         E1(key2, icv, calccred);
2093         if (IVAL(calccred,0) != cred0 ||
2094             IVAL(calccred,4) != cred1)
2095         {
2096           DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
2097                   cred0, cred1, time,
2098                   dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2099                   dcauth[cnum].cred[0], dcauth[cnum].cred[1],
2100                   IVAL(calccred,0),  IVAL(calccred,4)));
2101           /* PAXX: do something about it! */
2102         } else
2103           DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
2104                   cred0, cred1, time,
2105                   dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2106                   dcauth[cnum].cred[0], dcauth[cnum].cred[1],
2107                   IVAL(calccred,0),  IVAL(calccred,4)));
2108 }
2109
2110 static void makecred(int cnum, uint32 time, char *calccred)
2111 {
2112         uint32 sum[2];
2113         char netdata[8];
2114         char netsesskey[8];
2115         char icv[8];
2116         char key2[7];
2117
2118         SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time);
2119         SIVAL(netdata, 4, dcauth[cnum].svrcred[1]);
2120         SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
2121         SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
2122         E1(netsesskey,netdata,icv);
2123         memset(key2, 0, sizeof key2);
2124         key2[0] = netsesskey[7];
2125         E1(key2, icv, calccred);
2126         DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n",
2127            dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1],
2128            dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2129            dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1],
2130            IVAL(calccred, 0), IVAL(calccred, 4)));
2131 }
2132
2133 static void setsesskey(int cnum)
2134 {
2135         uint32 sum[2];
2136         char netsum[8];
2137         char netsesskey[8];
2138         char icv[8];
2139
2140         sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0];
2141         sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1];
2142         SIVAL(netsum,0,sum[0]);
2143         SIVAL(netsum,4,sum[1]);
2144         E1(dcauth[cnum].md4pw,netsum,icv);
2145         E1(dcauth[cnum].md4pw+9,icv,netsesskey);
2146         dcauth[cnum].sesskey[0] = IVAL(netsesskey,0);
2147         dcauth[cnum].sesskey[1] = IVAL(netsesskey,4);
2148
2149 DEBUG(1,("NL: session key %08x %08x\n",
2150          dcauth[cnum].sesskey[0],
2151          dcauth[cnum].sesskey[1]));
2152 }
2153
2154 static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass)
2155 {
2156   static struct uinfo u;
2157   static pstring fullnm;
2158   static pstring ascuser;
2159   extern pstring myname;
2160   static pstring stme;
2161   static pstring stdom;
2162   struct smb_passwd *smb_pass;
2163
2164   strcpy(ascuser,unistr(user));
2165   ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */
2166   DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len));
2167
2168   smb_pass = get_smbpwnam(ascuser);
2169   if(!smb_pass)
2170     return 0;
2171       DEBUG(1,("GETU %d\n", __LINE__));
2172       if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) {
2173               DEBUG(1,("pass mismatch:\n"));
2174               dump_data(1,ntowfpass,16);
2175               dump_data(1,smb_pass->smb_nt_passwd,16);
2176               return 0;
2177       }
2178
2179       DEBUG(1,("GETU %d\n", __LINE__));
2180   u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff;
2181   u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff;
2182   u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff;
2183       DEBUG(1,("GETU %d\n", __LINE__));
2184   u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff;
2185   u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff;
2186   u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff;
2187       DEBUG(1,("GETU %d\n", __LINE__));
2188   u.effectivename = ascuser;
2189   strcpy(fullnm, "Full name of ");
2190   strcat(fullnm, ascuser);
2191       DEBUG(1,("GETU %d\n", __LINE__));
2192   u.fullname = fullnm;
2193   u.logonscript = "foologin.cmd";
2194   u.profilepath = "prof";
2195   u.homedirectory = "foohomes";
2196       DEBUG(1,("GETU %d\n", __LINE__));
2197   u.homedirectorydrive = "a:";
2198   u.logoncount = 7;
2199   u.badpwcount = 8;
2200   u.uid = 778;
2201       DEBUG(1,("GETU %d\n", __LINE__));
2202   u.gid = 998;
2203   u.ngroups = 2;
2204   u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2));
2205   u.groups[0].gid = 776;
2206       DEBUG(1,("GETU %d\n", __LINE__));
2207   u.groups[0].attr = 0x7;
2208   u.groups[1].gid = 776;
2209   u.groups[1].attr = 0x7;
2210   u.userflags = 0x20;
2211   u.logonserver = stme;
2212   get_myname(myname,NULL);
2213   strcpy(stme, myname);
2214   strupper(stme);
2215   DEBUG(1,("LS %s\n", u.logonserver));
2216   u.logondomain = stdom;
2217   strcpy(stdom, lp_workgroup());
2218   strupper(stdom);
2219   DEBUG(1,("DOM %s\n", u.logondomain));
2220   u.nsids = 0;
2221   u.sids = 0;
2222       DEBUG(1,("GETU %d\n", __LINE__));
2223   return &u;
2224 };
2225
2226
2227 #endif /* NTDOMAIN */