示例#1
0
static authz_status dbdgroup_check_authorization(request_rec *r,
                                                 const char *require_args,
                                                 const void *parsed_require_args)
{
    int i, rv;
    const char *w;
    apr_array_header_t *groups = NULL;
    const char *t;
    authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config,
                                              &authz_dbd_module);

    if (!r->user) {
        return AUTHZ_DENIED_NO_USER;
    }

    if (groups == NULL) {
        groups = apr_array_make(r->pool, 4, sizeof(const char*));
        rv = authz_dbd_group_query(r, cfg, groups);
        if (rv != OK) {
            return AUTHZ_GENERAL_ERROR;
        }
    }

    t = require_args;
    while (t[0]) {
        w = ap_getword_white(r->pool, &t);
        for (i=0; i < groups->nelts; ++i) {
            if (!strcmp(w, ((const char**)groups->elts)[i])) {
                return AUTHZ_GRANTED;
            }
        }
    }

    return AUTHZ_DENIED;
}
/**
 * This hook is used to check to see if the resource being requested
 * is available for the authenticated user (r->user and r->ap_auth_type).
 * It runs after the access_checker and check_user_id hooks. Note that
 * it will *only* be called if Apache determines that access control has
 * been applied to this resource (through a 'Require' directive).
 *
 * @param r the current request
 * @return OK, DECLINED, or HTTP_...
 */
static int auth_checker(request_rec *r) {

    authnz_crowd_dir_config *config = get_config(r);
    if (config == NULL) {
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    if (r->user == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, "Authorisation requested, but no user provided.");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Iterate over requirements */
    const apr_array_header_t *requires = ap_requires(r);
    apr_array_header_t *user_groups = NULL;
    int x;
    for (x = 0; x < requires->nelts; x++) {

        require_line require = APR_ARRAY_IDX(requires, x, require_line);

        /* Ignore this requirement if it does not apply to the HTTP method used in the request. */
        if (!(require.method_mask & (AP_METHOD_BIT << r->method_number))) {
            continue;
        }

        const char *next_word = require.requirement;

        /* Only process group requirements */
        if (strcasecmp(ap_getword_white(r->pool, &next_word), "group") == 0) {

            /* Fetch groups only if actually needed. */
            if (user_groups == NULL) {
                user_groups = crowd_user_groups(r->user, r, config->crowd_config);
                if (user_groups == NULL) {
                    return HTTP_INTERNAL_SERVER_ERROR;
                }
            }

            /* Iterate over the groups mentioned in the requirement. */
            while (*next_word != '\0') {
                const char *required_group = ap_getword_conf(r->pool, &next_word);
                /* Iterate over the user's groups. */
                int y;
                for (y = 0; y < user_groups->nelts; y++) {
                    const char *user_group = APR_ARRAY_IDX(user_groups, y, const char *);
                    if (strcasecmp(user_group, required_group) == 0) {
                        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                            "Granted authorisation to '%s' on the basis of membership of '%s'.", r->user, user_group);
                        return OK;
                    }
                }

            }
        }

    }
    
    ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "Denied authorisation to '%s'.", r->user);
    return config->authoritative ? HTTP_UNAUTHORIZED : DECLINED;
}
示例#3
0
static int check_user_access(request_rec * r) {
	int m = r->method_number;
	const apr_array_header_t * reqs_arr = ap_requires(r);
	if (! reqs_arr) {
		return DECLINED;
	}
	require_line * reqs = (require_line *)reqs_arr->elts;
	int x;
	for (x = 0; x < reqs_arr->nelts; x++) {
		if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
			continue;
		}
		const char * t = reqs[x].requirement;
		const char * w = ap_getword_white(r->pool, &t);
		if (!strcasecmp(w, "pam-account")) {
			const char * pam_service = ap_getword_conf(r->pool, &t);
			if (pam_service && strlen(pam_service)) {
				authn_status ret = pam_authenticate_with_login_password(r, pam_service, r->user, NULL, _PAM_STEP_ACCOUNT);
				if (ret == AUTH_GRANTED) {
					return OK;
				}
			}
		}
	}
	return DECLINED;
}
/**************************************************
 * Authorization phase (Apache 2.4)
 *
 * Handles Require persona-idp directives.
 *
 * When this is first called, the authentication context hasn't been setup
 * yet. Return AUTHZ_DENIED_NO_USER to force it to run, then this will be
 * called again, with the context setup.
 **************************************************/
static authz_status persona_idp_check_authorization(request_rec *r,
                                                    const char *require_args,
                                                    const void *parsed_require_args) {

  ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "Require persona-idp");
  if (!r->user)
    // this triggers running authn hook, which we need
    return AUTHZ_DENIED_NO_USER;

  char *reqIdp = ap_getword_white(r->pool, &require_args);
  const char *issuer = apr_table_get(r->notes, PERSONA_ISSUER_NOTE);
  return issuer && !strcmp(issuer, reqIdp) ? AUTHZ_GRANTED : AUTHZ_DENIED;
}
示例#5
0
static bool parse_auth_header(apr_pool_t *pool, const char **auth_header,
                              gss_buffer_t value)
{
    char *auth_header_value;

    auth_header_value = ap_getword_white(pool, auth_header);
    if (!auth_header_value) return false;
    value->length = apr_base64_decode_len(auth_header_value) + 1;
    value->value = apr_pcalloc(pool, value->length);
    if (!value->value) return false;
    value->length = apr_base64_decode(value->value, auth_header_value);

    return true;
}
/**************************************************
 * Authorization phase (Apache 2.2)
 *
 * Requires authentication phase to run first.
 *
 * Handles Require persona-idp directives.
 **************************************************/
static int Auth_persona_check_auth(request_rec *r)
{
  const apr_array_header_t *reqs_arr=NULL;
  require_line *reqs=NULL;
  register int x;
  const char *szRequireLine;
  char *szRequire_cmd;

  if (!persona_authn_active(r)) {
    return DECLINED;
  }
  ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "Auth_persona_check_auth");

  /* get require line */
  reqs_arr = ap_requires(r);
  reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;

  /* decline if no require line found */
  if (!reqs_arr) return DECLINED;

  /* walk through the array to check each require command */
  for (x = 0; x < reqs_arr->nelts; x++) {

    if (!(reqs[x].method_mask & (AP_METHOD_BIT << r->method_number)))
      continue;

    /* get require line */
    szRequireLine = reqs[x].requirement;
    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG  "Require Line is '%s'", szRequireLine);

    /* get the first word in require line */
    szRequire_cmd = ap_getword_white(r->pool, &szRequireLine);
    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Require Cmd is '%s'", szRequire_cmd);

    // persona-idp: check host part of user name
    if (!strcmp("persona-idp", szRequire_cmd)) {
      char *reqIdp = ap_getword_conf(r->pool, &szRequireLine);
      const char *issuer = apr_table_get(r->notes, PERSONA_ISSUER_NOTE);
      if (!issuer || strcmp(issuer, reqIdp)) {
        return HTTP_FORBIDDEN;
      }
      ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r,
                    ERRTAG "user '%s' is authorized", r->user);
      return OK;
    }

  }
  return DECLINED;
}
static authz_status dbdgroup_check_authorization(request_rec *r,
                                                 const char *require_args,
                                                 const void *parsed_require_args)
{
    int i, rv;
    const char *w;
    apr_array_header_t *groups = NULL;

    const char *err = NULL;
    const ap_expr_info_t *expr = parsed_require_args;
    const char *require;

    const char *t;
    authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config,
                                              &authz_dbd_module);

    if (!r->user) {
        return AUTHZ_DENIED_NO_USER;
    }

    if (groups == NULL) {
        groups = apr_array_make(r->pool, 4, sizeof(const char*));
        rv = authz_dbd_group_query(r, cfg, groups);
        if (rv != OK) {
            return AUTHZ_GENERAL_ERROR;
        }
    }

    require = ap_expr_str_exec(r, expr, &err);
    if (err) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02590)
                      "authz_dbd authorize: require dbd-group: Can't "
                      "evaluate require expression: %s", err);
        return AUTHZ_DENIED;
    }

    t = require;
    while (t[0]) {
        w = ap_getword_white(r->pool, &t);
        for (i=0; i < groups->nelts; ++i) {
            if (!strcmp(w, ((const char**)groups->elts)[i])) {
                return AUTHZ_GRANTED;
            }
        }
    }

    return AUTHZ_DENIED;
}
static const char *parse_cmd(apr_pool_t *p, const char **args, ef_filter_t *filter)
{
    if (**args == '"') {
        const char *start = *args + 1;
        char *parms;
        int escaping = 0;
        apr_status_t rv;

        ++*args; /* move past leading " */
        /* find true end of args string (accounting for escaped quotes) */
        while (**args && (**args != '"' || (**args == '"' && escaping))) {
            if (escaping) {
                escaping = 0;
            }
            else if (**args == '\\') {
                escaping = 1;
            }
            ++*args;
        }
        if (**args != '"') {
            return "Expected cmd= delimiter";
        }
        /* copy *just* the arg string for parsing, */
        parms = apr_pstrndup(p, start, *args - start);
        ++*args; /* move past trailing " */

        /* parse and tokenize the args. */
        rv = apr_tokenize_to_argv(parms, &(filter->args), p);
        if (rv != APR_SUCCESS) {
            return "cmd= parse error";
        }
    }
    else
    {
        /* simple path */
        /* Allocate space for two argv pointers and parse the args. */
        filter->args = (char **)apr_palloc(p, 2 * sizeof(char *));
        filter->args[0] = ap_getword_white(p, args);
        filter->args[1] = NULL; /* end of args */
    }
    if (!filter->args[0]) {
        return "Invalid cmd= parameter";
    }
    filter->command = filter->args[0];

    return NULL;
}
示例#9
0
static int mod_authopenid_check_user_access(request_rec *r) {
  modauthopenid_config *s_cfg;
  s_cfg = (modauthopenid_config *) ap_get_module_config(r->per_dir_config, &authopenid_module);
  char *user = r->user;
  int m = r->method_number;
  int required_user = 0;
  register int x;
  const char *t, *w;
  const apr_array_header_t *reqs_arr = ap_requires(r);
  require_line *reqs;

  if (!reqs_arr) 
    return DECLINED;
  
  reqs = (require_line *)reqs_arr->elts;
  for (x = 0; x < reqs_arr->nelts; x++) {
    if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) 
      continue;

    t = reqs[x].requirement;
    w = ap_getword_white(r->pool, &t);
    if (!strcasecmp(w, "valid-user"))
      return OK;

    if (!strcasecmp(w, "user")) {
      required_user = 1;
      while (t[0]) {
	w = ap_getword_conf(r->pool, &t);
	if (!strcmp(user, w))
	  return OK;
      }
    }
  }

  if (!required_user)
    return DECLINED;

  APERR(r, "Access to %s failed: user '%s' invalid", r->uri, user);
  ap_note_auth_failure(r);
  return HTTP_UNAUTHORIZED;
}
示例#10
0
static const char *dbd_parse_config_query_parameters(cmd_parms *cmd, 
						     const char *require_line,
						     const void **parsed_require_line)
{
    const char *expr_err = NULL;
    ap_expr_info_t *expr;
    apr_array_header_t *expr_array = NULL;
    
    const char *t;
    char *w;
    
    /* parse each element of the require line and store it in an
       individual table entry. We will evaluate them in that order
       when passing the parameters to the db query */
    t = require_line;
    while ((w = ap_getword_white(cmd->pool, &t)) && w[0]) {
        
        expr = ap_expr_parse_cmd(cmd, w, AP_EXPR_FLAG_STRING_RESULT,
                                 &expr_err, NULL);
        
        if (expr_err)
            return apr_pstrcat(cmd->temp_pool,
                               "Cannot parse expression in require line: ",
                               expr_err, NULL);
        
        if (expr_array == NULL) {
            expr_array = apr_array_make(cmd->pool, 1, 
                                        sizeof(const ap_expr_info_t *));
        }
        *(const ap_expr_info_t **)apr_array_push(expr_array) = expr;
    }
    
    *parsed_require_line = expr_array;
    
    return NULL;
}
示例#11
0
apr_status_t proc_spawn_process(const char *cmdline, fcgid_proc_info *procinfo,
                                fcgid_procnode *procnode)
{
    HANDLE *finish_event, listen_handle;
    SECURITY_ATTRIBUTES SecurityAttributes;
    fcgid_server_conf *sconf;
    apr_procattr_t *proc_attr;
    apr_status_t rv;
    apr_file_t *file;
    const char * const *proc_environ;
    char sock_path[FCGID_PATH_MAX];
    int argc;
    char const * wargv[APACHE_ARG_MAX + 1], *word; /* For wrapper */
    const char *tmp;

    /* Build wrapper args */
    argc = 0;
    tmp = cmdline;
    while (1) {
        word = ap_getword_white(procnode->proc_pool, &tmp);
        if (word == NULL || *word == '\0')
            break;
        if (argc >= APACHE_ARG_MAX)
            break;
        wargv[argc++] = word;
    }
    wargv[argc] = NULL;

    memset(&SecurityAttributes, 0, sizeof(SecurityAttributes));

    /* Prepare finish event */
    finish_event = apr_palloc(procnode->proc_pool, sizeof(HANDLE));
    *finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (*finish_event == NULL
        || !SetHandleInformation(*finish_event, HANDLE_FLAG_INHERIT, TRUE))
    {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't create mutex for subprocess");
        return APR_ENOLOCK;
    }
    apr_pool_cleanup_register(procnode->proc_pool, finish_event,
                              close_finish_event, apr_pool_cleanup_null);

    /* For proc_kill_gracefully() */
    apr_pool_userdata_set(finish_event, FINISH_EVENT_DATA_NAME,
                          NULL, procnode->proc_pool);

    /* Pass the finish event id to subprocess */
    apr_table_setn(procinfo->proc_environ, SHUTDOWN_EVENT_NAME,
                   apr_ltoa(procnode->proc_pool, (long) *finish_event));

    /* Prepare the listen namedpipe file name (no check for truncation) */
    apr_snprintf(sock_path, sizeof sock_path,
                 "\\\\.\\pipe\\fcgidpipe-%lu.%d",
                 GetCurrentProcessId(), g_process_counter++);

    /* Prepare the listen namedpipe handle */
    SecurityAttributes.bInheritHandle = TRUE;
    SecurityAttributes.nLength = sizeof(SecurityAttributes);
    SecurityAttributes.lpSecurityDescriptor = NULL;
    listen_handle = CreateNamedPipe(sock_path,
                                    PIPE_ACCESS_DUPLEX,
                                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
                                    PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
                                    8192, 8192, 0, &SecurityAttributes);
    if (listen_handle == INVALID_HANDLE_VALUE) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't create namedpipe for subprocess");
        return APR_ENOSOCKET;
    }
    apr_cpystrn(procnode->socket_path, sock_path, sizeof(procnode->socket_path));
    apr_cpystrn(procnode->executable_path, wargv[0],
                sizeof(procnode->executable_path));

    /* Build environment variables */
    proc_environ = (const char * const *)
                   ap_create_environment(procnode->proc_pool,
                                         procinfo->proc_environ);
    if (!proc_environ) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't build environment variables");
        return APR_ENOMEM;
    }

    /* Create process now */
    if ((rv = apr_procattr_create(&proc_attr, procnode->proc_pool))
               != APR_SUCCESS
        || (rv = apr_procattr_dir_set(proc_attr,
                     ap_make_dirstr_parent(procnode->proc_pool,
                                           wargv[0]))) != APR_SUCCESS
        || (rv = apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM))
               != APR_SUCCESS
        || (rv = apr_procattr_detach_set(proc_attr, 1)) != APR_SUCCESS
        || (rv = apr_procattr_io_set(proc_attr, APR_NO_PIPE,
                                     APR_NO_FILE, APR_NO_FILE)) != APR_SUCCESS
        || (rv = apr_os_file_put(&file, &listen_handle, 0,
                                 procnode->proc_pool)) != APR_SUCCESS
        || (rv = apr_procattr_child_in_set(proc_attr, file, NULL))
               != APR_SUCCESS)
    {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, procinfo->main_server,
                     "mod_fcgid: can't create FastCGI process attribute");
        CloseHandle(listen_handle);
        return APR_ENOPROC;
    }

    /* fork and exec now */
    rv = apr_proc_create(&(procnode->proc_id), wargv[0], wargv,
                         proc_environ,
                         proc_attr, procnode->proc_pool);

    /* OK, I created the process, now put it back to idle list */
    CloseHandle(listen_handle);

    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, procinfo->main_server,
                     "mod_fcgid: can't run %s", wargv[0]);
        return rv;
    }

    /* FcgidWin32PreventOrphans feature */
    sconf = ap_get_module_config(procinfo->main_server->module_config,
                                 &fcgid_module);

    if (sconf->hJobObjectForAutoCleanup != NULL) {
        /* Associate cgi process to current process */
        if (AssignProcessToJobObject(sconf->hJobObjectForAutoCleanup,
                                     procnode->proc_id.hproc) == 0) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                         procinfo->main_server,
                         "mod_fcgid: unable to assign child process to "
                         "job object");
        }
    }

    return APR_SUCCESS;
}
示例#12
0
static int mag_auth(request_rec *req)
{
    const char *type;
    struct mag_config *cfg;
    const char *auth_header;
    char *auth_header_type;
    char *auth_header_value;
    int ret = HTTP_UNAUTHORIZED;
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    gss_ctx_id_t *pctx;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
    gss_name_t client = GSS_C_NO_NAME;
    gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
    gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
    uint32_t flags;
    uint32_t vtime;
    uint32_t maj, min;
    char *reply;
    size_t replen;
    char *clientname;
    gss_OID mech_type = GSS_C_NO_OID;
    gss_buffer_desc lname = GSS_C_EMPTY_BUFFER;
    struct mag_conn *mc = NULL;

    type = ap_auth_type(req);
    if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) {
        return DECLINED;
    }

    /* ignore auth for subrequests */
    if (!ap_is_initial_req(req)) {
        return OK;
    }

    cfg = ap_get_module_config(req->per_dir_config, &auth_gssapi_module);

    if (cfg->ssl_only) {
        if (!mag_conn_is_https(req->connection)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
                          "Not a TLS connection, refusing to authenticate!");
            goto done;
        }
    }

    if (cfg->gss_conn_ctx) {
        mc = (struct mag_conn *)ap_get_module_config(
                                                req->connection->conn_config,
                                                &auth_gssapi_module);
        if (!mc) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req,
                          "Failed to retrieve connection context!");
            goto done;
        }
    }

    /* if available, session always supersedes connection bound data */
    mag_check_session(req, cfg, &mc);

    if (mc) {
        /* register the context in the memory pool, so it can be freed
         * when the connection/request is terminated */
        apr_pool_userdata_set(mc, "mag_conn_ptr",
                              mag_conn_destroy, mc->parent);

        if (mc->established) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req,
                          "Already established context found!");
            apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name);
            req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate");
            req->user = apr_pstrdup(req->pool, mc->user_name);
            ret = OK;
            goto done;
        }
        pctx = &mc->ctx;
    } else {
        pctx = &ctx;
    }

    auth_header = apr_table_get(req->headers_in, "Authorization");
    if (!auth_header) goto done;

    auth_header_type = ap_getword_white(req->pool, &auth_header);
    if (!auth_header_type) goto done;

    if (strcasecmp(auth_header_type, "Negotiate") != 0) goto done;

    auth_header_value = ap_getword_white(req->pool, &auth_header);
    if (!auth_header_value) goto done;
    input.length = apr_base64_decode_len(auth_header_value) + 1;
    input.value = apr_pcalloc(req->pool, input.length);
    if (!input.value) goto done;
    input.length = apr_base64_decode(input.value, auth_header_value);

#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
    if (cfg->use_s4u2proxy) {
        maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, 0,
                                    GSS_C_NO_OID_SET, GSS_C_BOTH,
                                    cfg->cred_store, &acquired_cred,
                                    NULL, NULL);
        if (GSS_ERROR(maj)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                          mag_error(req, "gss_acquire_cred_from() failed",
                                    maj, min));
            goto done;
        }
    }
#endif

    maj = gss_accept_sec_context(&min, pctx, acquired_cred,
                                 &input, GSS_C_NO_CHANNEL_BINDINGS,
                                 &client, &mech_type, &output, &flags, &vtime,
                                 &delegated_cred);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                      mag_error(req, "gss_accept_sec_context() failed",
                                maj, min));
        goto done;
    }

    if (maj == GSS_S_CONTINUE_NEEDED) {
        if (!mc) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
                          "Mechanism needs continuation but neither "
                          "GssapiConnectionBound nor "
                          "GssapiUseSessions are available");
            gss_delete_sec_context(&min, pctx, GSS_C_NO_BUFFER);
            gss_release_buffer(&min, &output);
            output.length = 0;
        }
        /* auth not complete send token and wait next packet */
        goto done;
    }

    req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate");

    /* Always set the GSS name in an env var */
    maj = gss_display_name(&min, client, &name, NULL);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                      mag_error(req, "gss_accept_sec_context() failed",
                                maj, min));
        goto done;
    }
    clientname = apr_pstrndup(req->pool, name.value, name.length);
    apr_table_set(req->subprocess_env, "GSS_NAME", clientname);

#ifdef HAVE_GSS_STORE_CRED_INTO
    if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) {
        char *ccachefile = NULL;

        mag_store_deleg_creds(req, cfg->deleg_ccache_dir, clientname,
                              delegated_cred, &ccachefile);

        if (ccachefile) {
            apr_table_set(req->subprocess_env, "KRB5CCNAME", ccachefile);
        }
    }
#endif

    if (cfg->map_to_local) {
        maj = gss_localname(&min, client, mech_type, &lname);
        if (maj != GSS_S_COMPLETE) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, "%s",
                          mag_error(req, "gss_localname() failed", maj, min));
            goto done;
        }
        req->user = apr_pstrndup(req->pool, lname.value, lname.length);
    } else {
        req->user = clientname;
    }

    if (mc) {
        mc->user_name = apr_pstrdup(mc->parent, req->user);
        mc->gss_name = apr_pstrdup(mc->parent, clientname);
        mc->established = true;
        if (vtime == GSS_C_INDEFINITE || vtime < MIN_SESS_EXP_TIME) {
            vtime = MIN_SESS_EXP_TIME;
        }
        mc->expiration = time(NULL) + vtime;
        mag_attempt_session(req, cfg, mc);
    }

    ret = OK;

done:
    if (ret == HTTP_UNAUTHORIZED) {
        if (output.length != 0) {
            replen = apr_base64_encode_len(output.length) + 1;
            reply = apr_pcalloc(req->pool, 10 + replen);
            if (reply) {
                memcpy(reply, "Negotiate ", 10);
                apr_base64_encode(&reply[10], output.value, output.length);
                apr_table_add(req->err_headers_out,
                              "WWW-Authenticate", reply);
            }
        } else {
            apr_table_add(req->err_headers_out,
                          "WWW-Authenticate", "Negotiate");
        }
    }
    gss_release_cred(&min, &delegated_cred);
    gss_release_buffer(&min, &output);
    gss_release_name(&min, &client);
    gss_release_buffer(&min, &name);
    gss_release_buffer(&min, &lname);
    return ret;
}
示例#13
0
/*
 * Apache <2.4 authorization routine: match the claims from the authenticated user against the Require primitive
 */
int oidc_authz_worker(request_rec *r, const json_t * const claims,
		const require_line * const reqs, int nelts) {
	const int m = r->method_number;
	const char *token;
	const char *requirement;
	int i;
	int have_oauthattr = 0;
	int count_oauth_claims = 0;

	/* go through applicable Require directives */
	for (i = 0; i < nelts; ++i) {

		/* ignore this Require if it's in a <Limit> section that exclude this method */
		if (!(reqs[i].method_mask & (AP_METHOD_BIT << m))) {
			continue;
		}

		/* ignore if it's not a "Require claim ..." */
		requirement = reqs[i].requirement;

		token = ap_getword_white(r->pool, &requirement);

		if (apr_strnatcasecmp(token, OIDC_REQUIRE_NAME) != 0) {
			continue;
		}

		/* ok, we have a "Require claim" to satisfy */
		have_oauthattr = 1;

		/*
		 * If we have an applicable claim, but no claims were sent in the request, then we can
		 * just stop looking here, because it's not satisfiable. The code after this loop will
		 * give the appropriate response.
		 */
		if (!claims) {
			break;
		}

		/*
		 * iterate over the claim specification strings in this require directive searching
		 * for a specification that matches one of the claims.
		 */
		while (*requirement) {
			token = ap_getword_conf(r->pool, &requirement);
			count_oauth_claims++;

			oidc_debug(r, "evaluating claim specification: %s", token);

			if (oidc_authz_match_claim(r, token, claims) == TRUE) {

				/* if *any* claim matches, then authorization has succeeded and all of the others are ignored */
				oidc_debug(r, "require claim '%s' matched", token);
				return OK;
			}
		}
	}

	/* if there weren't any "Require claim" directives, we're irrelevant */
	if (!have_oauthattr) {
		oidc_debug(r, "no claim statements found, not performing authz");
		return DECLINED;
	}
	/* if there was a "Require claim", but no actual claims, that's cause to warn the admin of an iffy configuration */
	if (count_oauth_claims == 0) {
		oidc_warn(r,
				"'require claim' missing specification(s) in configuration, declining");
		return DECLINED;
	}

	/* log the event, also in Apache speak */
	oidc_debug(r, "authorization denied for client session");
	ap_note_auth_failure(r);

	return HTTP_UNAUTHORIZED;
}
示例#14
0
static int mag_auth(request_rec *req)
{
    const char *type;
    int auth_type = -1;
    struct mag_req_cfg *req_cfg;
    struct mag_config *cfg;
    const char *auth_header;
    char *auth_header_type;
    int ret = HTTP_UNAUTHORIZED;
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    gss_ctx_id_t *pctx;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc ba_user;
    gss_buffer_desc ba_pwd;
    gss_name_t client = GSS_C_NO_NAME;
    gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
    gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
    gss_cred_usage_t cred_usage = GSS_C_ACCEPT;
    uint32_t vtime;
    uint32_t maj, min;
    char *reply;
    size_t replen;
    gss_OID mech_type = GSS_C_NO_OID;
    gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
    gss_buffer_desc lname = GSS_C_EMPTY_BUFFER;
    struct mag_conn *mc = NULL;
    int i;
    bool send_auth_header = true;

    type = ap_auth_type(req);
    if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) {
        return DECLINED;
    }

    req_cfg = mag_init_cfg(req);

    cfg = req_cfg->cfg;

    desired_mechs = req_cfg->desired_mechs;

    /* implicit auth for subrequests if main auth already happened */
    if (!ap_is_initial_req(req) && req->main != NULL) {
        type = ap_auth_type(req->main);
        if ((type != NULL) && (strcasecmp(type, "GSSAPI") == 0)) {
            /* warn if the subrequest location and the main request
             * location have different configs */
            if (cfg != ap_get_module_config(req->main->per_dir_config,
                                            &auth_gssapi_module)) {
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
                              req, "Subrequest authentication bypass on "
                                   "location with different configuration!");
            }
            if (req->main->user) {
                req->user = apr_pstrdup(req->pool, req->main->user);
                return OK;
            } else {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                              "The main request is tasked to establish the "
                              "security context, can't proceed!");
                return HTTP_UNAUTHORIZED;
            }
        } else {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
                          "Subrequest GSSAPI auth with no auth on the main "
                          "request. This operation may fail if other "
                          "subrequests already established a context or the "
                          "mechanism requires multiple roundtrips.");
        }
    }

    if (cfg->ssl_only) {
        if (!mag_conn_is_https(req->connection)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "Not a TLS connection, refusing to authenticate!");
            goto done;
        }
    }

    if (cfg->gss_conn_ctx) {
        mc = (struct mag_conn *)ap_get_module_config(
                                                req->connection->conn_config,
                                                &auth_gssapi_module);
        if (!mc) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
                          "Failed to retrieve connection context!");
            goto done;
        }
    }

    /* if available, session always supersedes connection bound data */
    if (req_cfg->use_sessions) {
        mag_check_session(req_cfg, &mc);
    }

    auth_header = apr_table_get(req->headers_in, req_cfg->req_proto);

    if (mc) {
        if (mc->established &&
            (auth_header == NULL) &&
            (mc->auth_type != AUTH_TYPE_BASIC)) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
                          "Already established context found!");
            mag_set_req_data(req, cfg, mc);
            ret = OK;
            goto done;
        }
        pctx = &mc->ctx;
    } else {
        /* no preserved mc, create one just for this request */
        mc = mag_new_conn_ctx(req->pool);
        pctx = &ctx;
    }

    /* We can proceed only if we do have an auth header */
    if (!auth_header) goto done;

    auth_header_type = ap_getword_white(req->pool, &auth_header);
    if (!auth_header_type) goto done;

    /* We got auth header, sending auth header would mean re-auth */
    send_auth_header = !cfg->negotiate_once;

    for (i = 0; auth_types[i] != NULL; i++) {
        if (strcasecmp(auth_header_type, auth_types[i]) == 0) {
            auth_type = i;
            break;
        }
    }

    switch (auth_type) {
    case AUTH_TYPE_NEGOTIATE:
        if (!parse_auth_header(req->pool, &auth_header, &input)) {
            goto done;
        }
        break;
    case AUTH_TYPE_BASIC:
        if (!cfg->use_basic_auth) {
            goto done;
        }

        ba_pwd.value = ap_pbase64decode(req->pool, auth_header);
        if (!ba_pwd.value) goto done;
        ba_user.value = ap_getword_nulls_nc(req->pool,
                                            (char **)&ba_pwd.value, ':');
        if (!ba_user.value) goto done;

        if (((char *)ba_user.value)[0] == '\0' ||
            ((char *)ba_pwd.value)[0] == '\0') {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "Invalid empty user or password for Basic Auth");
            goto done;
        }
        ba_user.length = strlen(ba_user.value);
        ba_pwd.length = strlen(ba_pwd.value);

        if (mc->is_preserved && mc->established &&
            mag_basic_check(req_cfg, mc, ba_user, ba_pwd)) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
                          "Already established BASIC AUTH context found!");
            mag_set_req_data(req, cfg, mc);
            ret = OK;
            goto done;
        }

        break;

    case AUTH_TYPE_RAW_NTLM:
        if (!is_mech_allowed(desired_mechs, gss_mech_ntlmssp,
                             cfg->gss_conn_ctx)) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
                          "NTLM Authentication is not allowed!");
            goto done;
        }

        if (!parse_auth_header(req->pool, &auth_header, &input)) {
            goto done;
        }

        desired_mechs = discard_const(gss_mech_set_ntlmssp);
        break;

    default:
        goto done;
    }

    if (mc->established) {
        /* if we are re-authenticating make sure the conn context
         * is cleaned up so we do not accidentally reuse an existing
         * established context */
        mag_conn_clear(mc);
    }

    mc->auth_type = auth_type;

#ifdef HAVE_CRED_STORE
    if (use_s4u2proxy(req_cfg)) {
        cred_usage = GSS_C_BOTH;
    }
#endif

    if (auth_type == AUTH_TYPE_BASIC) {
        if (mag_auth_basic(req, cfg, ba_user, ba_pwd,
                           &client, &mech_type,
                           &delegated_cred, &vtime)) {
            goto complete;
        }
        goto done;
    }

    if (!mag_acquire_creds(req, cfg, desired_mechs,
                           cred_usage, &acquired_cred, NULL)) {
        goto done;
    }

    if (auth_type == AUTH_TYPE_NEGOTIATE &&
        cfg->allowed_mechs != GSS_C_NO_OID_SET) {
        maj = gss_set_neg_mechs(&min, acquired_cred, cfg->allowed_mechs);
        if (GSS_ERROR(maj)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
                          mag_error(req, "gss_set_neg_mechs() failed",
                                    maj, min));
            goto done;
        }
    }

    maj = gss_accept_sec_context(&min, pctx, acquired_cred,
                                 &input, GSS_C_NO_CHANNEL_BINDINGS,
                                 &client, &mech_type, &output, NULL, &vtime,
                                 &delegated_cred);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
                      mag_error(req, "gss_accept_sec_context() failed",
                                maj, min));
        goto done;
    } else if (maj == GSS_S_CONTINUE_NEEDED) {
        if (!mc->is_preserved) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
                          "Mechanism needs continuation but neither "
                          "GssapiConnectionBound nor "
                          "GssapiUseSessions are available");
            gss_release_buffer(&min, &output);
            output.length = 0;
        }
        /* auth not complete send token and wait next packet */
        goto done;
    }

complete:
    maj = gss_display_name(&min, client, &name, NULL);
    if (GSS_ERROR(maj)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
                      mag_error(req, "gss_display_name() failed",
                                maj, min));
        goto done;
    }

    mc->gss_name = apr_pstrndup(req->pool, name.value, name.length);
    if (vtime == GSS_C_INDEFINITE || vtime < MIN_SESS_EXP_TIME) {
        vtime = MIN_SESS_EXP_TIME;
    }
    mc->expiration = time(NULL) + vtime;

    mag_get_name_attributes(req, cfg, client, mc);

#ifdef HAVE_CRED_STORE
    if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) {
        char *ccache_path;

        mc->ccname = 0;
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
                      "requester: %s", mc->gss_name);

        ccache_path = get_ccache_name(req, cfg->deleg_ccache_dir, mc->gss_name,
                                      cfg->deleg_ccache_unique, mc);
        if (ccache_path == NULL) {
            goto done;
        }

        mag_store_deleg_creds(req, ccache_path, delegated_cred);
        mc->delegated = true;

        if (!req_cfg->use_sessions && cfg->deleg_ccache_unique) {
            /* queue removing ccache to avoid littering filesystem */
            apr_pool_cleanup_register(mc->pool, ccache_path,
                                      (int (*)(void *)) unlink,
                                      apr_pool_cleanup_null);
        }

        /* extract filename from full path */
        mc->ccname = strrchr(ccache_path, '/') + 1;
    }
#endif

    if (cfg->map_to_local) {
        maj = gss_localname(&min, client, mech_type, &lname);
        if (maj != GSS_S_COMPLETE) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
                          mag_error(req, "gss_localname() failed", maj, min));
            goto done;
        }
        mc->user_name = apr_pstrndup(req->pool, lname.value, lname.length);
    } else {
        mc->user_name = apr_pstrdup(mc->pool, mc->gss_name);
    }

    mc->established = true;
    if (auth_type == AUTH_TYPE_BASIC) {
        mag_basic_cache(req_cfg, mc, ba_user, ba_pwd);
    }
    if (req_cfg->use_sessions) {
        mag_attempt_session(req_cfg, mc);
    }

    /* Now set request data and env vars */
    mag_set_req_data(req, cfg, mc);

    if (req_cfg->send_persist)
        apr_table_set(req->headers_out, "Persistent-Auth",
            cfg->gss_conn_ctx ? "true" : "false");

    ret = OK;

done:

    if ((auth_type != AUTH_TYPE_BASIC) && (output.length != 0)) {
        int prefixlen = strlen(mag_str_auth_type(auth_type)) + 1;
        replen = apr_base64_encode_len(output.length) + 1;
        reply = apr_pcalloc(req->pool, prefixlen + replen);
        if (reply) {
            memcpy(reply, mag_str_auth_type(auth_type), prefixlen - 1);
            reply[prefixlen - 1] = ' ';
            apr_base64_encode(&reply[prefixlen], output.value, output.length);
            apr_table_add(req->err_headers_out, req_cfg->rep_proto, reply);
        }
    } else if (ret == HTTP_UNAUTHORIZED) {
        if (send_auth_header) {
            apr_table_add(req->err_headers_out,
                          req_cfg->rep_proto, "Negotiate");
            if (is_mech_allowed(desired_mechs, gss_mech_ntlmssp,
                                cfg->gss_conn_ctx)) {
                apr_table_add(req->err_headers_out, req_cfg->rep_proto,
                              "NTLM");
            }
        }
        if (cfg->use_basic_auth) {
            apr_table_add(req->err_headers_out, req_cfg->rep_proto,
                          apr_psprintf(req->pool, "Basic realm=\"%s\"",
                                       ap_auth_name(req)));
        }
    }

    if (ctx != GSS_C_NO_CONTEXT)
        gss_delete_sec_context(&min, &ctx, GSS_C_NO_BUFFER);
    gss_release_cred(&min, &acquired_cred);
    gss_release_cred(&min, &delegated_cred);
    gss_release_buffer(&min, &output);
    gss_release_name(&min, &client);
    gss_release_buffer(&min, &name);
    gss_release_buffer(&min, &lname);
    return ret;
}
示例#15
0
static int check_file_owner(request_rec *r)
{
    authz_owner_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                        &authz_owner_module);
    int m = r->method_number;
    register int x;
    const char *t, *w;
    const apr_array_header_t *reqs_arr = ap_requires(r);
    require_line *reqs;
    int required_owner = 0;
    apr_status_t status = 0;
    char *reason = NULL;

    if (!reqs_arr) {
        return DECLINED;
    }

    reqs = (require_line *)reqs_arr->elts;
    for (x = 0; x < reqs_arr->nelts; x++) {

        /* if authoritative = On then break if a require already failed. */
        if (reason && conf->authoritative) {
            break;
        }

        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
            continue;
        }

        t = reqs[x].requirement;
        w = ap_getword_white(r->pool, &t);

        if (!strcmp(w, "file-owner")) {
#if !APR_HAS_USER
            if ((required_owner & ~1) && conf->authoritative) {
                break;
            }

            required_owner |= 1; /* remember the requirement */
            reason = "'Require file-owner' is not supported on this platform.";
            continue;
#else  /* APR_HAS_USER */
            char *owner = NULL;
            apr_finfo_t finfo;

            if ((required_owner & ~1) && conf->authoritative) {
                break;
            }

            required_owner |= 1; /* remember the requirement */

            if (!r->filename) {
                reason = "no filename available";
                continue;
            }

            status = apr_stat(&finfo, r->filename, APR_FINFO_USER, r->pool);
            if (status != APR_SUCCESS) {
                reason = apr_pstrcat(r->pool, "could not stat file ",
                                     r->filename, NULL);
                continue;
            }

            if (!(finfo.valid & APR_FINFO_USER)) {
                reason = "no file owner information available";
                continue;
            }

            status = apr_uid_name_get(&owner, finfo.user, r->pool);
            if (status != APR_SUCCESS || !owner) {
                reason = "could not get name of file owner";
                continue;
            }

            if (strcmp(owner, r->user)) {
                reason = apr_psprintf(r->pool, "file owner %s does not match.",
                                      owner);
                continue;
            }

            /* this user is authorized */
            return OK;
#endif /* APR_HAS_USER */
        }

        /* file-group only figures out the file's group and lets
         * other modules do the actual authorization (against a group file/db).
         * Thus, these modules have to hook themselves after
         * mod_authz_owner and of course recognize 'file-group', too.
         */
        if (!strcmp(w, "file-group")) {
#if !APR_HAS_USER
            if ((required_owner & ~6) && conf->authoritative) {
                break;
            }

            required_owner |= 2; /* remember the requirement */
            reason = "'Require file-group' is not supported on this platform.";
            continue;
#else  /* APR_HAS_USER */
            char *group = NULL;
            apr_finfo_t finfo;

            if ((required_owner & ~6) && conf->authoritative) {
                break;
            }

            required_owner |= 2; /* remember the requirement */

            if (!r->filename) {
                reason = "no filename available";
                continue;
            }

            status = apr_stat(&finfo, r->filename, APR_FINFO_GROUP, r->pool);
            if (status != APR_SUCCESS) {
                reason = apr_pstrcat(r->pool, "could not stat file ",
                                     r->filename, NULL);
                continue;
            }

            if (!(finfo.valid & APR_FINFO_GROUP)) {
                reason = "no file group information available";
                continue;
            }

            status = apr_gid_name_get(&group, finfo.group, r->pool);
            if (status != APR_SUCCESS || !group) {
                reason = "could not get name of file group";
                continue;
            }

            /* store group name in a note and let others decide... */
            apr_table_setn(r->notes, AUTHZ_GROUP_NOTE, group);
            required_owner |= 4;
            continue;
#endif /* APR_HAS_USER */
        }
    }

    if (!required_owner || !conf->authoritative) {
        return DECLINED;
    }

    /* allow file-group passed to group db modules either if this is the
     * only applicable requirement here or if a file-owner failed but we're
     * not authoritative.
     * This allows configurations like:
     *
     * AuthzOwnerAuthoritative Off
     * require file-owner
     * require file-group
     *
     * with the semantical meaning of "either owner or group must match"
     * (inclusive or)
     *
     * [ 6 == 2 | 4; 7 == 1 | 2 | 4 ] should I use #defines instead?
     */
    if (required_owner == 6 || (required_owner == 7 && !conf->authoritative)) {
        return DECLINED;
    }

    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                  "Authorization of user %s to access %s failed, reason: %s",
                  r->user, r->uri, reason ? reason : "unknown");

    ap_note_auth_failure(r);
    return HTTP_UNAUTHORIZED;
}
示例#16
0
/**
 * Gets called whenever there is a "ReplaceFilterDefine" line in the config
 * file. The method creates a new configuration (replace_filter_t) for the
 * server (available through cmd->server). Returns an error message if things
 * didn't work out.
 *
 * @param cmd   The command record that holds the general data for the
 *              environment.
 * @param dummy To be ignored.
 * @param args  The arguments from the filter definition (everything following
 *              ReplaceFilterDefine.
 * @see cmd_parms 
 */
static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args)
{
    replace_server_t *conf = ap_get_module_config(cmd->server->module_config,
                                             &replace_module);
    const char *token;
    const char *name;
    replace_filter_t *filter;

    /* Extract the name of the filter. */
    name = ap_getword_white(cmd->pool, &args);
    if (!name) {
        return "Filter name not found";
    }

    /* Check if there is another filter by the same name. */
    if (apr_hash_get(conf->h, name, APR_HASH_KEY_STRING)) {
        return apr_psprintf(cmd->pool, "Replace Filter %s is already defined",
                            name);
    }
    
    /* Create a new filter configuration and populate the filter configuration 
     * with default values.
     */
    filter = (replace_filter_t *)apr_pcalloc(conf->p, sizeof(replace_filter_t));
    filter->name = name;
    filter->mode = OUTPUT_FILTER;
    filter->ftype = AP_FTYPE_RESOURCE;
    filter->pattern = NULL;
    filter->case_ignore = 0;
    apr_hash_set(conf->h, name, APR_HASH_KEY_STRING, filter);

    /* Parse the remaining arguments. */
    while (*args) {
        /* Ignore whitespaces. */
        while (apr_isspace(*args)) {
            ++args;
        }

        /* Set the filter mode. */
        if (!strncasecmp(args, "mode=", 5)) {
            args += 5;
            token = ap_getword_white(cmd->pool, &args);
            if (!strcasecmp(token, "output")) {
                filter->mode = OUTPUT_FILTER;
            }
            else if (!strcasecmp(token, "input")) {
                filter->mode = INPUT_FILTER;
            }
            else {
                return apr_psprintf(cmd->pool, "Invalid mode: `%s'",
                                    token);
            }
            continue;
        }

        /* Set the filter type. */
        if (!strncasecmp(args, "ftype=", 6)) {
            args += 6;
            token = ap_getword_white(cmd->pool, &args);
            filter->ftype = atoi(token);
            continue;
        }

        /* MIME type for incoming data. */
        if (!strncasecmp(args, "intype=", 7)) {
            args += 7;
            filter->intype = ap_getword_white(cmd->pool, &args);
            continue;
        }

        /* MIME type for outgoing data, if different from intype. */
        if (!strncasecmp(args, "outtype=", 8)) {
            args += 8;
            filter->outtype = ap_getword_white(cmd->pool, &args);
            continue;
        }

        /* check if the regular expression is to be handled case sensitive or
         * not.
         */
        if (!strncasecmp(args, "caseignore", 10)) {
            token = ap_getword_white(cmd->pool, &args);
            if (!strncasecmp(token, "caseignore", 10)) {
                filter->case_ignore = 1;
            } else {
                return apr_psprintf(cmd->pool, "mangled argument `%s'",
                                    token);
            }
            continue;
        }
        
        /* If there is any other argument than the already checked ones, return
         * with an error message.
         */
        return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'",
                            args);
    }

    /* parsing is done...  register the filter 
     */
    if (filter->mode == OUTPUT_FILTER) {
        /* XXX need a way to ensure uniqueness among all filters */
        if (!ap_register_output_filter(filter->name, replace_output_filter, 
                                       NULL, filter->ftype)) {
            return apr_psprintf(cmd->pool, 
                                "Unable to register output filter '%s'",
                                filter->name);
        }
    }
    else {
        ap_assert(1 != 1); /* we set the field wrong somehow */
    }

    return NULL;
}
/* Run an external authentication program using the given method for passing
 * in the data.  The login name is always passed in.   Dataname is "GROUP" or
 * "PASS" and data is the group list or password being checked.  To launch
 * a detached daemon, run this with extmethod=NULL.
 *
 * If the authenticator was run, we return the numeric code from the
 * authenticator, normally 0 if the login was valid, some small positive
 * number if not.  If we were not able to run the authenticator, we log
 * an error message and return a numeric error code:
 *
 *   -1   Could not execute authenticator, usually a path or permission problem
 *   -2   The external authenticator crashed or was killed.
 *   -3   Could not create process attribute structure
 *   -4   apr_proc_wait() did not return a status code.  Should never happen.
 *   -5   apr_proc_wait() returned before child finished.  Should never happen.
 */
static int exec_external(const char *extpath, const char *extmethod,
		const request_rec *r, const char *dataname, const char *data)
{
    conn_rec *c= r->connection;
    apr_pool_t *p= r->pool;
    int isdaemon, usecheck= 0, usepipeout= 0, usepipein= 0;
    apr_procattr_t *procattr;
    apr_proc_t proc;
    apr_status_t rc= APR_SUCCESS;
    char *child_env[12];
    char *child_arg[MAX_ARG+2];
    const char *t;
    int i, status= -4;
    apr_exit_why_e why= APR_PROC_EXIT;
    apr_sigfunc_t *sigchld;

    /* Set various flags based on the execution method */

    isdaemon= (extmethod == NULL);
    if (!isdaemon)
    {
	usecheck= extmethod && !strcasecmp(extmethod, "checkpassword");
	usepipeout= usecheck || (extmethod && !strcasecmp(extmethod, "pipes"));
	usepipein= usepipeout || (extmethod && !strcasecmp(extmethod, "pipe"));
    }

    /* Create the environment for the child.  Daemons don't get these, they
     * just inherit apache's environment variables.
     */

    if (!isdaemon)
    {
	const char *cookie, *host, *remote_host;
	authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
	    ap_get_module_config(r->per_dir_config, &authnz_external_module);
	i= 0;

	if (!usepipein)
	{
	    /* Put user name and password/group into environment */
	    child_env[i++]= apr_pstrcat(p, ENV_USER"=", r->user, NULL);
	    child_env[i++]= apr_pstrcat(p, dataname, "=", data, NULL);
	}

	child_env[i++]= apr_pstrcat(p, "PATH=", getenv("PATH"), NULL);

	child_env[i++]= apr_pstrcat(p, "AUTHTYPE=", dataname, NULL);

	remote_host= ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST,NULL);
	if (remote_host != NULL)
	    child_env[i++]= apr_pstrcat(p, ENV_HOST"=", remote_host,NULL);

	if (r->useragent_ip)
	    child_env[i++]= apr_pstrcat(p, ENV_IP"=", r->useragent_ip, NULL);

	if (r->uri)
	    child_env[i++]= apr_pstrcat(p, ENV_URI"=", r->uri, NULL);

	if ((host= apr_table_get(r->headers_in, "Host")) != NULL)
	    child_env[i++]= apr_pstrcat(p, ENV_HTTP_HOST"=", host, NULL);

	if (dir->context)
	    child_env[i++]= apr_pstrcat(r->pool, ENV_CONTEXT"=",
	    	dir->context, NULL);

#ifdef ENV_COOKIE
	if ((cookie= apr_table_get(r->headers_in, "Cookie")) != NULL)
	    child_env[i++]= apr_pstrcat(p, ENV_COOKIE"=", cookie, NULL);
#endif
	/* NOTE:  If you add environment variables,
	 *   remember to increase the size of the child_env[] array */

	/* End of environment */
	child_env[i]= NULL;
    }

    /* Construct argument array */
    for (t= extpath, i=0; *t != '\0' && (i <= MAX_ARG + 1);
	 child_arg[i++]= ap_getword_white(p, &t)) {}
    child_arg[i]= NULL;

    /* Create the process attribute structure describing the script we
     * want to run using the Thread/Process functions from the Apache
     * portable runtime library. */

    if (((rc= apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||

	/* should we create pipes to stdin, stdout and stderr? */
        ((rc= apr_procattr_io_set(procattr,
	    (usepipein && !usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE,
	    usepipeout ? APR_FULL_BLOCK : APR_NO_PIPE,
	    (usepipein && usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE))
	       != APR_SUCCESS ) ||

	/* will give full path of program and make a new environment */
	((rc= apr_procattr_cmdtype_set(procattr,
	    isdaemon ? APR_PROGRAM_ENV : APR_PROGRAM)) != APR_SUCCESS) ||

	/* detach the child only if it is a daemon */
	((rc= apr_procattr_detach_set(procattr, isdaemon)) != APR_SUCCESS) ||

	/* function to call if child has error after fork, before exec */
	((rc= apr_procattr_child_errfn_set(procattr, extchilderr)
	      != APR_SUCCESS)))
    {
	/* Failed.  Probably never happens. */
    	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
	    "could not set child process attributes");
	return -3;
    }

    /* Sometimes other modules wil mess up sigchild.  Need to fix it for
     * the wait call to work correctly.  */
    sigchld= apr_signal(SIGCHLD,SIG_DFL);

    /* Start the child process */
    rc= apr_proc_create(&proc, child_arg[0],
    	(const char * const *)child_arg,
	(const char * const *)child_env, procattr, p);
    if (rc != APR_SUCCESS)
    {
	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
		"Could not run external authenticator: %d: %s", rc,
		child_arg[0]);
	return -1;
    }

    if (isdaemon) return 0;

    apr_pool_note_subprocess(p, &proc, APR_KILL_AFTER_TIMEOUT);

    if (usepipein)
    {
	/* Select appropriate pipe to write to */
	apr_file_t *pipe= (usecheck ? proc.err : proc.in);

	/* Send the user */
	apr_file_write_full(pipe, r->user, strlen(r->user), NULL);
	apr_file_putc(usecheck ? '\0' : '\n', pipe);

	/* Send the password */
	apr_file_write_full(pipe, data, strlen(data), NULL);
	apr_file_putc(usecheck ? '\0' : '\n', pipe);

	/* Send the uri/path */
	apr_file_write_full(pipe, r->uri, strlen(r->uri), NULL);
	apr_file_putc(usecheck ? '\0' : '\n', pipe);

	/* Send dummy timestamp for checkpassword */
	if (usecheck) apr_file_write_full(pipe, "0", 2, NULL);

	/* Close the file */
	apr_file_close(pipe);
    }

    /* Wait for the child process to terminate, and get status */
    rc= apr_proc_wait(&proc,&status,&why,APR_WAIT);

    /* Restore sigchild to whatever it was before we reset it */
    apr_signal(SIGCHLD,sigchld);

    if (!APR_STATUS_IS_CHILD_DONE(rc))
    {
    	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
		"Could not get status from child process");
	return -5;
    }
    if (!APR_PROC_CHECK_EXIT(why))
    {
	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
		"External authenticator died on signal %d",status);
	return -2;
    }

    return status;
}
static int check_unix_group(request_rec *r, const char *grouplist)
{
    char *user= r->user;
    char *at;

    /* Strip @ sign and anything following it from the username.  Some
     * authentication modules, like mod_auth_kerb like appending such
     * stuff to user names, but an @ sign is never legal in a unix login
     * name, so it should be safe to always discard such stuff.
     */
    if ((at= strchr(user, '@')) != NULL) *at= '\0';

    /* Get info about login */
    struct passwd *pwd= getpwnam(user);
    if (pwd == NULL)
    {
        /* No such user - forget it */
        if (at != NULL) *at= '@';
        return 0;
    }

#ifdef HAVE_GETGROUPLIST
    int num_groups = 0;
    int grouplistresult = getgrouplist(user, pwd->pw_gid, NULL, &num_groups);
    if (grouplistresult != -1)
    {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
            "expected -1 from first getgrouplist, got %d", grouplistresult);
    }
    gid_t* user_groups = (gid_t*)apr_palloc(r->pool, num_groups*sizeof(gid_t));
    grouplistresult = getgrouplist(user, pwd->pw_gid, user_groups, &num_groups);
    /* Loop through list of groups passed in */
    while (*grouplist != '\0')
    {
        const char* const word = ap_getword_white(r->pool, &grouplist);
        gid_t match_group;
        if (apr_isdigit(word[0]))
        {
            // numeric group id 
            match_group = atoi(word);
        }
        else
        {
            struct group* const group = getgrnam(word);
            match_group = group == NULL ? -1 : group->gr_gid;
        }
        for (int i = 0; i < num_groups; i++)
        {
            gid_t const user_group = user_groups[i];
            if (user_group == match_group)
            {
                if (at != NULL) *at= '@';
                return 1;
            }
        }
    }
#else
    /* Loop through list of groups passed in */
    while (*grouplist != '\0')
    {
        struct group *grp;
        char* w= ap_getword_white(r->pool, &grouplist);
        if (apr_isdigit(w[0]))
        {
            /* Numeric group id */
            int gid= atoi(w);

            /* Check if it matches the user's primary group */
            if (gid == pwd->pw_gid)
            {
                if (at != NULL) *at= '@';
                return 1;
            }

            /* Get list of group members for numeric group id */
            grp= getgrgid(gid);
        }
        else
        {
            /* Get gid and list of group members for group name */
            grp= getgrnam(w);
            /* Check if gid of this group matches user's primary gid */
            if (grp != NULL && grp->gr_gid == pwd->pw_gid)
            {
                if (at != NULL) *at= '@';
                return 1;
            }
        }

        /* Walk through list of members, seeing if any match user login */
        if (grp != NULL)
        {
            char **p;
            for (p= grp->gr_mem; *p != NULL; p++)
            {
                if (!strcmp(user, *p))
                {
                    if (at != NULL) *at= '@';
                    return 1;
                }
            }
        }
    }
#endif

    /* Didn't find any matches, flunk him */
    if (at != NULL) *at= '@';
    return 0;
}
示例#19
0
static int dbm_check_auth(request_rec *r)
{
    dbm_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                     &auth_dbm_module);
    char *user = r->user;
    int m = r->method_number;

    const apr_array_header_t *reqs_arr = ap_requires(r);
    require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;

    register int x;
    const char *t;
    char *w;

    if (!conf->auth_dbmgrpfile)
        return DECLINED;
    if (!reqs_arr)
        return DECLINED;

    for (x = 0; x < reqs_arr->nelts; x++) {

        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m)))
            continue;

        t = reqs[x].requirement;
        w = ap_getword_white(r->pool, &t);

        if (!strcmp(w, "group") && conf->auth_dbmgrpfile) {
            const char *orig_groups, *groups;
            char *v;

            if (!(groups = get_dbm_grp(r, user, conf->auth_dbmgrpfile,
                                       conf->auth_dbmtype))) {
                if (!(conf->auth_dbmauthoritative))
                    return DECLINED;
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                            "user %s not in DBM group file %s: %s",
                            user, conf->auth_dbmgrpfile, r->filename);
                ap_note_basic_auth_failure(r);
                return HTTP_UNAUTHORIZED;
            }
            orig_groups = groups;
            while (t[0]) {
                w = ap_getword_white(r->pool, &t);
                groups = orig_groups;
                while (groups[0]) {
                    v = ap_getword(r->pool, &groups, ',');
                    if (!strcmp(v, w))
                        return OK;
                }
            }
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "user %s not in right group: %s",
                          user, r->filename);
            ap_note_basic_auth_failure(r);
            return HTTP_UNAUTHORIZED;
        }
    }

    return DECLINED;
}
示例#20
0
文件: mod_auth.c 项目: AzerTyQsdF/osx
static int check_user_access(request_rec *r)
{
    auth_config_rec *sec =
    (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module);
    char *user = r->connection->user;
    int m = r->method_number;
    int method_restricted = 0;
    register int x;
    const char *t, *w;
    table *grpstatus;
    const array_header *reqs_arr = ap_requires(r);
    require_line *reqs;

    /* BUG FIX: tadc, 11-Nov-1995.  If there is no "requires" directive, 
     * then any user will do.
     */
    if (reqs_arr == NULL) {
	return (OK);
    }
    reqs = (require_line *) reqs_arr->elts;

    if (sec->auth_grpfile) {
	grpstatus = groups_for_user(r->pool, user, sec->auth_grpfile);
    }
    else {
	grpstatus = NULL;
    }

    for (x = 0; x < reqs_arr->nelts; x++) {

        if (! (reqs[x].method_mask & (1 << m))) {
            continue;
        }

	method_restricted = 1;

	t = reqs[x].requirement;
	w = ap_getword_white(r->pool, &t);
	if (strcmp(w, "valid-user") == 0) {
	    return OK;
        }
        /*
         * If requested, allow access if the user is valid and the
         * owner of the document.
         */
	if (strcmp(w, "file-owner") == 0) {
#if defined(WIN32) || defined(NETWARE) || defined(OS2)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
                          "'Require file-owner' not supported "
                          "on this platform, ignored");
            continue;
#else
            struct passwd *pwent;
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                          "checking for 'owner' access for file '%s'",
                          r->filename);
            if (r->finfo.st_ino == 0) {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                              "no stat info for '%s'", r->filename);
                continue;
            }
            pwent = getpwuid(r->finfo.st_uid);
            if (pwent == NULL) {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                              "no username for UID %d (owner of '%s')",
                              r->finfo.st_uid, r->filename);
            }
            else {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                              "checking authenticated user '%s' "
                              "against owner '%s' of '%s'",
                              user, pwent->pw_name, r->filename);
                if (strcmp(user, pwent->pw_name) == 0) {
                    return OK;
                }
                else {
                    continue;
                }
            }
#endif
        }
	if (strcmp(w, "file-group") == 0) {
#if defined(WIN32) || defined(NETWARE) || defined(OS2)
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
                          "'Require file-group' not supported "
                          "on this platform, ignored");
            continue;
#else
            struct group *grent;
            if (sec->auth_grpfile == NULL) {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
                              "no AuthGroupFile, so 'file-group' "
                              "requirement cannot succeed for file '%s'",
                              r->filename);
                continue;
            }
            if (grpstatus == NULL) {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r,
                              "authenticated user '%s' not a member of "
                              "any groups, so 'file-group' requirement "
                              "cannot succeed for file '%s'",
                              user, r->filename);
                continue;
            }
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                          "checking for 'group' access for file '%s'",
                          r->filename);
            if (r->finfo.st_ino == 0) {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                              "no stat info for '%s'", r->filename);
                continue;
            }
            grent = getgrgid(r->finfo.st_gid);
            if (grent == NULL) {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                              "no group name for GID %d (owner of '%s')",
                              r->finfo.st_gid, r->filename);
            }
            else {
                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
                              "checking groups of authenticated user '%s' "
                              "against owner group '%s' of '%s'",
                              user, grent->gr_name, r->filename);
                if (ap_table_get(grpstatus, grent->gr_name) != NULL) {
                    return OK;
                }
                else {
                    continue;
                }
            }
#endif
        }
	if (strcmp(w, "user") == 0) {
	    while (t[0] != '\0') {
		w = ap_getword_conf(r->pool, &t);
		if (strcmp(user, w) == 0) {
		    return OK;
                }
	    }
	}
	else if (strcmp(w, "group") == 0) {
	    if (grpstatus == NULL) {
		return DECLINED;	/* DBM group?  Something else? */
            }

	    while (t[0]) {
		w = ap_getword_conf(r->pool, &t);
		if (ap_table_get(grpstatus, w)) {
		    return OK;
                }
	    }
	}
        else if (sec->auth_authoritative) {
	    /* if we aren't authoritative, any require directive could be
	     * valid even if we don't grok it.  However, if we are 
	     * authoritative, we can warn the user they did something wrong.
	     * That something could be a missing "AuthAuthoritative off", but
	     * more likely is a typo in the require directive.
	     */
	    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                          "access to %s failed, "
                          "reason: unknown require directive:"
                          "\"%s\"", r->uri, reqs[x].requirement);
	}
    }

    if (! method_restricted) {
	return OK;
    }

    if (! sec->auth_authoritative) {
	return DECLINED;
    }

    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                  "access to %s failed, reason: user %s not allowed access",
                  r->uri, user);
	
    ap_note_basic_auth_failure(r);
    return AUTH_REQUIRED;
}
示例#21
0
static int check_user_access(request_rec *r)
{
    auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                 &auth_module);
    char *user = r->user;
    int m = r->method_number;
    int method_restricted = 0;
    register int x;
    const char *t, *w;
    apr_table_t *grpstatus;
    const apr_array_header_t *reqs_arr = ap_requires(r);
    require_line *reqs;

    /* BUG FIX: tadc, 11-Nov-1995.  If there is no "requires" directive, 
     * then any user will do.
     */
    if (!reqs_arr) {
        return OK;
    }
    reqs = (require_line *)reqs_arr->elts;

    if (conf->auth_grpfile) {
        grpstatus = groups_for_user(r, user, conf->auth_grpfile);
    }
    else {
        grpstatus = NULL;
    }

    for (x = 0; x < reqs_arr->nelts; x++) {

        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
            continue;
        }

        method_restricted = 1;

        t = reqs[x].requirement;
        w = ap_getword_white(r->pool, &t);
        if (!strcmp(w, "valid-user")) {
            return OK;
        }
        if (!strcmp(w, "user")) {
            while (t[0]) {
                w = ap_getword_conf(r->pool, &t);
                if (!strcmp(user, w)) {
                    return OK;
                }
            }
        }
        else if (!strcmp(w, "group")) {
            if (!grpstatus) {
                return DECLINED;        /* DBM group?  Something else? */
            }

            while (t[0]) {
                w = ap_getword_conf(r->pool, &t);
                if (apr_table_get(grpstatus, w)) {
                    return OK;
                }
            }
        }
        else if (conf->auth_authoritative) {
            /* if we aren't authoritative, any require directive could be
             * valid even if we don't grok it.  However, if we are 
             * authoritative, we can warn the user they did something wrong.
             * That something could be a missing "AuthAuthoritative off", but
             * more likely is a typo in the require directive.
             */
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "access to %s failed, reason: unknown require "
                          "directive:\"%s\"", r->uri, reqs[x].requirement);
        }
    }

    if (!method_restricted) {
        return OK;
    }

    if (!(conf->auth_authoritative)) {
        return DECLINED;
    }

    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                  "access to %s failed, reason: user %s not allowed access",
                  r->uri, user);
        
    ap_note_basic_auth_failure(r);
    return HTTP_UNAUTHORIZED;
}
static int authz_unixgroup_check_user_access(request_rec *r) 
{
    authz_unixgroup_dir_config_rec *dir= (authz_unixgroup_dir_config_rec *)
	ap_get_module_config(r->per_dir_config, &authz_unixgroup_module);

    int m= r->method_number;
    int required_group= 0;
    register int x;
    const char *t, *w;
    const apr_array_header_t *reqs_arr= ap_requires(r);
    const char *filegroup= NULL;
    require_line *reqs;

    /* If not enabled, pass */
    if ( !dir->enabled ) return DECLINED;

    /* If there are no Require arguments, pass */
    if (!reqs_arr) return DECLINED;
    reqs=  (require_line *)reqs_arr->elts;

    /* Loop through the "Require" argument list */
    for(x= 0; x < reqs_arr->nelts; x++)
    {
	if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) continue;

	t= reqs[x].requirement;
	w= ap_getword_white(r->pool, &t);

	/* The 'file-group' directive causes mod_authz_owner to store the
	 * group name of the file we are trying to access in a note attached
	 * to the request.  It's our job to decide if the user actually is
	 * in that group.  If the note is missing, we just ignore it.
	 * Probably mod_authz_owner is not installed.
	 */
	if ( !strcasecmp(w, "file-group"))
	{
	    filegroup= apr_table_get(r->notes, AUTHZ_GROUP_NOTE);
	    if (filegroup == NULL) continue;
	}

	if ( !strcmp(w,"group") || filegroup != NULL)
	{
	    required_group= 1;

	    if (filegroup)
	    {
		/* Check if user is in the group that owns the file */
		if (check_unix_group(r,filegroup))
		    return OK;
	    }
	    else if (t[0])
	    {
		/* Pass rest of require line to authenticator */
		if (check_unix_group(r,t))
		    return OK;
	    }
	}
    }
    
    /* If we didn't see a 'require group' or aren't authoritive, decline */
    if (!required_group || !dir->authoritative)
	return DECLINED;

    /* Authentication failed and we are authoritive, declare unauthorized */
    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
    	"access to %s failed, reason: user %s not allowed access",
    	r->uri, r->user);

    ap_note_basic_auth_failure(r);
    return HTTP_UNAUTHORIZED;
}
static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args)
{
    ef_server_t *conf = ap_get_module_config(cmd->server->module_config,
                                             &ext_filter_module);
    const char *token;
    const char *name;
    char *normalized_name;
    ef_filter_t *filter;

    name = ap_getword_white(cmd->pool, &args);
    if (!name) {
        return "Filter name not found";
    }

    /* During request processing, we find information about the filter
     * by looking up the filter name provided by core server in our
     * hash table.  But the core server has normalized the filter
     * name by converting it to lower case.  Thus, when adding the
     * filter to our hash table we have to use lower case as well.
     */
    normalized_name = apr_pstrdup(cmd->pool, name);
    ap_str_tolower(normalized_name);

    if (apr_hash_get(conf->h, normalized_name, APR_HASH_KEY_STRING)) {
        return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",
                            name);
    }

    filter = (ef_filter_t *)apr_pcalloc(conf->p, sizeof(ef_filter_t));
    filter->name = name;
    filter->mode = OUTPUT_FILTER;
    filter->ftype = AP_FTYPE_RESOURCE;
    apr_hash_set(conf->h, normalized_name, APR_HASH_KEY_STRING, filter);

    while (*args) {
        while (apr_isspace(*args)) {
            ++args;
        }

        /* Nasty parsing...  I wish I could simply use ap_getword_white()
         * here and then look at the token, but ap_getword_white() doesn't
         * do the right thing when we have cmd="word word word"
         */
        if (!strncasecmp(args, "preservescontentlength", 22)) {
            token = ap_getword_white(cmd->pool, &args);
            if (!strcasecmp(token, "preservescontentlength")) {
                filter->preserves_content_length = 1;
            }
            else {
                return apr_psprintf(cmd->pool,
                                    "mangled argument `%s'",
                                    token);
            }
            continue;
        }

        if (!strncasecmp(args, "mode=", 5)) {
            args += 5;
            token = ap_getword_white(cmd->pool, &args);
            if (!strcasecmp(token, "output")) {
                filter->mode = OUTPUT_FILTER;
            }
            else if (!strcasecmp(token, "input")) {
                filter->mode = INPUT_FILTER;
            }
            else {
                return apr_psprintf(cmd->pool, "Invalid mode: `%s'",
                                    token);
            }
            continue;
        }

        if (!strncasecmp(args, "ftype=", 6)) {
            args += 6;
            token = ap_getword_white(cmd->pool, &args);
            filter->ftype = atoi(token);
            continue;
        }

        if (!strncasecmp(args, "enableenv=", 10)) {
            args += 10;
            token = ap_getword_white(cmd->pool, &args);
            filter->enable_env = token;
            continue;
        }

        if (!strncasecmp(args, "disableenv=", 11)) {
            args += 11;
            token = ap_getword_white(cmd->pool, &args);
            filter->disable_env = token;
            continue;
        }

        if (!strncasecmp(args, "intype=", 7)) {
            args += 7;
            filter->intype = ap_getword_white(cmd->pool, &args);
            continue;
        }

        if (!strncasecmp(args, "outtype=", 8)) {
            args += 8;
            filter->outtype = ap_getword_white(cmd->pool, &args);
            continue;
        }

        if (!strncasecmp(args, "cmd=", 4)) {
            args += 4;
            if ((token = parse_cmd(cmd->pool, &args, filter))) {
                return token;
            }
            continue;
        }

        return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'",
                            args);
    }

    /* parsing is done...  register the filter
     */
    if (filter->mode == OUTPUT_FILTER) {
        /* XXX need a way to ensure uniqueness among all filters */
        ap_register_output_filter(filter->name, ef_output_filter, NULL, filter->ftype);
    }
    else if (filter->mode == INPUT_FILTER) {
        /* XXX need a way to ensure uniqueness among all filters */
        ap_register_input_filter(filter->name, ef_input_filter, NULL, filter->ftype);
    }
    else {
        ap_assert(1 != 1); /* we set the field wrong somehow */
    }

    return NULL;
}
示例#24
0
static authz_status dbmgroup_check_authorization(request_rec *r,
                                                 const char *require_args,
                                                 const void *parsed_require_args)
{
    authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                      &authz_dbm_module);
    char *user = r->user;
    const char *t;
    char *w;
    const char *orig_groups = NULL;
    const char *realm = ap_auth_name(r);
    const char *groups;
    char *v;

    if (!user) {
        return AUTHZ_DENIED_NO_USER;
    }

    if (!conf->grpfile) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01798)
                        "No group file was specified in the configuration");
        return AUTHZ_DENIED;
    }

    /* fetch group data from dbm file only once. */
    if (!orig_groups) {
        apr_status_t status;

        status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm, NULL),
                             user, conf->grpfile, conf->dbmtype, &groups);

        if (status != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01799)
                          "could not open dbm (type %s) group access "
                          "file: %s", conf->dbmtype, conf->grpfile);
            return AUTHZ_GENERAL_ERROR;
        }

        if (groups == NULL) {
            /* no groups available, so exit immediately */
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01800)
                          "Authorization of user %s to access %s failed, reason: "
                          "user doesn't appear in DBM group file (%s).",
                          r->user, r->uri, conf->grpfile);
            return AUTHZ_DENIED;
        }

        orig_groups = groups;
    }

    t = require_args;
    while ((w = ap_getword_white(r->pool, &t)) && w[0]) {
        groups = orig_groups;
        while (groups[0]) {
            v = ap_getword(r->pool, &groups, ',');
            if (!strcmp(v, w)) {
                return AUTHZ_GRANTED;
            }
        }
    }

    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01801)
                  "Authorization of user %s to access %s failed, reason: "
                  "user is not part of the 'require'ed group(s).",
                  r->user, r->uri);

    return AUTHZ_DENIED;
}
示例#25
0
/**
 * This function gets called whenever there is a 'HeaderReplacePattern' in the 
 * config file.
 * Returns NULL if everything went alright, otherwise an error message.
 *
 * @param cmd           The command record filled with general information
 *                      about the environment.
 * @param dummy         To be ignored.
 * @param args          The arguments passed from the pattern definition. Must
 *                      be in the following order: name, header, pattern,
 *                      replacement string.
 */
static const char *add_header_pattern(cmd_parms *cmd, 
                                      void *dummy, 
                                      const char *args)
{
    const char *name;       // the filter name
    const char *header;     // the HTTP header field to match
    const char *pattern_str;// the textual representation of the pattern
    const char *replace;    // the replacement string
    
    replace_server_t *conf; // the server configuration (hashtable)
    replace_filter_t *filter; 
                            // the filter configuration
    header_replace_pattern_t *pattern; 
                            // the pattern to add
    header_replace_pattern_t *previous;
                            // the previous pattern, if any
    header_replace_pattern_t backup;                            
    pcre *re;               // the regular expression
    pcre_extra *pe;         // data from studying the pattern
    const char *error;      // error text for the failed regex compilation
    int error_offset;       // offset of the regex compilation error, if any
    int rc;                 // return count of the regex matching
    int i;                  // counter
    int rv;                 // return value for generic function calls
    int flags = 0;          // the flags for the regex matching

    /* Get the configuration record */
    conf = ap_get_module_config(cmd->server->module_config, &replace_module);
    if (conf == NULL) {
        return apr_pstrcat(cmd->temp_pool,
                           "Illegal server record", NULL, NULL);
    }

    /*
     * Parse the arguments.
     */

    /* Extract the name of the filter and check for its existence. */
    name = ap_getword_white(cmd->pool, &args);
    if (!apr_hash_get(conf->h, name, APR_HASH_KEY_STRING)) {
      return "ReplaceFilter not defined";
    }

    /* Extract the header field. */
    header = ap_getword_conf(cmd->pool, &args);
    if (!header || strlen(header) == 0) {
        return "Header field missing";
    }

    /* Extract the regex pattern */
    pattern_str = ap_getword_conf(cmd->pool, &args);
    if (!pattern_str || strlen(pattern_str) == 0) {
        return "Pattern definition missing";
    }

    if (!args || !strlen(args) > 0) {
        return "Replacement pattern missing";
    }

    /* Extract the replacement string */
    replace = ap_getword_conf(cmd->pool, &args);
    if (!replace) {
        return "Replacement pattern missing";
    }

    /* Check for additional, illegal configuration directives */
    if (args && strlen(args) > 0) {
        return apr_psprintf(cmd->temp_pool, "Illegal conf directive: \"%s\"", 
                            args);
    }
    
    /* Get the filter definition */
    filter = (replace_filter_t*)apr_hash_get(conf->h, name, 
                                            APR_HASH_KEY_STRING);
    if (filter == NULL) {
        return apr_pstrcat(cmd->temp_pool,
                           "Unknown filter definition for replace filter");
    }


    /* Check if we have to set the flag for case insensitive matching. */
    if (filter->case_ignore == 1) {
        flags |= PCRE_CASELESS;
    }

    /* Compile the pattern. */
    re = pcre_compile(pattern_str, flags, &error, &error_offset, NULL);

    /* Return ungraceful if the compilation of the regex failed. */
    if (re == NULL) {
        return apr_pstrcat(cmd->temp_pool, 
                           "Error compiling regular expression: ", error,
                           NULL);
    }
    
    /* Study the pattern. This is done for performance improvement, but most of
     * the time it doesn't speed up things, since the return value is simply
     * NULL. 
     */
    pe = pcre_study(re, 0, &error);
    if (error != NULL) {
        return apr_pstrcat(cmd->temp_pool,
                           "Error studying compiled pattern: ", error, NULL);
    }

    /* Check for an already existing pattern. */
    pattern = filter->header_pattern;
    previous = NULL;
    
    /* Find the last pattern in the list. */
    while (pattern && pattern->next != NULL) {
        previous = pattern;
        pattern = pattern->next;
    }

    /* If there has been no pattern at all, create one. Otherwise save the last
     * pattern and create a new one.
     */
    if (!pattern) {
        pattern = (header_replace_pattern_t *)apr_pcalloc(conf->p,
                                                   sizeof(header_replace_pattern_t));
        filter->header_pattern = pattern;
    } else {
        previous = pattern;
        pattern = (header_replace_pattern_t *)apr_pcalloc(conf->p,
                                                   sizeof(header_replace_pattern_t));
    }

    /* Assign the values to the structure and add the pattern to the list. */
    pattern->pattern = re;
    pattern->extra = pe;
    pattern->replacement = apr_pstrdup(conf->p, replace);
    pattern->header = apr_pstrdup(conf->p, header);
    pattern->next = NULL;

    if (previous) {
        previous->next = pattern;
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
                 "Filter %s: Added header pattern \"%s\"", name, pattern_str);
        
    return NULL;
}