Fixed interface code so that a UUID is transmitted as the following fields :
[Samba/ekacnet.git] / source / smbd / process.c
bloba51b1ddf853d615a63926774f8eff1a91f339b0e
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 process incoming packets - main loop
5 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
22 #include "includes.h"
24 extern int DEBUGLEVEL;
26 time_t smb_last_time=(time_t)0;
28 char *InBuffer = NULL;
29 char *OutBuffer = NULL;
30 char *last_inbuf = NULL;
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.
37 int max_send = BUFFER_SIZE;
39 * Size of the data we can receive. Set by us.
40 * Can be modified by the max xmit parameter.
42 int max_recv = BUFFER_SIZE;
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;
57 /****************************************************************************
58 structure to hold a linked list of queued messages.
59 for processing.
60 ****************************************************************************/
62 typedef struct {
63 ubi_slNode msg_next;
64 char *msg_buf;
65 int msg_len;
66 } pending_message_list;
68 static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
70 /****************************************************************************
71 Function to push a message onto the tail of a linked list of smb messages ready
72 for processing.
73 ****************************************************************************/
75 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
77 pending_message_list *msg = (pending_message_list *)
78 malloc(sizeof(pending_message_list));
80 if(msg == NULL)
82 DEBUG(0,("push_message: malloc fail (1)\n"));
83 return False;
86 msg->msg_buf = (char *)malloc(msg_len);
87 if(msg->msg_buf == NULL)
89 DEBUG(0,("push_message: malloc fail (2)\n"));
90 free((char *)msg);
91 return False;
94 memcpy(msg->msg_buf, buf, msg_len);
95 msg->msg_len = msg_len;
97 ubi_slAddTail( list_head, msg);
99 return True;
102 /****************************************************************************
103 Function to push a smb message onto a linked list of local smb messages ready
104 for processing.
105 ****************************************************************************/
107 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
109 return push_message(&smb_oplock_queue, buf, msg_len);
112 /****************************************************************************
113 Do a select on an two fd's - with timeout.
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.
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.
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.
130 The timeout is in milli seconds
131 ****************************************************************************/
133 static BOOL receive_message_or_smb(char *buffer, int buffer_len,
134 int timeout, BOOL *got_smb)
136 extern int Client;
137 fd_set fds;
138 int selrtn;
139 struct timeval to;
140 int maxfd;
142 smb_read_error = 0;
144 *got_smb = False;
147 * Check to see if we already have a message on the smb queue.
148 * If so - copy and return it.
151 if(ubi_slCount(&smb_oplock_queue) != 0)
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));
156 /* Free the message we just copied. */
157 free((char *)msg->msg_buf);
158 free((char *)msg);
159 *got_smb = True;
161 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
162 return True;
166 * Setup the select read fd set.
169 FD_ZERO(&fds);
170 FD_SET(Client,&fds);
171 maxfd = setup_oplock_select_set(&fds);
173 to.tv_sec = timeout / 1000;
174 to.tv_usec = (timeout % 1000) * 1000;
176 selrtn = sys_select(MAX(maxfd,Client)+1,&fds,timeout>0?&to:NULL);
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;
185 /* Did we timeout ? */
186 if (selrtn == 0) {
187 smb_read_error = READ_TIMEOUT;
188 return False;
191 if (FD_ISSET(Client,&fds))
193 *got_smb = True;
194 return receive_smb(Client, buffer, 0);
196 else
198 return receive_local_message(&fds, buffer, buffer_len, 0);
202 /****************************************************************************
203 Get the next SMB packet, doing the local message processing automatically.
204 ****************************************************************************/
206 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
208 BOOL got_smb = False;
209 BOOL ret;
213 ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb);
215 if(ret && !got_smb)
217 /* Deal with oplock break requests from other smbd's. */
218 process_local_message(inbuf, bufsize);
219 continue;
222 if(ret && (CVAL(inbuf,0) == 0x85))
224 /* Keepalive packet. */
225 got_smb = False;
229 while(ret && !got_smb);
231 return ret;
236 These flags determine some of the permissions required to do an operation
238 Note that I don't set NEED_WRITE on some write operations because they
239 are used by some brain-dead clients when printing, and I don't want to
240 force write permissions on print services.
242 #define AS_USER (1<<0)
243 #define NEED_WRITE (1<<1)
244 #define TIME_INIT (1<<2)
245 #define CAN_IPC (1<<3)
246 #define AS_GUEST (1<<5)
247 #define QUEUE_IN_OPLOCK (1<<6)
250 define a list of possible SMB messages and their corresponding
251 functions. Any message that has a NULL function is unimplemented -
252 please feel free to contribute implementations!
254 struct smb_message_struct
256 int code;
257 char *name;
258 int (*fn)(connection_struct *conn, char *, char *, int, int);
259 int flags;
261 smb_messages[] = {
263 /* CORE PROTOCOL */
265 {SMBnegprot,"SMBnegprot",reply_negprot,0},
266 {SMBtcon,"SMBtcon",reply_tcon,0},
267 {SMBtdis,"SMBtdis",reply_tdis,0},
268 {SMBexit,"SMBexit",reply_exit,0},
269 {SMBioctl,"SMBioctl",reply_ioctl,0},
270 {SMBecho,"SMBecho",reply_echo,0},
271 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
272 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
273 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
274 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
275 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
276 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
277 {SMBsearch,"SMBsearch",reply_search,AS_USER},
278 {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
280 /* note that SMBmknew and SMBcreate are deliberately overloaded */
281 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
282 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
284 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
285 {SMBread,"SMBread",reply_read,AS_USER},
286 {SMBwrite,"SMBwrite",reply_write,AS_USER},
287 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
288 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
289 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
290 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
291 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
293 /* this is a Pathworks specific call, allowing the
294 changing of the root path */
295 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
297 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
298 {SMBflush,"SMBflush",reply_flush,AS_USER},
299 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
300 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
301 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
302 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
303 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
304 {SMBlock,"SMBlock",reply_lock,AS_USER},
305 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
307 /* CORE+ PROTOCOL FOLLOWS */
309 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
310 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
311 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
312 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
313 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
315 /* LANMAN1.0 PROTOCOL FOLLOWS */
317 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
318 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
319 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
320 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
321 {SMBwritec,"SMBwritec",NULL,AS_USER},
322 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
323 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
324 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
325 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
326 {SMBioctls,"SMBioctls",NULL,AS_USER},
327 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
328 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
330 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
331 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
332 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
333 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
335 {SMBffirst,"SMBffirst",reply_search,AS_USER},
336 {SMBfunique,"SMBfunique",reply_search,AS_USER},
337 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
339 /* LANMAN2.0 PROTOCOL FOLLOWS */
340 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
341 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
342 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER },
343 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
345 /* NT PROTOCOL FOLLOWS */
346 {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
347 {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
348 {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
349 {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 },
351 /* messaging routines */
352 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
353 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
354 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
355 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
357 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
359 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
360 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
361 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
362 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
366 /****************************************************************************
367 do a switch on the message type, and return the response size
368 ****************************************************************************/
369 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
371 static int pid= -1;
372 int outsize = 0;
373 static int num_smb_messages =
374 sizeof(smb_messages) / sizeof(struct smb_message_struct);
375 int match;
376 extern int Client;
378 if (pid == -1)
379 pid = getpid();
381 errno = 0;
382 last_message = type;
384 /* make sure this is an SMB packet */
385 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
387 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
388 return(-1);
391 for (match=0;match<num_smb_messages;match++)
392 if (smb_messages[match].code == type)
393 break;
395 if (match == num_smb_messages)
397 DEBUG(0,("Unknown message type %d!\n",type));
398 outsize = reply_unknown(inbuf,outbuf);
400 else
402 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
404 if(global_oplock_break && (smb_messages[match].flags & QUEUE_IN_OPLOCK))
407 * Queue this message as we are the process of an oplock break.
410 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
411 DEBUGADD( 2, ( "oplock break state.\n" ) );
413 push_oplock_pending_smb_message( inbuf, size );
414 return -1;
417 if (smb_messages[match].fn)
419 int flags = smb_messages[match].flags;
420 static uint16 last_session_tag = UID_FIELD_INVALID;
421 /* In share mode security we must ignore the vuid. */
422 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
423 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
426 /* Ensure this value is replaced in the incoming packet. */
427 SSVAL(inbuf,smb_uid,session_tag);
430 * Ensure the correct username is in sesssetup_user.
431 * This is a really ugly bugfix for problems with
432 * multiple session_setup_and_X's being done and
433 * allowing %U and %G substitutions to work correctly.
434 * There is a reason this code is done here, don't
435 * move it unless you know what you're doing... :-).
436 * JRA.
438 if (session_tag != last_session_tag) {
439 user_struct *vuser = NULL;
441 last_session_tag = session_tag;
442 if(session_tag != UID_FIELD_INVALID)
443 vuser = get_valid_user_struct(session_tag);
444 if(vuser != NULL)
445 pstrcpy( sesssetup_user, vuser->requested_name);
448 /* does this protocol need to be run as root? */
449 if (!(flags & AS_USER))
450 unbecome_user();
452 /* does this protocol need to be run as the connected user? */
453 if ((flags & AS_USER) && !become_user(conn,session_tag)) {
454 if (flags & AS_GUEST)
455 flags &= ~AS_USER;
456 else
457 return(ERROR(ERRSRV,ERRinvnid));
459 /* this code is to work around a bug is MS client 3 without
460 introducing a security hole - it needs to be able to do
461 print queue checks as guest if it isn't logged in properly */
462 if (flags & AS_USER)
463 flags &= ~AS_GUEST;
465 /* does it need write permission? */
466 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
467 return(ERROR(ERRSRV,ERRaccess));
469 /* ipc services are limited */
470 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
471 return(ERROR(ERRSRV,ERRaccess));
474 /* load service specific parameters */
475 if (conn &&
476 !become_service(conn,(flags & AS_USER)?True:False)) {
477 return(ERROR(ERRSRV,ERRaccess));
480 /* does this protocol need to be run as guest? */
481 if ((flags & AS_GUEST) &&
482 (!become_guest() ||
483 !check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1)))) {
484 return(ERROR(ERRSRV,ERRaccess));
487 last_inbuf = inbuf;
489 outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize);
491 else
493 outsize = reply_unknown(inbuf,outbuf);
497 return(outsize);
501 /****************************************************************************
502 construct a reply to the incoming packet
503 ****************************************************************************/
504 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
506 int type = CVAL(inbuf,smb_com);
507 int outsize = 0;
508 int msg_type = CVAL(inbuf,0);
509 extern int chain_size;
511 smb_last_time = time(NULL);
513 chain_size = 0;
514 file_chain_reset();
515 reset_chain_p();
517 if (msg_type != 0)
518 return(reply_special(inbuf,outbuf));
520 construct_reply_common(inbuf, outbuf);
522 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
524 outsize += chain_size;
526 if(outsize > 4)
527 smb_setlen(outbuf,outsize - 4);
528 return(outsize);
532 /****************************************************************************
533 process an smb from the client - split out from the process() code so
534 it can be used by the oplock break code.
535 ****************************************************************************/
536 void process_smb(char *inbuf, char *outbuf)
538 extern int Client;
539 #ifdef WITH_SSL
540 extern BOOL sslEnabled; /* don't use function for performance reasons */
541 static int sslConnected = 0;
542 #endif /* WITH_SSL */
543 static int trans_num;
544 int msg_type = CVAL(inbuf,0);
545 int32 len = smb_len(inbuf);
546 int nread = len + 4;
548 if (trans_num == 0) {
549 /* on the first packet, check the global hosts allow/ hosts
550 deny parameters before doing any parsing of the packet
551 passed to us by the client. This prevents attacks on our
552 parsing code from hosts not in the hosts allow list */
553 if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) {
554 /* send a negative session response "not listining on calling
555 name" */
556 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
557 DEBUG( 1, ( "Connection denied from %s\n",
558 client_addr(Client) ) );
559 send_smb(Client,(char *)buf);
560 exit_server("connection denied");
564 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
565 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
567 #ifdef WITH_SSL
568 if(sslEnabled && !sslConnected){
569 sslConnected = sslutil_negotiate_ssl(Client, msg_type);
570 if(sslConnected < 0){ /* an error occured */
571 exit_server("SSL negotiation failed");
572 }else if(sslConnected){
573 trans_num++;
574 return;
577 #endif /* WITH_SSL */
579 #ifdef WITH_VTP
580 if(trans_num == 1 && VT_Check(inbuf))
582 VT_Process();
583 return;
585 #endif
587 if (msg_type == 0)
588 show_msg(inbuf);
589 else if(msg_type == 0x85)
590 return; /* Keepalive packet. */
592 nread = construct_reply(inbuf,outbuf,nread,max_send);
594 if(nread > 0)
596 if (CVAL(outbuf,0) == 0)
597 show_msg(outbuf);
599 if (nread != smb_len(outbuf) + 4)
601 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
602 nread, smb_len(outbuf)));
604 else
605 send_smb(Client,outbuf);
607 trans_num++;
612 /****************************************************************************
613 return a string containing the function name of a SMB command
614 ****************************************************************************/
615 char *smb_fn_name(int type)
617 static char *unknown_name = "SMBunknown";
618 static int num_smb_messages =
619 sizeof(smb_messages) / sizeof(struct smb_message_struct);
620 int match;
622 for (match=0;match<num_smb_messages;match++)
623 if (smb_messages[match].code == type)
624 break;
626 if (match == num_smb_messages)
627 return(unknown_name);
629 return(smb_messages[match].name);
633 /****************************************************************************
634 Helper function for contruct_reply.
635 ****************************************************************************/
637 void construct_reply_common(char *inbuf,char *outbuf)
639 memset(outbuf,'\0',smb_size);
641 set_message(outbuf,0,0,True);
642 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
644 memcpy(outbuf+4,inbuf+4,4);
645 CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
646 CVAL(outbuf,smb_reh) = 0;
647 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
648 means a reply */
649 SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS); /* say we support long filenames */
650 SSVAL(outbuf,smb_err,SMB_SUCCESS);
651 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
652 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
653 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
654 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
657 /****************************************************************************
658 construct a chained reply and add it to the already made reply
659 **************************************************************************/
660 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
662 static char *orig_inbuf;
663 static char *orig_outbuf;
664 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
665 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
666 char *inbuf2, *outbuf2;
667 int outsize2;
668 char inbuf_saved[smb_wct];
669 char outbuf_saved[smb_wct];
670 extern int chain_size;
671 int wct = CVAL(outbuf,smb_wct);
672 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
674 /* maybe its not chained */
675 if (smb_com2 == 0xFF) {
676 CVAL(outbuf,smb_vwv0) = 0xFF;
677 return outsize;
680 if (chain_size == 0) {
681 /* this is the first part of the chain */
682 orig_inbuf = inbuf;
683 orig_outbuf = outbuf;
686 /* we need to tell the client where the next part of the reply will be */
687 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
688 CVAL(outbuf,smb_vwv0) = smb_com2;
690 /* remember how much the caller added to the chain, only counting stuff
691 after the parameter words */
692 chain_size += outsize - smb_wct;
694 /* work out pointers into the original packets. The
695 headers on these need to be filled in */
696 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
697 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
699 /* remember the original command type */
700 smb_com1 = CVAL(orig_inbuf,smb_com);
702 /* save the data which will be overwritten by the new headers */
703 memcpy(inbuf_saved,inbuf2,smb_wct);
704 memcpy(outbuf_saved,outbuf2,smb_wct);
706 /* give the new packet the same header as the last part of the SMB */
707 memmove(inbuf2,inbuf,smb_wct);
709 /* create the in buffer */
710 CVAL(inbuf2,smb_com) = smb_com2;
712 /* create the out buffer */
713 construct_reply_common(inbuf2, outbuf2);
715 DEBUG(3,("Chained message\n"));
716 show_msg(inbuf2);
718 /* process the request */
719 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
720 bufsize-chain_size);
722 /* copy the new reply and request headers over the old ones, but
723 preserve the smb_com field */
724 memmove(orig_outbuf,outbuf2,smb_wct);
725 CVAL(orig_outbuf,smb_com) = smb_com1;
727 /* restore the saved data, being careful not to overwrite any
728 data from the reply header */
729 memcpy(inbuf2,inbuf_saved,smb_wct);
731 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
732 if (ofs < 0) ofs = 0;
733 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
736 return outsize2;
739 /****************************************************************************
740 Process any timeout housekeeping. Return False if the caler should exit.
741 ****************************************************************************/
743 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
745 extern int Client;
746 static time_t last_smb_conf_reload_time = 0;
747 static time_t last_keepalive_sent_time = 0;
748 static time_t last_idle_closed_check = 0;
749 time_t t;
750 BOOL allidle = True;
751 extern int keepalive;
753 if (smb_read_error == READ_EOF)
755 DEBUG(3,("end of file from client\n"));
756 return False;
759 if (smb_read_error == READ_ERROR)
761 DEBUG(3,("receive_smb error (%s) exiting\n",
762 strerror(errno)));
763 return False;
766 *last_timeout_processing_time = t = time(NULL);
768 if(last_smb_conf_reload_time == 0)
769 last_smb_conf_reload_time = t;
771 if(last_keepalive_sent_time == 0)
772 last_keepalive_sent_time = t;
774 if(last_idle_closed_check == 0)
775 last_idle_closed_check = t;
777 /* become root again if waiting */
778 unbecome_user();
780 /* check for smb.conf reload */
781 if (t >= last_smb_conf_reload_time + SMBD_RELOAD_CHECK)
783 /* reload services, if files have changed. */
784 reload_services(True);
785 last_smb_conf_reload_time = t;
789 * If reload_after_sighup == True then we got a SIGHUP
790 * and are being asked to reload. Fix from <branko.cibej@hermes.si>
793 if (reload_after_sighup)
795 DEBUG(0,("Reloading services after SIGHUP\n"));
796 reload_services(False);
797 reload_after_sighup = False;
798 last_smb_conf_reload_time = t;
800 * Use this as an excuse to print some stats.
802 print_stat_cache_statistics();
805 /* automatic timeout if all connections are closed */
806 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT)
808 DEBUG( 2, ( "Closing idle connection\n" ) );
809 return False;
811 else
812 last_idle_closed_check = t;
814 if (keepalive && (t - last_keepalive_sent_time)>keepalive)
816 struct cli_state *cli = server_client();
817 if (!send_keepalive(Client)) {
818 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
819 return False;
821 /* also send a keepalive to the password server if its still
822 connected */
823 if (cli && cli->initialised)
824 send_keepalive(cli->fd);
825 last_keepalive_sent_time = t;
828 /* check for connection timeouts */
829 allidle = conn_idle_all(t, deadtime);
831 if (allidle && conn_num_open()>0) {
832 DEBUG(2,("Closing idle connection 2.\n"));
833 return False;
836 if(global_machine_password_needs_changing)
838 unsigned char trust_passwd_hash[16];
839 time_t lct;
840 pstring remote_machine_list;
843 * We're in domain level security, and the code that
844 * read the machine password flagged that the machine
845 * password needs changing.
849 * First, open the machine password file with an exclusive lock.
852 if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
853 DEBUG(0,("process: unable to open the machine account password file for \
854 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
855 return True;
858 if(!get_trust_account_password( trust_passwd_hash, &lct)) {
859 DEBUG(0,("process: unable to read the machine account password for \
860 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
861 trust_password_unlock();
862 return True;
866 * Make sure someone else hasn't already done this.
869 if(t < lct + lp_machine_password_timeout()) {
870 trust_password_unlock();
871 global_machine_password_needs_changing = False;
872 return True;
875 pstrcpy(remote_machine_list, lp_passwordserver());
877 change_trust_account_password( global_myworkgroup, remote_machine_list);
878 trust_password_unlock();
879 global_machine_password_needs_changing = False;
883 * Check to see if we have any blocking locks
884 * outstanding on the queue.
886 process_blocking_lock_queue(t);
889 * Check to see if we have any change notifies
890 * outstanding on the queue.
892 process_pending_change_notify_queue(t);
895 * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
896 * have removed any blocking locks. JRA.
899 *select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
900 SMBD_SELECT_TIMEOUT*1000;
902 return True;
905 /****************************************************************************
906 process commands from the client
907 ****************************************************************************/
909 void smbd_process(void)
911 extern int smb_echo_count;
912 time_t last_timeout_processing_time = time(NULL);
913 unsigned int num_smbs = 0;
915 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
916 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
917 if ((InBuffer == NULL) || (OutBuffer == NULL))
918 return;
920 InBuffer += SMB_ALIGNMENT;
921 OutBuffer += SMB_ALIGNMENT;
923 #if PRIME_NMBD
924 DEBUG(3,("priming nmbd\n"));
926 struct in_addr ip;
927 ip = *interpret_addr2("localhost");
928 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
929 *OutBuffer = 0;
930 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
932 #endif
935 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
937 /* re-initialise the timezone */
938 TimeInit();
940 while (True)
942 int deadtime = lp_deadtime()*60;
943 BOOL got_smb = False;
944 int select_timeout = SMBD_SELECT_TIMEOUT*1000;
946 if (deadtime <= 0)
947 deadtime = DEFAULT_SMBD_TIMEOUT;
949 #if USE_READ_PREDICTION
950 if (lp_readprediction())
951 do_read_prediction();
952 #endif
954 errno = 0;
956 while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb))
958 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
959 return;
960 num_smbs = 0; /* Reset smb counter. */
963 if(got_smb) {
965 * Ensure we do timeout processing if the SMB we just got was
966 * only an echo request. This allows us to set the select
967 * timeout in 'receive_message_or_smb()' to any value we like
968 * without worrying that the client will send echo requests
969 * faster than the select timeout, thus starving out the
970 * essential processing (change notify, blocking locks) that
971 * the timeout code does. JRA.
973 int num_echos = smb_echo_count;
975 process_smb(InBuffer, OutBuffer);
977 if(smb_echo_count != num_echos) {
978 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
979 return;
980 num_smbs = 0; /* Reset smb counter. */
983 num_smbs++;
986 * If we are getting smb requests in a constant stream
987 * with no echos, make sure we attempt timeout processing
988 * every select_timeout milliseconds - but only check for this
989 * every 200 smb requests.
992 if((num_smbs % 200) == 0) {
993 time_t new_check_time = time(NULL);
994 if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
995 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
996 return;
997 num_smbs = 0; /* Reset smb counter. */
998 last_timeout_processing_time = new_check_time; /* Reset time. */
1002 else
1003 process_local_message(InBuffer, BUFFER_SIZE);