]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-pom-ng-rpc.patch
- up to 3.5.4; updated vserver patch; hack for rpm 5.3; rpm want's patch50000 even...
[packages/kernel.git] / kernel-pom-ng-rpc.patch
CommitLineData
2380c486
JR
1diff -Nur --exclude '*.orig' linux/include/linux/netfilter/nf_conntrack_rpc.h linux/include/linux/netfilter/nf_conntrack_rpc.h
2--- linux/include/linux/netfilter/nf_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
3+++ linux/include/linux/netfilter/nf_conntrack_rpc.h 2006-05-04 11:26:08.000000000 +0200
0c5527e5 4@@ -0,0 +1,76 @@
2380c486
JR
5+/* RPC extension for IP connection tracking, Version 2.2
6+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
7+ * - original rpc tracking module
8+ * - "recent" connection handling for kernel 2.3+ netfilter
9+ *
10+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
11+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
12+ *
13+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
14+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
15+ * - extended matching to support filtering on procedures
16+ *
17+ * (C) 2005 by David Stes <stes@pandora.be>
18+ * - upgraded to 2.6.13 API
19+ *
20+ * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
21+ *
22+ * This program is free software; you can redistribute it and/or
23+ * modify it under the terms of the GNU General Public License
24+ * as published by the Free Software Foundation; either version
25+ * 2 of the License, or (at your option) any later version.
26+ **
27+ */
28+
29+#include <asm/param.h>
30+#include <linux/sched.h>
31+#include <linux/timer.h>
32+#include <linux/stddef.h>
33+#include <linux/list.h>
34+
35+#include <net/netfilter/nf_conntrack_helper.h>
36+
37+#ifndef _IP_CONNTRACK_RPC_H
38+#define _IP_CONNTRACK_RPC_H
39+
40+#define RPC_PORT 111
41+
42+
43+/* Datum in RPC packets are encoded in XDR */
44+#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
45+
46+/* Fast timeout, to deny DoS atacks */
47+#define EXP (60 * HZ)
48+
49+/* Normal timeouts */
50+#define EXPIRES (180 * HZ)
51+
52+/* For future conections RPC, using client's cache bindings
53+ * I'll use ip_conntrack_lock to lock these lists */
54+
55+/* This identifies each request and stores protocol */
56+struct request_p {
57+ struct list_head list;
58+
59+ u_int32_t xid;
60+ u_int32_t ip;
61+ u_int16_t port;
62+
63+ /* Protocol */
64+ u_int16_t proto;
65+
66+ struct timer_list timeout;
67+};
68+
69+static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
70+ u_int32_t ip, u_int32_t port) {
71+ return (p->xid == xid && p->ip == ip && p->port);
72+
73+}
0c5527e5
AM
74+#define NIPQUAD(addr) \
75+ ((unsigned char *)&addr)[0], \
76+ ((unsigned char *)&addr)[1], \
77+ ((unsigned char *)&addr)[2], \
78+ ((unsigned char *)&addr)[3]
2380c486
JR
79+
80+#endif /* _IP_CONNTRACK_RPC_H */
81diff -Nur --exclude '*.orig' linux/include/linux/netfilter_ipv4/ipt_rpc.h linux/include/linux/netfilter_ipv4/ipt_rpc.h
82--- linux/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
83+++ linux/include/linux/netfilter_ipv4/ipt_rpc.h 2006-05-04 11:26:08.000000000 +0200
84@@ -0,0 +1,35 @@
85+/* RPC extension for IP netfilter matching, Version 2.2
86+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
87+ * - original rpc tracking module
88+ * - "recent" connection handling for kernel 2.3+ netfilter
89+ *
90+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
91+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
92+ *
93+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
94+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
95+ * - extended matching to support filtering on procedures
96+ *
97+ * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
98+ *
99+ * This program is free software; you can redistribute it and/or
100+ * modify it under the terms of the GNU General Public License
101+ * as published by the Free Software Foundation; either version
102+ * 2 of the License, or (at your option) any later version.
103+ **
104+ */
105+
106+#ifndef _IPT_RPC_H
107+#define _IPT_RPC_H
108+
109+struct ipt_rpc_data;
110+
111+struct ipt_rpc_info {
112+ int inverse;
113+ int strict;
114+ const char c_procs[1408];
115+ int i_procs;
116+ struct ipt_rpc_data *data;
117+};
118+
119+#endif /* _IPT_RPC_H */
120diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
121--- linux/net/ipv4/netfilter/Kconfig 2006-05-02 23:38:44.000000000 +0200
122+++ linux/net/ipv4/netfilter/Kconfig 2006-05-04 11:26:08.000000000 +0200
123@@ -606,5 +606,37 @@
124 Allows altering the ARP packet payload: source and destination
125 hardware and network addresses.
126
127+config IP_NF_MATCH_RPC
128+ tristate 'RPC match support'
129+ depends on NF_CONNTRACK && IP_NF_IPTABLES
130+ help
131+ This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
132+ matcher and tracker.
133+
134+ This option supplies two connection tracking modules;
135+ ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
136+ portmapper requests using UDP and TCP respectively.
137+
138+ This option also adds an RPC match module for iptables, which
139+ matches both via the old "record match" method and a new
140+ "procedure match" method. The older method matches all RPC
141+ procedure packets that relate to previously recorded packets
142+ seen querying a portmapper. The newer method matches only
143+ those RPC procedure packets explicitly specified by the user,
144+ and that can then be related to previously recorded packets
145+ seen querying a portmapper.
146+
147+ These three modules are required if RPCs are to be filtered
148+ accurately; as RPCs are allocated pseudo-randomly to UDP and
149+ TCP ports as they register with the portmapper.
150+
151+ Up to 8 portmapper ports per module, and up to 128 RPC
152+ procedures per iptables rule, may be specified by the user,
153+ to enable effective RPC management.
154+
155+
156+ If you want to compile it as a module, say M here and read
157+ <file:Documentation/modules.txt>. If unsure, say `N'.
158+
159 endmenu
160
5d3a3ea2
AM
161--- a/net/ipv4/netfilter/Makefile~ 2012-09-15 09:52:33.000000000 +0200
162+++ b/net/ipv4/netfilter/Makefile 2012-09-15 09:52:54.377311767 +0200
163@@ -1,4 +1,5 @@
164 obj-$(CONFIG_NF_NAT_MMS) += nf_nat_mms.o
2380c486 165+obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
5d3a3ea2
AM
166 #
167 # Makefile for the netfilter modules on top of IPv4.
168 #
2380c486
JR
169diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
170--- linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
171+++ linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2007-08-15 03:04:53.000000000 +0200
172@@ -0,0 +1,557 @@
173+/* RPC extension for IP (TCP) connection tracking, Version 2.2
174+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
175+ * - original rpc tracking module
176+ * - "recent" connection handling for kernel 2.3+ netfilter
177+ *
178+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
179+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
180+ *
181+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
182+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
183+ * - extended matching to support filtering on procedures
184+ *
185+ * (c) 2004,2005 by David Stes <stes@pandora.be>
186+ * - add nsrexec option for Legato NetWorker
187+ * - upgraded to 2.6.12+ conntrack module api
188+ *
189+ * (c) 2005 by David Stes <stes@pandora.be>
190+ * - upgraded to 2.6.13 conntrack module api
191+ *
192+ * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
193+ *
194+ * This program is free software; you can redistribute it and/or
195+ * modify it under the terms of the GNU General Public License
196+ * as published by the Free Software Foundation; either version
197+ * 2 of the License, or (at your option) any later version.
198+ **
199+ * Module load syntax:
200+ * insmod ip_conntrack_rpc_tcp.o nsrexec=<n> ports=port1,...port<MAX_PORTS>
201+ *
202+ * Please give the ports of all RPC servers you wish to connect to.
203+ * For example, ports=111,7938 for Legato NetWorker's portmapper on 7938.
204+ * If you don't specify ports, the default will be port 111 (SUN portmap).
205+ *
206+ * Please specify nsrexec, the TCP port of the rexec() service of
207+ * Legato NetWorker. For example, nsrexec=7937
208+ *
209+ **
210+ * Note to all:
211+ *
212+ * RPCs should not be exposed to the internet - ask the Pentagon;
213+ *
214+ * "The unidentified crackers pleaded guilty in July to charges
215+ * of juvenile delinquency stemming from a string of Pentagon
216+ * network intrusions in February.
217+ *
218+ * The youths, going by the names TooShort and Makaveli, used
219+ * a common server security hole to break in, according to
220+ * Dane Jasper, owner of the California Internet service
221+ * provider, Sonic. They used the hole, known as the 'statd'
222+ * exploit, to attempt more than 800 break-ins, Jasper said."
223+ *
224+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
225+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
226+ **
227+ */
228+
229+#include <linux/module.h>
230+#include <linux/netfilter.h>
231+#include <linux/ip.h>
232+#include <net/checksum.h>
233+#include <net/tcp.h>
234+
235+#include <asm/param.h>
236+#include <linux/sched.h>
237+#include <linux/timer.h>
238+#include <linux/stddef.h>
239+#include <linux/list.h>
240+
241+#include <linux/netfilter_ipv4/ip_tables.h>
242+#include <net/netfilter/nf_conntrack_expect.h>
243+#include <net/netfilter/nf_conntrack_helper.h>
244+#include <linux/netfilter/nf_conntrack_rpc.h>
245+
246+#define MAX_PORTS 8
247+static int ports[MAX_PORTS];
248+static int ports_n_c = 0;
249+static int nsrexec = 0;
250+
251+#ifdef MODULE_PARM
252+module_param(nsrexec,int, 0400);
253+MODULE_PARM_DESC(nsrexec, "TCP port of Legato NetWorker's rexec service");
254+module_param_array(ports, int, &ports_n_c, 0400);
255+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
256+#endif
257+
258+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
259+MODULE_DESCRIPTION("RPC TCP connection tracking module");
260+MODULE_LICENSE("GPL");
261+
262+#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
263+ format, ## args)
264+
265+#if 0
266+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
267+ format, ## args)
268+#else
269+#define DEBUGP(format, args...)
270+#endif
271+
272+DEFINE_RWLOCK(ipct_rpc_tcp_lock);
273+
274+//#define ASSERT_READ_LOCK(x)
275+//#define ASSERT_WRITE_LOCK(x)
276+
277+//#include <linux/netfilter_ipv4/listhelp.h>
278+
279+/* For future conections RPC, using client's cache bindings
280+ * I'll use ip_conntrack_lock to lock these lists */
281+
282+LIST_HEAD(request_p_list_tcp);
283+
284+
285+static void delete_request_p(unsigned long request_p_ul)
286+{
287+ struct request_p *p = (void *)request_p_ul;
288+
289+ write_lock_bh(&ipct_rpc_tcp_lock);
290+ list_del(&p->list);
291+ write_unlock_bh(&ipct_rpc_tcp_lock);
292+ kfree(p);
293+ return;
294+}
295+
296+
297+static void req_cl(struct request_p * r)
298+{
299+ write_lock_bh(&ipct_rpc_tcp_lock);
300+ del_timer(&r->timeout);
301+ list_del(&r->list);
302+ write_unlock_bh(&ipct_rpc_tcp_lock);
303+ kfree(r);
304+ return;
305+}
306+
307+
308+static void clean_request(struct list_head *list)
309+{
310+ struct list_head *first = list->prev;
311+ struct list_head *temp = list->next;
312+ struct list_head *aux;
313+
314+ if (list_empty(list))
315+ return;
316+
317+ while (first != temp) {
318+ aux = temp->next;
319+ req_cl((struct request_p *)temp);
320+ temp = aux;
321+ }
322+ req_cl((struct request_p *)temp);
323+ return;
324+}
325+
326+
327+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
328+ u_int16_t port)
329+{
330+ struct request_p *req_p = NULL, *p;
331+
332+ /* Verifies if entry already exists */
333+ write_lock_bh(&ipct_rpc_tcp_lock);
334+// req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
335+// struct request_p *, xid, ip, port);
336+
337+ list_for_each_entry(p, &request_p_list_tcp, list)
338+ if (p->xid == xid && p->ip == ip && p->port == port)
339+ req_p = p;
340+
341+ if (req_p) {
342+ /* Refresh timeout */
343+ if (del_timer(&req_p->timeout)) {
344+ req_p->timeout.expires = jiffies + EXP;
345+ add_timer(&req_p->timeout);
346+ }
347+ write_unlock_bh(&ipct_rpc_tcp_lock);
348+ return;
349+
350+ }
351+ write_unlock_bh(&ipct_rpc_tcp_lock);
352+
353+ /* Allocate new request_p */
354+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
355+ if (!req_p) {
356+ DEBUGP("can't allocate request_p\n");
357+ return;
358+ }
359+
360+ req_p->list.next = NULL;
361+ req_p->list.prev = NULL;
362+ req_p->xid = xid;
363+ req_p->ip = ip;
364+ req_p->port = port;
365+ req_p->proto = proto;
366+
367+ /* Initialize timer */
368+ init_timer(&req_p->timeout);
369+ req_p->timeout.expires = jiffies + EXP;
370+ req_p->timeout.data = (unsigned long)req_p;
371+ req_p->timeout.function = delete_request_p;
372+ add_timer(&req_p->timeout);
373+
374+ /* Put in list */
375+ write_lock_bh(&ipct_rpc_tcp_lock);
376+ list_add(req_p, &request_p_list_tcp);
377+ write_unlock_bh(&ipct_rpc_tcp_lock);
378+ return;
379+}
380+
381+
382+static int check_rpc_packet(const u_int32_t *data,
383+ int dir, struct nf_conn *ct,
384+ struct list_head request_p_list)
385+{
386+ u_int32_t xid;
387+ int ret = NF_ACCEPT;
388+ struct request_p *req_p = NULL, *p;
389+ struct nf_conntrack_expect *exp;
390+
391+
392+ if (ct == NULL) {
393+ DEBUGP("ct is NULL");
394+ return ret;
395+ }
396+
397+ /* Translstion's buffer for XDR */
398+ u_int16_t port_buf;
399+
400+ /* Get XID */
401+ xid = *data;
402+
403+ /* This does sanity checking on RPC payloads,
404+ * and permits only the RPC "get port" (3)
405+ * in authorised procedures in client
406+ * communications with the portmapper.
407+ */
408+
409+ /* perform direction dependant RPC work */
410+ if (dir == IP_CT_DIR_ORIGINAL) {
411+
412+ data += 5;
413+
414+ /* Get RPC requestor */
415+ if (IXDR_GET_INT32(data) != 3) {
416+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
417+ return NF_ACCEPT;
418+ }
419+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
420+
421+ data++;
422+
423+ /* Jump Credentials and Verfifier */
424+ data += IXDR_GET_INT32(data) + 2;
425+ data += IXDR_GET_INT32(data) + 2;
426+
427+ /* Get RPC procedure */
428+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
429+ (unsigned int)IXDR_GET_INT32(data));
430+
431+ /* Get RPC protocol and store against client parameters */
432+ data = data + 2;
433+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.u3.ip,
434+ ct->tuplehash[dir].tuple.src.u.all);
435+
436+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
437+ xid, IXDR_GET_INT32(data),
438+ NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
439+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
440+
441+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
442+ (unsigned int)IXDR_GET_INT32(data));
443+
444+ } else {
445+
446+ /* Check for returning packet's stored counterpart */
447+ /* req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
448+ struct request_p *, xid,
449+ ct->tuplehash[!dir].tuple.src.u3.ip,
450+ ct->tuplehash[!dir].tuple.src.u.all);
451+ */
452+
453+ list_for_each_entry(p, &request_p_list_tcp, list)
454+ if (p->xid == xid &&
455+ p->ip == ct->tuplehash[!dir].tuple.src.u3.ip &&
456+ p->port == ct->tuplehash[!dir].tuple.src.u.all)
457+ req_p = p;
458+
459+ /* Drop unexpected packets */
460+ if (!req_p) {
461+ DEBUGP("packet is not expected. [skip]\n");
462+ return NF_ACCEPT;
463+ }
464+
465+ /* Verifies if packet is really an RPC reply packet */
466+ data++;
467+ if (IXDR_GET_INT32(data) != 1) {
468+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
469+ return NF_ACCEPT;
470+ }
471+
472+ /* Is status accept? */
473+ data++;
474+ if (IXDR_GET_INT32(data)) {
475+ DEBUGP("packet is not an RPC accept. [skip]\n");
476+ return NF_ACCEPT;
477+ }
478+
479+ /* Get Verifier length. Jump verifier */
480+ data++;
481+ data = data + IXDR_GET_INT32(data) + 2;
482+
483+ /* Is accpet status "success"? */
484+ if (IXDR_GET_INT32(data)) {
485+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
486+ return NF_ACCEPT;
487+ }
488+
489+ /* Get server port number */
490+ data++;
491+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
492+
493+ /* If a packet has made it this far then it deserves an
494+ * expectation ... if port == 0, then this service is
495+ * not going to be registered.
496+ */
497+ if (port_buf && port_buf != nsrexec) {
498+ DEBUGP("port found: %u\n", port_buf);
499+
500+ exp = nf_ct_expect_alloc(ct);
501+ if (!exp) {
502+ ret = NF_DROP;
503+ goto out;
504+ }
505+
506+ /* Watch out, Radioactive-Man! */
507+ exp->tuple.src.u3.ip = ct->tuplehash[!dir].tuple.src.u3.ip;
508+ exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
509+ exp->mask.src.u3.ip = 0xffffffff;
510+
511+ switch (req_p->proto) {
512+ case IPPROTO_UDP:
513+ exp->tuple.src.u.udp.port = 0;
514+ exp->tuple.dst.u.udp.port = htons(port_buf);
515+ exp->tuple.dst.protonum = IPPROTO_UDP;
516+ exp->mask.src.u.udp.port = 0;
517+ break;
518+
519+ case IPPROTO_TCP:
520+ exp->tuple.src.u.tcp.port = 0;
521+ exp->tuple.dst.u.tcp.port = htons(port_buf);
522+ exp->tuple.dst.protonum = IPPROTO_TCP;
523+ exp->mask.src.u.tcp.port = 0;
524+ break;
525+ }
526+ exp->expectfn = NULL;
527+ exp->master = ct;
528+
529+ struct nf_conn_help *m_help = nfct_help(exp->master);
530+ if (m_help->helper == NULL) {
531+ DEBUGP("master helper NULL");
532+ ret = NF_ACCEPT;
533+ }
534+
535+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
536+ NIPQUAD(exp->tuple.src.u3.ip),
537+ NIPQUAD(exp->tuple.dst.u3.ip),
538+ port_buf, req_p->proto);
539+
540+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
541+ NIPQUAD(exp->mask.src.u3.ip),
542+ NIPQUAD(exp->mask.dst.u3.ip),
543+ exp->mask.dst.protonum);
544+
545+ if (nf_ct_expect_related(exp) != 0) {
546+ ret = NF_DROP;
547+ }
548+
549+ }
550+
551+out:
552+ req_cl(req_p);
553+
554+ DEBUGP("packet evaluated. [expect]\n");
555+ }
556+
557+ return ret;
558+
559+}
560+
561+
562+/* RPC TCP helper */
563+/* static int help(const struct iphdr *iph, size_t len,
564+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) */
565+static int help(struct sk_buff **pskb,
566+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
567+{
568+ int dir;
569+ int crp_ret;
570+ struct tcphdr _tcph, *tcph;
571+ const u_int32_t *data;
572+ size_t tcplen;
573+ struct iphdr *iph;
574+ size_t len;
575+
576+ /* Not whole TCP header? */
577+ iph=ip_hdr(*pskb);
578+ tcph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_tcph),&_tcph);
579+ if (!tcph)
580+ return NF_ACCEPT;
581+
582+ len = (*pskb)->len; /* stes */
583+ data = (const u_int32_t *)tcph + tcph->doff;
584+ tcplen = len - iph->ihl * 4;
585+ dir = CTINFO2DIR(ctinfo);
586+
587+ DEBUGP("new packet to evaluate ..\n");
588+
589+ /* This works for packets like handshake packets, ignore */
590+ if (len == ((tcph->doff + iph->ihl) * 4)) {
591+ DEBUGP("packet has no data (may still be handshaking). [skip]\n");
592+ return NF_ACCEPT;
593+ }
594+
595+ /* Until there's been traffic both ways, don't look in packets. */
596+ if (ctinfo != IP_CT_ESTABLISHED
597+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
598+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
599+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
600+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
601+ return NF_ACCEPT;
602+ }
603+
604+ /* Not whole TCP header? */
605+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
606+ DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
607+ DEBUGP("packet does not contain a complete TCP header. [skip]\n");
608+ return NF_ACCEPT;
609+ }
610+
611+ /* perform direction dependant protocol work */
612+ if (dir == IP_CT_DIR_ORIGINAL) {
613+
614+ DEBUGP("packet is from the initiator. [cont]\n");
615+
616+ /* Tests if packet len is ok */
617+ if ((tcplen - (tcph->doff * 4)) != 60) {
618+ DEBUGP("packet length is not correct. [skip]\n");
619+ return NF_ACCEPT;
620+ }
621+
622+ } else {
623+
624+ DEBUGP("packet is from the receiver. [cont]\n");
625+
626+ /* Tests if packet len is ok */
627+ if ((tcplen - (tcph->doff * 4)) != 32) {
628+ DEBUGP("packet length is not correct. [skip]\n");
629+ return NF_ACCEPT;
630+ }
631+ }
632+
633+ /* Get to the data */
634+ data++;
635+
636+ /* Check the RPC data */
637+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
638+
639+ return crp_ret;
640+
641+}
642+
643+
644+static struct nf_conntrack_helper rpc_helpers[MAX_PORTS];
645+static char rpc_names[MAX_PORTS][10];
646+static const struct nf_conntrack_expect_policy rpc_exp_policy = {
647+ .max_expected = 1,
648+ .timeout = 5 * 60, /* stes */
649+};
650+
651+static void fini(void);
652+
653+static int __init init(void)
654+{
655+ int port, ret;
656+ char *tmpname;
657+
658+ /* If no port given, default to standard RPC port */
659+ if (ports[0] == 0)
660+ ports[0] = RPC_PORT;
661+
662+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
663+ memset(&rpc_helpers[port], 0, sizeof(struct nf_conntrack_helper));
664+
665+ tmpname = &rpc_names[port][0];
666+ if (ports[port] == RPC_PORT)
667+ sprintf(tmpname, "rpc");
668+ else
669+ sprintf(tmpname, "rpc-%d", ports[port]);
670+ rpc_helpers[port].name = tmpname;
671+
672+ rpc_helpers[port].me = THIS_MODULE;
673+ rpc_helpers[port].expect_policy = &rpc_exp_policy;
674+
675+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
676+
677+ /* RPC can come from ports 0:65535 to ports[port] (111) */
678+ rpc_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
679+
680+ rpc_helpers[port].help = help;
681+
682+ PRINTK("registering helper for port #%d: %d/TCP\n", port, ports[port]);
683+ PRINTK("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
684+ NIPQUAD(rpc_helpers[port].tuple.dst.u3.ip),
685+ ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
686+ NIPQUAD(rpc_helpers[port].tuple.src.u3.ip),
687+ ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
688+
689+ ret = nf_conntrack_helper_register(&rpc_helpers[port]);
690+
691+ if (ret) {
692+ printk("ERROR registering port %d\n",
693+ ports[port]);
694+ fini();
695+ return -EBUSY;
696+ }
697+ ports_n_c++;
698+ }
699+
700+ PRINTK("%s Legato NetWorker support for port %d/TCP\n", (nsrexec)?"enabling":"disabling", nsrexec);
701+
702+ return 0;
703+}
704+
705+
706+/* This function is intentionally _NOT_ defined as __exit, because
707+ * it is needed by the init function */
708+static void fini(void)
709+{
710+ int port;
711+
712+ DEBUGP("cleaning request list\n");
713+ clean_request(&request_p_list_tcp);
714+
715+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
716+ DEBUGP("unregistering port %d\n", ports[port]);
717+ nf_conntrack_helper_unregister(&rpc_helpers[port]);
718+ }
719+}
720+
721+
722+module_init(init);
723+module_exit(fini);
724+
725+struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
726+EXPORT_SYMBOL(request_p_list_tcp);
727+EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
728+EXPORT_SYMBOL(ipct_rpc_tcp_lock);
729+
730diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
731--- linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
732+++ linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2007-08-15 01:44:02.000000000 +0200
733@@ -0,0 +1,530 @@
734+/* RPC extension for IP (UDP) connection tracking, Version 2.2
735+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
736+ * - original rpc tracking module
737+ * - "recent" connection handling for kernel 2.3+ netfilter
738+ *
739+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
740+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
741+ *
742+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
743+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
744+ * - extended matching to support filtering on procedures
745+ *
746+ * (c) 2004,2005 by David Stes <stes@pandora.be>
747+ * - upgraded to 2.6.12+ conntrack module api
748+ *
749+ * (c) 2005 by David Stes <stes@pandora.be>
750+ * - upgraded to 2.6.13 api
751+ *
752+ * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
753+ *
754+ * This program is free software; you can redistribute it and/or
755+ * modify it under the terms of the GNU General Public License
756+ * as published by the Free Software Foundation; either version
757+ * 2 of the License, or (at your option) any later version.
758+ **
759+ * Module load syntax:
760+ * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
761+ *
762+ * Please give the ports of all RPC servers you wish to connect to.
763+ * If you don't specify ports, the default will be port 111.
764+ **
765+ * Note to all:
766+ *
767+ * RPCs should not be exposed to the internet - ask the Pentagon;
768+ *
769+ * "The unidentified crackers pleaded guilty in July to charges
770+ * of juvenile delinquency stemming from a string of Pentagon
771+ * network intrusions in February.
772+ *
773+ * The youths, going by the names TooShort and Makaveli, used
774+ * a common server security hole to break in, according to
775+ * Dane Jasper, owner of the California Internet service
776+ * provider, Sonic. They used the hole, known as the 'statd'
777+ * exploit, to attempt more than 800 break-ins, Jasper said."
778+ *
779+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
780+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
781+ **
782+ */
783+
784+#include <linux/module.h>
785+#include <linux/netfilter.h>
786+#include <linux/ip.h>
787+#include <net/checksum.h>
788+#include <net/udp.h>
789+
790+#include <asm/param.h>
791+#include <linux/sched.h>
792+#include <linux/timer.h>
793+#include <linux/stddef.h>
794+#include <linux/list.h>
795+#include <linux/udp.h>
796+
797+#include <linux/netfilter_ipv4/ip_tables.h>
798+#include <net/netfilter/nf_conntrack_expect.h>
799+#include <net/netfilter/nf_conntrack_helper.h>
800+#include <linux/netfilter/nf_conntrack_rpc.h>
801+
802+#define MAX_PORTS 8
803+static int ports[MAX_PORTS];
804+static int ports_n_c = 0;
805+
806+#ifdef MODULE_PARM
807+module_param_array(ports, int, &ports_n_c, 0400);
808+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
809+#endif
810+
811+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
812+MODULE_DESCRIPTION("RPC UDP connection tracking module");
813+MODULE_LICENSE("GPL");
814+
815+#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
816+ format, ## args)
817+
818+#if 0
819+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
820+ format, ## args)
821+#else
822+#define DEBUGP(format, args...)
823+#endif
824+
825+DEFINE_RWLOCK(ipct_rpc_udp_lock);
826+//#define ASSERT_READ_LOCK(x)
827+//#define ASSERT_WRITE_LOCK(x)
828+//#include <linux/netfilter_ipv4/listhelp.h>
829+
830+/* For future conections RPC, using client's cache bindings
831+ * I'll use ip_conntrack_lock to lock these lists */
832+
833+LIST_HEAD(request_p_list_udp);
834+
835+
836+static void delete_request_p(unsigned long request_p_ul)
837+{
838+ struct request_p *p = (void *)request_p_ul;
839+
840+ write_lock_bh(&ipct_rpc_udp_lock);
841+ list_del(&p->list);
842+ write_unlock_bh(&ipct_rpc_udp_lock);
843+ kfree(p);
844+ return;
845+}
846+
847+
848+static void req_cl(struct request_p * r)
849+{
850+ write_lock_bh(&ipct_rpc_udp_lock);
851+ del_timer(&r->timeout);
852+ list_del(&r->list);
853+ write_unlock_bh(&ipct_rpc_udp_lock);
854+ kfree(r);
855+ return;
856+}
857+
858+
859+static void clean_request(struct list_head *list)
860+{
861+ struct list_head *first = list->prev;
862+ struct list_head *temp = list->next;
863+ struct list_head *aux;
864+
865+ if (list_empty(list))
866+ return;
867+
868+ while (first != temp) {
869+ aux = temp->next;
870+ req_cl((struct request_p *)temp);
871+ temp = aux;
872+ }
873+ req_cl((struct request_p *)temp);
874+ return;
875+}
876+
877+
878+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
879+ u_int16_t port)
880+{
881+ struct request_p *req_p = NULL, *p;
882+
883+ /* Verifies if entry already exists */
884+ write_lock_bh(&ipct_rpc_udp_lock);
885+// req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
886+// struct request_p *, xid, ip, port);
887+
888+ list_for_each_entry(p, &request_p_list_udp, list)
889+ if (p->xid == xid && p->ip == ip && p->port == port)
890+ req_p = p;
891+
892+ if (req_p) {
893+ /* Refresh timeout */
894+ if (del_timer(&req_p->timeout)) {
895+ req_p->timeout.expires = jiffies + EXP;
896+ add_timer(&req_p->timeout);
897+ }
898+ write_unlock_bh(&ipct_rpc_udp_lock);
899+ return;
900+
901+ }
902+ write_unlock_bh(&ipct_rpc_udp_lock);
903+
904+ /* Allocate new request_p */
905+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
906+ if (!req_p) {
907+ DEBUGP("can't allocate request_p\n");
908+ return;
909+ }
910+
911+ req_p->list.next = NULL;
912+ req_p->list.prev = NULL;
913+ req_p->xid = xid;
914+ req_p->ip = ip;
915+ req_p->port = port;
916+ req_p->proto = proto;
917+
918+ /* Initialize timer */
919+ init_timer(&req_p->timeout);
920+ req_p->timeout.expires = jiffies + EXP;
921+ req_p->timeout.data = (unsigned long)req_p;
922+ req_p->timeout.function = delete_request_p;
923+ add_timer(&req_p->timeout);
924+
925+ /* Put in list */
926+ write_lock_bh(&ipct_rpc_udp_lock);
927+ list_add(req_p, &request_p_list_udp);
928+ write_unlock_bh(&ipct_rpc_udp_lock);
929+ return;
930+
931+}
932+
933+
934+static int check_rpc_packet(const u_int32_t *data,
935+ int dir, struct nf_conn *ct,
936+ struct list_head request_p_list)
937+{
938+ int ret = NF_ACCEPT;
939+ u_int32_t xid;
940+ struct request_p *req_p = NULL, *p;
941+ struct nf_conntrack_expect *exp;
942+
943+ /* Translstion's buffer for XDR */
944+ u_int16_t port_buf;
945+
946+
947+ /* Get XID */
948+ xid = *data;
949+
950+ /* This does sanity checking on RPC payloads,
951+ * and permits only the RPC "get port" (3)
952+ * in authorised procedures in client
953+ * communications with the portmapper.
954+ */
955+
956+ /* perform direction dependant RPC work */
957+ if (dir == IP_CT_DIR_ORIGINAL) {
958+
959+ data += 5;
960+
961+ /* Get RPC requestor */
962+ if (IXDR_GET_INT32(data) != 3) {
963+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
964+ return NF_ACCEPT;
965+ }
966+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
967+
968+ data++;
969+
970+ /* Jump Credentials and Verfifier */
971+ data = data + IXDR_GET_INT32(data) + 2;
972+ data = data + IXDR_GET_INT32(data) + 2;
973+
974+ /* Get RPC procedure */
975+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
976+ (unsigned int)IXDR_GET_INT32(data));
977+
978+ /* Get RPC protocol and store against client parameters */
979+ data = data + 2;
980+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.u3.ip,
981+ ct->tuplehash[dir].tuple.src.u.all);
982+
983+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
984+ xid, IXDR_GET_INT32(data),
985+ NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
986+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
987+
988+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
989+ (unsigned int)IXDR_GET_INT32(data));
990+
991+ } else {
992+
993+ /* Check for returning packet's stored counterpart */
994+ /* req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
995+ struct request_p *, xid,
996+ ct->tuplehash[!dir].tuple.src.u3.ip,
997+ ct->tuplehash[!dir].tuple.src.u.all);
998+
999+ */
1000+ list_for_each_entry(p, &request_p_list_udp, list)
1001+ if (p->xid == xid &&
1002+ p->ip == ct->tuplehash[!dir].tuple.src.u3.ip &&
1003+ p->port == ct->tuplehash[!dir].tuple.src.u.all)
1004+ req_p = p;
1005+
1006+ /* Drop unexpected packets */
1007+ if (!req_p) {
1008+ DEBUGP("packet is not expected. [skip]\n");
1009+ return NF_ACCEPT;
1010+ }
1011+
1012+ /* Verifies if packet is really an RPC reply packet */
1013+ data++;
1014+ if (IXDR_GET_INT32(data) != 1) {
1015+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
1016+ return NF_ACCEPT;
1017+ }
1018+
1019+ /* Is status accept? */
1020+ data++;
1021+ if (IXDR_GET_INT32(data)) {
1022+ DEBUGP("packet is not an RPC accept. [skip]\n");
1023+ return NF_ACCEPT;
1024+ }
1025+
1026+ /* Get Verifier length. Jump verifier */
1027+ data++;
1028+ data = data + IXDR_GET_INT32(data) + 2;
1029+
1030+ /* Is accpet status "success"? */
1031+ if (IXDR_GET_INT32(data)) {
1032+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
1033+ return NF_ACCEPT;
1034+ }
1035+
1036+ /* Get server port number */
1037+ data++;
1038+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
1039+
1040+ /* If a packet has made it this far then it deserves an
1041+ * expectation ... if port == 0, then this service is
1042+ * not going to be registered.
1043+ */
1044+ if (port_buf) {
1045+ DEBUGP("port found: %u\n", port_buf);
1046+
1047+ exp = nf_ct_expect_alloc(ct);
1048+ if (!exp) {
1049+ ret = NF_DROP;
1050+ goto out;
1051+ }
1052+
1053+ /* Watch out, Radioactive-Man! */
1054+ exp->tuple.src.u3.ip = ct->tuplehash[!dir].tuple.src.u3.ip;
1055+ exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
1056+ exp->mask.src.u3.ip = 0xffffffff;
1057+
1058+ switch (req_p->proto) {
1059+ case IPPROTO_UDP:
1060+ exp->tuple.src.u.udp.port = 0;
1061+ exp->tuple.dst.u.udp.port = htons(port_buf);
1062+ exp->tuple.dst.protonum = IPPROTO_UDP;
1063+ exp->mask.src.u.udp.port = 0;
1064+ break;
1065+
1066+ case IPPROTO_TCP:
1067+ exp->tuple.src.u.tcp.port = 0;
1068+ exp->tuple.dst.u.tcp.port = htons(port_buf);
1069+ exp->tuple.dst.protonum = IPPROTO_TCP;
1070+ exp->mask.src.u.tcp.port = 0;
1071+ break;
1072+ }
1073+ exp->expectfn = NULL;
1074+ exp->master = ct;
1075+
1076+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
1077+ NIPQUAD(exp->tuple.src.u3.ip),
1078+ NIPQUAD(exp->tuple.dst.u3.ip),
1079+ port_buf, req_p->proto);
1080+
1081+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
1082+ NIPQUAD(exp->mask.src.u3.ip),
1083+ NIPQUAD(exp->mask.dst.u3.ip),
1084+ exp->mask.dst.protonum);
1085+
1086+ if (nf_ct_expect_related(exp) != 0) {
1087+ ret = NF_DROP;
1088+ }
1089+ }
1090+
1091+out:
1092+ req_cl(req_p);
1093+
1094+ DEBUGP("packet evaluated. [expect]\n");
1095+ }
1096+
1097+ return ret;
1098+}
1099+
1100+
1101+/* RPC UDP helper */
1102+/* static int help(const struct iphdr *iph, size_t len,
1103+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) */
1104+static int help(struct sk_buff **pskb,
1105+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1106+{
1107+ int dir;
1108+ int crp_ret;
1109+ struct udphdr _udph, *udph;
1110+ const u_int32_t *data;
1111+ size_t udplen;
1112+ struct iphdr *iph;
1113+ size_t len;
1114+ const u_int16_t *chsm;
1115+
1116+ /* Not whole UDP header? */
1117+ iph=ip_hdr(*pskb);
1118+ udph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_udph),&_udph);
1119+ if (!udph)
1120+ return NF_ACCEPT;
1121+
1122+ len = (*pskb)->len; /* stes */
1123+ data = (const u_int32_t *)udph + 2;
1124+ udplen = len - iph->ihl * 4;
1125+ dir = CTINFO2DIR(ctinfo);
1126+
1127+ /* Checksum */
1128+ chsm = (const u_int16_t *)udph + 3;
1129+
1130+ DEBUGP("new packet to evaluate ..\n");
1131+
1132+ /* Not whole UDP header? */
1133+ if (udplen < sizeof(struct udphdr)) {
1134+ DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
1135+ DEBUGP("packet does not contain a complete UDP header. [skip]\n");
1136+ return NF_ACCEPT;
1137+ }
1138+
1139+ /* perform direction dependant protocol work */
1140+ if (dir == IP_CT_DIR_ORIGINAL) {
1141+
1142+ DEBUGP("packet is from the initiator. [cont]\n");
1143+
1144+ /* Tests if packet len is ok */
1145+ if ((udplen - sizeof(struct udphdr)) != 56) {
1146+ DEBUGP("packet length is not correct. [skip]\n");
1147+ return NF_ACCEPT;
1148+ }
1149+
1150+ } else {
1151+
1152+ DEBUGP("packet is from the receiver. [cont]\n");
1153+
1154+ /* Until there's been traffic both ways, don't look in packets. */
1155+ if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1156+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
1157+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
1158+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
1159+ return NF_ACCEPT;
1160+ }
1161+
1162+ /* Tests if packet len is ok */
1163+ if ((udplen - sizeof(struct udphdr)) != 28) {
1164+ DEBUGP("packet length is not correct. [skip]\n");
1165+ return NF_ACCEPT;
1166+ }
1167+
1168+ }
1169+
1170+ /* Get to the data */
1171+ /* udp *data == *correct */
1172+
1173+ /* Check the RPC data */
1174+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
1175+
1176+ return crp_ret;
1177+
1178+}
1179+
1180+
1181+static struct nf_conntrack_helper rpc_helpers[MAX_PORTS];
1182+static char rpc_names[MAX_PORTS][10];
1183+static const struct nf_conntrack_expect_policy rpc_exp_policy = {
1184+ .max_expected = 1,
1185+ .timeout = 5 * 60, /* stes */
1186+};
1187+
1188+static void fini(void);
1189+
1190+static int __init init(void)
1191+{
1192+ int port, ret;
1193+ char *tmpname;
1194+
1195+ /* If no port given, default to standard RPC port */
1196+ if (ports[0] == 0)
1197+ ports[0] = RPC_PORT;
1198+
1199+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1200+ memset(&rpc_helpers[port], 0, sizeof(struct nf_conntrack_helper));
1201+
1202+ tmpname = &rpc_names[port][0];
1203+ if (ports[port] == RPC_PORT)
1204+ sprintf(tmpname, "rpc");
1205+ else
1206+ sprintf(tmpname, "rpc-%d", ports[port]);
1207+ rpc_helpers[port].name = tmpname;
1208+
1209+ rpc_helpers[port].me = THIS_MODULE;
1210+ rpc_helpers[port].expect_policy = &rpc_exp_policy;
1211+
1212+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
1213+
1214+ /* RPC can come from ports 0:65535 to ports[port] (111) */
1215+ rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
1216+
1217+ rpc_helpers[port].help = help;
1218+
1219+ PRINTK("registering helper for port #%d: %d/UDP\n", port, ports[port]);
1220+ PRINTK("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1221+ NIPQUAD(rpc_helpers[port].tuple.dst.u3.ip),
1222+ ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
1223+ NIPQUAD(rpc_helpers[port].tuple.src.u3.ip),
1224+ ntohs(rpc_helpers[port].tuple.src.u.udp.port));
1225+
1226+ ret = nf_conntrack_helper_register(&rpc_helpers[port]);
1227+
1228+ if (ret) {
1229+ printk("ERROR registering port %d\n",
1230+ ports[port]);
1231+ fini();
1232+ return -EBUSY;
1233+ }
1234+ ports_n_c++;
1235+ }
1236+ return 0;
1237+}
1238+
1239+
1240+/* This function is intentionally _NOT_ defined as __exit, because
1241+ * it is needed by the init function */
1242+static void fini(void)
1243+{
1244+ int port;
1245+
1246+ DEBUGP("cleaning request list\n");
1247+ clean_request(&request_p_list_udp);
1248+
1249+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
1250+ DEBUGP("unregistering port %d\n", ports[port]);
1251+ nf_conntrack_helper_unregister(&rpc_helpers[port]);
1252+ }
1253+}
1254+
1255+
1256+module_init(init);
1257+module_exit(fini);
1258+
1259+struct module *ip_conntrack_rpc_udp = THIS_MODULE;
1260+EXPORT_SYMBOL(request_p_list_udp);
1261+EXPORT_SYMBOL(ip_conntrack_rpc_udp);
1262+EXPORT_SYMBOL(ipct_rpc_udp_lock);
1263+
1264diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/ipt_rpc.c linux/net/ipv4/netfilter/ipt_rpc.c
1265--- linux/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
1266+++ linux/net/ipv4/netfilter/ipt_rpc.c 2007-08-15 01:40:43.000000000 +0200
1267@@ -0,0 +1,448 @@
1268+/* RPC extension for IP connection matching, Version 2.2
1269+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
1270+ * - original rpc tracking module
1271+ * - "recent" connection handling for kernel 2.3+ netfilter
1272+ *
1273+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1274+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1275+ *
1276+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1277+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
1278+ * - extended matching to support filtering on procedures
1279+ *
1280+ * (c) 2004,2005 by David Stes <stes@pandora.be>
1281+ * - upgraded to 2.6.12+ conntrack module api
1282+ * - upgraded to 2.6.13 api
1283+ *
1284+ * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
1285+ *
1286+ * This program is free software; you can redistribute it and/or
1287+ * modify it under the terms of the GNU General Public License
1288+ * as published by the Free Software Foundation; either version
1289+ * 2 of the License, or (at your option) any later version.
1290+ **
1291+ * Module load syntax:
1292+ * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
1293+ *
1294+ * Please give the ports of all RPC servers you wish to connect to.
1295+ * If you don't specify ports, the default will be port 111.
1296+ **
1297+ * Note to all:
1298+ *
1299+ * RPCs should not be exposed to the internet - ask the Pentagon;
1300+ *
1301+ * "The unidentified crackers pleaded guilty in July to charges
1302+ * of juvenile delinquency stemming from a string of Pentagon
1303+ * network intrusions in February.
1304+ *
1305+ * The youths, going by the names TooShort and Makaveli, used
1306+ * a common server security hole to break in, according to
1307+ * Dane Jasper, owner of the California Internet service
1308+ * provider, Sonic. They used the hole, known as the 'statd'
1309+ * exploit, to attempt more than 800 break-ins, Jasper said."
1310+ *
1311+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
1312+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
1313+ **
1314+ */
1315+
1316+#include <linux/module.h>
1317+#include <linux/skbuff.h>
1318+#include <linux/list.h>
1319+#include <linux/udp.h>
1320+#include <linux/tcp.h>
1321+#include <linux/netfilter_ipv4/ip_tables.h>
1322+#include <linux/netfilter/nf_conntrack_rpc.h>
1323+#include <linux/netfilter_ipv4/ipt_rpc.h>
1324+
1325+#define MAX_PORTS 8
1326+static int ports[MAX_PORTS];
1327+static int ports_n_c = 0;
1328+
1329+#ifdef MODULE_PARM
1330+module_param_array(ports, int, &ports_n_c, 0400);
1331+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
1332+#endif
1333+
1334+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
1335+MODULE_DESCRIPTION("RPC connection matching module");
1336+MODULE_LICENSE("GPL");
1337+
1338+#define PRINTK(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1339+ format, ## args)
1340+
1341+#if 0
1342+#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1343+ format, ## args)
1344+#else
1345+#define DEBUGP(format, args...)
1346+#endif
1347+
1348+/* EXPORT_NO_SYMBOLS; */
1349+
1350+/* vars from ip_conntrack_rpc_tcp */
1351+extern struct list_head request_p_list_tcp;
1352+extern struct module *ip_conntrack_rpc_tcp;
1353+
1354+/* vars from ip_conntrack_rpc_udp */
1355+extern struct list_head request_p_list_udp;
1356+extern struct module *ip_conntrack_rpc_udp;
1357+
1358+extern rwlock_t ipct_rpc_tcp_lock;
1359+extern rwlock_t ipct_rpc_udp_lock;
1360+
1361+#define ASSERT_READ_LOCK(x)
1362+#define ASSERT_WRITE_LOCK(x)
1363+
1364+#if 0
1365+#define ASSERT_READ_LOCK(x) \
1366+do { \
1367+ if (x == &request_p_list_udp) \
1368+ MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
1369+ else if (x == &request_p_list_tcp) \
1370+ MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
1371+} while (0)
1372+
1373+#define ASSERT_WRITE_LOCK(x) \
1374+do { \
1375+ if (x == &request_p_list_udp) \
1376+ MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
1377+ else if (x == &request_p_list_tcp) \
1378+ MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
1379+} while (0)
1380+#endif
1381+
1382+const int IPT_RPC_CHAR_LEN = 11;
1383+
1384+static int k_atoi(char *string)
1385+{
1386+ unsigned int result = 0;
1387+ int maxoctet = IPT_RPC_CHAR_LEN;
1388+
1389+ for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
1390+ if (*string < 0)
1391+ return(0);
1392+ if (*string == 0)
1393+ break;
1394+ if (*string < 48 || *string > 57) {
1395+ return(0);
1396+ }
1397+ result = result * 10 + ( *string - 48 );
1398+ }
1399+ return(result);
1400+}
1401+
1402+
1403+static int match_rpcs(char *c_procs, int i_procs, int proc)
1404+{
1405+ int proc_ctr;
1406+ char *proc_ptr;
1407+ unsigned int proc_num;
1408+
1409+ DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
1410+
1411+ if (i_procs == -1)
1412+ return 1;
1413+
1414+ for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
1415+
1416+ proc_ptr = c_procs;
1417+ proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
1418+ proc_num = k_atoi(proc_ptr);
1419+
1420+ if (proc_num == proc)
1421+ return 1;
1422+ }
1423+
1424+ return 0;
1425+}
1426+
1427+
1428+static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
1429+ int *hotdrop, int dir, struct nf_conn *ct,
1430+ int offset, struct list_head request_p_list)
1431+{
1432+ const struct ipt_rpc_info *rpcinfo = matchinfo;
1433+ struct request_p *req_p = NULL, *p;
1434+ u_int32_t xid;
1435+
1436+
1437+ /* Get XID */
1438+ xid = *data;
1439+
1440+ /* This does sanity checking on RPC payloads,
1441+ * and permits only the RPC "get port" (3)
1442+ * in authorised procedures in client
1443+ * communications with the portmapper.
1444+ */
1445+
1446+ data += 5;
1447+
1448+ /* Get RPC requestor */
1449+ if (IXDR_GET_INT32(data) != 3) {
1450+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
1451+ if(rpcinfo->strict == 1)
1452+ *hotdrop = 1;
1453+ return 0;
1454+ }
1455+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
1456+
1457+ data++;
1458+
1459+ /* Jump Credentials and Verfifier */
1460+ data = data + IXDR_GET_INT32(data) + 2;
1461+ data = data + IXDR_GET_INT32(data) + 2;
1462+
1463+ /* Get RPC procedure */
1464+ if (match_rpcs((char *)&rpcinfo->c_procs,
1465+ rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
1466+ DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
1467+ (unsigned int)IXDR_GET_INT32(data));
1468+
1469+ /* If the RPC conntrack half entry already exists .. */
1470+
1471+ switch (ct->tuplehash[0].tuple.dst.protonum) {
1472+ case IPPROTO_UDP:
1473+ write_lock_bh(&ipct_rpc_udp_lock);
1474+ case IPPROTO_TCP:
1475+ write_lock_bh(&ipct_rpc_tcp_lock);
1476+ }
1477+/* req_p = LIST_FIND(&request_p_list, request_p_cmp,
1478+ struct request_p *, xid,
1479+ ct->tuplehash[dir].tuple.src.u3.ip,
1480+ ct->tuplehash[dir].tuple.src.u.all);
1481+*/
1482+ list_for_each_entry(p, &request_p_list, list)
1483+ if (p->xid == xid &&
1484+ p->ip == ct->tuplehash[!dir].tuple.src.u3.ip &&
1485+ p->port == ct->tuplehash[!dir].tuple.src.u.all)
1486+ req_p = p;
1487+
1488+ if (req_p) {
1489+ DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1490+ xid, ct->tuplehash[dir].tuple.dst.protonum,
1491+ NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
1492+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
1493+
1494+ /* .. remove it */
1495+ if (del_timer(&req_p->timeout))
1496+ req_p->timeout.expires = 0;
1497+
1498+ list_del(&req_p->list);
1499+ DEBUGP("RPC req_p removed. [done]\n");
1500+
1501+ } else {
1502+ DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1503+ xid, ct->tuplehash[dir].tuple.dst.protonum,
1504+ NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
1505+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
1506+
1507+ }
1508+ switch (ct->tuplehash[0].tuple.dst.protonum) {
1509+ case IPPROTO_UDP:
1510+ write_unlock_bh(&ipct_rpc_udp_lock);
1511+ case IPPROTO_TCP:
1512+ write_unlock_bh(&ipct_rpc_tcp_lock);
1513+ }
1514+
1515+ if(rpcinfo->strict == 1)
1516+ *hotdrop = 1;
1517+ return 0;
1518+ }
1519+
1520+ DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
1521+ (unsigned int)IXDR_GET_INT32(data));
1522+ return (1 && (!offset));
1523+}
1524+
1525+
1526+
1527+/* static int match(const struct sk_buff *skb, const struct net_device *in,
1528+ const struct net_device *out, const void *matchinfo,
1529+ int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
1530+*/
1531+static int match(const struct sk_buff *skb, const struct net_device *in,
1532+ const struct net_device *out, const void *matchinfo,
1533+ int offset, unsigned int protoff, int *hotdrop)
1534+{
1535+ struct nf_conn *ct;
1536+ enum ip_conntrack_info ctinfo;
1537+ const u_int32_t *data;
1538+ enum ip_conntrack_dir dir;
1539+ const struct tcphdr *tcp;
1540+ const struct ipt_rpc_info *rpcinfo = matchinfo;
1541+ int port, portsok;
1542+ int tval;
1543+ struct iphdr *ip; /* stes */
1544+ void *hdr; /* stes */
1545+ u_int16_t datalen; /* stes */
1546+
1547+ /* Initialization stes - see 2.4 ip_tables.c ipt_do_table() */
1548+ ip = ip_hdr(skb);
1549+ hdr = (u_int32_t *)ip + ip->ihl;
1550+ datalen = skb->len - ip->ihl * 4;
1551+
1552+ DEBUGP("new packet to evaluate ..\n");
1553+
1554+ ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
1555+ if (!ct) {
1556+ DEBUGP("no ct available [skip]\n");
1557+ return 0;
1558+ }
1559+
1560+ DEBUGP("ct detected. [cont]\n");
1561+ dir = CTINFO2DIR(ctinfo);
1562+
1563+ /* we only want the client to server packets for matching */
1564+ if (dir != IP_CT_DIR_ORIGINAL)
1565+ return 0;
1566+
1567+ /* This does sanity checking on UDP or TCP packets,
1568+ * like their respective modules.
1569+ */
1570+
1571+ switch (ct->tuplehash[0].tuple.dst.protonum) {
1572+
1573+ case IPPROTO_UDP:
1574+ DEBUGP("PROTO_UDP [cont]\n");
1575+ if (offset == 0 && datalen < sizeof(struct udphdr)) {
1576+ DEBUGP("packet does not contain a complete header. [drop]\n");
1577+ return 0;
1578+ }
1579+
1580+ for (port=0,portsok=0; port <= ports_n_c; port++) {
1581+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
1582+ portsok++;
1583+ break;
1584+ }
1585+ }
1586+ if (portsok == 0) {
1587+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
1588+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
1589+ return 0;
1590+ }
1591+
1592+ if ((datalen - sizeof(struct udphdr)) != 56) {
1593+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
1594+ if (rpcinfo->strict == 1)
1595+ *hotdrop = 1;
1596+ return 0;
1597+ }
1598+ DEBUGP("packet length is correct. [cont]\n");
1599+
1600+ /* Get to the data */
1601+ data = (const u_int32_t *)hdr + 2;
1602+
1603+ /* Check the RPC data */
1604+ tval = check_rpc_packet(data, matchinfo, hotdrop,
1605+ dir, ct, offset,
1606+ request_p_list_udp);
1607+
1608+ return tval;
1609+
1610+
1611+ case IPPROTO_TCP:
1612+ DEBUGP("PROTO_TCP [cont]\n");
1613+ if (offset == 0 && datalen < sizeof(struct tcphdr)) {
1614+ DEBUGP("packet does not contain a complete header. [drop]\n");
1615+ return 0;
1616+ }
1617+
1618+ for (port=0,portsok=0; port <= ports_n_c; port++) {
1619+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
1620+ portsok++;
1621+ break;
1622+ }
1623+ }
1624+ if (portsok == 0) {
1625+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
1626+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
1627+ return 0;
1628+ }
1629+
1630+ tcp = hdr;
1631+ if (datalen == (tcp->doff * 4)) {
1632+ DEBUGP("packet does not contain any data. [match]\n");
1633+ return (1 && (!offset));
1634+ }
1635+
1636+ /* Tests if packet len is ok */
1637+ if ((datalen - (tcp->doff * 4)) != 60) {
1638+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
1639+ if(rpcinfo->strict == 1)
1640+ *hotdrop = 1;
1641+ return 0;
1642+ }
1643+ DEBUGP("packet length is correct. [cont]\n");
1644+
1645+ /* Get to the data */
1646+ data = (const u_int32_t *)tcp + tcp->doff + 1;
1647+
1648+ /* Check the RPC data */
1649+ tval = check_rpc_packet(data, matchinfo, hotdrop,
1650+ dir, ct, offset,
1651+ request_p_list_tcp);
1652+
1653+ return tval;
1654+
1655+ }
1656+
1657+ DEBUGP("transport protocol=%u, is not supported [skip]\n",
1658+ ct->tuplehash[0].tuple.dst.protonum);
1659+ return 0;
1660+}
1661+
1662+
1663+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
1664+ unsigned int matchsize, unsigned int hook_mask)
1665+{
1666+ if (hook_mask
1667+ & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING)
1668+ | (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_LOCAL_OUT))) {
1669+ printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
1670+ return 0;
1671+ }
1672+
a1f66529 1673+ if (matchsize != XT_ALIGN(sizeof(struct ipt_rpc_info)))
2380c486
JR
1674+ return 0;
1675+
1676+ return 1;
1677+}
1678+
1679+static struct xt_match rpc_match = {
1680+ .name = "rpc",
1681+ .family = AF_INET,
1682+ .match = match,
1683+ .matchsize = sizeof(struct ipt_rpc_info),
1684+ .checkentry = checkentry,
1685+ .me = THIS_MODULE,
1686+};
1687+
1688+static int __init init(void)
1689+{
1690+ int port;
1691+
1692+ /* If no port given, default to standard RPC port */
1693+ if (ports[0] == 0)
1694+ ports[0] = RPC_PORT;
1695+
1696+ PRINTK("registering match [%s] for;\n", rpc_match.name);
1697+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1698+ PRINTK(" port %i (UDP|TCP);\n", ports[port]);
1699+ ports_n_c++;
1700+ }
1701+
1702+ return xt_register_match(&rpc_match);
1703+}
1704+
1705+
1706+static void fini(void)
1707+{
1708+ DEBUGP("unregistering match\n");
1709+ xt_unregister_match(&rpc_match);
1710+}
1711+
1712+
1713+module_init(init);
1714+module_exit(fini);
1715+
This page took 0.255249 seconds and 4 git commands to generate.