Download | Plain Text | No Line Numbers


  1. /*
  2.  * ProFTPD: mod_xclient
  3.  *
  4.  * Copyright (c) 2018 Manuel Mausz
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  */
  20.  
  21. #define MOD_XCLIENT_VERSION "mod_xclient/0.1.0"
  22.  
  23. #include "conf.h"
  24. #include "privs.h"
  25.  
  26. static const char *trace_channel = "xclient";
  27.  
  28. static int xclient_engine = FALSE;
  29.  
  30. /* command handlers */
  31. MODRET xclient_xclient(cmd_rec *cmd)
  32. {
  33. if (xclient_engine == FALSE)
  34. return PR_DECLINED(cmd);
  35.  
  36. if (cmd->argc < 2)
  37. return PR_DECLINED(cmd);
  38.  
  39. if (strncasecmp(cmd->argv[1], "XCLIENT", 7) == 0) {
  40. if (cmd->argc < 4) {
  41. pr_response_add_err(R_501, _("Invalid number of parameters"));
  42. pr_cmd_set_errno(cmd, EINVAL);
  43. errno = EINVAL;
  44. return PR_ERROR(cmd);
  45. }
  46.  
  47. const pr_netaddr_t *remote_addr = NULL;
  48. unsigned int remote_port = 0;
  49.  
  50. for (unsigned int i = 2; i < cmd->argc; ++i) {
  51. const char *param = cmd->argv[i];
  52. pr_trace_msg(trace_channel, 5, "parsing parameter '%s'", param);
  53. if (strncasecmp(param, "ADDR=", 5) == 0) {
  54. remote_addr = pr_netaddr_get_addr2(session.pool, param + 5, NULL,
  55. PR_NETADDR_GET_ADDR_FL_EXCL_DNS);
  56. if (remote_addr == NULL) {
  57. pr_response_add_err(R_501, _("%s: Invalid IP address provided"),
  58. param + 5);
  59. pr_cmd_set_errno(cmd, EINVAL);
  60. errno = EINVAL;
  61. return PR_ERROR(cmd);
  62. }
  63. }
  64. else if (strncasecmp(param, "PORT=", 5) == 0) {
  65. char *tmp = NULL;
  66. unsigned long res = strtoul(param + 5, &tmp, 10);
  67. if (tmp == NULL || *tmp != '\0' || res <= 0 || res > 65535) {
  68. pr_response_add_err(R_501, _("%s: Invalid port provided"),
  69. param + 5);
  70. pr_cmd_set_errno(cmd, EINVAL);
  71. errno = EINVAL;
  72. return PR_ERROR(cmd);
  73. }
  74.  
  75. remote_port = res;
  76. }
  77. else {
  78. pr_response_add_err(R_500, _("'%s' not understood"), param);
  79. pr_cmd_set_errno(cmd, EINVAL);
  80. errno = EINVAL;
  81. return PR_ERROR(cmd);
  82. }
  83. }
  84.  
  85. if (remote_addr != NULL && remote_port > 0) {
  86. session.c->remote_addr = remote_addr;
  87. session.c->remote_port = remote_port;
  88.  
  89. /* now perform reverse DNS lookups */
  90. if (ServerUseReverseDNS) {
  91. int reverse_dns = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
  92. session.c->remote_name = pr_netaddr_get_dnsstr(session.c->remote_addr);
  93. pr_netaddr_set_reverse_dns(reverse_dns);
  94. }
  95. else
  96. session.c->remote_name = pr_netaddr_get_ipstr(session.c->remote_addr);
  97.  
  98. pr_netaddr_set_sess_addrs();
  99.  
  100. /* find the new class for this session */
  101. session.conn_class = pr_class_match_addr(session.c->remote_addr);
  102.  
  103. pr_log_debug(DEBUG0, MOD_XCLIENT_VERSION
  104. ": new client remote address name: %s/%s",
  105. pr_netaddr_get_ipstr(pr_netaddr_get_sess_remote_addr()),
  106. pr_netaddr_get_sess_remote_name());
  107. pr_trace_msg(trace_channel, 5, ": new client remote address name: %s/%s",
  108. pr_netaddr_get_ipstr(pr_netaddr_get_sess_remote_addr()),
  109. pr_netaddr_get_sess_remote_name());
  110. }
  111.  
  112. pr_response_add(R_200, _("SITE %s command successful"),
  113. (char *)cmd->argv[1]);
  114. return PR_HANDLED(cmd);
  115. }
  116.  
  117. return PR_DECLINED(cmd);
  118. }
  119.  
  120. /* configuration handlers */
  121. MODRET set_xclient_engine(cmd_rec *cmd)
  122. {
  123. CHECK_ARGS(cmd, 1);
  124. CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
  125.  
  126. int engine = get_boolean(cmd, 1);
  127. if (engine == -1)
  128. CONF_ERROR(cmd, "expected Boolean parameter");
  129.  
  130. config_rec *c = add_config_param(cmd->argv[0], 1, NULL);
  131. c->argv[0] = palloc(c->pool, sizeof(int));
  132. *((int *)c->argv[0]) = engine;
  133.  
  134. return PR_HANDLED(cmd);
  135. }
  136.  
  137. /* initialization routines */
  138. static int xclient_sess_init(void)
  139. {
  140. config_rec *c = NULL;
  141. c = find_config(main_server->conf, CONF_PARAM, "XClientEngine", FALSE);
  142. if (c != NULL)
  143. xclient_engine = *((int *)c->argv[0]);
  144. return 0;
  145. }
  146.  
  147. /* module api tables */
  148. static conftable xclient_conftab[] =
  149. {
  150. { "XClientEngine", set_xclient_engine, NULL },
  151. { NULL }
  152. };
  153.  
  154. static cmdtable xclient_cmdtab[] =
  155. {
  156. { CMD, C_SITE, G_NONE, xclient_xclient, FALSE, FALSE, CL_MISC },
  157. { 0, NULL }
  158. };
  159.  
  160. module xclient_module =
  161. {
  162. /* always NULL */
  163. NULL, NULL,
  164.  
  165. /* module api version 2.0 */
  166. 0x20,
  167.  
  168. /* module name */
  169. "xclient",
  170.  
  171. /* module configuration handler table */
  172. xclient_conftab,
  173.  
  174. /* module command handler table */
  175. xclient_cmdtab,
  176.  
  177. /* module authentication handler table */
  178. NULL,
  179.  
  180. /* module initialization function */
  181. NULL,
  182.  
  183. /* module session initialization function */
  184. xclient_sess_init,
  185.  
  186. /* module version */
  187. MOD_XCLIENT_VERSION
  188. };
  189.