smb-vc-reset-on-request-20090218
authorAsanka Herath <asanka@secure-endpoints.com>
Thu, 19 Feb 2009 04:04:24 +0000 (04:04 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 19 Feb 2009 04:04:24 +0000 (04:04 +0000)
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
src/WINNT/afsd/afsd_eventmessages.mc
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c

index 192d8d5..a6ed02c 100644 (file)
@@ -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);
index f01059d..5c0f27f 100644 (file)
@@ -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 */
index 7b00fd5..87a186b 100644 (file)
@@ -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));
index 4667324..e943d37 100644 (file)
@@ -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__);
index b2c615f..dadaa91 100644 (file)
@@ -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 */