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