1 /* RPC extension for IP connection matching, Version 2.2
2 * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3 * - original rpc tracking module
4 * - "recent" connection handling for kernel 2.3+ netfilter
6 * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
7 * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
9 * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
10 * - upgraded conntrack modules to newnat api - kernel 2.4.20+
11 * - extended matching to support filtering on procedures
13 * libipt_rpc.c,v 2.2 2003/01/12 18:30:00
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
20 * Userspace library syntax:
21 * --rpc [--rpcs procedure1,procedure2,...procedure128] [--static]
23 * Procedures can be supplied in either numeric or named formats.
24 * Without --rpcs, this module will behave as the old record-rpc.
28 * RPCs should not be exposed to the internet - ask the Pentagon;
30 * "The unidentified crackers pleaded guilty in July to charges
31 * of juvenile delinquency stemming from a string of Pentagon
32 * network intrusions in February.
34 * The youths, going by the names TooShort and Makaveli, used
35 * a common server security hole to break in, according to
36 * Dane Jasper, owner of the California Internet service
37 * provider, Sonic. They used the hole, known as the 'statd'
38 * exploit, to attempt more than 800 break-ins, Jasper said."
40 * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
41 * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
53 #include <linux/netfilter_ipv4/ipt_rpc.h>
57 const int IPT_RPC_RPCS
= 1;
58 const int IPT_RPC_STRC
= 2;
60 const int IPT_RPC_INT_LBL
= 1;
61 const int IPT_RPC_INT_NUM
= 2;
62 const int IPT_RPC_INT_BTH
= 3;
64 const int IPT_RPC_CHAR_LEN
= 11;
65 const int IPT_RPC_MAX_ENTS
= 128;
67 const char preerr
[11] = "RPC match:";
70 static int k_itoa(char *string
, int number
)
72 int maxoctet
= IPT_RPC_CHAR_LEN
- 1;
73 int store
[IPT_RPC_CHAR_LEN
];
77 for (counter
=0 ; maxoctet
!= 0 && number
!= 0; counter
++, maxoctet
--) {
78 store
[counter
] = number
/ 10;
79 store
[counter
] = number
- ( store
[counter
] * 10 );
83 for ( ; counter
!= 0; counter
--, string
++)
84 *string
= store
[counter
- 1] + 48;
92 static int k_atoi(char *string
)
94 unsigned int result
= 0;
95 int maxoctet
= IPT_RPC_CHAR_LEN
;
98 for ( ; *string
!= 0 && maxoctet
!= 0; maxoctet
--, string
++) {
103 if (*string
< 48 || *string
> 57) {
106 result
= result
* 10 + ( *string
- 48 );
113 static void print_rpcs(char *c_procs
, int i_procs
, int labels
)
117 unsigned int proc_num
;
118 struct rpcent
*rpcent
;
121 for (proc_ctr
=0; proc_ctr
<= i_procs
; proc_ctr
++) {
127 proc_ptr
+= proc_ctr
* IPT_RPC_CHAR_LEN
;
128 proc_num
= k_atoi(proc_ptr
);
130 /* labels(1) == no labels, only numbers
131 * labels(2) == no numbers, only labels
132 * labels(3) == both labels and numbers
135 if (labels
== IPT_RPC_INT_LBL
|| labels
== IPT_RPC_INT_BTH
) {
136 if ( (rpcent
= getrpcbynumber(proc_num
)) == NULL
)
139 printf("%s", rpcent
->r_name
);
142 if (labels
== IPT_RPC_INT_BTH
)
145 if (labels
== IPT_RPC_INT_NUM
|| labels
== IPT_RPC_INT_BTH
)
146 printf("%i", proc_num
);
148 if (labels
== IPT_RPC_INT_BTH
)
156 static void help(void)
160 " --rpcs list,of,procedures"
161 "\ta list of rpc program numbers to apply\n"
162 "\t\t\t\tie. 100003,mountd,rquotad (numeric or\n"
163 "\t\t\t\tname form; see /etc/rpc).\n"
165 "\t\t\ta flag to force the drop of packets\n"
166 "\t\t\t\tnot containing \"get\" portmapper requests.\n",
171 static struct option opts
[] = {
172 { "rpcs", 1, 0, '1'},
173 { "strict", 0, 0, '2'},
178 static void init(struct ipt_entry_match
*match
, unsigned int *nfcache
)
180 struct ipt_rpc_info
*rpcinfo
= ((struct ipt_rpc_info
*)match
->data
);
184 /* initialise those funky user vars */
185 rpcinfo
->i_procs
= -1;
187 memset((char *)rpcinfo
->c_procs
, 0, sizeof(rpcinfo
->c_procs
));
191 static void parse_rpcs_string(char *string
, struct ipt_entry_match
**match
)
193 char err1
[64] = "%s invalid --rpcs option-set: `%s' (at character %i)";
194 char err2
[64] = "%s unable to resolve rpc name entry: `%s'";
195 char err3
[64] = "%s maximum number of --rpc options (%i) exceeded";
202 struct rpcent
*rpcent_ptr
;
203 struct ipt_rpc_info
*rpcinfo
= (struct ipt_rpc_info
*)(*match
)->data
;
206 memset(buf
, 0, sizeof(buf
));
208 for (src
=string
, dst
=buf
; term
!= 1 ; src
++, dst
++) {
210 if ( *src
!= ',' && *src
!= '\0' ) {
211 if ( ( *src
>= 65 && *src
<= 90 ) || ( *src
>= 97 && *src
<= 122) ) {
215 } else if ( *src
>= 48 && *src
<= 57 ) {
219 exit_error(PARAMETER_PROBLEM
, err1
, preerr
,
220 string
, src
- string
+ 1);
227 if ( (rpcent_ptr
= getrpcbyname(dup
)) == NULL
)
228 exit_error(PARAMETER_PROBLEM
, err2
,
230 idup
= rpcent_ptr
->r_number
;
236 if ( rpcinfo
->i_procs
> IPT_RPC_MAX_ENTS
)
237 exit_error(PARAMETER_PROBLEM
, err3
, preerr
,
240 c_procs
= (char *)rpcinfo
->c_procs
;
241 c_procs
+= rpcinfo
->i_procs
* IPT_RPC_CHAR_LEN
;
243 memset(buf
, 0, sizeof(buf
));
244 k_itoa((char *)dup
, idup
);
246 strcpy(c_procs
, dup
);
252 memset(buf
, 0, sizeof(buf
));
253 dst
= (char *)buf
- 1;
261 static int parse(int c
, char **argv
, int invert
, unsigned int *flags
,
262 const struct ipt_entry
*entry
,
263 unsigned int *nfcache
,
264 struct ipt_entry_match
**match
)
266 struct ipt_rpc_info
*rpcinfo
= (struct ipt_rpc_info
*)(*match
)->data
;
273 exit_error(PARAMETER_PROBLEM
,
274 "%s unexpected '!' with --rpcs\n", preerr
);
275 if (*flags
& IPT_RPC_RPCS
)
276 exit_error(PARAMETER_PROBLEM
,
277 "%s repeated use of --rpcs\n", preerr
);
278 parse_rpcs_string(optarg
, match
);
280 *flags
|= IPT_RPC_RPCS
;
285 exit_error(PARAMETER_PROBLEM
,
286 "%s unexpected '!' with --strict\n", preerr
);
287 if (*flags
& IPT_RPC_STRC
)
288 exit_error(PARAMETER_PROBLEM
,
289 "%s repeated use of --strict\n", preerr
);
291 *flags
|= IPT_RPC_STRC
;
303 static void final_check(unsigned int flags
)
305 if (flags
!= (flags
| IPT_RPC_RPCS
)) {
306 printf("%s option \"--rpcs\" was not used ... reverting ", preerr
);
307 printf("to old \"record-rpc\" functionality ..\n");
312 static void print(const struct ipt_ip
*ip
,
313 const struct ipt_entry_match
*match
,
316 struct ipt_rpc_info
*rpcinfo
= ((struct ipt_rpc_info
*)match
->data
);
320 if(rpcinfo
->strict
== 1)
325 if(rpcinfo
->i_procs
== -1) {
329 print_rpcs((char *)&rpcinfo
->c_procs
, rpcinfo
->i_procs
, IPT_RPC_INT_BTH
);
336 static void save(const struct ipt_ip
*ip
, const struct ipt_entry_match
*match
)
338 struct ipt_rpc_info
*rpcinfo
= ((struct ipt_rpc_info
*)match
->data
);
341 if(rpcinfo
->i_procs
> -1) {
343 print_rpcs((char *)&rpcinfo
->c_procs
, rpcinfo
->i_procs
, IPT_RPC_INT_NUM
);
347 if(rpcinfo
->strict
== 1)
353 static struct iptables_match rpcstruct
= {
356 .version
= IPTABLES_VERSION
,
357 .size
= IPT_ALIGN(sizeof(struct ipt_rpc_info
)),
358 .userspacesize
= IPT_ALIGN(sizeof(struct ipt_rpc_info
)),
362 .final_check
= &final_check
,
371 register_match(&rpcstruct
);