diff options
-rw-r--r-- | source3/include/dfs.h | 53 | ||||
-rw-r--r-- | source3/smbd/dfs.c | 215 |
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; +} |