Branch: Tag:

2003-11-04

2003-11-04 14:51:40 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Messed around with compile_security_pattern() some more.

Rev: server/base_server/roxen.pike:1.842

6:   // 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   //!
5043:    " 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.   
5100:    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 );      
5118:    // @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)    {
5139:    {    // Got a match for this security check.    patterns++; -  int thr_code = 3; +  int thr_code = 1;    // run instructions.    foreach(check[2], mixed instr )    {
5152:    variables += ({ v });    }    else if( intp( instr ) ) { -  thr_code = 4; +  thr_code = 2;    need_auth = 1;    }    else if( stringp( instr ) )
5161:    if( cmd == DENY )    {    code += " return " + -  ((thr_code == 4)?"authmethod->authenticate_throw(id, realm)": +  ((thr_code == 2)?"authmethod->authenticate_throw(id, realm)":    "1") +    ";\n";    }
5169:    {    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"
5192:    " }\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;    }    }
5225:    "{\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)