Example #1
0
static const char *pattern_compress(const char *pattern)
{
	char *dest, *ret;

	dest = ret = t_strdup_noconst(pattern);

	/* @UNSAFE: compress the pattern */
	while (*pattern != '\0') {
		if (*pattern == '*' || *pattern == '%') {
			/* remove duplicate hierarchy wildcards */
			while (*pattern == '%') pattern++;

			/* "%*" -> "*" */
			if (*pattern == '*') {
				/* remove duplicate wildcards */
				while (*pattern == '*' || *pattern == '%')
					pattern++;
				*dest++ = '*';
			} else {
				*dest++ = '%';
			}
		} else {
			*dest++ = *pattern++;
		}
	}
	*dest = '\0';
	return ret;
}
Example #2
0
static int
openssl_iostream_use_certificate(struct ssl_iostream *ssl_io, const char *cert)
{
    BIO *in;
    X509 *x;
    int ret = 0;

    in = BIO_new_mem_buf(t_strdup_noconst(cert), strlen(cert));
    if (in == NULL) {
        i_error("BIO_new_mem_buf() failed: %s", openssl_iostream_error());
        return -1;
    }

    x = PEM_read_bio_X509(in, NULL, NULL, NULL);
    if (x != NULL) {
        ret = SSL_use_certificate(ssl_io->ssl, x);
        if (ERR_peek_error() != 0)
            ret = 0;
        X509_free(x);
    }
    BIO_free(in);

    if (ret == 0) {
        i_error("%s: Can't load ssl_cert: %s", ssl_io->source,
                ssl_iostream_get_use_certificate_error(cert));
        return -1;
    }
    return 0;
}
Example #3
0
const char *t_str_tabunescape(const char *str)
{
	if (strchr(str, '\001') == NULL)
		return str;
	else
		return str_tabunescape(t_strdup_noconst(str));
}
Example #4
0
const char *rfc2822_header_field_name_sanitize(const char *name)
{
	char *result = t_strdup_noconst(name);
	char *p;

	/* Make the whole name lower case ... */
	result = str_lcase(result);

	/* ... except for the first letter and those that follow '-' */
	p = result;
	*p = i_toupper(*p);
	while ( *p != '\0' ) {
		if ( *p == '-' ) {
			p++;

			if ( *p != '\0' )
				*p = i_toupper(*p);

			continue;
		}

		p++;
	}

	return result;
}
Example #5
0
static char *
vpopmail_password_lookup(struct auth_request *auth_request, bool *cleartext,
			 enum passdb_result *result_r)
{
	char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
	struct vqpasswd *vpw;
	char *password;

	vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
	if (vpw == NULL) {
		*result_r = PASSDB_RESULT_USER_UNKNOWN;
		return NULL;
	}

	if (vpopmail_is_disabled(auth_request, vpw)) {
		auth_request_log_info(auth_request, AUTH_SUBSYS_DB,
				      "%s disabled in vpopmail for this user",
				      auth_request->service);
		password = NULL;
		*result_r = PASSDB_RESULT_USER_DISABLED;
	} else {
		if (vpw->pw_clear_passwd != NULL &&
		    *vpw->pw_clear_passwd != '\0') {
			password = t_strdup_noconst(vpw->pw_clear_passwd);
			*cleartext = TRUE;
		} else if (!*cleartext)
			password = t_strdup_noconst(vpw->pw_passwd);
		else
			password = NULL;
		*result_r = password != NULL ? PASSDB_RESULT_OK :
			PASSDB_RESULT_SCHEME_NOT_AVAILABLE;
	}

	safe_memset(vpw->pw_passwd, 0, strlen(vpw->pw_passwd));
	if (vpw->pw_clear_passwd != NULL) {
		safe_memset(vpw->pw_clear_passwd, 0,
			    strlen(vpw->pw_clear_passwd));
	}

	return password;
}
Example #6
0
static void
bsdauth_verify_plain(struct auth_request *request, const char *password,
		    verify_plain_callback_t *callback)
{
	struct passwd pw;
	const char *type;
	int result;

	auth_request_log_debug(request, "bsdauth", "lookup");

	switch (i_getpwnam(request->user, &pw)) {
	case -1:
		auth_request_log_error(request, "bsdauth",
				       "getpwnam() failed: %m");
		callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
		return;
	case 0:
		auth_request_log_unknown_user(request, "bsdauth");
		callback(PASSDB_RESULT_USER_UNKNOWN, request);
		return;
	}

	/* check if the password is valid */
	type = t_strdup_printf("auth-%s", request->service);
	result = auth_userokay(request->user, NULL, t_strdup_noconst(type),
			       t_strdup_noconst(password));

	/* clear the passwords from memory */
	safe_memset(pw.pw_passwd, 0, strlen(pw.pw_passwd));

	if (result == 0) {
		auth_request_log_password_mismatch(request, "bsdauth");
		callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
		return;
	}

	/* make sure we're using the username exactly as it's in the database */
        auth_request_set_field(request, "user", pw.pw_name, NULL);

	callback(PASSDB_RESULT_OK, request);
}
Example #7
0
static void client_connected(struct master_service_connection *conn)
{
	enum mail_storage_service_flags flags =
		MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS;
	string_t *instr, *keys;
	const char **args, *key, *value, *error, *version_line, *data_line;
	struct mail_storage_service_ctx *service_ctx;
	struct mail_storage_service_input input;
	struct mail_storage_service_user *user;
	char buf[1024];
	unsigned int i, socket_count;
	int fd = -1;
	ssize_t ret;

	alarm(SCRIPT_LOGIN_READ_TIMEOUT_SECS);

	net_set_nonblock(conn->fd, FALSE);
	instr = t_str_new(1024);
	ret = fd_read(conn->fd, buf, sizeof(buf), &fd);
	while (ret > 0) {
		str_append_n(instr, buf, ret);
		if (buf[ret-1] == '\n' &&
		    strchr(str_c(instr), '\n')[1] != '\0') {
			str_truncate(instr, str_len(instr)-1);
			break;
		}

		ret = read(conn->fd, buf, sizeof(buf));
	}

	version_line = str_c(instr);
	data_line = strchr(version_line, '\n');
	if (data_line != NULL)
		version_line = t_strdup_until(version_line, data_line++);
	else
		version_line = NULL;

	if (ret > 0 || version_line != NULL) {
		if (version_line == NULL ||
		    !version_string_verify(version_line, "script-login",
				SCRIPT_LOGIN_PROTOCOL_VERSION_MAJOR)) {
			i_fatal("Client not compatible with this binary "
				"(connecting to wrong socket?)");
		}
	}

	if (ret <= 0) {
		if (ret < 0)
			i_fatal("read() failed: %m");
		else
			i_fatal("read() failed: disconnected");
	}
	if (fd == -1)
		i_fatal("client fd not received");

	alarm(0);

	/* put everything to environment */
	env_clean();
	keys = t_str_new(256);
	args = t_strsplit_tab(data_line);

	if (str_array_length(args) < 3)
		i_fatal("Missing input fields");

	i = 0;
	memset(&input, 0, sizeof(input));
	input.module = "mail"; /* need to get mail_uid, mail_gid */
	input.service = "script-login";
	(void)net_addr2ip(args[i++], &input.local_ip);
	(void)net_addr2ip(args[i++], &input.remote_ip);
	input.username = args[i++];
	input.userdb_fields = args + i;

	env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL));
	env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL));
	env_put(t_strconcat("USER="******"%s ", key);
		}
	}
	env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL));

	master_service_init_log(master_service,
		t_strdup_printf("script-login(%s): ", input.username));

	if (drop_to_userdb_privileges) {
		service_ctx = mail_storage_service_init(master_service, NULL, flags);
		if (mail_storage_service_lookup(service_ctx, &input, &user, &error) <= 0)
			i_fatal("%s", error);
		mail_storage_service_restrict_setenv(service_ctx, user);
		/* we can't exec anything in a chroot */
		env_remove("RESTRICT_CHROOT");
		restrict_access_by_env(getenv("HOME"), TRUE);
	}

	if (dup2(fd, STDIN_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (dup2(fd, STDOUT_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (close(fd) < 0)
		i_fatal("close() failed: %m");
	if (conn->fd != SCRIPT_COMM_FD) {
		if (dup2(conn->fd, SCRIPT_COMM_FD) < 0)
			i_fatal("dup2() failed: %m");
		if (close(conn->fd) < 0)
			i_fatal("close() failed: %m");
	}

	/* close all listener sockets */
	socket_count = master_service_get_socket_count(master_service);
	for (i = 0; i < socket_count; i++) {
		if (close(MASTER_LISTEN_FD_FIRST + i) < 0)
			i_error("close(listener) failed: %m");
	}
	if (close(MASTER_STATUS_FD) < 0)
		i_error("close(status) failed: %m");

	execvp_const(exec_args[0], exec_args);
}
Example #8
0
void doveadm_dsync_main(int *_argc, char **_argv[])
{
	int argc = *_argc;
	const char *getopt_str;
	char **argv = *_argv;
	char **new_argv, *mailbox = NULL, *alt_char = NULL, *username = NULL;
	char *p, *dup, new_flags[6];
	int max_argc, src, dest, i, j;
	bool flag_f = FALSE, flag_R = FALSE, flag_m, flag_u, flag_C, has_arg;
	bool dsync_server = FALSE;

	p = strrchr(argv[0], '/');
	if (p == NULL) p = argv[0];
	if (strstr(p, "dsync") == NULL)
		return;

	/* @UNSAFE: this is called when the "doveadm" binary is called as
	   "dsync" (for backwards compatibility) */
	max_argc = argc + 7;
	new_argv = t_new(char *, max_argc);
	new_argv[0] = argv[0];
	dest = 1;
	getopt_str = master_service_getopt_string();

	/* add global doveadm flags */
	for (src = 1; src < argc; src++) {
		if (argv[src][0] != '-')
			break;

		flag_m = FALSE; flag_C = FALSE; has_arg = FALSE; flag_u = FALSE;
		dup = t_strdup_noconst(argv[src]);
		for (i = j = 1; argv[src][i] != '\0'; i++) {
			switch (argv[src][i]) {
			case 'C':
				flag_C = TRUE;
				break;
			case 'f':
				flag_f = TRUE;
				break;
			case 'R':
				flag_R = TRUE;
				break;
			case 'm':
				flag_m = TRUE;
				break;
			case 'u':
				flag_u = TRUE;
				break;
			default:
				p = strchr(getopt_str, argv[src][i]);
				if (p != NULL && p[1] == ':')
					has_arg = TRUE;
				dup[j++] = argv[src][i];
				break;
			}
		}
		if (j > 1) {
			dup[j++] = '\0';
			new_argv[dest++] = dup;
			if (has_arg && src+1 < argc)
				new_argv[dest++] = argv[++src];
		}
		if (flag_m) {
			if (src+1 == argc)
				i_fatal("-m missing parameter");
			mailbox = argv[++src];
		}
		if (flag_u) {
			if (src+1 == argc)
				i_fatal("-u missing parameter");
			username = argv[++src];
		}
		if (flag_C) {
			if (src+1 == argc)
				i_fatal("-C missing parameter");
			alt_char = argv[++src];
		}
	}
	if (alt_char != NULL) {
		new_argv[dest++] = "-o";
		new_argv[dest++] =
			p_strconcat(pool_datastack_create(),
				    "dsync_alt_char=", alt_char, NULL);
	}

	/* mirror|backup|server */
	if (src == argc)
		i_fatal("Missing mirror or backup parameter");
	if (strcmp(argv[src], "sync") == 0 ||
	    strcmp(argv[src], "dsync-server") == 0) {
		/* we're re-executing dsync due to doveconf.
		   "backup" re-exec detection is later. */
		return;
	}
	if (strcmp(argv[src], "mirror") == 0)
		new_argv[dest] = "sync";
	else if (strcmp(argv[src], "backup") == 0)
		new_argv[dest] = "backup";
	else if (strcmp(argv[src], "server") == 0) {
		new_argv[dest] = "dsync-server";
		dsync_server = TRUE;
	} else
		i_fatal("Invalid parameter: %s", argv[src]);
	src++; dest++;

	if (src < argc && strncmp(argv[src], "-E", 2) == 0) {
		/* we're re-executing dsync due to doveconf */
		return;
	}

	/* dsync flags */
	new_flags[0] = '-';
	new_flags[1] = 'E'; i = 2;
	if (!dsync_server) {
		if (flag_f)
			new_flags[i++] = 'f';
		if (flag_R)
			new_flags[i++] = 'R';
		if (mailbox != NULL)
			new_flags[i++] = 'm';
	}
	i_assert((unsigned int)i < sizeof(new_flags));
	new_flags[i] = '\0';

	if (i > 1) {
		new_argv[dest++] = strdup(new_flags);
		if (mailbox != NULL)
			new_argv[dest++] = mailbox;
	}
	if (username != NULL) {
		new_argv[dest++] = "-u";
		new_argv[dest++] = username;
	}

	/* rest of the parameters */
	for (; src < argc; src++)
		new_argv[dest++] = argv[src];
	i_assert(dest < max_argc);
	new_argv[dest] = NULL;

	legacy_dsync = TRUE;
	*_argc = dest;
	*_argv = new_argv;
	optind = 1;
}
Example #9
0
static bool parse_digest_response(struct digest_auth_request *request,
				  const unsigned char *data, size_t size,
				  const char **error)
{
	char *copy, *key, *value;
	bool failed;

	/*
	   realm="realm"
	   username="******"
	   nonce="randomized data"
	   cnonce="??"
	   nc=00000001
	   qop="auth|auth-int|auth-conf"
	   digest-uri="serv-type/host[/serv-name]"
	   response=32 HEX digits
	   maxbuf=number (with auth-int, auth-conf, defaults to 64k)
	   charset="utf-8" (iso-8859-1 if it doesn't exist)
	   cipher="cipher-value"
	   authzid="authzid-value"
	*/

	*error = NULL;
	failed = FALSE;

	if (size == 0) {
		*error = "Client sent no input";
		return FALSE;
	}

	/* treating response as NUL-terminated string also gets rid of all
	   potential problems with NUL characters in strings. */
	copy = t_strdup_noconst(t_strndup(data, size));
	while (*copy != '\0') {
		if (parse_next(&copy, &key, &value)) {
			if (!auth_handle_response(request, key, value, error)) {
				failed = TRUE;
				break;
			}
		}

		if (*copy == ',')
			copy++;
	}

	if (!failed) {
		if (!request->nonce_found) {
			*error = "Missing nonce parameter";
			failed = TRUE;
		} else if (request->cnonce == NULL) {
			*error = "Missing cnonce parameter";
			failed = TRUE;
		} else if (request->username == NULL) {
			*error = "Missing username parameter";
			failed = TRUE;
		}
	}

	if (request->nonce_count == NULL)
		request->nonce_count = p_strdup(request->pool, "00000001");
	if (request->qop_value == NULL)
		request->qop_value = p_strdup(request->pool, "auth");

	return !failed;
}
Example #10
0
const char *t_str_ucase(const char *str)
{
	i_assert(str != NULL);

	return str_ucase(t_strdup_noconst(str));
}
Example #11
0
void test_strescape(void)
{
	static struct strinput unesc[] = {
		{ "foo", "foo" },
		{ "\\\\\\\\\\\"\\\"\\\'\\\'", "\\\\\"\"\'\'" },
		{ "\\a\\n\\r\\", "anr" }
	};
	static struct strinput tabesc[] = {
		{ "foo", "foo" },
		{ "\001", "\0011" },
		{ "\t", "\001t" },
		{ "\r", "\001r" },
		{ "\n", "\001n" },
		{ "\001\001\t\t\r\r\n\n", "\0011\0011\001t\001t\001r\001r\001n\001n" }
	};
	unsigned char buf[1 << CHAR_BIT];
	const char *escaped, *tabstr;
	string_t *str;
	unsigned int i;

	test_begin("str_escape");
	for (i = 1; i < sizeof(buf); i++)
		buf[i-1] = i;
	buf[i-1] = '\0';

	escaped = str_escape((char *)buf);
	test_assert(strlen(escaped) == (1 << CHAR_BIT) - 1 + 3);
	test_assert(escaped['\"'-1] == '\\'); /* 34 */
	test_assert(escaped['\"'] == '\"');
	test_assert(escaped['\''+1-1] == '\\'); /* 39 */
	test_assert(escaped['\''+1] == '\'');
	test_assert(escaped['\\'+2-1] == '\\'); /* 92 */
	test_assert(escaped['\\'+2] == '\\');
	test_assert(strcmp(str_escape("\\\\\"\"\'\'"),
			   "\\\\\\\\\\\"\\\"\\\'\\\'") == 0);
	test_end();

	str = t_str_new(256);
	test_begin("str_unescape");
	for (i = 0; i < N_ELEMENTS(unesc); i++) {
		test_assert(strcmp(str_unescape(t_strdup_noconst(unesc[i].input)),
				   unesc[i].output) == 0);
		str_truncate(str, 0);
		str_append_unescaped(str, unesc[i].input, strlen(unesc[i].input));
		test_assert(strcmp(str_c(str), unesc[i].output) == 0);
	}
	test_end();

	test_begin("str_tabescape");
	for (i = 0; i < N_ELEMENTS(tabesc); i++) {
		test_assert(strcmp(str_tabunescape(t_strdup_noconst(tabesc[i].output)),
				   tabesc[i].input) == 0);
		test_assert(strcmp(str_tabescape(tabesc[i].input),
				   tabesc[i].output) == 0);
		str_truncate(str, 0);
		str_append_tabunescaped(str, tabesc[i].output, strlen(tabesc[i].output));
		test_assert(strcmp(str_c(str), tabesc[i].input) == 0);
	}
	str_truncate(str, 0);
	tabstr = "\0012\001l\001";
	str_append_tabunescaped(str, tabstr, strlen(tabstr));
	test_assert(strcmp(str_c(str), "2l") == 0);
	test_assert(strcmp(str_c(str), str_tabunescape(t_strdup_noconst(tabstr))) == 0);
	test_end();
}