smtp-server-cmd-xclient.c revision 2a33e0253aa28f156949d40584008a3a337d32e8
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* XCLIENT command (http://www.postfix.org/XCLIENT_README.html) */
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainencmd_xclient_check_state(struct smtp_server_cmd_ctx *cmd)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* http://www.postfix.org/XCLIENT_README.html:
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). */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "XCLIENT not permitted during a mail transaction");
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenstatic void cmd_xclient_completed(struct smtp_server_cmd_ctx *cmd)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_connection *conn = cmd->conn;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_command *command = cmd->cmd;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i_assert(smtp_server_command_is_replied(command));
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!smtp_server_command_replied_success(command)) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* failure */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* success */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen smtp_server_connection_set_proxy_data(conn, proxy_data);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenstatic void cmd_xclient_recheck(struct smtp_server_cmd_ctx *cmd)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen struct smtp_server_connection *conn = cmd->conn;
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 smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_XCLIENT);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* succes; send greeting */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen conn->set.hostname, conn->set.login_greeting);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainensmtp_server_cmd_xclient_extra_field(struct smtp_server_connection *conn,
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen !str_array_icase_find(conn->set.xclient_extensions, param->keyword))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenvoid smtp_server_cmd_xclient(struct smtp_server_cmd_ctx *cmd,
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 ARRAY_TYPE(smtp_proxy_data_field) extra_fields = ARRAY_INIT;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const char *const *argv;
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 /* check transaction state as far as possible */
659fe5d24825b160cae512538088020d97a60239Timo Sirainen /* check whether client is trusted */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (!smtp_server_connection_is_trusted(conn)) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen "You are not from trusted IP");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data = p_new(cmd->pool, struct smtp_proxy_data, 1);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (smtp_param_parse(pool_datastack_create(), *argv,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (smtp_xtext_parse(param.value, ¶m.value, &error) < 0) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen "Invalid %s parameter: %s",
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (strncasecmp(param.value, "IPV6:", 5) == 0) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (net_addr2ip(param.value, &proxy_data->source_ip) < 0 ||
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen (ipv6 && proxy_data->source_ip.family != AF_INET6)) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen "Invalid ADDR parameter");
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen } else if (strcmp(param.keyword, "HELO") == 0) {
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strcmp(param.keyword, "LOGIN") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcasecmp(param.value, "[UNAVAILABLE]") == 0)
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)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (net_str2port(param.value, &proxy_data->source_port) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid PORT parameter");
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen } else if (strcmp(param.keyword, "PROTO") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_data->proto = SMTP_PROXY_PROTOCOL_ESMTP;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid PROTO parameter");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strcmp(param.keyword, "TIMEOUT") == 0) {
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen "Invalid TIMEOUT parameter");
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen } else if (strcmp(param.keyword, "TTL") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid TTL parameter");
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen proxy_data->extra_fields = array_get(&extra_fields,
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);
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen if (callbacks != NULL && callbacks->conn_cmd_xclient != NULL) {
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen /* specific implementation of XCLIENT command */