summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/dfs.h53
-rw-r--r--source3/smbd/dfs.c215
2 files changed, 268 insertions, 0 deletions
diff --git a/source3/include/dfs.h b/source3/include/dfs.h
new file mode 100644
index 0000000000..1bf26e230b
--- /dev/null
+++ b/source3/include/dfs.h
@@ -0,0 +1,53 @@
+
+typedef struct _referal_trans_param
+{
+ uint16 level;
+ char directory[255];
+ uint16 type;
+} referal_trans_param;
+
+typedef struct _referal_ver_2
+{
+ uint16 version;
+ uint16 size;
+ uint16 server_type;
+ uint16 flags;
+ uint32 proximity;
+ uint32 ttl;
+ uint16 filename_offset;
+ uint16 mangledname_offset;
+ uint16 sharename_offset;
+ char sharename[255];
+} referal_ver_2;
+
+typedef struct _dfs_response
+{
+ uint16 path_consumed;
+ uint16 number_of_referal;
+ uint32 server_function;
+ referal_ver_2 *referal;
+ char filename[255];
+ char mangledname[255];
+ struct _dfs_response *next;
+} dfs_response;
+
+
+typedef struct _dfs_internal_table
+{
+ pstring localpath;
+ pstring mangledpath;
+ pstring sharename;
+ unsigned int proximity;
+ unsigned int type;
+ int localpath_length;
+ int mangledpath_length;
+ int sharename_length;
+} dfs_internal_table;
+
+typedef struct _dfs_internal
+{
+
+ dfs_internal_table *table;
+ int size;
+ BOOL ready;
+} dfs_internal;
diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c
new file mode 100644
index 0000000000..0c1b3db4c4
--- /dev/null
+++ b/source3/smbd/dfs.c
@@ -0,0 +1,215 @@
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+dfs_internal dfs_struct;
+extern pstring global_myname;
+
+/****************************************************************************
+read a line and split it
+****************************************************************************/
+static BOOL parse_dfs_text_entry(char *line, dfs_internal_table *buf)
+{
+#define MAXTOK 4
+ char *tok[MAXTOK+1];
+ int count = 0;
+
+ tok[count] = strtok(line,":");
+
+ /* strip the comment lines */
+ if (tok[0][0]=='#') return (False);
+ count++;
+
+ while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count<MAXTOK)
+ {
+ count++;
+ }
+
+ DEBUG(7,("Found [%d] tokens\n", count));
+
+ if (count>1) {
+ StrnCpy(buf->localpath, tok[0], sizeof(buf->localpath)-1);
+ StrnCpy(buf->sharename, tok[1], sizeof(buf->sharename)-1);
+/*
+ strupper(buf->localpath);
+ strupper(buf->sharename);
+*/
+ buf->localpath_length=strlen(buf->localpath);
+ buf->sharename_length=strlen(buf->sharename);
+ }
+ else
+ return (False);
+
+ if (count>2)
+ buf->proximity = atoi(tok[2]);
+ else
+ buf->proximity = 0;
+
+ if (count>3)
+ buf->type = atoi(tok[3]);
+ else
+ buf->type = 2;
+
+ DEBUGADD(7,("[%s]\n", buf->localpath));
+ DEBUGADD(7,("[%s]\n", buf->sharename));
+ return(True);
+}
+
+/****************************************************************************
+mangle the localpath and store it.
+****************************************************************************/
+static void mangle_dfs_path(dfs_internal_table *buf)
+{
+ char *p;
+ char *s;
+ char *q;
+ int i;
+
+ fstring temp;
+
+ p=buf->localpath;
+ s=buf->mangledpath;
+
+ ZERO_STRUCTP(s);
+ DEBUG(0, ("DFS name is:[%s]\n", buf->localpath));
+
+ /* copy the head: \server-name\ */
+ q=strchr(p+1, '\\');
+ strncpy(s, p, q-p+1);
+ p=q+1;
+
+ while (q!=NULL)
+ {
+ q=strchr(p, '\\');
+ if (q!=NULL)
+ i=PTR_DIFF(q,p);
+ else
+ i=strlen(p);
+
+ strncpy(temp, p, i);
+
+ if (!is_8_3(temp, True))
+ mangle_name_83(temp);
+
+ strncat(s, temp, i);
+ if (q!=NULL)
+ strncat(s, "\\", 1);
+ p=q+1;
+ }
+
+/*
+ strupper(buf->mangledpath);
+*/
+ buf->mangledpath_length=strlen(buf->mangledpath);
+ DEBUGADD(0, ("DFS mangled name is: [%s]\n", buf->mangledpath));
+}
+
+/****************************************************************************
+initialisation de la table dfs en memoire au demarrage de samba
+****************************************************************************/
+BOOL init_dfs_table(void)
+{
+ char *file=lp_dfs_map();
+ int num_lines=0;
+ int total=0;
+ FILE *f;
+ pstring line;
+ int i;
+
+ dfs_internal_table *entry;
+
+ entry=NULL;
+ dfs_struct.ready=False;
+
+ if (*file=='\0') {
+ DEBUG(0,("No DFS map, Samba is running in NON DFS mode\n"));
+ return False;
+ }
+
+ f = sys_fopen(file, "r");
+ if (!f) {
+ DEBUG(0,("No DFS map file, Samba is running in NON DFS mode\n"));
+ return False;
+ }
+
+ while ( fgets(line, sizeof(pstring), f) )
+ {
+ entry = Realloc(entry,sizeof(dfs_internal_table)*(total+1));
+ if (! entry)
+ {
+ total = 0;
+ break;
+ }
+
+ if ( parse_dfs_text_entry(line, &(entry[total]) ) )
+ {
+ total++;
+ }
+ num_lines++;
+ }
+ dfs_struct.size=total;
+ dfs_struct.table=entry;
+ fclose(f);
+
+ /* we have the file in memory */
+ /* now initialise the mangled names */
+ for (i=0; i<total; i++)
+ {
+ mangle_dfs_path(&(entry[i]));
+ }
+
+ dfs_struct.ready=True;
+ DEBUG(0,("Samba is DFS aware now!\n"));
+ return True;
+}
+
+/****************************************************************************
+ check if a path name is a DFS branch
+****************************************************************************/
+int under_dfs(connection_struct *conn, const char *path)
+{
+ fstring fullpath;
+ int i;
+ int snum;
+
+ int mangled_len;
+ int file_len;
+ int path_len;
+
+ BOOL ok=False;
+
+ dfs_internal_table *list=dfs_struct.table;
+
+ snum=SNUM(conn);
+ snprintf(fullpath, sizeof(fullpath), "\\%s\\%s\\%s", global_myname,
+ lp_servicename(snum), path);
+
+ strupper(fullpath);
+
+ path_len=strlen(fullpath);
+
+ DEBUG(0,("looking for: [%s]\n", fullpath));
+ for(i=0; i<dfs_struct.size; i++)
+ {
+ file_len=list[i].localpath_length;
+ mangled_len=list[i].mangledpath_length;
+
+ DEBUG(6,("checking against [%s][%d]\n", list[i].localpath,i));
+
+ if(file_len==path_len && !strncasecmp(list[i].localpath, fullpath, file_len))
+ {
+ DEBUG(0,("found one linked to [%s]\n", list[i].sharename));
+ ok=True;
+ break;
+ }
+
+ if(mangled_len==path_len && !strncasecmp(list[i].mangledpath, fullpath, mangled_len))
+ {
+ DEBUG(0,("found one mangled linked to [%s]\n", list[i].sharename));
+ ok=True;
+ break;
+ }
+ }
+ return ok;
+}