char *dir_canonical_path(pool *p, const char *path) { char buf[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; char work[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; if (p == NULL || path == NULL) { errno = EINVAL; return NULL; } if (*path == '~') { if (pr_fs_interpolate(path, work, sizeof(work)-1) != 1) { if (pr_fs_dircat(work, sizeof(work), pr_fs_getcwd(), path) < 0) { return NULL; } } } else { if (pr_fs_dircat(work, sizeof(work), pr_fs_getcwd(), path) < 0) { return NULL; } } pr_fs_clean_path(work, buf, sizeof(buf)-1); return pstrdup(p, buf); }
/* dir_best_path() creates the "most" fully canonicalized path possible * (i.e. if path components at the end don't exist, they are ignored). */ char *dir_best_path(pool *p, const char *path) { char workpath[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; char realpath_buf[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; char *target = NULL, *ntarget; int fini = 0; if (*path == '~') { if (pr_fs_interpolate(path, workpath, sizeof(workpath)-1) != 1) { if (pr_fs_dircat(workpath, sizeof(workpath), pr_fs_getcwd(), path) < 0) return NULL; } } else { if (pr_fs_dircat(workpath, sizeof(workpath), pr_fs_getcwd(), path) < 0) return NULL; } pr_fs_clean_path(pstrdup(p, workpath), workpath, sizeof(workpath)-1); while (!fini && *workpath) { if (pr_fs_resolve_path(workpath, realpath_buf, sizeof(realpath_buf)-1, 0) != -1) break; ntarget = strrchr(workpath, '/'); if (ntarget) { if (target) { if (pr_fs_dircat(workpath, sizeof(workpath), workpath, target) < 0) return NULL; } target = ntarget; *target++ = '\0'; } else fini++; } if (!fini && *workpath) { if (target) { if (pr_fs_dircat(workpath, sizeof(workpath), realpath_buf, target) < 0) return NULL; } else sstrncpy(workpath, realpath_buf, sizeof(workpath)); } else { if (pr_fs_dircat(workpath, sizeof(workpath), "/", target) < 0) return NULL; } return pstrdup(p, workpath); }
/* Takes a directory and returns its absolute version. ~username references * are appropriately interpolated. "Absolute" includes a _full_ reference * based on the root directory, not upon a chrooted dir. */ char *dir_abs_path(pool *p, const char *path, int interpolate) { char *res = NULL; if (p == NULL || path == NULL) { errno = EINVAL; return NULL; } if (interpolate) { char buf[PR_TUNABLE_PATH_MAX+1]; memset(buf, '\0', sizeof(buf)); switch (pr_fs_interpolate(path, buf, sizeof(buf)-1)) { case -1: return NULL; case 0: /* Do nothing; path exists */ break; case 1: /* Interpolation occurred; make a copy of the interpolated path. */ path = pstrdup(p, buf); break; } } if (*path != '/') { if (session.chroot_path) { res = pdircat(p, session.chroot_path, pr_fs_getcwd(), path, NULL); } else { res = pdircat(p, pr_fs_getcwd(), path, NULL); } } else { if (session.chroot_path) { if (strncmp(path, session.chroot_path, strlen(session.chroot_path)) != 0) { res = pdircat(p, session.chroot_path, path, NULL); } else { res = pstrdup(p, path); } } else { res = pstrdup(p, path); } } return res; }
int proxy_session_setup_env(pool *p, const char *user, int flags) { struct passwd *pw; config_rec *c; int i, res = 0, xerrno = 0; const char *xferlog = NULL; session.hide_password = TRUE; /* Note: the given user name may not be known locally on the proxy; thus * having pr_auth_getpwnam() returning NULL here is not an unexpected * use case. */ pw = pr_auth_getpwnam(p, user); if (pw != NULL) { if (pw->pw_uid == PR_ROOT_UID) { int root_login = FALSE; pr_event_generate("mod_auth.root-login", NULL); c = find_config(main_server->conf, CONF_PARAM, "RootLogin", FALSE); if (c != NULL) { root_login = *((int *) c->argv[0]); } if (root_login == FALSE) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "root login attempted, denied by RootLogin configuration"); pr_log_auth(PR_LOG_NOTICE, "SECURITY VIOLATION: Root login attempted."); return -1; } pr_log_auth(PR_LOG_WARNING, "ROOT proxy login successful"); } res = pr_auth_is_valid_shell(main_server->conf, pw->pw_shell); if (res == FALSE) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "authentication for user '%s' failed: Invalid shell", user); pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Invalid shell: '%s'", user, pw->pw_shell); errno = EPERM; return -1; } res = pr_auth_banned_by_ftpusers(main_server->conf, pw->pw_name); if (res == TRUE) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "authentication for user '%s' failed: User in " PR_FTPUSERS_PATH, user); pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): User in " PR_FTPUSERS_PATH, pw->pw_name); errno = EPERM; return -1; } session.user = pstrdup(p, pw->pw_name); session.group = pstrdup(p, pr_auth_gid2name(p, pw->pw_gid)); session.login_uid = pw->pw_uid; session.login_gid = pw->pw_gid; } else { session.user = pstrdup(session.pool, user); /* XXX What should session.group, session.login_uid, session.login_gid * be? Kept as is? */ } if (session.gids == NULL && session.groups == NULL) { res = pr_auth_getgroups(p, session.user, &session.gids, &session.groups); if (res < 1 && errno != ENOENT) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "no supplemental groups found for user '%s'", session.user); } } if (flags & PROXY_SESSION_FL_CHECK_LOGIN_ACL) { int login_acl; login_acl = login_check_limits(main_server->conf, FALSE, TRUE, &i); if (!login_acl) { pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Limit configuration " "denies login", user); return -1; } } /* XXX Will users want wtmp logging for a proxy login? */ session.wtmp_log = FALSE; c = find_config(main_server->conf, CONF_PARAM, "TransferLog", FALSE); if (c == NULL) { xferlog = PR_XFERLOG_PATH; } else { xferlog = c->argv[0]; } PRIVS_ROOT if (strncasecmp(xferlog, "none", 5) == 0) { xferlog_open(NULL); } else { xferlog_open(xferlog); } res = xerrno = 0; if (pw != NULL) { res = set_groups(p, pw->pw_gid, session.gids); xerrno = errno; } PRIVS_RELINQUISH if (res < 0) { pr_log_pri(PR_LOG_WARNING, "unable to set process groups: %s", strerror(xerrno)); } session.disable_id_switching = TRUE; session.proc_prefix = pstrdup(session.pool, session.c->remote_name); session.sf_flags = 0; pr_scoreboard_entry_update(session.pid, PR_SCORE_USER, session.user, PR_SCORE_CWD, pr_fs_getcwd(), NULL); if (session.group != NULL) { session.group = pstrdup(session.pool, session.group); } if (session.groups != NULL) { session.groups = copy_array_str(session.pool, session.groups); } proxy_sess_state |= PROXY_SESS_STATE_PROXY_AUTHENTICATED; pr_timer_remove(PR_TIMER_LOGIN, ANY_MODULE); return 0; }