Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:1:   // This file is part of Roxen WebServer.   // Copyright © 1996 - 2001, Roxen IS.   //   // The Roxen WebServer main program.   //   // Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others.   // ABS and suicide systems contributed freely by Francesco Chemolli    - constant cvs_version="$Id: roxen.pike,v 1.841 2003/11/03 14:11:47 grubba Exp $"; + constant cvs_version="$Id: roxen.pike,v 1.842 2003/11/04 14:51:40 grubba Exp $";      //! @appears roxen   //!   //! The Roxen WebServer main program.      // The argument cache. Used by the image cache.   ArgCache argcache;      // Some headerfiles   #define IN_ROXEN
Roxen.git/server/base_server/roxen.pike:5036:   // #endif    }             string code = "";    array variables = ({ " object userdb_module",    " object authmethod = id->conf",    " string realm = \"User\"",    " mapping(string:int|mapping) state = ([])", -  " int shorted = 0;", +     });       // Some state variables for optimizing.    int all_shorted = 1; // All allow patterns have return.    int need_auth = 0; // We need auth for some checks. -  +  int max_short_code = 0; // Max fail code for return checks.    int patterns; // Number of patterns.    multiset(string) checks = (<>); // Checks in state.       foreach( pattern / "\n", string line )    {    line = String.trim_all_whites( line );    if( !strlen(line) || line[0] == '#' )    continue;    sscanf( line, "%[^#]#", line );   
Roxen.git/server/base_server/roxen.pike:5093:    line);    else    code +=    sprintf(" authmethod = id->conf->find_auth_module( %O );\n",    line);    continue;    }    else if( sscanf( line, "realm %s", line ) )    {    line = String.trim_all_whites( line ); -  code += sprintf( " realm = %O;\n", line ); +  code += sprintf( " realm = %O;\n", line ); +  continue;    } -  else +  else {    m->report_notice( LOC_M( 60,"Syntax error in security patterns: "    "Expected 'allow' or 'deny'\n" )); -  +  continue; +  }    int shorted = sscanf( line, "%s return", line );          // Notes on the state variable:    //    // It has several potential entries (currently "ip", "user", "group",    // "time", "date", "referer", "language" and "luck").    // An entry exists in the mapping if a corresponding accept directive    // has been executed.    // @mixed    // @value 0    // Successful match.    // @value 1 -  // Fail with return. +  // Plain failure.    // @value 2 -  // Fail with authenticate return. -  // @value 3 -  // Fail without return. -  // @value 4 -  // Fail with authenticate without return. +  // Fail with authenticate.    // @endmixed    // -  // If the checking ends with an ok return (ie shorted == 1) only -  // entries with a value of 3 or higher will be regarded. -  // The highest regarded failure value will be used to determine -  // the action. +  // Shorted directives will only be regarded if all unshorted directives +  // encountered at that point have succeeded. +  // If the checking ends with an ok return unshorted directives of +  // the same class will be disregarded as well as any potential +  // short directives. +  // If there are unshorted directives of type 2 and none of type 1, +  // an auth request will be sent. +  // If there are unshorted directives, and all of them have been +  // satisfied an OK will be sent. +  // If there is a potential short directive of type 2, an auth +  // request will be sent. +  // If there are no unshorted directives and no potential short +  // directives an OK will be sent. +  // Otherwise a FAIL will be sent.       foreach(security_checks, array(string|int|array) check)    {    array args;    if (sizeof(args = array_sscanf(line, check[0])) == check[1])    {    // Got a match for this security check.    patterns++; -  int thr_code = 3; +  int thr_code = 1;    // run instructions.    foreach(check[2], mixed instr )    {    if( functionp( instr ) )    args = instr( @args );    else if( multisetp( instr ) )    {    foreach( (array)instr, string v )    if( !has_value( variables, v ) )    variables += ({ v });    }    else if( intp( instr ) ) { -  thr_code = 4; +  thr_code = 2;    need_auth = 1;    }    else if( stringp( instr ) )    {    code += sprintf( instr, @args )+"\n";    if( cmd == DENY )    {    code += " return " + -  ((thr_code == 4)?"authmethod->authenticate_throw(id, realm)": +  ((thr_code == 2)?"authmethod->authenticate_throw(id, realm)":    "1") +    ";\n";    }    else    {    if (shorted) {    // OK with return. Ignore FAIL/return. -  +  if (all_shorted) { +  code += + #if defined(SECURITY_PATTERN_DEBUG) || defined(HTACCESS_DEBUG) +  " {\n" +  " report_debug(\" Result: 0 (fast return)\\n\");\n" +  " return 0;\n" +  " }\n"; + #else /* !SECURITY_PATTERN_DEBUG && !HTACCESS_DEBUG */ +  " return 0;\n"; + #endif /* SECURITY_PATTERN_DEBUG || HTACCESS_DEBUG */ +  } else { +  code += " {\n";    if (checks[check[3]]) {    code += -  sprintf(" {\n" -  " m_delete(state, %O);\n" -  " shorted = 1;\n" -  " break;\n" -  " }\n", +  sprintf(" m_delete(state, %O);\n",    check[3]); -  } else { +  } +  if (max_short_code) { +  code += " short_fail = 0;\n"; +  }    code += -  " {\n" -  " shorted = 1;\n" +     " break;\n"    " }\n";    } -  +  // Handle the fail case. +  if (sizeof(checks)) { +  // Check that we can satify all preceeding tests. +  code += +  " else if (!sizeof(filter(values(state),\n" +  " values(state))))\n";    } else { -  +  code += " else\n"; +  } +  // OK so far for non return tests. +  if (thr_code < max_short_code) { +  code += +  sprintf(" if (short_fail < %d)\n" +  " short_fail = %d;\n", +  thr_code, +  thr_code); +  } else { +  code += +  sprintf(" short_fail = %d;\n", thr_code); +  max_short_code = thr_code; +  } +  } else {    // OK without return. Mark as OK.    code +=    sprintf(" {\n"    " state->%s = 0;\n"    " }\n",    check[3]);    all_shorted = 0; -  } +  // Handle the fail case.    if (checks[check[3]]) { -  // If not marked, or marked as lower failure +  // If not marked    // set the failure level.    code += -  sprintf(" else if (zero_type(state->%s) ||\n" -  " (state->%s && state->%s < %d))\n", -  check[3], -  check[3], check[3], thr_code-(shorted*2)); +  sprintf(" else if (zero_type(state->%s))\n", +  check[3]);    } else {    code += " else\n";    }    code += sprintf(" {\n"    " state->%s = %d;\n"    " }\n", -  check[3], thr_code-(shorted*2)); +  check[3], thr_code);    checks[check[3]] = 1;    }    }    } -  +  }    break;    }    }    }    if( !patterns ) return 0;    code = (" do {\n" +    code +    " } while(0);\n");    code = ("#include <module.h>\n"    "int|mapping f( RequestID id )\n"    "{\n" +    (variables * ";\n") +    ";\n" + -  +  (max_short_code?" int short_fail;\n":"") +   #if defined(SECURITY_PATTERN_DEBUG) || defined(HTACCESS_DEBUG)    sprintf(" report_debug(\"Verifying against pattern:\\n\"\n"    "%{ \" \" %O \"\\n\"\n%}"    " \"...\\n\");\n" -  "%s" +  "%s"+ +  (max_short_code? +  " report_debug(sprintf(\" Short code: %%O\\n\",\n" +  " short_fail));\n":"")+    " report_debug(sprintf(\" Result: %%O\\n\",\n"    " state));\n",    pattern/"\n", code) +   #else /* !SECURITY_PATTERN_DEBUG && !HTACCESS_DEBUG */    code +   #endif /* SECURITY_PATTERN_DEBUG || HTACCESS_DEBUG */ -  (all_shorted? -  " if(shorted) return 0;\n": -  "")+ -  ((need_auth || !all_shorted)? +  +  (!all_shorted?    " int fail = 0;\n"    " foreach(values(state), int value) {\n" -  " if (fail < value) fail = value;\n" -  " }\n": -  "")+ -  (all_shorted? -  "": -  " if (!fail || (shorted && fail < 3)) return 0;\n")+ -  (need_auth? -  " if ((fail-1) & 1)\n" +  " fail |= value;\n" +  " }\n" +  " if (!fail)\n" +  " return 0;\n": +  "") + +  (max_short_code > 1? +  " if (short_fail > 1)\n"    " return authmethod->authenticate_throw(id, realm);\n": -  "")+ +  "") + +  (!all_shorted && need_auth? +  " if (fail == 2)\n" +  " return authmethod->authenticate_throw(id, realm);\n": +  "") +    " return 1;\n"    "}\n");   #if defined(SECURITY_PATTERN_DEBUG) || defined(HTACCESS_DEBUG)    report_debug(sprintf("Compiling security pattern:\n"    "%{ %s\n%}\n"    "Code:\n"    "%{ %s\n%}\n",    pattern/"\n",    code/"\n"));   #endif /* SECURITY_PATTERN_DEBUG || HTACCESS_DEBUG */