Beispiel #1
0
void fd_debug_verify_leaks(int first_fd, int last_fd)
{
	struct ip_addr addr, raddr;
	in_port_t port, rport;
	struct stat st;
	int old_errno;

	for (; first_fd <= last_fd; first_fd++) {
		if (fcntl(first_fd, F_GETFD, 0) == -1 && errno == EBADF)
			continue;

		old_errno = errno;

		if (net_getsockname(first_fd, &addr, &port) == 0) {
			if (addr.family == AF_UNIX) {
				struct sockaddr_un sa;

				socklen_t socklen = sizeof(sa);

				if (getsockname(first_fd, (void *)&sa,
						&socklen) < 0)
					sa.sun_path[0] = '\0';

				i_panic("Leaked UNIX socket fd %d: %s",
					first_fd, sa.sun_path);
			}

			if (net_getpeername(first_fd, &raddr, &rport) < 0) {
				memset(&raddr, 0, sizeof(raddr));
				rport = 0;
			}
			i_panic("Leaked socket fd %d: %s:%u -> %s:%u",
				first_fd, net_ip2addr(&addr), port,
				net_ip2addr(&raddr), rport);
		}

		if (fstat(first_fd, &st) == 0) {
#ifdef __APPLE__
			/* OSX workaround: gettimeofday() calls shm_open()
			   internally and the fd won't get closed on exec.
			   We'll just skip all ino/dev=0 files and hope they
			   weren't anything else. */
			if (st.st_ino == 0 && st.st_dev == 0)
				continue;
#endif
#ifdef HAVE_SYS_SYSMACROS_H
			i_panic("Leaked file fd %d: dev %s.%s inode %s",
				first_fd, dec2str(major(st.st_dev)),
				dec2str(minor(st.st_dev)), dec2str(st.st_ino));
#else
			i_panic("Leaked file fd %d: dev %s inode %s",
				first_fd, dec2str(st.st_dev),
				dec2str(st.st_ino));
#endif
		}

		i_panic("Leaked unknown fd %d (errno = %s)",
			first_fd, strerror(old_errno));
	}
}
Beispiel #2
0
static int imap_master_client_verify(const struct imap_master_input *master_input,
				     int fd_client, const char **error_r)
{
	struct stat peer_st;

	if (master_input->peer_ino == 0)
		return 0;

	/* make sure we have the right fd */
	if (fstat(fd_client, &peer_st) < 0) {
		*error_r = t_strdup_printf("fstat(peer) failed: %m");
		return -1;
	}
	if (peer_st.st_ino != master_input->peer_ino ||
	    !CMP_DEV_T(peer_st.st_dev, master_input->peer_dev)) {
		*error_r = t_strdup_printf(
			"BUG: Expected peer device=%lu,%lu inode=%s doesn't match "
			"client fd's actual device=%lu,%lu inode=%s",
			(unsigned long)major(peer_st.st_dev),
			(unsigned long)minor(peer_st.st_dev), dec2str(peer_st.st_ino),
			(unsigned long)major(master_input->peer_dev),
			(unsigned long)minor(master_input->peer_dev),
			dec2str(master_input->peer_ino));
		return -1;
	}
	return 0;
}
static int
user_verify_restricted_uid(struct auth_request *auth_request)
{
	struct auth_master_connection *conn = auth_request->master;
	struct auth_fields *reply = auth_request->userdb_reply;
	const char *value, *reason;
	uid_t uid;

	if (conn->userdb_restricted_uid == 0)
		return 0;

	value = auth_fields_find(reply, "uid");
	if (value == NULL)
		reason = "userdb reply doesn't contain uid";
	else if (str_to_uid(value, &uid) < 0)
		reason = "userdb reply contains invalid uid";
	else if (uid != conn->userdb_restricted_uid) {
		reason = t_strdup_printf(
			"userdb uid (%s) doesn't match peer uid (%s)",
			dec2str(uid), dec2str(conn->userdb_restricted_uid));
	} else {
		return 0;
	}

	auth_request_log_error(auth_request, "userdb",
		"client doesn't have lookup permissions for this user: %s "
		"(to bypass this check, set: service auth { unix_listener %s { mode=0777 } })",
		reason, conn->path);
	return -1;
}
Beispiel #4
0
static void sig_die(const siginfo_t *si, void *context)
{
	struct master_service *service = context;

	/* SIGINT comes either from master process or from keyboard. we don't
	   want to log it in either case.*/
	if (si->si_signo != SIGINT) {
		i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
			  si->si_signo, dec2str(si->si_pid),
			  dec2str(si->si_uid),
			  lib_signal_code_to_str(si->si_signo, si->si_code));
	} else if ((service->flags & MASTER_SERVICE_FLAG_NO_IDLE_DIE) != 0) {
		/* never die when idling */
		return;
	} else if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
		/* SIGINT came from master. die only if we're not handling
		   any clients currently. */
		if (service->master_status.available_count !=
		    service->total_available_count)
			return;

		if (service->idle_die_callback != NULL &&
		    !service->idle_die_callback()) {
			/* we don't want to die - send a notification to master
			   so it doesn't think we're ignoring it completely. */
			master_status_send(service, FALSE);
			return;
		}
	}

	service->killed = TRUE;
	io_loop_stop(service->ioloop);
}
Beispiel #5
0
int unix_socket_create(const char *path, int mode,
		       uid_t uid, gid_t gid, int backlog)
{
	mode_t old_umask;
	int fd;

	old_umask = umask(0777 ^ mode);
	fd = net_listen_unix_unlink_stale(path, backlog);
	umask(old_umask);

	if (fd < 0) {
		i_error("net_listen_unix(%s) failed: %m", path);
		return -1;
	}

	if (uid != (uid_t)-1 || gid != (gid_t)-1) {
		/* set correct permissions */
		if (chown(path, uid, gid) < 0) {
			i_error("chown(%s, %s, %s) failed: %m",
				path, dec2str(uid), dec2str(gid));
			i_close_fd(&fd);
			return -1;
		}
	}
	return fd;
}
Beispiel #6
0
enum checkpassword_sigchld_handler_result
checkpassword_sigchld_handler(const struct child_wait_status *child_wait_status,
			      struct chkpw_auth_request *request)
{
	int status = child_wait_status->status;
	pid_t pid = child_wait_status->pid;

	if (request == NULL) {
		i_error("checkpassword: sighandler called for unknown child %s",
			dec2str(pid));
		return SIGCHLD_RESULT_UNKNOWN_CHILD;
	}

	if (WIFSIGNALED(status)) {
		i_error("checkpassword: Child %s died with signal %d",
			dec2str(pid), WTERMSIG(status));
		return SIGCHLD_RESULT_DEAD_CHILD;
	} else if (WIFEXITED(status)) {
		request->exited = TRUE;
		request->exit_status = WEXITSTATUS(status);

		auth_request_log_debug(request->request,
				       "checkpassword", "exit_status=%d",
				       request->exit_status);
		return SIGCHLD_RESULT_OK;
	} else {
		/* shouldn't happen */
		auth_request_log_debug(request->request, "checkpassword",
				       "Child exited with status=%d", status);
		return SIGCHLD_RESULT_UNKNOWN_ERROR;
	}
}
static const char *sieve_generate_tmp_filename(const char *scriptname)
{
	static struct timeval last_tv = { 0, 0 };
	struct timeval tv;

	/* use secs + usecs to guarantee uniqueness within this process. */
	if (ioloop_timeval.tv_sec > last_tv.tv_sec ||
		(ioloop_timeval.tv_sec == last_tv.tv_sec &&
		ioloop_timeval.tv_usec > last_tv.tv_usec)) {
		tv = ioloop_timeval;
	} else {
		tv = last_tv;
		if (++tv.tv_usec == 1000000) {
			tv.tv_sec++;
			tv.tv_usec = 0;
		}
	}
	last_tv = tv;

	if ( scriptname == NULL ) {
		return t_strdup_printf("%s.M%sP%s.%s.tmp",
			dec2str(tv.tv_sec), dec2str(tv.tv_usec),
			my_pid, my_hostname);
	}

	scriptname = t_strdup_printf("%s_%s.M%sP%s.%s",
		scriptname,	dec2str(tv.tv_sec), dec2str(tv.tv_usec),
		my_pid, my_hostname);
	return sieve_script_file_from_name(scriptname);
}
Beispiel #8
0
static const struct var_expand_table *
get_var_expand_table(struct client *client)
{
	struct var_expand_table *tab;

	tab = t_malloc(sizeof(login_var_expand_empty_tab));
	memcpy(tab, login_var_expand_empty_tab,
	       sizeof(login_var_expand_empty_tab));

	if (client->virtual_user != NULL)
		get_var_expand_users(tab, client->virtual_user);
	tab[3].value = login_binary->protocol;
	tab[4].value = getenv("HOME");
	tab[5].value = net_ip2addr(&client->local_ip);
	tab[6].value = net_ip2addr(&client->ip);
	tab[7].value = my_pid;
	tab[8].value = client->auth_mech_name == NULL ? NULL :
		str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
	tab[9].value = dec2str(client->local_port);
	tab[10].value = dec2str(client->remote_port);
	if (!client->tls) {
		tab[11].value = client->secured ? "secured" : NULL;
		tab[12].value = "";
	} else {
		const char *ssl_state =
			ssl_proxy_is_handshaked(client->ssl_proxy) ?
			"TLS" : "TLS handshaking";
		const char *ssl_error =
			ssl_proxy_get_last_error(client->ssl_proxy);

		tab[11].value = ssl_error == NULL ? ssl_state :
			t_strdup_printf("%s: %s", ssl_state, ssl_error);
		tab[12].value =
			ssl_proxy_get_security_string(client->ssl_proxy);
	}
	tab[13].value = client->mail_pid == 0 ? "" :
		dec2str(client->mail_pid);
	tab[14].value = client_get_session_id(client);
	tab[15].value = net_ip2addr(&client->real_local_ip);
	tab[16].value = net_ip2addr(&client->real_remote_ip);
	tab[17].value = dec2str(client->real_local_port);
	tab[18].value = dec2str(client->real_remote_port);
	if (client->virtual_user_orig != NULL)
		get_var_expand_users(tab+19, client->virtual_user_orig);
	else {
		tab[19].value = tab[0].value;
		tab[20].value = tab[1].value;
		tab[21].value = tab[2].value;
	}
	if (client->virtual_auth_user != NULL)
		get_var_expand_users(tab+22, client->virtual_auth_user);
	else {
		tab[22].value = tab[19].value;
		tab[23].value = tab[20].value;
		tab[24].value = tab[21].value;
	}
	tab[25].value = client->listener_name;
	return tab;
}
static int
service_parse_privileges(struct mail_storage_service_ctx *ctx,
			 struct mail_storage_service_user *user,
			 struct mail_storage_service_privileges *priv_r,
			 const char **error_r)
{
	const struct mail_user_settings *set = user->user_set;
	uid_t uid = (uid_t)-1;
	gid_t gid = (gid_t)-1;

	memset(priv_r, 0, sizeof(*priv_r));
	if (*set->mail_uid != '\0') {
		if (!parse_uid(set->mail_uid, &uid, error_r)) {
			*error_r = t_strdup_printf("%s (from %s)", *error_r,
						   user->uid_source);
			return -1;
		}
		if (uid < (uid_t)set->first_valid_uid ||
		    (set->last_valid_uid != 0 &&
		     uid > (uid_t)set->last_valid_uid)) {
			*error_r = t_strdup_printf(
				"Mail access for users with UID %s not permitted "
				"(see first_valid_uid in config file, uid from %s).",
				dec2str(uid), user->uid_source);
			return -1;
		}
	}
	priv_r->uid = uid;
	priv_r->uid_source = user->uid_source;

	if (*set->mail_gid != '\0') {
		if (!parse_gid(set->mail_gid, &gid, error_r)) {
			*error_r = t_strdup_printf("%s (from %s)", *error_r,
						   user->gid_source);
			return -1;
		}
		if (gid < (gid_t)set->first_valid_gid ||
		    (set->last_valid_gid != 0 &&
		     gid > (gid_t)set->last_valid_gid)) {
			*error_r = t_strdup_printf(
				"Mail access for users with GID %s not permitted "
				"(see first_valid_gid in config file, gid from %s).",
				dec2str(gid), user->gid_source);
			return -1;
		}
	}
	priv_r->gid = gid;
	priv_r->gid_source = user->gid_source;

	/* variable strings are expanded in mail_user_init(),
	   but we need the home and chroot sooner so do them separately here. */
	priv_r->home = user_expand_varstr(ctx, user, priv_r,
					  user->user_set->mail_home);
	priv_r->chroot = user_expand_varstr(ctx, user, priv_r,
					    user->user_set->mail_chroot);
	return 0;
}
Beispiel #10
0
static char *cydir_generate_tmp_filename(void)
{
	static unsigned int create_count = 0;

	return i_strdup_printf("temp.%s.P%sQ%uM%s.%s",
			       dec2str(ioloop_timeval.tv_sec), my_pid,
			       create_count++,
			       dec2str(ioloop_timeval.tv_usec), my_hostname);
}
Beispiel #11
0
static void passwd_file_lookup(struct auth_request *auth_request,
			       userdb_callback_t *callback)
{
	struct userdb_module *_module = auth_request->userdb->userdb;
	struct passwd_file_userdb_module *module =
		(struct passwd_file_userdb_module *)_module;
	struct passwd_user *pu;
        const struct var_expand_table *table;
	string_t *str;
	const char *key, *value;
	char **p;

	pu = db_passwd_file_lookup(module->pwf, auth_request,
				   module->username_format);
	if (pu == NULL || pu->uid == 0) {
		callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
		return;
	}

	if (pu->uid != (uid_t)-1) {
		auth_request_set_userdb_field(auth_request, "uid",
					      dec2str(pu->uid));
	}
	if (pu->gid != (gid_t)-1) {
		auth_request_set_userdb_field(auth_request, "gid",
					      dec2str(pu->gid));
	}

	if (pu->home != NULL)
		auth_request_set_userdb_field(auth_request, "home", pu->home);

	if (pu->extra_fields != NULL) {
		str = t_str_new(512);
		table = auth_request_get_var_expand_table(auth_request, NULL);

		for (p = pu->extra_fields; *p != NULL; p++) {
			if (strncmp(*p, "userdb_", 7) != 0)
				continue;

			key = *p + 7;
			value = strchr(key, '=');
			if (value != NULL) {
				key = t_strdup_until(key, value);
				str_truncate(str, 0);
				auth_request_var_expand_with_table(str, value + 1,
					auth_request, table, NULL);
				value = str_c(str);
			} else {
				value = "";
			}
			auth_request_set_userdb_field(auth_request, key, value);
		}
	}

	callback(USERDB_RESULT_OK, auth_request);
}
Beispiel #12
0
static void testsuite_tmp_dir_init(void)
{
	testsuite_tmp_dir = i_strdup_printf
		("/tmp/dsieve-testsuite.%s.%s", dec2str(time(NULL)), dec2str(getpid()));

	if ( mkdir(testsuite_tmp_dir, 0700) < 0 ) {
		i_fatal("failed to create temporary directory '%s': %m.", 
			testsuite_tmp_dir);		
	}
}
Beispiel #13
0
static void
userdb_nss_lookup(struct auth_request *auth_request,
		  userdb_callback_t *callback)
{
	struct userdb_module *_module = auth_request->userdb->userdb;
	struct nss_userdb_module *module = (struct nss_userdb_module *)_module;
	struct passwd pw;
	enum nss_status status;
	enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE;
	int err;

	auth_request_log_debug(auth_request, "nss", "lookup");

	status = module->getpwnam_r(auth_request->user, &pw,
				    module->buf, module->bufsize, &err);
	switch (status) {
	case NSS_STATUS_TRYAGAIN:
		auth_request_log_error(auth_request, "nss",
				       "returned tryagain (err=%d)", err);
		break;
	case NSS_STATUS_UNAVAIL:
		auth_request_log_error(auth_request, "nss",
				       "unavailable (err=%d)", err);
		break;
	case NSS_STATUS_NOTFOUND:
		auth_request_log_info(auth_request, "nss", "unknown user");
		result = USERDB_RESULT_USER_UNKNOWN;
		break;
	case NSS_STATUS_SUCCESS:
		result = USERDB_RESULT_OK;
		break;
	default:
		auth_request_log_info(auth_request, "nss",
				      "returned %d (err=%d)", status, err);
		break;
	}

	if (result != USERDB_RESULT_OK) {
		callback(result, auth_request);
		return;
	}

	auth_request_set_field(auth_request, "user", pw.pw_name, NULL);

	auth_request_init_userdb_reply(auth_request);
	auth_request_set_userdb_field(auth_request, "system_groups_user",
				      pw.pw_name);
	auth_request_set_userdb_field(auth_request, "uid", dec2str(pw.pw_uid));
	auth_request_set_userdb_field(auth_request, "gid", dec2str(pw.pw_gid));
	auth_request_set_userdb_field(auth_request, "home", pw.pw_dir);

	callback(USERDB_RESULT_OK, auth_request);
}
static void imap_hibernate_write_cmd(struct client *client, string_t *cmd,
				     const buffer_t *state, int fd_notify)
{
	struct stat peer_st;

	str_append_tabescaped(cmd, client->user->username);
	str_append_c(cmd, '\t');
	str_append_tabescaped(cmd, client->user->set->mail_log_prefix);
	str_printfa(cmd, "\tidle_notify_interval=%u",
		    client->set->imap_idle_notify_interval);
	if (fstat(client->fd_in, &peer_st) == 0) {
		str_printfa(cmd, "\tpeer_dev_major=%lu\tpeer_dev_minor=%lu\tpeer_ino=%llu",
			    (unsigned long)major(peer_st.st_dev),
			    (unsigned long)minor(peer_st.st_dev),
			    (unsigned long long)peer_st.st_ino);
	}

	if (client->session_id != NULL) {
		str_append(cmd, "\tsession=");
		str_append_tabescaped(cmd, client->session_id);
	}
	if (client->user->local_ip != NULL)
		str_printfa(cmd, "\tlip=%s", net_ip2addr(client->user->local_ip));
	if (client->user->remote_ip != NULL)
		str_printfa(cmd, "\trip=%s", net_ip2addr(client->user->remote_ip));
	if (client->userdb_fields != NULL) {
		string_t *userdb_fields = t_str_new(256);
		unsigned int i;

		for (i = 0; client->userdb_fields[i] != NULL; i++) {
			if (i > 0)
				str_append_c(userdb_fields, '\t');
			str_append_tabescaped(userdb_fields, client->userdb_fields[i]);
		}
		str_append(cmd, "\tuserdb_fields=");
		str_append_tabescaped(cmd, str_c(userdb_fields));
	}
	if (client->user->uid != (uid_t)-1)
		str_printfa(cmd, "\tuid=%s", dec2str(client->user->uid));
	if (client->user->gid != (gid_t)-1)
		str_printfa(cmd, "\tgid=%s", dec2str(client->user->gid));
	str_append(cmd, "\tstats=");
	str_append_tabescaped(cmd, client_stats(client));
	if (client->command_queue != NULL &&
	    strcasecmp(client->command_queue->name, "IDLE") == 0)
		str_append(cmd, "\tidle-cmd");
	if (fd_notify != -1)
		str_append(cmd, "\tnotify_fd");
	str_append(cmd, "\tstate=");
	base64_encode(state->data, state->used, cmd);
	str_append_c(cmd, '\n');
}
static const struct var_expand_table *
get_var_expand_table(struct master_service *service,
		     struct mail_storage_service_user *user,
		     const struct mail_storage_service_input *input,
		     const struct mail_storage_service_privileges *priv)
{
	static struct var_expand_table static_tab[] = {
		{ 'u', NULL, "user" },
		{ 'n', NULL, "username" },
		{ 'd', NULL, "domain" },
		{ 's', NULL, "service" },
		{ 'l', NULL, "lip" },
		{ 'r', NULL, "rip" },
		{ 'p', NULL, "pid" },
		{ 'i', NULL, "uid" },
		{ '\0', NULL, "gid" },
		{ '\0', NULL, "session" },
		{ '\0', NULL, "auth_user" },
		{ '\0', NULL, "auth_username" },
		{ '\0', NULL, "auth_domain" },
		{ '\0', NULL, NULL }
	};
	struct var_expand_table *tab;

	tab = t_malloc(sizeof(static_tab));
	memcpy(tab, static_tab, sizeof(static_tab));

	tab[0].value = input->username;
	tab[1].value = t_strcut(input->username, '@');
	tab[2].value = strchr(input->username, '@');
	if (tab[2].value != NULL) tab[2].value++;
	tab[3].value = service->name;
	tab[4].value = net_ip2addr(&input->local_ip);
	tab[5].value = net_ip2addr(&input->remote_ip);
	tab[6].value = my_pid;
	tab[7].value = priv == NULL ? NULL :
		dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
	tab[8].value = priv == NULL ? NULL :
		dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
	tab[9].value = input->session_id;
	if (user == NULL || user->auth_user == NULL) {
		tab[10].value = tab[0].value;
		tab[11].value = tab[1].value;
		tab[12].value = tab[2].value;
	} else {
		tab[10].value = user->auth_user;
		tab[11].value = t_strcut(user->auth_user, '@');
		tab[12].value = strchr(user->auth_user, '@');
	}
	return tab;
}
Beispiel #16
0
static int process_io_open(void)
{
	uid_t uid;

	if (proc_io_fd != -1)
		return proc_io_fd;

	if (proc_io_disabled)
		return -1;
	proc_io_fd = open(PROC_IO_PATH, O_RDONLY);
	if (proc_io_fd == -1 && errno == EACCES) {
		/* kludge: if we're running with permissions temporarily
		   dropped, get them temporarily back so we can open
		   /proc/self/io. */
		uid = geteuid();
		if (seteuid(0) == 0) {
			proc_io_fd = open(PROC_IO_PATH, O_RDONLY);
			if (seteuid(uid) < 0) {
				/* oops, this is bad */
				i_fatal("stats: seteuid(%s) failed", dec2str(uid));
			}
		}
		errno = EACCES;
	}
	if (proc_io_fd == -1) {
		if (errno != ENOENT)
			i_error("open(%s) failed: %m", PROC_IO_PATH);
		proc_io_disabled = TRUE;
		return -1;
	}
	return proc_io_fd;
}
Beispiel #17
0
static void sieve_tool_get_user_data
(const char **username_r, const char **homedir_r)
{
	uid_t process_euid = geteuid();
	struct passwd *pw;
	const char *user = NULL, *home = NULL;

	user = getenv("USER");
	home = getenv("HOME");

	if ( user == NULL || *user == '\0' ||
		home == NULL || *home == '\0' ) {

		if ((pw = getpwuid(process_euid)) != NULL) {
			user = pw->pw_name;
			home = pw->pw_dir;
		}
	}

	if ( username_r != NULL ) {
		if ( user == NULL || *user == '\0' ) {
			i_fatal("couldn't lookup our username (uid=%s)",
				dec2str(process_euid));
		}

		*username_r = t_strdup(user);
	}

	if ( homedir_r != NULL )
		*homedir_r = t_strdup(home);
}
Beispiel #18
0
void doveadm_master_send_signal(int signo)
{
	const char *pidfile_path;
	unsigned int i;
	pid_t pid;

	pidfile_path = t_strconcat(doveadm_settings->base_dir,
				   "/"MASTER_PID_FILE_NAME, NULL);

	if (!pid_file_read(pidfile_path, &pid))
		i_fatal("Dovecot is not running (read from %s)", pidfile_path);

	if (kill(pid, signo) < 0)
		i_fatal("kill(%s, %d) failed: %m", dec2str(pid), signo);

	if (signo == SIGTERM) {
		/* wait for a while for the process to die */
		usleep(1000);
		for (i = 0; i < 30; i++) {
			if (kill(pid, 0) < 0) {
				if (errno != ESRCH)
					i_error("kill() failed: %m");
				break;
			}
			usleep(100000);
		}
	}
}
Beispiel #19
0
static void
service_process_get_status_error(string_t *str, struct service_process *process,
				 int status, bool *default_fatal_r)
{
	struct service *service = process->service;
	const char *msg;

	*default_fatal_r = FALSE;

	str_printfa(str, "service(%s): child %s ", service->set->name,
		    dec2str(process->pid));
	if (WIFSIGNALED(status)) {
		str_printfa(str, "killed with signal %d", WTERMSIG(status));
		log_coredump(service, str, status);
		return;
	}
	if (!WIFEXITED(status)) {
		str_printfa(str, "died with status %d", status);
		return;
	}

	status = WEXITSTATUS(status);
	if (status == 0) {
		str_truncate(str, 0);
		return;
	}
	str_printfa(str, "returned error %d", status);

	msg = get_exit_status_message(service, status);
	if (msg != NULL)
		str_printfa(str, " (%s)", msg);

	if (status == FATAL_DEFAULT)
		*default_fatal_r = TRUE;
}
static void
checkpassword_request_half_finish(struct chkpw_auth_request *request)
{
	if (!request->exited || request->fd_in != -1)
		return;

	switch (request->exit_status) {
	case 3:
		/* User does not exist. */
		auth_request_log_info(request->request, "userdb-checkpassword",
				      "User unknown");
		checkpassword_request_finish(request,
					     USERDB_RESULT_USER_UNKNOWN);
		break;
	case 2:
		/* This is intentionally not 0. checkpassword-reply exits with
		   2 on success when AUTHORIZED is set. */
		if (request->input_buf != NULL) {
			checkpassword_request_finish(request, USERDB_RESULT_OK);
			break;
		}
		/* missing input - fall through */
	default:
		/* whatever error... */
		auth_request_log_error(request->request, "userdb-checkpassword",
			"Child %s exited with status %d",
			dec2str(request->pid), request->exit_status);
		checkpassword_request_finish(request,
					     USERDB_RESULT_INTERNAL_FAILURE);
		break;
	}
}
Beispiel #21
0
struct userdb_template *
userdb_template_build(pool_t pool, const char *userdb_name, const char *args)
{
	struct userdb_template *tmpl;
	const char *const *tmp, *key, *value, *nonull_value;
	uid_t uid;
	gid_t gid;

	tmpl = p_new(pool, struct userdb_template, 1);

	tmp = t_strsplit_spaces(args, " ");
	p_array_init(&tmpl->args, pool, str_array_length(tmp));

	for (; *tmp != NULL; tmp++) {
		value = strchr(*tmp, '=');
		if (value == NULL)
			key = *tmp;
		else
			key = t_strdup_until(*tmp, value++);

		nonull_value = value == NULL ? "" : value;
		if (strcasecmp(key, "uid") == 0) {
			uid = userdb_parse_uid(NULL, nonull_value);
			if (uid == (uid_t)-1) {
				i_fatal("%s userdb: Invalid uid: %s",
					userdb_name, nonull_value);
			}
			value = dec2str(uid);
		} else if (strcasecmp(key, "gid") == 0) {
			gid = userdb_parse_gid(NULL, nonull_value);
			if (gid == (gid_t)-1) {
				i_fatal("%s userdb: Invalid gid: %s",
					userdb_name, nonull_value);
			}
			value = dec2str(gid);
		} else if (*key == '\0') {
			i_fatal("%s userdb: Empty key (=%s)",
				userdb_name, nonull_value);
		}
		key = p_strdup(pool, key);
		value = p_strdup(pool, value);

		array_append(&tmpl->args, &key, 1);
		array_append(&tmpl->args, &value, 1);
	}
	return tmpl;
}
Beispiel #22
0
static void passwd_lookup(struct auth_request *auth_request,
			  userdb_callback_t *callback)
{
	struct userdb_module *_module = auth_request->userdb->userdb;
	struct passwd_userdb_module *module =
		(struct passwd_userdb_module *)_module;
	struct passwd pw;
	struct timeval start_tv;
	int ret;

	auth_request_log_debug(auth_request, "passwd", "lookup");

	if (gettimeofday(&start_tv, NULL) < 0)
		start_tv.tv_sec = 0;
	ret = i_getpwnam(auth_request->user, &pw);
	if (start_tv.tv_sec != 0)
		passwd_check_warnings(auth_request, module, &start_tv);

	switch (ret) {
	case -1:
		auth_request_log_error(auth_request, "passwd",
				       "getpwnam() failed: %m");
		callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
		return;
	case 0:
		auth_request_log_info(auth_request, "passwd", "unknown user");
		callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
		return;
	}

	auth_request_set_field(auth_request, "user", pw.pw_name, NULL);

	auth_request_init_userdb_reply(auth_request);
	auth_request_set_userdb_field(auth_request, "system_groups_user",
				      pw.pw_name);
	auth_request_set_userdb_field(auth_request, "uid", dec2str(pw.pw_uid));
	auth_request_set_userdb_field(auth_request, "gid", dec2str(pw.pw_gid));
	auth_request_set_userdb_field(auth_request, "home", pw.pw_dir);

	userdb_template_export(module->tmpl, auth_request);

	callback(USERDB_RESULT_OK, auth_request);
}
Beispiel #23
0
const char *maildir_filename_generate(void)
{
	static struct timeval last_tv = { 0, 0 };
	struct timeval tv;

	/* use secs + usecs to guarantee uniqueness within this process. */
	if (timeval_cmp(&ioloop_timeval, &last_tv) > 0)
		tv = ioloop_timeval;
	else {
		tv = last_tv;
		if (++tv.tv_usec == 1000000) {
			tv.tv_sec++;
			tv.tv_usec = 0;
		}
	}
	last_tv = tv;

	return t_strdup_printf("%s.M%sP%s.%s",
			       dec2str(tv.tv_sec), dec2str(tv.tv_usec),
			       my_pid, my_hostname);
}
Beispiel #24
0
//  Show 4 digits prec for dec, 5 for ra
void HMS::print_extra_precise_( char *buf ) const
{
    char lbuf[32];

    if ( show_sign_ ) {
        dec2str( lbuf, 32, val_, 4 );
    }
    else {
        ra2str( lbuf, 32, val_ * 15.0, 5 );
    }
    strncpy( buf, lbuf, 32 );
}
Beispiel #25
0
static void service_process_status_timeout(struct service_process *process)
{
	service_error(process->service,
		      "Initial status notification not received in %d "
		      "seconds, killing the process",
		      SERVICE_FIRST_STATUS_TIMEOUT_SECS);
	if (kill(process->pid, SIGKILL) < 0 && errno != ESRCH) {
		service_error(process->service, "kill(%s, SIGKILL) failed: %m",
			      dec2str(process->pid));
	}
	timeout_remove(&process->to_status);
}
Beispiel #26
0
static int
service_process_write_anvil_kill(int fd, struct service_process *process)
{
	const char *data;

	data = t_strdup_printf("KILL\t%s\n", dec2str(process->pid));
	if (write(fd, data, strlen(data)) < 0) {
		if (errno != EAGAIN)
			i_error("write(anvil process) failed: %m");
		return -1;
	}
	return 0;
}
Beispiel #27
0
static void
maildir_handle_size_caching(struct index_mail *mail, bool quick_check,
			    bool vsize)
{
	struct mailbox *box = mail->mail.mail.box;
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
	enum mail_fetch_field field;
	uoff_t size;
	int pop3_state;

	field = vsize ? MAIL_FETCH_VIRTUAL_SIZE : MAIL_FETCH_PHYSICAL_SIZE;
	if ((mail->data.dont_cache_fetch_fields & field) != 0)
		return;

	if (quick_check && maildir_quick_size_lookup(mail, vsize, &size) > 0) {
		/* already in filename / uidlist. don't add it anywhere,
		   including to the uidlist if it's already in filename.
		   do some extra checks here to catch potential cache bugs. */
		if (vsize && mail->data.virtual_size != size) {
			mail_cache_set_corrupted(box->cache,
				"Corrupted virtual size for uid=%u: "
				"%"PRIuUOFF_T" != %"PRIuUOFF_T,
				mail->mail.mail.uid,
				mail->data.virtual_size, size);
			mail->data.virtual_size = size;
		} else if (!vsize && mail->data.physical_size != size) {
			mail_cache_set_corrupted(box->cache,
				"Corrupted physical size for uid=%u: "
				"%"PRIuUOFF_T" != %"PRIuUOFF_T,
				mail->mail.mail.uid,
				mail->data.physical_size, size);
			mail->data.physical_size = size;
		}
		mail->data.dont_cache_fetch_fields |= field;
		return;
	}

	/* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
	pop3_state = maildir_get_pop3_state(mail);
	if (pop3_state >= 0 && mail->mail.mail.uid != 0) {
		/* if size is wanted permanently, store it to uidlist
		   so that in case cache file gets lost we can get it quickly */
		mail->data.dont_cache_fetch_fields |= field;
		size = vsize ? mail->data.virtual_size :
			mail->data.physical_size;
		maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
					vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
					MAILDIR_UIDLIST_REC_EXT_PSIZE,
					dec2str(size));
	}
}
Beispiel #28
0
static const char *get_cram_challenge(void)
{
    unsigned char buf[17];
    size_t i;

    random_fill(buf, sizeof(buf)-1);

    for (i = 0; i < sizeof(buf)-1; i++)
        buf[i] = (buf[i] % 10) + '0';
    buf[sizeof(buf)-1] = '\0';

    return t_strdup_printf("<%s.%s@%s>", (const char *)buf,
                           dec2str(ioloop_time), my_hostname);
}
Beispiel #29
0
static void
lookup_credentials_callback(enum passdb_result result,
			    const unsigned char *credentials, size_t size,
			    struct auth_request *request)
{
	struct auth_worker_client *client = request->context;
	struct auth_stream_reply *reply;
	string_t *str;

	if (request->passdb_failure && result == PASSDB_RESULT_OK)
		result = PASSDB_RESULT_PASSWORD_MISMATCH;

	reply = auth_stream_reply_init(pool_datastack_create());
	auth_stream_reply_add(reply, NULL, dec2str(request->id));

	if (result != PASSDB_RESULT_OK) {
		auth_stream_reply_add(reply, "FAIL", NULL);
		auth_stream_reply_add(reply, NULL,
				      t_strdup_printf("%d", result));
	} else {
		auth_stream_reply_add(reply, "OK", NULL);
		auth_stream_reply_add(reply, NULL, request->user);

		str = t_str_new(64);
		str_printfa(str, "{%s.b64}", request->credentials_scheme);
		base64_encode(credentials, size, str);
		auth_stream_reply_add(reply, NULL, str_c(str));

		if (request->extra_fields != NULL) {
			const char *fields =
				auth_stream_reply_export(request->extra_fields);
			auth_stream_reply_import(reply, fields);
		}
		if (request->extra_cache_fields != NULL) {
			const char *fields =
				auth_stream_reply_export(request->extra_cache_fields);
			auth_stream_reply_import(reply, fields);
		}
	}
	str = auth_stream_reply_get_str(reply);
	str_append_c(str, '\n');
	auth_worker_send_reply(client, str);

	auth_request_unref(&request);
	auth_worker_client_check_throttle(client);
	auth_worker_client_unref(&client);
}
Beispiel #30
0
void hostpid_init(void)
{
	static char hostname[256], pid[MAX_INT_STRLEN];

	if (gethostname(hostname, sizeof(hostname)-1) == -1)
		i_strocpy(hostname, "unknown", sizeof(hostname));
	hostname[sizeof(hostname)-1] = '\0';
	my_hostname = hostname;

	if (strchr(hostname, '/') != NULL)
		i_fatal("Invalid system hostname: %s", hostname);

	/* allow calling hostpid_init() multiple times to reset hostname */
	i_free_and_null(my_domain);

	i_strocpy(pid, dec2str(getpid()), sizeof(pid));
	my_pid = pid;
}