예제 #1
0
static bool client_handle_parser_error(struct imap_client *client,
				       struct imap_parser *parser)
{
	const char *msg;
	enum imap_parser_error parse_error;

	msg = imap_parser_get_error(parser, &parse_error);
	switch (parse_error) {
	case IMAP_PARSE_ERROR_NONE:
		i_unreached();
	case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
		client_send_reply(&client->common,
				  IMAP_CMD_REPLY_BYE, msg);
		client_destroy(&client->common,
			       t_strconcat("Disconnected: ", msg, NULL));
		return FALSE;
	default:
		break;
	}

	client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, msg);
	client->cmd_finished = TRUE;
	client->skip_line = TRUE;
	return TRUE;
}
예제 #2
0
static void
imap_client_notify_starttls(struct client *client,
			    bool success, const char *text)
{
	if (success)
		client_send_reply(client, IMAP_CMD_REPLY_OK, text);
	else
		client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
}
예제 #3
0
static bool client_handle_parser_error(struct imap_client *client,
				       struct imap_parser *parser)
{
	const char *msg;
	bool fatal;

	msg = imap_parser_get_error(parser, &fatal);
	if (fatal) {
		client_send_reply(&client->common,
				  IMAP_CMD_REPLY_BYE, msg);
		client_destroy(&client->common,
			       t_strconcat("Disconnected: ", msg, NULL));
		return FALSE;
	}

	client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, msg);
	client->cmd_finished = TRUE;
	client->skip_line = TRUE;
	return TRUE;
}
예제 #4
0
static int cmd_capability(struct imap_client *imap_client)
{
	struct client *client = &imap_client->common;

	/* Client is required to send CAPABILITY after STARTTLS, so the
	   capability resp-code workaround checks only pre-STARTTLS
	   CAPABILITY commands. */
	if (!client->starttls)
		imap_client->client_ignores_capability_resp_code = TRUE;
	client_send_raw(client, t_strconcat(
		"* CAPABILITY ", get_capability(client), "\r\n", NULL));
	client_send_reply(client, IMAP_CMD_REPLY_OK,
		"Pre-login capabilities listed, post-login capabilities have more.");
	return 1;
}
예제 #5
0
static void cmd_id_finish(struct imap_client *client)
{
	/* finished handling the parameters */
	if (!client->id_logged) {
		client->id_logged = TRUE;

		if (client->cmd_id->log_reply != NULL) {
			client_log(&client->common, t_strdup_printf(
				"ID sent: %s", str_c(client->cmd_id->log_reply)));
		}
	}

	client_send_raw(&client->common,
		t_strdup_printf("* ID %s\r\n",
			imap_id_reply_generate(client->set->imap_id_send)));
	client_send_reply(&client->common, IMAP_CMD_REPLY_OK, "ID completed.");
}
void imap_client_auth_result(struct client *client,
			     enum client_auth_result result,
			     const struct client_auth_reply *reply,
			     const char *text)
{
	struct imap_url url;
	string_t *referral;

	switch (result) {
	case CLIENT_AUTH_RESULT_SUCCESS:
		/* nothing to be done for IMAP */
		break;
	case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS:
	case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN:
		/* IMAP referral

		   [nologin] referral host=.. [port=..] [destuser=..]
		   [reason=..]

		   NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
		   OK [...] Logged in, but you should use this server instead.
		   .. [REFERRAL ..] (Reason from auth server)
		*/
		referral = t_str_new(128);

		memset(&url, 0, sizeof(url));
		url.userid = reply->destuser;
		url.auth_type = client->auth_mech_name;
		url.host_name = reply->host;
		if (reply->port != 143) {
			url.have_port = TRUE;
			url.port = reply->port;
		}
		str_append(referral, "REFERRAL ");
		str_append(referral, imap_url_create(&url));

		if (result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS) {
			client_send_reply_code(client, IMAP_CMD_REPLY_OK,
					       str_c(referral), text);
		} else {
			client_send_reply_code(client, IMAP_CMD_REPLY_NO,
					       str_c(referral), text);
		}
		break;
	case CLIENT_AUTH_RESULT_ABORTED:
		client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
		break;
	case CLIENT_AUTH_RESULT_AUTHFAILED_REASON:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       "ALERT", text);
		break;
	case CLIENT_AUTH_RESULT_AUTHZFAILED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_AUTHZFAILED, text);
		break;
	case CLIENT_AUTH_RESULT_TEMPFAIL:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_UNAVAILABLE, text);
		break;
	case CLIENT_AUTH_RESULT_SSL_REQUIRED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_PRIVACYREQUIRED, text);
		break;
	case CLIENT_AUTH_RESULT_AUTHFAILED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_AUTHFAILED, text);
		break;
	}
}
예제 #7
0
파일: pop3-proxy.c 프로젝트: bdraco/core
void pop3_proxy_error(struct client *client, const char *text)
{
	client_send_reply(client, POP3_CMD_REPLY_ERROR, text);
}
예제 #8
0
파일: pop3-proxy.c 프로젝트: bdraco/core
int pop3_proxy_parse_line(struct client *client, const char *line)
{
	struct pop3_client *pop3_client = (struct pop3_client *)client;
	struct ostream *output;
	enum login_proxy_ssl_flags ssl_flags;

	i_assert(!client->destroyed);

	output = login_proxy_get_ostream(client->login_proxy);
	switch (pop3_client->proxy_state) {
	case POP3_PROXY_BANNER:
		/* this is a banner */
		if (strncmp(line, "+OK", 3) != 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Remote returned invalid banner: %s",
				str_sanitize(line, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		pop3_client->proxy_xclient =
			strncmp(line+3, " [XCLIENT]", 10) == 0;

		ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
		if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
			if (proxy_send_login(pop3_client, output) < 0) {
				client_proxy_failed(client, TRUE);
				return -1;
			}
		} else {
			o_stream_nsend_str(output, "STLS\r\n");
			pop3_client->proxy_state = POP3_PROXY_STARTTLS;
		}
		return 0;
	case POP3_PROXY_STARTTLS:
		if (strncmp(line, "+OK", 3) != 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Remote STLS failed: %s",
				str_sanitize(line, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		if (login_proxy_starttls(client->login_proxy) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		/* i/ostreams changed. */
		output = login_proxy_get_ostream(client->login_proxy);
		if (proxy_send_login(pop3_client, output) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		return 1;
	case POP3_PROXY_XCLIENT:
		if (strncmp(line, "+OK", 3) != 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Remote XCLIENT failed: %s",
				str_sanitize(line, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		pop3_client->proxy_state = client->proxy_sasl_client == NULL ?
			POP3_PROXY_LOGIN1 : POP3_PROXY_LOGIN2;
		return 0;
	case POP3_PROXY_LOGIN1:
		i_assert(client->proxy_sasl_client == NULL);
		if (strncmp(line, "+OK", 3) != 0)
			break;

		/* USER successful, send PASS */
		o_stream_nsend_str(output, t_strdup_printf(
			"PASS %s\r\n", client->proxy_password));
		proxy_free_password(client);
		pop3_client->proxy_state = POP3_PROXY_LOGIN2;
		return 0;
	case POP3_PROXY_LOGIN2:
		if (strncmp(line, "+ ", 2) == 0 &&
		    client->proxy_sasl_client != NULL) {
			/* continue SASL authentication */
			if (pop3_proxy_continue_sasl_auth(client, output,
							  line+2) < 0) {
				client_proxy_failed(client, TRUE);
				return -1;
			}
			return 0;
		}
		if (strncmp(line, "+OK", 3) != 0)
			break;

		/* Login successful. Send this line to client. */
		line = t_strconcat(line, "\r\n", NULL);
		o_stream_nsend_str(client->output, line);

		client_proxy_finish_destroy_client(client);
		return 1;
	case POP3_PROXY_STATE_COUNT:
		i_unreached();
	}

	/* Login failed. Pass through the error message to client.

	   If the backend server isn't Dovecot, the error message may
	   be different from Dovecot's "user doesn't exist" error. This
	   would allow an attacker to find out what users exist in the
	   system.

	   The optimal way to handle this would be to replace the
	   backend's "password failed" error message with Dovecot's
	   AUTH_FAILED_MSG, but this would require a new setting and
	   the sysadmin to actually bother setting it properly.

	   So for now we'll just forward the error message. This
	   shouldn't be a real problem since of course everyone will
	   be using only Dovecot as their backend :) */
	if (strncmp(line, "-ERR ", 5) != 0) {
		client_send_reply(client, POP3_CMD_REPLY_ERROR,
				  AUTH_FAILED_MSG);
	} else {
		client_send_raw(client, t_strconcat(line, "\r\n", NULL));
	}

	if (client->set->auth_verbose) {
		if (strncmp(line, "-ERR ", 5) == 0)
			line += 5;
		client_proxy_log_failure(client, line);
	}
	client->proxy_auth_failed = TRUE;
	client_proxy_failed(client, FALSE);
	return -1;
}