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