DEVEL15-windows-freelance-improved-dfs-handling-20080127
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 28 Jan 2008 07:23:35 +0000 (07:23 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 28 Jan 2008 07:23:35 +0000 (07:23 +0000)
LICENSE MIT

Cell names are published as share names.  As a result they are searched
for as part of the Dfs Referral evaluation.  If share "foo" can not be
reached, the CIFS client will fallback to searching for "fo" as well.

Since the freelance client automatically adds a symlink for prefixes
of the cell name, this results in both "foo" and "fo" being added to
the freelance root.afs volume.  This patch prevents that negative side
effect.

(cherry picked from commit 36bdf1ccd859fb0039d8ae9abd04f9eea08d704d)

src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_freelance.c
src/WINNT/afsd/cm_freelance.h
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/smb3.c

index 65676fb..c17d987 100644 (file)
@@ -246,6 +246,7 @@ int RXAFS_Lookup (struct rx_connection *,
 #define CM_FLAG_DIRSEARCH      0x40            /* for directory search */
 #define CM_FLAG_CHECKPATH      0x80            /* Path instead of File */
 #define CM_FLAG_NOPROBE         0x100           /* For use with cm_GetCellxxx - do not probe server status */
+#define CM_FLAG_DFS_REFERRAL    0x200           /* The request is a DFS Referral - the last char of the lookup name may be missing */
 
 /* error codes */
 #define CM_ERROR_BASE                  0x66543200
index 3b2651c..507e4d1 100644 (file)
@@ -821,7 +821,7 @@ int cm_getNoLocalMountPoints() {
 }
 
 #if !defined(DJGPP)
-long cm_FreelanceMountPointExists(char * filename)
+long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
 {
     char* cp;
     char line[512];
@@ -889,6 +889,11 @@ long cm_FreelanceMountPointExists(char * filename)
                 found = 1;
                 break;
             }
+
+            if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
+                found = 1;
+                break;
+            }
         }
         RegCloseKey(hkFreelance);
     }
@@ -898,7 +903,7 @@ long cm_FreelanceMountPointExists(char * filename)
     return found;
 }
 
-long cm_FreelanceSymlinkExists(char * filename)
+long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
 {
     char* cp;
     char line[512];
@@ -946,6 +951,11 @@ long cm_FreelanceSymlinkExists(char * filename)
                 found = 1;
                 break;
             }
+
+            if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
+                found = 1;
+                break;
+            }
         }
         for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
             TCHAR szValueName[16];
@@ -1009,8 +1019,8 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
     }
 
 #if !defined(DJGPP)
-    if ( cm_FreelanceMountPointExists(filename) ||
-         cm_FreelanceSymlinkExists(filename) )
+    if ( cm_FreelanceMountPointExists(filename, 0) ||
+         cm_FreelanceSymlinkExists(filename, 0) )
         return -1;
 #endif
     
@@ -1246,8 +1256,8 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
     }
 
 #if !defined(DJGPP)
-    if ( cm_FreelanceMountPointExists(filename) ||
-         cm_FreelanceSymlinkExists(filename) )
+    if ( cm_FreelanceMountPointExists(filename, 0) ||
+         cm_FreelanceSymlinkExists(filename, 0) )
         return CM_ERROR_EXISTS;
 #endif
 
index 2cebe49..9f327fa 100644 (file)
@@ -19,6 +19,8 @@ extern long cm_FreelanceRemoveMount(char *toremove);
 extern long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp);
 extern long cm_FreelanceRemoveSymlink(char *toremove);
 extern long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp);
+extern long cm_FreelanceMountPointExists(char * filename, int prefix_ok);
+extern long cm_FreelanceSymlinkExists(char * filename, int prefix_ok);
 extern int cm_clearLocalMountPointChange();
 extern int cm_FakeRootFid(cm_fid_t *fidp);
 
index 7bc7c56..136e0ba 100644 (file)
@@ -1290,21 +1290,29 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us
 
             osi_Log1(afsd_logp,"cm_Lookup adding mount for non-existent directory: %s", 
                       osi_LogSaveString(afsd_logp,namep));
+
+            /* 
+             * There is an ugly behavior where a share name "foo" will be searched
+             * for as "fo".  If the searched for name differs by an already existing
+             * symlink or mount point in the Freelance directory, do not add the 
+             * new value automatically.
+             */
+
             if (namep[0] == '.') {
                 if (cm_GetCell_Gen(&namep[1], &fullname[1], CM_FLAG_CREATE)) {
                     found = 1;
-                    if ( stricmp(&namep[1], &fullname[1]) )
+                    if (!cm_FreelanceMountPointExists(fullname, 0))
+                        code = cm_FreelanceAddMount(fullname, &fullname[1], "root.cell.", 1, &rock.fid);
+                    if ( stricmp(&namep[1], &fullname[1]) && !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
                         code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid);
-                    else
-                        code = cm_FreelanceAddMount(namep, &fullname[1], "root.cell.", 1, &rock.fid);
                 }
             } else {
                 if (cm_GetCell_Gen(namep, fullname, CM_FLAG_CREATE)) {
                     found = 1;
-                    if ( stricmp(namep, fullname) )
+                    if (!cm_FreelanceMountPointExists(fullname, 0))
+                        code = cm_FreelanceAddMount(fullname, fullname, "root.cell.", 0, &rock.fid);
+                    if ( stricmp(namep, fullname) && !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
                         code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid);
-                    else
-                        code = cm_FreelanceAddMount(namep, fullname, "root.cell.", 0, &rock.fid);
                 }
             }
             if (!found || code < 0) {   /* add mount point failed, so give up */
index 41a914f..3523aca 100644 (file)
@@ -170,7 +170,7 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
     for (i=0;i<len;i++) {
         if(!(i%16)) {
             if(i) {
-                osi_Log0(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
+                osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
                 strcat(buf,"\r\n");
                 OutputDebugString(buf);
             }
@@ -191,7 +191,7 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
         buf[j] = (k>32 && k<127)?k:'.';
     }    
     if(i) {
-        osi_Log0(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
+        osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
         strcat(buf,"\r\n");
         OutputDebugString(buf);
     }   
@@ -3640,9 +3640,13 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             /* 
              * We have a requested path.  Check to see if it is something 
              * we know about.
+                        *
+                        * But be careful because the name that we might be searching
+                        * for might be a known name with the final character stripped
+                        * off.  If we 
              */
             code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2],
-                            CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                            CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
                             userp, NULL, &req, &scp);
             if (code == 0) {
                 /* Yes it is. */