1 diff -NurpP --minimal linux/include/net/netfilter/nf_conntrack.h linux/include/net/netfilter/nf_conntrack.h
2 --- linux/include/net/netfilter/nf_conntrack.h 2007-05-30 11:57:00.000000000 +0200
3 +++ linux/include/net/netfilter/nf_conntrack.h 2007-05-30 11:58:41.000000000 +0200
4 @@ -29,6 +29,7 @@ union nf_conntrack_expect_proto {
7 /* Add protocol helper include file here */
8 +#include <linux/netfilter/nf_conntrack_rsh.h>
9 #include <linux/netfilter/nf_conntrack_ftp.h>
10 #include <linux/netfilter/nf_conntrack_pptp.h>
11 #include <linux/netfilter/nf_conntrack_h323.h>
12 @@ -39,6 +40,7 @@ union nf_conntrack_expect_proto {
13 /* per conntrack: application helper private data */
14 union nf_conntrack_help {
15 /* insert conntrack helper private data (master) here */
16 + struct nf_ct_rsh_master ct_rsh_info;
17 struct nf_ct_ftp_master ct_ftp_info;
18 struct nf_ct_pptp_master ct_pptp_info;
19 struct nf_ct_h323_master ct_h323_info;
20 diff -NurpP --minimal linux/include/linux/netfilter/nf_conntrack_rsh.h linux/include/linux/netfilter/nf_conntrack_rsh.h
21 --- linux/include/linux/netfilter/nf_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
22 +++ linux/include/linux/netfilter/nf_conntrack_rsh.h 2007-05-30 11:58:41.000000000 +0200
24 +/* RSH extension for IP connection tracking, Version 1.0
25 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
26 + * based on HW's ip_conntrack_irc.c
28 + * nf_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
30 + * This program is free software; you can redistribute it and/or
31 + * modify it under the terms of the GNU General Public License
32 + * as published by the Free Software Foundation; either version
33 + * 2 of the License, or (at your option) any later version.
35 +#ifndef _IP_CONNTRACK_RSH_H
36 +#define _IP_CONNTRACK_RSH_H
40 +/* This structure is per expected connection */
41 +struct nf_ct_rsh_expect
46 +/* This structure exists only once per master */
47 +struct nf_ct_rsh_master {
50 +#endif /* _IP_CONNTRACK_RSH_H */
52 diff -NurpP --minimal linux/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
53 --- linux/net/ipv4/netfilter/Kconfig 2007-05-30 11:57:07.000000000 +0200
54 +++ linux/net/ipv4/netfilter/Kconfig 2007-05-30 11:58:41.000000000 +0200
55 @@ -870,5 +870,28 @@ config IP_NF_MMS
56 If you want to compile it as a module, say M here and read
57 <file:Documentation/modules.txt>. If unsure, say `Y'.
59 +config NF_CONNTRACK_RSH
60 + tristate 'RSH protocol support'
61 + depends on NF_CONNTRACK
63 + The RSH connection tracker is required if the dynamic
64 + stderr "Server to Client" connection is to occur during a
65 + normal RSH session. This typically operates as follows;
67 + Client 0:1023 --> Server 514 (stream 1 - stdin/stdout)
68 + Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
70 + This connection tracker will identify new RSH sessions,
71 + extract the outbound session details, and notify netfilter
72 + of pending "related" sessions.
74 + Warning: This module could be dangerous. It is not "best
75 + practice" to use RSH, use SSH in all instances.
76 + (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
79 + If you want to compile it as a module, say M here and read
80 + <file:Documentation/modules.txt>. If unsure, say `N'.
84 diff -NurpP --minimal linux/net/netfilter/Makefile linux/net/netfilter/Makefile
85 --- linux/net/netfilter/Makefile 2007-05-30 11:57:07.000000000 +0200
86 +++ linux/net/netfilter/Makefile 2007-05-30 11:58:41.000000000 +0200
88 +obj-$(CONFIG_NF_CONNTRACK_RSH) += nf_conntrack_rsh.o
89 diff -NurpP --minimal linux/net/netfilter/nf_conntrack_rsh.c linux/net/netfilter/nf_conntrack_rsh.c
90 --- linux/net/netfilter/nf_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
91 +++ linux/net/netfilter/nf_conntrack_rsh.c 2007-05-30 11:58:41.000000000 +0200
93 +/* RSH extension for IP connection tracking, Version 1.0
94 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
95 + * based on HW's ip_conntrack_irc.c
97 + * (C) 2004,2005 by David Stes <stes@pandora.be>
98 + * Modification for Legato NetWorker range [7937-9936] instead of [0:1023]
100 + * (C) 2005 by David Stes <stes@pandora.be>
101 + * Upgrade to 2.6.13 API
103 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
105 + * This program is free software; you can redistribute it and/or
106 + * modify it under the terms of the GNU General Public License
107 + * as published by the Free Software Foundation; either version
108 + * 2 of the License, or (at your option) any later version.
110 + * Module load syntax:
111 + * insmod ip_conntrack_rsh.o range=1023,ports=port1,port2,...port<MAX_PORTS>
113 + * please give the ports of all RSH servers You wish to connect to.
114 + * If You don't specify ports, the default will be port 514
117 + * RSH blows ... you should use SSH (openssh.org) to replace it,
118 + * unfortunately I babysit some sysadmins that won't migrate
119 + * their legacy crap, in our second tier.
124 + * Some docco ripped from the net to teach me all there is to know about
125 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
128 + * I have no idea what "unix rshd man pages" these guys have .. but that
129 + * is some pretty detailed docco!
132 + * 4. Of the rsh protocol.
133 + * -----------------------
135 + * The rshd listens on TCP port #514. The following info is from the unix
138 + * "Service Request Protocol
140 + * When the rshd daemon receives a service request, it initiates the
141 + * following protocol:
143 + * 1. The rshd daemon checks the source port number for the request.
144 + * If the port number is not in the range 0 through 1023, the rshd daemon
145 + * terminates the connection.
147 + * 2. The rshd daemon reads characters from the socket up to a null byte.
148 + * The string read is interpreted as an ASCII number (base 10). If this
149 + * number is nonzero, the rshd daemon interprets it as the port number
150 + * of a secondary stream to be used as standard error. A second connection
151 + * is created to the specified port on the client host. The source port
152 + * on the local host is in the range 0 through 1023.
154 + * 3. The rshd daemon uses the source address of the initial connection
155 + * request to determine the name of the client host. If the name cannot
156 + * be determined, the rshd daemon uses the dotted decimal representation
157 + * of the client host's address.
159 + * 4. The rshd daemon retrieves the following information from the initial
162 + * * A null-terminated string of at most 16 bytes interpreted as
163 + * the user name of the user on the client host.
165 + * * A null-terminated string of at most 16 bytes interpreted as
166 + * the user name to be used on the local server host.
168 + * * Another null-terminated string interpreted as a command line
169 + * to be passed to a shell on the local server host.
171 + * 5. The rshd daemon attempts to validate the user using the following steps:
173 + * a. The rshd daemon looks up the local user name in the /etc/passwd
174 + * file and tries to switch to the home directory (using the chdir
175 + * subroutine). If either the lookup or the directory change fails,
176 + * the rshd daemon terminates the connection.
178 + * b. If the local user ID is a nonzero value, the rshd daemon searches
179 + * the /etc/hosts.equiv file to see if the name of the client
180 + * workstation is listed. If the client workstation is listed as an
181 + * equivalent host, the rshd daemon validates the user.
183 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
184 + * authenticate the user by checking the .rhosts file.
186 + * d. If either the $HOME/.rhosts authentication fails or the
187 + * client host is not an equivalent host, the rshd daemon
188 + * terminates the connection.
190 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
191 + * on the initial connection and passes the command line to the user's
192 + * local login shell. The shell then inherits the network connections
193 + * established by the rshd daemon."
198 +#include <linux/module.h>
199 +#include <linux/netfilter.h>
200 +#include <linux/ip.h>
201 +#include <net/checksum.h>
202 +#include <net/tcp.h>
204 +#include <linux/netfilter_ipv4/ip_tables.h>
205 +#include <net/netfilter/nf_conntrack_expect.h>
206 +#include <net/netfilter/nf_conntrack_helper.h>
207 +#include <linux/netfilter/nf_conntrack_rsh.h>
210 +static int range; /* defaults to = 1023 */
211 +static unsigned short rangemask; /* defaults to = 0xfc00 */
212 +static int ports[MAX_PORTS];
213 +static int ports_n_c = 0;
215 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
216 +MODULE_DESCRIPTION("RSH connection tracking module");
217 +MODULE_LICENSE("GPL");
219 +module_param(range, int, 0400);
220 +MODULE_PARM_DESC(range, "max port of reserved range (default is 1023)");
221 +module_param_array(ports, int, &ports_n_c, 0400);
222 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
225 +static DEFINE_SPINLOCK(rsh_buffer_lock);
226 +static char rsh_buffer[65535];
228 +unsigned int (*ip_nat_rsh_hook)(struct sk_buff **pskb,
229 + enum ip_conntrack_info ctinfo,
230 + unsigned int matchoff,
231 + struct nf_conntrack_expect *exp);
233 +#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
237 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
240 +#define DEBUGP(format, args...)
244 +/* FIXME: This should be in userspace. Later. */
245 +static int help(struct sk_buff **pskb,
246 + struct nf_conn *ct, enum ip_conntrack_info ctinfo)
248 + struct tcphdr _tcph, *th;
249 + char *data, *rb_ptr;
250 + int ret = NF_ACCEPT;
251 + int dir = CTINFO2DIR(ctinfo);
252 + struct nf_conntrack_expect *exp;
253 + unsigned int dataoff, datalen;
257 + /* note that "maxoctet" is used to maintain sanity (8 was the
258 + * original array size used in rshd/glibc) -- is there a
259 + * vulnerability in rshd.c in the looped port *= 10?
262 + DEBUGP("entered\n");
264 + /* bail if packet is not from RSH client */
265 + if (dir == IP_CT_DIR_REPLY) {
269 + /* Until there's been traffic both ways, don't look in packets. */
270 + if (ctinfo != IP_CT_ESTABLISHED
271 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
272 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
276 + /* Not a full tcp header? */
277 + th = skb_header_pointer(*pskb, ip_hdr(*pskb)->ihl*4,
278 + sizeof(_tcph), &_tcph);
280 + DEBUGP("rsh: skb_header_pointer null\n");
285 + dataoff = ip_hdr(*pskb)->ihl*4 + th->doff*4;
286 + if (dataoff >= (*pskb)->len) {
289 + datalen = (*pskb)->len - dataoff;
290 + spin_lock_bh(&rsh_buffer_lock);
291 + rb_ptr = skb_header_pointer(*pskb, dataoff, datalen, rsh_buffer);
292 + BUG_ON(rb_ptr == NULL);
295 + DEBUGP("rsh: find rsh stderr port datalen %u\n",datalen);
299 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
306 + if (*data < 48 || *data > 57) {
307 + DEBUGP("these aren't the packets you're looking for ..\n");
308 + ret = NF_ACCEPT; goto out;
310 + port = port * 10 + ( *data - 48 );
313 + /* dont relate sessions that try to expose the client */
315 + DEBUGP("skipping, port is 0!\n");
316 + ret = NF_ACCEPT;goto out;
319 + DEBUGP("found port %u\n", port);
320 + if (port > range) {
321 + DEBUGP("skipping, expected port size is greater than range!\n");
325 + exp = nf_ct_expect_alloc(ct);
331 + /* new(,related) connection is;
332 + * reply + dst (uint)port + src port (0:1023)
335 + /* Watch out, Radioactive-Man! */
336 + exp->tuple.src.u3.ip = ct->tuplehash[!dir].tuple.src.u3.ip;
337 + exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
338 + exp->tuple.src.u.tcp.port = 0;
339 + exp->tuple.dst.u.tcp.port = htons(port);
340 + exp->tuple.dst.protonum = IPPROTO_TCP;
342 + exp->mask.src.u3.ip = 0xffffffff;
344 + exp->mask.src.u.tcp.port = htons(rangemask);
346 + exp->expectfn = NULL;
349 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
350 + NIPQUAD(exp->tuple.src.ip),
351 + ntohs(exp->tuple.src.u.tcp.port),
352 + NIPQUAD(exp->tuple.dst.ip),
353 + ntohs(exp->tuple.dst.u.tcp.port));
355 + if (ip_nat_rsh_hook)
356 + ret = ip_nat_rsh_hook(pskb, ctinfo, rb_ptr - data, exp);
357 + else if (nf_ct_expect_related(exp) != 0) {
361 + nf_ct_expect_put(exp);
364 + spin_unlock_bh(&rsh_buffer_lock);
368 +static struct nf_conntrack_helper rsh_helpers[MAX_PORTS];
369 +static char rsh_names[MAX_PORTS][10];
370 +static const struct nf_conntrack_expect_policy rsh_exp_policy = {
372 + .timeout = 5, /* stes bug timeout=0 */
375 +static void fini(void);
377 +static int __init init(void)
382 + /* If no port given, default to standard RSH port */
384 + ports[0] = RSH_PORT;
386 + /* the check on reserved port <1023 doesn't work with Legato */
387 + /* for Legato NetWorker, the check should be that port <= 9936 */
392 + /* Legato uses range [ 7937 : 9936 ] -> 7937 by default */
394 + rangemask = 0xffff ^ range; /* defaults to = 0xfc00 */
396 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
397 + memset(&rsh_helpers[port], 0, sizeof(struct nf_conntrack_helper));
399 + tmpname = &rsh_names[port][0];
400 + if (ports[port] == RSH_PORT)
401 + sprintf(tmpname, "rsh");
403 + sprintf(tmpname, "rsh-%d", ports[port]);
404 + rsh_helpers[port].name = tmpname;
406 + rsh_helpers[port].me = THIS_MODULE;
407 + rsh_helpers[port].expect_policy = &rsh_exp_policy;
409 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
411 + /* RSH must come from ports 0:1023 to ports[port] (514) */
412 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
414 + rsh_helpers[port].help = help;
416 + PRINTK("registering helper for port #%d: %d/TCP\n", port, ports[port]);
417 + PRINTK("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
418 + NIPQUAD(rsh_helpers[port].tuple.src.u3.ip),
419 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
420 + NIPQUAD(rsh_helpers[port].tuple.dst.u3.ip),
421 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
423 + ret = nf_conntrack_helper_register(&rsh_helpers[port]);
426 + printk("ERROR registering port %d\n",
436 +/* This function is intentionally _NOT_ defined as __exit, because
437 + * it is needed by the init function */
438 +static void fini(void)
441 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
442 + DEBUGP("unregistering port %d\n", ports[port]);
443 + nf_conntrack_helper_unregister(&rsh_helpers[port]);