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