static void pre_jail_init(char *unused_name, char **unused_argv) { mode_t saved_mask; VSTRING *redirect; /* * Never, ever, get killed by a master signal, as that would corrupt the * database when we're in the middle of an update. */ setsid(); /* * Security: don't create root-owned files that contain untrusted data. * And don't create Postfix-owned files in root-owned directories, * either. We want a correct relationship between (file/directory) * ownership and (file/directory) content. * * XXX Non-root open can violate the principle of least surprise: Postfix * can't open an *SQL config file for database read-write access, even * though it can open that same control file for database read-only * access. * * The solution is to query a map type and obtain its properties before * opening it. A clean solution is to add a dict_info() API that is * similar to dict_open() except it returns properties (dict flags) only. * A pragmatic solution is to overload the existing API and have * dict_open() return a dummy map when given a null map name. * * However, the proxymap daemon has been opening *SQL maps as non-root for * years now without anyone complaining, let's not solve a problem that * doesn't exist. */ SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid); redirect = vstring_alloc(100); /* * Keep state in persistent (external) or volatile (internal) map. * * Start the cache cleanup thread after permanently dropping privileges. */ #define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE \ | DICT_FLAG_OPEN_LOCK | DICT_FLAG_UTF8_REQUEST) saved_mask = umask(022); verify_map = dict_cache_open(*var_verify_map ? data_redirect_map(redirect, var_verify_map) : "internal:verify", O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS); (void) umask(saved_mask); /* * Clean up and restore privilege. */ vstring_free(redirect); RESTORE_SAVED_EUGID(); }
int main(int argc, char **argv) { DICT_CACHE_TEST *test_job; VSTRING *inbuf = vstring_alloc(100); char *bufp; ARGV *args; DICT_CACHE *cache = 0; int stdin_is_tty; msg_vstream_init(argv[0], VSTREAM_ERR); if (argc != 1) usage(argv[0]); test_job = create_requests(DICT_CACHE_SREQ_LIMIT); stdin_is_tty = isatty(0); for (;;) { if (stdin_is_tty) { vstream_printf("> "); vstream_fflush(VSTREAM_OUT); } if (vstring_fgets_nonl(inbuf, VSTREAM_IN) == 0) break; bufp = vstring_str(inbuf); if (!stdin_is_tty) { vstream_printf("> %s\n", bufp); vstream_fflush(VSTREAM_OUT); } if (*bufp == '#') continue; args = argv_split(bufp, DELIMS); if (argc == 0) { vstream_printf("usage: %s\n", USAGE); vstream_fflush(VSTREAM_OUT); continue; } if (strcmp(args->argv[0], "verbose") == 0 && args->argc == 2) { msg_verbose = atoi(args->argv[1]); } else if (strcmp(args->argv[0], "elapsed") == 0 && args->argc == 2) { show_elapsed = atoi(args->argv[1]); #ifdef HAS_LMDB } else if (strcmp(args->argv[0], "lmdb_map_size") == 0 && args->argc == 2) { dict_lmdb_map_size = atol(args->argv[1]); #endif } else if (strcmp(args->argv[0], "cache") == 0 && args->argc == 2) { if (cache) dict_cache_close(cache); cache = dict_cache_open(args->argv[1], O_CREAT | O_RDWR, DICT_CACHE_OPEN_FLAGS); } else if (strcmp(args->argv[0], "reset") == 0 && args->argc == 1) { reset_requests(test_job); } else if (strcmp(args->argv[0], "run") == 0 && args->argc == 1) { run_requests(test_job, cache, inbuf); } else if (strcmp(args->argv[0], "status") == 0 && args->argc == 1) { show_status(test_job, cache); } else { add_request(test_job, args); } vstream_fflush(VSTREAM_OUT); argv_free(args); } vstring_free(inbuf); free_requests(test_job); if (cache) dict_cache_close(cache); return (0); }
static void pre_jail_init(char *unused_name, char **unused_argv) { VSTRING *redirect; /* * Open read-only maps before dropping privilege, for consistency with * other Postfix daemons. */ psc_acl_pre_jail_init(var_mynetworks, VAR_PSC_ACL); if (*var_psc_acl) psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL); /* Ignore smtpd_forbid_cmds lookup errors. Non-critical feature. */ if (*var_psc_forbid_cmds) psc_forbid_cmds = string_list_init(MATCH_FLAG_RETURN, var_psc_forbid_cmds); if (*var_psc_dnsbl_reply) psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY, DICT_FLAG_DUP_WARN); /* * Never, ever, get killed by a master signal, as that would corrupt the * database when we're in the middle of an update. */ if (setsid() < 0) msg_warn("setsid: %m"); /* * Security: don't create root-owned files that contain untrusted data. * And don't create Postfix-owned files in root-owned directories, * either. We want a correct relationship between (file or directory) * ownership and (file or directory) content. To open files before going * to jail, temporarily drop root privileges. */ SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid); redirect = vstring_alloc(100); /* * Keep state in persistent external map. As a safety measure we sync the * database on each update. This hurts on LINUX file systems that sync * all dirty disk blocks whenever any application invokes fsync(). * * Start the cache maintenance pseudo thread after dropping privileges. */ #define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \ DICT_FLAG_OPEN_LOCK) if (*var_psc_cache_map) psc_cache_map = dict_cache_open(data_redirect_map(redirect, var_psc_cache_map), O_CREAT | O_RDWR, PSC_DICT_OPEN_FLAGS); /* * Clean up and restore privilege. */ vstring_free(redirect); RESTORE_SAVED_EUGID(); /* * Initialize the dummy SMTP engine. */ psc_smtpd_pre_jail_init(); }