ip_ftp_pxy.c (170268) | ip_ftp_pxy.c (255332) |
---|---|
1/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 170268 2007-06-04 02:54:36Z darrenr $ */ | 1/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 255332 2013-09-06 23:11:19Z cy $ */ |
2 3/* | 2 3/* |
4 * Copyright (C) 1997-2003 by Darren Reed | 4 * Copyright (C) 2012 by Darren Reed. |
5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * Simple FTP transparent proxy for in-kernel use. For use with the NAT 9 * code. 10 * | 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * Simple FTP transparent proxy for in-kernel use. For use with the NAT 9 * code. 10 * |
11 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 170268 2007-06-04 02:54:36Z darrenr $ | 11 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 255332 2013-09-06 23:11:19Z cy $ |
12 * Id: ip_ftp_pxy.c,v 2.88.2.19 2006/04/01 10:14:53 darrenr Exp $ 13 */ 14 15#define IPF_FTP_PROXY 16 17#define IPF_MINPORTLEN 18 | 12 * Id: ip_ftp_pxy.c,v 2.88.2.19 2006/04/01 10:14:53 darrenr Exp $ 13 */ 14 15#define IPF_FTP_PROXY 16 17#define IPF_MINPORTLEN 18 |
18#define IPF_MINEPRTLEN 20 |
|
18#define IPF_MAXPORTLEN 30 19#define IPF_MIN227LEN 39 20#define IPF_MAX227LEN 51 21#define IPF_MIN229LEN 47 22#define IPF_MAX229LEN 51 23 24#define FTPXY_GO 0 25#define FTPXY_INIT 1 --- 7 unchanged lines hidden (view full) --- 33#define FTPXY_ADOK_1 9 34#define FTPXY_ACCT_1 10 35#define FTPXY_ACOK_1 11 36#define FTPXY_USER_2 12 37#define FTPXY_USOK_2 13 38#define FTPXY_PASS_2 14 39#define FTPXY_PAOK_2 15 40 | 19#define IPF_MAXPORTLEN 30 20#define IPF_MIN227LEN 39 21#define IPF_MAX227LEN 51 22#define IPF_MIN229LEN 47 23#define IPF_MAX229LEN 51 24 25#define FTPXY_GO 0 26#define FTPXY_INIT 1 --- 7 unchanged lines hidden (view full) --- 34#define FTPXY_ADOK_1 9 35#define FTPXY_ACCT_1 10 36#define FTPXY_ACOK_1 11 37#define FTPXY_USER_2 12 38#define FTPXY_USOK_2 13 39#define FTPXY_PASS_2 14 40#define FTPXY_PAOK_2 15 41 |
42#define FTPXY_JUNK_OK 0 43#define FTPXY_JUNK_BAD 1 /* Ignore all commands for this connection */ 44#define FTPXY_JUNK_EOL 2 /* consume the rest of this line only */ 45#define FTPXY_JUNK_CONT 3 /* Saerching for next numeric */ 46 |
|
41/* 42 * Values for FTP commands. Numerics cover 0-999 43 */ 44#define FTPXY_C_PASV 1000 | 47/* 48 * Values for FTP commands. Numerics cover 0-999 49 */ 50#define FTPXY_C_PASV 1000 |
51#define FTPXY_C_PORT 1001 52#define FTPXY_C_EPSV 1002 53#define FTPXY_C_EPRT 1003 |
|
45 | 54 |
46int ippr_ftp_client __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); 47int ippr_ftp_complete __P((char *, size_t)); 48int ippr_ftp_in __P((fr_info_t *, ap_session_t *, nat_t *)); 49int ippr_ftp_init __P((void)); 50void ippr_ftp_fini __P((void)); 51int ippr_ftp_new __P((fr_info_t *, ap_session_t *, nat_t *)); 52int ippr_ftp_out __P((fr_info_t *, ap_session_t *, nat_t *)); 53int ippr_ftp_pasv __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); 54int ippr_ftp_epsv __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); 55int ippr_ftp_port __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); 56int ippr_ftp_process __P((fr_info_t *, nat_t *, ftpinfo_t *, int)); 57int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); 58int ippr_ftp_valid __P((ftpinfo_t *, int, char *, size_t)); 59int ippr_ftp_server_valid __P((ftpside_t *, char *, size_t)); 60int ippr_ftp_client_valid __P((ftpside_t *, char *, size_t)); 61u_short ippr_ftp_atoi __P((char **)); 62int ippr_ftp_pasvreply __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, 63 u_int, char *, char *, u_int)); | |
64 | 55 |
56typedef struct ipf_ftp_softc_s { 57 int ipf_p_ftp_pasvonly; 58 /* Do not require logins before transfers */ 59 int ipf_p_ftp_insecure; 60 int ipf_p_ftp_pasvrdr; 61 /* PASV must be last command prior to 227 */ 62 int ipf_p_ftp_forcepasv; 63 int ipf_p_ftp_debug; 64 int ipf_p_ftp_single_xfer; 65 void *ipf_p_ftp_tune; 66} ipf_ftp_softc_t; |
|
65 | 67 |
66int ftp_proxy_init = 0; 67int ippr_ftp_pasvonly = 0; 68int ippr_ftp_insecure = 0; /* Do not require logins before transfers */ 69int ippr_ftp_pasvrdr = 0; 70int ippr_ftp_forcepasv = 0; /* PASV must be last command prior to 227 */ 71#if defined(_KERNEL) 72int ippr_ftp_debug = 0; 73#else 74int ippr_ftp_debug = 2; 75#endif | 68 69void ipf_p_ftp_main_load __P((void)); 70void ipf_p_ftp_main_unload __P((void)); 71void *ipf_p_ftp_soft_create __P((ipf_main_softc_t *)); 72void ipf_p_ftp_soft_destroy __P((ipf_main_softc_t *, void *)); 73 74int ipf_p_ftp_client __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 75 ftpinfo_t *, int)); 76int ipf_p_ftp_complete __P((char *, size_t)); 77int ipf_p_ftp_in __P((void *, fr_info_t *, ap_session_t *, nat_t *)); 78int ipf_p_ftp_new __P((void *, fr_info_t *, ap_session_t *, nat_t *)); 79void ipf_p_ftp_del __P((ipf_main_softc_t *, ap_session_t *)); 80int ipf_p_ftp_out __P((void *, fr_info_t *, ap_session_t *, nat_t *)); 81int ipf_p_ftp_pasv __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 82 ftpinfo_t *, int)); 83int ipf_p_ftp_epsv __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 84 ftpinfo_t *, int)); 85int ipf_p_ftp_port __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 86 ftpinfo_t *, int)); 87int ipf_p_ftp_process __P((ipf_ftp_softc_t *, fr_info_t *, nat_t *, 88 ftpinfo_t *, int)); 89int ipf_p_ftp_server __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 90 ftpinfo_t *, int)); 91int ipf_p_ftp_valid __P((ipf_ftp_softc_t *, ftpinfo_t *, int, char *, size_t)); 92int ipf_p_ftp_server_valid __P((ipf_ftp_softc_t *, ftpside_t *, char *, 93 size_t)); 94int ipf_p_ftp_client_valid __P((ipf_ftp_softc_t *, ftpside_t *, char *, 95 size_t)); 96u_short ipf_p_ftp_atoi __P((char **)); 97int ipf_p_ftp_pasvreply __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 98 ftpinfo_t *, u_int, char *, char *)); 99int ipf_p_ftp_eprt __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 100 ftpinfo_t *, int)); 101int ipf_p_ftp_eprt4 __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 102 ftpinfo_t *, int)); 103int ipf_p_ftp_eprt6 __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 104 ftpinfo_t *, int)); 105int ipf_p_ftp_addport __P((ipf_ftp_softc_t *, fr_info_t *, ip_t *, nat_t *, 106 ftpinfo_t *, int, int, int)); 107void ipf_p_ftp_setpending __P((ipf_main_softc_t *, ftpinfo_t *)); 108 |
76/* | 109/* |
77 * 1 - security 78 * 2 - errors 79 * 3 - error debugging 80 * 4 - parsing errors 81 * 5 - parsing info 82 * 6 - parsing debug | 110 * Debug levels |
83 */ | 111 */ |
112#define DEBUG_SECURITY 0x01 113#define DEBUG_ERROR 0x02 114#define DEBUG_INFO 0x04 115#define DEBUG_PARSE_ERR 0x08 116#define DEBUG_PARSE_INFO 0x10 117#define DEBUG_PARSE 0x20 |
|
84 | 118 |
119static int ipf_p_ftp_proxy_init = 0; |
|
85static frentry_t ftppxyfr; | 120static frentry_t ftppxyfr; |
86static ipftuneable_t ftptune = { 87 { &ippr_ftp_debug }, 88 "ippr_ftp_debug", 89 0, 90 10, 91 sizeof(ippr_ftp_debug), 92 0, 93 NULL | 121static ipftuneable_t ipf_ftp_tuneables[] = { 122 { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_debug) }, 123 "ftp_debug", 0, 0x7f, 124 stsizeof(ipf_ftp_softc_t, ipf_p_ftp_debug), 125 0, NULL, NULL }, 126 { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_pasvonly) }, 127 "ftp_pasvonly", 0, 1, 128 stsizeof(ipf_ftp_softc_t, ipf_p_ftp_pasvonly), 129 0, NULL, NULL }, 130 { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_insecure) }, 131 "ftp_insecure", 0, 1, 132 stsizeof(ipf_ftp_softc_t, ipf_p_ftp_insecure), 133 0, NULL, NULL }, 134 { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_pasvrdr) }, 135 "ftp_pasvrdr", 0, 1, 136 stsizeof(ipf_ftp_softc_t, ipf_p_ftp_pasvrdr), 137 0, NULL, NULL }, 138 { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_forcepasv) }, 139 "ftp_forcepasv", 0, 1, 140 stsizeof(ipf_ftp_softc_t, ipf_p_ftp_forcepasv), 141 0, NULL, NULL }, 142 { { (void *)offsetof(ipf_ftp_softc_t, ipf_p_ftp_single_xfer) }, 143 "ftp_single_xfer", 0, 1, 144 stsizeof(ipf_ftp_softc_t, ipf_p_ftp_single_xfer), 145 0, NULL, NULL }, 146 { { NULL }, NULL, 0, 0, 0, 0, NULL, NULL } |
94}; 95 96 | 147}; 148 149 |
97/* 98 * Initialize local structures. 99 */ 100int ippr_ftp_init() | 150void 151ipf_p_ftp_main_load() |
101{ 102 bzero((char *)&ftppxyfr, sizeof(ftppxyfr)); 103 ftppxyfr.fr_ref = 1; 104 ftppxyfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; | 152{ 153 bzero((char *)&ftppxyfr, sizeof(ftppxyfr)); 154 ftppxyfr.fr_ref = 1; 155 ftppxyfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; |
105 MUTEX_INIT(&ftppxyfr.fr_lock, "FTP Proxy Mutex"); 106 ftp_proxy_init = 1; 107 (void) fr_addipftune(&ftptune); | |
108 | 156 |
109 return 0; | 157 MUTEX_INIT(&ftppxyfr.fr_lock, "FTP Proxy Mutex"); 158 ipf_p_ftp_proxy_init = 1; |
110} 111 112 | 159} 160 161 |
113void ippr_ftp_fini() | 162void 163ipf_p_ftp_main_unload() |
114{ | 164{ |
115 (void) fr_delipftune(&ftptune); | |
116 | 165 |
117 if (ftp_proxy_init == 1) { | 166 if (ipf_p_ftp_proxy_init == 1) { |
118 MUTEX_DESTROY(&ftppxyfr.fr_lock); | 167 MUTEX_DESTROY(&ftppxyfr.fr_lock); |
119 ftp_proxy_init = 0; | 168 ipf_p_ftp_proxy_init = 0; |
120 } 121} 122 123 | 169 } 170} 171 172 |
124int ippr_ftp_new(fin, aps, nat) 125fr_info_t *fin; 126ap_session_t *aps; 127nat_t *nat; | 173/* 174 * Initialize local structures. 175 */ 176void * 177ipf_p_ftp_soft_create(softc) 178 ipf_main_softc_t *softc; |
128{ | 179{ |
180 ipf_ftp_softc_t *softf; 181 182 KMALLOC(softf, ipf_ftp_softc_t *); 183 if (softf == NULL) 184 return NULL; 185 186 bzero((char *)softf, sizeof(*softf)); 187#if defined(_KERNEL) 188 softf->ipf_p_ftp_debug = 0; 189#else 190 softf->ipf_p_ftp_debug = DEBUG_PARSE_ERR; 191#endif 192 softf->ipf_p_ftp_forcepasv = 1; 193 194 softf->ipf_p_ftp_tune = ipf_tune_array_copy(softf, 195 sizeof(ipf_ftp_tuneables), 196 ipf_ftp_tuneables); 197 if (softf->ipf_p_ftp_tune == NULL) { 198 ipf_p_ftp_soft_destroy(softc, softf); 199 return NULL; 200 } 201 if (ipf_tune_array_link(softc, softf->ipf_p_ftp_tune) == -1) { 202 ipf_p_ftp_soft_destroy(softc, softf); 203 return NULL; 204 } 205 206 return softf; 207} 208 209 210void 211ipf_p_ftp_soft_destroy(softc, arg) 212 ipf_main_softc_t *softc; 213 void *arg; 214{ 215 ipf_ftp_softc_t *softf = arg; 216 217 if (softf->ipf_p_ftp_tune != NULL) { 218 ipf_tune_array_unlink(softc, softf->ipf_p_ftp_tune); 219 KFREES(softf->ipf_p_ftp_tune, sizeof(ipf_ftp_tuneables)); 220 softf->ipf_p_ftp_tune = NULL; 221 } 222 223 KFREE(softf); 224} 225 226 227int 228ipf_p_ftp_new(arg, fin, aps, nat) 229 void *arg; 230 fr_info_t *fin; 231 ap_session_t *aps; 232 nat_t *nat; 233{ |
|
129 ftpinfo_t *ftp; 130 ftpside_t *f; 131 132 KMALLOC(ftp, ftpinfo_t *); 133 if (ftp == NULL) 134 return -1; 135 | 234 ftpinfo_t *ftp; 235 ftpside_t *f; 236 237 KMALLOC(ftp, ftpinfo_t *); 238 if (ftp == NULL) 239 return -1; 240 |
136 fin = fin; /* LINT */ | |
137 nat = nat; /* LINT */ 138 139 aps->aps_data = ftp; 140 aps->aps_psiz = sizeof(ftpinfo_t); | 241 nat = nat; /* LINT */ 242 243 aps->aps_data = ftp; 244 aps->aps_psiz = sizeof(ftpinfo_t); |
245 aps->aps_sport = htons(fin->fin_sport); 246 aps->aps_dport = htons(fin->fin_dport); |
|
141 142 bzero((char *)ftp, sizeof(*ftp)); 143 f = &ftp->ftp_side[0]; 144 f->ftps_rptr = f->ftps_buf; 145 f->ftps_wptr = f->ftps_buf; 146 f = &ftp->ftp_side[1]; 147 f->ftps_rptr = f->ftps_buf; 148 f->ftps_wptr = f->ftps_buf; 149 ftp->ftp_passok = FTPXY_INIT; 150 ftp->ftp_incok = 0; 151 return 0; 152} 153 154 | 247 248 bzero((char *)ftp, sizeof(*ftp)); 249 f = &ftp->ftp_side[0]; 250 f->ftps_rptr = f->ftps_buf; 251 f->ftps_wptr = f->ftps_buf; 252 f = &ftp->ftp_side[1]; 253 f->ftps_rptr = f->ftps_buf; 254 f->ftps_wptr = f->ftps_buf; 255 ftp->ftp_passok = FTPXY_INIT; 256 ftp->ftp_incok = 0; 257 return 0; 258} 259 260 |
155int ippr_ftp_port(fin, ip, nat, f, dlen) 156fr_info_t *fin; 157ip_t *ip; 158nat_t *nat; 159ftpside_t *f; 160int dlen; | 261void 262ipf_p_ftp_setpending(ipf_main_softc_t *softc, ftpinfo_t *ftp) |
161{ | 263{ |
162 tcphdr_t *tcp, tcph, *tcp2 = &tcph; | 264 if (ftp->ftp_pendnat != NULL) 265 ipf_nat_setpending(softc, ftp->ftp_pendnat); 266 267 if (ftp->ftp_pendstate != NULL) { 268 READ_ENTER(&softc->ipf_state); 269 ipf_state_setpending(softc, ftp->ftp_pendstate); 270 RWLOCK_EXIT(&softc->ipf_state); 271 } 272} 273 274 275void 276ipf_p_ftp_del(softc, aps) 277 ipf_main_softc_t *softc; 278 ap_session_t *aps; 279{ 280 ftpinfo_t *ftp; 281 282 ftp = aps->aps_data; 283 if (ftp != NULL) 284 ipf_p_ftp_setpending(softc, ftp); 285} 286 287 288int 289ipf_p_ftp_port(softf, fin, ip, nat, ftp, dlen) 290 ipf_ftp_softc_t *softf; 291 fr_info_t *fin; 292 ip_t *ip; 293 nat_t *nat; 294 ftpinfo_t *ftp; 295 int dlen; 296{ |
163 char newbuf[IPF_FTPBUFSZ], *s; | 297 char newbuf[IPF_FTPBUFSZ], *s; |
164 struct in_addr swip, swip2; | |
165 u_int a1, a2, a3, a4; | 298 u_int a1, a2, a3, a4; |
166 int inc, off, flags; | |
167 u_short a5, a6, sp; 168 size_t nlen, olen; | 299 u_short a5, a6, sp; 300 size_t nlen, olen; |
169 fr_info_t fi; 170 nat_t *nat2; | 301 tcphdr_t *tcp; 302 int inc, off; 303 ftpside_t *f; |
171 mb_t *m; 172 173 m = fin->fin_m; | 304 mb_t *m; 305 306 m = fin->fin_m; |
307 f = &ftp->ftp_side[0]; |
|
174 tcp = (tcphdr_t *)fin->fin_dp; 175 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 176 177 /* 178 * Check for client sending out PORT message. 179 */ 180 if (dlen < IPF_MINPORTLEN) { | 308 tcp = (tcphdr_t *)fin->fin_dp; 309 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 310 311 /* 312 * Check for client sending out PORT message. 313 */ 314 if (dlen < IPF_MINPORTLEN) { |
181 if (ippr_ftp_debug > 1) 182 printf("ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", | 315 DT3(ftp_PORT_error_dlen, nat_t *, nat, ftpside_t *, f, 316 u_int, dlen); 317 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) 318 printf("ipf_p_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", |
183 dlen); 184 return 0; 185 } 186 /* 187 * Skip the PORT command + space 188 */ 189 s = f->ftps_rptr + 5; 190 /* 191 * Pick out the address components, two at a time. 192 */ | 319 dlen); 320 return 0; 321 } 322 /* 323 * Skip the PORT command + space 324 */ 325 s = f->ftps_rptr + 5; 326 /* 327 * Pick out the address components, two at a time. 328 */ |
193 a1 = ippr_ftp_atoi(&s); | 329 a1 = ipf_p_ftp_atoi(&s); |
194 if (s == NULL) { | 330 if (s == NULL) { |
195 if (ippr_ftp_debug > 1) 196 printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 1); | 331 DT2(ftp_PORT_error_atoi_1, nat_t *, nat, ftpside_t *, f); 332 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 333 printf("ipf_p_ftp_port:ipf_p_ftp_atoi(%d) failed\n", 1); |
197 return 0; 198 } | 334 return 0; 335 } |
199 a2 = ippr_ftp_atoi(&s); | 336 a2 = ipf_p_ftp_atoi(&s); |
200 if (s == NULL) { | 337 if (s == NULL) { |
201 if (ippr_ftp_debug > 1) 202 printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 2); | 338 DT2(ftp_PORT_error_atoi_2, nat_t *, nat, ftpside_t *, f); 339 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 340 printf("ipf_p_ftp_port:ipf_p_ftp_atoi(%d) failed\n", 2); |
203 return 0; 204 } 205 206 /* 207 * Check that IP address in the PORT/PASV reply is the same as the 208 * sender of the command - prevents using PORT for port scanning. 209 */ 210 a1 <<= 16; 211 a1 |= a2; 212 if (((nat->nat_dir == NAT_OUTBOUND) && | 341 return 0; 342 } 343 344 /* 345 * Check that IP address in the PORT/PASV reply is the same as the 346 * sender of the command - prevents using PORT for port scanning. 347 */ 348 a1 <<= 16; 349 a1 |= a2; 350 if (((nat->nat_dir == NAT_OUTBOUND) && |
213 (a1 != ntohl(nat->nat_inip.s_addr))) || | 351 (a1 != ntohl(nat->nat_osrcaddr))) || |
214 ((nat->nat_dir == NAT_INBOUND) && | 352 ((nat->nat_dir == NAT_INBOUND) && |
215 (a1 != ntohl(nat->nat_oip.s_addr)))) { 216 if (ippr_ftp_debug > 0) 217 printf("ippr_ftp_port:%s != nat->nat_inip\n", "a1"); | 353 (a1 != ntohl(nat->nat_nsrcaddr)))) { 354 DT3(ftp_PORT_error_address, nat_t *, nat, ftpside_t *, f, 355 u_int, a1); 356 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 357 printf("ipf_p_ftp_port:%s != nat->nat_inip\n", "a1"); |
218 return APR_ERR(1); 219 } 220 | 358 return APR_ERR(1); 359 } 360 |
221 a5 = ippr_ftp_atoi(&s); | 361 a5 = ipf_p_ftp_atoi(&s); |
222 if (s == NULL) { | 362 if (s == NULL) { |
223 if (ippr_ftp_debug > 1) 224 printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 3); | 363 DT2(ftp_PORT_error_atoi_3, nat_t *, nat, ftpside_t *, f); 364 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 365 printf("ipf_p_ftp_port:ipf_p_ftp_atoi(%d) failed\n", 3); |
225 return 0; 226 } 227 if (*s == ')') 228 s++; 229 230 /* 231 * check for CR-LF at the end. 232 */ 233 if (*s == '\n') 234 s--; | 366 return 0; 367 } 368 if (*s == ')') 369 s++; 370 371 /* 372 * check for CR-LF at the end. 373 */ 374 if (*s == '\n') 375 s--; |
235 if ((*s == '\r') && (*(s + 1) == '\n')) { 236 s += 2; 237 a6 = a5 & 0xff; 238 } else { 239 if (ippr_ftp_debug > 1) 240 printf("ippr_ftp_port:missing %s\n", "cr-lf"); | 376 if ((*s != '\r') || (*(s + 1) != '\n')) { 377 DT2(ftp_PORT_error_no_crlf, nat_t *, nat, ftpside_t *, f); 378 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 379 printf("ipf_p_ftp_port:missing %s\n", "cr-lf"); |
241 return 0; 242 } | 380 return 0; 381 } |
382 s += 2; 383 a6 = a5 & 0xff; |
|
243 | 384 |
385 /* 386 * Calculate the source port. Verification of > 1024 is in 387 * ipf_p_ftp_addport. 388 */ |
|
244 a5 >>= 8; 245 a5 &= 0xff; 246 sp = a5 << 8 | a6; | 389 a5 >>= 8; 390 a5 &= 0xff; 391 sp = a5 << 8 | a6; |
392 |
|
247 /* | 393 /* |
248 * Don't allow the PORT command to specify a port < 1024 due to 249 * security crap. 250 */ 251 if (sp < 1024) { 252 if (ippr_ftp_debug > 0) 253 printf("ippr_ftp_port:sp(%d) < 1024\n", sp); 254 return 0; 255 } 256 /* | |
257 * Calculate new address parts for PORT command 258 */ 259 if (nat->nat_dir == NAT_INBOUND) | 394 * Calculate new address parts for PORT command 395 */ 396 if (nat->nat_dir == NAT_INBOUND) |
260 a1 = ntohl(nat->nat_oip.s_addr); | 397 a1 = ntohl(nat->nat_ndstaddr); |
261 else 262 a1 = ntohl(ip->ip_src.s_addr); | 398 else 399 a1 = ntohl(ip->ip_src.s_addr); |
400 a1 = ntohl(ip->ip_src.s_addr); |
|
263 a2 = (a1 >> 16) & 0xff; 264 a3 = (a1 >> 8) & 0xff; 265 a4 = a1 & 0xff; 266 a1 >>= 24; 267 olen = s - f->ftps_rptr; 268 /* DO NOT change this to snprintf! */ 269#if defined(SNPRINTF) && defined(_KERNEL) 270 SNPRINTF(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n", 271 "PORT", a1, a2, a3, a4, a5, a6); 272#else 273 (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", 274 "PORT", a1, a2, a3, a4, a5, a6); 275#endif 276 277 nlen = strlen(newbuf); 278 inc = nlen - olen; | 401 a2 = (a1 >> 16) & 0xff; 402 a3 = (a1 >> 8) & 0xff; 403 a4 = a1 & 0xff; 404 a1 >>= 24; 405 olen = s - f->ftps_rptr; 406 /* DO NOT change this to snprintf! */ 407#if defined(SNPRINTF) && defined(_KERNEL) 408 SNPRINTF(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n", 409 "PORT", a1, a2, a3, a4, a5, a6); 410#else 411 (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", 412 "PORT", a1, a2, a3, a4, a5, a6); 413#endif 414 415 nlen = strlen(newbuf); 416 inc = nlen - olen; |
279 if ((inc + ip->ip_len) > 65535) { 280 if (ippr_ftp_debug > 0) 281 printf("ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n", | 417 if ((inc + fin->fin_plen) > 65535) { 418 DT3(ftp_PORT_error_inc, nat_t *, nat, ftpside_t *, f, 419 int, inc); 420 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 421 printf("ipf_p_ftp_port:inc(%d) + ip->ip_len > 65535\n", |
282 inc); 283 return 0; 284 } 285 286#if !defined(_KERNEL) | 422 inc); 423 return 0; 424 } 425 426#if !defined(_KERNEL) |
287 bcopy(newbuf, MTOD(m, char *) + off, nlen); | 427 M_ADJ(m, inc); |
288#else | 428#else |
289# if defined(MENTAT) 290 if (inc < 0) 291 (void)adjmsg(m, inc); 292# else /* defined(MENTAT) */ | |
293 /* 294 * m_adj takes care of pkthdr.len, if required and treats inc<0 to 295 * mean remove -len bytes from the end of the packet. 296 * The mbuf chain will be extended if necessary by m_copyback(). 297 */ 298 if (inc < 0) | 429 /* 430 * m_adj takes care of pkthdr.len, if required and treats inc<0 to 431 * mean remove -len bytes from the end of the packet. 432 * The mbuf chain will be extended if necessary by m_copyback(). 433 */ 434 if (inc < 0) |
299 m_adj(m, inc); 300# endif /* defined(MENTAT) */ | 435 M_ADJ(m, inc); |
301#endif /* !defined(_KERNEL) */ 302 COPYBACK(m, off, nlen, newbuf); | 436#endif /* !defined(_KERNEL) */ 437 COPYBACK(m, off, nlen, newbuf); |
438 fin->fin_flx |= FI_DOCKSUM; |
|
303 304 if (inc != 0) { | 439 440 if (inc != 0) { |
305 ip->ip_len += inc; 306 fin->fin_dlen += inc; | |
307 fin->fin_plen += inc; | 441 fin->fin_plen += inc; |
442 ip->ip_len = htons(fin->fin_plen); 443 fin->fin_dlen += inc; |
|
308 } 309 | 444 } 445 |
446 f->ftps_cmd = FTPXY_C_PORT; 447 return ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, sp, inc); 448} 449 450 451int 452ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, nport, inc) 453 ipf_ftp_softc_t *softf; 454 fr_info_t *fin; 455 ip_t *ip; 456 nat_t *nat; 457 ftpinfo_t *ftp; 458 int dlen, nport, inc; 459{ 460 tcphdr_t tcph, *tcp2 = &tcph; 461 ipf_main_softc_t *softc; 462 ipf_nat_softc_t *softn; 463 int direction; 464 fr_info_t fi; 465 ipnat_t *ipn; 466 nat_t *nat2; 467 u_short sp; 468 int flags; 469 470 softc = fin->fin_main_soft; 471 softn = softc->ipf_nat_soft; 472 473 if ((ftp->ftp_pendnat != NULL) || (ftp->ftp_pendstate != NULL)) { 474 if (softf->ipf_p_ftp_single_xfer != 0) { 475 DT2(ftp_PORT_error_add_active, nat_t *, nat, 476 ftpinfo_t *, ftp); 477 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 478 printf("ipf_p_ftp_addport:xfer active %p/%p\n", 479 ftp->ftp_pendnat, ftp->ftp_pendstate); 480 return 0; 481 } 482 ipf_p_ftp_setpending(softc, ftp); 483 } 484 |
|
310 /* | 485 /* |
486 * Add skeleton NAT entry for connection which will come back the 487 * other way. 488 */ 489 sp = nport; 490 /* 491 * Don't allow the PORT command to specify a port < 1024 due to 492 * security risks. 493 */ 494 if (sp < 1024) { 495 DT3(ftp_PORT_error_port, nat_t *, nat, ftpinfo_t *, ftp, 496 u_int, sp); 497 if (softf->ipf_p_ftp_debug & DEBUG_SECURITY) 498 printf("ipf_p_ftp_addport:sp(%d) < 1024\n", sp); 499 return 0; 500 } 501 /* |
|
311 * The server may not make the connection back from port 20, but 312 * it is the most likely so use it here to check for a conflicting 313 * mapping. 314 */ 315 bcopy((char *)fin, (char *)&fi, sizeof(fi)); | 502 * The server may not make the connection back from port 20, but 503 * it is the most likely so use it here to check for a conflicting 504 * mapping. 505 */ 506 bcopy((char *)fin, (char *)&fi, sizeof(fi)); |
316 fi.fin_state = NULL; 317 fi.fin_nat = NULL; | |
318 fi.fin_flx |= FI_IGNORE; 319 fi.fin_data[0] = sp; 320 fi.fin_data[1] = fin->fin_data[1] - 1; | 507 fi.fin_flx |= FI_IGNORE; 508 fi.fin_data[0] = sp; 509 fi.fin_data[1] = fin->fin_data[1] - 1; |
510 fi.fin_src6 = nat->nat_ndst6; 511 fi.fin_dst6 = nat->nat_nsrc6; 512 513 if (nat->nat_v[0] == 6) { 514#ifndef USE_INET6 515 return APR_INC(inc); 516#endif 517 } 518 |
|
321 /* 322 * Add skeleton NAT entry for connection which will come back the 323 * other way. 324 */ | 519 /* 520 * Add skeleton NAT entry for connection which will come back the 521 * other way. 522 */ |
325 if (nat->nat_dir == NAT_OUTBOUND) 326 nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, 327 nat->nat_inip, nat->nat_oip); 328 else 329 nat2 = nat_inlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, 330 nat->nat_inip, nat->nat_oip); 331 if (nat2 == NULL) { 332 int slen; 333 334 slen = ip->ip_len; 335 ip->ip_len = fin->fin_hlen + sizeof(*tcp2); 336 bzero((char *)tcp2, sizeof(*tcp2)); 337 tcp2->th_win = htons(8192); 338 tcp2->th_sport = htons(sp); 339 TCP_OFF_A(tcp2, 5); 340 tcp2->th_flags = TH_SYN; 341 tcp2->th_dport = 0; /* XXX - don't specify remote port */ 342 fi.fin_data[1] = 0; 343 fi.fin_dlen = sizeof(*tcp2); 344 fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); 345 fi.fin_dp = (char *)tcp2; 346 fi.fin_fr = &ftppxyfr; 347 fi.fin_out = nat->nat_dir; 348 fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; 349 swip = ip->ip_src; 350 swip2 = ip->ip_dst; | 523#ifdef USE_INET6 524 if (nat->nat_v[0] == 6) { |
351 if (nat->nat_dir == NAT_OUTBOUND) { | 525 if (nat->nat_dir == NAT_OUTBOUND) { |
352 fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; 353 ip->ip_src = nat->nat_inip; 354 } else if (nat->nat_dir == NAT_INBOUND) { 355 fi.fin_fi.fi_saddr = nat->nat_oip.s_addr; 356 ip->ip_src = nat->nat_oip; | 526 nat2 = ipf_nat6_outlookup(&fi, IPN_TCP|NAT_SEARCH, 527 nat->nat_pr[1], 528 &nat->nat_osrc6.in6, 529 &nat->nat_odst6.in6); 530 } else { 531 nat2 = ipf_nat6_inlookup(&fi, IPN_TCP|NAT_SEARCH, 532 nat->nat_pr[0], 533 &nat->nat_odst6.in6, 534 &nat->nat_osrc6.in6); |
357 } | 535 } |
536 } else 537#endif 538 { 539 if (nat->nat_dir == NAT_OUTBOUND) { 540 nat2 = ipf_nat_outlookup(&fi, IPN_TCP|NAT_SEARCH, 541 nat->nat_pr[1], 542 nat->nat_osrcip, 543 nat->nat_odstip); 544 } else { 545 nat2 = ipf_nat_inlookup(&fi, IPN_TCP|NAT_SEARCH, 546 nat->nat_pr[0], 547 nat->nat_odstip, 548 nat->nat_osrcip); 549 } 550 } 551 if (nat2 != NULL) 552 return APR_INC(inc); |
|
358 | 553 |
359 flags = NAT_SLAVE|IPN_TCP|SI_W_DPORT; 360 if (nat->nat_dir == NAT_INBOUND) 361 flags |= NAT_NOTRULEPORT; 362 nat2 = nat_new(&fi, nat->nat_ptr, NULL, flags, nat->nat_dir); | 554 ipn = ipf_proxy_rule_rev(nat); 555 if (ipn == NULL) 556 return APR_ERR(1); 557 ipn->in_use = 0; |
363 | 558 |
364 if (nat2 != NULL) { 365 (void) nat_proto(&fi, nat2, IPN_TCP); 366 nat_update(&fi, nat2, nat->nat_ptr); 367 fi.fin_ifp = NULL; 368 if (nat->nat_dir == NAT_INBOUND) { 369 fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; 370 ip->ip_dst = nat->nat_inip; 371 } 372 (void) fr_addstate(&fi, NULL, SI_W_DPORT); 373 if (fi.fin_state != NULL) 374 fr_statederef((ipstate_t **)&fi.fin_state); 375 } 376 ip->ip_len = slen; 377 ip->ip_src = swip; 378 ip->ip_dst = swip2; | 559 fi.fin_fr = &ftppxyfr; 560 fi.fin_dp = (char *)tcp2; 561 fi.fin_dlen = sizeof(*tcp2); 562 fi.fin_plen = fi.fin_hlen + sizeof(*tcp2); 563 fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; 564 fi.fin_data[1] = sp; 565 fi.fin_data[0] = 0; 566 567 bzero((char *)tcp2, sizeof(*tcp2)); 568 tcp2->th_sport = 0; 569 tcp2->th_dport = htons(sp); 570 571 tcp2->th_win = htons(8192); 572 TCP_OFF_A(tcp2, 5); 573 tcp2->th_flags = TH_SYN; 574 575 if (nat->nat_dir == NAT_INBOUND) { 576 fi.fin_out = 1; 577 direction = NAT_OUTBOUND; 578 } else { 579 fi.fin_out = 0; 580 direction = NAT_INBOUND; |
379 } | 581 } |
582 flags = SI_W_SPORT|NAT_SLAVE|IPN_TCP; 583 584 MUTEX_ENTER(&softn->ipf_nat_new); 585 if (nat->nat_v[0] == 6) { 586#ifdef USE_INET6 587 nat2 = ipf_nat6_add(&fi, ipn, &ftp->ftp_pendnat, flags, 588 direction); 589#endif 590 } else { 591 nat2 = ipf_nat_add(&fi, ipn, &ftp->ftp_pendnat, flags, 592 direction); 593 } 594 MUTEX_EXIT(&softn->ipf_nat_new); 595 596 if (nat2 == NULL) { 597 KFREES(ipn, ipn->in_size); 598 return APR_ERR(1); 599 } 600 601 (void) ipf_nat_proto(&fi, nat2, IPN_TCP); 602 MUTEX_ENTER(&nat2->nat_lock); 603 ipf_nat_update(&fi, nat2); 604 MUTEX_EXIT(&nat2->nat_lock); 605 fi.fin_ifp = NULL; 606 if (nat2->nat_dir == NAT_INBOUND) 607 fi.fin_dst6 = nat->nat_osrc6; 608 if (ipf_state_add(softc, &fi, (ipstate_t **)&ftp->ftp_pendstate, 609 SI_W_SPORT) != 0) 610 ipf_nat_setpending(softc, nat2); 611 |
|
380 return APR_INC(inc); 381} 382 383 | 612 return APR_INC(inc); 613} 614 615 |
384int ippr_ftp_client(fin, ip, nat, ftp, dlen) 385fr_info_t *fin; 386nat_t *nat; 387ftpinfo_t *ftp; 388ip_t *ip; 389int dlen; | 616int 617ipf_p_ftp_client(softf, fin, ip, nat, ftp, dlen) 618 ipf_ftp_softc_t *softf; 619 fr_info_t *fin; 620 nat_t *nat; 621 ftpinfo_t *ftp; 622 ip_t *ip; 623 int dlen; |
390{ 391 char *rptr, *wptr, cmd[6], c; 392 ftpside_t *f; 393 int inc, i; 394 395 inc = 0; 396 f = &ftp->ftp_side[0]; 397 rptr = f->ftps_rptr; --- 5 unchanged lines hidden (view full) --- 403 cmd[i] = TOUPPER(c); 404 } else { 405 cmd[i] = c; 406 } 407 } 408 cmd[i] = '\0'; 409 410 ftp->ftp_incok = 0; | 624{ 625 char *rptr, *wptr, cmd[6], c; 626 ftpside_t *f; 627 int inc, i; 628 629 inc = 0; 630 f = &ftp->ftp_side[0]; 631 rptr = f->ftps_rptr; --- 5 unchanged lines hidden (view full) --- 637 cmd[i] = TOUPPER(c); 638 } else { 639 cmd[i] = c; 640 } 641 } 642 cmd[i] = '\0'; 643 644 ftp->ftp_incok = 0; |
645 DT2(ftp_client_command, char [], cmd, int, ftp->ftp_passok); |
|
411 if (!strncmp(cmd, "USER ", 5) || !strncmp(cmd, "XAUT ", 5)) { 412 if (ftp->ftp_passok == FTPXY_ADOK_1 || 413 ftp->ftp_passok == FTPXY_AUOK_1) { 414 ftp->ftp_passok = FTPXY_USER_2; 415 ftp->ftp_incok = 1; 416 } else { 417 ftp->ftp_passok = FTPXY_USER_1; 418 ftp->ftp_incok = 1; --- 13 unchanged lines hidden (view full) --- 432 !strncmp(cmd, "ADAT ", 5)) { 433 ftp->ftp_passok = FTPXY_ADAT_1; 434 ftp->ftp_incok = 1; 435 } else if ((ftp->ftp_passok == FTPXY_PAOK_1 || 436 ftp->ftp_passok == FTPXY_PAOK_2) && 437 !strncmp(cmd, "ACCT ", 5)) { 438 ftp->ftp_passok = FTPXY_ACCT_1; 439 ftp->ftp_incok = 1; | 646 if (!strncmp(cmd, "USER ", 5) || !strncmp(cmd, "XAUT ", 5)) { 647 if (ftp->ftp_passok == FTPXY_ADOK_1 || 648 ftp->ftp_passok == FTPXY_AUOK_1) { 649 ftp->ftp_passok = FTPXY_USER_2; 650 ftp->ftp_incok = 1; 651 } else { 652 ftp->ftp_passok = FTPXY_USER_1; 653 ftp->ftp_incok = 1; --- 13 unchanged lines hidden (view full) --- 667 !strncmp(cmd, "ADAT ", 5)) { 668 ftp->ftp_passok = FTPXY_ADAT_1; 669 ftp->ftp_incok = 1; 670 } else if ((ftp->ftp_passok == FTPXY_PAOK_1 || 671 ftp->ftp_passok == FTPXY_PAOK_2) && 672 !strncmp(cmd, "ACCT ", 5)) { 673 ftp->ftp_passok = FTPXY_ACCT_1; 674 ftp->ftp_incok = 1; |
440 } else if ((ftp->ftp_passok == FTPXY_GO) && !ippr_ftp_pasvonly && | 675 } else if ((ftp->ftp_passok == FTPXY_GO) && 676 !softf->ipf_p_ftp_pasvonly && |
441 !strncmp(cmd, "PORT ", 5)) { | 677 !strncmp(cmd, "PORT ", 5)) { |
442 inc = ippr_ftp_port(fin, ip, nat, f, dlen); 443 } else if (ippr_ftp_insecure && !ippr_ftp_pasvonly && | 678 inc = ipf_p_ftp_port(softf, fin, ip, nat, ftp, dlen); 679 } else if ((ftp->ftp_passok == FTPXY_GO) && 680 !softf->ipf_p_ftp_pasvonly && 681 !strncmp(cmd, "EPRT ", 5)) { 682 inc = ipf_p_ftp_eprt(softf, fin, ip, nat, ftp, dlen); 683 } else if (softf->ipf_p_ftp_insecure && 684 !softf->ipf_p_ftp_pasvonly && |
444 !strncmp(cmd, "PORT ", 5)) { | 685 !strncmp(cmd, "PORT ", 5)) { |
445 inc = ippr_ftp_port(fin, ip, nat, f, dlen); | 686 inc = ipf_p_ftp_port(softf, fin, ip, nat, ftp, dlen); |
446 } | 687 } |
688 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) 689 printf("ipf_p_ftp_client: cmd[%s] passok %d incok %d inc %d\n", 690 cmd, ftp->ftp_passok, ftp->ftp_incok, inc); |
|
447 | 691 |
692 DT2(ftp_client_passok, char *, cmd, int, ftp->ftp_passok); |
|
448 while ((*rptr++ != '\n') && (rptr < wptr)) 449 ; 450 f->ftps_rptr = rptr; 451 return inc; 452} 453 454 | 693 while ((*rptr++ != '\n') && (rptr < wptr)) 694 ; 695 f->ftps_rptr = rptr; 696 return inc; 697} 698 699 |
455int ippr_ftp_pasv(fin, ip, nat, ftp, dlen) 456fr_info_t *fin; 457ip_t *ip; 458nat_t *nat; 459ftpinfo_t *ftp; 460int dlen; | 700int 701ipf_p_ftp_pasv(softf, fin, ip, nat, ftp, dlen) 702 ipf_ftp_softc_t *softf; 703 fr_info_t *fin; 704 ip_t *ip; 705 nat_t *nat; 706 ftpinfo_t *ftp; 707 int dlen; |
461{ 462 u_int a1, a2, a3, a4, data_ip; 463 char newbuf[IPF_FTPBUFSZ]; 464 const char *brackets[2]; 465 u_short a5, a6; 466 ftpside_t *f; 467 char *s; 468 | 708{ 709 u_int a1, a2, a3, a4, data_ip; 710 char newbuf[IPF_FTPBUFSZ]; 711 const char *brackets[2]; 712 u_short a5, a6; 713 ftpside_t *f; 714 char *s; 715 |
469 if (ippr_ftp_forcepasv != 0 && 470 ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) { 471 if (ippr_ftp_debug > 0) 472 printf("ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n", 473 ftp->ftp_side[0].ftps_cmds); | 716 if ((softf->ipf_p_ftp_forcepasv != 0) && 717 (ftp->ftp_side[0].ftps_cmd != FTPXY_C_PASV)) { 718 DT2(ftp_PASV_error_state, nat_t *, nat, ftpinfo_t *, ftp); 719 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 720 printf("ipf_p_ftp_pasv:ftps_cmd(%d) != FTPXY_C_PASV\n", 721 ftp->ftp_side[0].ftps_cmd); |
474 return 0; 475 } 476 477 f = &ftp->ftp_side[1]; 478 479#define PASV_REPLEN 24 480 /* 481 * Check for PASV reply message. 482 */ 483 if (dlen < IPF_MIN227LEN) { | 722 return 0; 723 } 724 725 f = &ftp->ftp_side[1]; 726 727#define PASV_REPLEN 24 728 /* 729 * Check for PASV reply message. 730 */ 731 if (dlen < IPF_MIN227LEN) { |
484 if (ippr_ftp_debug > 1) 485 printf("ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", | 732 DT3(ftp_PASV_error_short, nat_t *, nat, ftpinfo_t *, ftp, 733 int, dlen); 734 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 735 printf("ipf_p_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", |
486 dlen); 487 return 0; 488 } else if (strncmp(f->ftps_rptr, 489 "227 Entering Passive Mod", PASV_REPLEN)) { | 736 dlen); 737 return 0; 738 } else if (strncmp(f->ftps_rptr, 739 "227 Entering Passive Mod", PASV_REPLEN)) { |
490 if (ippr_ftp_debug > 0) 491 printf("ippr_ftp_pasv:%d reply wrong\n", 227); | 740 DT2(ftp_PASV_error_string, nat_t *, nat, ftpinfo_t *, ftp); 741 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 742 printf("ipf_p_ftp_pasv:%d reply wrong\n", 227); |
492 return 0; 493 } 494 495 brackets[0] = ""; 496 brackets[1] = ""; 497 /* 498 * Skip the PASV reply + space 499 */ --- 4 unchanged lines hidden (view full) --- 504 brackets[1] = ")"; 505 } 506 s++; 507 } 508 509 /* 510 * Pick out the address components, two at a time. 511 */ | 743 return 0; 744 } 745 746 brackets[0] = ""; 747 brackets[1] = ""; 748 /* 749 * Skip the PASV reply + space 750 */ --- 4 unchanged lines hidden (view full) --- 755 brackets[1] = ")"; 756 } 757 s++; 758 } 759 760 /* 761 * Pick out the address components, two at a time. 762 */ |
512 a1 = ippr_ftp_atoi(&s); | 763 a1 = ipf_p_ftp_atoi(&s); |
513 if (s == NULL) { | 764 if (s == NULL) { |
514 if (ippr_ftp_debug > 1) 515 printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 1); | 765 DT2(ftp_PASV_error_atoi_1, nat_t *, nat, ftpside_t *, f); 766 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 767 printf("ipf_p_ftp_pasv:ipf_p_ftp_atoi(%d) failed\n", 1); |
516 return 0; 517 } | 768 return 0; 769 } |
518 a2 = ippr_ftp_atoi(&s); | 770 a2 = ipf_p_ftp_atoi(&s); |
519 if (s == NULL) { | 771 if (s == NULL) { |
520 if (ippr_ftp_debug > 1) 521 printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 2); | 772 DT2(ftp_PASV_error_atoi_2, nat_t *, nat, ftpside_t *, f); 773 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 774 printf("ipf_p_ftp_pasv:ipf_p_ftp_atoi(%d) failed\n", 2); |
522 return 0; 523 } 524 525 /* 526 * check that IP address in the PASV reply is the same as the 527 * sender of the command - prevents using PASV for port scanning. 528 */ 529 a1 <<= 16; 530 a1 |= a2; 531 532 if (((nat->nat_dir == NAT_INBOUND) && | 775 return 0; 776 } 777 778 /* 779 * check that IP address in the PASV reply is the same as the 780 * sender of the command - prevents using PASV for port scanning. 781 */ 782 a1 <<= 16; 783 a1 |= a2; 784 785 if (((nat->nat_dir == NAT_INBOUND) && |
533 (a1 != ntohl(nat->nat_inip.s_addr))) || | 786 (a1 != ntohl(nat->nat_ndstaddr))) || |
534 ((nat->nat_dir == NAT_OUTBOUND) && | 787 ((nat->nat_dir == NAT_OUTBOUND) && |
535 (a1 != ntohl(nat->nat_oip.s_addr)))) { 536 if (ippr_ftp_debug > 0) 537 printf("ippr_ftp_pasv:%s != nat->nat_oip\n", "a1"); | 788 (a1 != ntohl(nat->nat_odstaddr)))) { 789 DT3(ftp_PASV_error_address, nat_t *, nat, ftpside_t *, f, 790 u_int, a1); 791 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 792 printf("ipf_p_ftp_pasv:%s != nat->nat_oip\n", "a1"); |
538 return 0; 539 } 540 | 793 return 0; 794 } 795 |
541 a5 = ippr_ftp_atoi(&s); | 796 a5 = ipf_p_ftp_atoi(&s); |
542 if (s == NULL) { | 797 if (s == NULL) { |
543 if (ippr_ftp_debug > 1) 544 printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 3); | 798 DT2(ftp_PASV_error_atoi_3, nat_t *, nat, ftpside_t *, f); 799 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 800 printf("ipf_p_ftp_pasv:ipf_p_ftp_atoi(%d) failed\n", 3); |
545 return 0; 546 } 547 548 if (*s == ')') 549 s++; 550 if (*s == '.') 551 s++; 552 if (*s == '\n') 553 s--; 554 /* 555 * check for CR-LF at the end. 556 */ | 801 return 0; 802 } 803 804 if (*s == ')') 805 s++; 806 if (*s == '.') 807 s++; 808 if (*s == '\n') 809 s--; 810 /* 811 * check for CR-LF at the end. 812 */ |
557 if ((*s == '\r') && (*(s + 1) == '\n')) { 558 s += 2; 559 } else { 560 if (ippr_ftp_debug > 1) 561 printf("ippr_ftp_pasv:missing %s", "cr-lf\n"); | 813 if ((*s != '\r') || (*(s + 1) != '\n')) { 814 DT(pasv_missing_crlf); 815 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 816 printf("ipf_p_ftp_pasv:missing %s", "cr-lf\n"); |
562 return 0; 563 } | 817 return 0; 818 } |
819 s += 2; |
|
564 565 a6 = a5 & 0xff; 566 a5 >>= 8; 567 /* 568 * Calculate new address parts for 227 reply 569 */ 570 if (nat->nat_dir == NAT_INBOUND) { | 820 821 a6 = a5 & 0xff; 822 a5 >>= 8; 823 /* 824 * Calculate new address parts for 227 reply 825 */ 826 if (nat->nat_dir == NAT_INBOUND) { |
571 data_ip = nat->nat_outip.s_addr; | 827 data_ip = nat->nat_odstaddr; |
572 a1 = ntohl(data_ip); 573 } else 574 data_ip = htonl(a1); 575 576 a2 = (a1 >> 16) & 0xff; 577 a3 = (a1 >> 8) & 0xff; 578 a4 = a1 & 0xff; 579 a1 >>= 24; 580 581#if defined(SNPRINTF) && defined(_KERNEL) 582 SNPRINTF(newbuf, sizeof(newbuf), "%s %s%u,%u,%u,%u,%u,%u%s\r\n", 583 "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, 584 a5, a6, brackets[1]); 585#else 586 (void) sprintf(newbuf, "%s %s%u,%u,%u,%u,%u,%u%s\r\n", 587 "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, 588 a5, a6, brackets[1]); 589#endif | 828 a1 = ntohl(data_ip); 829 } else 830 data_ip = htonl(a1); 831 832 a2 = (a1 >> 16) & 0xff; 833 a3 = (a1 >> 8) & 0xff; 834 a4 = a1 & 0xff; 835 a1 >>= 24; 836 837#if defined(SNPRINTF) && defined(_KERNEL) 838 SNPRINTF(newbuf, sizeof(newbuf), "%s %s%u,%u,%u,%u,%u,%u%s\r\n", 839 "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, 840 a5, a6, brackets[1]); 841#else 842 (void) sprintf(newbuf, "%s %s%u,%u,%u,%u,%u,%u%s\r\n", 843 "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, 844 a5, a6, brackets[1]); 845#endif |
590 return ippr_ftp_pasvreply(fin, ip, nat, f, (a5 << 8 | a6), 591 newbuf, s, data_ip); | 846 return ipf_p_ftp_pasvreply(softf, fin, ip, nat, ftp, (a5 << 8 | a6), 847 newbuf, s); |
592} 593 | 848} 849 |
594int ippr_ftp_pasvreply(fin, ip, nat, f, port, newmsg, s, data_ip) 595fr_info_t *fin; 596ip_t *ip; 597nat_t *nat; 598ftpside_t *f; 599u_int port; 600char *newmsg; 601char *s; 602u_int data_ip; | 850int 851ipf_p_ftp_pasvreply(softf, fin, ip, nat, ftp, port, newmsg, s) 852 ipf_ftp_softc_t *softf; 853 fr_info_t *fin; 854 ip_t *ip; 855 nat_t *nat; 856 ftpinfo_t *ftp; 857 u_int port; 858 char *newmsg; 859 char *s; |
603{ | 860{ |
604 int inc, off, nflags, sflags; | 861 int inc, off, nflags; |
605 tcphdr_t *tcp, tcph, *tcp2; | 862 tcphdr_t *tcp, tcph, *tcp2; |
606 struct in_addr swip, swip2; 607 struct in_addr data_addr; | 863 ipf_main_softc_t *softc; 864 ipf_nat_softc_t *softn; |
608 size_t nlen, olen; | 865 size_t nlen, olen; |
866#ifdef USE_INET6 867 ip6_t *ip6; 868#endif 869 ipnat_t *ipn; |
|
609 fr_info_t fi; | 870 fr_info_t fi; |
871 ftpside_t *f; |
|
610 nat_t *nat2; 611 mb_t *m; 612 | 872 nat_t *nat2; 873 mb_t *m; 874 |
875 softc = fin->fin_main_soft; 876 softn = softc->ipf_nat_soft; 877 878 if ((ftp->ftp_pendnat != NULL) || (ftp->ftp_pendstate != NULL)) 879 ipf_p_ftp_setpending(softc, ftp); 880 |
|
613 m = fin->fin_m; 614 tcp = (tcphdr_t *)fin->fin_dp; 615 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 616 | 881 m = fin->fin_m; 882 tcp = (tcphdr_t *)fin->fin_dp; 883 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 884 |
617 data_addr.s_addr = data_ip; | |
618 tcp2 = &tcph; 619 inc = 0; 620 | 885 tcp2 = &tcph; 886 inc = 0; 887 |
621 | 888 f = &ftp->ftp_side[1]; |
622 olen = s - f->ftps_rptr; 623 nlen = strlen(newmsg); 624 inc = nlen - olen; | 889 olen = s - f->ftps_rptr; 890 nlen = strlen(newmsg); 891 inc = nlen - olen; |
625 if ((inc + ip->ip_len) > 65535) { 626 if (ippr_ftp_debug > 0) 627 printf("ippr_ftp_pasv:inc(%d) + ip->ip_len > 65535\n", | 892 if ((inc + fin->fin_plen) > 65535) { 893 DT3(ftp_PASV_error_inc, nat_t *, nat, ftpside_t *, f, 894 int, inc); 895 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 896 printf("ipf_p_ftp_pasv:inc(%d) + ip->ip_len > 65535\n", |
628 inc); 629 return 0; 630 } 631 | 897 inc); 898 return 0; 899 } 900 |
632#if !defined(_KERNEL) 633 bcopy(newmsg, MTOD(m, char *) + off, nlen); 634#else 635# if defined(MENTAT) 636 if (inc < 0) 637 (void)adjmsg(m, inc); 638# else /* defined(MENTAT) */ 639 /* 640 * m_adj takes care of pkthdr.len, if required and treats inc<0 to 641 * mean remove -len bytes from the end of the packet. 642 * The mbuf chain will be extended if necessary by m_copyback(). 643 */ 644 if (inc < 0) 645 m_adj(m, inc); 646# endif /* defined(MENTAT) */ 647#endif /* !defined(_KERNEL) */ 648 COPYBACK(m, off, nlen, newmsg); | 901 ipn = ipf_proxy_rule_fwd(nat); 902 if (ipn == NULL) 903 return APR_ERR(1); 904 ipn->in_use = 0; |
649 | 905 |
650 if (inc != 0) { 651 ip->ip_len += inc; 652 fin->fin_dlen += inc; 653 fin->fin_plen += inc; 654 } 655 | |
656 /* 657 * Add skeleton NAT entry for connection which will come back the 658 * other way. 659 */ | 906 /* 907 * Add skeleton NAT entry for connection which will come back the 908 * other way. 909 */ |
910 bzero((char *)tcp2, sizeof(*tcp2)); |
|
660 bcopy((char *)fin, (char *)&fi, sizeof(fi)); | 911 bcopy((char *)fin, (char *)&fi, sizeof(fi)); |
661 fi.fin_state = NULL; 662 fi.fin_nat = NULL; | |
663 fi.fin_flx |= FI_IGNORE; 664 fi.fin_data[0] = 0; 665 fi.fin_data[1] = port; 666 nflags = IPN_TCP|SI_W_SPORT; | 912 fi.fin_flx |= FI_IGNORE; 913 fi.fin_data[0] = 0; 914 fi.fin_data[1] = port; 915 nflags = IPN_TCP|SI_W_SPORT; |
667 if (ippr_ftp_pasvrdr && f->ftps_ifp) 668 nflags |= SI_W_DPORT; 669 if (nat->nat_dir == NAT_OUTBOUND) 670 nat2 = nat_outlookup(&fi, nflags|NAT_SEARCH, 671 nat->nat_p, nat->nat_inip, nat->nat_oip); | 916 917 fi.fin_fr = &ftppxyfr; 918 fi.fin_dp = (char *)tcp2; 919 fi.fin_out = 1 - fin->fin_out; 920 fi.fin_dlen = sizeof(*tcp2); 921 fi.fin_src6 = nat->nat_osrc6; 922 fi.fin_dst6 = nat->nat_odst6; 923 fi.fin_plen = fi.fin_hlen + sizeof(*tcp); 924 fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; 925 926 TCP_OFF_A(tcp2, 5); 927 tcp2->th_flags = TH_SYN; 928 tcp2->th_win = htons(8192); 929 tcp2->th_dport = htons(port); 930 931 MUTEX_ENTER(&softn->ipf_nat_new); 932#ifdef USE_INET6 933 if (nat->nat_v[0] == 6) 934 nat2 = ipf_nat6_add(&fi, ipn, &ftp->ftp_pendnat, 935 nflags, nat->nat_dir); |
672 else | 936 else |
673 nat2 = nat_inlookup(&fi, nflags|NAT_SEARCH, 674 nat->nat_p, nat->nat_inip, nat->nat_oip); | 937#endif 938 nat2 = ipf_nat_add(&fi, ipn, &ftp->ftp_pendnat, 939 nflags, nat->nat_dir); 940 MUTEX_EXIT(&softn->ipf_nat_new); 941 |
675 if (nat2 == NULL) { | 942 if (nat2 == NULL) { |
676 int slen; | 943 KFREES(ipn, ipn->in_size); 944 return APR_ERR(1); 945 } |
677 | 946 |
678 slen = ip->ip_len; 679 ip->ip_len = fin->fin_hlen + sizeof(*tcp2); 680 bzero((char *)tcp2, sizeof(*tcp2)); 681 tcp2->th_win = htons(8192); 682 tcp2->th_sport = 0; /* XXX - fake it for nat_new */ 683 TCP_OFF_A(tcp2, 5); 684 tcp2->th_flags = TH_SYN; 685 fi.fin_data[1] = port; 686 fi.fin_dlen = sizeof(*tcp2); 687 tcp2->th_dport = htons(port); 688 fi.fin_data[0] = 0; 689 fi.fin_dp = (char *)tcp2; 690 fi.fin_plen = fi.fin_hlen + sizeof(*tcp); 691 fi.fin_fr = &ftppxyfr; 692 fi.fin_out = nat->nat_dir; 693 fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE; 694 swip = ip->ip_src; 695 swip2 = ip->ip_dst; 696 if (nat->nat_dir == NAT_OUTBOUND) { 697 fi.fin_fi.fi_daddr = data_addr.s_addr; 698 fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; 699 ip->ip_dst = data_addr; 700 ip->ip_src = nat->nat_inip; 701 } else if (nat->nat_dir == NAT_INBOUND) { 702 fi.fin_fi.fi_saddr = nat->nat_oip.s_addr; 703 fi.fin_fi.fi_daddr = nat->nat_outip.s_addr; 704 ip->ip_src = nat->nat_oip; 705 ip->ip_dst = nat->nat_outip; | 947 (void) ipf_nat_proto(&fi, nat2, IPN_TCP); 948 MUTEX_ENTER(&nat2->nat_lock); 949 ipf_nat_update(&fi, nat2); 950 MUTEX_EXIT(&nat2->nat_lock); 951 fi.fin_ifp = NULL; 952 if (nat->nat_dir == NAT_INBOUND) { 953 if (nat->nat_v[0] == 6) { 954#ifdef USE_INET6 955 fi.fin_dst6 = nat->nat_ndst6; 956#endif 957 } else { 958 fi.fin_daddr = nat->nat_ndstaddr; |
706 } | 959 } |
960 } 961 if (ipf_state_add(softc, &fi, (ipstate_t **)&ftp->ftp_pendstate, 962 SI_W_SPORT) != 0) 963 ipf_nat_setpending(softc, nat2); |
|
707 | 964 |
708 sflags = nflags; 709 nflags |= NAT_SLAVE; 710 if (nat->nat_dir == NAT_INBOUND) 711 nflags |= NAT_NOTRULEPORT; 712 nat2 = nat_new(&fi, nat->nat_ptr, NULL, nflags, nat->nat_dir); 713 if (nat2 != NULL) { 714 (void) nat_proto(&fi, nat2, IPN_TCP); 715 nat_update(&fi, nat2, nat->nat_ptr); 716 fi.fin_ifp = NULL; 717 if (nat->nat_dir == NAT_INBOUND) { 718 fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; 719 ip->ip_dst = nat->nat_inip; 720 } 721 (void) fr_addstate(&fi, NULL, sflags); 722 if (fi.fin_state != NULL) 723 fr_statederef((ipstate_t **)&fi.fin_state); 724 } | 965#if !defined(_KERNEL) 966 M_ADJ(m, inc); 967#else 968 /* 969 * m_adj takes care of pkthdr.len, if required and treats inc<0 to 970 * mean remove -len bytes from the end of the packet. 971 * The mbuf chain will be extended if necessary by m_copyback(). 972 */ 973 if (inc < 0) 974 M_ADJ(m, inc); 975#endif /* !defined(_KERNEL) */ 976 COPYBACK(m, off, nlen, newmsg); 977 fin->fin_flx |= FI_DOCKSUM; |
725 | 978 |
726 ip->ip_len = slen; 727 ip->ip_src = swip; 728 ip->ip_dst = swip2; | 979 if (inc != 0) { 980 fin->fin_plen += inc; 981 fin->fin_dlen += inc; 982 if (nat->nat_v[0] == 6) { 983#ifdef USE_INET6 984 ip6 = (ip6_t *)fin->fin_ip; 985 u_short len = ntohs(ip6->ip6_plen) + inc; 986 ip6->ip6_plen = htons(len); 987#endif 988 } else { 989 ip->ip_len = htons(fin->fin_plen); 990 } |
729 } | 991 } |
730 return inc; | 992 993 return APR_INC(inc); |
731} 732 733 | 994} 995 996 |
734int ippr_ftp_server(fin, ip, nat, ftp, dlen) 735fr_info_t *fin; 736ip_t *ip; 737nat_t *nat; 738ftpinfo_t *ftp; 739int dlen; | 997int 998ipf_p_ftp_server(softf, fin, ip, nat, ftp, dlen) 999 ipf_ftp_softc_t *softf; 1000 fr_info_t *fin; 1001 ip_t *ip; 1002 nat_t *nat; 1003 ftpinfo_t *ftp; 1004 int dlen; |
740{ 741 char *rptr, *wptr; 742 ftpside_t *f; 743 int inc; 744 745 inc = 0; 746 f = &ftp->ftp_side[1]; 747 rptr = f->ftps_rptr; 748 wptr = f->ftps_wptr; 749 | 1005{ 1006 char *rptr, *wptr; 1007 ftpside_t *f; 1008 int inc; 1009 1010 inc = 0; 1011 f = &ftp->ftp_side[1]; 1012 rptr = f->ftps_rptr; 1013 wptr = f->ftps_wptr; 1014 |
1015 DT2(ftp_server_response, char *, rptr, int, ftp->ftp_passok); |
|
750 if (*rptr == ' ') 751 goto server_cmd_ok; 752 if (!ISDIGIT(*rptr) || !ISDIGIT(*(rptr + 1)) || !ISDIGIT(*(rptr + 2))) 753 return 0; | 1016 if (*rptr == ' ') 1017 goto server_cmd_ok; 1018 if (!ISDIGIT(*rptr) || !ISDIGIT(*(rptr + 1)) || !ISDIGIT(*(rptr + 2))) 1019 return 0; |
1020 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) 1021 printf("ipf_p_ftp_server_1: cmd[%4.4s] passok %d\n", 1022 rptr, ftp->ftp_passok); |
|
754 if (ftp->ftp_passok == FTPXY_GO) { 755 if (!strncmp(rptr, "227 ", 4)) | 1023 if (ftp->ftp_passok == FTPXY_GO) { 1024 if (!strncmp(rptr, "227 ", 4)) |
756 inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen); | 1025 inc = ipf_p_ftp_pasv(softf, fin, ip, nat, ftp, dlen); |
757 else if (!strncmp(rptr, "229 ", 4)) | 1026 else if (!strncmp(rptr, "229 ", 4)) |
758 inc = ippr_ftp_epsv(fin, ip, nat, f, dlen); 759 } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) { 760 inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen); 761 } else if (ippr_ftp_insecure && !strncmp(rptr, "229 ", 4)) { 762 inc = ippr_ftp_epsv(fin, ip, nat, f, dlen); | 1027 inc = ipf_p_ftp_epsv(softf, fin, ip, nat, ftp, dlen); 1028 else if (strncmp(rptr, "200", 3)) { 1029 /* 1030 * 200 is returned for a successful command. 1031 */ 1032 ; 1033 } 1034 } else if (softf->ipf_p_ftp_insecure && !strncmp(rptr, "227 ", 4)) { 1035 inc = ipf_p_ftp_pasv(softf, fin, ip, nat, ftp, dlen); 1036 } else if (softf->ipf_p_ftp_insecure && !strncmp(rptr, "229 ", 4)) { 1037 inc = ipf_p_ftp_epsv(softf, fin, ip, nat, ftp, dlen); |
763 } else if (*rptr == '5' || *rptr == '4') 764 ftp->ftp_passok = FTPXY_INIT; 765 else if (ftp->ftp_incok) { 766 if (*rptr == '3') { 767 if (ftp->ftp_passok == FTPXY_ACCT_1) 768 ftp->ftp_passok = FTPXY_GO; 769 else 770 ftp->ftp_passok++; --- 8 unchanged lines hidden (view full) --- 779 ftp->ftp_passok = FTPXY_GO; 780 break; 781 default : 782 ftp->ftp_passok += 3; 783 break; 784 } 785 } 786 } | 1038 } else if (*rptr == '5' || *rptr == '4') 1039 ftp->ftp_passok = FTPXY_INIT; 1040 else if (ftp->ftp_incok) { 1041 if (*rptr == '3') { 1042 if (ftp->ftp_passok == FTPXY_ACCT_1) 1043 ftp->ftp_passok = FTPXY_GO; 1044 else 1045 ftp->ftp_passok++; --- 8 unchanged lines hidden (view full) --- 1054 ftp->ftp_passok = FTPXY_GO; 1055 break; 1056 default : 1057 ftp->ftp_passok += 3; 1058 break; 1059 } 1060 } 1061 } |
787server_cmd_ok: | |
788 ftp->ftp_incok = 0; | 1062 ftp->ftp_incok = 0; |
1063server_cmd_ok: 1064 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) 1065 printf("ipf_p_ftp_server_2: cmd[%4.4s] passok %d\n", 1066 rptr, ftp->ftp_passok); 1067 DT3(ftp_server_passok, char *,rptr, int, ftp->ftp_incok, 1068 int, ftp->ftp_passok); |
|
789 790 while ((*rptr++ != '\n') && (rptr < wptr)) 791 ; 792 f->ftps_rptr = rptr; 793 return inc; 794} 795 796 797/* | 1069 1070 while ((*rptr++ != '\n') && (rptr < wptr)) 1071 ; 1072 f->ftps_rptr = rptr; 1073 return inc; 1074} 1075 1076 1077/* |
1078 * 0 FTPXY_JUNK_OK 1079 * 1 FTPXY_JUNK_BAD 1080 * 2 FTPXY_JUNK_EOL 1081 * 3 FTPXY_JUNK_CONT 1082 * |
|
798 * Look to see if the buffer starts with something which we recognise as 799 * being the correct syntax for the FTP protocol. 800 */ | 1083 * Look to see if the buffer starts with something which we recognise as 1084 * being the correct syntax for the FTP protocol. 1085 */ |
801int ippr_ftp_client_valid(ftps, buf, len) 802ftpside_t *ftps; 803char *buf; 804size_t len; | 1086int 1087ipf_p_ftp_client_valid(softf, ftps, buf, len) 1088 ipf_ftp_softc_t *softf; 1089 ftpside_t *ftps; 1090 char *buf; 1091 size_t len; |
805{ 806 register char *s, c, pc; 807 register size_t i = len; 808 char cmd[5]; 809 810 s = buf; 811 | 1092{ 1093 register char *s, c, pc; 1094 register size_t i = len; 1095 char cmd[5]; 1096 1097 s = buf; 1098 |
812 if (ftps->ftps_junk == 1) 813 return 1; | 1099 if (ftps->ftps_junk == FTPXY_JUNK_BAD) 1100 return FTPXY_JUNK_BAD; |
814 815 if (i < 5) { | 1101 1102 if (i < 5) { |
816 if (ippr_ftp_debug > 3) 817 printf("ippr_ftp_client_valid:i(%d) < 5\n", (int)i); | 1103 DT1(client_valid, int, i); 1104 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 1105 printf("ipf_p_ftp_client_valid:i(%d) < 5\n", (int)i); |
818 return 2; 819 } 820 821 i--; 822 c = *s++; 823 824 if (ISALPHA(c)) { 825 cmd[0] = TOUPPER(c); --- 16 unchanged lines hidden (view full) --- 842 } else if ((c != ' ') && (c != '\r')) 843 goto bad_client_command; 844 } else 845 goto bad_client_command; 846 } else 847 goto bad_client_command; 848 } else { 849bad_client_command: | 1106 return 2; 1107 } 1108 1109 i--; 1110 c = *s++; 1111 1112 if (ISALPHA(c)) { 1113 cmd[0] = TOUPPER(c); --- 16 unchanged lines hidden (view full) --- 1130 } else if ((c != ' ') && (c != '\r')) 1131 goto bad_client_command; 1132 } else 1133 goto bad_client_command; 1134 } else 1135 goto bad_client_command; 1136 } else { 1137bad_client_command: |
850 if (ippr_ftp_debug > 3) | 1138 DT4(client_junk, int, len, int, i, int, c, char *, buf); 1139 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) |
851 printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n", | 1140 printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n", |
852 "ippr_ftp_client_valid", | 1141 "ipf_p_ftp_client_valid", |
853 ftps->ftps_junk, (int)len, (int)i, c, 854 (int)len, (int)len, buf); | 1142 ftps->ftps_junk, (int)len, (int)i, c, 1143 (int)len, (int)len, buf); |
855 return 1; | 1144 return FTPXY_JUNK_BAD; |
856 } 857 858 for (; i; i--) { 859 pc = c; 860 c = *s++; 861 if ((pc == '\r') && (c == '\n')) { 862 cmd[4] = '\0'; | 1145 } 1146 1147 for (; i; i--) { 1148 pc = c; 1149 c = *s++; 1150 if ((pc == '\r') && (c == '\n')) { 1151 cmd[4] = '\0'; |
863 if (!strcmp(cmd, "PASV")) 864 ftps->ftps_cmds = FTPXY_C_PASV; 865 else 866 ftps->ftps_cmds = 0; | 1152 if (!strcmp(cmd, "PASV")) { 1153 ftps->ftps_cmd = FTPXY_C_PASV; 1154 } else if (!strcmp(cmd, "EPSV")) { 1155 ftps->ftps_cmd = FTPXY_C_EPSV; 1156 } else { 1157 ftps->ftps_cmd = 0; 1158 } |
867 return 0; 868 } 869 } 870#if !defined(_KERNEL) | 1159 return 0; 1160 } 1161 } 1162#if !defined(_KERNEL) |
871 printf("ippr_ftp_client_valid:junk after cmd[%*.*s]\n", | 1163 printf("ipf_p_ftp_client_valid:junk after cmd[%*.*s]\n", |
872 (int)len, (int)len, buf); 873#endif | 1164 (int)len, (int)len, buf); 1165#endif |
874 return 2; | 1166 return FTPXY_JUNK_EOL; |
875} 876 877 | 1167} 1168 1169 |
878int ippr_ftp_server_valid(ftps, buf, len) 879ftpside_t *ftps; 880char *buf; 881size_t len; | 1170int 1171ipf_p_ftp_server_valid(softf, ftps, buf, len) 1172 ipf_ftp_softc_t *softf; 1173 ftpside_t *ftps; 1174 char *buf; 1175 size_t len; |
882{ 883 register char *s, c, pc; 884 register size_t i = len; 885 int cmd; 886 887 s = buf; 888 cmd = 0; 889 | 1176{ 1177 register char *s, c, pc; 1178 register size_t i = len; 1179 int cmd; 1180 1181 s = buf; 1182 cmd = 0; 1183 |
890 if (ftps->ftps_junk == 1) 891 return 1; | 1184 if (ftps->ftps_junk == FTPXY_JUNK_BAD) 1185 return FTPXY_JUNK_BAD; |
892 893 if (i < 5) { | 1186 1187 if (i < 5) { |
894 if (ippr_ftp_debug > 3) 895 printf("ippr_ftp_servert_valid:i(%d) < 5\n", (int)i); | 1188 DT1(server_valid, int, i); 1189 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 1190 printf("ipf_p_ftp_servert_valid:i(%d) < 5\n", (int)i); |
896 return 2; 897 } 898 899 c = *s++; 900 i--; | 1191 return 2; 1192 } 1193 1194 c = *s++; 1195 i--; |
901 if (c == ' ') | 1196 if (c == ' ') { 1197 cmd = -1; |
902 goto search_eol; | 1198 goto search_eol; |
1199 } |
|
903 904 if (ISDIGIT(c)) { 905 cmd = (c - '0') * 100; 906 c = *s++; 907 i--; 908 if (ISDIGIT(c)) { 909 cmd += (c - '0') * 10; 910 c = *s++; 911 i--; 912 if (ISDIGIT(c)) { 913 cmd += (c - '0'); 914 c = *s++; 915 i--; 916 if ((c != '-') && (c != ' ')) 917 goto bad_server_command; | 1200 1201 if (ISDIGIT(c)) { 1202 cmd = (c - '0') * 100; 1203 c = *s++; 1204 i--; 1205 if (ISDIGIT(c)) { 1206 cmd += (c - '0') * 10; 1207 c = *s++; 1208 i--; 1209 if (ISDIGIT(c)) { 1210 cmd += (c - '0'); 1211 c = *s++; 1212 i--; 1213 if ((c != '-') && (c != ' ')) 1214 goto bad_server_command; |
1215 if (c == '-') 1216 return FTPXY_JUNK_CONT; |
|
918 } else 919 goto bad_server_command; 920 } else 921 goto bad_server_command; 922 } else { 923bad_server_command: | 1217 } else 1218 goto bad_server_command; 1219 } else 1220 goto bad_server_command; 1221 } else { 1222bad_server_command: |
924 if (ippr_ftp_debug > 3) | 1223 DT4(server_junk, int len, buf, int, i, int, c, char *, buf); 1224 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_INFO) |
925 printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n", | 1225 printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n", |
926 "ippr_ftp_server_valid", | 1226 "ipf_p_ftp_server_valid", |
927 ftps->ftps_junk, (int)len, (int)i, 928 c, (int)len, (int)len, buf); | 1227 ftps->ftps_junk, (int)len, (int)i, 1228 c, (int)len, (int)len, buf); |
929 return 1; | 1229 if (ftps->ftps_junk == FTPXY_JUNK_CONT) 1230 return FTPXY_JUNK_CONT; 1231 return FTPXY_JUNK_BAD; |
930 } 931search_eol: 932 for (; i; i--) { 933 pc = c; 934 c = *s++; 935 if ((pc == '\r') && (c == '\n')) { | 1232 } 1233search_eol: 1234 for (; i; i--) { 1235 pc = c; 1236 c = *s++; 1237 if ((pc == '\r') && (c == '\n')) { |
936 ftps->ftps_cmds = cmd; 937 return 0; | 1238 if (cmd == -1) { 1239 if (ftps->ftps_junk == FTPXY_JUNK_CONT) 1240 return FTPXY_JUNK_CONT; 1241 } else { 1242 ftps->ftps_cmd = cmd; 1243 } 1244 return FTPXY_JUNK_OK; |
938 } 939 } | 1245 } 1246 } |
940 if (ippr_ftp_debug > 3) 941 printf("ippr_ftp_server_valid:junk after cmd[%*.*s]\n", | 1247 1248 DT2(junk_eol, int, len, char *, buf); 1249 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_INFO) 1250 printf("ipf_p_ftp_server_valid:junk after cmd[%*.*s]\n", |
942 (int)len, (int)len, buf); | 1251 (int)len, (int)len, buf); |
943 return 2; | 1252 return FTPXY_JUNK_EOL; |
944} 945 946 | 1253} 1254 1255 |
947int ippr_ftp_valid(ftp, side, buf, len) 948ftpinfo_t *ftp; 949int side; 950char *buf; 951size_t len; | 1256int 1257ipf_p_ftp_valid(softf, ftp, side, buf, len) 1258 ipf_ftp_softc_t *softf; 1259 ftpinfo_t *ftp; 1260 int side; 1261 char *buf; 1262 size_t len; |
952{ 953 ftpside_t *ftps; 954 int ret; 955 956 ftps = &ftp->ftp_side[side]; 957 958 if (side == 0) | 1263{ 1264 ftpside_t *ftps; 1265 int ret; 1266 1267 ftps = &ftp->ftp_side[side]; 1268 1269 if (side == 0) |
959 ret = ippr_ftp_client_valid(ftps, buf, len); | 1270 ret = ipf_p_ftp_client_valid(softf, ftps, buf, len); |
960 else | 1271 else |
961 ret = ippr_ftp_server_valid(ftps, buf, len); | 1272 ret = ipf_p_ftp_server_valid(softf, ftps, buf, len); |
962 return ret; 963} 964 965 966/* 967 * For map rules, the following applies: 968 * rv == 0 for outbound processing, 969 * rv == 1 for inbound processing. 970 * For rdr rules, the following applies: 971 * rv == 0 for inbound processing, 972 * rv == 1 for outbound processing. 973 */ | 1273 return ret; 1274} 1275 1276 1277/* 1278 * For map rules, the following applies: 1279 * rv == 0 for outbound processing, 1280 * rv == 1 for inbound processing. 1281 * For rdr rules, the following applies: 1282 * rv == 0 for inbound processing, 1283 * rv == 1 for outbound processing. 1284 */ |
974int ippr_ftp_process(fin, nat, ftp, rv) 975fr_info_t *fin; 976nat_t *nat; 977ftpinfo_t *ftp; 978int rv; | 1285int 1286ipf_p_ftp_process(softf, fin, nat, ftp, rv) 1287 ipf_ftp_softc_t *softf; 1288 fr_info_t *fin; 1289 nat_t *nat; 1290 ftpinfo_t *ftp; 1291 int rv; |
979{ | 1292{ |
980 int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff; | 1293 int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff, retry; |
981 char *rptr, *wptr, *s; 982 u_32_t thseq, thack; 983 ap_session_t *aps; 984 ftpside_t *f, *t; 985 tcphdr_t *tcp; 986 ip_t *ip; 987 mb_t *m; 988 989 m = fin->fin_m; 990 ip = fin->fin_ip; 991 tcp = (tcphdr_t *)fin->fin_dp; 992 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 993 994 f = &ftp->ftp_side[rv]; 995 t = &ftp->ftp_side[1 - rv]; 996 thseq = ntohl(tcp->th_seq); 997 thack = ntohl(tcp->th_ack); | 1294 char *rptr, *wptr, *s; 1295 u_32_t thseq, thack; 1296 ap_session_t *aps; 1297 ftpside_t *f, *t; 1298 tcphdr_t *tcp; 1299 ip_t *ip; 1300 mb_t *m; 1301 1302 m = fin->fin_m; 1303 ip = fin->fin_ip; 1304 tcp = (tcphdr_t *)fin->fin_dp; 1305 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 1306 1307 f = &ftp->ftp_side[rv]; 1308 t = &ftp->ftp_side[1 - rv]; 1309 thseq = ntohl(tcp->th_seq); 1310 thack = ntohl(tcp->th_ack); |
998 | |
999#ifdef __sgi 1000 mlen = fin->fin_plen - off; 1001#else 1002 mlen = MSGDSIZE(m) - off; 1003#endif | 1311#ifdef __sgi 1312 mlen = fin->fin_plen - off; 1313#else 1314 mlen = MSGDSIZE(m) - off; 1315#endif |
1004 if (ippr_ftp_debug > 4) 1005 printf("ippr_ftp_process: mlen %d\n", mlen); | |
1006 | 1316 |
1317 DT3(process_debug, tcphdr_t *, tcp, int, off, int, mlen); 1318 if (softf->ipf_p_ftp_debug & DEBUG_INFO) 1319 printf("ipf_p_ftp_process: %d:%d,%d, mlen %d flags %x\n", 1320 fin->fin_out, fin->fin_sport, fin->fin_dport, 1321 mlen, tcp->th_flags); 1322 |
|
1007 if ((mlen == 0) && ((tcp->th_flags & TH_OPENING) == TH_OPENING)) { 1008 f->ftps_seq[0] = thseq + 1; 1009 t->ftps_seq[0] = thack; 1010 return 0; 1011 } else if (mlen < 0) { 1012 return 0; 1013 } 1014 1015 aps = nat->nat_aps; 1016 1017 sel = aps->aps_sel[1 - rv]; 1018 sel2 = aps->aps_sel[rv]; | 1323 if ((mlen == 0) && ((tcp->th_flags & TH_OPENING) == TH_OPENING)) { 1324 f->ftps_seq[0] = thseq + 1; 1325 t->ftps_seq[0] = thack; 1326 return 0; 1327 } else if (mlen < 0) { 1328 return 0; 1329 } 1330 1331 aps = nat->nat_aps; 1332 1333 sel = aps->aps_sel[1 - rv]; 1334 sel2 = aps->aps_sel[rv]; |
1019 if (rv == 0) { | 1335 if (rv == 1) { |
1020 seqoff = aps->aps_seqoff[sel]; 1021 if (aps->aps_seqmin[sel] > seqoff + thseq) 1022 seqoff = aps->aps_seqoff[!sel]; 1023 ackoff = aps->aps_ackoff[sel2]; 1024 if (aps->aps_ackmin[sel2] > ackoff + thack) 1025 ackoff = aps->aps_ackoff[!sel2]; 1026 } else { 1027 seqoff = aps->aps_ackoff[sel]; | 1336 seqoff = aps->aps_seqoff[sel]; 1337 if (aps->aps_seqmin[sel] > seqoff + thseq) 1338 seqoff = aps->aps_seqoff[!sel]; 1339 ackoff = aps->aps_ackoff[sel2]; 1340 if (aps->aps_ackmin[sel2] > ackoff + thack) 1341 ackoff = aps->aps_ackoff[!sel2]; 1342 } else { 1343 seqoff = aps->aps_ackoff[sel]; |
1028 if (ippr_ftp_debug > 2) | 1344 if (softf->ipf_p_ftp_debug & DEBUG_INFO) |
1029 printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq, 1030 aps->aps_ackmin[sel]); 1031 if (aps->aps_ackmin[sel] > seqoff + thseq) 1032 seqoff = aps->aps_ackoff[!sel]; 1033 1034 ackoff = aps->aps_seqoff[sel2]; | 1345 printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq, 1346 aps->aps_ackmin[sel]); 1347 if (aps->aps_ackmin[sel] > seqoff + thseq) 1348 seqoff = aps->aps_ackoff[!sel]; 1349 1350 ackoff = aps->aps_seqoff[sel2]; |
1035 if (ippr_ftp_debug > 2) | 1351 if (softf->ipf_p_ftp_debug & DEBUG_INFO) |
1036 printf("ackoff %d thack %x seqmin %x\n", ackoff, thack, 1037 aps->aps_seqmin[sel2]); 1038 if (ackoff > 0) { 1039 if (aps->aps_seqmin[sel2] > ackoff + thack) 1040 ackoff = aps->aps_seqoff[!sel2]; 1041 } else { 1042 if (aps->aps_seqmin[sel2] > thack) 1043 ackoff = aps->aps_seqoff[!sel2]; 1044 } 1045 } | 1352 printf("ackoff %d thack %x seqmin %x\n", ackoff, thack, 1353 aps->aps_seqmin[sel2]); 1354 if (ackoff > 0) { 1355 if (aps->aps_seqmin[sel2] > ackoff + thack) 1356 ackoff = aps->aps_seqoff[!sel2]; 1357 } else { 1358 if (aps->aps_seqmin[sel2] > thack) 1359 ackoff = aps->aps_seqoff[!sel2]; 1360 } 1361 } |
1046 if (ippr_ftp_debug > 2) { | 1362 if (softf->ipf_p_ftp_debug & DEBUG_INFO) { |
1047 printf("%s: %x seq %x/%d ack %x/%d len %d/%d off %d\n", 1048 rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff, 1049 thack, ackoff, mlen, fin->fin_plen, off); 1050 printf("sel %d seqmin %x/%x offset %d/%d\n", sel, 1051 aps->aps_seqmin[sel], aps->aps_seqmin[sel2], 1052 aps->aps_seqoff[sel], aps->aps_seqoff[sel2]); 1053 printf("sel %d ackmin %x/%x offset %d/%d\n", sel2, 1054 aps->aps_ackmin[sel], aps->aps_ackmin[sel2], 1055 aps->aps_ackoff[sel], aps->aps_ackoff[sel2]); 1056 } 1057 1058 /* 1059 * XXX - Ideally, this packet should get dropped because we now know 1060 * that it is out of order (and there is no real danger in doing so 1061 * apart from causing packets to go through here ordered). 1062 */ | 1363 printf("%s: %x seq %x/%d ack %x/%d len %d/%d off %d\n", 1364 rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff, 1365 thack, ackoff, mlen, fin->fin_plen, off); 1366 printf("sel %d seqmin %x/%x offset %d/%d\n", sel, 1367 aps->aps_seqmin[sel], aps->aps_seqmin[sel2], 1368 aps->aps_seqoff[sel], aps->aps_seqoff[sel2]); 1369 printf("sel %d ackmin %x/%x offset %d/%d\n", sel2, 1370 aps->aps_ackmin[sel], aps->aps_ackmin[sel2], 1371 aps->aps_ackoff[sel], aps->aps_ackoff[sel2]); 1372 } 1373 1374 /* 1375 * XXX - Ideally, this packet should get dropped because we now know 1376 * that it is out of order (and there is no real danger in doing so 1377 * apart from causing packets to go through here ordered). 1378 */ |
1063 if (ippr_ftp_debug > 2) { | 1379 if (softf->ipf_p_ftp_debug & DEBUG_INFO) { |
1064 printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n", 1065 rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff); 1066 } 1067 1068 ok = 0; 1069 if (t->ftps_seq[0] == 0) { 1070 t->ftps_seq[0] = thack; 1071 ok = 1; 1072 } else { 1073 if (ackoff == 0) { 1074 if (t->ftps_seq[0] == thack) 1075 ok = 1; 1076 else if (t->ftps_seq[1] == thack) { 1077 t->ftps_seq[0] = thack; 1078 ok = 1; 1079 } 1080 } else { | 1380 printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n", 1381 rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff); 1382 } 1383 1384 ok = 0; 1385 if (t->ftps_seq[0] == 0) { 1386 t->ftps_seq[0] = thack; 1387 ok = 1; 1388 } else { 1389 if (ackoff == 0) { 1390 if (t->ftps_seq[0] == thack) 1391 ok = 1; 1392 else if (t->ftps_seq[1] == thack) { 1393 t->ftps_seq[0] = thack; 1394 ok = 1; 1395 } 1396 } else { |
1081 if (t->ftps_seq[0] + ackoff == thack) | 1397 if (t->ftps_seq[0] + ackoff == thack) { 1398 t->ftps_seq[0] = thack; |
1082 ok = 1; | 1399 ok = 1; |
1083 else if (t->ftps_seq[0] == thack + ackoff) | 1400 } else if (t->ftps_seq[0] == thack + ackoff) { 1401 t->ftps_seq[0] = thack + ackoff; |
1084 ok = 1; | 1402 ok = 1; |
1085 else if (t->ftps_seq[1] + ackoff == thack) { 1086 t->ftps_seq[0] = thack - ackoff; | 1403 } else if (t->ftps_seq[1] + ackoff == thack) { 1404 t->ftps_seq[0] = thack; |
1087 ok = 1; 1088 } else if (t->ftps_seq[1] == thack + ackoff) { | 1405 ok = 1; 1406 } else if (t->ftps_seq[1] == thack + ackoff) { |
1089 t->ftps_seq[0] = thack - ackoff; | 1407 t->ftps_seq[0] = thack + ackoff; |
1090 ok = 1; 1091 } 1092 } 1093 } 1094 | 1408 ok = 1; 1409 } 1410 } 1411 } 1412 |
1095 if (ippr_ftp_debug > 2) { | 1413 if (softf->ipf_p_ftp_debug & DEBUG_INFO) { |
1096 if (!ok) 1097 printf("%s ok\n", "not"); 1098 } 1099 1100 if (!mlen) { | 1414 if (!ok) 1415 printf("%s ok\n", "not"); 1416 } 1417 1418 if (!mlen) { |
1101 if (t->ftps_seq[0] + ackoff != thack) { 1102 if (ippr_ftp_debug > 1) { 1103 printf("%s:seq[0](%x) + (%x) != (%x)\n", 1104 "ippr_ftp_process", t->ftps_seq[0], | 1419 if (t->ftps_seq[0] + ackoff != thack && 1420 t->ftps_seq[1] + ackoff != thack) { 1421 DT3(thack, ftpside_t *t, t, int, ackoff, u_32_t, thack); 1422 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) { 1423 printf("%s:seq[0](%u) + (%d) != (%u)\n", 1424 "ipf_p_ftp_process", t->ftps_seq[0], |
1105 ackoff, thack); | 1425 ackoff, thack); |
1426 printf("%s:seq[0](%u) + (%d) != (%u)\n", 1427 "ipf_p_ftp_process", t->ftps_seq[1], 1428 ackoff, thack); |
|
1106 } 1107 return APR_ERR(1); 1108 } 1109 | 1429 } 1430 return APR_ERR(1); 1431 } 1432 |
1110 if (ippr_ftp_debug > 2) { 1111 printf("ippr_ftp_process:f:seq[0] %x seq[1] %x\n", | 1433 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) { 1434 printf("ipf_p_ftp_process:f:seq[0] %x seq[1] %x\n", |
1112 f->ftps_seq[0], f->ftps_seq[1]); 1113 } 1114 1115 if (tcp->th_flags & TH_FIN) { 1116 if (thseq == f->ftps_seq[1]) { 1117 f->ftps_seq[0] = f->ftps_seq[1] - seqoff; 1118 f->ftps_seq[1] = thseq + 1 - seqoff; 1119 } else { | 1435 f->ftps_seq[0], f->ftps_seq[1]); 1436 } 1437 1438 if (tcp->th_flags & TH_FIN) { 1439 if (thseq == f->ftps_seq[1]) { 1440 f->ftps_seq[0] = f->ftps_seq[1] - seqoff; 1441 f->ftps_seq[1] = thseq + 1 - seqoff; 1442 } else { |
1120 if (ippr_ftp_debug > 1) { 1121 printf("FIN: thseq %x seqoff %d ftps_seq %x %x\n", 1122 thseq, seqoff, f->ftps_seq[0], f->ftps_seq[1]); | 1443 DT2(thseq, ftpside_t *t, t, u_32_t, thseq); 1444 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) { 1445 printf("FIN: thseq %x seqoff %d ftps_seq %x\n", 1446 thseq, seqoff, f->ftps_seq[0]); |
1123 } 1124 return APR_ERR(1); 1125 } 1126 } 1127 f->ftps_len = 0; 1128 return 0; 1129 } 1130 --- 4 unchanged lines hidden (view full) --- 1135 * Retransmitted data packet. 1136 */ 1137 } else if ((thseq + mlen == f->ftps_seq[0]) || 1138 (thseq + mlen == f->ftps_seq[1])) { 1139 ok = 1; 1140 } 1141 1142 if (ok == 0) { | 1447 } 1448 return APR_ERR(1); 1449 } 1450 } 1451 f->ftps_len = 0; 1452 return 0; 1453 } 1454 --- 4 unchanged lines hidden (view full) --- 1459 * Retransmitted data packet. 1460 */ 1461 } else if ((thseq + mlen == f->ftps_seq[0]) || 1462 (thseq + mlen == f->ftps_seq[1])) { 1463 ok = 1; 1464 } 1465 1466 if (ok == 0) { |
1467 DT3(ok_0, ftpside_t *, f, u_32_t, thseq, int, mlen); |
|
1143 inc = thseq - f->ftps_seq[0]; | 1468 inc = thseq - f->ftps_seq[0]; |
1144 if (ippr_ftp_debug > 1) { | 1469 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) { |
1145 printf("inc %d sel %d rv %d\n", inc, sel, rv); 1146 printf("th_seq %x ftps_seq %x/%x\n", 1147 thseq, f->ftps_seq[0], f->ftps_seq[1]); 1148 printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel], 1149 aps->aps_ackoff[sel]); 1150 printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel], 1151 aps->aps_seqoff[sel]); 1152 } --- 5 unchanged lines hidden (view full) --- 1158 rptr = f->ftps_rptr; 1159 wptr = f->ftps_wptr; 1160 f->ftps_seq[0] = thseq; 1161 f->ftps_seq[1] = f->ftps_seq[0] + mlen; 1162 f->ftps_len = mlen; 1163 1164 while (mlen > 0) { 1165 len = MIN(mlen, sizeof(f->ftps_buf) - (wptr - rptr)); | 1470 printf("inc %d sel %d rv %d\n", inc, sel, rv); 1471 printf("th_seq %x ftps_seq %x/%x\n", 1472 thseq, f->ftps_seq[0], f->ftps_seq[1]); 1473 printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel], 1474 aps->aps_ackoff[sel]); 1475 printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel], 1476 aps->aps_seqoff[sel]); 1477 } --- 5 unchanged lines hidden (view full) --- 1483 rptr = f->ftps_rptr; 1484 wptr = f->ftps_wptr; 1485 f->ftps_seq[0] = thseq; 1486 f->ftps_seq[1] = f->ftps_seq[0] + mlen; 1487 f->ftps_len = mlen; 1488 1489 while (mlen > 0) { 1490 len = MIN(mlen, sizeof(f->ftps_buf) - (wptr - rptr)); |
1491 if (len == 0) 1492 break; |
|
1166 COPYDATA(m, off, len, wptr); 1167 mlen -= len; 1168 off += len; 1169 wptr += len; 1170 | 1493 COPYDATA(m, off, len, wptr); 1494 mlen -= len; 1495 off += len; 1496 wptr += len; 1497 |
1171 if (ippr_ftp_debug > 3) | 1498whilemore: 1499 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) |
1172 printf("%s:len %d/%d off %d wptr %lx junk %d [%*.*s]\n", | 1500 printf("%s:len %d/%d off %d wptr %lx junk %d [%*.*s]\n", |
1173 "ippr_ftp_process", | 1501 "ipf_p_ftp_process", |
1174 len, mlen, off, (u_long)wptr, f->ftps_junk, 1175 len, len, rptr); 1176 1177 f->ftps_wptr = wptr; | 1502 len, mlen, off, (u_long)wptr, f->ftps_junk, 1503 len, len, rptr); 1504 1505 f->ftps_wptr = wptr; |
1178 if (f->ftps_junk != 0) { | 1506 if (f->ftps_junk != FTPXY_JUNK_OK) { |
1179 i = f->ftps_junk; | 1507 i = f->ftps_junk; |
1180 f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, | 1508 f->ftps_junk = ipf_p_ftp_valid(softf, ftp, rv, rptr, |
1181 wptr - rptr); | 1509 wptr - rptr); |
1510 DT2(junk_transit, int, i, int, f->ftps_junk); |
|
1182 | 1511 |
1183 if (ippr_ftp_debug > 5) | 1512 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) |
1184 printf("%s:junk %d -> %d\n", | 1513 printf("%s:junk %d -> %d\n", |
1185 "ippr_ftp_process", i, f->ftps_junk); | 1514 "ipf_p_ftp_process", i, f->ftps_junk); |
1186 | 1515 |
1187 if (f->ftps_junk != 0) { | 1516 if (f->ftps_junk == FTPXY_JUNK_BAD) { 1517 DT(buffer_full); |
1188 if (wptr - rptr == sizeof(f->ftps_buf)) { | 1518 if (wptr - rptr == sizeof(f->ftps_buf)) { |
1189 if (ippr_ftp_debug > 4) | 1519 if (softf->ipf_p_ftp_debug & 1520 DEBUG_PARSE_INFO) |
1190 printf("%s:full buffer\n", | 1521 printf("%s:full buffer\n", |
1191 "ippr_ftp_process"); | 1522 "ipf_p_ftp_process"); |
1192 f->ftps_rptr = f->ftps_buf; 1193 f->ftps_wptr = f->ftps_buf; 1194 rptr = f->ftps_rptr; 1195 wptr = f->ftps_wptr; | 1523 f->ftps_rptr = f->ftps_buf; 1524 f->ftps_wptr = f->ftps_buf; 1525 rptr = f->ftps_rptr; 1526 wptr = f->ftps_wptr; |
1196 /* 1197 * Because we throw away data here that 1198 * we would otherwise parse, set the 1199 * junk flag to indicate just ignore 1200 * any data upto the next CRLF. 1201 */ 1202 f->ftps_junk = 1; | |
1203 continue; 1204 } 1205 } 1206 } 1207 | 1527 continue; 1528 } 1529 } 1530 } 1531 |
1208 while ((f->ftps_junk == 0) && (wptr > rptr)) { | 1532 while ((f->ftps_junk == FTPXY_JUNK_OK) && (wptr > rptr)) { |
1209 len = wptr - rptr; | 1533 len = wptr - rptr; |
1210 f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, len); | 1534 f->ftps_junk = ipf_p_ftp_valid(softf, ftp, rv, 1535 rptr, len); |
1211 | 1536 |
1212 if (ippr_ftp_debug > 3) { | 1537 if (softf->ipf_p_ftp_debug & DEBUG_PARSE) { |
1213 printf("%s=%d len %d rv %d ptr %lx/%lx ", | 1538 printf("%s=%d len %d rv %d ptr %lx/%lx ", |
1214 "ippr_ftp_valid", | 1539 "ipf_p_ftp_valid", |
1215 f->ftps_junk, len, rv, (u_long)rptr, 1216 (u_long)wptr); 1217 printf("buf [%*.*s]\n", len, len, rptr); 1218 } 1219 | 1540 f->ftps_junk, len, rv, (u_long)rptr, 1541 (u_long)wptr); 1542 printf("buf [%*.*s]\n", len, len, rptr); 1543 } 1544 |
1220 if (f->ftps_junk == 0) { | 1545 if (f->ftps_junk == FTPXY_JUNK_OK) { 1546 f->ftps_cmds++; |
1221 f->ftps_rptr = rptr; 1222 if (rv) | 1547 f->ftps_rptr = rptr; 1548 if (rv) |
1223 inc += ippr_ftp_server(fin, ip, nat, 1224 ftp, len); | 1549 inc += ipf_p_ftp_server(softf, fin, ip, 1550 nat, ftp, len); |
1225 else | 1551 else |
1226 inc += ippr_ftp_client(fin, ip, nat, 1227 ftp, len); | 1552 inc += ipf_p_ftp_client(softf, fin, ip, 1553 nat, ftp, len); |
1228 rptr = f->ftps_rptr; 1229 wptr = f->ftps_wptr; 1230 } 1231 } 1232 1233 /* 1234 * Off to a bad start so lets just forget about using the 1235 * ftp proxy for this connection. 1236 */ | 1554 rptr = f->ftps_rptr; 1555 wptr = f->ftps_wptr; 1556 } 1557 } 1558 1559 /* 1560 * Off to a bad start so lets just forget about using the 1561 * ftp proxy for this connection. 1562 */ |
1237 if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) { | 1563 if ((f->ftps_cmds == 0) && (f->ftps_junk == FTPXY_JUNK_BAD)) { |
1238 /* f->ftps_seq[1] += inc; */ 1239 | 1564 /* f->ftps_seq[1] += inc; */ 1565 |
1240 if (ippr_ftp_debug > 1) | 1566 DT(ftp_junk_cmd); 1567 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) |
1241 printf("%s:cmds == 0 junk == 1\n", | 1568 printf("%s:cmds == 0 junk == 1\n", |
1242 "ippr_ftp_process"); | 1569 "ipf_p_ftp_process"); |
1243 return APR_ERR(2); 1244 } 1245 | 1570 return APR_ERR(2); 1571 } 1572 |
1246 if ((f->ftps_junk != 0) && (rptr < wptr)) { | 1573 retry = 0; 1574 if ((f->ftps_junk != FTPXY_JUNK_OK) && (rptr < wptr)) { |
1247 for (s = rptr; s < wptr; s++) { 1248 if ((*s == '\r') && (s + 1 < wptr) && 1249 (*(s + 1) == '\n')) { 1250 rptr = s + 2; | 1575 for (s = rptr; s < wptr; s++) { 1576 if ((*s == '\r') && (s + 1 < wptr) && 1577 (*(s + 1) == '\n')) { 1578 rptr = s + 2; |
1251 f->ftps_junk = 0; | 1579 retry = 1; 1580 if (f->ftps_junk != FTPXY_JUNK_CONT) 1581 f->ftps_junk = FTPXY_JUNK_OK; |
1252 break; 1253 } 1254 } 1255 } 1256 1257 if (rptr == wptr) { 1258 rptr = wptr = f->ftps_buf; 1259 } else { 1260 /* 1261 * Compact the buffer back to the start. The junk 1262 * flag should already be set and because we're not 1263 * throwing away any data, it is preserved from its 1264 * current state. 1265 */ 1266 if (rptr > f->ftps_buf) { | 1582 break; 1583 } 1584 } 1585 } 1586 1587 if (rptr == wptr) { 1588 rptr = wptr = f->ftps_buf; 1589 } else { 1590 /* 1591 * Compact the buffer back to the start. The junk 1592 * flag should already be set and because we're not 1593 * throwing away any data, it is preserved from its 1594 * current state. 1595 */ 1596 if (rptr > f->ftps_buf) { |
1267 bcopy(rptr, f->ftps_buf, len); | 1597 bcopy(rptr, f->ftps_buf, wptr - rptr); |
1268 wptr -= rptr - f->ftps_buf; 1269 rptr = f->ftps_buf; 1270 } 1271 } 1272 f->ftps_rptr = rptr; 1273 f->ftps_wptr = wptr; | 1598 wptr -= rptr - f->ftps_buf; 1599 rptr = f->ftps_buf; 1600 } 1601 } 1602 f->ftps_rptr = rptr; 1603 f->ftps_wptr = wptr; |
1604 if (retry) 1605 goto whilemore; |
|
1274 } 1275 1276 /* f->ftps_seq[1] += inc; */ 1277 if (tcp->th_flags & TH_FIN) 1278 f->ftps_seq[1]++; | 1606 } 1607 1608 /* f->ftps_seq[1] += inc; */ 1609 if (tcp->th_flags & TH_FIN) 1610 f->ftps_seq[1]++; |
1279 if (ippr_ftp_debug > 3) { | 1611 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_INFO) { |
1280#ifdef __sgi 1281 mlen = fin->fin_plen; 1282#else 1283 mlen = MSGDSIZE(m); 1284#endif 1285 mlen -= off; 1286 printf("ftps_seq[1] = %x inc %d len %d\n", 1287 f->ftps_seq[1], inc, mlen); 1288 } 1289 1290 f->ftps_rptr = rptr; 1291 f->ftps_wptr = wptr; 1292 return APR_INC(inc); 1293} 1294 1295 | 1612#ifdef __sgi 1613 mlen = fin->fin_plen; 1614#else 1615 mlen = MSGDSIZE(m); 1616#endif 1617 mlen -= off; 1618 printf("ftps_seq[1] = %x inc %d len %d\n", 1619 f->ftps_seq[1], inc, mlen); 1620 } 1621 1622 f->ftps_rptr = rptr; 1623 f->ftps_wptr = wptr; 1624 return APR_INC(inc); 1625} 1626 1627 |
1296int ippr_ftp_out(fin, aps, nat) 1297fr_info_t *fin; 1298ap_session_t *aps; 1299nat_t *nat; | 1628int 1629ipf_p_ftp_out(arg, fin, aps, nat) 1630 void *arg; 1631 fr_info_t *fin; 1632 ap_session_t *aps; 1633 nat_t *nat; |
1300{ | 1634{ |
1635 ipf_ftp_softc_t *softf = arg; |
|
1301 ftpinfo_t *ftp; 1302 int rev; 1303 1304 ftp = aps->aps_data; 1305 if (ftp == NULL) 1306 return 0; 1307 1308 rev = (nat->nat_dir == NAT_OUTBOUND) ? 0 : 1; 1309 if (ftp->ftp_side[1 - rev].ftps_ifp == NULL) 1310 ftp->ftp_side[1 - rev].ftps_ifp = fin->fin_ifp; 1311 | 1636 ftpinfo_t *ftp; 1637 int rev; 1638 1639 ftp = aps->aps_data; 1640 if (ftp == NULL) 1641 return 0; 1642 1643 rev = (nat->nat_dir == NAT_OUTBOUND) ? 0 : 1; 1644 if (ftp->ftp_side[1 - rev].ftps_ifp == NULL) 1645 ftp->ftp_side[1 - rev].ftps_ifp = fin->fin_ifp; 1646 |
1312 return ippr_ftp_process(fin, nat, ftp, rev); | 1647 return ipf_p_ftp_process(softf, fin, nat, ftp, rev); |
1313} 1314 1315 | 1648} 1649 1650 |
1316int ippr_ftp_in(fin, aps, nat) 1317fr_info_t *fin; 1318ap_session_t *aps; 1319nat_t *nat; | 1651int 1652ipf_p_ftp_in(arg, fin, aps, nat) 1653 void *arg; 1654 fr_info_t *fin; 1655 ap_session_t *aps; 1656 nat_t *nat; |
1320{ | 1657{ |
1658 ipf_ftp_softc_t *softf = arg; |
|
1321 ftpinfo_t *ftp; 1322 int rev; 1323 1324 ftp = aps->aps_data; 1325 if (ftp == NULL) 1326 return 0; 1327 1328 rev = (nat->nat_dir == NAT_OUTBOUND) ? 0 : 1; 1329 if (ftp->ftp_side[rev].ftps_ifp == NULL) 1330 ftp->ftp_side[rev].ftps_ifp = fin->fin_ifp; 1331 | 1659 ftpinfo_t *ftp; 1660 int rev; 1661 1662 ftp = aps->aps_data; 1663 if (ftp == NULL) 1664 return 0; 1665 1666 rev = (nat->nat_dir == NAT_OUTBOUND) ? 0 : 1; 1667 if (ftp->ftp_side[rev].ftps_ifp == NULL) 1668 ftp->ftp_side[rev].ftps_ifp = fin->fin_ifp; 1669 |
1332 return ippr_ftp_process(fin, nat, ftp, 1 - rev); | 1670 return ipf_p_ftp_process(softf, fin, nat, ftp, 1 - rev); |
1333} 1334 1335 1336/* | 1671} 1672 1673 1674/* |
1337 * ippr_ftp_atoi - implement a version of atoi which processes numbers in | 1675 * ipf_p_ftp_atoi - implement a version of atoi which processes numbers in |
1338 * pairs separated by commas (which are expected to be in the range 0 - 255), 1339 * returning a 16 bit number combining either side of the , as the MSB and 1340 * LSB. 1341 */ | 1676 * pairs separated by commas (which are expected to be in the range 0 - 255), 1677 * returning a 16 bit number combining either side of the , as the MSB and 1678 * LSB. 1679 */ |
1342u_short ippr_ftp_atoi(ptr) 1343char **ptr; | 1680u_short 1681ipf_p_ftp_atoi(ptr) 1682 char **ptr; |
1344{ 1345 register char *s = *ptr, c; 1346 register u_char i = 0, j = 0; 1347 1348 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1349 i *= 10; 1350 i += c - '0'; 1351 } --- 7 unchanged lines hidden (view full) --- 1359 } 1360 *ptr = s; 1361 i &= 0xff; 1362 j &= 0xff; 1363 return (i << 8) | j; 1364} 1365 1366 | 1683{ 1684 register char *s = *ptr, c; 1685 register u_char i = 0, j = 0; 1686 1687 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1688 i *= 10; 1689 i += c - '0'; 1690 } --- 7 unchanged lines hidden (view full) --- 1698 } 1699 *ptr = s; 1700 i &= 0xff; 1701 j &= 0xff; 1702 return (i << 8) | j; 1703} 1704 1705 |
1367int ippr_ftp_epsv(fin, ip, nat, f, dlen) 1368fr_info_t *fin; 1369ip_t *ip; 1370nat_t *nat; 1371ftpside_t *f; 1372int dlen; | 1706int 1707ipf_p_ftp_eprt(softf, fin, ip, nat, ftp, dlen) 1708 ipf_ftp_softc_t *softf; 1709 fr_info_t *fin; 1710 ip_t *ip; 1711 nat_t *nat; 1712 ftpinfo_t *ftp; 1713 int dlen; |
1373{ | 1714{ |
1715 ftpside_t *f; 1716 1717 /* 1718 * Check for client sending out EPRT message. 1719 */ 1720 if (dlen < IPF_MINEPRTLEN) { 1721 DT1(epert_dlen, int, dlen); 1722 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 1723 printf("ipf_p_ftp_eprt:dlen(%d) < IPF_MINEPRTLEN\n", 1724 dlen); 1725 return 0; 1726 } 1727 1728 /* 1729 * Parse the EPRT command. Format is: 1730 * "EPRT |1|1.2.3.4|2000|" for IPv4 and 1731 * "EPRT |2|ef00::1:2|2000|" for IPv6 1732 */ 1733 f = &ftp->ftp_side[0]; 1734 if (f->ftps_rptr[5] != '|') 1735 return 0; 1736 if (f->ftps_rptr[5] == f->ftps_rptr[7]) { 1737 if (f->ftps_rptr[6] == '1' && nat->nat_v[0] == 4) 1738 return ipf_p_ftp_eprt4(softf, fin, ip, nat, ftp, dlen); 1739#ifdef USE_INET6 1740 if (f->ftps_rptr[6] == '2' && nat->nat_v[0] == 6) 1741 return ipf_p_ftp_eprt6(softf, fin, ip, nat, ftp, dlen); 1742#endif 1743 } 1744 return 0; 1745} 1746 1747 1748int 1749ipf_p_ftp_eprt4(softf, fin, ip, nat, ftp, dlen) 1750 ipf_ftp_softc_t *softf; 1751 fr_info_t *fin; 1752 ip_t *ip; 1753 nat_t *nat; 1754 ftpinfo_t *ftp; 1755 int dlen; 1756{ 1757 int a1, a2, a3, a4, port, olen, nlen, inc, off; |
|
1374 char newbuf[IPF_FTPBUFSZ]; | 1758 char newbuf[IPF_FTPBUFSZ]; |
1375 char *s; | 1759 char *s, c, delim; 1760 u_32_t addr, i; 1761 tcphdr_t *tcp; 1762 ftpside_t *f; 1763 mb_t *m; 1764 1765 m = fin->fin_m; 1766 tcp = (tcphdr_t *)fin->fin_dp; 1767 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 1768 f = &ftp->ftp_side[0]; 1769 delim = f->ftps_rptr[5]; 1770 s = f->ftps_rptr + 8; 1771 1772 /* 1773 * get the IP address. 1774 */ 1775 i = 0; 1776 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1777 i *= 10; 1778 i += c - '0'; 1779 } 1780 if (i > 255) 1781 return 0; 1782 if (c != '.') 1783 return 0; 1784 addr = (i << 24); 1785 1786 i = 0; 1787 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1788 i *= 10; 1789 i += c - '0'; 1790 } 1791 if (i > 255) 1792 return 0; 1793 if (c != '.') 1794 return 0; 1795 addr |= (addr << 16); 1796 1797 i = 0; 1798 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1799 i *= 10; 1800 i += c - '0'; 1801 } 1802 if (i > 255) 1803 return 0; 1804 if (c != '.') 1805 return 0; 1806 addr |= (addr << 8); 1807 1808 i = 0; 1809 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1810 i *= 10; 1811 i += c - '0'; 1812 } 1813 if (i > 255) 1814 return 0; 1815 if (c != delim) 1816 return 0; 1817 addr |= addr; 1818 1819 /* 1820 * Get the port number 1821 */ 1822 i = 0; 1823 while (((c = *s++) != '\0') && ISDIGIT(c)) { 1824 i *= 10; 1825 i += c - '0'; 1826 } 1827 if (i > 65535) 1828 return 0; 1829 if (c != delim) 1830 return 0; 1831 port = i; 1832 1833 /* 1834 * Check for CR-LF at the end of the command string. 1835 */ 1836 if ((*s != '\r') || (*(s + 1) != '\n')) { 1837 DT(eprt4_no_crlf); 1838 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 1839 printf("ipf_p_ftp_eprt4:missing %s\n", "cr-lf"); 1840 return 0; 1841 } 1842 s += 2; 1843 1844 /* 1845 * Calculate new address parts for PORT command 1846 */ 1847 if (nat->nat_dir == NAT_INBOUND) 1848 a1 = ntohl(nat->nat_odstaddr); 1849 else 1850 a1 = ntohl(ip->ip_src.s_addr); 1851 a2 = (a1 >> 16) & 0xff; 1852 a3 = (a1 >> 8) & 0xff; 1853 a4 = a1 & 0xff; 1854 a1 >>= 24; 1855 olen = s - f->ftps_rptr; 1856 /* DO NOT change this to snprintf! */ 1857 /* 1858 * While we could force the use of | as a delimiter here, it makes 1859 * sense to preserve whatever character is being used by the systems 1860 * involved in the communication. 1861 */ 1862#if defined(SNPRINTF) && defined(_KERNEL) 1863 SNPRINTF(newbuf, sizeof(newbuf), "%s %c1%c%u.%u.%u.%u%c%u%c\r\n", 1864 "EPRT", delim, delim, a1, a2, a3, a4, delim, port, delim); 1865#else 1866 (void) sprintf(newbuf, "%s %c1%c%u.%u.%u.%u%c%u%c\r\n", 1867 "EPRT", delim, delim, a1, a2, a3, a4, delim, port, 1868 delim); 1869#endif 1870 1871 nlen = strlen(newbuf); 1872 inc = nlen - olen; 1873 if ((inc + fin->fin_plen) > 65535) { 1874 DT2(eprt4_len, int, inc, int, fin->fin_plen); 1875 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 1876 printf("ipf_p_ftp_eprt4:inc(%d) + ip->ip_len > 65535\n", 1877 inc); 1878 return 0; 1879 } 1880 1881 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 1882#if !defined(_KERNEL) 1883 M_ADJ(m, inc); 1884#else 1885 if (inc < 0) 1886 M_ADJ(m, inc); 1887#endif 1888 /* the mbuf chain will be extended if necessary by m_copyback() */ 1889 COPYBACK(m, off, nlen, newbuf); 1890 fin->fin_flx |= FI_DOCKSUM; 1891 1892 if (inc != 0) { 1893 fin->fin_plen += inc; 1894 ip->ip_len = htons(fin->fin_plen); 1895 fin->fin_dlen += inc; 1896 } 1897 1898 f->ftps_cmd = FTPXY_C_EPRT; 1899 return ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, port, inc); 1900} 1901 1902 1903int 1904ipf_p_ftp_epsv(softf, fin, ip, nat, ftp, dlen) 1905 ipf_ftp_softc_t *softf; 1906 fr_info_t *fin; 1907 ip_t *ip; 1908 nat_t *nat; 1909 ftpinfo_t *ftp; 1910 int dlen; 1911{ 1912 char newbuf[IPF_FTPBUFSZ]; |
1376 u_short ap = 0; | 1913 u_short ap = 0; |
1914 ftpside_t *f; 1915 char *s; |
|
1377 | 1916 |
1917 if ((softf->ipf_p_ftp_forcepasv != 0) && 1918 (ftp->ftp_side[0].ftps_cmd != FTPXY_C_EPSV)) { 1919 DT1(epsv_cmd, int, ftp->ftp_side[0].ftps_cmd); 1920 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 1921 printf("ipf_p_ftp_epsv:ftps_cmd(%d) != FTPXY_C_EPSV\n", 1922 ftp->ftp_side[0].ftps_cmd); 1923 return 0; 1924 } 1925 f = &ftp->ftp_side[1]; 1926 |
|
1378#define EPSV_REPLEN 33 1379 /* 1380 * Check for EPSV reply message. 1381 */ | 1927#define EPSV_REPLEN 33 1928 /* 1929 * Check for EPSV reply message. 1930 */ |
1382 if (dlen < IPF_MIN229LEN) | 1931 if (dlen < IPF_MIN229LEN) { |
1383 return (0); | 1932 return (0); |
1384 else if (strncmp(f->ftps_rptr, 1385 "229 Entering Extended Passive Mode", EPSV_REPLEN)) | 1933 } else if (strncmp(f->ftps_rptr, 1934 "229 Entering Extended Passive Mode", EPSV_REPLEN)) { |
1386 return (0); | 1935 return (0); |
1936} |
|
1387 1388 /* 1389 * Skip the EPSV command + space 1390 */ 1391 s = f->ftps_rptr + 33; 1392 while (*s && !ISDIGIT(*s)) 1393 s++; 1394 1395 /* 1396 * As per RFC 2428, there are no addres components in the EPSV 1397 * response. So we'll go straight to getting the port. 1398 */ 1399 while (*s && ISDIGIT(*s)) { 1400 ap *= 10; 1401 ap += *s++ - '0'; 1402 } 1403 | 1937 1938 /* 1939 * Skip the EPSV command + space 1940 */ 1941 s = f->ftps_rptr + 33; 1942 while (*s && !ISDIGIT(*s)) 1943 s++; 1944 1945 /* 1946 * As per RFC 2428, there are no addres components in the EPSV 1947 * response. So we'll go straight to getting the port. 1948 */ 1949 while (*s && ISDIGIT(*s)) { 1950 ap *= 10; 1951 ap += *s++ - '0'; 1952 } 1953 |
1404 if (!*s) | 1954 if (!s) { |
1405 return 0; | 1955 return 0; |
1956} |
|
1406 1407 if (*s == '|') 1408 s++; 1409 if (*s == ')') 1410 s++; 1411 if (*s == '\n') 1412 s--; 1413 /* 1414 * check for CR-LF at the end. 1415 */ | 1957 1958 if (*s == '|') 1959 s++; 1960 if (*s == ')') 1961 s++; 1962 if (*s == '\n') 1963 s--; 1964 /* 1965 * check for CR-LF at the end. 1966 */ |
1416 if ((*s == '\r') && (*(s + 1) == '\n')) { 1417 s += 2; 1418 } else | 1967 if ((*s != '\r') || (*(s + 1) != '\n')) { |
1419 return 0; | 1968 return 0; |
1969 } 1970 s += 2; |
|
1420 1421#if defined(SNPRINTF) && defined(_KERNEL) 1422 SNPRINTF(newbuf, sizeof(newbuf), "%s (|||%u|)\r\n", 1423 "229 Entering Extended Passive Mode", ap); 1424#else 1425 (void) sprintf(newbuf, "%s (|||%u|)\r\n", 1426 "229 Entering Extended Passive Mode", ap); 1427#endif 1428 | 1971 1972#if defined(SNPRINTF) && defined(_KERNEL) 1973 SNPRINTF(newbuf, sizeof(newbuf), "%s (|||%u|)\r\n", 1974 "229 Entering Extended Passive Mode", ap); 1975#else 1976 (void) sprintf(newbuf, "%s (|||%u|)\r\n", 1977 "229 Entering Extended Passive Mode", ap); 1978#endif 1979 |
1429 return ippr_ftp_pasvreply(fin, ip, nat, f, (u_int)ap, newbuf, s, 1430 ip->ip_src.s_addr); | 1980 return ipf_p_ftp_pasvreply(softf, fin, ip, nat, ftp, (u_int)ap, 1981 newbuf, s); |
1431} | 1982} |
1983 1984#ifdef USE_INET6 1985int 1986ipf_p_ftp_eprt6(softf, fin, ip, nat, ftp, dlen) 1987 ipf_ftp_softc_t *softf; 1988 fr_info_t *fin; 1989 ip_t *ip; 1990 nat_t *nat; 1991 ftpinfo_t *ftp; 1992 int dlen; 1993{ 1994 int port, olen, nlen, inc, off, left, i; 1995 char newbuf[IPF_FTPBUFSZ]; 1996 char *s, c; 1997 i6addr_t addr, *a6; 1998 tcphdr_t *tcp; 1999 ip6_t *ip6; 2000 char delim; 2001 u_short whole; 2002 u_short part; 2003 ftpside_t *f; 2004 u_short *t; 2005 int fwd; 2006 mb_t *m; 2007 u_32_t a; 2008 2009 m = fin->fin_m; 2010 ip6 = (ip6_t *)ip; 2011 f = &ftp->ftp_side[0]; 2012 s = f->ftps_rptr + 8; 2013 f = &ftp->ftp_side[0]; 2014 delim = f->ftps_rptr[5]; 2015 tcp = (tcphdr_t *)fin->fin_dp; 2016 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 2017 2018 addr.i6[0] = 0; 2019 addr.i6[1] = 0; 2020 addr.i6[2] = 0; 2021 addr.i6[3] = 0; 2022 /* 2023 * Parse an IPv6 address. 2024 * Go forward until either :: or | is found. If :: is found, 2025 * reverse direction. Direction change is performed to ease 2026 * parsing an unknown number of 0s in the middle. 2027 */ 2028 whole = 0; 2029 t = (u_short *)&addr; 2030 fwd = 1; 2031 for (part = 0; (c = *s) != '\0'; ) { 2032 if (c == delim) { 2033 *t = htons((u_short)whole); 2034 break; 2035 } 2036 if (c == ':') { 2037 *t = part; 2038 if (fwd) { 2039 *t = htons((u_short)whole); 2040 t++; 2041 } else { 2042 *t = htons((u_short)(whole >> 16)); 2043 t--; 2044 } 2045 whole = 0; 2046 if (fwd == 1 && s[1] == ':') { 2047 while (*s && *s != '|') 2048 s++; 2049 if ((c = *s) != delim) 2050 break; 2051 t = (u_short *)&addr.i6[3]; 2052 t++; 2053 fwd = 0; 2054 } else if (fwd == 0 && s[-1] == ':') { 2055 break; 2056 } 2057 } else { 2058 if (c >= '0' && c <= '9') { 2059 c -= '0'; 2060 } else if (c >= 'a' && c <= 'f') { 2061 c -= 'a' + 10; 2062 } else if (c >= 'A' && c <= 'F') { 2063 c -= 'A' + 10; 2064 } 2065 if (fwd) { 2066 whole <<= 8; 2067 whole |= c; 2068 } else { 2069 whole >>= 8; 2070 whole |= ((u_32_t)c) << 24; 2071 } 2072 } 2073 if (fwd) 2074 s++; 2075 else 2076 s--; 2077 } 2078 if (c != ':' && c != delim) 2079 return 0; 2080 2081 while (*s != '|') 2082 s++; 2083 s++; 2084 2085 /* 2086 * Get the port number 2087 */ 2088 i = 0; 2089 while (((c = *s++) != '\0') && ISDIGIT(c)) { 2090 i *= 10; 2091 i += c - '0'; 2092 } 2093 if (i > 65535) 2094 return 0; 2095 if (c != delim) 2096 return 0; 2097 port = (u_short)(i & 0xffff); 2098 2099 /* 2100 * Check for CR-LF at the end of the command string. 2101 */ 2102 if ((*s != '\r') || (*(s + 1) != '\n')) { 2103 DT(eprt6_no_crlf); 2104 if (softf->ipf_p_ftp_debug & DEBUG_PARSE_ERR) 2105 printf("ipf_p_ftp_eprt6:missing %s\n", "cr-lf"); 2106 return 0; 2107 } 2108 s += 2; 2109 2110 /* 2111 * Calculate new address parts for PORT command 2112 */ 2113 a6 = (i6addr_t *)&ip6->ip6_src; 2114 olen = s - f->ftps_rptr; 2115 /* DO NOT change this to snprintf! */ 2116 /* 2117 * While we could force the use of | as a delimiter here, it makes 2118 * sense to preserve whatever character is being used by the systems 2119 * involved in the communication. 2120 */ 2121 s = newbuf; 2122 left = sizeof(newbuf); 2123#if defined(SNPRINTF) && defined(_KERNEL) 2124 SNPRINTF(newbuf, left, "EPRT %c2%c", delim, delim); 2125 left -= strlen(s) + 1; 2126 s += strlen(s); 2127 a = ntohl(a6->i6[0]); 2128 SNPRINTF(s, left, "%x:%x:", a >> 16, a & 0xffff); 2129 left -= strlen(s); 2130 s += strlen(s); 2131 a = ntohl(a6->i6[1]); 2132 SNPRINTF(s, left, "%x:%x:", a >> 16, a & 0xffff); 2133 left -= strlen(s); 2134 s += strlen(s); 2135 a = ntohl(a6->i6[2]); 2136 SNPRINTF(s, left, "%x:%x:", a >> 16, a & 0xffff); 2137 left -= strlen(s); 2138 s += strlen(s); 2139 a = ntohl(a6->i6[3]); 2140 SNPRINTF(s, left, "%x:%x", a >> 16, a & 0xffff); 2141 left -= strlen(s); 2142 s += strlen(s); 2143 sprintf(s, "|%d|\r\n", port); 2144#else 2145 (void) sprintf(s, "EPRT %c2%c", delim, delim); 2146 s += strlen(s); 2147 a = ntohl(a6->i6[0]); 2148 sprintf(s, "%x:%x:", a >> 16, a & 0xffff); 2149 s += strlen(s); 2150 a = ntohl(a6->i6[1]); 2151 sprintf(s, "%x:%x:", a >> 16, a & 0xffff); 2152 left -= strlen(s); 2153 s += strlen(s); 2154 a = ntohl(a6->i6[2]); 2155 sprintf(s, "%x:%x:", a >> 16, a & 0xffff); 2156 left -= strlen(s); 2157 s += strlen(s); 2158 a = ntohl(a6->i6[3]); 2159 sprintf(s, "%x:%x", a >> 16, a & 0xffff); 2160 left -= strlen(s); 2161 s += strlen(s); 2162 sprintf(s, "|%d|\r\n", port); 2163#endif 2164 nlen = strlen(newbuf); 2165 inc = nlen - olen; 2166 if ((inc + fin->fin_plen) > 65535) { 2167 DT2(eprt6_len, int, inc, int, fin->fin_plen); 2168 if (softf->ipf_p_ftp_debug & DEBUG_ERROR) 2169 printf("ipf_p_ftp_eprt6:inc(%d) + ip->ip_len > 65535\n", 2170 inc); 2171 return 0; 2172 } 2173 2174 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; 2175#if !defined(_KERNEL) 2176 M_ADJ(m, inc); 2177#else 2178 if (inc < 0) 2179 M_ADJ(m, inc); 2180#endif 2181 /* the mbuf chain will be extended if necessary by m_copyback() */ 2182 COPYBACK(m, off, nlen, newbuf); 2183 fin->fin_flx |= FI_DOCKSUM; 2184 2185 if (inc != 0) { 2186 fin->fin_plen += inc; 2187 ip6->ip6_plen = htons(fin->fin_plen - fin->fin_hlen); 2188 fin->fin_dlen += inc; 2189 } 2190 2191 f->ftps_cmd = FTPXY_C_EPRT; 2192 return ipf_p_ftp_addport(softf, fin, ip, nat, ftp, dlen, port, inc); 2193} 2194#endif |
|