struct passwd *pr_auth_getpwent(pool *p) { cmd_rec *cmd = NULL; modret_t *mr = NULL; struct passwd *res = NULL; cmd = make_cmd(p, 0); mr = dispatch_auth(cmd, "getpwent", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; } if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } /* Sanity check */ if (res == NULL) return NULL; /* Make sure the UID and GID are not -1 */ if (res->pw_uid == (uid_t) -1) { pr_log_pri(PR_LOG_WARNING, "error: UID of -1 not allowed"); return NULL; } if (res->pw_gid == (gid_t) -1) { pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed"); return NULL; } return res; }
const char *pr_auth_gid2name(pool *p, gid_t gid) { cmd_rec *cmd = NULL; modret_t *mr = NULL; static char namebuf[64]; char *res = NULL; int have_name = FALSE; memset(namebuf, '\0', sizeof(namebuf)); gidcache_create(); if ((auth_caching & PR_AUTH_CACHE_FL_GID2NAME) && gid_tab) { void *v = NULL; v = pr_table_kget(gid_tab, (const void *) &gid, sizeof(gid_t), NULL); if (v) { sstrncpy(namebuf, v, sizeof(namebuf)); pr_trace_msg(trace_channel, 8, "using name '%s' from gidcache for GID %lu", namebuf, (unsigned long) gid); res = namebuf; return res; } else { pr_trace_msg(trace_channel, 9, "no value found in gidcache for GID %lu: %s", (unsigned long) gid, strerror(errno)); } } cmd = make_cmd(p, 1, (void *) &gid); mr = dispatch_auth(cmd, "gid2name", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; sstrncpy(namebuf, res, sizeof(namebuf)); res = namebuf; gidcache_add(gid, res); have_name = TRUE; } if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } if (!have_name) { snprintf(namebuf, sizeof(namebuf)-1, "%lu", (unsigned long) gid); } res = namebuf; return res; }
void pr_auth_endgrent(pool *p) { cmd_rec *cmd = NULL; cmd = make_cmd(p, 0); (void) dispatch_auth(cmd, "endgrent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return; }
uid_t pr_auth_name2uid(pool *p, const char *name) { cmd_rec *cmd = NULL; modret_t *mr = NULL; uid_t res = (uid_t) -1; cmd = make_cmd(p, 1, name); mr = dispatch_auth(cmd, "name2uid", NULL); if (MODRET_ISHANDLED(mr)) res = *((uid_t *) mr->data); else errno = EINVAL; if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; }
void pr_auth_endpwent(pool *p) { cmd_rec *cmd = NULL; cmd = make_cmd(p, 0); (void) dispatch_auth(cmd, "endpwent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } if (auth_tab) { pr_trace_msg(trace_channel, 5, "emptying authcache"); (void) pr_table_empty(auth_tab); (void) pr_table_free(auth_tab); auth_tab = NULL; } return; }
int pr_auth_authorize(pool *p, const char *name) { cmd_rec *cmd = NULL; modret_t *mr = NULL; module *m = NULL; int res = PR_AUTH_OK; cmd = make_cmd(p, 1, name); if (auth_tab) { /* Fetch the specific module to be used for authenticating this user. */ void *v = pr_table_get(auth_tab, name, NULL); if (v) { m = *((module **) v); pr_trace_msg(trace_channel, 4, "using module 'mod_%s.c' from authcache to authorize user '%s'", m->name, name); } } mr = dispatch_auth(cmd, "authorize", m ? &m : NULL); /* Unlike the other auth calls, we assume here that unless the handlers * explicitly return ERROR, the user is authorized. Thus HANDLED and * DECLINED are both treated as "yes, this user is authorized". This * handles the case where the authenticating module (e.g. mod_sql) * does NOT provide an 'authorize' handler. */ if (MODRET_ISERROR(mr)) { res = MODRET_ERROR(mr); } if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; }
int pr_auth_requires_pass(pool *p, const char *name) { cmd_rec *cmd; modret_t *mr; int res = TRUE; cmd = make_cmd(p, 1, name); mr = dispatch_auth(cmd, "requires_pass", NULL); if (MODRET_ISHANDLED(mr)) res = FALSE; else if (MODRET_ISERROR(mr)) res = MODRET_ERROR(mr); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; }
struct passwd *pr_auth_getpwuid(pool *p, uid_t uid) { cmd_rec *cmd = NULL; modret_t *mr = NULL; struct passwd *res = NULL; cmd = make_cmd(p, 1, (void *) &uid); mr = dispatch_auth(cmd, "getpwuid", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; } if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } /* Sanity check */ if (res == NULL) { errno = ENOENT; return NULL; } /* Make sure the UID and GID are not -1 */ if (res->pw_uid == (uid_t) -1) { pr_log_pri(PR_LOG_WARNING, "error: UID of -1 not allowed"); return NULL; } if (res->pw_gid == (gid_t) -1) { pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed"); return NULL; } pr_log_debug(DEBUG10, "retrieved user '%s' for UID %lu", res->pw_name, (unsigned long) uid); return res; }
struct group *pr_auth_getgrnam(pool *p, const char *name) { cmd_rec *cmd = NULL; modret_t *mr = NULL; struct group *res = NULL; cmd = make_cmd(p, 1, name); mr = dispatch_auth(cmd, "getgrnam", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; } if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } /* Sanity check */ if (res == NULL) { errno = ENOENT; return NULL; } /* Make sure the GID is not -1 */ if (res->gr_gid == (gid_t) -1) { pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed"); return NULL; } gidcache_add(res->gr_gid, name); pr_log_debug(DEBUG10, "retrieved GID %lu for group '%s'", (unsigned long) res->gr_gid, name); return res; }
int pr_auth_check(pool *p, const char *cpw, const char *name, const char *pw) { cmd_rec *cmd = NULL; modret_t *mr = NULL; module *m = NULL; int res = PR_AUTH_BADPWD; cmd = make_cmd(p, 3, cpw, name, pw); /* First, check for any of the modules in the "authenticating only" list * of modules. This is usually only mod_auth_pam, but other modules * might also add themselves (e.g. mod_radius under certain conditions). */ if (auth_module_list) { struct auth_module_elt *elt; for (elt = (struct auth_module_elt *) auth_module_list->xas_list; elt; elt = elt->next) { m = pr_module_get(elt->name); if (m) { mr = dispatch_auth(cmd, "check", &m); if (MODRET_ISHANDLED(mr)) { pr_trace_msg(trace_channel, 4, "module '%s' used for authenticating user '%s'", elt->name, name); res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; } if (MODRET_ISERROR(mr)) { res = MODRET_ERROR(mr); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; } m = NULL; } } } if (auth_tab) { /* Fetch the specific module to be used for authenticating this user. */ void *v = pr_table_get(auth_tab, name, NULL); if (v) { m = *((module **) v); pr_trace_msg(trace_channel, 4, "using module 'mod_%s.c' from authcache to authenticate user '%s'", m->name, name); } } mr = dispatch_auth(cmd, "check", m ? &m : NULL); if (MODRET_ISHANDLED(mr)) res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; }
struct passwd *pr_auth_getpwnam(pool *p, const char *name) { cmd_rec *cmd = NULL; modret_t *mr = NULL; struct passwd *res = NULL; module *m = NULL; cmd = make_cmd(p, 1, name); mr = dispatch_auth(cmd, "getpwnam", &m); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } /* Sanity check */ if (res == NULL) { errno = ENOENT; return NULL; } /* Make sure the UID and GID are not -1 */ if (res->pw_uid == (uid_t) -1) { pr_log_pri(PR_LOG_ERR, "error: UID of -1 not allowed"); return NULL; } if (res->pw_gid == (gid_t) -1) { pr_log_pri(PR_LOG_ERR, "error: GID of -1 not allowed"); return NULL; } if ((auth_caching & PR_AUTH_CACHE_FL_AUTH_MODULE) && !auth_tab && auth_pool) { auth_tab = pr_table_alloc(auth_pool, 0); } if (m && auth_tab) { int count = 0; void *value = NULL; value = palloc(auth_pool, sizeof(module *)); *((module **) value) = m; count = pr_table_exists(auth_tab, name); if (count <= 0) { if (pr_table_add(auth_tab, pstrdup(auth_pool, name), value, sizeof(module *)) < 0) { pr_trace_msg(trace_channel, 3, "error adding module 'mod_%s.c' for user '%s' to the authcache: %s", m->name, name, strerror(errno)); } else { pr_trace_msg(trace_channel, 5, "stashed module 'mod_%s.c' for user '%s' in the authcache", m->name, name); } } else { if (pr_table_set(auth_tab, pstrdup(auth_pool, name), value, sizeof(module *)) < 0) { pr_trace_msg(trace_channel, 3, "error setting module 'mod_%s.c' for user '%s' in the authcache: %s", m->name, name, strerror(errno)); } else { pr_trace_msg(trace_channel, 5, "stashed module 'mod_%s.c' for user '%s' in the authcache", m->name, name); } } } uidcache_add(res->pw_uid, name); /* Get the (possibly rewritten) home directory. */ res->pw_dir = pr_auth_get_home(p, res->pw_dir); pr_log_debug(DEBUG10, "retrieved UID %lu for user '%s'", (unsigned long) res->pw_uid, name); return res; }
int pr_auth_getgroups(pool *p, const char *name, array_header **group_ids, array_header **group_names) { cmd_rec *cmd = NULL; modret_t *mr = NULL; int res = -1; /* Allocate memory for the array_headers of GIDs and group names. */ if (group_ids) *group_ids = make_array(permanent_pool, 2, sizeof(gid_t)); if (group_names) *group_names = make_array(permanent_pool, 2, sizeof(char *)); cmd = make_cmd(p, 3, name, group_ids ? *group_ids : NULL, group_names ? *group_names : NULL); mr = dispatch_auth(cmd, "getgroups", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = *((int *) mr->data); /* Note: the number of groups returned should, barring error, * always be at least 1, as per getgroups(2) behavior. This one * ID is present because it is the primary group membership set in * struct passwd, from /etc/passwd. This will need to be documented * for the benefit of auth_getgroup() implementors. */ if (group_ids) { register unsigned int i; char *strgids = ""; gid_t *gids = (*group_ids)->elts; for (i = 0; i < (*group_ids)->nelts; i++) { char buf[64]; snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long) gids[i]); buf[sizeof(buf)-1] = '\0'; strgids = pstrcat(p, strgids, i != 0 ? ", " : "", buf, NULL); } pr_log_debug(DEBUG10, "retrieved group %s: %s", (*group_ids)->nelts == 1 ? "ID" : "IDs", strgids); } if (group_names) { register unsigned int i; char *strgroups = ""; char **groups = (*group_names)->elts; for (i = 0; i < (*group_names)->nelts; i++) strgroups = pstrcat(p, strgroups, i != 0 ? ", " : "", groups[i], NULL); pr_log_debug(DEBUG10, "retrieved group %s: %s", (*group_names)->nelts == 1 ? "name" : "names", strgroups); } } if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; }
/* Read the headers of the response and try the available handlers if authentication or validation is needed. */ apr_status_t serf__handle_auth_response(int *consumed_response, serf_request_t *request, serf_bucket_t *response, void *baton, apr_pool_t *pool) { apr_status_t status; serf_status_line sl; *consumed_response = 0; /* TODO: the response bucket was created by the application, not at all guaranteed that this is of type response_bucket!! */ status = serf_bucket_response_status(response, &sl); if (SERF_BUCKET_READ_ERROR(status)) { return status; } if (!sl.version && (APR_STATUS_IS_EOF(status) || APR_STATUS_IS_EAGAIN(status))) { return status; } status = serf_bucket_response_wait_for_headers(response); if (status) { if (!APR_STATUS_IS_EOF(status)) { return status; } /* If status is APR_EOF, there were no headers to read. This can be ok in some situations, and it definitely means there's no authentication requested now. */ return APR_SUCCESS; } if (sl.code == 401 || sl.code == 407) { /* Authentication requested. */ /* Don't bother handling the authentication request if the response wasn't received completely yet. Serf will call serf__handle_auth_response again when more data is received. */ status = discard_body(response); *consumed_response = 1; /* Discard all response body before processing authentication. */ if (!APR_STATUS_IS_EOF(status)) { return status; } status = dispatch_auth(sl.code, request, response, baton, pool); if (status != APR_SUCCESS) { return status; } /* Requeue the request with the necessary auth headers. */ /* ### Application doesn't know about this request! */ if (request->ssltunnel) { serf__ssltunnel_request_create(request->conn, request->setup, request->setup_baton); } else { serf_connection_priority_request_create(request->conn, request->setup, request->setup_baton); } return APR_EOF; } else { serf__validate_response_func_t validate_resp; serf_connection_t *conn = request->conn; serf_context_t *ctx = conn->ctx; serf__authn_info_t *authn_info; apr_status_t resp_status = APR_SUCCESS; /* Validate the response server authn headers. */ authn_info = serf__get_authn_info_for_server(conn); if (authn_info->scheme) { validate_resp = authn_info->scheme->validate_response_func; resp_status = validate_resp(authn_info->scheme, HOST, sl.code, conn, request, response, pool); } /* Validate the response proxy authn headers. */ authn_info = &ctx->proxy_authn_info; if (!resp_status && authn_info->scheme) { validate_resp = authn_info->scheme->validate_response_func; resp_status = validate_resp(authn_info->scheme, PROXY, sl.code, conn, request, response, pool); } if (resp_status) { /* If there was an error in the final step of the authentication, consider the reponse body as invalid and discard it. */ status = discard_body(response); *consumed_response = 1; if (!APR_STATUS_IS_EOF(status)) { return status; } /* The whole body was discarded, now return our error. */ return resp_status; } } return APR_SUCCESS; }
/* Read the headers of the response and try the available handlers if authentication or validation is needed. */ apr_status_t serf__handle_auth_response(int *consumed_response, serf_request_t *request, serf_bucket_t *response, void *baton, apr_pool_t *pool) { apr_status_t status; serf_status_line sl; *consumed_response = 0; status = serf_bucket_response_status(response, &sl); if (SERF_BUCKET_READ_ERROR(status)) { return status; } if (!sl.version && (APR_STATUS_IS_EOF(status) || APR_STATUS_IS_EAGAIN(status))) { return status; } status = serf_bucket_response_wait_for_headers(response); if (status) { if (!APR_STATUS_IS_EOF(status)) { return status; } /* If status is APR_EOF, there were no headers to read. This can be ok in some situations, and it definitely means there's no authentication requested now. */ return APR_SUCCESS; } if (sl.code == 401 || sl.code == 407) { /* Authentication requested. */ /* Don't bother handling the authentication request if the response wasn't received completely yet. Serf will call serf__handle_auth_response again when more data is received. */ status = discard_body(response); *consumed_response = 1; /* Discard all response body before processing authentication. */ if (!APR_STATUS_IS_EOF(status)) { return status; } status = dispatch_auth(sl.code, request, response, baton, pool); if (status != APR_SUCCESS) { return status; } /* Requeue the request with the necessary auth headers. */ /* ### Application doesn't know about this request! */ serf_connection_priority_request_create(request->conn, request->setup, request->setup_baton); return APR_EOF; } return APR_SUCCESS; }