END_TEST START_TEST (auth_cache_name2gid_failed_test) { int res; gid_t gid; authtable authtab; char *sym_name = "name2gid"; /* Load the appropriate AUTH symbol, and call it. */ memset(&authtab, 0, sizeof(authtab)); authtab.name = sym_name; authtab.handler = decline_name2gid; authtab.m = &unit_tests_module; res = pr_stash_add_symbol(PR_SYM_AUTH, &authtab); fail_unless(res == 0, "Failed to add '%s' AUTH symbol: %s", sym_name, strerror(errno)); mark_point(); gid = pr_auth_name2gid(p, PR_TEST_AUTH_NAME); fail_unless(gid == (gid_t) -1, "Expected -1, got %lu", (unsigned long) gid); fail_unless(name2gid_count == 1, "Expected call count 1, got %u", name2gid_count); /* Call again; the call counter should NOT increment due to caching. */ gid = pr_auth_name2gid(p, PR_TEST_AUTH_NAME); fail_unless(gid == (gid_t) -1, "Expected -1, got %lu", (unsigned long) gid); fail_unless(name2gid_count == 1, "Expected call count 1, got %u", name2gid_count); pr_stash_remove_symbol(PR_SYM_AUTH, sym_name, &unit_tests_module); }
END_TEST START_TEST (auth_name2gid_test) { int res; gid_t gid; authtable authtab; char *sym_name = "name2gid"; pr_auth_cache_set(FALSE, PR_AUTH_CACHE_FL_BAD_NAME2GID); gid = pr_auth_name2gid(NULL, NULL); fail_unless(gid == (gid_t) -1, "Found GID unexpectedly"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL, got %d (%s)", errno, strerror(errno)); gid = pr_auth_name2gid(p, PR_TEST_AUTH_NAME); fail_unless(gid == (gid_t) -1, "Found GID unexpectedly"); fail_unless(name2gid_count == 0, "Expected call count 0, got %u", name2gid_count); mark_point(); /* Load the appropriate AUTH symbol, and call it. */ memset(&authtab, 0, sizeof(authtab)); authtab.name = sym_name; authtab.handler = handle_name2gid; authtab.m = &unit_tests_module; res = pr_stash_add_symbol(PR_SYM_AUTH, &authtab); fail_unless(res == 0, "Failed to add '%s' AUTH symbol: %s", sym_name, strerror(errno)); mark_point(); gid = pr_auth_name2gid(p, PR_TEST_AUTH_NAME); fail_unless(gid == PR_TEST_AUTH_GID, "Expected GID %lu, got %lu", (unsigned long) PR_TEST_AUTH_GID, (unsigned long) gid); fail_unless(name2gid_count == 1, "Expected call count 1, got %u", name2gid_count); mark_point(); /* Call again; the call counter should NOT increment due to caching. */ gid = pr_auth_name2gid(p, PR_TEST_AUTH_NAME); fail_unless(gid == PR_TEST_AUTH_GID, "Expected GID %lu, got %lu", (unsigned long) PR_TEST_AUTH_GID, (unsigned long) gid); fail_unless(name2gid_count == 1, "Expected call count 1, got %u", name2gid_count); pr_stash_remove_symbol(PR_SYM_AUTH, sym_name, &unit_tests_module); }
void pr_ctrls_set_group_acl(pool *grp_acl_pool, ctrls_grp_acl_t *grp_acl, const char *allow, char *grouplist) { char *group = NULL, **groups = NULL; array_header *gid_list = NULL; gid_t gid = 0; pool *tmp_pool = NULL; if (grp_acl_pool == NULL || grp_acl == NULL || allow == NULL || grouplist == NULL) { return; } tmp_pool = make_sub_pool(grp_acl_pool); if (strncmp(allow, "allow", 6) == 0) { grp_acl->allow = TRUE; } else { grp_acl->allow = FALSE; } /* Parse the given expression into an array, then retrieve the GID * for each given name. */ groups = pr_ctrls_parse_acl(grp_acl_pool, grouplist); /* Allocate an array of gid_t's */ gid_list = make_array(grp_acl_pool, 0, sizeof(gid_t)); for (group = *groups; group != NULL; group = *++groups) { /* Handle a group name of "*" differently. */ if (strncmp(group, "*", 2) == 0) { grp_acl->ngids = 1; grp_acl->gids = NULL; destroy_pool(tmp_pool); return; } else { gid = pr_auth_name2gid(tmp_pool, group); if (gid == (gid_t) -1) continue; } *((gid_t *) push_array(gid_list)) = gid; } grp_acl->ngids = gid_list->nelts; grp_acl->gids = (gid_t *) gid_list->elts; destroy_pool(tmp_pool); }
MODRET site_chgrp(cmd_rec *cmd) { gid_t gid; char *path = NULL, *tmp = NULL, *arg = ""; register unsigned int i = 0; #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) regex_t *preg; #endif if (cmd->argc < 3) { pr_response_add_err(R_500, _("'SITE %s' not understood"), _get_full_cmd(cmd)); return NULL; } /* Construct the target file name by concatenating all the parameters after * the mode, separating them with spaces. */ for (i = 2; i <= cmd->argc-1; i++) arg = pstrcat(cmd->tmp_pool, arg, *arg ? " " : "", pr_fs_decode_path(cmd->tmp_pool, cmd->argv[i]), NULL); #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) preg = (regex_t *) get_param_ptr(CURRENT_CONF, "PathAllowFilter", FALSE); if (preg && regexec(preg, arg, 0, NULL, 0) != 0) { pr_log_debug(DEBUG2, "'%s %s' denied by PathAllowFilter", cmd->argv[0], arg); pr_response_add_err(R_550, _("%s: Forbidden filename"), cmd->arg); return PR_ERROR(cmd); } preg = (regex_t *) get_param_ptr(CURRENT_CONF, "PathDenyFilter", FALSE); if (preg && regexec(preg, arg, 0, NULL, 0) == 0) { pr_log_debug(DEBUG2, "'%s %s' denied by PathDenyFilter", cmd->argv[0], arg); pr_response_add_err(R_550, _("%s: Forbidden filename"), cmd->arg); return PR_ERROR(cmd); } #endif path = dir_realpath(cmd->tmp_pool, arg); if (!path) { pr_response_add_err(R_550, "%s: %s", arg, strerror(errno)); return PR_ERROR(cmd); } /* Map the given group argument, if a string, to a GID. If already a * number, pass through as is. */ gid = strtoul(cmd->argv[1], &tmp, 10); if (tmp && *tmp) { /* Try the parameter as a user name. */ gid = pr_auth_name2gid(cmd->tmp_pool, cmd->argv[1]); if (gid == (gid_t) -1) { pr_response_add_err(R_550, "%s: %s", arg, strerror(EINVAL)); return PR_ERROR(cmd); } } if (core_chgrp(cmd, path, (uid_t) -1, gid) == -1) { pr_response_add_err(R_550, "%s: %s", arg, strerror(errno)); return PR_ERROR(cmd); } else pr_response_add(R_200, _("SITE %s command successful"), cmd->argv[0]); return PR_HANDLED(cmd); }
MODRET site_chgrp(cmd_rec *cmd) { int res; gid_t gid; char *path = NULL, *tmp = NULL, *arg = ""; register unsigned int i = 0; #ifdef PR_USE_REGEX pr_regex_t *pre; #endif if (cmd->argc < 3) { pr_response_add_err(R_500, _("'SITE %s' not understood"), _get_full_cmd(cmd)); return NULL; } /* Construct the target file name by concatenating all the parameters after * the mode, separating them with spaces. */ for (i = 2; i <= cmd->argc-1; i++) arg = pstrcat(cmd->tmp_pool, arg, *arg ? " " : "", pr_fs_decode_path(cmd->tmp_pool, cmd->argv[i]), NULL); #ifdef PR_USE_REGEX pre = get_param_ptr(CURRENT_CONF, "PathAllowFilter", FALSE); if (pre != NULL && pr_regexp_exec(pre, arg, 0, NULL, 0, 0, 0) != 0) { pr_log_debug(DEBUG2, "'%s %s' denied by PathAllowFilter", cmd->argv[0], arg); pr_response_add_err(R_550, _("%s: Forbidden filename"), cmd->arg); return PR_ERROR(cmd); } pre = get_param_ptr(CURRENT_CONF, "PathDenyFilter", FALSE); if (pre != NULL && pr_regexp_exec(pre, arg, 0, NULL, 0, 0, 0) == 0) { pr_log_debug(DEBUG2, "'%s %s' denied by PathDenyFilter", cmd->argv[0], arg); pr_response_add_err(R_550, _("%s: Forbidden filename"), cmd->arg); return PR_ERROR(cmd); } #endif path = dir_realpath(cmd->tmp_pool, arg); if (!path) { pr_response_add_err(R_550, "%s: %s", arg, strerror(errno)); return PR_ERROR(cmd); } /* Map the given group argument, if a string, to a GID. If already a * number, pass through as is. */ gid = strtoul(cmd->argv[1], &tmp, 10); if (tmp && *tmp) { /* Try the parameter as a group name. */ gid = pr_auth_name2gid(cmd->tmp_pool, cmd->argv[1]); if (gid == (gid_t) -1) { pr_log_debug(DEBUG9, "SITE CHGRP: Unable to resolve group name '%s' to GID", cmd->argv[1]); pr_response_add_err(R_550, "%s: %s", arg, strerror(EINVAL)); return PR_ERROR(cmd); } } res = core_chgrp(cmd, path, (uid_t) -1, gid); if (res < 0) { int xerrno = errno; (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " "error chown'ing '%s' to GID %lu: %s", cmd->argv[0], session.user, (unsigned long) session.uid, (unsigned long) session.gid, path, (unsigned long) gid, strerror(xerrno)); pr_response_add_err(R_550, "%s: %s", arg, strerror(xerrno)); errno = xerrno; return PR_ERROR(cmd); } else { pr_response_add(R_200, _("SITE %s command successful"), cmd->argv[0]); } return PR_HANDLED(cmd); }
MODRET site_chgrp(cmd_rec *cmd) { int res; gid_t gid; char *path = NULL, *tmp = NULL, *arg = ""; struct stat st; register unsigned int i = 0; #ifdef PR_USE_REGEX pr_regex_t *pre; #endif if (cmd->argc < 3) { pr_response_add_err(R_500, _("'SITE %s' not understood"), _get_full_cmd(cmd)); return NULL; } /* Construct the target file name by concatenating all the parameters after * the mode, separating them with spaces. */ for (i = 2; i <= cmd->argc-1; i++) { char *decoded_path; decoded_path = pr_fs_decode_path2(cmd->tmp_pool, cmd->argv[i], FSIO_DECODE_FL_TELL_ERRORS); if (decoded_path == NULL) { int xerrno = errno; pr_log_debug(DEBUG8, "'%s' failed to decode properly: %s", (char *) cmd->argv[i], strerror(xerrno)); pr_response_add_err(R_550, _("SITE %s: Illegal character sequence in command"), (char *) cmd->argv[1]); pr_cmd_set_errno(cmd, xerrno); errno = xerrno; return PR_ERROR(cmd); } arg = pstrcat(cmd->tmp_pool, arg, *arg ? " " : "", decoded_path, NULL); } #ifdef PR_USE_REGEX pre = get_param_ptr(CURRENT_CONF, "PathAllowFilter", FALSE); if (pre != NULL && pr_regexp_exec(pre, arg, 0, NULL, 0, 0, 0) != 0) { pr_log_debug(DEBUG2, "'%s %s' denied by PathAllowFilter", (char *) cmd->argv[0], arg); pr_response_add_err(R_550, _("%s: Forbidden filename"), cmd->arg); pr_cmd_set_errno(cmd, EPERM); errno = EPERM; return PR_ERROR(cmd); } pre = get_param_ptr(CURRENT_CONF, "PathDenyFilter", FALSE); if (pre != NULL && pr_regexp_exec(pre, arg, 0, NULL, 0, 0, 0) == 0) { pr_log_debug(DEBUG2, "'%s %s' denied by PathDenyFilter", (char *) cmd->argv[0], arg); pr_response_add_err(R_550, _("%s: Forbidden filename"), cmd->arg); pr_cmd_set_errno(cmd, EPERM); errno = EPERM; return PR_ERROR(cmd); } #endif if (pr_fsio_lstat(arg, &st) == 0) { if (S_ISLNK(st.st_mode)) { char link_path[PR_TUNABLE_PATH_MAX]; int len; memset(link_path, '\0', sizeof(link_path)); len = dir_readlink(cmd->tmp_pool, arg, link_path, sizeof(link_path)-1, PR_DIR_READLINK_FL_HANDLE_REL_PATH); if (len > 0) { link_path[len] = '\0'; arg = pstrdup(cmd->tmp_pool, link_path); } } } path = dir_realpath(cmd->tmp_pool, arg); if (path == NULL) { int xerrno = errno; pr_response_add_err(R_550, "%s: %s", arg, strerror(xerrno)); pr_cmd_set_errno(cmd, xerrno); errno = xerrno; return PR_ERROR(cmd); } /* Map the given group argument, if a string, to a GID. If already a * number, pass through as is. */ gid = strtoul(cmd->argv[1], &tmp, 10); if (tmp && *tmp) { /* Try the parameter as a group name. */ gid = pr_auth_name2gid(cmd->tmp_pool, cmd->argv[1]); if (gid == (gid_t) -1) { int xerrno = EINVAL; pr_log_debug(DEBUG9, "SITE CHGRP: Unable to resolve group name '%s' to GID", (char *) cmd->argv[1]); pr_response_add_err(R_550, "%s: %s", arg, strerror(xerrno)); pr_cmd_set_errno(cmd, xerrno); errno = xerrno; return PR_ERROR(cmd); } } res = core_chgrp(cmd, path, (uid_t) -1, gid); if (res < 0) { int xerrno = errno; (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %s, GID %s): " "error chown'ing '%s' to GID %s: %s", (char *) cmd->argv[0], session.user, pr_uid2str(cmd->tmp_pool, session.uid), pr_gid2str(cmd->tmp_pool, session.gid), path, pr_gid2str(cmd->tmp_pool, gid), strerror(xerrno)); pr_response_add_err(R_550, "%s: %s", arg, strerror(xerrno)); pr_cmd_set_errno(cmd, xerrno); errno = xerrno; return PR_ERROR(cmd); } pr_response_add(R_200, _("SITE %s command successful"), (char *) cmd->argv[0]); return PR_HANDLED(cmd); }