smtp-server-cmd-xclient.c revision 2a33e0253aa28f156949d40584008a3a337d32e8
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "smtp-syntax.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "smtp-reply.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "smtp-server-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* XCLIENT command (http://www.postfix.org/XCLIENT_README.html) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainenstatic bool
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainencmd_xclient_check_state(struct smtp_server_cmd_ctx *cmd)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* http://www.postfix.org/XCLIENT_README.html:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen The XCLIENT command may be sent at any time, except in the middle
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen of a mail delivery transaction (i.e. between MAIL and DOT, or MAIL
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen and RSET). */
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen if (conn->state.trans != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen smtp_server_reply(cmd, 503, "5.5.0",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "XCLIENT not permitted during a mail transaction");
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen return FALSE;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen }
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen return TRUE;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen}
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenstatic void cmd_xclient_completed(struct smtp_server_cmd_ctx *cmd)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen{
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_connection *conn = cmd->conn;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_command *command = cmd->cmd;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_proxy_data *proxy_data =
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen (struct smtp_proxy_data *)command->data;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i_assert(smtp_server_command_is_replied(command));
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!smtp_server_command_replied_success(command)) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* failure */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* success */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_connection_reset_state(conn);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_connection_set_proxy_data(conn, proxy_data);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen}
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenstatic void cmd_xclient_recheck(struct smtp_server_cmd_ctx *cmd)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen{
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_connection *conn = cmd->conn;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* all preceeding commands have finished and now the transaction state is
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen clear. This provides the opportunity to re-check the protocol state */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!cmd_xclient_check_state(cmd))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_XCLIENT);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* succes; send greeting */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_reply(cmd, 220, NULL, "%s %s",
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen conn->set.hostname, conn->set.login_greeting);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen}
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenstatic void
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainensmtp_server_cmd_xclient_extra_field(struct smtp_server_connection *conn,
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen pool_t pool, const struct smtp_param *param,
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen ARRAY_TYPE(smtp_proxy_data_field) *fields)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen{
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_proxy_data_field *field;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (conn->set.xclient_extensions == NULL ||
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen !str_array_icase_find(conn->set.xclient_extensions, param->keyword))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!array_is_created(fields))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen p_array_init(fields, pool, 8);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen field = array_append_space(fields);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen field->name = p_strdup(pool, param->keyword);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen field->value = p_strdup(pool, param->value);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen}
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenvoid smtp_server_cmd_xclient(struct smtp_server_cmd_ctx *cmd,
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const char *params)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen{
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_connection *conn = cmd->conn;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_command *command = cmd->cmd;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const struct smtp_server_callbacks *callbacks = conn->callbacks;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_proxy_data *proxy_data;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen ARRAY_TYPE(smtp_proxy_data_field) extra_fields = ARRAY_INIT;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const char *const *argv;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value )
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | LOGIN )
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen attribute-value = xtext
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* check transaction state as far as possible */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!cmd_xclient_check_state(cmd))
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen /* check whether client is trusted */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!smtp_server_connection_is_trusted(conn)) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen smtp_server_reply(cmd, 550, "5.7.14",
659fe5d24825b160cae512538088020d97a60239Timo Sirainen "You are not from trusted IP");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data = p_new(cmd->pool, struct smtp_proxy_data, 1);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen argv = t_strsplit(params, " ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (; *argv != NULL; argv++) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen struct smtp_param param;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const char *error;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (smtp_param_parse(pool_datastack_create(), *argv,
659fe5d24825b160cae512538088020d97a60239Timo Sirainen &param, &error) < 0) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen "Invalid parameter: %s", error);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen param.keyword = t_str_ucase(param.keyword);
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (smtp_xtext_parse(param.value, &param.value, &error) < 0) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen "Invalid %s parameter: %s",
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen param.keyword, error);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen }
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (strcmp(param.keyword, "ADDR") == 0) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen bool ipv6 = FALSE;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen continue;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (strncasecmp(param.value, "IPV6:", 5) == 0) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen ipv6 = TRUE;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen param.value += 5;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen }
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (net_addr2ip(param.value, &proxy_data->source_ip) < 0 ||
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen (ipv6 && proxy_data->source_ip.family != AF_INET6)) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen "Invalid ADDR parameter");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen } else if (strcmp(param.keyword, "HELO") == 0) {
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen continue;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen if (smtp_helo_domain_parse
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen (param.value, TRUE, &proxy_data->helo) >= 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data->helo =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(cmd->pool, proxy_data->helo);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strcmp(param.keyword, "LOGIN") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data->login = p_strdup(cmd->pool, param.value);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen } else if (strcmp(param.keyword, "PORT") == 0) {
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (net_str2port(param.value, &proxy_data->source_port) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid PORT parameter");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen }
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen } else if (strcmp(param.keyword, "PROTO") == 0) {
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen param.value = t_str_ucase(param.value);
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen if (strcmp(param.value, "SMTP") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data->proto = SMTP_PROXY_PROTOCOL_SMTP;
d39c0e195c67be5f2b0a15f25a8d6039bef02711Timo Sirainen else if (strcmp(param.value, "ESMTP") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data->proto = SMTP_PROXY_PROTOCOL_ESMTP;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen else if (strcmp(param.value, "LMTP") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data->proto = SMTP_PROXY_PROTOCOL_LMTP;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid PROTO parameter");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strcmp(param.keyword, "TIMEOUT") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (str_to_uint(param.value,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &proxy_data->timeout_secs) < 0) {
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen "Invalid TIMEOUT parameter");
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen return;
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen }
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen } else if (strcmp(param.keyword, "TTL") == 0) {
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen if (str_to_uint(param.value,
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen &proxy_data->ttl_plus_1) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid TTL parameter");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen proxy_data->ttl_plus_1++;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen } else {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_cmd_xclient_extra_field(conn,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd->pool, &param, &extra_fields);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&extra_fields)) {
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen proxy_data->extra_fields = array_get(&extra_fields,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &proxy_data->extra_fields_count);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen }
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen smtp_server_command_input_lock(cmd);
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen command->data = proxy_data;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen command->hook_next = cmd_xclient_recheck;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen command->hook_completed = cmd_xclient_completed;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (conn->state.state == SMTP_SERVER_STATE_GREETING)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_XCLIENT);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen smtp_server_command_ref(command);
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen if (callbacks != NULL && callbacks->conn_cmd_xclient != NULL) {
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen /* specific implementation of XCLIENT command */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen callbacks->conn_cmd_xclient(conn->context, cmd, proxy_data);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen smtp_server_command_unref(&command);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen