Roxen.git / server / modules / filesystems / filesystem.pike

version» Context lines:

Roxen.git/server/modules/filesystems/filesystem.pike:1:   // This is a roxen module. Copyright © 1996 - 1999, Idonex AB.      // This is a virtual "file-system".   // It will be located somewhere in the name-space of the server.   // Also inherited by some of the other filesystems.      inherit "module";   inherit "roxenlib";   inherit "socket";    - constant cvs_version= "$Id: filesystem.pike,v 1.68 2000/03/01 18:30:33 nilsson Exp $"; + constant cvs_version= "$Id: filesystem.pike,v 1.69 2000/03/07 21:15:36 mast Exp $";   constant thread_safe=1;      #include <module.h>   #include <roxen.h>   #include <stat.h>   #include <request_trace.h>      #if DEBUG_LEVEL > 20   # ifndef FILESYSTEM_DEBUG   # define FILESYSTEM_DEBUG
Roxen.git/server/modules/filesystems/filesystem.pike:129:    "This is useful for eg named-ftp.");       defvar("no_symlinks", 0, "Forbid access to symlinks", TYPE_FLAG|VAR_MORE,    "EXPERIMENTAL.\n"    "Forbid access to paths containing symbolic links.<br>\n"    "NOTE: This can cause *alot* of lstat system-calls to be performed "    "and can make the server much slower.");       defvar("charset", "iso-8859-1", "File charset", TYPE_STRING,    "The charset the files on disk have."); +  +  defvar("internal_files", "", "Internal files", TYPE_STRING, +  "A comma separated list of glob patterns that matches files " +  "which should be considered internal. Internal files can't be " +  "requested directly from a client, won't show up in directory " +  "listings and can never be uploaded, moved or deleted from a " +  "client. They can only be accessed internally, e.g. with the " +  "RXML <tt>&lt;insert&gt;</tt> and <tt>&lt;use&gt;</tt> tags.");   }    -  + array(string) internal_files = ({});    -  + string check_variable (string var, mixed val) + { +  if (var == "internal_files") +  internal_files = map (val / ",", String.trim_whites); +  return 0; + } +  +    string path;   int stat_cache;      void start()   {   #ifdef THREADS    if(QUERY(access_as_user))    report_warning("It is not possible to use 'Access as user' when "    "running with threads. Remove -DENABLE_THREADS from "    "the start script if you really need this function\n");   #endif       path = QUERY(searchpath);    stat_cache = QUERY(stat_cache); -  +  internal_files = map (QUERY (internal_files) / ",", String.trim_whites);    FILESYSTEM_WERR("Online at "+QUERY(mountpoint)+" (path="+path+")");    cache_expire("stat_cache");   }      string query_location()   {    return QUERY(mountpoint);   }       - mixed stat_file( mixed f, mixed id ) + #define FILTER_INTERNAL_FILE(f, id) \ +  (!id->misc->internal_get && sizeof (filter (internal_files, glob, (f/"/")[-1]))) +  + mixed stat_file( string f, RequestID id )   {    array fs; -  +  +  FILESYSTEM_WERR("stat_file for \""+f+"\""); +  +  if (FILTER_INTERNAL_FILE (f, id)) return 0; +     if(stat_cache && !id->pragma["no-cache"] &&    (fs=cache_lookup("stat_cache",path+f)))    return fs[0];      #ifndef THREADS    object privs;    if (((int)id->misc->uid) && ((int)id->misc->gid) &&    (QUERY(access_as_user))) {    // NB: Root-access is prevented.    privs=Privs("Statting file", (int)id->misc->uid, (int)id->misc->gid );
Roxen.git/server/modules/filesystems/filesystem.pike:182: Inside #if undefined(THREADS)
   fs = file_stat(path + f); /* No security currently in this function */   #ifndef THREADS    privs = 0;   #endif    if(!stat_cache)    return fs;    cache_set("stat_cache", path+f, ({fs}));    return fs;   }    - string real_file( mixed f, mixed id ) + string real_file( string f, RequestID id )   {    if(this->stat_file( f, id ))   /* This filesystem might be inherited by other filesystem, therefore    'this' */    return path + f;   }    - int dir_filter_function(string f) + int dir_filter_function(string f, RequestID id)   {    if(f[0]=='.' && !QUERY(.files)) return 0;    if(!QUERY(tilde) && backup_extension(f)) return 0; -  +  if (FILTER_INTERNAL_FILE (f, id)) return 0;    return 1;   }    - array find_dir( string f, object id ) + array find_dir( string f, RequestID id )   {    mixed ret;    array dir;    -  +  FILESYSTEM_WERR("find_dir for \""+f+"\""); +     object privs;      #ifndef THREADS    if (((int)id->misc->uid) && ((int)id->misc->gid) &&    (QUERY(access_as_user))) {    // NB: Root-access is prevented.    privs=Privs("Getting dir", (int)id->misc->uid, (int)id->misc->gid );    }   #endif   
Roxen.git/server/modules/filesystems/filesystem.pike:236:    // Access to this dir is not allowed.    if(sizeof(dir & ({".nodiraccess",".www_not_browsable",".nodir_access"})))    {    errors++;    return 0;    }       dirlists++;       // Pass _all_ files, hide none. -  if(QUERY(tilde) && QUERY(.files)) /* This is quite a lot faster */ +  if(QUERY(tilde) && QUERY(.files) && +  (!sizeof (internal_files) || id->misc->internal_get)) +  /* This is quite a lot faster */    return dir;    -  return Array.filter(dir, dir_filter_function); +  return Array.filter(dir, dir_filter_function, id);   }         mapping putting = ([]);      void done_with_put( array(object|string) id_arr )   {   // werror("Done with put.\n");    object to;    object from;
Roxen.git/server/modules/filesystems/filesystem.pike:362:    if (arr[1] == -3) {    return(1);    }    } else {    return(0);    }    }    return(0);   }    - mixed find_file( string f, object id ) + mixed find_file( string f, RequestID id )   {    TRACE_ENTER("find_file(\""+f+"\")", 0);    object o;    int size;    string tmp;    string oldf = f;       FILESYSTEM_WERR("Request for \""+f+"\"");       string mountpoint = QUERY(mountpoint);
Roxen.git/server/modules/filesystems/filesystem.pike:436:    /* FIXME: Should probably keep prestates etc too.    * /grubba 1999-01-14    */    string new_query =    http_encode_string(id->not_query[..sizeof(id->not_query)-2]) +    (id->query?("?" + id->query):"");    TRACE_LEAVE("Redirecting to \"" + new_query + "\"");    return http_redirect(new_query, id);    }    -  if(!id->misc->internal_get && !QUERY(.files) +  if(!id->misc->internal_get) { +  if (!QUERY(.files)    && (tmp = (id->not_query/"/")[-1])    && tmp[0] == '.') {    TRACE_LEAVE("Is .-file");    return 0;    } -  +  if (FILTER_INTERNAL_FILE (f, id)) { +  TRACE_LEAVE ("Is internal file"); +  return 0; +  } +  }   #ifndef THREADS    object privs;    if (((int)id->misc->uid) && ((int)id->misc->gid) &&    (QUERY(access_as_user))) {    // NB: Root-access is prevented.    privs=Privs("Getting file", (int)id->misc->uid, (int)id->misc->gid );    }   #endif       TRACE_ENTER("Opening file \"" + f + "\"", 0);
Roxen.git/server/modules/filesystems/filesystem.pike:488:    break;       case "MKDIR":    if(!QUERY(put))    {    id->misc->error_code = 405;    TRACE_LEAVE("MKDIR disallowed (since PUT is disallowed)");    return 0;    }    +  if (FILTER_INTERNAL_FILE (f, id)) { +  id->misc->error_code = 405; +  TRACE_LEAVE("MKDIR disallowed (since the dir name matches internal file glob)"); +  return 0; +  } +     if(QUERY(check_auth) && (!id->auth || !id->auth[0])) {    TRACE_LEAVE("MKDIR: Permission denied");    return http_auth_required("foo",    "<h1>Permission to 'MKDIR' denied</h1>");    }    mkdirs++;    object privs;      // #ifndef THREADS // Ouch. This is is _needed_. Well well...    if (((int)id->misc->uid) && ((int)id->misc->gid)) {
Roxen.git/server/modules/filesystems/filesystem.pike:538:    break;       case "PUT":    if(!QUERY(put))    {    id->misc->error_code = 405;    TRACE_LEAVE("PUT disallowed");    return 0;    }    +  if (FILTER_INTERNAL_FILE (f, id)) { +  id->misc->error_code = 405; +  TRACE_LEAVE("PUT of internal file is disallowed"); +  return 0; +  } +     if(QUERY(check_auth) && (!id->auth || !id->auth[0])) {    TRACE_LEAVE("PUT: Permission denied");    return http_auth_required("foo",    "<h1>Permission to 'PUT' files denied</h1>");    }       puts++;       QUOTA_WERR("Checking quota.\n");    if (id->misc->quota_obj && (id->misc->len > 0) &&
Roxen.git/server/modules/filesystems/filesystem.pike:655:    // Change permission of a file.    // FIXME: !!       if(!QUERY(put))    {    id->misc->error_code = 405;    TRACE_LEAVE("CHMOD disallowed (since PUT is disallowed)");    return 0;    }    +  if (FILTER_INTERNAL_FILE (f, id)) { +  id->misc->error_code = 405; +  TRACE_LEAVE("CHMOD of internal file is disallowed"); +  return 0; +  } +     if(QUERY(check_auth) && (!id->auth || !id->auth[0])) {    TRACE_LEAVE("CHMOD: Permission denied");    return http_auth_required("foo",    "<h1>Permission to 'CHMOD' files denied</h1>");    }       object privs;      // #ifndef THREADS // Ouch. This is is _needed_. Well well...    if (((int)id->misc->uid) && ((int)id->misc->gid)) {
Roxen.git/server/modules/filesystems/filesystem.pike:739:    "<h1>Permission to 'MV' files denied</h1>");    }    string movefrom;    if(!id->misc->move_from ||    !(movefrom = id->conf->real_file(id->misc->move_from, id))) {    id->misc->error_code = 405;    errors++;    TRACE_LEAVE("MV: No source file");    return 0;    } +  +  if (FILTER_INTERNAL_FILE (movefrom, id) || +  FILTER_INTERNAL_FILE (f, id)) { +  id->misc->error_code = 405; +  TRACE_LEAVE("MV to or from internal file is disallowed"); +  return 0; +  } +     moves++;       object privs;      // #ifndef THREADS // Ouch. This is is _needed_. Well well...    if (((int)id->misc->uid) && ((int)id->misc->gid)) {    // NB: Root-access is prevented.    privs=Privs("Moving file", (int)id->misc->uid, (int)id->misc->gid );    }   // #endif
Roxen.git/server/modules/filesystems/filesystem.pike:828:    string new_uri = combine_path(uri + "/../",    id->misc["new-uri"]);       if (new_uri[..sizeof(mountpoint)-1] != mountpoint) {    id->misc->error_code = 405;    TRACE_LEAVE("MOVE: Dest file on other filesystem.");    return(0);    }    string moveto = path + "/" + new_uri[sizeof(mountpoint)..];    +  if (FILTER_INTERNAL_FILE (f, id) || +  FILTER_INTERNAL_FILE (moveto, id)) { +  id->misc->error_code = 405; +  TRACE_LEAVE("MOVE to or from internal file is disallowed"); +  return 0; +  } +     size = FILE_SIZE(moveto);       if(!QUERY(delete) && size != -1)    {    id->misc->error_code = 405;    TRACE_LEAVE("MOVE disallowed (DELE disabled, can't overwrite file)");    return 0;    }       if(size < -1)
Roxen.git/server/modules/filesystems/filesystem.pike:901:    return http_string_answer("Ok");          case "DELETE":    if(!QUERY(delete) || size==-1)    {    id->misc->error_code = 405;    TRACE_LEAVE("DELETE: Disabled");    return 0;    } +  +  if (FILTER_INTERNAL_FILE (f, id)) { +  id->misc->error_code = 405; +  TRACE_LEAVE("DELETE of internal file is disallowed"); +  return 0; +  } +     if(QUERY(check_auth) && (!id->auth || !id->auth[0])) {    TRACE_LEAVE("DELETE: Permission denied");    return http_low_answer(403, "<h1>Permission to DELETE file denied</h1>");    }       if (QUERY(no_symlinks) && (contains_symlinks(path, oldf))) {    errors++;    report_error("Deletion of " + f + " failed. Permission denied.\n");    TRACE_LEAVE("DELETE: Contains symlinks");    return http_low_answer(403, "<h2>Permission denied.</h2>");