From 939f6d6794e1dc0677624ac67d1f00950417b713 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Thu, 15 Jul 1999 20:44:24 +0000 Subject: more dfs stuff. this looks like it's going to be more appropriate to use the vfs tables. at the moment, i replaced all calls to unix_convert() with unix_dfs_convert(). this does the job, but it's not very nice. (This used to be commit 00d4aebce9f268a737ef9df9bdbe59f8fe831979) --- source3/include/proto.h | 11 +++-- source3/smbd/dfs.c | 125 ++++++++++++++++++++++++++++++------------------ source3/smbd/filename.c | 36 ++++++++++++-- source3/smbd/nttrans.c | 12 ++++- source3/smbd/reply.c | 100 ++++++++++++++++++++++++++++---------- source3/smbd/trans2.c | 42 +++++++++++++--- 6 files changed, 239 insertions(+), 87 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index c17cbb657b..4cea4b6cee 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3315,7 +3315,8 @@ SMB_BIG_UINT sys_disk_free(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SM /*The following definitions come from smbd/dfs.c */ BOOL init_dfs_table(void); -int under_dfs(connection_struct *conn, const char *path); +int under_dfs(connection_struct *conn, const char *path, + char *local_path, size_t path_len); /*The following definitions come from smbd/dir.c */ @@ -3370,8 +3371,12 @@ void sys_sync_file(int fd); /*The following definitions come from smbd/filename.c */ void print_stat_cache_statistics(void); -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst); +BOOL unix_dfs_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst); +BOOL unix_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst); BOOL check_name(char *name,connection_struct *conn); /*The following definitions come from smbd/files.c */ diff --git a/source3/smbd/dfs.c b/source3/smbd/dfs.c index ca45d89b37..55433f2c47 100644 --- a/source3/smbd/dfs.c +++ b/source3/smbd/dfs.c @@ -18,42 +18,42 @@ static BOOL parse_dfs_text_entry(char *line, dfs_internal_table *buf) tok[count] = strtok(line,":"); /* strip the comment lines */ - if (tok[0][0]=='#') return (False); + if (tok[0][0] == '#') return (False); count++; - while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count1) { + 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); + buf->localpath_length = strlen(buf->localpath); + buf->sharename_length = strlen(buf->sharename); } else return (False); - if (count>2) + if (count > 2) buf->proximity = atoi(tok[2]); else buf->proximity = 0; - if (count>3) + 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); + DEBUGADD(7,("localpath: [%s]\n", buf->localpath)); + DEBUGADD(7,("sharename: [%s]\n", buf->sharename)); + return True; } /**************************************************************************** @@ -69,7 +69,7 @@ static void mangle_dfs_path(dfs_internal_table *buf) fstring temp; p = buf->localpath; - mp =buf->mangledpath; + mp = buf->mangledpath; mlen = sizeof(buf->mangledpath); ZERO_STRUCTP(mp); @@ -112,19 +112,19 @@ 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; + 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; + entry = NULL; + dfs_struct.ready = False; - if (*file=='\0') { + if (*file == '\0') { DEBUG(0,("No DFS map, Samba is running in NON DFS mode\n")); return False; } @@ -150,75 +150,106 @@ BOOL init_dfs_table(void) } num_lines++; } - dfs_struct.size=total; - dfs_struct.table=entry; + dfs_struct.size = total; + dfs_struct.table = entry; fclose(f); /* we have the file in memory */ /* now initialise the mangled names */ - for (i=0; iname_len); } +/**************************************************************************** + this routine converts from the dos and dfs namespace to the unix namespace. +****************************************************************************/ +BOOL unix_dfs_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) +{ + pstring local_path; + + DEBUG(10,("unix_dfs_convert: %s\n", name)); + + if (name != NULL && + under_dfs(conn, name, local_path, sizeof(local_path))) + { + DEBUG(10,("%s is in dfs map.\n", name)); + + /* check for our own name */ + if (StrCaseCmp(global_myname, name+1) > 0) + { + return False; + } + + pstrcpy(name, local_path); + + DEBUG(10,("removed name: %s\n", name)); + } + return unix_convert(name, conn, saved_last_component, bad_path, pst); +} + /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format @@ -329,9 +359,9 @@ used to pick the correct error code to return between ENOENT and ENOTDIR as Windows applications depend on ERRbadpath being returned if a component of a pathname does not exist. ****************************************************************************/ - -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, - BOOL *bad_path, SMB_STRUCT_STAT *pst) +BOOL unix_convert(char *name,connection_struct *conn, + char *saved_last_component, + BOOL *bad_path, SMB_STRUCT_STAT *pst) { SMB_STRUCT_STAT st; char *start, *end; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 657dd8b130..ac688a5baa 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -669,7 +669,11 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) { @@ -952,7 +956,11 @@ static int call_nt_transact_create(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bfa68ab140..b8300da40a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -832,15 +832,14 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SMB_STRUCT_STAT st; pstrcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,conn,0,&bad_path,&st); - - mode = SVAL(inbuf,smb_vwv0); - - if(under_dfs(conn, name)) { + if (!unix_dfs_convert(name,conn,0,&bad_path,&st)) + { SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); } + mode = SVAL(inbuf,smb_vwv0); + if (check_name(name,conn)) { if(VALID_STAT(st)) ok = S_ISDIR(st.st_mode); @@ -898,11 +897,6 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(fname,smb_buf(inbuf) + 1); - if (under_dfs(conn, fname)) { - SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); - return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); - } - /* dos smetimes asks for a stat of "" - it returns a "hidden directory" under WfWg - weird! */ if (! (*fname)) @@ -915,7 +909,11 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { - unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(fname,conn)) { if (VALID_STAT(sbuf) || conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == 0) @@ -980,7 +978,11 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL bad_path = False; pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path,&st); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); @@ -1087,7 +1089,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstrcpy(directory,smb_buf(inbuf)+1); pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } unix_format(dir2); if (!check_name(directory,conn)) @@ -1348,7 +1354,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, share_mode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) @@ -1453,7 +1463,11 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) @@ -1587,7 +1601,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (createmode & aVOLID) { @@ -1673,7 +1691,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } unixmode = unix_mode(conn,createmode); @@ -1779,7 +1801,11 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - unix_convert(name,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(name,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } p = strrchr(name,'/'); if (!p) { @@ -2940,7 +2966,11 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(directory, conn)) ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), @@ -3035,7 +3065,11 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,conn, NULL,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn, NULL,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(directory,conn)) { @@ -3236,12 +3270,20 @@ int rename_internals(connection_struct *conn, *directory = *mask = 0; - unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,newname_last_component,&bad_path2,NULL); + if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } + if (!unix_dfs_convert(newname,conn,newname_last_component,&bad_path2,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } /* * Split the old name into directory and last component - * strings. Note that unix_convert may have stripped off a + * strings. Note that if (!unix_dfs_convert may have stripped off a * leading ./ from both name and newname if the rename is * at the root of the share. We need to make sure either both * name and newname contain a / character or neither of them do @@ -3552,8 +3594,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRSRV,ERRinvdevice)); } - unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,0,&bad_path2,NULL); + if (!unix_dfs_convert(name,conn,0,&bad_path1,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } + if (!unix_dfs_convert(newname,conn,0,&bad_path2,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } target_is_directory = dos_directory_exist(newname,NULL); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f324b658b9..14fa26dd55 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -216,7 +216,11 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } fsp = file_new(); if (!fsp) @@ -665,7 +669,11 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { @@ -1255,7 +1263,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, * to do this call. JRA. */ fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1288,7 +1300,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = &fname1[0]; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False), &sbuf))) { @@ -1518,7 +1534,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * to do this call. JRA. */ fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&st); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (!check_name(fname,conn) || (!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1549,7 +1569,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path,&st); + if (!unix_dfs_convert(fname,conn,0,&bad_path,&st)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) @@ -1880,7 +1904,11 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL)) + { + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED)); + } if (check_name(directory,conn)) ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False), unix_mode(conn,aDIR)); -- cgit