Exemplo n.º 1
0
struct sieve_binary *sieve_compile_script
(struct sieve_script *script, struct sieve_error_handler *ehandler,
	enum sieve_compile_flags flags, enum sieve_error *error_r)
{
	struct sieve_ast *ast;
	struct sieve_binary *sbin;
	enum sieve_error error, *errorp;

	if ( error_r != NULL )
		errorp = error_r;
	else
		errorp = &error;
	*errorp = SIEVE_ERROR_NONE;

	/* Parse */
	if ( (ast = sieve_parse(script, ehandler, errorp)) == NULL ) {
		switch ( *errorp ) {
		case SIEVE_ERROR_NOT_FOUND:
			if (error_r == NULL) {
				sieve_error(ehandler, sieve_script_name(script),
					"script not found");
			}
			break;
		default:
			sieve_error(ehandler, sieve_script_name(script),
				"parse failed");
		}
		return NULL;
	}

	/* Validate */
	if ( !sieve_validate(ast, ehandler, flags, errorp) ) {
		sieve_error(ehandler, sieve_script_name(script),
			"validation failed");

 		sieve_ast_unref(&ast);
 		return NULL;
 	}

	/* Generate */
	if ( (sbin=sieve_generate(ast, ehandler, flags, errorp)) == NULL ) {
		sieve_error(ehandler, sieve_script_name(script),
			"code generation failed");
		sieve_ast_unref(&ast);
		return NULL;
	}

	/* Cleanup */
	sieve_ast_unref(&ast);
	return sbin;
}
Exemplo n.º 2
0
static gint sieve_auth(SieveSession *session)
{
	SieveAuthType forced_auth_type = session->forced_auth_type;

	if (!session->use_auth) {
		session->state = SIEVE_READY;
		sieve_connected(session, TRUE);
		return SE_OK;
	}

	session->state = SIEVE_AUTH;
	sieve_error(session, _("Authenticating..."));

	if ((forced_auth_type == SIEVEAUTH_CRAM_MD5 || forced_auth_type == 0) &&
	     (session->avail_auth_type & SIEVEAUTH_CRAM_MD5) != 0)
		return sieve_auth_cram_md5(session);
	else if ((forced_auth_type == SIEVEAUTH_LOGIN || forced_auth_type == 0) &&
		  (session->avail_auth_type & SIEVEAUTH_LOGIN) != 0)
		return sieve_auth_login(session);
	else if ((forced_auth_type == SIEVEAUTH_PLAIN || forced_auth_type == 0) &&
		  (session->avail_auth_type & SIEVEAUTH_PLAIN) != 0)
		return sieve_auth_plain(session);
	else if (forced_auth_type == 0) {
		log_warning(LOG_PROTOCOL, _("No Sieve auth method available\n"));
		session->state = SIEVE_RETRY_AUTH;
		return SE_AUTHFAIL;
	} else {
		log_warning(LOG_PROTOCOL, _("Selected Sieve auth method not available\n"));
		session->state = SIEVE_RETRY_AUTH;
		return SE_AUTHFAIL;
	}

	return SE_OK;
}
Exemplo n.º 3
0
struct sieve_binary *sieve_open
(struct sieve_instance *svinst, const char *script_location,
	const char *script_name, struct sieve_error_handler *ehandler,
	enum sieve_compile_flags flags, enum sieve_error *error_r)
{
	struct sieve_script *script;
	struct sieve_binary *sbin;
	enum sieve_error error;

	/* First open the scriptfile itself */
	if ( (script=sieve_script_create_open
		(svinst, script_location, script_name, &error)) == NULL ) {
		/* Failed */
		if (error_r != NULL)
			*error_r = error;
		switch ( error ) {
		case SIEVE_ERROR_NOT_FOUND:
			sieve_error(ehandler, script_name, "script not found");
			break;
		default:
			sieve_internal_error(ehandler, script_name, "failed to open script");
		}
		return NULL;
	}

	sbin = sieve_open_script(script, ehandler, flags, error_r);

	/* Drop script reference, if sbin != NULL it holds a reference of its own.
	 * Otherwise the script object is freed here.
	 */
	sieve_script_unref(&script);

	return sbin;
}
Exemplo n.º 4
0
struct sieve_binary *sieve_compile
(struct sieve_instance *svinst, const char *script_location,
	const char *script_name, struct sieve_error_handler *ehandler,
	enum sieve_compile_flags flags, enum sieve_error *error_r)
{
	struct sieve_script *script;
	struct sieve_binary *sbin;
	enum sieve_error error;

	if ( (script = sieve_script_create_open
		(svinst, script_location, script_name, &error)) == NULL ) {
		if (error_r != NULL)
			*error_r = error;
		switch ( error ) {
		case SIEVE_ERROR_NOT_FOUND:
			sieve_error(ehandler, script_name, "script not found");
			break;
		default:
			sieve_internal_error(ehandler, script_name, "failed to open script");
		}
		return NULL;
	}

	sbin = sieve_compile_script(script, ehandler, flags, error_r);

	if ( svinst->debug && sbin != NULL ) {
		sieve_sys_debug(svinst, "Script `%s' from %s successfully compiled",
			sieve_script_name(script), sieve_script_location(script));
	}

	sieve_script_unref(&script);

	return sbin;
}
Exemplo n.º 5
0
static void sieve_read_chunk(SieveSession *session, gchar *data, guint len)
{
	log_print(LOG_PROTOCOL, "Sieve< [%u bytes]\n", len);

	switch (session->state) {
	case SIEVE_GETSCRIPT_DATA:
		command_cb(session->current_cmd, (gchar *)data);
		break;
	case SIEVE_SETACTIVE:
		/* Dovecot shows a script's warnings when making it active */
		/* TODO: append message in case it is very long*/
		strretchomp(data);
		sieve_error(session, data);
		break;
	case SIEVE_PUTSCRIPT: {
		SieveResult result = {.description = (gchar *)data};
		sieve_session_putscript_cb(session, &result);
		break;
	}
	default:
		log_warning(LOG_PROTOCOL,
				_("error occurred on SIEVE session\n"));
	}
}

static gint sieve_read_chunk_done(SieveSession *session)
{
	gint ret = SE_OK;

	switch (session->state) {
	case SIEVE_GETSCRIPT_DATA:
		/* wait for ending "OK" response */
		break;
	case SIEVE_SETACTIVE:
	case SIEVE_PUTSCRIPT:
		session->state = SIEVE_READY;
		break;
	default:
		log_warning(LOG_PROTOCOL,
				_("error occurred on SIEVE session\n"));
	}

	if (ret == SE_OK && session->state == SIEVE_READY)
		ret = sieve_pop_send_queue(session);

	if (ret == SE_OK)
		return session_recv_msg(SESSION(session));

	return 0;
}
Exemplo n.º 6
0
static void sieve_queue_send(SieveSession *session, SieveState next_state,
		gchar *msg, sieve_session_data_cb_fn cb, gpointer data)
{
	gboolean queue = FALSE;
	SieveCommand *cmd = g_new0(SieveCommand, 1);
	cmd->session = session;
	cmd->next_state = next_state;
	cmd->msg = msg;
	cmd->data = data;
	cmd->cb = cb;

	if (!session_is_connected(SESSION(session))) {
		log_print(LOG_PROTOCOL, "Sieve: connecting to %s:%hu\n",
				session->host, session->port);
		if (sieve_session_connect(session) < 0) {
			sieve_connect_finished(SESSION(session), FALSE);
		}
		queue = TRUE;
	} else if (session->state == SIEVE_RETRY_AUTH) {
		log_print(LOG_PROTOCOL, _("Sieve: retrying auth\n"));
		if (sieve_auth(session) == SE_AUTHFAIL)
			sieve_error(session, _("Auth method not available"));
		queue = TRUE;
	} else if (session->state != SIEVE_READY) {
		log_print(LOG_PROTOCOL, "Sieve: in state %d\n", session->state);
		queue = TRUE;
	}

	if (queue) {
		session->send_queue = g_slist_prepend(session->send_queue, cmd);
	} else {
		if (session->current_cmd)
			command_free(session->current_cmd);
		session->current_cmd = cmd;
		session->state = next_state;
		log_send(session, cmd);
		if (session_send_msg(SESSION(session), SESSION_SEND, cmd->msg) < 0) {
			/* error */
		}
	}
}
Exemplo n.º 7
0
static gint sieve_session_recv_msg(Session *session, const gchar *msg)
{
	SieveSession *sieve_session = SIEVE_SESSION(session);
	SieveResult result;
	gint ret = SE_OK;

	log_print(LOG_PROTOCOL, "Sieve< %s\n", msg);
	if (response_is_bye(msg)) {
		gchar *status;
		parse_response((gchar *)msg, &result);
		if (!result.description)
			status = g_strdup(_("Disconnected"));
		else if (g_str_has_prefix(result.description, "Disconnected"))
			status = g_strdup(result.description);
		else
			status = g_strdup_printf(_("Disconnected: %s"), result.description);
		sieve_session->error = SE_ERROR;
		sieve_error(sieve_session, status);
		sieve_session->state = SIEVE_DISCONNECTED;
		g_free(status);
		return -1;
	}

	switch (sieve_session->state) {
	case SIEVE_CAPABILITIES:
		if (response_is_ok(msg)) {
			/* capabilities list done */

#ifdef USE_GNUTLS
			if (sieve_session->tls_init_done == FALSE &&
					sieve_session->config->tls_type != SIEVE_TLS_NO) {
				if (sieve_session->capability.starttls) {
					log_print(LOG_PROTOCOL, "Sieve> STARTTLS\n");
					session_send_msg(session, SESSION_SEND, "STARTTLS");
					sieve_session->state = SIEVE_STARTTLS;
				} else if (sieve_session->config->tls_type == SIEVE_TLS_YES) {
					log_warning(LOG_PROTOCOL, "Sieve: does not support STARTTLS\n");
					sieve_session->state = SIEVE_ERROR;
				} else {
					log_warning(LOG_PROTOCOL, "Sieve: continuing without TLS\n");
					sieve_session->state = SIEVE_READY;
				}
				break;
			}
#endif
			/* authenticate after getting capabilities */
			if (!sieve_session->authenticated) {
				ret = sieve_auth(sieve_session);
			} else {
				sieve_session->state = SIEVE_READY;
				sieve_connected(sieve_session, TRUE);
			}
		} else {
			/* got a capability */
			gchar *cap_name, *cap_value;
			parse_split((gchar *)msg, &cap_name, &cap_value);
			sieve_got_capability(sieve_session, cap_name, cap_value);
		}
		break;
	case SIEVE_READY:
		if (!msg[0])
			break;
		log_warning(LOG_PROTOCOL,
				_("unhandled message on Sieve session: %s\n"), msg);
		break;
	case SIEVE_STARTTLS:
#ifdef USE_GNUTLS
		if (session_start_tls(session) < 0) {
			sieve_session->state = SIEVE_ERROR;
			sieve_session->error = SE_ERROR;
			sieve_error(sieve_session, _("TLS failed"));
			return -1;
		}
		sieve_session->tls_init_done = TRUE;
		sieve_session->state = SIEVE_CAPABILITIES;
#endif
		break;
	case SIEVE_AUTH:
		ret = sieve_auth_recv(sieve_session, msg);
		break;
	case SIEVE_AUTH_LOGIN_USER:
		ret = sieve_auth_login_user_recv(sieve_session, msg);
		break;
	case SIEVE_AUTH_PLAIN:
	case SIEVE_AUTH_LOGIN_PASS:
	case SIEVE_AUTH_CRAM_MD5:
		if (response_is_no(msg)) {
			log_print(LOG_PROTOCOL, "Sieve auth failed\n");
			session->state = SIEVE_RETRY_AUTH;
			ret = SE_AUTHFAIL;
		} else if (response_is_ok(msg)) {
			log_print(LOG_PROTOCOL, "Sieve auth completed\n");
			sieve_error(sieve_session, "");
			sieve_session->authenticated = TRUE;
			sieve_session->state = SIEVE_READY;
			sieve_connected(sieve_session, TRUE);
		}
		break;
	case SIEVE_NOOP:
		if (!response_is_ok(msg)) {
			sieve_session->state = SIEVE_ERROR;
		}
		sieve_session->state = SIEVE_READY;
		break;
	case SIEVE_LISTSCRIPTS:
		if (response_is_no(msg)) {
			/* got an error. probably not authenticated. */
			command_cb(sieve_session->current_cmd, NULL);
			sieve_session->state = SIEVE_READY;
		} else if (response_is_ok(msg)) {
			/* end of list */
			sieve_session->state = SIEVE_READY;
			sieve_session->error = SE_OK;
			command_cb(sieve_session->current_cmd,
					(gpointer)&(SieveScript){0});
		} else {
			/* got a script name */
			SieveScript script;
			gchar *script_status;

			parse_split((gchar *)msg, &script.name, &script_status);
			script.active = (script_status &&
					strcasecmp(script_status, "active") == 0);

			command_cb(sieve_session->current_cmd,
					(gpointer)&script);
		}
		break;
	case SIEVE_RENAMESCRIPT:
		if (response_is_no(msg)) {
			/* error */
			command_cb(sieve_session->current_cmd, NULL);
		} else if (response_is_ok(msg)) {
			command_cb(sieve_session->current_cmd, (void*)TRUE);
		} else {
			log_warning(LOG_PROTOCOL, _("error occurred on SIEVE session\n"));
		}
		sieve_session->state = SIEVE_READY;
		break;
	case SIEVE_SETACTIVE:
		parse_response((gchar *)msg, &result);
		if (result.success) {
			/* clear status possibly set when setting another
			 * script active. TODO: give textual feedback */
			sieve_error(sieve_session, "");

			command_cb(sieve_session->current_cmd, NULL);
		} else if (result.description) {
			command_cb(sieve_session->current_cmd,
					result.description);
		} else {
			log_warning(LOG_PROTOCOL, _("error occurred on SIEVE session\n"));
		}
		if (result.has_octets) {
			return sieve_session_recv_chunk(sieve_session,
					result.octets);
		} else {
			sieve_session->state = SIEVE_READY;
		}
		break;
	case SIEVE_GETSCRIPT:
		if (response_is_no(msg)) {
			command_cb(sieve_session->current_cmd, (void *)-1);
			sieve_session->state = SIEVE_READY;
		} else {
			parse_response((gchar *)msg, &result);
			sieve_session->state = SIEVE_GETSCRIPT_DATA;
			return sieve_session_recv_chunk(sieve_session,
					result.octets);
		}
		break;
	case SIEVE_GETSCRIPT_DATA:
		if (!msg[0])
			break;
		sieve_session->state = SIEVE_READY;
		if (response_is_ok(msg)) {
			command_cb(sieve_session->current_cmd, NULL);
		} else if (msg[0]) {
			log_warning(LOG_PROTOCOL, _("error occurred on SIEVE session\n"));
		}
		break;
	case SIEVE_PUTSCRIPT:
		if (!msg[0])
			break;
		parse_response((gchar *)msg, &result);
		sieve_session_putscript_cb(sieve_session, &result);
		if (result.has_octets) {
			return sieve_session_recv_chunk(sieve_session,
					result.octets);
		} else {
			sieve_session->state = SIEVE_READY;
		}
		break;
	case SIEVE_DELETESCRIPT:
		parse_response((gchar *)msg, &result);
		if (!result.success) {
			command_cb(sieve_session->current_cmd,
					result.description);
		} else {
			command_cb(sieve_session->current_cmd, NULL);
		}
		sieve_session->state = SIEVE_READY;
		break;
	case SIEVE_ERROR:
		log_warning(LOG_PROTOCOL, _("error occurred on Sieve session. data: %s\n"), msg);
		sieve_session->error = SE_ERROR;
		break;
	case SIEVE_RETRY_AUTH:
		log_warning(LOG_PROTOCOL, _("unhandled message on Sieve session: %s\n"),
					msg);
		ret = sieve_auth(sieve_session);
		break;
	default:
		log_warning(LOG_PROTOCOL, _("unhandled message on Sieve session: %d\n"),
					sieve_session->state);
		sieve_session->error = SE_ERROR;
		return -1;
	}

	if (ret == SE_OK && sieve_session->state == SIEVE_READY)
		ret = sieve_pop_send_queue(sieve_session);

	if (ret == SE_OK) {
		return session_recv_msg(session);
	} else if (ret == SE_AUTHFAIL) {
		sieve_error(sieve_session, _("Auth failed"));
		sieve_session->state = SIEVE_ERROR;
		sieve_session->error = SE_ERROR;
	}

	return 0;
}