- added some error checking
[kai/samba.git] / source / smbd / process.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    process incoming packets - main loop
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 struct timeval smb_last_time;
27
28 static char *InBuffer = NULL;
29 char *OutBuffer = NULL;
30 char *last_inbuf = NULL;
31
32 /* 
33  * Size of data we can send to client. Set
34  *  by the client for all protocols above CORE.
35  *  Set by us for CORE protocol.
36  */
37 int max_send = BUFFER_SIZE;
38 /*
39  * Size of the data we can receive. Set by us.
40  * Can be modified by the max xmit parameter.
41  */
42 int max_recv = BUFFER_SIZE;
43
44 extern int last_message;
45 extern int global_oplock_break;
46 extern pstring sesssetup_user;
47 extern char *last_inbuf;
48 extern char *InBuffer;
49 extern char *OutBuffer;
50 extern int smb_read_error;
51 extern VOLATILE SIG_ATOMIC_T reload_after_sighup;
52 extern BOOL global_machine_password_needs_changing;
53 extern fstring global_myworkgroup;
54 extern pstring global_myname;
55 extern int max_send;
56
57 /****************************************************************************
58  structure to hold a linked list of queued messages.
59  for processing.
60 ****************************************************************************/
61
62 typedef struct {
63    ubi_slNode msg_next;
64    char *msg_buf;
65    int msg_len;
66 } pending_message_list;
67
68 static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
69
70 /****************************************************************************
71  Function to push a message onto the tail of a linked list of smb messages ready
72  for processing.
73 ****************************************************************************/
74
75 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
76 {
77   pending_message_list *msg = (pending_message_list *)
78                                malloc(sizeof(pending_message_list));
79
80   if(msg == NULL)
81   {
82     DEBUG(0,("push_message: malloc fail (1)\n"));
83     return False;
84   }
85
86   msg->msg_buf = (char *)malloc(msg_len);
87   if(msg->msg_buf == NULL)
88   {
89     DEBUG(0,("push_message: malloc fail (2)\n"));
90     free((char *)msg);
91     return False;
92   }
93
94   memcpy(msg->msg_buf, buf, msg_len);
95   msg->msg_len = msg_len;
96
97   ubi_slAddTail( list_head, msg);
98
99   return True;
100 }
101
102 /****************************************************************************
103  Function to push a smb message onto a linked list of local smb messages ready
104  for processing.
105 ****************************************************************************/
106
107 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
108 {
109   return push_message(&smb_oplock_queue, buf, msg_len);
110 }
111
112 /****************************************************************************
113   Do a select on an two fd's - with timeout. 
114
115   If a local udp message has been pushed onto the
116   queue (this can only happen during oplock break
117   processing) return this first.
118
119   If a pending smb message has been pushed onto the
120   queue (this can only happen during oplock break
121   processing) return this next.
122
123   If the first smbfd is ready then read an smb from it.
124   if the second (loopback UDP) fd is ready then read a message
125   from it and setup the buffer header to identify the length
126   and from address.
127   Returns False on timeout or error.
128   Else returns True.
129
130 The timeout is in milli seconds
131 ****************************************************************************/
132
133 static BOOL receive_message_or_smb(char *buffer, int buffer_len, 
134                                    int timeout, BOOL *got_smb)
135 {
136   fd_set fds;
137   int selrtn;
138   struct timeval to;
139   int maxfd;
140
141   smb_read_error = 0;
142
143   *got_smb = False;
144
145   /*
146    * Check to see if we already have a message on the smb queue.
147    * If so - copy and return it.
148    */
149   
150   if(ubi_slCount(&smb_oplock_queue) != 0)
151   {
152     pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
153     memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
154   
155     /* Free the message we just copied. */
156     free((char *)msg->msg_buf);
157     free((char *)msg);
158     *got_smb = True;
159
160     DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
161     return True;
162   }
163
164   /*
165    * Setup the select read fd set.
166    */
167
168   FD_ZERO(&fds);
169   FD_SET(smbd_server_fd(),&fds);
170   maxfd = setup_oplock_select_set(&fds);
171
172   to.tv_sec = timeout / 1000;
173   to.tv_usec = (timeout % 1000) * 1000;
174
175   selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
176
177   /* Check if error */
178   if(selrtn == -1) {
179     /* something is wrong. Maybe the socket is dead? */
180     smb_read_error = READ_ERROR;
181     return False;
182   } 
183     
184   /* Did we timeout ? */
185   if (selrtn == 0) {
186     smb_read_error = READ_TIMEOUT;
187     return False;
188   }
189
190   if (FD_ISSET(smbd_server_fd(),&fds))
191   {
192     *got_smb = True;
193     return receive_smb(smbd_server_fd(), buffer, 0);
194   }
195   else
196   {
197     return receive_local_message(&fds, buffer, buffer_len, 0);
198   }
199 }
200
201 /****************************************************************************
202 Get the next SMB packet, doing the local message processing automatically.
203 ****************************************************************************/
204
205 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
206 {
207   BOOL got_smb = False;
208   BOOL ret;
209
210   do
211   {
212     ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb);
213
214     if(ret && !got_smb)
215     {
216       /* Deal with oplock break requests from other smbd's. */
217       process_local_message(inbuf, bufsize);
218       continue;
219     }
220
221     if(ret && (CVAL(inbuf,0) == 0x85))
222     {
223       /* Keepalive packet. */
224       got_smb = False;
225     }
226
227   }
228   while(ret && !got_smb);
229
230   return ret;
231 }
232
233 /****************************************************************************
234  We're terminating and have closed all our files/connections etc.
235  If there are any pending local messages we need to respond to them
236  before termination so that other smbds don't think we just died whilst
237  holding oplocks.
238 ****************************************************************************/
239
240 void respond_to_all_remaining_local_messages(void)
241 {
242   char buffer[1024];
243   fd_set fds;
244
245   /*
246    * Assert we have no exclusive open oplocks.
247    */
248
249   if(get_number_of_exclusive_open_oplocks()) {
250     DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
251           get_number_of_exclusive_open_oplocks() ));
252     return;
253   }
254
255   /*
256    * Setup the select read fd set.
257    */
258
259   FD_ZERO(&fds);
260   if(!setup_oplock_select_set(&fds))
261     return;
262
263   /*
264    * Keep doing receive_local_message with a 1 ms timeout until
265    * we have no more messages.
266    */
267
268   while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
269     /* Deal with oplock break requests from other smbd's. */
270     process_local_message(buffer, sizeof(buffer));
271
272     FD_ZERO(&fds);
273     (void)setup_oplock_select_set(&fds);
274   }
275
276   return;
277 }
278
279
280 /*
281 These flags determine some of the permissions required to do an operation 
282
283 Note that I don't set NEED_WRITE on some write operations because they
284 are used by some brain-dead clients when printing, and I don't want to
285 force write permissions on print services.
286 */
287 #define AS_USER (1<<0)
288 #define NEED_WRITE (1<<1)
289 #define TIME_INIT (1<<2)
290 #define CAN_IPC (1<<3)
291 #define AS_GUEST (1<<5)
292 #define QUEUE_IN_OPLOCK (1<<6)
293
294 /* 
295    define a list of possible SMB messages and their corresponding
296    functions. Any message that has a NULL function is unimplemented -
297    please feel free to contribute implementations!
298 */
299 struct smb_message_struct
300 {
301   int code;
302   char *name;
303   int (*fn)(connection_struct *conn, char *, char *, int, int);
304   int flags;
305 }
306  smb_messages[] = {
307
308     /* CORE PROTOCOL */
309
310    {SMBnegprot,"SMBnegprot",reply_negprot,0},
311    {SMBtcon,"SMBtcon",reply_tcon,0},
312    {SMBtdis,"SMBtdis",reply_tdis,0},
313    {SMBexit,"SMBexit",reply_exit,0},
314    {SMBioctl,"SMBioctl",reply_ioctl,0},
315    {SMBecho,"SMBecho",reply_echo,0},
316    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
317    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
318    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
319    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
320    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
321    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
322    {SMBsearch,"SMBsearch",reply_search,AS_USER},
323    {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
324
325    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
326    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
327    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
328
329    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
330    {SMBread,"SMBread",reply_read,AS_USER},
331    {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC },
332    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC },
333    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
334    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
335    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
336    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
337
338    /* this is a Pathworks specific call, allowing the 
339       changing of the root path */
340    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
341
342    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
343    {SMBflush,"SMBflush",reply_flush,AS_USER},
344    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
345    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
346    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
347    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
348    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
349    {SMBlock,"SMBlock",reply_lock,AS_USER},
350    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
351    
352    /* CORE+ PROTOCOL FOLLOWS */
353    
354    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
355    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
356    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
357    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
358    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
359    
360    /* LANMAN1.0 PROTOCOL FOLLOWS */
361    
362    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
363    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
364    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
365    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
366    {SMBwritec,"SMBwritec",NULL,AS_USER},
367    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
368    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER },
369    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
370    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
371    {SMBioctls,"SMBioctls",NULL,AS_USER},
372    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
373    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
374    
375    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
376    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
377    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
378    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER },
379    
380    {SMBffirst,"SMBffirst",reply_search,AS_USER},
381    {SMBfunique,"SMBfunique",reply_search,AS_USER},
382    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
383
384    /* LANMAN2.0 PROTOCOL FOLLOWS */
385    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
386    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
387    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
388    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
389
390    /* NT PROTOCOL FOLLOWS */
391    {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
392    {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
393    {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
394    {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 },
395
396    /* messaging routines */
397    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
398    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
399    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
400    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
401
402    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
403    
404    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
405    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
406    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
407    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
408  };
409
410
411 /****************************************************************************
412 do a switch on the message type, and return the response size
413 ****************************************************************************/
414 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
415 {
416   static pid_t pid= (pid_t)-1;
417   int outsize = 0;
418   static int num_smb_messages = 
419     sizeof(smb_messages) / sizeof(struct smb_message_struct);
420   int match;
421   extern int global_smbpid;
422
423   if (pid == (pid_t)-1)
424     pid = getpid();
425
426   errno = 0;
427   last_message = type;
428
429   /* make sure this is an SMB packet */
430   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
431   {
432     DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
433     return(-1);
434   }
435
436   for (match=0;match<num_smb_messages;match++)
437     if (smb_messages[match].code == type)
438       break;
439
440   /* yuck! this is an interim measure before we get rid of our
441      current inbuf/outbuf system */
442   global_smbpid = SVAL(inbuf,smb_pid);
443
444   if (match == num_smb_messages)
445   {
446     DEBUG(0,("Unknown message type %d!\n",type));
447     outsize = reply_unknown(inbuf,outbuf);
448   }
449   else
450   {
451     DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid));
452
453     if(global_oplock_break)
454     {
455       int flags = smb_messages[match].flags;
456
457       if(flags & QUEUE_IN_OPLOCK)
458       {
459         /* 
460          * Queue this message as we are the process of an oplock break.
461          */
462
463         DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
464         DEBUGADD( 2, ( "oplock break state.\n" ) );
465
466         push_oplock_pending_smb_message( inbuf, size );
467         return -1;
468       }          
469     }
470     if (smb_messages[match].fn)
471     {
472       int flags = smb_messages[match].flags;
473       static uint16 last_session_tag = UID_FIELD_INVALID;
474       /* In share mode security we must ignore the vuid. */
475       uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
476       connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
477
478
479       /* Ensure this value is replaced in the incoming packet. */
480       SSVAL(inbuf,smb_uid,session_tag);
481
482       /*
483        * Ensure the correct username is in sesssetup_user.
484        * This is a really ugly bugfix for problems with
485        * multiple session_setup_and_X's being done and
486        * allowing %U and %G substitutions to work correctly.
487        * There is a reason this code is done here, don't
488        * move it unless you know what you're doing... :-).
489        * JRA.
490        */
491       if (session_tag != last_session_tag) {
492         user_struct *vuser = NULL;
493
494         last_session_tag = session_tag;
495         if(session_tag != UID_FIELD_INVALID)
496           vuser = get_valid_user_struct(session_tag);           
497         if(vuser != NULL)
498           pstrcpy( sesssetup_user, vuser->requested_name);
499       }
500
501       /* does this protocol need to be run as root? */
502       if (!(flags & AS_USER))
503         unbecome_user();
504
505       /* does this protocol need to be run as the connected user? */
506       if ((flags & AS_USER) && !become_user(conn,session_tag)) {
507         if (flags & AS_GUEST) 
508           flags &= ~AS_USER;
509         else
510           return(ERROR(ERRSRV,ERRaccess));
511       }
512       /* this code is to work around a bug is MS client 3 without
513          introducing a security hole - it needs to be able to do
514          print queue checks as guest if it isn't logged in properly */
515       if (flags & AS_USER)
516         flags &= ~AS_GUEST;
517
518       /* does it need write permission? */
519       if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
520         return(ERROR(ERRSRV,ERRaccess));
521
522       /* ipc services are limited */
523       if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
524         return(ERROR(ERRSRV,ERRaccess));            
525       }
526
527       /* load service specific parameters */
528       if (conn && 
529           !become_service(conn,(flags & AS_USER)?True:False)) {
530         return(ERROR(ERRSRV,ERRaccess));
531       }
532
533       /* does this protocol need to be run as guest? */
534       if ((flags & AS_GUEST) && 
535           (!become_guest() || 
536            !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
537         return(ERROR(ERRSRV,ERRaccess));
538       }
539
540       last_inbuf = inbuf;
541
542       outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize);
543     }
544     else
545     {
546       outsize = reply_unknown(inbuf,outbuf);
547     }
548   }
549
550   return(outsize);
551 }
552
553
554 /****************************************************************************
555   construct a reply to the incoming packet
556 ****************************************************************************/
557 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
558 {
559   int type = CVAL(inbuf,smb_com);
560   int outsize = 0;
561   int msg_type = CVAL(inbuf,0);
562
563   GetTimeOfDay(&smb_last_time);
564
565   chain_size = 0;
566   file_chain_reset();
567   reset_chain_p();
568
569   if (msg_type != 0)
570     return(reply_special(inbuf,outbuf));  
571
572   construct_reply_common(inbuf, outbuf);
573
574   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
575
576   outsize += chain_size;
577
578   if(outsize > 4)
579     smb_setlen(outbuf,outsize - 4);
580   return(outsize);
581 }
582
583
584 /****************************************************************************
585   process an smb from the client - split out from the process() code so
586   it can be used by the oplock break code.
587 ****************************************************************************/
588 void process_smb(char *inbuf, char *outbuf)
589 {
590 #ifdef WITH_SSL
591   extern BOOL sslEnabled;     /* don't use function for performance reasons */
592   static int sslConnected = 0;
593 #endif /* WITH_SSL */
594   static int trans_num;
595   int msg_type = CVAL(inbuf,0);
596   int32 len = smb_len(inbuf);
597   int nread = len + 4;
598
599 #ifdef WITH_PROFILE
600   profile_p->smb_count++;
601 #endif
602
603   if (trans_num == 0) {
604           /* on the first packet, check the global hosts allow/ hosts
605              deny parameters before doing any parsing of the packet
606              passed to us by the client.  This prevents attacks on our
607              parsing code from hosts not in the hosts allow list */
608           if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
609                   /* send a negative session response "not listining on calling
610                    name" */
611                   static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
612                   DEBUG( 1, ( "Connection denied from %s\n",
613                               client_addr() ) );
614                   send_smb(smbd_server_fd(),(char *)buf);
615                   exit_server("connection denied");
616           }
617   }
618
619   DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
620   DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
621
622 #ifdef WITH_SSL
623     if(sslEnabled && !sslConnected){
624         sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
625         if(sslConnected < 0){   /* an error occured */
626             exit_server("SSL negotiation failed");
627         }else if(sslConnected){
628             trans_num++;
629             return;
630         }
631     }
632 #endif  /* WITH_SSL */
633
634   if (msg_type == 0)
635     show_msg(inbuf);
636   else if(msg_type == 0x85)
637     return; /* Keepalive packet. */
638
639   nread = construct_reply(inbuf,outbuf,nread,max_send);
640       
641   if(nread > 0) 
642   {
643     if (CVAL(outbuf,0) == 0)
644       show_msg(outbuf);
645         
646     if (nread != smb_len(outbuf) + 4) 
647     {
648       DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
649                  nread, smb_len(outbuf)));
650     }
651     else
652       send_smb(smbd_server_fd(),outbuf);
653   }
654   trans_num++;
655 }
656
657
658
659 /****************************************************************************
660 return a string containing the function name of a SMB command
661 ****************************************************************************/
662 char *smb_fn_name(int type)
663 {
664         static char *unknown_name = "SMBunknown";
665         static int num_smb_messages = 
666                 sizeof(smb_messages) / sizeof(struct smb_message_struct);
667         int match;
668
669         for (match=0;match<num_smb_messages;match++)
670                 if (smb_messages[match].code == type)
671                         break;
672
673         if (match == num_smb_messages)
674                 return(unknown_name);
675
676         return(smb_messages[match].name);
677 }
678
679
680 /****************************************************************************
681  Helper function for contruct_reply.
682 ****************************************************************************/
683
684 void construct_reply_common(char *inbuf,char *outbuf)
685 {
686   memset(outbuf,'\0',smb_size);
687
688   set_message(outbuf,0,0,True);
689   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
690
691   memcpy(outbuf+4,inbuf+4,4);
692   CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
693   CVAL(outbuf,smb_reh) = 0;
694   SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
695                                  means a reply */
696   SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
697         /* say we support long filenames */
698
699   SSVAL(outbuf,smb_err,SMB_SUCCESS);
700   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
701   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
702   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
703   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
704 }
705
706 /****************************************************************************
707   construct a chained reply and add it to the already made reply
708   **************************************************************************/
709 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
710 {
711   static char *orig_inbuf;
712   static char *orig_outbuf;
713   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
714   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
715   char *inbuf2, *outbuf2;
716   int outsize2;
717   char inbuf_saved[smb_wct];
718   char outbuf_saved[smb_wct];
719   int wct = CVAL(outbuf,smb_wct);
720   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
721
722   /* maybe its not chained */
723   if (smb_com2 == 0xFF) {
724     CVAL(outbuf,smb_vwv0) = 0xFF;
725     return outsize;
726   }
727
728   if (chain_size == 0) {
729     /* this is the first part of the chain */
730     orig_inbuf = inbuf;
731     orig_outbuf = outbuf;
732   }
733
734   /*
735    * The original Win95 redirector dies on a reply to
736    * a lockingX and read chain unless the chain reply is
737    * 4 byte aligned. JRA.
738    */
739
740   outsize = (outsize + 3) & ~3;
741
742   /* we need to tell the client where the next part of the reply will be */
743   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
744   CVAL(outbuf,smb_vwv0) = smb_com2;
745
746   /* remember how much the caller added to the chain, only counting stuff
747      after the parameter words */
748   chain_size += outsize - smb_wct;
749
750   /* work out pointers into the original packets. The
751      headers on these need to be filled in */
752   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
753   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
754
755   /* remember the original command type */
756   smb_com1 = CVAL(orig_inbuf,smb_com);
757
758   /* save the data which will be overwritten by the new headers */
759   memcpy(inbuf_saved,inbuf2,smb_wct);
760   memcpy(outbuf_saved,outbuf2,smb_wct);
761
762   /* give the new packet the same header as the last part of the SMB */
763   memmove(inbuf2,inbuf,smb_wct);
764
765   /* create the in buffer */
766   CVAL(inbuf2,smb_com) = smb_com2;
767
768   /* create the out buffer */
769   construct_reply_common(inbuf2, outbuf2);
770
771   DEBUG(3,("Chained message\n"));
772   show_msg(inbuf2);
773
774   /* process the request */
775   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
776                             bufsize-chain_size);
777
778   /* copy the new reply and request headers over the old ones, but
779      preserve the smb_com field */
780   memmove(orig_outbuf,outbuf2,smb_wct);
781   CVAL(orig_outbuf,smb_com) = smb_com1;
782
783   /* restore the saved data, being careful not to overwrite any
784    data from the reply header */
785   memcpy(inbuf2,inbuf_saved,smb_wct);
786   {
787     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
788     if (ofs < 0) ofs = 0;
789     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
790   }
791
792   return outsize2;
793 }
794
795 /****************************************************************************
796  Setup the needed select timeout.
797 ****************************************************************************/
798
799 static int setup_select_timeout(void)
800 {
801   int change_notify_timeout = lp_change_notify_timeout() * 1000;
802   int select_timeout;
803
804   /*
805    * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
806    * have removed any blocking locks. JRA.
807    */
808
809   select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
810                                               SMBD_SELECT_TIMEOUT*1000;
811
812   if (change_notifies_pending())
813     select_timeout = MIN(select_timeout, change_notify_timeout);
814
815   return select_timeout;
816 }
817
818 /****************************************************************************
819  Check if services need reloading.
820 ****************************************************************************/
821
822 void check_reload(int t)
823 {
824   static time_t last_smb_conf_reload_time = 0;
825
826   if(last_smb_conf_reload_time == 0)
827     last_smb_conf_reload_time = t;
828
829   if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
830   {
831     reload_services(True);
832     reload_after_sighup = False;
833     last_smb_conf_reload_time = t;
834   }
835 }
836
837 /****************************************************************************
838  Process any timeout housekeeping. Return False if the caller should exit.
839 ****************************************************************************/
840
841 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
842 {
843   static time_t last_keepalive_sent_time = 0;
844   static time_t last_idle_closed_check = 0;
845   time_t t;
846   BOOL allidle = True;
847   extern int keepalive;
848
849   if (smb_read_error == READ_EOF) 
850   {
851     DEBUG(3,("end of file from client\n"));
852     return False;
853   }
854
855   if (smb_read_error == READ_ERROR) 
856   {
857     DEBUG(3,("receive_smb error (%s) exiting\n",
858               strerror(errno)));
859     return False;
860   }
861
862   *last_timeout_processing_time = t = time(NULL);
863
864   if(last_keepalive_sent_time == 0)
865     last_keepalive_sent_time = t;
866
867   if(last_idle_closed_check == 0)
868     last_idle_closed_check = t;
869
870   /* become root again if waiting */
871   unbecome_user();
872
873   /* check if we need to reload services */
874   check_reload(t);
875
876   /* automatic timeout if all connections are closed */      
877   if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) 
878   {
879     DEBUG( 2, ( "Closing idle connection\n" ) );
880     return False;
881   }
882   else
883     last_idle_closed_check = t;
884
885   if (keepalive && (t - last_keepalive_sent_time)>keepalive) 
886   {
887     struct cli_state *cli = server_client();
888     if (!send_keepalive(smbd_server_fd())) {
889       DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
890       return False;
891     }       
892     /* also send a keepalive to the password server if its still
893        connected */
894     if (cli && cli->initialised)
895       send_keepalive(cli->fd);
896     last_keepalive_sent_time = t;
897   }
898
899   /* check for connection timeouts */
900   allidle = conn_idle_all(t, deadtime);
901
902   if (allidle && conn_num_open()>0) {
903     DEBUG(2,("Closing idle connection 2.\n"));
904     return False;
905   }
906
907   if(global_machine_password_needs_changing)
908   {
909     unsigned char trust_passwd_hash[16];
910     time_t lct;
911     pstring remote_machine_list;
912
913     /*
914      * We're in domain level security, and the code that
915      * read the machine password flagged that the machine
916      * password needs changing.
917      */
918
919     /*
920      * First, open the machine password file with an exclusive lock.
921      */
922
923     if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
924       DEBUG(0,("process: unable to open the machine account password file for \
925 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
926       return True;
927     }
928
929     if(!get_trust_account_password( trust_passwd_hash, &lct)) {
930       DEBUG(0,("process: unable to read the machine account password for \
931 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
932       trust_password_unlock();
933       return True;
934     }
935
936     /*
937      * Make sure someone else hasn't already done this.
938      */
939
940     if(t < lct + lp_machine_password_timeout()) {
941       trust_password_unlock();
942       global_machine_password_needs_changing = False;
943       return True;
944     }
945
946     pstrcpy(remote_machine_list, lp_passwordserver());
947
948     change_trust_account_password( global_myworkgroup, remote_machine_list);
949     trust_password_unlock();
950     global_machine_password_needs_changing = False;
951   }
952
953   /*
954    * Check to see if we have any blocking locks
955    * outstanding on the queue.
956    */
957   process_blocking_lock_queue(t);
958
959   /*
960    * Check to see if we have any change notifies 
961    * outstanding on the queue.
962    */
963   process_pending_change_notify_queue(t);
964
965   /*
966    * Now we are root, check if the log files need pruning.
967    */
968   if(need_to_check_log_size())
969       check_log_size();
970
971   /*
972    * Modify the select timeout depending upon
973    * what we have remaining in our queues.
974    */
975
976   *select_timeout = setup_select_timeout();
977
978   return True;
979 }
980
981 /****************************************************************************
982   process commands from the client
983 ****************************************************************************/
984
985 void smbd_process(void)
986 {
987   extern int smb_echo_count;
988   time_t last_timeout_processing_time = time(NULL);
989   unsigned int num_smbs = 0;
990
991   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
992   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
993   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
994     return;
995
996   InBuffer += SMB_ALIGNMENT;
997   OutBuffer += SMB_ALIGNMENT;
998
999   max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1000
1001   /* re-initialise the timezone */
1002   TimeInit();
1003
1004   while (True)
1005   {
1006     int deadtime = lp_deadtime()*60;
1007     BOOL got_smb = False;
1008     int select_timeout = setup_select_timeout();
1009
1010     if (deadtime <= 0)
1011       deadtime = DEFAULT_SMBD_TIMEOUT;
1012
1013 #if USE_READ_PREDICTION
1014     if (lp_readprediction())
1015       do_read_prediction();
1016 #endif
1017
1018     errno = 0;      
1019
1020     /* free up temporary memory */
1021     lp_talloc_free();
1022
1023     while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb))
1024     {
1025       if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1026         return;
1027       num_smbs = 0; /* Reset smb counter. */
1028     }
1029
1030     if(got_smb) {
1031       /*
1032        * Ensure we do timeout processing if the SMB we just got was
1033        * only an echo request. This allows us to set the select
1034        * timeout in 'receive_message_or_smb()' to any value we like
1035        * without worrying that the client will send echo requests
1036        * faster than the select timeout, thus starving out the
1037        * essential processing (change notify, blocking locks) that
1038        * the timeout code does. JRA.
1039        */ 
1040       int num_echos = smb_echo_count;
1041
1042       process_smb(InBuffer, OutBuffer);
1043
1044       if(smb_echo_count != num_echos) {
1045         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1046           return;
1047         num_smbs = 0; /* Reset smb counter. */
1048       }
1049
1050       num_smbs++;
1051
1052       /*
1053        * If we are getting smb requests in a constant stream
1054        * with no echos, make sure we attempt timeout processing
1055        * every select_timeout milliseconds - but only check for this
1056        * every 200 smb requests.
1057        */
1058
1059       if((num_smbs % 200) == 0) {
1060         time_t new_check_time = time(NULL);
1061         if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
1062           if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1063             return;
1064           num_smbs = 0; /* Reset smb counter. */
1065           last_timeout_processing_time = new_check_time; /* Reset time. */
1066         }
1067       }
1068     }
1069     else
1070       process_local_message(InBuffer, BUFFER_SIZE);
1071   }
1072 }