END_TEST START_TEST (find_config2_test) { int res; config_rec *c; xaset_t *set = NULL; const char *name; unsigned long flags = 0; c = find_config2(NULL, -1, NULL, FALSE, flags); fail_unless(c == NULL, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL, got %d (%s)", errno, strerror(errno)); mark_point(); name = "foo"; c = add_config_param_set(&set, name, 0); fail_unless(c != NULL, "Failed to add config '%s': %s", name, strerror(errno)); name = "bar"; c = find_config2(set, -1, name, FALSE, flags); fail_unless(c == NULL, "Failed to handle null arguments"); fail_unless(errno == ENOENT, "Failed to set errno to ENOENT, got %d (%s)", errno, strerror(errno)); mark_point(); /* We expect to find "foo", but a 'next' should be empty. */ name = "foo"; c = find_config2(set, -1, name, FALSE, flags); fail_unless(c != NULL, "Failed to find config '%s': %s", name, strerror(errno)); mark_point(); c = find_config_next2(c, c->next, -1, name, FALSE, flags); fail_unless(c == NULL, "Found next config unexpectedly"); fail_unless(errno == ENOENT, "Failed to set errno to ENOENT, got %d (%s)", errno, strerror(errno)); /* Now add another config, find "foo" again; this time, a 'next' should * NOT be empty; it should find the 2nd config we added. */ name = "foo2"; c = add_config_param_set(&set, name, 0); fail_unless(c != NULL, "Failed to add config '%s': %s", name, strerror(errno)); name = NULL; c = find_config2(set, -1, name, FALSE, flags); fail_unless(c != NULL, "Failed to find any config: %s", strerror(errno)); mark_point(); c = find_config_next2(c, c->next, -1, name, FALSE, flags); fail_unless(c != NULL, "Expected to find another config"); mark_point(); name = "foo"; res = remove_config(set, name, FALSE); fail_unless(res > 0, "Failed to remove config '%s': %s", name, strerror(errno)); mark_point(); c = find_config2(set, -1, name, FALSE, flags); fail_unless(c == NULL, "Found config '%s' unexpectedly", name); fail_unless(errno == ENOENT, "Failed to set errno to ENOENT, got %d (%s)", errno, strerror(errno)); }
/* This is one messy function. Yuck. Yay legacy code. */ config_rec *pr_auth_get_anon_config(pool *p, char **login_name, char **user_name, char **anon_name) { config_rec *c = NULL, *topc = NULL; char *config_user_name, *config_anon_name = NULL; unsigned char is_alias = FALSE, *auth_alias_only = NULL; unsigned long config_flags = (PR_CONFIG_FIND_FL_SKIP_DIR|PR_CONFIG_FIND_FL_SKIP_LIMIT|PR_CONFIG_FIND_FL_SKIP_DYNDIR); /* Precendence rules: * 1. Search for UserAlias directive. * 2. Search for Anonymous directive. * 3. Normal user login */ config_user_name = get_param_ptr(main_server->conf, "UserName", FALSE); if (config_user_name && user_name) { *user_name = config_user_name; } /* If the main_server->conf->set list is large (e.g. there are many * config_recs in the list, as can happen if MANY <Directory> sections are * configured), the login can timeout because this find_config() call takes * a long time. The reason this issue strikes HERE first in the login * process is that this appears to the first find_config() call which has * a TRUE recurse flag. * * The find_config() call below is looking for a UserAlias directive * anywhere in the configuration, no matter how deeply buried in nested * config contexts it might be. */ c = find_config2(main_server->conf, CONF_PARAM, "UserAlias", TRUE, config_flags); if (c != NULL) { do { pr_signals_handle(); if (strncmp(c->argv[0], "*", 2) == 0 || strcmp(c->argv[0], *login_name) == 0) { is_alias = TRUE; break; } } while ((c = find_config_next2(c, c->next, CONF_PARAM, "UserAlias", TRUE, config_flags)) != NULL); } /* This is where things get messy, rapidly. */ topc = c; while (c && c->parent && (auth_alias_only = get_param_ptr(c->parent->set, "AuthAliasOnly", FALSE))) { /* while() loops should always handle signals. */ pr_signals_handle(); if (auth_alias_only) { /* If AuthAliasOnly is on, ignore this one and continue. */ if (*auth_alias_only == TRUE) { c = find_config_next2(c, c->next, CONF_PARAM, "UserAlias", TRUE, config_flags); continue; } } /* At this point, we have found an "AuthAliasOnly off" config in * c->parent->set. See if there's a UserAlias in the same config set. */ is_alias = FALSE; find_config_set_top(topc); c = find_config_next2(c, c->next, CONF_PARAM, "UserAlias", TRUE, config_flags); if (c && (strncmp(c->argv[0], "*", 2) == 0 || strcmp(c->argv[0], *login_name) == 0)) { is_alias = TRUE; } } if (c) { *login_name = c->argv[1]; /* If the alias is applied inside an <Anonymous> context, we have found * our anon block. */ if (c->parent && c->parent->config_type == CONF_ANON) { c = c->parent; } else { c = NULL; } } /* Next, search for an anonymous entry. */ if (c == NULL) { c = find_config(main_server->conf, CONF_ANON, NULL, FALSE); } else { find_config_set_top(c); } if (c) { do { pr_signals_handle(); config_anon_name = get_param_ptr(c->subset, "UserName", FALSE); if (!config_anon_name) config_anon_name = config_user_name; if (config_anon_name && strcmp(config_anon_name, *login_name) == 0) { if (anon_name) *anon_name = config_anon_name; break; } } while ((c = find_config_next(c, c->next, CONF_ANON, NULL, FALSE)) != NULL); } if (!is_alias) { /* Yes, we do want to be using c here. Otherwise, we risk a regression * of Bug#3501. */ auth_alias_only = get_param_ptr(c ? c->subset : main_server->conf, "AuthAliasOnly", FALSE); if (auth_alias_only && *auth_alias_only == TRUE) { if (c && c->config_type == CONF_ANON) { c = NULL; } else { *login_name = NULL; } auth_alias_only = get_param_ptr(main_server->conf, "AuthAliasOnly", FALSE); if (*login_name && auth_alias_only && *auth_alias_only == TRUE) { *login_name = NULL; } if ((!login_name || !c) && anon_name) { *anon_name = NULL; } } } return c; }