locking.c: Added fix for race condition in slow share mode code.
[kai/samba.git] / source3 / smbd / pipes.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Pipe SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1997,
6                  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 #if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */
368
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 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
376 /* identauth >= 2^32 can be detected because it will be specified in hex */
377 static void make_dom_sid(DOM_SID *sid, char *domsid)
378 {
379         int identauth;
380         char *p;
381
382         DEBUG(4,("netlogon domain SID: %s\n", domsid));
383
384         /* assume, but should check, that domsid starts "S-" */
385         p = strtok(domsid+2,"-");
386         sid->sid_no = atoi(p);
387
388         /* identauth in decimal should be <  2^32 */
389         /* identauth in hex     should be >= 2^32 */
390         identauth = atoi(strtok(0,"-"));
391
392         DEBUG(4,("netlogon rev %d\n", sid->sid_no));
393         DEBUG(4,("netlogon %s ia %d\n", p, identauth));
394
395         sid->id_auth[0] = 0;
396         sid->id_auth[1] = 0;
397         sid->id_auth[2] = (identauth & 0xff000000) >> 24;
398         sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
399         sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
400         sid->id_auth[5] = (identauth & 0x000000ff);
401
402         sid->num_auths = 0;
403
404         while ((p = strtok(0, "-")) != NULL)
405         {
406                 sid->sub_auths[sid->num_auths++] = atoi(p);
407         }
408 }
409
410 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
411 {
412         if (hdr == NULL) return;
413
414         hdr->major        = 5;               /* RPC version 5 */
415         hdr->minor        = 0;               /* minor version 0 */
416         hdr->pkt_type     = 2;               /* RPC response packet */
417         hdr->frag         = 3;               /* first frag + last frag */
418         hdr->pack_type    = 1;               /* packed data representation */
419         hdr->frag_len     = data_len;        /* fragment length, fill in later */
420         hdr->auth_len     = 0;               /* authentication length */
421         hdr->call_id      = call_id;         /* call identifier - match incoming RPC */
422         hdr->alloc_hint   = data_len - 0x18; /* allocation hint (no idea) */
423         hdr->context_id   = 0;               /* presentation context identifier */
424         hdr->cancel_count = 0;               /* cancel count */
425         hdr->reserved     = 0;               /* reserved */
426 }
427
428 static void make_rpc_reply(char *inbuf, char *q, char *base, int data_len)
429 {
430         uint32 callid = RIVAL(inbuf, 12);
431         RPC_HDR hdr;
432
433         create_rpc_reply(&hdr, callid, data_len);
434         smb_io_rpc_hdr(False, &hdr, q, base, 4);
435 }
436
437 static int lsa_reply_open_policy(char *q, char *base)
438 {
439         char *start = q;
440         LSA_R_OPEN_POL r_o;
441
442         /* set up the LSA QUERY INFO response */
443         bzero(&(r_o.pol.data), POL_HND_SIZE);
444         r_o.status = 0x0;
445
446         /* store the response in the SMB stream */
447         q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
448
449         /* return length of SMB data stored */
450         return q - start; 
451 }
452
453 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
454 {
455         hdr->uni_max_len = max_len;
456         hdr->uni_str_len = len;
457         hdr->undoc       = terminate;
458 }
459
460 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
461 {
462         /* set up string lengths. add one if string is not null-terminated */
463         str->uni_max_len = len + (terminate != 0 ? 1 : 0);
464         str->undoc       = 0;
465         str->uni_str_len = len;
466
467         /* store the string (null-terminated copy) */
468         PutUniCode((char *)str->buffer, buf);
469
470         /* overwrite the last character: some strings are terminated with 4 not 0 */
471         str->buffer[len] = (uint16)terminate;
472 }
473
474 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
475 {
476         int domlen = strlen(dom_name);
477
478         d_q->uni_dom_max_len = domlen * 2;
479         d_q->padding = 0;
480         d_q->uni_dom_str_len = domlen * 2;
481
482         d_q->buffer_dom_name = 0; /* domain buffer pointer */
483         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
484
485         /* NOT null-terminated: 4-terminated instead! */
486         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
487
488         make_dom_sid(&(d_q->dom_sid), dom_sid);
489 }
490
491 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
492                                 char *dom_name, char *dom_sid)
493 {
494         char *start = q;
495         LSA_R_QUERY_INFO r_q;
496
497         /* set up the LSA QUERY INFO response */
498
499         r_q.undoc_buffer = 1; /* not null */
500         r_q.info_class = q_q->info_class;
501
502         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
503
504         r_q.status = 0x0;
505
506         /* store the response in the SMB stream */
507         q = lsa_io_r_query(False, &r_q, q, base, 4);
508
509         /* return length of SMB data stored */
510         return q - start; 
511 }
512
513 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
514 {
515         memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
516         r_c->status = status;
517 }
518
519 #if 0
520         char chal[8];
521         /* PAXX: set these to random values */
522         for (int i = 0; i < 8; i+++)
523         {
524                 chal[i] = 0xA5;
525         }
526 #endif
527
528 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
529                                         char chal[8])
530 {
531         char *start = q;
532         LSA_R_REQ_CHAL r_c;
533
534         /* set up the LSA REQUEST CHALLENGE response */
535
536         make_lsa_r_req_chal(&r_c, chal, 0);
537
538         /* store the response in the SMB stream */
539         q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
540
541         /* return length of SMB data stored */
542         return q - start; 
543 }
544
545 static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
546 {
547         memcpy(cred->data, resp_cred, sizeof(cred->data));
548 }
549
550 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
551                               char resp_cred[8], NEG_FLAGS *flgs, int status)
552 {
553         make_lsa_chal(&(r_a->srv_chal), resp_cred);
554         memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
555         r_a->status = status;
556 }
557
558 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
559                                 char resp_cred[8], int status)
560 {
561         char *start = q;
562         LSA_R_AUTH_2 r_a;
563
564         /* set up the LSA AUTH 2 response */
565
566         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
567
568         /* store the response in the SMB stream */
569         q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
570
571         /* return length of SMB data stored */
572         return q - start; 
573 }
574
575 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
576 {
577         make_lsa_chal(&(cred->challenge), srv_chal);
578         cred->timestamp = srv_time;
579 }
580         
581
582 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
583                               char srv_chal[8], UTIME srv_time, int status)
584 {
585         make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
586         r_a->status = status;
587 }
588
589 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
590                                 char srv_cred[8], UTIME srv_time,
591                                 int status)
592 {
593         char *start = q;
594         LSA_R_SRV_PWSET r_s;
595
596         /* set up the LSA Server Password Set response */
597         make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
598
599         /* store the response in the SMB stream */
600         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
601
602         /* return length of SMB data stored */
603         return q - start; 
604 }
605
606 static void make_lsa_user_info(LSA_USER_INFO *usr,
607
608         NTTIME *logon_time,
609         NTTIME *logoff_time,
610         NTTIME *kickoff_time,
611         NTTIME *pass_last_set_time,
612         NTTIME *pass_can_change_time,
613         NTTIME *pass_must_change_time,
614
615         char *user_name,
616         char *full_name,
617         char *logon_script,
618         char *profile_path,
619         char *home_dir,
620         char *dir_drive,
621
622         uint16 logon_count,
623         uint16 bad_pw_count,
624
625         uint32 user_id,
626         uint32 group_id,
627         uint32 num_groups,
628         DOM_GID *gids,
629         uint32 user_flgs,
630
631         char sess_key[16],
632
633         char *logon_srv,
634         char *logon_dom,
635
636         char *dom_sid,
637         char *other_sids) /* space-delimited set of SIDs */ 
638 {
639         /* only cope with one "other" sid, right now. */
640         /* need to count the number of space-delimited sids */
641         int i;
642         int num_other_sids = other_sids != NULL ? 1 : 0;
643
644         int len_user_name    = strlen(user_name   );
645         int len_full_name    = strlen(full_name   );
646         int len_logon_script = strlen(logon_script);
647         int len_profile_path = strlen(profile_path);
648         int len_home_dir     = strlen(home_dir    );
649         int len_dir_drive    = strlen(dir_drive   );
650
651         int len_logon_srv    = strlen(logon_srv);
652         int len_logon_dom    = strlen(logon_dom);
653
654         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
655
656         usr->logon_time            = *logon_time;
657         usr->logoff_time           = *logoff_time;
658         usr->kickoff_time          = *kickoff_time;
659         usr->pass_last_set_time    = *pass_last_set_time;
660         usr->pass_can_change_time  = *pass_can_change_time;
661         usr->pass_must_change_time = *pass_must_change_time;
662
663         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
664         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
665         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
666         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
667         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
668         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
669
670         usr->logon_count = logon_count;
671         usr->bad_pw_count = bad_pw_count;
672
673         usr->user_id = user_id;
674         usr->group_id = group_id;
675         usr->num_groups = num_groups;
676         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
677         usr->user_flgs = user_flgs;
678
679         if (sess_key != NULL)
680         {
681                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
682         }
683         else
684         {
685                 bzero(usr->sess_key, sizeof(usr->sess_key));
686         }
687
688         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
689         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
690
691         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
692
693         bzero(usr->padding, sizeof(usr->padding));
694
695         usr->num_other_sids = num_other_sids;
696         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
697         
698         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
699         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
700         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
701         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
702         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
703         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
704
705         usr->num_groups2 = num_groups;
706         for (i = 0; i < num_groups; i++)
707         {
708                 usr->gids[i] = gids[i];
709         }
710
711         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
712         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
713
714         make_dom_sid(&(usr->dom_sid), dom_sid);
715         make_dom_sid(&(usr->other_sids[0]), other_sids);
716 }
717
718
719 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
720                                 char srv_cred[8], UTIME srv_time,
721                                 LSA_USER_INFO *user_info)
722 {
723         char *start = q;
724         LSA_R_SAM_LOGON r_s;
725
726         /* XXXX maybe we want to say 'no', reject the client's credentials */
727         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
728         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
729
730         /* store the user information, if there is any. */
731         r_s.user = user_info;
732         r_s.buffer_user = user_info != NULL ? 1 : 0;
733         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
734
735         /* store the response in the SMB stream */
736         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
737
738         /* return length of SMB data stored */
739         return q - start; 
740 }
741
742
743 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
744                                 char srv_cred[8], UTIME srv_time,
745                                 uint32 status)
746 {
747         char *start = q;
748         LSA_R_SAM_LOGOFF r_s;
749
750         /* XXXX maybe we want to say 'no', reject the client's credentials */
751         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
752         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
753
754         r_s.status = status;
755
756         /* store the response in the SMB stream */
757         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
758
759         /* return length of SMB data stored */
760         return q - start; 
761 }
762
763 #endif /* LUKE PLEASE CHECK THIS !! */