pipes.c:
[jerry/samba.git] / source / 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 0
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    PAXX: Someone fix above.
369    The above API is indexing RPC calls based on RPC flags and 
370    fragment length. I've decided to do it based on operation number :-)
371 */
372
373 /* this function is due to be replaced */
374 static void initrpcreply(char *inbuf, char *q)
375 {
376         uint32 callid;
377
378         SCVAL(q, 0, 5); q++; /* RPC version 5 */
379         SCVAL(q, 0, 0); q++; /* minor version 0 */
380         SCVAL(q, 0, 2); q++; /* RPC response packet */
381         SCVAL(q, 0, 3); q++; /* first frag + last frag */
382         RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */
383         RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */
384         SSVAL(q, 0, 0); q += 2; /* authentication length */
385         callid = RIVAL(inbuf, 12);
386         RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */
387         SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */
388         SSVAL(q, 0, 0); q += 2; /* presentation context identifier */
389         SCVAL(q, 0, 0); q++; /* cancel count */
390         SCVAL(q, 0, 0); q++; /* reserved */
391 }
392
393 /* this function is due to be replaced */
394 static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
395 {
396         SSVAL(q, 8, datalen + 4);
397         SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
398         SIVAL(q, datalen, rtnval);
399         *rlen = datalen + 4;
400         { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); }
401 }
402
403 /* RID username mapping function.  just for fun, it maps to the unix uid */
404 static uint32 name_to_rid(char *user_name)
405 {
406     struct passwd *pw = Get_Pwnam(user_name, False);
407     if (!pw)
408         {
409       DEBUG(1,("Username %s is invalid on this system\n", user_name));
410       return (uint32)(-1);
411     }
412
413     return (uint32)(pw->pw_uid);
414 }
415
416
417 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
418 char *dom_sid_to_string(DOM_SID *sid)
419 {
420   static pstring sidstr;
421   char subauth[16];
422   int i;
423   uint32 ia = (sid->id_auth[0]) +
424               (sid->id_auth[1] << 8 ) +
425               (sid->id_auth[2] << 16) +
426               (sid->id_auth[3] << 24);
427
428   sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
429
430   for (i = 0; i < sid->num_auths; i++)
431   {
432     sprintf(subauth, "-%d", sid->sub_auths[i]);
433     strcat(sidstr, subauth);
434   }
435
436   DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
437   return sidstr;
438 }
439
440 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
441 /* identauth >= 2^32 can be detected because it will be specified in hex */
442 static void make_dom_sid(DOM_SID *sid, char *domsid)
443 {
444         int identauth;
445         char *p;
446
447         DEBUG(4,("netlogon domain SID: %s\n", domsid));
448
449         /* assume, but should check, that domsid starts "S-" */
450         p = strtok(domsid+2,"-");
451         sid->sid_no = atoi(p);
452
453         /* identauth in decimal should be <  2^32 */
454         /* identauth in hex     should be >= 2^32 */
455         identauth = atoi(strtok(0,"-"));
456
457         DEBUG(4,("netlogon rev %d\n", sid->sid_no));
458         DEBUG(4,("netlogon %s ia %d\n", p, identauth));
459
460         sid->id_auth[0] = 0;
461         sid->id_auth[1] = 0;
462         sid->id_auth[2] = (identauth & 0xff000000) >> 24;
463         sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
464         sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
465         sid->id_auth[5] = (identauth & 0x000000ff);
466
467         sid->num_auths = 0;
468
469         while ((p = strtok(0, "-")) != NULL)
470         {
471                 sid->sub_auths[sid->num_auths++] = atoi(p);
472         }
473 }
474
475 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
476 {
477         if (hdr == NULL) return;
478
479         hdr->major        = 5;               /* RPC version 5 */
480         hdr->minor        = 0;               /* minor version 0 */
481         hdr->pkt_type     = 2;               /* RPC response packet */
482         hdr->frag         = 3;               /* first frag + last frag */
483         hdr->pack_type    = 1;               /* packed data representation */
484         hdr->frag_len     = data_len;        /* fragment length, fill in later */
485         hdr->auth_len     = 0;               /* authentication length */
486         hdr->call_id      = call_id;         /* call identifier - match incoming RPC */
487         hdr->alloc_hint   = data_len - 0x18; /* allocation hint (no idea) */
488         hdr->context_id   = 0;               /* presentation context identifier */
489         hdr->cancel_count = 0;               /* cancel count */
490         hdr->reserved     = 0;               /* reserved */
491 }
492
493 static void make_rpc_reply(char *inbuf, char *q, int data_len)
494 {
495         uint32 callid = RIVAL(inbuf, 12);
496         RPC_HDR hdr;
497
498         create_rpc_reply(&hdr, callid, data_len);
499         smb_io_rpc_hdr(False, &hdr, q, q, 4);
500 }
501
502 static int lsa_reply_open_policy(char *q, char *base)
503 {
504         char *start = q;
505         LSA_R_OPEN_POL r_o;
506
507         /* set up the LSA QUERY INFO response */
508         bzero(&(r_o.pol.data), POL_HND_SIZE);
509         r_o.status = 0x0;
510
511         /* store the response in the SMB stream */
512         q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
513
514         /* return length of SMB data stored */
515         return q - start; 
516 }
517
518 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
519 {
520         hdr->uni_max_len = max_len;
521         hdr->uni_str_len = len;
522         hdr->undoc       = terminate;
523 }
524
525 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
526 {
527         make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
528         hdr->undoc_buffer = len > 0 ? 1 : 0;
529 }
530
531 static void make_unistr(UNISTR *str, char *buf)
532 {
533         /* store the string (null-terminated copy) */
534         PutUniCode((char *)(str->buffer), buf);
535 }
536
537 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
538 {
539         /* set up string lengths. add one if string is not null-terminated */
540         str->uni_max_len = len + (terminate != 0 ? 1 : 0);
541         str->undoc       = 0;
542         str->uni_str_len = len;
543
544         /* store the string (null-terminated copy) */
545         PutUniCode((char *)str->buffer, buf);
546
547         /* overwrite the last character: some strings are terminated with 4 not 0 */
548         str->buffer[len] = (uint16)terminate;
549 }
550
551 static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
552 {
553         rid2->type    = 0x5;
554         rid2->undoc   = 0x5;
555         rid2->rid     = rid;
556         rid2->rid_idx = 0;
557 }
558
559 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
560 {
561         int len_sid_str = strlen(sid_str);
562
563         sid2->type = 0x5;
564         sid2->undoc = 0;
565         make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
566         make_unistr  (&(sid2->str), sid_str);
567 }
568
569 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
570 {
571         int domlen = strlen(dom_name);
572
573         d_q->uni_dom_max_len = domlen * 2;
574         d_q->padding = 0;
575         d_q->uni_dom_str_len = domlen * 2;
576
577         d_q->buffer_dom_name = 0; /* domain buffer pointer */
578         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
579
580         /* NOT null-terminated: 4-terminated instead! */
581         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
582
583         make_dom_sid(&(d_q->dom_sid), dom_sid);
584 }
585
586 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
587                                 char *dom_name, char *dom_sid)
588 {
589         char *start = q;
590         LSA_R_QUERY_INFO r_q;
591
592         /* set up the LSA QUERY INFO response */
593
594         r_q.undoc_buffer = 1; /* not null */
595         r_q.info_class = q_q->info_class;
596
597         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
598
599         r_q.status = 0x0;
600
601         /* store the response in the SMB stream */
602         q = lsa_io_r_query(False, &r_q, q, base, 4);
603
604         /* return length of SMB data stored */
605         return q - start; 
606 }
607
608 /* pretty much hard-coded choice of "other" sids, unfortunately... */
609 static void make_dom_ref(DOM_R_REF *ref,
610                                 char *dom_name, char *dom_sid,
611                                 char *other_sid1, char *other_sid2, char *other_sid3)
612 {
613         int len_dom_name   = strlen(dom_name);
614         int len_other_sid1 = strlen(other_sid1);
615         int len_other_sid2 = strlen(other_sid2);
616         int len_other_sid3 = strlen(other_sid3);
617
618         ref->undoc_buffer = 1;
619         ref->num_ref_doms_1 = 4;
620         ref->buffer_dom_name = 1;
621         ref->max_entries = 32;
622         ref->num_ref_doms_2 = 4;
623
624         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
625         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
626         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
627         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
628
629         if (dom_name != NULL)
630         {
631                 make_unistr(&(ref->uni_dom_name), dom_name);
632         }
633
634         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
635         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
636         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
637         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
638 }
639
640 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
641                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
642                                 char *dom_name, char *dom_sid,
643                                 char *other_sid1, char *other_sid2, char *other_sid3)
644 {
645         int i;
646
647         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
648                      other_sid1, other_sid2, other_sid3);
649
650         r_l->num_entries = num_entries;
651         r_l->undoc_buffer = 1;
652         r_l->num_entries2 = num_entries;
653
654         for (i = 0; i < num_entries; i++)
655         {
656                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
657         }
658
659         r_l->num_entries3 = num_entries;
660 }
661
662 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
663                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
664                                 char *dom_name, char *dom_sid,
665                                 char *other_sid1, char *other_sid2, char *other_sid3)
666 {
667         int i;
668
669         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
670                      other_sid1, other_sid2, other_sid3);
671
672         r_l->num_entries = num_entries;
673         r_l->undoc_buffer = 1;
674         r_l->num_entries2 = num_entries;
675
676         for (i = 0; i < num_entries; i++)
677         {
678                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
679         }
680
681         r_l->num_entries3 = num_entries;
682 }
683
684 static int lsa_reply_lookup_sids(char *q, char *base,
685                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
686                                 char *dom_name, char *dom_sid,
687                                 char *other_sid1, char *other_sid2, char *other_sid3)
688 {
689         char *start = q;
690         LSA_R_LOOKUP_SIDS r_l;
691
692         /* set up the LSA Lookup SIDs response */
693         make_reply_lookup_sids(&r_l, num_entries, dom_sids,
694                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
695         r_l.status = 0x0;
696
697         /* store the response in the SMB stream */
698         q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4);
699
700         /* return length of SMB data stored */
701         return q - start; 
702 }
703
704 static int lsa_reply_lookup_rids(char *q, char *base,
705                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
706                                 char *dom_name, char *dom_sid,
707                                 char *other_sid1, char *other_sid2, char *other_sid3)
708 {
709         char *start = q;
710         LSA_R_LOOKUP_RIDS r_l;
711
712         /* set up the LSA Lookup RIDs response */
713         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
714                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
715         r_l.status = 0x0;
716
717         /* store the response in the SMB stream */
718         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4);
719
720         /* return length of SMB data stored */
721         return q - start; 
722 }
723
724 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
725 {
726         memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
727         r_c->status = status;
728 }
729
730 #if 0
731         char chal[8];
732         /* PAXX: set these to random values */
733         for (int i = 0; i < 8; i+++)
734         {
735                 chal[i] = 0xA5;
736         }
737 #endif
738
739 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
740                                         char chal[8])
741 {
742         char *start = q;
743         LSA_R_REQ_CHAL r_c;
744
745         /* set up the LSA REQUEST CHALLENGE response */
746
747         make_lsa_r_req_chal(&r_c, chal, 0);
748
749         /* store the response in the SMB stream */
750         q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
751
752         /* return length of SMB data stored */
753         return q - start; 
754 }
755
756 static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
757 {
758         memcpy(cred->data, resp_cred, sizeof(cred->data));
759 }
760
761 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
762                               char resp_cred[8], NEG_FLAGS *flgs, int status)
763 {
764         make_lsa_chal(&(r_a->srv_chal), resp_cred);
765         memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
766         r_a->status = status;
767 }
768
769 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
770                                 char resp_cred[8], int status)
771 {
772         char *start = q;
773         LSA_R_AUTH_2 r_a;
774
775         /* set up the LSA AUTH 2 response */
776
777         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
778
779         /* store the response in the SMB stream */
780         q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
781
782         /* return length of SMB data stored */
783         return q - start; 
784 }
785
786 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
787 {
788         make_lsa_chal(&(cred->challenge), srv_chal);
789         cred->timestamp = srv_time;
790 }
791         
792
793 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
794                               char srv_chal[8], UTIME srv_time, int status)
795 {
796         make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
797         r_a->status = status;
798 }
799
800 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
801                                 char srv_cred[8], UTIME srv_time,
802                                 int status)
803 {
804         char *start = q;
805         LSA_R_SRV_PWSET r_s;
806
807         /* set up the LSA Server Password Set response */
808         make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
809
810         /* store the response in the SMB stream */
811         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
812
813         /* return length of SMB data stored */
814         return q - start; 
815 }
816
817 static void make_lsa_user_info(LSA_USER_INFO *usr,
818
819         NTTIME *logon_time,
820         NTTIME *logoff_time,
821         NTTIME *kickoff_time,
822         NTTIME *pass_last_set_time,
823         NTTIME *pass_can_change_time,
824         NTTIME *pass_must_change_time,
825
826         char *user_name,
827         char *full_name,
828         char *logon_script,
829         char *profile_path,
830         char *home_dir,
831         char *dir_drive,
832
833         uint16 logon_count,
834         uint16 bad_pw_count,
835
836         uint32 user_id,
837         uint32 group_id,
838         uint32 num_groups,
839         DOM_GID *gids,
840         uint32 user_flgs,
841
842         char sess_key[16],
843
844         char *logon_srv,
845         char *logon_dom,
846
847         char *dom_sid,
848         char *other_sids) /* space-delimited set of SIDs */ 
849 {
850         /* only cope with one "other" sid, right now. */
851         /* need to count the number of space-delimited sids */
852         int i;
853         int num_other_sids = other_sids != NULL ? 1 : 0;
854
855         int len_user_name    = strlen(user_name   );
856         int len_full_name    = strlen(full_name   );
857         int len_logon_script = strlen(logon_script);
858         int len_profile_path = strlen(profile_path);
859         int len_home_dir     = strlen(home_dir    );
860         int len_dir_drive    = strlen(dir_drive   );
861
862         int len_logon_srv    = strlen(logon_srv);
863         int len_logon_dom    = strlen(logon_dom);
864
865         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
866
867         usr->logon_time            = *logon_time;
868         usr->logoff_time           = *logoff_time;
869         usr->kickoff_time          = *kickoff_time;
870         usr->pass_last_set_time    = *pass_last_set_time;
871         usr->pass_can_change_time  = *pass_can_change_time;
872         usr->pass_must_change_time = *pass_must_change_time;
873
874         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
875         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
876         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
877         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
878         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
879         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
880
881         usr->logon_count = logon_count;
882         usr->bad_pw_count = bad_pw_count;
883
884         usr->user_id = user_id;
885         usr->group_id = group_id;
886         usr->num_groups = num_groups;
887         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
888         usr->user_flgs = user_flgs;
889
890         if (sess_key != NULL)
891         {
892                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
893         }
894         else
895         {
896                 bzero(usr->sess_key, sizeof(usr->sess_key));
897         }
898
899         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
900         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
901
902         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
903
904         bzero(usr->padding, sizeof(usr->padding));
905
906         usr->num_other_sids = num_other_sids;
907         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
908         
909         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
910         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
911         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
912         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
913         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
914         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
915
916         usr->num_groups2 = num_groups;
917         for (i = 0; i < num_groups; i++)
918         {
919                 usr->gids[i] = gids[i];
920         }
921
922         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
923         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
924
925         make_dom_sid(&(usr->dom_sid), dom_sid);
926         make_dom_sid(&(usr->other_sids[0]), other_sids);
927 }
928
929
930 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
931                                 char srv_cred[8], UTIME srv_time,
932                                 LSA_USER_INFO *user_info)
933 {
934         char *start = q;
935         LSA_R_SAM_LOGON r_s;
936
937         /* XXXX maybe we want to say 'no', reject the client's credentials */
938         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
939         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
940
941         /* store the user information, if there is any. */
942         r_s.user = user_info;
943         r_s.buffer_user = user_info != NULL ? 1 : 0;
944         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
945
946         /* store the response in the SMB stream */
947         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
948
949         /* return length of SMB data stored */
950         return q - start; 
951 }
952
953
954 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
955                                 char srv_cred[8], UTIME srv_time,
956                                 uint32 status)
957 {
958         char *start = q;
959         LSA_R_SAM_LOGOFF r_s;
960
961         /* XXXX maybe we want to say 'no', reject the client's credentials */
962         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
963         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
964
965         r_s.status = status;
966
967         /* store the response in the SMB stream */
968         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
969
970         /* return length of SMB data stored */
971         return q - start; 
972 }
973
974
975 static void api_lsa_open_policy( char *param, char *data,
976                              char **rdata, int *rdata_len )
977 {
978         int reply_len;
979
980         /* we might actually want to decode the query, but it's not necessary */
981         /* lsa_io_q_open_policy(...); */
982
983         /* return a 20 byte policy handle */
984         reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18);
985
986         /* construct header, now that we know the reply length */
987         make_rpc_reply(data, *rdata, reply_len);
988         *rdata_len = reply_len + 0x18;
989 }
990
991 static void api_lsa_query_info( char *param, char *data,
992                                 char **rdata, int *rdata_len )
993 {
994         int reply_len;
995
996         LSA_Q_QUERY_INFO q_i;
997         pstring dom_name;
998         pstring dom_sid;
999
1000         /* grab the info class and policy handle */
1001         lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4);
1002
1003         pstrcpy(dom_name, lp_workgroup());
1004         pstrcpy(dom_sid , lp_domainsid());
1005
1006         /* construct reply.  return status is always 0x0 */
1007         reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, 
1008                                                                          dom_name, dom_sid);
1009
1010         /* construct header, now that we know the reply length */
1011         make_rpc_reply(data, *rdata, reply_len);
1012         *rdata_len = reply_len + 0x18;
1013 }
1014
1015 static void api_lsa_lookup_sids( char *param, char *data,
1016                                  char **rdata, int *rdata_len )
1017 {
1018         int reply_len;
1019
1020         int i;
1021         LSA_Q_LOOKUP_SIDS q_l;
1022         pstring dom_name;
1023         pstring dom_sid;
1024         fstring dom_sids[MAX_LOOKUP_SIDS];
1025
1026         /* grab the info class and policy handle */
1027         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4);
1028
1029         pstrcpy(dom_name, lp_workgroup());
1030         pstrcpy(dom_sid , lp_domainsid());
1031
1032         /* convert received SIDs to strings, so we can do them. */
1033         for (i = 0; i < q_l.num_entries; i++)
1034         {
1035                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1036         }
1037
1038         /* construct reply.  return status is always 0x0 */
1039         reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18,
1040                     q_l.num_entries, dom_sids, /* text-converted SIDs */
1041                                 dom_name, dom_sid, /* domain name, domain SID */
1042                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1043
1044         /* construct header, now that we know the reply length */
1045         make_rpc_reply(data, *rdata, reply_len);
1046         *rdata_len = reply_len + 0x18;
1047 }
1048
1049 static void api_lsa_lookup_names( char *param, char *data,
1050                                   char **rdata, int *rdata_len )
1051 {
1052         int reply_len;
1053
1054         int i;
1055         LSA_Q_LOOKUP_RIDS q_l;
1056         pstring dom_name;
1057         pstring dom_sid;
1058         uint32 dom_rids[MAX_LOOKUP_SIDS];
1059
1060         /* grab the info class and policy handle */
1061         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4);
1062
1063         pstrcpy(dom_name, lp_workgroup());
1064         pstrcpy(dom_sid , lp_domainsid());
1065
1066         /* convert received RIDs to strings, so we can do them. */
1067         for (i = 0; i < q_l.num_entries; i++)
1068         {
1069                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1070                 dom_rids[i] = name_to_rid(user_name);
1071         }
1072
1073         /* construct reply.  return status is always 0x0 */
1074         reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18,
1075                     q_l.num_entries, dom_rids, /* text-converted SIDs */
1076                                 dom_name, dom_sid, /* domain name, domain SID */
1077                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1078
1079         /* construct header, now that we know the reply length */
1080         make_rpc_reply(data, *rdata, reply_len);
1081         *rdata_len = reply_len + 0x18;
1082 }
1083
1084 BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
1085                      int mdrcnt,int mprcnt,
1086                      char **rdata,char **rparam,
1087                      int *rdata_len,int *rparam_len)
1088 {
1089         uint16 opnum = SVAL(data,22);
1090
1091         int pkttype = CVAL(data, 2);
1092         if (pkttype == 0x0b) /* RPC BIND */
1093         {
1094                 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1095                 LsarpcTNP1(data,rdata,rdata_len);
1096                 return True;
1097         }
1098
1099         DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1100         switch (opnum)
1101         {
1102                 case LSA_OPENPOLICY:
1103                 {
1104                         DEBUG(3,("LSA_OPENPOLICY\n"));
1105                         api_lsa_open_policy(param, data, rdata, rdata_len);
1106                         break;
1107                 }
1108
1109                 case LSA_QUERYINFOPOLICY:
1110                 {
1111                         DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
1112
1113                         api_lsa_query_info(param, data, rdata, rdata_len);
1114                         break;
1115                 }
1116
1117                 case LSA_ENUMTRUSTDOM:
1118                 {
1119                         char *q = *rdata + 0x18;
1120
1121                         DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
1122
1123                         initrpcreply(data, *rdata);
1124
1125                         SIVAL(q, 0, 0); /* enumeration context */
1126                         SIVAL(q, 0, 4); /* entries read */
1127                         SIVAL(q, 0, 8); /* trust information */
1128
1129                         endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1130
1131                         break;
1132                 }
1133
1134                 case LSA_CLOSE:
1135                 {
1136                         char *q = *rdata + 0x18;
1137
1138                         DEBUG(3,("LSA_CLOSE\n"));
1139
1140                         initrpcreply(data, *rdata);
1141
1142                         SIVAL(q, 0, 0);
1143                         SIVAL(q, 0, 4);
1144                         SIVAL(q, 0, 8);
1145                         SIVAL(q, 0, 12);
1146                         SIVAL(q, 0, 16);
1147
1148                         endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1149
1150                         break;
1151                 }
1152
1153                 case LSA_OPENSECRET:
1154                 {
1155                         char *q = *rdata + 0x18;
1156                         DEBUG(3,("LSA_OPENSECRET\n"));
1157
1158                         initrpcreply(data, *rdata);
1159
1160                         SIVAL(q, 0, 0);
1161                         SIVAL(q, 0, 4);
1162                         SIVAL(q, 0, 8);
1163                         SIVAL(q, 0, 12);
1164                         SIVAL(q, 0, 16);
1165
1166                         endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1167
1168                         break;
1169                 }
1170
1171                 case LSA_LOOKUPSIDS:
1172                 {
1173                         DEBUG(3,("LSA_OPENSECRET\n"));
1174                         api_lsa_lookup_sids(param, data, rdata, rdata_len);
1175                         break;
1176                 }
1177
1178                 case LSA_LOOKUPNAMES:
1179                 {
1180                         DEBUG(3,("LSA_LOOKUPNAMES\n"));
1181                         api_lsa_lookup_names(param, data, rdata, rdata_len);
1182                         break;
1183                 }
1184
1185                 default:
1186                 {
1187                         DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1188                         break;
1189                 }
1190         }
1191         return True;
1192 }
1193
1194
1195 #ifdef UNDEFINED_NTDOMAIN
1196 /*
1197    PAXX: Someone fix above.
1198    The above API is indexing RPC calls based on RPC flags and 
1199    fragment length. I've decided to do it based on operation number :-)
1200 */
1201
1202  BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
1203                      int mdrcnt,int mprcnt,
1204                      char **rdata,char **rparam,
1205                      int *rdata_len,int *rparam_len)
1206 {
1207         uint16 opnum;
1208         char *q;
1209         char *domainname;
1210         int domlen;
1211         pstring domsid;
1212         char *p;
1213         int numsubauths;
1214         int subauths[MAXSUBAUTHS];
1215         struct smb_passwd *smb_pass; /* To check if machine account exists */
1216         pstring machacct;
1217         pstring foo;
1218         uint16 infoclass;
1219         uint16 revision; /* Domain sid revision */
1220         int identauth;
1221         int i;
1222         char *logonsrv;
1223         char *unicomp;
1224         char *accountname;
1225         uint16 secchanneltype;
1226         uint32 negflags;
1227         char netcred[8];
1228         uint32 rcvcred[8];
1229         char rtncred[8];
1230         uint32 clnttime;
1231         uint32 rtntime;
1232         char *newpass;
1233         uint16 logonlevel;
1234         uint16 switchval;
1235         uint16 dommaxlen;
1236         uint16 paramcontrol;
1237         uint32 logonid[2];
1238         uint16 usernamelen;
1239         uint16 usernamemaxlen;
1240         uint16 wslen;
1241         uint16 wsmaxlen;
1242         uchar *rc4lmowfpass;
1243         uchar *rc4ntowfpass;
1244         char *domain;
1245         char *username;
1246         char *ws;
1247         struct uinfo *userinfo;
1248         int pkttype;
1249         uchar rc4key[16];
1250         uchar ntowfpass[16];
1251         uint32 nentries;
1252         char *policyhandle;
1253         #define MAXSIDS 64
1254         uchar *sids[MAXSIDS]; /* for lookup SID */
1255         int nsids;
1256         #define MAXNAMES 64
1257         uchar *names[MAXNAMES];
1258
1259   opnum = SVAL(data,22);
1260
1261   pkttype = CVAL(data, 2);
1262   if (pkttype == 0x0b) /* RPC BIND */
1263   {
1264     DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1265     LsarpcTNP1(data,rdata,rdata_len);
1266     return True;
1267   }
1268
1269   DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1270   initrpcreply(data, *rdata);
1271   DEBUG(4,("netlogon LINE %d\n",__LINE__));
1272   switch (opnum)
1273   {
1274     case LSAOPENPOLICY:
1275             DEBUG(1,("LSAOPENPOLICY\n"));
1276             char *q = *rdata + 0x18;
1277             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1278             /* return a 20 byte policy handle */
1279             /* here's a pretty handle:- */
1280             qSIVAL(time(NULL));
1281             qSIVAL(0x810a792f);
1282             qSIVAL(0x11d107d5);
1283             qSIVAL(time(NULL));
1284             qSIVAL(0x6cbcf800);
1285             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1286             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */
1287             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1288             break;
1289
1290     case LSAQUERYINFOPOLICY:
1291             DEBUG(1,("LSAQUERYINFOPOLICY\n"));
1292             dump_data(1,data,128);
1293             infoclass = SVAL(data, 44); /* also a policy handle but who cares? */
1294             q = *rdata + 0x18;
1295             qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose
1296                                     value is ignored */
1297             qSSVAL(infoclass);
1298             domainname = lp_workgroup();
1299             domlen = strlen(domainname);
1300             strcpy(domsid,lp_domainsid());
1301             DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1302             /* assume, but should check, that domsid starts "S-" */
1303             p = strtok(domsid+2,"-");
1304             revision = atoi(p);
1305             DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1306             identauth = atoi(strtok(0,"-"));
1307             DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1308             numsubauths = 0;
1309             while (p = strtok(0, "-"))
1310                     subauths[numsubauths++] = atoi(p);
1311             DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1312             
1313             switch (infoclass)
1314                     {
1315                     case 5:
1316                     case 3:
1317                     default:
1318                             qSSVAL(0); /* 2 undocumented bytes */
1319                             qSSVAL(domlen*2);
1320                             qSSVAL(domlen*2); /* unicode domain len and maxlen */
1321                             qSIVAL(4); /* domain buffer pointer */
1322                             qSIVAL(2); /* domain sid pointer */
1323                             qunistr(domainname);
1324                             qSIVAL(numsubauths);
1325                             qSCVAL(revision);
1326                             qSCVAL(numsubauths);
1327                             qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1328                             qRSIVAL(identauth); /* next 4 bytes */
1329                             for (i = 0; i < numsubauths; i++)
1330                                     {
1331                                             qSIVAL(subauths[i]);
1332                                     }
1333                     }
1334             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1335             break;
1336
1337     case LSAENUMTRUSTDOM:
1338             DEBUG(1,("LSAENUMTRUSTDOM\n"));
1339             q = *rdata + 0x18;
1340             qSIVAL(0); /* enumeration context */
1341             qSIVAL(0); /* entries read */
1342             qSIVAL(0); /* trust information */
1343             endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1344             break;
1345
1346     case LSACLOSE:
1347             DEBUG(1,("LSACLOSE\n"));
1348             q = *rdata + 0x18;
1349             qSIVAL(0);
1350             qSIVAL(0);
1351             qSIVAL(0);
1352             qSIVAL(0);
1353             qSIVAL(0);
1354             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1355       break;
1356
1357     case LSAOPENSECRET:
1358             DEBUG(1,("LSAOPENSECRET\n"));
1359             q = *rdata + 0x18;
1360             qSIVAL(0);
1361             qSIVAL(0);
1362             qSIVAL(0);
1363             qSIVAL(0);
1364             qSIVAL(0);
1365             endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1366       break;
1367
1368     case LSALOOKUPSIDS:
1369             DEBUG(1,("LSAOPENSECRET\n"));
1370             q = data + 0x18;
1371             policyhandle = q; q += 20;
1372             nentries = qIVAL;
1373             DEBUG(4,("lookupsid entries %d\n",nentries));
1374             q += (2+nentries) * 4; /* skip bufptrs */
1375             /* now we have nentries sids of the form:
1376                uint32  Subauthority count (SAC)
1377                char    Revision
1378                char    Subaurity count again
1379                char[6] Identifier authority
1380                [uint32  subauthority] * SAC
1381                */
1382             for (nsids = 0; nsids < nentries; nsids++)
1383                     {
1384                             DEBUG(4,("lookupsid q in %lx\n",q));
1385                             sids[nsids] = q;
1386                             DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0)));
1387                             q += 4+1+1+6+IVAL(q,0)*4;
1388                             DEBUG(4,("lookupsid q %lx\n",q));
1389                     }
1390       /* There's 16 bytes of something after all of that, don't know
1391          what it is though - incorrectly documented */
1392
1393       DEBUG(4,("lookupsid line %d\n",__LINE__));
1394       /* formulate reply */
1395       q = *rdata + 0x18;
1396       qSIVAL(2); /* bufptr */
1397       qSIVAL(4); /* number of referenced domains
1398                      - need one per each identifier authority in call */
1399       qSIVAL(2); /* dom bufptr */
1400       qSIVAL(32); /* max entries */
1401       qSIVAL(4); /* number of reference domains? */
1402
1403       qunihdr(lp_workgroup()); /* reference domain */
1404       qSIVAL(2); /* sid bufptr */
1405
1406       qunihdr("S-1-1");
1407       qSIVAL(2); /* sid bufptr */
1408
1409       qunihdr("S-1-5");
1410       qSIVAL(2); /* sid bufptr */
1411
1412       qunihdr("S-1-3");
1413       qSIVAL(2); /* sid bufptr */
1414
1415       qunistr(lp_workgroup());
1416       DEBUG(4,("lookupsid line %d\n",__LINE__));
1417
1418       strcpy(domsid,lp_domainsid());
1419       p = strtok(domsid+2,"-");
1420       revision = atoi(p);
1421       identauth = atoi(strtok(0,"-"));
1422       numsubauths = 0;
1423       while (p = strtok(0, "-"))
1424         subauths[numsubauths++] = atoi(p);
1425       qSIVAL(numsubauths);
1426       qSCVAL(revision);
1427       qSCVAL(numsubauths);
1428       qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1429       qRSIVAL(identauth); /* next 4 bytes */
1430       DEBUG(4,("lookupsid line %d\n",__LINE__));
1431       for (i = 0; i < numsubauths; i++)
1432       {
1433         qSIVAL(subauths[i]);
1434       }
1435       DEBUG(4,("lookupsid line %d\n",__LINE__));
1436
1437       qunistr("S-1-1");
1438       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1439       DEBUG(4,("lookupsid line %d\n",__LINE__));
1440
1441       qunistr("S-1-5");
1442       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1443
1444       qunistr("S-1-3");
1445       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1446
1447       qSIVAL(nentries);
1448       qSIVAL(2); /* bufptr */
1449       qSIVAL(nentries);
1450       DEBUG(4,("lookupsid line %d\n",__LINE__));
1451       for (i = 0; i < nentries; i++)
1452       {
1453         qSSVAL(5); /* SID name use ?! */
1454         qSSVAL(0); /* undocumented */
1455       DEBUG(4,("lookupsid line %d\n",__LINE__));
1456         qunihdr(sidtostring(sids[i]));
1457       DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i])));
1458         qSIVAL(0); /* domain index out of above reference domains */
1459       }
1460       DEBUG(4,("lookupsid line %d\n",__LINE__));
1461       for (i = 0; i < nentries; i++)
1462       {
1463         qunistr(sidtostring(sids[i]));
1464       }
1465       qSIVAL(nentries); /* mapped count */
1466       endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1467       break;
1468
1469     case LSALOOKUPNAMES:
1470             DEBUG(1,("LSALOOKUPNAMES\n"));
1471       q = data + 0x18;
1472       policyhandle = q; q += 20;
1473       nentries = qIVAL;
1474       DEBUG(4,("lookupnames entries %d\n",nentries));
1475       q += 4; /* skip second count */
1476       q += 8 * nentries; /* skip pointers */
1477       for (nnames = 0; nnames < nentries; nnames++)
1478       {
1479               names[nnames] = q; /* set name string to unicode header */
1480               q += IVAL(q,0)*2; /* guessing here */
1481       }
1482       /* There's a translated sids structure next but it looks fals */
1483
1484       DEBUG(4,("lookupnames line %d\n",__LINE__));
1485       /* formulate reply */
1486       q = *rdata + 0x18;
1487       qSIVAL(2); /* bufptr */
1488       qSIVAL(4); /* number of referenced domains
1489                      - need one per each identifier authority in call */
1490       qSIVAL(2); /* dom bufptr */
1491       qSIVAL(32); /* max entries */
1492       qSIVAL(4); /* number of reference domains? */
1493
1494       qunihdr(lp_workgroup()); /* reference domain */
1495       qSIVAL(2); /* sid bufptr */
1496
1497       qunihdr("S-1-1");
1498       qSIVAL(2); /* sid bufptr */
1499
1500       qunihdr("S-1-5");
1501       qSIVAL(2); /* sid bufptr */
1502
1503       qunihdr("S-1-3");
1504       qSIVAL(2); /* sid bufptr */
1505
1506       qunistr(lp_workgroup());
1507       DEBUG(4,("lookupnames line %d\n",__LINE__));
1508
1509       strcpy(domsid,lp_domainsid());
1510       p = strtok(domsid+2,"-");
1511       revision = atoi(p);
1512       identauth = atoi(strtok(0,"-"));
1513       numsubauths = 0;
1514       while (p = strtok(0, "-"))
1515         subauths[numsubauths++] = atoi(p);
1516       qSIVAL(numsubauths);
1517       qSCVAL(revision);
1518       qSCVAL(numsubauths);
1519       qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1520       qRSIVAL(identauth); /* next 4 bytes */
1521       DEBUG(4,("lookupsid line %d\n",__LINE__));
1522       for (i = 0; i < numsubauths; i++)
1523       {
1524         qSIVAL(subauths[i]);
1525       }
1526       DEBUG(4,("lookupsid line %d\n",__LINE__));
1527
1528       qunistr("S-1-1");
1529       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1530       DEBUG(4,("lookupsid line %d\n",__LINE__));
1531
1532       qunistr("S-1-5");
1533       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1534
1535       qunistr("S-1-3");
1536       qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1537
1538       qSIVAL(nentries);
1539       qSIVAL(2); /* bufptr */
1540       qSIVAL(nentries);
1541       DEBUG(4,("lookupnames line %d\n",__LINE__));
1542       for (i = 0; i < nentries; i++)
1543       {
1544         qSSVAL(5); /* SID name use  5 == well known sid, 1 == user sid see showacls */
1545         qSSVAL(5); /* undocumented */
1546       DEBUG(4,("lookupnames line %d\n",__LINE__));
1547         qSIVAL(nametorid(names[i]));
1548       DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i])));
1549         qSIVAL(0); /* domain index out of above reference domains */
1550       }
1551       qSIVAL(nentries); /* mapped count */
1552       endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1553       break;
1554
1555     default:
1556       DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1557   }
1558   return(True);
1559 }
1560
1561  BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
1562                      int mdrcnt,int mprcnt,
1563                      char **rdata,char **rparam,
1564                      int *rdata_len,int *rparam_len)
1565 {
1566   uint16 opnum;
1567   char *q;
1568   char *domainname;
1569   int domlen;
1570   pstring domsid;
1571   char *p;
1572   int numsubauths;
1573   int subauths[MAXSUBAUTHS];
1574   struct smb_passwd *smb_pass; /* To check if machine account exists */
1575   pstring machacct;
1576   pstring foo;
1577   uint16 infoclass;
1578   uint16 revision; /* Domain sid revision */
1579   int identauth;
1580   int i;
1581   char *logonsrv;
1582   char *unicomp;
1583   char *accountname;
1584   uint16 secchanneltype;
1585   uint32 negflags;
1586   char netcred[8];
1587   uint32 rcvcred[8];
1588   char rtncred[8];
1589   uint32 clnttime;
1590   uint32 rtntime;
1591   char *newpass;
1592   uint16 logonlevel;
1593   uint16 switchval;
1594   uint16 dommaxlen;
1595   uint16 paramcontrol;
1596   uint32 logonid[2];
1597   uint16 usernamelen;
1598   uint16 usernamemaxlen;
1599   uint16 wslen;
1600   uint16 wsmaxlen;
1601   uchar *rc4lmowfpass;
1602   uchar *rc4ntowfpass;
1603   char *domain;
1604   char *username;
1605   char *ws;
1606   struct uinfo *userinfo;
1607   int pkttype;
1608   ArcfourContext c;
1609   uchar rc4key[16];
1610   uchar ntowfpass[16];
1611
1612   opnum = SVAL(data,22);
1613
1614   pkttype = CVAL(data, 2);
1615   if (pkttype == 0x0b) /* RPC BIND */
1616   {
1617     DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1618     LsarpcTNP1(data,rdata,rdata_len);
1619     return True;
1620   }
1621
1622   DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum));
1623   initrpcreply(data, *rdata);
1624   DEBUG(4,("netlogon LINE %d\n",__LINE__));
1625   switch (opnum)
1626   {
1627     case LSAREQCHAL:
1628             DEBUG(1,("LSAREQCHAL\n"));
1629             q = data + 0x18;
1630             dump_data(1,q,128);
1631             logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */
1632             q = skip_unicode_string(logonsrv,1) + 12;
1633             q = align4(q, data);
1634             unicomp = q;
1635             q = skip_unicode_string(unicomp,1);
1636             
1637       
1638             DEBUG(1,("logonsrv=%s unicomp=%s\n", 
1639                      unistr(logonsrv), 
1640                      unistr(unicomp)));
1641       
1642             dcauth[cnum].chal[0] = IVAL(q, 0);
1643             dcauth[cnum].chal[1] = IVAL(q, 4);
1644             dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */
1645             dcauth[cnum].cred[1] = IVAL(q, 4);
1646
1647 DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1]));
1648
1649             /* PAXX: set these to random values */
1650             dcauth[cnum].svrchal[0] = 0x11111111;
1651             dcauth[cnum].svrchal[1] = 0x22222222;
1652             dcauth[cnum].svrcred[0] = 0x11111111;
1653             dcauth[cnum].svrcred[1] = 0x22222222;
1654             strcpy(machacct,unistr(unicomp));
1655             strcat(machacct, "$");
1656             smb_pass = get_smbpwnam(machacct);
1657             if(smb_pass)
1658                     memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16);
1659             else
1660                     {
1661                             /* No such machine account. Should error out here, but we'll
1662                                print and carry on */
1663                             DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct));
1664                     }
1665             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]);
1666             DEBUG(1,("pass %s %s\n", machacct, foo));
1667             setsesskey(cnum);
1668             q = *rdata + 0x18;
1669             qSIVAL(dcauth[cnum].svrchal[0]);
1670             qSIVAL(dcauth[cnum].svrchal[1]);
1671
1672 DEBUG(1,("NL: server challenge %08x %08x\n", 
1673          dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1]));
1674
1675             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1676             break;
1677
1678     case LSAAUTH2:
1679             DEBUG(1,("LSAAUTH2\n"));
1680             dump_data(1,q,128);
1681             q = data + 0x18;
1682             logonsrv = q + 16;
1683             q = skip_unicode_string(logonsrv,1)+12;
1684             q = align4(q, data);
1685             accountname = q;
1686
1687             q = skip_unicode_string(accountname,1);
1688             secchanneltype = qSVAL;
1689             q += 12;
1690             q = align4(q, data);
1691             unicomp = q;
1692             dump_data(1,unicomp,32);
1693             q = skip_unicode_string(unicomp,1);
1694             rcvcred[0] = qIVAL;
1695             rcvcred[1] = qIVAL;
1696             q = align4(q, data);
1697             negflags = qIVAL;
1698             DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", 
1699                      unistr(logonsrv), unistr(accountname), unistr(unicomp),
1700                      rcvcred[0], rcvcred[1], negflags));
1701
1702 DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", 
1703          rcvcred[0], rcvcred[1], negflags));
1704
1705             checkcred(cnum, rcvcred[0], rcvcred[1], 0);
1706             q = *rdata + 0x18;
1707             makecred(cnum, 0, q);
1708             q += 8;
1709
1710             qSIVAL(negflags);
1711             /* update stored client credentials */
1712             dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0];
1713             dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1];
1714             endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1715             break;
1716
1717     case LSASVRPWSET:
1718             DEBUG(1,("LSASVRPWSET\n"));
1719             q = data + 0x18;
1720             dump_data(1,q,128);
1721             logonsrv = q + 16;
1722             q = skip_unicode_string(logonsrv,1)+12;
1723             q = align4(q, data);
1724             accountname = q;
1725             q = skip_unicode_string(accountname,1);
1726             secchanneltype = qSVAL;
1727             q += 12;
1728             q = align4(q, data);
1729             unicomp = q;
1730             q = skip_unicode_string(unicomp,1);
1731             rcvcred[0] = qIVAL;
1732             rcvcred[1] = qIVAL;
1733             clnttime = qIVAL;
1734
1735             DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n",
1736                      unistr(logonsrv), unistr(accountname), unistr(unicomp)));
1737
1738             checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1739             DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags));
1740             newpass = q;
1741
1742             DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n",
1743                      unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass));
1744
1745             /* PAXX: For the moment we'll reject these */
1746             /* TODO Need to set newpass in smbpasswd file for accountname */
1747             q = *rdata + 0x18;
1748             makecred(cnum, clnttime+1, q);
1749             q += 8;
1750             qSIVAL(0); /* timestamp. Seems to be ignored */
1751             
1752             dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1753
1754             endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len);
1755             break;
1756
1757     case LSASAMLOGON:
1758             DEBUG(1,("LSASAMLOGON\n"));
1759             dump_data(1,data,128);
1760             q = data + 0x18;
1761             logonsrv = q + 16;
1762             DEBUG(1,("SMLOG %d\n", __LINE__));
1763             q = skip_unicode_string(logonsrv,1)+16;
1764             q = align4(q, data);
1765             unicomp = q;
1766             q = skip_unicode_string(unicomp,1)+4;
1767             DEBUG(1,("SMLOG %d  logonsrv=%s unicomp=%s\n", 
1768                      __LINE__, unistr(logonsrv), unistr(unicomp)));
1769             q = align4(q, data);
1770             rcvcred[0] = qIVAL;
1771             DEBUG(1,("SMLOG %d\n", __LINE__));
1772             rcvcred[1] = qIVAL;
1773             DEBUG(1,("SMLOG %d\n", __LINE__));
1774             clnttime = qIVAL;
1775             checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1776             q += 2;
1777             rtncred[0] = qIVAL; /* all these are ignored */
1778             DEBUG(1,("SMLOG %d\n", __LINE__));
1779             rtncred[1] = qIVAL;
1780             rtntime = qIVAL;
1781             logonlevel = qSVAL;
1782             DEBUG(1,("SMLOG %d\n", __LINE__));
1783             switchval = qSVAL;
1784             switch (switchval)
1785                     {
1786                     case 1:
1787                             
1788                             q += 6;
1789                             domlen = qSVAL;
1790                             dommaxlen = qSVAL; q += 4;
1791                             paramcontrol = qIVAL;
1792                             logonid[0] = qIVAL; /* low part */
1793                             logonid[1] = qIVAL; /* high part */
1794                             
1795                             usernamelen = qSVAL;
1796                             
1797                             DEBUG(1,("SMLOG %d\n", __LINE__));
1798                             usernamemaxlen = qSVAL; q += 4;
1799                             
1800                             DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", 
1801                                      usernamelen, usernamemaxlen, dommaxlen));
1802                             
1803                             dump_data(1,q,128);
1804                             
1805                             wslen = qSVAL;
1806                             wsmaxlen = qSVAL; q += 4;
1807                             rc4lmowfpass = q; q += 16;
1808                             rc4ntowfpass = q; q += 16;
1809                             
1810                             q += 12; domain = q; q += dommaxlen + 12;
1811                             q = align4(q, data);
1812                             username = q; q += usernamemaxlen + 12; 
1813                             q = align4(q, data);
1814                             ws = q;
1815                             DEBUG(1,("domain=%s username=%s ws=%s\n",
1816                                      unistr(domain), unistr(username),
1817                                      unistr(ws)));
1818                             break;
1819                     default: 
1820                             DEBUG(0,("unknown switch in SAMLOGON %d\n",
1821                                      switchval));
1822                     }
1823             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]);
1824             DEBUG(1,("userNAME %s  [%s]\n", foo, username));
1825             DEBUG(1,("SMLOG %d\n", __LINE__));
1826             q = *rdata + 0x18;
1827             qSIVAL(0x16a4b4); /* magic buffer pointer ? */
1828             makecred(cnum, clnttime+1, q);
1829             dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1830             q += 8;
1831             qSIVAL(0); /* timestamp. client doesn't care */
1832             qSSVAL(3); /* switch value 3. May be others? */
1833             qSSVAL(0); /* undocumented */
1834             DEBUG(1,("SMLOG %d\n", __LINE__));
1835             
1836             memset(rc4key, 0, sizeof rc4key);
1837             SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]);
1838             SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]);
1839             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]);
1840             DEBUG(1,("rc4ntowf %s\n", foo));
1841             arcfour_init(&c, rc4key, sizeof rc4key);
1842             arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass);
1843             for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]);
1844             DEBUG(1,("ntowf %s\n", foo));
1845             
1846             if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) {
1847                     qSIVAL(0); /* no buffer */
1848                     qSCVAL(1); /* Authoratitive. Change if passthrough? */
1849                     qSCVAL(0); /* pad for above boolean */
1850                     qSSVAL(0); /* pad for above boolean */
1851                     
1852                     endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len);
1853                     break;
1854             }
1855
1856             qSIVAL(2); /* another magic bufptr? */
1857       DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo));
1858       qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]);
1859       qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]);
1860       DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1]));
1861       qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]);
1862       qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]);
1863       qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]);
1864       qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]);
1865       DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename));
1866       qunihdr(userinfo->effectivename);
1867       qunihdr(userinfo->fullname);
1868       DEBUG(1,("SMLOG %d\n", __LINE__));
1869       qunihdr(userinfo->logonscript);
1870       qunihdr(userinfo->profilepath);
1871       qunihdr(userinfo->homedirectory);
1872       qunihdr(userinfo->homedirectorydrive);
1873       DEBUG(1,("SMLOG %d\n", __LINE__));
1874       qSSVAL(userinfo->logoncount);
1875       qSSVAL(userinfo->badpwcount);
1876       qSIVAL(userinfo->uid);
1877       qSIVAL(userinfo->gid);
1878       DEBUG(1,("SMLOG %d\n", __LINE__));
1879       qSIVAL(userinfo->ngroups);
1880       qSIVAL(8); /* ptr to groups */
1881       qSIVAL(userinfo->userflags);
1882       DEBUG(1,("SMLOG %d\n", __LINE__));
1883       qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */
1884       qunihdr(userinfo->logonserver);
1885       qunihdr(userinfo->logondomain);
1886       DEBUG(1,("SMLOG %d\n", __LINE__));
1887       qSIVAL(2); /* logon domain id ptr */
1888       DEBUG(1,("SMLOG %d\n", __LINE__));
1889       memset(q,0,40); q += 40; /* expansion room */
1890       DEBUG(1,("SMLOG %d\n", __LINE__));
1891       qSIVAL(userinfo->nsids);
1892       DEBUG(1,("SMLOG %d\n", __LINE__));
1893       qSIVAL(0); /* ptr to sids and values */
1894       DEBUG(1,("SMLOG %d\n", __LINE__));
1895       qunistr(userinfo->effectivename);
1896       DEBUG(1,("SMLOG %d\n", __LINE__));
1897       qunistr(userinfo->fullname);
1898       DEBUG(1,("SMLOG %d\n", __LINE__));
1899       qunistr(userinfo->logonscript);
1900       DEBUG(1,("SMLOG %d\n", __LINE__));
1901       qunistr(userinfo->profilepath);
1902       qunistr(userinfo->homedirectory);
1903       qunistr(userinfo->homedirectorydrive);
1904       DEBUG(1,("SMLOG %d\n", __LINE__));
1905       qSIVAL(userinfo->ngroups);
1906       for (i = 0; i < userinfo->ngroups; i++)
1907       {
1908         qSIVAL(userinfo->groups[i].gid);
1909         qSIVAL(userinfo->groups[i].attr);
1910       }
1911       qunistr(userinfo->logonserver);
1912       qunistr(userinfo->logondomain);
1913       for (i = 0; i < userinfo->nsids; i++)
1914       {
1915         /* put the extra sids: PAXX: TODO */
1916       }
1917       /* Assumption. This is the only domain, sending our SID */
1918       /* PAXX: may want to do passthrough later */
1919       strcpy(domsid,lp_domainsid());
1920   DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1921       /* assume, but should check, that domsid starts "S-" */
1922       p = strtok(domsid+2,"-");
1923       revision = atoi(p);
1924   DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1925       identauth = atoi(strtok(0,"-"));
1926   DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1927       numsubauths = 0;
1928       while (p = strtok(0, "-"))
1929         subauths[numsubauths++] = atoi(p);
1930       qSIVAL(numsubauths);
1931       qSCVAL(revision);
1932       qSCVAL(numsubauths);
1933       qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */
1934       qRSIVAL(identauth); /* next 4 bytes */
1935       DEBUG(1,("SMLOG %d\n", __LINE__));
1936       for (i = 0; i < numsubauths; i++)
1937       {
1938         qSIVAL(subauths[i]);
1939       }
1940       qSCVAL(1); /* Authoratitive. Change if passthrough? */
1941       qSCVAL(0); /* pad for above boolean */
1942       qSSVAL(0); /* pad for above boolean */
1943
1944       endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1945       break;
1946
1947     case LSASAMLOGOFF:
1948             DEBUG(1,("LSASAMLOGOFF\n"));
1949       q = data + 0x18;
1950       logonsrv = q + 16;
1951       DEBUG(1,("SAMLOGOFF %d\n", __LINE__));
1952       unicomp = skip_unicode_string(logonsrv,1)+16;
1953       if (strlen(unistr(logonsrv)) % 2 == 0)
1954         q += 2;
1955       DEBUG(1,("SMLOG %d\n", __LINE__));
1956       q = skip_unicode_string(unicomp,1)+4;
1957       if (strlen(unistr(unicomp)) % 2 == 0)
1958         q += 2;
1959       DEBUG(1,("SMLOG %d\n", __LINE__));
1960       rcvcred[0] = qIVAL;
1961       DEBUG(1,("SMLOG %d\n", __LINE__));
1962       rcvcred[1] = qIVAL;
1963       DEBUG(1,("SMLOG %d\n", __LINE__));
1964       clnttime = qIVAL;
1965       checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1966       q += 4;
1967       rtncred[0] = qIVAL; /* all these are ignored */
1968       DEBUG(1,("SMLOG %d\n", __LINE__));
1969       rtncred[1] = qIVAL;
1970       rtntime = qIVAL;
1971       logonlevel = qSVAL;
1972       DEBUG(1,("SMLOG %d\n", __LINE__));
1973       switchval = qSVAL;
1974       switch (switchval)
1975       {
1976         case 1:
1977           q += 4;
1978           domlen = qSVAL;
1979           dommaxlen = qSVAL; q += 4;
1980           paramcontrol = qIVAL;
1981           logonid[0] = qIVAL; /* low part */
1982           logonid[1] = qIVAL; /* high part */
1983           usernamelen = qSVAL;
1984       DEBUG(1,("SMLOG %d\n", __LINE__));
1985           usernamemaxlen = qSVAL; q += 4;
1986           wslen = qSVAL;
1987           wsmaxlen = qSVAL; q += 4;
1988           rc4lmowfpass = q; q += 16;
1989           rc4ntowfpass = q; q += 16;
1990           q += 12; domain = q; q += dommaxlen + 12;
1991           if ((domlen/2) % 2 != 0) q += 2;
1992           username = q; q += usernamemaxlen + 12; /* PAXX: HACK */
1993           if ((usernamelen/2) % 2 != 0) q += 2;
1994           ws = q;
1995           break;
1996         default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval));
1997       }
1998       DEBUG(1,("SAMLOGOFF %s\n", unistr(username)));
1999     default:
2000       DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
2001   }
2002   return(True);
2003 }
2004
2005 static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time)
2006 {
2007         uint32 sum[2];
2008         char netdata[8];
2009         char netsesskey[8];
2010         char calccred[8];
2011         char icv[8];
2012         char key2[7];
2013
2014         SIVAL(netdata, 0, dcauth[cnum].cred[0]+time);
2015         SIVAL(netdata, 4, dcauth[cnum].cred[1]);
2016         SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
2017         SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
2018         E1(netsesskey,netdata,icv);
2019         memset(key2, 0, sizeof key2);
2020         key2[0] = netsesskey[7];
2021         E1(key2, icv, calccred);
2022         if (IVAL(calccred,0) != cred0 ||
2023             IVAL(calccred,4) != cred1)
2024         {
2025           DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
2026                   cred0, cred1, time,
2027                   dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2028                   dcauth[cnum].cred[0], dcauth[cnum].cred[1],
2029                   IVAL(calccred,0),  IVAL(calccred,4)));
2030           /* PAXX: do something about it! */
2031         } else
2032           DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
2033                   cred0, cred1, time,
2034                   dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2035                   dcauth[cnum].cred[0], dcauth[cnum].cred[1],
2036                   IVAL(calccred,0),  IVAL(calccred,4)));
2037 }
2038
2039 static void makecred(int cnum, uint32 time, char *calccred)
2040 {
2041         uint32 sum[2];
2042         char netdata[8];
2043         char netsesskey[8];
2044         char icv[8];
2045         char key2[7];
2046
2047         SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time);
2048         SIVAL(netdata, 4, dcauth[cnum].svrcred[1]);
2049         SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
2050         SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
2051         E1(netsesskey,netdata,icv);
2052         memset(key2, 0, sizeof key2);
2053         key2[0] = netsesskey[7];
2054         E1(key2, icv, calccred);
2055         DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n",
2056            dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1],
2057            dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2058            dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1],
2059            IVAL(calccred, 0), IVAL(calccred, 4)));
2060 }
2061
2062 static void setsesskey(int cnum)
2063 {
2064         uint32 sum[2];
2065         char netsum[8];
2066         char netsesskey[8];
2067         char icv[8];
2068
2069         sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0];
2070         sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1];
2071         SIVAL(netsum,0,sum[0]);
2072         SIVAL(netsum,4,sum[1]);
2073         E1(dcauth[cnum].md4pw,netsum,icv);
2074         E1(dcauth[cnum].md4pw+9,icv,netsesskey);
2075         dcauth[cnum].sesskey[0] = IVAL(netsesskey,0);
2076         dcauth[cnum].sesskey[1] = IVAL(netsesskey,4);
2077
2078 DEBUG(1,("NL: session key %08x %08x\n",
2079          dcauth[cnum].sesskey[0],
2080          dcauth[cnum].sesskey[1]));
2081 }
2082
2083 static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass)
2084 {
2085   static struct uinfo u;
2086   static pstring fullnm;
2087   static pstring ascuser;
2088   extern pstring myname;
2089   static pstring stme;
2090   static pstring stdom;
2091   struct smb_passwd *smb_pass;
2092
2093   strcpy(ascuser,unistr(user));
2094   ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */
2095   DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len));
2096
2097   smb_pass = get_smbpwnam(ascuser);
2098   if(!smb_pass)
2099     return 0;
2100       DEBUG(1,("GETU %d\n", __LINE__));
2101       if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) {
2102               DEBUG(1,("pass mismatch:\n"));
2103               dump_data(1,ntowfpass,16);
2104               dump_data(1,smb_pass->smb_nt_passwd,16);
2105               return 0;
2106       }
2107
2108       DEBUG(1,("GETU %d\n", __LINE__));
2109   u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff;
2110   u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff;
2111   u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff;
2112       DEBUG(1,("GETU %d\n", __LINE__));
2113   u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff;
2114   u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff;
2115   u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff;
2116       DEBUG(1,("GETU %d\n", __LINE__));
2117   u.effectivename = ascuser;
2118   strcpy(fullnm, "Full name of ");
2119   strcat(fullnm, ascuser);
2120       DEBUG(1,("GETU %d\n", __LINE__));
2121   u.fullname = fullnm;
2122   u.logonscript = "foologin.cmd";
2123   u.profilepath = "prof";
2124   u.homedirectory = "foohomes";
2125       DEBUG(1,("GETU %d\n", __LINE__));
2126   u.homedirectorydrive = "a:";
2127   u.logoncount = 7;
2128   u.badpwcount = 8;
2129   u.uid = 778;
2130       DEBUG(1,("GETU %d\n", __LINE__));
2131   u.gid = 998;
2132   u.ngroups = 2;
2133   u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2));
2134   u.groups[0].gid = 776;
2135       DEBUG(1,("GETU %d\n", __LINE__));
2136   u.groups[0].attr = 0x7;
2137   u.groups[1].gid = 776;
2138   u.groups[1].attr = 0x7;
2139   u.userflags = 0x20;
2140   u.logonserver = stme;
2141   get_myname(myname,NULL);
2142   strcpy(stme, myname);
2143   strupper(stme);
2144   DEBUG(1,("LS %s\n", u.logonserver));
2145   u.logondomain = stdom;
2146   strcpy(stdom, lp_workgroup());
2147   strupper(stdom);
2148   DEBUG(1,("DOM %s\n", u.logondomain));
2149   u.nsids = 0;
2150   u.sids = 0;
2151       DEBUG(1,("GETU %d\n", __LINE__));
2152   return &u;
2153 };
2154
2155
2156 #endif /* NTDOMAIN */
2157 /* space in front of this function so that make proto doesn't pick it up */
2158  void _dummy_function(void)
2159 {
2160         UTIME t;
2161         lsa_reply_req_chal(NULL, NULL, NULL, NULL);
2162         lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0);
2163         lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0);
2164         make_lsa_user_info(NULL,
2165                                                 NULL, NULL, NULL, NULL, NULL, NULL,
2166                                            NULL, NULL, NULL, NULL, NULL, NULL,
2167                                                 0, 0,
2168                         0, 0, 0, NULL, 0,
2169                                                  NULL,
2170                                                 NULL, NULL,
2171                                                 NULL, NULL);
2172         lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL);
2173         lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0);
2174 }