Download | Plain Text | Line Numbers
/*
* ProFTPD: mod_xclient
*
* Copyright (c) 2018 Manuel Mausz
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#define MOD_XCLIENT_VERSION "mod_xclient/0.1.0"
#include "conf.h"
#include "privs.h"
static const char *trace_channel = "xclient";
static int xclient_engine = FALSE;
/* command handlers */
MODRET xclient_xclient(cmd_rec *cmd)
{
if (xclient_engine == FALSE)
return PR_DECLINED(cmd);
if (cmd->argc < 2)
return PR_DECLINED(cmd);
if (strncasecmp(cmd->argv[1], "XCLIENT", 7) == 0) {
if (cmd->argc < 4) {
pr_response_add_err(R_501, _("Invalid number of parameters"));
pr_cmd_set_errno(cmd, EINVAL);
errno = EINVAL;
return PR_ERROR(cmd);
}
const pr_netaddr_t *remote_addr = NULL;
unsigned int remote_port = 0;
for (unsigned int i = 2; i < cmd->argc; ++i) {
const char *param = cmd->argv[i];
pr_trace_msg(trace_channel, 5, "parsing parameter '%s'", param);
if (strncasecmp(param, "ADDR=", 5) == 0) {
remote_addr = pr_netaddr_get_addr2(session.pool, param + 5, NULL,
PR_NETADDR_GET_ADDR_FL_EXCL_DNS);
if (remote_addr == NULL) {
pr_response_add_err(R_501, _("%s: Invalid IP address provided"),
param + 5);
pr_cmd_set_errno(cmd, EINVAL);
errno = EINVAL;
return PR_ERROR(cmd);
}
}
else if (strncasecmp(param, "PORT=", 5) == 0) {
char *tmp = NULL;
unsigned long res = strtoul(param + 5, &tmp, 10);
if (tmp == NULL || *tmp != '\0' || res <= 0 || res > 65535) {
pr_response_add_err(R_501, _("%s: Invalid port provided"),
param + 5);
pr_cmd_set_errno(cmd, EINVAL);
errno = EINVAL;
return PR_ERROR(cmd);
}
remote_port = res;
}
else {
pr_response_add_err(R_500, _("'%s' not understood"), param);
pr_cmd_set_errno(cmd, EINVAL);
errno = EINVAL;
return PR_ERROR(cmd);
}
}
if (remote_addr != NULL && remote_port > 0) {
session.c->remote_addr = remote_addr;
session.c->remote_port = remote_port;
/* now perform reverse DNS lookups */
if (ServerUseReverseDNS) {
int reverse_dns = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
session.c->remote_name = pr_netaddr_get_dnsstr(session.c->remote_addr);
pr_netaddr_set_reverse_dns(reverse_dns);
}
else
session.c->remote_name = pr_netaddr_get_ipstr(session.c->remote_addr);
pr_netaddr_set_sess_addrs();
/* find the new class for this session */
session.conn_class = pr_class_match_addr(session.c->remote_addr);
pr_log_debug(DEBUG0, MOD_XCLIENT_VERSION
": new client remote address name: %s/%s",
pr_netaddr_get_ipstr(pr_netaddr_get_sess_remote_addr()),
pr_netaddr_get_sess_remote_name());
pr_trace_msg(trace_channel, 5, ": new client remote address name: %s/%s",
pr_netaddr_get_ipstr(pr_netaddr_get_sess_remote_addr()),
pr_netaddr_get_sess_remote_name());
}
pr_response_add(R_200, _("SITE %s command successful"),
(char *)cmd->argv[1]);
return PR_HANDLED(cmd);
}
return PR_DECLINED(cmd);
}
/* configuration handlers */
MODRET set_xclient_engine(cmd_rec *cmd)
{
CHECK_ARGS(cmd, 1);
CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
int engine = get_boolean(cmd, 1);
if (engine == -1)
CONF_ERROR(cmd, "expected Boolean parameter");
config_rec *c = add_config_param(cmd->argv[0], 1, NULL);
c->argv[0] = palloc(c->pool, sizeof(int));
*((int *)c->argv[0]) = engine;
return PR_HANDLED(cmd);
}
/* initialization routines */
static int xclient_sess_init(void)
{
config_rec *c = NULL;
c = find_config(main_server->conf, CONF_PARAM, "XClientEngine", FALSE);
if (c != NULL)
xclient_engine = *((int *)c->argv[0]);
return 0;
}
/* module api tables */
static conftable xclient_conftab[] =
{
{ "XClientEngine", set_xclient_engine, NULL },
{ NULL }
};
static cmdtable xclient_cmdtab[] =
{
{ CMD, C_SITE, G_NONE, xclient_xclient, FALSE, FALSE, CL_MISC },
{ 0, NULL }
};
module xclient_module =
{
/* always NULL */
NULL, NULL,
/* module api version 2.0 */
0x20,
/* module name */
"xclient",
/* module configuration handler table */
xclient_conftab,
/* module command handler table */
xclient_cmdtab,
/* module authentication handler table */
NULL,
/* module initialization function */
NULL,
/* module session initialization function */
xclient_sess_init,
/* module version */
MOD_XCLIENT_VERSION
};