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.2.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. static int xclient_rewrite = FALSE;
  30.  
  31. /* command handlers */
  32. MODRET xclient_xclient(cmd_rec *cmd)
  33. {
  34. if (xclient_engine == FALSE)
  35. return PR_DECLINED(cmd);
  36.  
  37. if (cmd->argc < 2)
  38. return PR_DECLINED(cmd);
  39.  
  40. if (strncasecmp(cmd->argv[1], "XCLIENT", 7) == 0) {
  41. if (cmd->argc < 4) {
  42. pr_response_add_err(R_501, _("Invalid number of parameters"));
  43. pr_cmd_set_errno(cmd, EINVAL);
  44. errno = EINVAL;
  45. return PR_ERROR(cmd);
  46. }
  47.  
  48. const pr_netaddr_t *remote_addr = NULL;
  49. unsigned int remote_port = 0;
  50.  
  51. for (unsigned int i = 2; i < cmd->argc; ++i) {
  52. const char *param = cmd->argv[i];
  53. pr_trace_msg(trace_channel, 5, "parsing parameter '%s'", param);
  54. if (strncasecmp(param, "ADDR=", 5) == 0) {
  55. remote_addr = pr_netaddr_get_addr2(session.pool,
  56. param + 5, NULL, PR_NETADDR_GET_ADDR_FL_EXCL_DNS);
  57. if (remote_addr == NULL) {
  58. pr_response_add_err(R_501, _("%s: Invalid IP address provided"),
  59. param + 5);
  60. pr_cmd_set_errno(cmd, EINVAL);
  61. errno = EINVAL;
  62. return PR_ERROR(cmd);
  63. }
  64. }
  65. else if (strncasecmp(param, "PORT=", 5) == 0) {
  66. char *tmp = NULL;
  67. remote_port = strtoul(param + 5, &tmp, 10);
  68. if (tmp == NULL || *tmp != '\0' || remote_port <= 0 || remote_port > 65535) {
  69. pr_response_add_err(R_501, _("%s: Invalid port provided"),
  70. param + 5);
  71. pr_cmd_set_errno(cmd, EINVAL);
  72. errno = EINVAL;
  73. return PR_ERROR(cmd);
  74. }
  75. }
  76. else {
  77. pr_response_add_err(R_500, _("'%s' not understood"), param);
  78. pr_cmd_set_errno(cmd, EINVAL);
  79. errno = EINVAL;
  80. return PR_ERROR(cmd);
  81. }
  82. }
  83.  
  84. if (remote_addr != NULL && remote_port > 0) {
  85. const char *addr = pr_netaddr_get_ipstr(remote_addr);
  86. (void) pr_table_remove(session.notes, "mod_xclient.addr", NULL);
  87. if (pr_table_add_dup(session.notes, "mod_xclient.addr", addr, 0) < 0) {
  88. pr_trace_msg(trace_channel, 3,
  89. "error stashing 'mod_xclient.addr' in session.notes: %s",
  90. strerror(errno));
  91. }
  92.  
  93. char port[6];
  94. pr_snprintf(port, sizeof(port), "%u", remote_port);
  95. (void) pr_table_remove(session.notes, "mod_xclient.port", NULL);
  96. if (pr_table_add_dup(session.notes, "mod_xclient.port", port, 0) < 0) {
  97. pr_trace_msg(trace_channel, 3,
  98. "error stashing 'mod_xclient.port' in session.notes: %s",
  99. strerror(errno));
  100. }
  101.  
  102. if (xclient_rewrite) {
  103. session.c->remote_addr = remote_addr;
  104. session.c->remote_port = remote_port;
  105.  
  106. /* now perform reverse DNS lookups */
  107. if (ServerUseReverseDNS) {
  108. int reverse_dns = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
  109. session.c->remote_name = pr_netaddr_get_dnsstr(session.c->remote_addr);
  110. pr_netaddr_set_reverse_dns(reverse_dns);
  111. }
  112. else
  113. session.c->remote_name = pr_netaddr_get_ipstr(session.c->remote_addr);
  114.  
  115. pr_netaddr_set_sess_addrs();
  116.  
  117. /* find the new class for this session */
  118. session.conn_class = pr_class_match_addr(session.c->remote_addr);
  119. }
  120.  
  121. pr_log_debug(DEBUG0, MOD_XCLIENT_VERSION
  122. ": stored%s client remote address: %s",
  123. (xclient_rewrite) ? "+rewrote" : "", addr);
  124. pr_trace_msg(trace_channel, 5, ": stored"
  125. ": stored%s client remote address: %s",
  126. (xclient_rewrite) ? "+rewrote" : "", addr);
  127. }
  128.  
  129. pr_response_add(R_200, _("SITE %s command successful"),
  130. (char *)cmd->argv[1]);
  131. return PR_HANDLED(cmd);
  132. }
  133.  
  134. return PR_DECLINED(cmd);
  135. }
  136.  
  137. /* configuration handlers */
  138. MODRET set_xclient_engine(cmd_rec *cmd)
  139. {
  140. CHECK_ARGS(cmd, 1);
  141. CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
  142.  
  143. int engine = get_boolean(cmd, 1);
  144. if (engine == -1)
  145. CONF_ERROR(cmd, "expected Boolean parameter");
  146.  
  147. config_rec *c = add_config_param(cmd->argv[0], 1, NULL);
  148. c->argv[0] = palloc(c->pool, sizeof(int));
  149. *((int *)c->argv[0]) = engine;
  150.  
  151. return PR_HANDLED(cmd);
  152. }
  153.  
  154. MODRET set_xclient_rewrite(cmd_rec *cmd)
  155. {
  156. CHECK_ARGS(cmd, 1);
  157. CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
  158.  
  159. int rewrite = get_boolean(cmd, 1);
  160. if (rewrite == -1)
  161. CONF_ERROR(cmd, "expected Boolean parameter");
  162.  
  163. config_rec *c = add_config_param(cmd->argv[0], 1, NULL);
  164. c->argv[0] = palloc(c->pool, sizeof(int));
  165. *((int *)c->argv[0]) = rewrite;
  166.  
  167. return PR_HANDLED(cmd);
  168. }
  169.  
  170. /* initialization routines */
  171. static int xclient_sess_init(void)
  172. {
  173. config_rec *c = NULL;
  174. c = find_config(main_server->conf, CONF_PARAM, "XClientEngine", FALSE);
  175. if (c != NULL)
  176. xclient_engine = *((int *)c->argv[0]);
  177.  
  178. c = find_config(main_server->conf, CONF_PARAM, "XClientRewrite", FALSE);
  179. if (c != NULL)
  180. xclient_rewrite = *((int *)c->argv[0]);
  181.  
  182. return 0;
  183. }
  184.  
  185. /* module api tables */
  186. static conftable xclient_conftab[] =
  187. {
  188. { "XClientEngine", set_xclient_engine, NULL },
  189. { "XClientRewrite", set_xclient_rewrite, NULL },
  190. { NULL }
  191. };
  192.  
  193. static cmdtable xclient_cmdtab[] =
  194. {
  195. { CMD, C_SITE, G_NONE, xclient_xclient, FALSE, FALSE, CL_MISC },
  196. { 0, NULL }
  197. };
  198.  
  199. module xclient_module =
  200. {
  201. /* always NULL */
  202. NULL, NULL,
  203.  
  204. /* module api version 2.0 */
  205. 0x20,
  206.  
  207. /* module name */
  208. "xclient",
  209.  
  210. /* module configuration handler table */
  211. xclient_conftab,
  212.  
  213. /* module command handler table */
  214. xclient_cmdtab,
  215.  
  216. /* module authentication handler table */
  217. NULL,
  218.  
  219. /* module initialization function */
  220. NULL,
  221.  
  222. /* module session initialization function */
  223. xclient_sess_init,
  224.  
  225. /* module version */
  226. MOD_XCLIENT_VERSION
  227. };
  228.