From 4eb808d26b1d417189d363924c4e2e32ed832690 Mon Sep 17 00:00:00 2001 From: Asanka Herath Date: Thu, 19 Feb 2009 04:04:24 +0000 Subject: [PATCH] smb-vc-reset-on-request-20090218 LICENSE MIT When processing SMB_SESSION_SETUP_ANDX in smb_ReceiveV3SessionSetupX it is possible that the smb client might indicate that it requires an Mpx Count greater than we are configured to support. If so, log it to the Windows Event Log as a warning. It is also possible that the client might specify that its maximum receive buffer is smaller than the SMB_PACKETSIZE. If so, log it to the Windows Event Log as a warning. Finally, if the client specifies a virtual circuit number of zero, the client thinks this is its first time communicating with us. In which case we should invalidate all prior virtual circuits. We also log this request to the Windows Event Log as informational. --- src/WINNT/afsd/afsd_eventlog.c | 21 +++++++------ src/WINNT/afsd/afsd_eventmessages.mc | 25 +++++++++++++++- src/WINNT/afsd/smb.c | 58 ++++++++++++++++++++++++++++++++++++ src/WINNT/afsd/smb.h | 2 ++ src/WINNT/afsd/smb3.c | 29 ++++++++++++++++++ 5 files changed, 125 insertions(+), 10 deletions(-) diff --git a/src/WINNT/afsd/afsd_eventlog.c b/src/WINNT/afsd/afsd_eventlog.c index 192d8d5..a6ed02c 100644 --- a/src/WINNT/afsd/afsd_eventlog.c +++ b/src/WINNT/afsd/afsd_eventlog.c @@ -167,7 +167,7 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...) CHAR lpStrings[MAXARGS][STRLEN]; WORD wNumArgs = 0; WORD wNumStrings = 0; - DWORD code; + DWORD code; // Ensure that our event source is properly initialized. if (!AddEventSource()) @@ -195,6 +195,7 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...) case MSG_SERVICE_ERROR_STOP: case MSG_CRYPT_OFF: case MSG_CRYPT_ON: + case MSG_SMB_RESET_ALL_VCS: break; case MSG_FLUSH_BAD_SHARE_NAME: case MSG_FLUSH_OPEN_ENUM_ERROR: @@ -209,6 +210,8 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...) break; case MSG_TIME_FLUSH_PER_VOLUME: case MSG_TIME_FLUSH_TOTAL: + case MSG_SMB_MAX_MPX_COUNT: + case MSG_SMB_MAX_BUFFER_SIZE: wNumArgs = 2; lpArgs[0] = va_arg(listArgs, LPTSTR); lpArgs[1] = va_arg(listArgs, LPTSTR); @@ -296,14 +299,14 @@ LogEvent(WORD wEventType, DWORD dwEventID, ...) // Log the event. code = ReportEvent(hEventSource, // handle of event source - wEventType, // event type - 0, // event category - dwEventID, // event ID - NULL, // current user's SID - wNumArgs, // strings in lpszArgs - 0, // no bytes of raw data - wNumArgs ? lpArgs : NULL, // array of error strings - NULL); // no raw data + wEventType, // event type + 0, // event category + dwEventID, // event ID + NULL, // current user's SID + wNumArgs, // strings in lpszArgs + 0, // no bytes of raw data + wNumArgs ? lpArgs : NULL,// array of error strings + NULL); // no raw data DeregisterEventSource(hEventSource); diff --git a/src/WINNT/afsd/afsd_eventmessages.mc b/src/WINNT/afsd/afsd_eventmessages.mc index f01059d..5c0f27f 100644 --- a/src/WINNT/afsd/afsd_eventmessages.mc +++ b/src/WINNT/afsd/afsd_eventmessages.mc @@ -7,7 +7,7 @@ ;// Do not edit the header file. It is autogenerated from ;// afsd_eventmessages.mc. If you edit afsd_eventmessages.mc ;// be sure to ensure the consistency of the data types in LogEvent() -;// +;// located in afsd_eventlog.c ; ;#ifndef __AFSD_EVENTMESSAGES_H_ ;#define __AFSD_EVENTMESSAGES_H_ 1 @@ -358,5 +358,28 @@ Language=English Unexpected SMB Session Close: %1. . +MessageId= +Severity=Warning +Facility=System +SymbolicName=MSG_SMB_MAX_MPX_COUNT +Language=English +MaxMpxCount for client is too large (Client=%1, Server=%2). +. + +MessageId= +Severity=Warning +Facility=System +SymbolicName=MSG_SMB_MAX_BUFFER_SIZE +Language=English +MaxBufferSize for client is too small (Client=%1, Server=%2). +. + +MessageId= +Severity=Informational +Facility=System +SymbolicName=MSG_SMB_RESET_ALL_VCS +Language=English +Windows SMB Redirector requests reset of all SMB virtual circuits. +. ;#endif /* __AFSD_EVENTMESSAGES_H_ 1 */ diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 7b00fd5..87a186b 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -819,6 +819,61 @@ void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime) *unixTimep = dosTime + smb_localZero; } +void smb_MarkAllVCsDead(smb_vc_t * exclude) +{ + smb_vc_t *vcp; + smb_vc_t **vcp_to_cleanup = NULL; + int n_to_cleanup = 0; + int i; + + osi_Log1(smb_logp, "Marking all VCs as dead excluding %p", exclude); + + lock_ObtainWrite(&smb_globalLock); /* for dead_sessions[] */ + lock_ObtainWrite(&smb_rctLock); + for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) { + + if (vcp->magic != SMB_VC_MAGIC) + osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", + __FILE__, __LINE__); + + if (vcp == exclude) + continue; + + lock_ObtainMutex(&vcp->mx); + if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { + vcp->flags |= SMB_VCFLAG_ALREADYDEAD; + lock_ReleaseMutex(&vcp->mx); + dead_sessions[vcp->session] = TRUE; + } else { + lock_ReleaseMutex(&vcp->mx); + } + n_to_cleanup ++; + } + + vcp_to_cleanup = malloc(sizeof(vcp_to_cleanup[0]) * n_to_cleanup); + i = 0; + for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) { + if (vcp == exclude) + continue; + + vcp_to_cleanup[i++] = vcp; + smb_HoldVCNoLock(vcp); + } + + osi_assert(i == n_to_cleanup); + + lock_ReleaseWrite(&smb_rctLock); + lock_ReleaseWrite(&smb_globalLock); + + for (i=0; i < n_to_cleanup; i++) { + smb_CleanupDeadVC(vcp_to_cleanup[i]); + smb_ReleaseVC(vcp_to_cleanup[i]); + vcp_to_cleanup[i] = 0; + } + + free(vcp_to_cleanup); +} + #ifdef DEBUG_SMB_REFCOUNT smb_vc_t *smb_FindVCDbg(unsigned short lsn, int flags, int lana, char *file, long line) #else @@ -834,11 +889,14 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana) osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", __FILE__, __LINE__); + lock_ObtainMutex(&vcp->mx); if (lsn == vcp->lsn && lana == vcp->lana && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { + lock_ReleaseMutex(&vcp->mx); smb_HoldVCNoLock(vcp); break; } + lock_ReleaseMutex(&vcp->mx); } if (!vcp && (flags & SMB_FLAG_CREATE)) { vcp = malloc(sizeof(*vcp)); diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 4667324..e943d37 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -546,6 +546,8 @@ extern void smb_ReleaseVCNoLock(smb_vc_t *vcp); extern void smb_CleanupDeadVC(smb_vc_t *vcp); +extern void smb_MarkAllVCsDead(smb_vc_t *exclude_vcp); + #ifdef DEBUG_SMB_REFCOUNT extern smb_tid_t *smb_FindTIDDbg(smb_vc_t *vcp, unsigned short tid, int flags, char *, long); #define smb_FindTID(a,b,c) smb_FindTIDDbg(a,b,c,__FILE__,__LINE__); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index b2c615f..dadaa91 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -686,11 +686,40 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * clientchar_t usern[SMB_MAX_USERNAME_LENGTH]; char *secBlobOut = NULL; int secBlobOutLength = 0; + int maxBufferSize = 0; + int maxMpxCount = 0; + int vcNumber = 0; /* Check for bad conns */ if (vcp->flags & SMB_VCFLAG_REMOTECONN) return CM_ERROR_REMOTECONN; + /* maxBufferSize */ + maxBufferSize = smb_GetSMBParm(inp, 2); + maxMpxCount = smb_GetSMBParm(inp, 3); + vcNumber = smb_GetSMBParm(inp, 4); + + osi_Log3(smb_logp, "SESSION_SETUP_ANDX with MaxBufferSize=%d, MaxMpxCount=%d, VCNumber=%d", + maxBufferSize, maxMpxCount, vcNumber); + + if (maxMpxCount > smb_maxMpxRequests) { + LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_MPX_COUNT, maxMpxCount, smb_maxMpxRequests); + osi_Log2(smb_logp, "MaxMpxCount for client is too large (Client=%d, Server=%d)", + maxMpxCount, smb_maxMpxRequests); + } + + if (maxBufferSize < SMB_PACKETSIZE) { + LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_BUFFER_SIZE, maxBufferSize, SMB_PACKETSIZE); + osi_Log2(smb_logp, "MaxBufferSize for client is too small (Client=%d, Server=%d)", + maxBufferSize, SMB_PACKETSIZE); + } + + if (vcNumber == 0) { + LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_RESET_ALL_VCS); + osi_Log0(smb_logp, "Resetting all VCs"); + smb_MarkAllVCsDead(vcp); + } + if (vcp->flags & SMB_VCFLAG_USENT) { if (smb_authType == SMB_AUTH_EXTENDED) { /* extended authentication */ -- 1.9.4