Deleted Added
full compact
ip_ftp_pxy.c (130886) ip_ftp_pxy.c (145522)
1/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 145522 2005-04-25 18:43:14Z darrenr $ */
2
1/*
3/*
4 * Copyright (C) 1997-2003 by Darren Reed
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 *
2 * Simple FTP transparent proxy for in-kernel use. For use with the NAT
3 * code.
4 *
8 * Simple FTP transparent proxy for in-kernel use. For use with the NAT
9 * code.
10 *
5 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 130886 2004-06-21 22:46:36Z darrenr $
11 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 145522 2005-04-25 18:43:14Z darrenr $
12 * Id: ip_ftp_pxy.c,v 2.88.2.15 2005/03/19 19:38:10 darrenr Exp
6 */
13 */
7#if SOLARIS && defined(_KERNEL)
8extern kmutex_t ipf_rw;
9#endif
10
14
11#define isdigit(x) ((x) >= '0' && (x) <= '9')
12#define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z'))
13#define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z'))
14#define isalpha(x) (isupper(x) || islower(x))
15#define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A')
16
17#define IPF_FTP_PROXY
18
19#define IPF_MINPORTLEN 18
20#define IPF_MAXPORTLEN 30
21#define IPF_MIN227LEN 39
22#define IPF_MAX227LEN 51
15#define IPF_FTP_PROXY
16
17#define IPF_MINPORTLEN 18
18#define IPF_MAXPORTLEN 30
19#define IPF_MIN227LEN 39
20#define IPF_MAX227LEN 51
23#define IPF_FTPBUFSZ 96 /* This *MUST* be >= 53! */
21#define IPF_MIN229LEN 47
22#define IPF_MAX229LEN 51
24
25#define FTPXY_GO 0
26#define FTPXY_INIT 1
27#define FTPXY_USER_1 2
28#define FTPXY_USOK_1 3
29#define FTPXY_PASS_1 4
30#define FTPXY_PAOK_1 5
31#define FTPXY_AUTH_1 6

--- 9 unchanged lines hidden (view full) ---

41
42/*
43 * Values for FTP commands. Numerics cover 0-999
44 */
45#define FTPXY_C_PASV 1000
46
47int ippr_ftp_client __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
48int ippr_ftp_complete __P((char *, size_t));
23
24#define FTPXY_GO 0
25#define FTPXY_INIT 1
26#define FTPXY_USER_1 2
27#define FTPXY_USOK_1 3
28#define FTPXY_PASS_1 4
29#define FTPXY_PAOK_1 5
30#define FTPXY_AUTH_1 6

--- 9 unchanged lines hidden (view full) ---

40
41/*
42 * Values for FTP commands. Numerics cover 0-999
43 */
44#define FTPXY_C_PASV 1000
45
46int ippr_ftp_client __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
47int ippr_ftp_complete __P((char *, size_t));
49int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
48int ippr_ftp_in __P((fr_info_t *, ap_session_t *, nat_t *));
50int ippr_ftp_init __P((void));
49int ippr_ftp_init __P((void));
51int ippr_ftp_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
52int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
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));
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));
54int ippr_ftp_port __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));
55int ippr_ftp_process __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
56int ippr_ftp_process __P((fr_info_t *, nat_t *, ftpinfo_t *, int));
56int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
57int ippr_ftp_valid __P((ftpinfo_t *, int, char *, size_t));
58int ippr_ftp_server_valid __P((ftpside_t *, char *, size_t));
59int ippr_ftp_client_valid __P((ftpside_t *, char *, size_t));
60u_short ippr_ftp_atoi __P((char **));
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));
61
64
62static frentry_t ftppxyfr;
65
66int ftp_proxy_init = 0;
63int ippr_ftp_pasvonly = 0;
67int ippr_ftp_pasvonly = 0;
64int ippr_ftp_insecure = 0;
65int ippr_ftp_forcepasv = 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
76/*
77 * 1 - security
78 * 2 - errors
79 * 3 - error debugging
80 * 4 - parsing errors
81 * 5 - parsing info
82 * 6 - parsing debug
83 */
66
84
85static 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
94};
67
95
96
68/*
69 * Initialize local structures.
70 */
71int ippr_ftp_init()
72{
73 bzero((char *)&ftppxyfr, sizeof(ftppxyfr));
74 ftppxyfr.fr_ref = 1;
75 ftppxyfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
97/*
98 * Initialize local structures.
99 */
100int ippr_ftp_init()
101{
102 bzero((char *)&ftppxyfr, sizeof(ftppxyfr));
103 ftppxyfr.fr_ref = 1;
104 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
76 return 0;
77}
78
79
109 return 0;
110}
111
112
80int ippr_ftp_new(fin, ip, aps, nat)
113void ippr_ftp_fini()
114{
115 (void) fr_delipftune(&ftptune);
116
117 if (ftp_proxy_init == 1) {
118 MUTEX_DESTROY(&ftppxyfr.fr_lock);
119 ftp_proxy_init = 0;
120 }
121}
122
123
124int ippr_ftp_new(fin, aps, nat)
81fr_info_t *fin;
125fr_info_t *fin;
82ip_t *ip;
83ap_session_t *aps;
84nat_t *nat;
85{
86 ftpinfo_t *ftp;
87 ftpside_t *f;
88
89 KMALLOC(ftp, ftpinfo_t *);
90 if (ftp == NULL)
91 return -1;
126ap_session_t *aps;
127nat_t *nat;
128{
129 ftpinfo_t *ftp;
130 ftpside_t *f;
131
132 KMALLOC(ftp, ftpinfo_t *);
133 if (ftp == NULL)
134 return -1;
135
136 fin = fin; /* LINT */
137 nat = nat; /* LINT */
138
92 aps->aps_data = ftp;
93 aps->aps_psiz = sizeof(ftpinfo_t);
94
95 bzero((char *)ftp, sizeof(*ftp));
96 f = &ftp->ftp_side[0];
97 f->ftps_rptr = f->ftps_buf;
98 f->ftps_wptr = f->ftps_buf;
99 f = &ftp->ftp_side[1];
100 f->ftps_rptr = f->ftps_buf;
101 f->ftps_wptr = f->ftps_buf;
102 ftp->ftp_passok = FTPXY_INIT;
139 aps->aps_data = ftp;
140 aps->aps_psiz = sizeof(ftpinfo_t);
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;
103 return 0;
104}
105
106
107int ippr_ftp_port(fin, ip, nat, f, dlen)
108fr_info_t *fin;
109ip_t *ip;
110nat_t *nat;
111ftpside_t *f;
112int dlen;
113{
114 tcphdr_t *tcp, tcph, *tcp2 = &tcph;
115 char newbuf[IPF_FTPBUFSZ], *s;
151 return 0;
152}
153
154
155int ippr_ftp_port(fin, ip, nat, f, dlen)
156fr_info_t *fin;
157ip_t *ip;
158nat_t *nat;
159ftpside_t *f;
160int dlen;
161{
162 tcphdr_t *tcp, tcph, *tcp2 = &tcph;
163 char newbuf[IPF_FTPBUFSZ], *s;
164 struct in_addr swip, swip2;
116 u_int a1, a2, a3, a4;
165 u_int a1, a2, a3, a4;
117 struct in_addr swip;
166 int inc, off, flags;
118 u_short a5, a6, sp;
119 size_t nlen, olen;
120 fr_info_t fi;
167 u_short a5, a6, sp;
168 size_t nlen, olen;
169 fr_info_t fi;
121 int inc, off;
122 nat_t *ipn;
170 nat_t *nat2;
123 mb_t *m;
171 mb_t *m;
124#if SOLARIS && defined(_KERNEL)
125 mb_t *m1;
126#endif
127
172
173 m = fin->fin_m;
128 tcp = (tcphdr_t *)fin->fin_dp;
174 tcp = (tcphdr_t *)fin->fin_dp;
175 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
176
129 /*
130 * Check for client sending out PORT message.
131 */
132 if (dlen < IPF_MINPORTLEN) {
177 /*
178 * Check for client sending out PORT message.
179 */
180 if (dlen < IPF_MINPORTLEN) {
133#if !defined(_KERNEL) && !defined(KERNEL)
134 fprintf(stdout,
135 "ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", dlen);
136#endif
181 if (ippr_ftp_debug > 1)
182 printf("ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n",
183 dlen);
137 return 0;
138 }
184 return 0;
185 }
139 off = fin->fin_hlen + (tcp->th_off << 2);
140 /*
141 * Skip the PORT command + space
142 */
143 s = f->ftps_rptr + 5;
144 /*
145 * Pick out the address components, two at a time.
146 */
147 a1 = ippr_ftp_atoi(&s);
148 if (s == NULL) {
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 */
193 a1 = ippr_ftp_atoi(&s);
194 if (s == NULL) {
149#if !defined(_KERNEL) && !defined(KERNEL)
150 fprintf(stdout, "ippr_ftp_port:ippr_ftp_atoi(1) failed\n");
151#endif
195 if (ippr_ftp_debug > 1)
196 printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 1);
152 return 0;
153 }
154 a2 = ippr_ftp_atoi(&s);
155 if (s == NULL) {
197 return 0;
198 }
199 a2 = ippr_ftp_atoi(&s);
200 if (s == NULL) {
156#if !defined(_KERNEL) && !defined(KERNEL)
157 fprintf(stdout, "ippr_ftp_port:ippr_ftp_atoi(2) failed\n");
158#endif
201 if (ippr_ftp_debug > 1)
202 printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 2);
159 return 0;
160 }
203 return 0;
204 }
205
161 /*
206 /*
162 * check that IP address in the PORT/PASV reply is the same as the
207 * Check that IP address in the PORT/PASV reply is the same as the
163 * sender of the command - prevents using PORT for port scanning.
164 */
165 a1 <<= 16;
166 a1 |= a2;
208 * sender of the command - prevents using PORT for port scanning.
209 */
210 a1 <<= 16;
211 a1 |= a2;
167 if (a1 != ntohl(nat->nat_inip.s_addr)) {
168#if !defined(_KERNEL) && !defined(KERNEL)
169 fprintf(stdout, "ippr_ftp_port:a1 != nat->nat_inip\n");
170#endif
171 return 0;
212 if (((nat->nat_dir == NAT_OUTBOUND) &&
213 (a1 != ntohl(nat->nat_inip.s_addr))) ||
214 ((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");
218 return APR_ERR(1);
172 }
173
174 a5 = ippr_ftp_atoi(&s);
175 if (s == NULL) {
219 }
220
221 a5 = ippr_ftp_atoi(&s);
222 if (s == NULL) {
176#if !defined(_KERNEL) && !defined(KERNEL)
177 fprintf(stdout, "ippr_ftp_port:ippr_ftp_atoi(3) failed\n");
178#endif
223 if (ippr_ftp_debug > 1)
224 printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 3);
179 return 0;
180 }
181 if (*s == ')')
182 s++;
183
184 /*
185 * check for CR-LF at the end.
186 */
187 if (*s == '\n')
188 s--;
189 if ((*s == '\r') && (*(s + 1) == '\n')) {
190 s += 2;
191 a6 = a5 & 0xff;
192 } else {
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--;
235 if ((*s == '\r') && (*(s + 1) == '\n')) {
236 s += 2;
237 a6 = a5 & 0xff;
238 } else {
193#if !defined(_KERNEL) && !defined(KERNEL)
194 fprintf(stdout, "ippr_ftp_port:missing cr-lf\n");
195#endif
239 if (ippr_ftp_debug > 1)
240 printf("ippr_ftp_port:missing %s\n", "cr-lf");
196 return 0;
197 }
241 return 0;
242 }
243
198 a5 >>= 8;
199 a5 &= 0xff;
244 a5 >>= 8;
245 a5 &= 0xff;
246 sp = a5 << 8 | a6;
200 /*
247 /*
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 /*
201 * Calculate new address parts for PORT command
202 */
257 * Calculate new address parts for PORT command
258 */
203 a1 = ntohl(ip->ip_src.s_addr);
259 if (nat->nat_dir == NAT_INBOUND)
260 a1 = ntohl(nat->nat_oip.s_addr);
261 else
262 a1 = ntohl(ip->ip_src.s_addr);
204 a2 = (a1 >> 16) & 0xff;
205 a3 = (a1 >> 8) & 0xff;
206 a4 = a1 & 0xff;
207 a1 >>= 24;
208 olen = s - f->ftps_rptr;
209 /* DO NOT change this to snprintf! */
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! */
210#if defined(OpenBSD) && (200311 >= 200311)
211 (void) snprintf(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n",
212 "PORT", a1, a2, a3, a4, a5, a6);
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);
213#else
214 (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n",
215 "PORT", a1, a2, a3, a4, a5, a6);
216#endif
217
218 nlen = strlen(newbuf);
219 inc = nlen - olen;
220 if ((inc + ip->ip_len) > 65535) {
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;
279 if ((inc + ip->ip_len) > 65535) {
221#if !defined(_KERNEL) && !defined(KERNEL)
222 fprintf(stdout,
223 "ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n", inc);
224#endif
280 if (ippr_ftp_debug > 0)
281 printf("ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n",
282 inc);
225 return 0;
226 }
227
228#if !defined(_KERNEL)
283 return 0;
284 }
285
286#if !defined(_KERNEL)
229 m = *fin->fin_mp;
230 bcopy(newbuf, (char *)m + off, nlen);
287 bcopy(newbuf, MTOD(m, char *) + off, nlen);
231#else
288#else
232# if SOLARIS
233 m = fin->fin_qfm;
234 for (m1 = m; m1->b_cont; m1 = m1->b_cont)
235 ;
236 if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
237 mblk_t *nm;
238
239 /* alloc enough to keep same trailer space for lower driver */
240 nm = allocb(nlen, BPRI_MED);
241 PANIC((!nm),("ippr_ftp_out: allocb failed"));
242
243 nm->b_band = m1->b_band;
244 nm->b_wptr += nlen;
245
246 m1->b_wptr -= olen;
247 PANIC((m1->b_wptr < m1->b_rptr),
248 ("ippr_ftp_out: cannot handle fragmented data block"));
249
250 linkb(m1, nm);
251 } else {
252 if (m1->b_datap->db_struiolim == m1->b_wptr)
253 m1->b_datap->db_struiolim += inc;
254 m1->b_datap->db_struioflag &= ~STRUIO_IP;
255 m1->b_wptr += inc;
256 }
257 copyin_mblk(m, off, nlen, newbuf);
258# else
259 m = *fin->fin_mp;
289# if defined(MENTAT)
260 if (inc < 0)
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)
261 m_adj(m, inc);
299 m_adj(m, inc);
262 /* the mbuf chain will be extended if necessary by m_copyback() */
263 m_copyback(m, off, nlen, newbuf);
264# ifdef M_PKTHDR
265 if (!(m->m_flags & M_PKTHDR))
266 m->m_pkthdr.len += inc;
267# endif
268# endif
269#endif
270 if (inc != 0) {
271#if ((SOLARIS || defined(__sgi)) && defined(_KERNEL)) || !defined(_KERNEL)
272 register u_32_t sum1, sum2;
300# endif /* defined(MENTAT) */
301#endif /* !defined(_KERNEL) */
302 COPYBACK(m, off, nlen, newbuf);
273
303
274 sum1 = ip->ip_len;
275 sum2 = ip->ip_len + inc;
276
277 /* Because ~1 == -2, We really need ~1 == -1 */
278 if (sum1 > sum2)
279 sum2--;
280 sum2 -= sum1;
281 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
282
283 fix_outcksum(fin, &ip->ip_sum, sum2);
284#endif
304 if (inc != 0) {
285 ip->ip_len += inc;
305 ip->ip_len += inc;
306 fin->fin_dlen += inc;
307 fin->fin_plen += inc;
286 }
287
288 /*
308 }
309
310 /*
289 * Add skeleton NAT entry for connection which will come back the
290 * other way.
291 */
292 sp = (a5 << 8 | a6);
293 /*
294 * Don't allow the PORT command to specify a port < 1024 due to
295 * security crap.
296 */
297 if (sp < 1024) {
298#if !defined(_KERNEL) && !defined(KERNEL)
299 fprintf(stdout, "ippr_ftp_port:sp(%d) < 1024\n", sp);
300#endif
301 return 0;
302 }
303
304 /*
305 * The server may not make the connection back from port 20, but
306 * it is the most likely so use it here to check for a conflicting
307 * mapping.
308 */
309 bcopy((char *)fin, (char *)&fi, sizeof(fi));
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));
316 fi.fin_state = NULL;
317 fi.fin_nat = NULL;
318 fi.fin_flx |= FI_IGNORE;
310 fi.fin_data[0] = sp;
311 fi.fin_data[1] = fin->fin_data[1] - 1;
319 fi.fin_data[0] = sp;
320 fi.fin_data[1] = fin->fin_data[1] - 1;
312 ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip,
313 ip->ip_dst, 0);
314 if (ipn == NULL) {
321 /*
322 * Add skeleton NAT entry for connection which will come back the
323 * other way.
324 */
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) {
315 int slen;
316
317 slen = ip->ip_len;
318 ip->ip_len = fin->fin_hlen + sizeof(*tcp2);
319 bzero((char *)tcp2, sizeof(*tcp2));
320 tcp2->th_win = htons(8192);
321 tcp2->th_sport = htons(sp);
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);
322 tcp2->th_off = 5;
339 TCP_OFF_A(tcp2, 5);
323 tcp2->th_flags = TH_SYN;
324 tcp2->th_dport = 0; /* XXX - don't specify remote port */
325 fi.fin_data[1] = 0;
326 fi.fin_dlen = sizeof(*tcp2);
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);
327 fi.fin_dp = (char *)tcp2;
328 fi.fin_fr = &ftppxyfr;
345 fi.fin_dp = (char *)tcp2;
346 fi.fin_fr = &ftppxyfr;
329 fi.fin_out = 1;
347 fi.fin_out = nat->nat_dir;
348 fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE;
330 swip = ip->ip_src;
349 swip = ip->ip_src;
331 fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
332 ip->ip_src = nat->nat_inip;
333 ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_DPORT,
334 NAT_OUTBOUND);
335 if (ipn != NULL) {
336 ipn->nat_age = fr_defnatage;
337 (void) fr_addstate(ip, &fi, NULL,
338 FI_W_DPORT|FI_IGNOREPKT);
350 swip2 = ip->ip_dst;
351 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;
339 }
357 }
358
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);
363
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, &nat2->nat_state, SI_W_DPORT);
373 if (fi.fin_state != NULL)
374 fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
375 }
340 ip->ip_len = slen;
341 ip->ip_src = swip;
376 ip->ip_len = slen;
377 ip->ip_src = swip;
378 ip->ip_dst = swip2;
379 } else {
380 ipstate_t *is;
381
382 nat_update(&fi, nat2, nat->nat_ptr);
383 READ_ENTER(&ipf_state);
384 is = nat2->nat_state;
385 if (is != NULL) {
386 MUTEX_ENTER(&is->is_lock);
387 (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb,
388 is->is_flags);
389 MUTEX_EXIT(&is->is_lock);
390 }
391 RWLOCK_EXIT(&ipf_state);
342 }
392 }
343 return inc;
393 return APR_INC(inc);
344}
345
346
347int ippr_ftp_client(fin, ip, nat, ftp, dlen)
348fr_info_t *fin;
349nat_t *nat;
350ftpinfo_t *ftp;
351ip_t *ip;

--- 5 unchanged lines hidden (view full) ---

357
358 inc = 0;
359 f = &ftp->ftp_side[0];
360 rptr = f->ftps_rptr;
361 wptr = f->ftps_wptr;
362
363 for (i = 0; (i < 5) && (i < dlen); i++) {
364 c = rptr[i];
394}
395
396
397int ippr_ftp_client(fin, ip, nat, ftp, dlen)
398fr_info_t *fin;
399nat_t *nat;
400ftpinfo_t *ftp;
401ip_t *ip;

--- 5 unchanged lines hidden (view full) ---

407
408 inc = 0;
409 f = &ftp->ftp_side[0];
410 rptr = f->ftps_rptr;
411 wptr = f->ftps_wptr;
412
413 for (i = 0; (i < 5) && (i < dlen); i++) {
414 c = rptr[i];
365 if (isalpha(c)) {
366 cmd[i] = toupper(c);
415 if (ISALPHA(c)) {
416 cmd[i] = TOUPPER(c);
367 } else {
368 cmd[i] = c;
369 }
370 }
371 cmd[i] = '\0';
372
373 ftp->ftp_incok = 0;
374 if (!strncmp(cmd, "USER ", 5) || !strncmp(cmd, "XAUT ", 5)) {

--- 42 unchanged lines hidden (view full) ---

417
418int ippr_ftp_pasv(fin, ip, nat, ftp, dlen)
419fr_info_t *fin;
420ip_t *ip;
421nat_t *nat;
422ftpinfo_t *ftp;
423int dlen;
424{
417 } else {
418 cmd[i] = c;
419 }
420 }
421 cmd[i] = '\0';
422
423 ftp->ftp_incok = 0;
424 if (!strncmp(cmd, "USER ", 5) || !strncmp(cmd, "XAUT ", 5)) {

--- 42 unchanged lines hidden (view full) ---

467
468int ippr_ftp_pasv(fin, ip, nat, ftp, dlen)
469fr_info_t *fin;
470ip_t *ip;
471nat_t *nat;
472ftpinfo_t *ftp;
473int dlen;
474{
425 tcphdr_t *tcp, tcph, *tcp2 = &tcph;
426 struct in_addr swip, swip2;
427 u_int a1, a2, a3, a4;
428 u_short a5, a6, dp;
429 fr_info_t fi;
475 u_int a1, a2, a3, a4, data_ip;
476 char newbuf[IPF_FTPBUFSZ];
477 char *s, *brackets[2];
478 u_short a5, a6;
430 ftpside_t *f;
479 ftpside_t *f;
431 nat_t *ipn;
432 int inc;
433 char *s;
434
435 if (ippr_ftp_forcepasv != 0 &&
436 ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) {
480
481 if (ippr_ftp_forcepasv != 0 &&
482 ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) {
437#if !defined(_KERNEL) && !defined(KERNEL)
438 fprintf(stdout,
439 "ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n",
440 ftp->ftp_side[0].ftps_cmds);
441#endif
483 if (ippr_ftp_debug > 0)
484 printf("ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n",
485 ftp->ftp_side[0].ftps_cmds);
442 return 0;
443 }
444
445 f = &ftp->ftp_side[1];
446
447#define PASV_REPLEN 24
448 /*
449 * Check for PASV reply message.
450 */
451 if (dlen < IPF_MIN227LEN) {
486 return 0;
487 }
488
489 f = &ftp->ftp_side[1];
490
491#define PASV_REPLEN 24
492 /*
493 * Check for PASV reply message.
494 */
495 if (dlen < IPF_MIN227LEN) {
452#if !defined(_KERNEL) && !defined(KERNEL)
453 fprintf(stdout,
454 "ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", dlen);
455#endif
496 if (ippr_ftp_debug > 1)
497 printf("ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n",
498 dlen);
456 return 0;
457 } else if (strncmp(f->ftps_rptr,
458 "227 Entering Passive Mod", PASV_REPLEN)) {
499 return 0;
500 } else if (strncmp(f->ftps_rptr,
501 "227 Entering Passive Mod", PASV_REPLEN)) {
459#if !defined(_KERNEL) && !defined(KERNEL)
460 fprintf(stdout, "ippr_ftp_pasv:227 reply wrong\n");
461#endif
502 if (ippr_ftp_debug > 0)
503 printf("ippr_ftp_pasv:%d reply wrong\n", 227);
462 return 0;
463 }
464
504 return 0;
505 }
506
465 tcp = (tcphdr_t *)fin->fin_dp;
466
507 brackets[0] = "";
508 brackets[1] = "";
467 /*
468 * Skip the PASV reply + space
469 */
470 s = f->ftps_rptr + PASV_REPLEN;
509 /*
510 * Skip the PASV reply + space
511 */
512 s = f->ftps_rptr + PASV_REPLEN;
471 while (*s && !isdigit(*s))
513 while (*s && !ISDIGIT(*s)) {
514 if (*s == '(') {
515 brackets[0] = "(";
516 brackets[1] = ")";
517 }
472 s++;
518 s++;
519 }
520
473 /*
474 * Pick out the address components, two at a time.
475 */
476 a1 = ippr_ftp_atoi(&s);
477 if (s == NULL) {
521 /*
522 * Pick out the address components, two at a time.
523 */
524 a1 = ippr_ftp_atoi(&s);
525 if (s == NULL) {
478#if !defined(_KERNEL) && !defined(KERNEL)
479 fprintf(stdout, "ippr_ftp_pasv:ippr_ftp_atoi(1) failed\n");
480#endif
526 if (ippr_ftp_debug > 1)
527 printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 1);
481 return 0;
482 }
483 a2 = ippr_ftp_atoi(&s);
484 if (s == NULL) {
528 return 0;
529 }
530 a2 = ippr_ftp_atoi(&s);
531 if (s == NULL) {
485#if !defined(_KERNEL) && !defined(KERNEL)
486 fprintf(stdout, "ippr_ftp_pasv:ippr_ftp_atoi(2) failed\n");
487#endif
532 if (ippr_ftp_debug > 1)
533 printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 2);
488 return 0;
489 }
490
491 /*
534 return 0;
535 }
536
537 /*
492 * check that IP address in the PORT/PASV reply is the same as the
493 * sender of the command - prevents using PORT for port scanning.
538 * check that IP address in the PASV reply is the same as the
539 * sender of the command - prevents using PASV for port scanning.
494 */
495 a1 <<= 16;
496 a1 |= a2;
540 */
541 a1 <<= 16;
542 a1 |= a2;
497 if (a1 != ntohl(nat->nat_oip.s_addr)) {
498#if !defined(_KERNEL) && !defined(KERNEL)
499 fprintf(stdout, "ippr_ftp_pasv:a1 != nat->nat_oip\n");
500#endif
543
544 if (((nat->nat_dir == NAT_INBOUND) &&
545 (a1 != ntohl(nat->nat_inip.s_addr))) ||
546 ((nat->nat_dir == NAT_OUTBOUND) &&
547 (a1 != ntohl(nat->nat_oip.s_addr)))) {
548 if (ippr_ftp_debug > 0)
549 printf("ippr_ftp_pasv:%s != nat->nat_oip\n", "a1");
501 return 0;
502 }
503
504 a5 = ippr_ftp_atoi(&s);
505 if (s == NULL) {
550 return 0;
551 }
552
553 a5 = ippr_ftp_atoi(&s);
554 if (s == NULL) {
506#if !defined(_KERNEL) && !defined(KERNEL)
507 fprintf(stdout, "ippr_ftp_pasv:ippr_ftp_atoi(3) failed\n");
508#endif
555 if (ippr_ftp_debug > 1)
556 printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 3);
509 return 0;
510 }
511
512 if (*s == ')')
513 s++;
514 if (*s == '.')
515 s++;
516 if (*s == '\n')
517 s--;
518 /*
519 * check for CR-LF at the end.
520 */
521 if ((*s == '\r') && (*(s + 1) == '\n')) {
522 s += 2;
557 return 0;
558 }
559
560 if (*s == ')')
561 s++;
562 if (*s == '.')
563 s++;
564 if (*s == '\n')
565 s--;
566 /*
567 * check for CR-LF at the end.
568 */
569 if ((*s == '\r') && (*(s + 1) == '\n')) {
570 s += 2;
523 a6 = a5 & 0xff;
524 } else {
571 } else {
525#if !defined(_KERNEL) && !defined(KERNEL)
526 fprintf(stdout, "ippr_ftp_pasv:missing cr-lf\n");
527#endif
572 if (ippr_ftp_debug > 1)
573 printf("ippr_ftp_pasv:missing %s", "cr-lf\n");
528 return 0;
529 }
574 return 0;
575 }
576
577 a6 = a5 & 0xff;
530 a5 >>= 8;
531 /*
532 * Calculate new address parts for 227 reply
533 */
578 a5 >>= 8;
579 /*
580 * Calculate new address parts for 227 reply
581 */
534 a1 = ntohl(ip->ip_src.s_addr);
582 if (nat->nat_dir == NAT_INBOUND) {
583 data_ip = nat->nat_outip.s_addr;
584 a1 = ntohl(data_ip);
585 } else
586 data_ip = htonl(a1);
587
535 a2 = (a1 >> 16) & 0xff;
536 a3 = (a1 >> 8) & 0xff;
537 a4 = a1 & 0xff;
538 a1 >>= 24;
588 a2 = (a1 >> 16) & 0xff;
589 a3 = (a1 >> 8) & 0xff;
590 a4 = a1 & 0xff;
591 a1 >>= 24;
539 inc = 0;
540#if 0
541 olen = s - f->ftps_rptr;
542 (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n",
543 "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6);
544 nlen = strlen(newbuf);
545 inc = nlen - olen;
546 if ((inc + ip->ip_len) > 65535)
547 return 0;
548
592
549#if !defined(_KERNEL)
550 m = *fin->fin_mp;
551 m_copyback(m, off, nlen, newbuf);
593#if defined(SNPRINTF) && defined(_KERNEL)
594 SNPRINTF(newbuf, sizeof(newbuf), "%s %s%u,%u,%u,%u,%u,%u%s\r\n",
595 "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4,
596 a5, a6, brackets[1]);
552#else
597#else
553# if SOLARIS
554 m = fin->fin_qfm;
555 for (m1 = m; m1->b_cont; m1 = m1->b_cont)
556 ;
557 if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
558 mblk_t *nm;
598 (void) sprintf(newbuf, "%s %s%u,%u,%u,%u,%u,%u%s\r\n",
599 "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4,
600 a5, a6, brackets[1]);
601#endif
602 return ippr_ftp_pasvreply(fin, ip, nat, f, (a5 << 8 | a6),
603 newbuf, s, data_ip);
604}
559
605
560 /* alloc enough to keep same trailer space for lower driver */
561 nm = allocb(nlen, BPRI_MED);
562 PANIC((!nm),("ippr_ftp_out: allocb failed"));
606int ippr_ftp_pasvreply(fin, ip, nat, f, port, newmsg, s, data_ip)
607fr_info_t *fin;
608ip_t *ip;
609nat_t *nat;
610ftpside_t *f;
611u_int port;
612char *newmsg;
613char *s;
614u_int data_ip;
615{
616 int inc, off, nflags, sflags;
617 tcphdr_t *tcp, tcph, *tcp2;
618 struct in_addr swip, swip2;
619 struct in_addr data_addr;
620 size_t nlen, olen;
621 fr_info_t fi;
622 nat_t *nat2;
623 mb_t *m;
563
624
564 nm->b_band = m1->b_band;
565 nm->b_wptr += nlen;
625 m = fin->fin_m;
626 tcp = (tcphdr_t *)fin->fin_dp;
627 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
566
628
567 m1->b_wptr -= olen;
568 PANIC((m1->b_wptr < m1->b_rptr),
569 ("ippr_ftp_out: cannot handle fragmented data block"));
629 data_addr.s_addr = data_ip;
630 tcp2 = &tcph;
631 inc = 0;
570
632
571 linkb(m1, nm);
572 } else {
573 m1->b_wptr += inc;
633
634 olen = s - f->ftps_rptr;
635 nlen = strlen(newmsg);
636 inc = nlen - olen;
637 if ((inc + ip->ip_len) > 65535) {
638 if (ippr_ftp_debug > 0)
639 printf("ippr_ftp_pasv:inc(%d) + ip->ip_len > 65535\n",
640 inc);
641 return 0;
574 }
642 }
575 /*copyin_mblk(m, off, nlen, newbuf);*/
576# else /* SOLARIS */
577 m = *fin->fin_mp;
643
644#if !defined(_KERNEL)
645 bcopy(newmsg, MTOD(m, char *) + off, nlen);
646#else
647# if defined(MENTAT)
578 if (inc < 0)
648 if (inc < 0)
649 (void)adjmsg(m, inc);
650# else /* defined(MENTAT) */
651 /*
652 * m_adj takes care of pkthdr.len, if required and treats inc<0 to
653 * mean remove -len bytes from the end of the packet.
654 * The mbuf chain will be extended if necessary by m_copyback().
655 */
656 if (inc < 0)
579 m_adj(m, inc);
657 m_adj(m, inc);
580 /* the mbuf chain will be extended if necessary by m_copyback() */
581 /*m_copyback(m, off, nlen, newbuf);*/
582# endif /* SOLARIS */
583#endif /* _KERNEL */
584 if (inc != 0) {
585#if ((SOLARIS || defined(__sgi)) && defined(_KERNEL)) || !defined(_KERNEL)
586 register u_32_t sum1, sum2;
658# endif /* defined(MENTAT) */
659#endif /* !defined(_KERNEL) */
660 COPYBACK(m, off, nlen, newmsg);
587
661
588 sum1 = ip->ip_len;
589 sum2 = ip->ip_len + inc;
590
591 /* Because ~1 == -2, We really need ~1 == -1 */
592 if (sum1 > sum2)
593 sum2--;
594 sum2 -= sum1;
595 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
596
597 fix_outcksum(fin, &ip->ip_sum, sum2);
598#endif /* SOLARIS || defined(__sgi) */
662 if (inc != 0) {
599 ip->ip_len += inc;
663 ip->ip_len += inc;
664 fin->fin_dlen += inc;
665 fin->fin_plen += inc;
600 }
666 }
601#endif /* 0 */
602
603 /*
604 * Add skeleton NAT entry for connection which will come back the
605 * other way.
606 */
607 bcopy((char *)fin, (char *)&fi, sizeof(fi));
667
668 /*
669 * Add skeleton NAT entry for connection which will come back the
670 * other way.
671 */
672 bcopy((char *)fin, (char *)&fi, sizeof(fi));
673 fi.fin_state = NULL;
674 fi.fin_nat = NULL;
675 fi.fin_flx |= FI_IGNORE;
608 fi.fin_data[0] = 0;
676 fi.fin_data[0] = 0;
609 dp = htons(fin->fin_data[1] - 1);
610 fi.fin_data[1] = ntohs(dp);
611 ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip,
612 ip->ip_dst, 0);
613 if (ipn == NULL) {
677 fi.fin_data[1] = port;
678 nflags = IPN_TCP|SI_W_SPORT;
679 if (ippr_ftp_pasvrdr && f->ftps_ifp)
680 nflags |= SI_W_DPORT;
681 if (nat->nat_dir == NAT_OUTBOUND)
682 nat2 = nat_outlookup(&fi, nflags|NAT_SEARCH,
683 nat->nat_p, nat->nat_inip, nat->nat_oip);
684 else
685 nat2 = nat_inlookup(&fi, nflags|NAT_SEARCH,
686 nat->nat_p, nat->nat_inip, nat->nat_oip);
687 if (nat2 == NULL) {
614 int slen;
615
616 slen = ip->ip_len;
617 ip->ip_len = fin->fin_hlen + sizeof(*tcp2);
618 bzero((char *)tcp2, sizeof(*tcp2));
619 tcp2->th_win = htons(8192);
620 tcp2->th_sport = 0; /* XXX - fake it for nat_new */
688 int slen;
689
690 slen = ip->ip_len;
691 ip->ip_len = fin->fin_hlen + sizeof(*tcp2);
692 bzero((char *)tcp2, sizeof(*tcp2));
693 tcp2->th_win = htons(8192);
694 tcp2->th_sport = 0; /* XXX - fake it for nat_new */
621 tcp2->th_off = 5;
695 TCP_OFF_A(tcp2, 5);
622 tcp2->th_flags = TH_SYN;
696 tcp2->th_flags = TH_SYN;
623 fi.fin_data[1] = a5 << 8 | a6;
697 fi.fin_data[1] = port;
624 fi.fin_dlen = sizeof(*tcp2);
698 fi.fin_dlen = sizeof(*tcp2);
625 tcp2->th_dport = htons(fi.fin_data[1]);
699 tcp2->th_dport = htons(port);
626 fi.fin_data[0] = 0;
627 fi.fin_dp = (char *)tcp2;
700 fi.fin_data[0] = 0;
701 fi.fin_dp = (char *)tcp2;
702 fi.fin_plen = fi.fin_hlen + sizeof(*tcp);
628 fi.fin_fr = &ftppxyfr;
703 fi.fin_fr = &ftppxyfr;
629 fi.fin_out = 1;
704 fi.fin_out = nat->nat_dir;
705 fi.fin_flx &= FI_LOWTTL|FI_FRAG|FI_TCPUDP|FI_OPTIONS|FI_IGNORE;
630 swip = ip->ip_src;
631 swip2 = ip->ip_dst;
706 swip = ip->ip_src;
707 swip2 = ip->ip_dst;
632 fi.fin_fi.fi_daddr = ip->ip_src.s_addr;
633 fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
634 ip->ip_dst = ip->ip_src;
635 ip->ip_src = nat->nat_inip;
636 ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_SPORT,
637 NAT_OUTBOUND);
638 if (ipn != NULL) {
639 ipn->nat_age = fr_defnatage;
640 (void) fr_addstate(ip, &fi, NULL,
641 FI_W_SPORT|FI_IGNOREPKT);
708 if (nat->nat_dir == NAT_OUTBOUND) {
709 fi.fin_fi.fi_daddr = data_addr.s_addr;
710 fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
711 ip->ip_dst = data_addr;
712 ip->ip_src = nat->nat_inip;
713 } else if (nat->nat_dir == NAT_INBOUND) {
714 fi.fin_fi.fi_saddr = nat->nat_oip.s_addr;
715 fi.fin_fi.fi_daddr = nat->nat_outip.s_addr;
716 ip->ip_src = nat->nat_oip;
717 ip->ip_dst = nat->nat_outip;
642 }
718 }
719
720 sflags = nflags;
721 nflags |= NAT_SLAVE;
722 if (nat->nat_dir == NAT_INBOUND)
723 nflags |= NAT_NOTRULEPORT;
724 nat2 = nat_new(&fi, nat->nat_ptr, NULL, nflags, nat->nat_dir);
725 if (nat2 != NULL) {
726 (void) nat_proto(&fi, nat2, IPN_TCP);
727 nat_update(&fi, nat2, nat->nat_ptr);
728 fi.fin_ifp = NULL;
729 if (nat->nat_dir == NAT_INBOUND) {
730 fi.fin_fi.fi_daddr = nat->nat_inip.s_addr;
731 ip->ip_dst = nat->nat_inip;
732 }
733 (void) fr_addstate(&fi, &nat2->nat_state, sflags);
734 if (fi.fin_state != NULL)
735 fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
736 }
737
643 ip->ip_len = slen;
644 ip->ip_src = swip;
645 ip->ip_dst = swip2;
738 ip->ip_len = slen;
739 ip->ip_src = swip;
740 ip->ip_dst = swip2;
741 } else {
742 ipstate_t *is;
743
744 nat_update(&fi, nat2, nat->nat_ptr);
745 READ_ENTER(&ipf_state);
746 is = nat2->nat_state;
747 if (is != NULL) {
748 MUTEX_ENTER(&is->is_lock);
749 (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb,
750 is->is_flags);
751 MUTEX_EXIT(&is->is_lock);
752 }
753 RWLOCK_EXIT(&ipf_state);
646 }
647 return inc;
648}
649
650
651int ippr_ftp_server(fin, ip, nat, ftp, dlen)
652fr_info_t *fin;
653ip_t *ip;

--- 5 unchanged lines hidden (view full) ---

659 ftpside_t *f;
660 int inc;
661
662 inc = 0;
663 f = &ftp->ftp_side[1];
664 rptr = f->ftps_rptr;
665 wptr = f->ftps_wptr;
666
754 }
755 return inc;
756}
757
758
759int ippr_ftp_server(fin, ip, nat, ftp, dlen)
760fr_info_t *fin;
761ip_t *ip;

--- 5 unchanged lines hidden (view full) ---

767 ftpside_t *f;
768 int inc;
769
770 inc = 0;
771 f = &ftp->ftp_side[1];
772 rptr = f->ftps_rptr;
773 wptr = f->ftps_wptr;
774
667 if (!isdigit(*rptr) || !isdigit(*(rptr + 1)) || !isdigit(*(rptr + 2)))
775 if (*rptr == ' ')
776 goto server_cmd_ok;
777 if (!ISDIGIT(*rptr) || !ISDIGIT(*(rptr + 1)) || !ISDIGIT(*(rptr + 2)))
668 return 0;
669 if (ftp->ftp_passok == FTPXY_GO) {
670 if (!strncmp(rptr, "227 ", 4))
671 inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen);
778 return 0;
779 if (ftp->ftp_passok == FTPXY_GO) {
780 if (!strncmp(rptr, "227 ", 4))
781 inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen);
782 else if (!strncmp(rptr, "229 ", 4))
783 inc = ippr_ftp_epsv(fin, ip, nat, f, dlen);
672 } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) {
673 inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen);
784 } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) {
785 inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen);
786 } else if (ippr_ftp_insecure && !strncmp(rptr, "229 ", 4)) {
787 inc = ippr_ftp_epsv(fin, ip, nat, f, dlen);
674 } else if (*rptr == '5' || *rptr == '4')
675 ftp->ftp_passok = FTPXY_INIT;
676 else if (ftp->ftp_incok) {
677 if (*rptr == '3') {
678 if (ftp->ftp_passok == FTPXY_ACCT_1)
679 ftp->ftp_passok = FTPXY_GO;
680 else
681 ftp->ftp_passok++;

--- 8 unchanged lines hidden (view full) ---

690 ftp->ftp_passok = FTPXY_GO;
691 break;
692 default :
693 ftp->ftp_passok += 3;
694 break;
695 }
696 }
697 }
788 } else if (*rptr == '5' || *rptr == '4')
789 ftp->ftp_passok = FTPXY_INIT;
790 else if (ftp->ftp_incok) {
791 if (*rptr == '3') {
792 if (ftp->ftp_passok == FTPXY_ACCT_1)
793 ftp->ftp_passok = FTPXY_GO;
794 else
795 ftp->ftp_passok++;

--- 8 unchanged lines hidden (view full) ---

804 ftp->ftp_passok = FTPXY_GO;
805 break;
806 default :
807 ftp->ftp_passok += 3;
808 break;
809 }
810 }
811 }
812server_cmd_ok:
698 ftp->ftp_incok = 0;
699
700 while ((*rptr++ != '\n') && (rptr < wptr))
701 ;
702 f->ftps_rptr = rptr;
703 return inc;
704}
705
706
707/*
708 * Look to see if the buffer starts with something which we recognise as
709 * being the correct syntax for the FTP protocol.
710 */
711int ippr_ftp_client_valid(ftps, buf, len)
712ftpside_t *ftps;
713char *buf;
714size_t len;
715{
813 ftp->ftp_incok = 0;
814
815 while ((*rptr++ != '\n') && (rptr < wptr))
816 ;
817 f->ftps_rptr = rptr;
818 return inc;
819}
820
821
822/*
823 * Look to see if the buffer starts with something which we recognise as
824 * being the correct syntax for the FTP protocol.
825 */
826int ippr_ftp_client_valid(ftps, buf, len)
827ftpside_t *ftps;
828char *buf;
829size_t len;
830{
716 register char *s, c;
831 register char *s, c, pc;
717 register size_t i = len;
718 char cmd[5];
719
832 register size_t i = len;
833 char cmd[5];
834
835 s = buf;
836
837 if (ftps->ftps_junk == 1)
838 return 1;
839
720 if (i < 5) {
840 if (i < 5) {
721#if !defined(_KERNEL) && !defined(KERNEL)
722 fprintf(stdout, "ippr_ftp_client_valid:i(%lu) < 5\n",
723 (u_long)i);
724#endif
841 if (ippr_ftp_debug > 3)
842 printf("ippr_ftp_client_valid:i(%d) < 5\n", (int)i);
725 return 2;
726 }
843 return 2;
844 }
727 s = buf;
728 c = *s++;
845
729 i--;
846 i--;
847 c = *s++;
730
848
731 if (isalpha(c)) {
732 cmd[0] = toupper(c);
849 if (ISALPHA(c)) {
850 cmd[0] = TOUPPER(c);
733 c = *s++;
734 i--;
851 c = *s++;
852 i--;
735 if (isalpha(c)) {
736 cmd[1] = toupper(c);
853 if (ISALPHA(c)) {
854 cmd[1] = TOUPPER(c);
737 c = *s++;
738 i--;
855 c = *s++;
856 i--;
739 if (isalpha(c)) {
740 cmd[2] = toupper(c);
857 if (ISALPHA(c)) {
858 cmd[2] = TOUPPER(c);
741 c = *s++;
742 i--;
859 c = *s++;
860 i--;
743 if (isalpha(c)) {
744 cmd[3] = toupper(c);
861 if (ISALPHA(c)) {
862 cmd[3] = TOUPPER(c);
745 c = *s++;
746 i--;
747 if ((c != ' ') && (c != '\r'))
748 goto bad_client_command;
749 } else if ((c != ' ') && (c != '\r'))
750 goto bad_client_command;
751 } else
752 goto bad_client_command;
753 } else
754 goto bad_client_command;
755 } else {
756bad_client_command:
863 c = *s++;
864 i--;
865 if ((c != ' ') && (c != '\r'))
866 goto bad_client_command;
867 } else if ((c != ' ') && (c != '\r'))
868 goto bad_client_command;
869 } else
870 goto bad_client_command;
871 } else
872 goto bad_client_command;
873 } else {
874bad_client_command:
757#if !defined(_KERNEL) && !defined(KERNEL)
758 fprintf(stdout,
759 "ippr_ftp_client_valid:bad cmd:len %lu i %lu c 0x%x\n",
760 (u_long)i, (u_long)len, c);
761#endif
875 if (ippr_ftp_debug > 3)
876 printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n",
877 "ippr_ftp_client_valid",
878 ftps->ftps_junk, (int)len, (int)i, c,
879 (int)len, (int)len, buf);
762 return 1;
763 }
764
765 for (; i; i--) {
880 return 1;
881 }
882
883 for (; i; i--) {
884 pc = c;
766 c = *s++;
885 c = *s++;
767 if (c == '\n') {
886 if ((pc == '\r') && (c == '\n')) {
768 cmd[4] = '\0';
769 if (!strcmp(cmd, "PASV"))
770 ftps->ftps_cmds = FTPXY_C_PASV;
771 else
772 ftps->ftps_cmds = 0;
773 return 0;
774 }
775 }
887 cmd[4] = '\0';
888 if (!strcmp(cmd, "PASV"))
889 ftps->ftps_cmds = FTPXY_C_PASV;
890 else
891 ftps->ftps_cmds = 0;
892 return 0;
893 }
894 }
776#if !defined(_KERNEL) && !defined(KERNEL)
777 fprintf(stdout, "ippr_ftp_client_valid:junk after cmd[%s]\n", buf);
895#if !defined(_KERNEL)
896 printf("ippr_ftp_client_valid:junk after cmd[%*.*s]\n",
897 (int)len, (int)len, buf);
778#endif
779 return 2;
780}
781
782
783int ippr_ftp_server_valid(ftps, buf, len)
784ftpside_t *ftps;
785char *buf;
786size_t len;
787{
898#endif
899 return 2;
900}
901
902
903int ippr_ftp_server_valid(ftps, buf, len)
904ftpside_t *ftps;
905char *buf;
906size_t len;
907{
788 register char *s, c;
908 register char *s, c, pc;
789 register size_t i = len;
790 int cmd;
791
909 register size_t i = len;
910 int cmd;
911
792 if (i < 5)
793 return 2;
794 s = buf;
912 s = buf;
795 c = *s++;
796 cmd = 0;
913 cmd = 0;
914
915 if (ftps->ftps_junk == 1)
916 return 1;
917
918 if (i < 5) {
919 if (ippr_ftp_debug > 3)
920 printf("ippr_ftp_servert_valid:i(%d) < 5\n", (int)i);
921 return 2;
922 }
923
924 c = *s++;
797 i--;
925 i--;
926 if (c == ' ')
927 goto search_eol;
798
928
799 if (isdigit(c)) {
929 if (ISDIGIT(c)) {
800 cmd = (c - '0') * 100;
801 c = *s++;
802 i--;
930 cmd = (c - '0') * 100;
931 c = *s++;
932 i--;
803 if (isdigit(c)) {
933 if (ISDIGIT(c)) {
804 cmd += (c - '0') * 10;
805 c = *s++;
806 i--;
934 cmd += (c - '0') * 10;
935 c = *s++;
936 i--;
807 if (isdigit(c)) {
937 if (ISDIGIT(c)) {
808 cmd += (c - '0');
809 c = *s++;
810 i--;
811 if ((c != '-') && (c != ' '))
812 goto bad_server_command;
813 } else
814 goto bad_server_command;
815 } else
816 goto bad_server_command;
817 } else {
818bad_server_command:
938 cmd += (c - '0');
939 c = *s++;
940 i--;
941 if ((c != '-') && (c != ' '))
942 goto bad_server_command;
943 } else
944 goto bad_server_command;
945 } else
946 goto bad_server_command;
947 } else {
948bad_server_command:
819#if !defined(_KERNEL) && !defined(KERNEL)
820 fprintf(stdout,
821 "ippr_ftp_server_valid:bad cmd:len %lu i %lu c 0x%x\n",
822 (u_long)i, (u_long)len, c);
823#endif
949 if (ippr_ftp_debug > 3)
950 printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n",
951 "ippr_ftp_server_valid",
952 ftps->ftps_junk, (int)len, (int)i,
953 c, (int)len, (int)len, buf);
824 return 1;
825 }
954 return 1;
955 }
826
956search_eol:
827 for (; i; i--) {
957 for (; i; i--) {
958 pc = c;
828 c = *s++;
959 c = *s++;
829 if (c == '\n') {
960 if ((pc == '\r') && (c == '\n')) {
830 ftps->ftps_cmds = cmd;
831 return 0;
832 }
833 }
961 ftps->ftps_cmds = cmd;
962 return 0;
963 }
964 }
834#if !defined(_KERNEL) && !defined(KERNEL)
835 fprintf(stdout, "ippr_ftp_server_valid:junk after cmd[%s]\n", buf);
836#endif
965 if (ippr_ftp_debug > 3)
966 printf("ippr_ftp_server_valid:junk after cmd[%*.*s]\n",
967 (int)len, (int)len, buf);
837 return 2;
838}
839
840
841int ippr_ftp_valid(ftp, side, buf, len)
842ftpinfo_t *ftp;
843int side;
844char *buf;

--- 8 unchanged lines hidden (view full) ---

853 ret = ippr_ftp_client_valid(ftps, buf, len);
854 else
855 ret = ippr_ftp_server_valid(ftps, buf, len);
856 return ret;
857}
858
859
860/*
968 return 2;
969}
970
971
972int ippr_ftp_valid(ftp, side, buf, len)
973ftpinfo_t *ftp;
974int side;
975char *buf;

--- 8 unchanged lines hidden (view full) ---

984 ret = ippr_ftp_client_valid(ftps, buf, len);
985 else
986 ret = ippr_ftp_server_valid(ftps, buf, len);
987 return ret;
988}
989
990
991/*
992 * For map rules, the following applies:
861 * rv == 0 for outbound processing,
862 * rv == 1 for inbound processing.
993 * rv == 0 for outbound processing,
994 * rv == 1 for inbound processing.
995 * For rdr rules, the following applies:
996 * rv == 0 for inbound processing,
997 * rv == 1 for outbound processing.
863 */
998 */
864int ippr_ftp_process(fin, ip, nat, ftp, rv)
999int ippr_ftp_process(fin, nat, ftp, rv)
865fr_info_t *fin;
1000fr_info_t *fin;
866ip_t *ip;
867nat_t *nat;
868ftpinfo_t *ftp;
869int rv;
870{
871 int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff;
1001nat_t *nat;
1002ftpinfo_t *ftp;
1003int rv;
1004{
1005 int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff;
1006 char *rptr, *wptr, *s;
872 u_32_t thseq, thack;
1007 u_32_t thseq, thack;
873 char *rptr, *wptr;
874 ap_session_t *aps;
875 ftpside_t *f, *t;
876 tcphdr_t *tcp;
1008 ap_session_t *aps;
1009 ftpside_t *f, *t;
1010 tcphdr_t *tcp;
1011 ip_t *ip;
877 mb_t *m;
878
1012 mb_t *m;
1013
1014 m = fin->fin_m;
1015 ip = fin->fin_ip;
879 tcp = (tcphdr_t *)fin->fin_dp;
1016 tcp = (tcphdr_t *)fin->fin_dp;
880 off = fin->fin_hlen + (tcp->th_off << 2);
881#if SOLARIS && defined(_KERNEL)
882 m = fin->fin_qfm;
883#else
884 m = *fin->fin_mp;
885#endif
1017 off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
886
1018
887#ifndef _KERNEL
888 mlen = mbuflen(m);
1019 f = &ftp->ftp_side[rv];
1020 t = &ftp->ftp_side[1 - rv];
1021 thseq = ntohl(tcp->th_seq);
1022 thack = ntohl(tcp->th_ack);
1023
1024#ifdef __sgi
1025 mlen = fin->fin_plen - off;
889#else
1026#else
890# if SOLARIS
891 mlen = msgdsize(m);
892# else
893 mlen = mbufchainlen(m);
894# endif
1027 mlen = MSGDSIZE(m) - off;
895#endif
1028#endif
896 mlen -= off;
1029 if (ippr_ftp_debug > 4)
1030 printf("ippr_ftp_process: mlen %d\n", mlen);
897
1031
1032 if (mlen <= 0) {
1033 if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
1034 f->ftps_seq[0] = thseq + 1;
1035 t->ftps_seq[0] = thack;
1036 }
1037 return 0;
1038 }
898 aps = nat->nat_aps;
1039 aps = nat->nat_aps;
899 t = &ftp->ftp_side[1 - rv];
900 f = &ftp->ftp_side[rv];
901 thseq = ntohl(tcp->th_seq);
902 thack = ntohl(tcp->th_ack);
903
904 sel = aps->aps_sel[1 - rv];
905 sel2 = aps->aps_sel[rv];
906 if (rv == 0) {
907 seqoff = aps->aps_seqoff[sel];
908 if (aps->aps_seqmin[sel] > seqoff + thseq)
909 seqoff = aps->aps_seqoff[!sel];
910 ackoff = aps->aps_ackoff[sel2];
911 if (aps->aps_ackmin[sel2] > ackoff + thack)
912 ackoff = aps->aps_ackoff[!sel2];
913 } else {
1040
1041 sel = aps->aps_sel[1 - rv];
1042 sel2 = aps->aps_sel[rv];
1043 if (rv == 0) {
1044 seqoff = aps->aps_seqoff[sel];
1045 if (aps->aps_seqmin[sel] > seqoff + thseq)
1046 seqoff = aps->aps_seqoff[!sel];
1047 ackoff = aps->aps_ackoff[sel2];
1048 if (aps->aps_ackmin[sel2] > ackoff + thack)
1049 ackoff = aps->aps_ackoff[!sel2];
1050 } else {
914#if PROXY_DEBUG
915 printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq,
916 aps->aps_ackmin[sel]);
917#endif
918 seqoff = aps->aps_ackoff[sel];
1051 seqoff = aps->aps_ackoff[sel];
1052 if (ippr_ftp_debug > 2)
1053 printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq,
1054 aps->aps_ackmin[sel]);
919 if (aps->aps_ackmin[sel] > seqoff + thseq)
920 seqoff = aps->aps_ackoff[!sel];
921
1055 if (aps->aps_ackmin[sel] > seqoff + thseq)
1056 seqoff = aps->aps_ackoff[!sel];
1057
922#if PROXY_DEBUG
923 printf("ackoff %d thack %x seqmin %x\n", ackoff, thack,
924 aps->aps_seqmin[sel2]);
925#endif
926 ackoff = aps->aps_seqoff[sel2];
1058 ackoff = aps->aps_seqoff[sel2];
1059 if (ippr_ftp_debug > 2)
1060 printf("ackoff %d thack %x seqmin %x\n", ackoff, thack,
1061 aps->aps_seqmin[sel2]);
927 if (ackoff > 0) {
928 if (aps->aps_seqmin[sel2] > ackoff + thack)
929 ackoff = aps->aps_seqoff[!sel2];
930 } else {
931 if (aps->aps_seqmin[sel2] > thack)
932 ackoff = aps->aps_seqoff[!sel2];
933 }
934 }
1062 if (ackoff > 0) {
1063 if (aps->aps_seqmin[sel2] > ackoff + thack)
1064 ackoff = aps->aps_seqoff[!sel2];
1065 } else {
1066 if (aps->aps_seqmin[sel2] > thack)
1067 ackoff = aps->aps_seqoff[!sel2];
1068 }
1069 }
935#if PROXY_DEBUG
936 printf("%s: %x seq %x/%d ack %x/%d len %d\n", rv ? "IN" : "OUT",
937 tcp->th_flags, thseq, seqoff, thack, ackoff, mlen);
938 printf("sel %d seqmin %x/%x offset %d/%d\n", sel,
939 aps->aps_seqmin[sel], aps->aps_seqmin[sel2],
940 aps->aps_seqoff[sel], aps->aps_seqoff[sel2]);
941 printf("sel %d ackmin %x/%x offset %d/%d\n", sel2,
942 aps->aps_ackmin[sel], aps->aps_ackmin[sel2],
943 aps->aps_ackoff[sel], aps->aps_ackoff[sel2]);
944#endif
1070 if (ippr_ftp_debug > 2) {
1071 printf("%s: %x seq %x/%d ack %x/%d len %d/%d off %d\n",
1072 rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff,
1073 thack, ackoff, mlen, fin->fin_plen, off);
1074 printf("sel %d seqmin %x/%x offset %d/%d\n", sel,
1075 aps->aps_seqmin[sel], aps->aps_seqmin[sel2],
1076 aps->aps_seqoff[sel], aps->aps_seqoff[sel2]);
1077 printf("sel %d ackmin %x/%x offset %d/%d\n", sel2,
1078 aps->aps_ackmin[sel], aps->aps_ackmin[sel2],
1079 aps->aps_ackoff[sel], aps->aps_ackoff[sel2]);
1080 }
945
946 /*
947 * XXX - Ideally, this packet should get dropped because we now know
948 * that it is out of order (and there is no real danger in doing so
949 * apart from causing packets to go through here ordered).
950 */
1081
1082 /*
1083 * XXX - Ideally, this packet should get dropped because we now know
1084 * that it is out of order (and there is no real danger in doing so
1085 * apart from causing packets to go through here ordered).
1086 */
951#if PROXY_DEBUG
952 printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n",
953 rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff);
954#endif
1087 if (ippr_ftp_debug > 2) {
1088 printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n",
1089 rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff);
1090 }
955
956 ok = 0;
957 if (t->ftps_seq[0] == 0) {
958 t->ftps_seq[0] = thack;
959 ok = 1;
960 } else {
961 if (ackoff == 0) {
962 if (t->ftps_seq[0] == thack)

--- 12 unchanged lines hidden (view full) ---

975 ok = 1;
976 } else if (t->ftps_seq[1] == thack + ackoff) {
977 t->ftps_seq[0] = thack - ackoff;
978 ok = 1;
979 }
980 }
981 }
982
1091
1092 ok = 0;
1093 if (t->ftps_seq[0] == 0) {
1094 t->ftps_seq[0] = thack;
1095 ok = 1;
1096 } else {
1097 if (ackoff == 0) {
1098 if (t->ftps_seq[0] == thack)

--- 12 unchanged lines hidden (view full) ---

1111 ok = 1;
1112 } else if (t->ftps_seq[1] == thack + ackoff) {
1113 t->ftps_seq[0] = thack - ackoff;
1114 ok = 1;
1115 }
1116 }
1117 }
1118
983#if PROXY_DEBUG
984 if (!ok)
985 printf("not ok\n");
986#endif
1119 if (ippr_ftp_debug > 2) {
1120 if (!ok)
1121 printf("%s ok\n", "not");
1122 }
987
988 if (!mlen) {
989 if (t->ftps_seq[0] + ackoff != thack) {
1123
1124 if (!mlen) {
1125 if (t->ftps_seq[0] + ackoff != thack) {
990#if !defined(_KERNEL) && !defined(KERNEL)
991 fprintf(stdout,
992 "ippr_ftp_process:seq[0](%x) + ackoff(%x) != thack(%x)\n",
993 t->ftps_seq[0], ackoff, thack);
994#endif
1126 if (ippr_ftp_debug > 1) {
1127 printf("%s:seq[0](%x) + (%x) != (%x)\n",
1128 "ippr_ftp_process", t->ftps_seq[0],
1129 ackoff, thack);
1130 }
995 return APR_ERR(1);
996 }
997
1131 return APR_ERR(1);
1132 }
1133
998#if PROXY_DEBUG
999 printf("f:seq[0] %x seq[1] %x\n", f->ftps_seq[0], f->ftps_seq[1]);
1000#endif
1134 if (ippr_ftp_debug > 2) {
1135 printf("ippr_ftp_process:f:seq[0] %x seq[1] %x\n",
1136 f->ftps_seq[0], f->ftps_seq[1]);
1137 }
1138
1001 if (tcp->th_flags & TH_FIN) {
1002 if (thseq == f->ftps_seq[1]) {
1003 f->ftps_seq[0] = f->ftps_seq[1] - seqoff;
1004 f->ftps_seq[1] = thseq + 1 - seqoff;
1005 } else {
1139 if (tcp->th_flags & TH_FIN) {
1140 if (thseq == f->ftps_seq[1]) {
1141 f->ftps_seq[0] = f->ftps_seq[1] - seqoff;
1142 f->ftps_seq[1] = thseq + 1 - seqoff;
1143 } else {
1006#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL))
1007 printf("FIN: thseq %x seqoff %d ftps_seq %x\n",
1008 thseq, seqoff, f->ftps_seq[0]);
1009#endif
1144 if (ippr_ftp_debug > 1) {
1145 printf("FIN: thseq %x seqoff %d ftps_seq %x\n",
1146 thseq, seqoff, f->ftps_seq[0]);
1147 }
1010 return APR_ERR(1);
1011 }
1012 }
1013 f->ftps_len = 0;
1014 return 0;
1015 }
1016
1017 ok = 0;

--- 4 unchanged lines hidden (view full) ---

1022 */
1023 } else if ((thseq + mlen == f->ftps_seq[0]) ||
1024 (thseq + mlen == f->ftps_seq[1])) {
1025 ok = 1;
1026 }
1027
1028 if (ok == 0) {
1029 inc = thseq - f->ftps_seq[0];
1148 return APR_ERR(1);
1149 }
1150 }
1151 f->ftps_len = 0;
1152 return 0;
1153 }
1154
1155 ok = 0;

--- 4 unchanged lines hidden (view full) ---

1160 */
1161 } else if ((thseq + mlen == f->ftps_seq[0]) ||
1162 (thseq + mlen == f->ftps_seq[1])) {
1163 ok = 1;
1164 }
1165
1166 if (ok == 0) {
1167 inc = thseq - f->ftps_seq[0];
1030#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL))
1031 printf("inc %d sel %d rv %d\n", inc, sel, rv);
1032 printf("th_seq %x ftps_seq %x/%x\n", thseq, f->ftps_seq[0],
1033 f->ftps_seq[1]);
1034 printf("ackmin %x ackoff %d\n", (u_int)aps->aps_ackmin[sel],
1035 aps->aps_ackoff[sel]);
1036 printf("seqmin %x seqoff %d\n", (u_int)aps->aps_seqmin[sel],
1037 aps->aps_seqoff[sel]);
1038#endif
1168 if (ippr_ftp_debug > 1) {
1169 printf("inc %d sel %d rv %d\n", inc, sel, rv);
1170 printf("th_seq %x ftps_seq %x/%x\n",
1171 thseq, f->ftps_seq[0], f->ftps_seq[1]);
1172 printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel],
1173 aps->aps_ackoff[sel]);
1174 printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel],
1175 aps->aps_seqoff[sel]);
1176 }
1039
1040 return APR_ERR(1);
1041 }
1042
1043 inc = 0;
1044 rptr = f->ftps_rptr;
1045 wptr = f->ftps_wptr;
1046 f->ftps_seq[0] = thseq;
1047 f->ftps_seq[1] = f->ftps_seq[0] + mlen;
1048 f->ftps_len = mlen;
1049
1050 while (mlen > 0) {
1177
1178 return APR_ERR(1);
1179 }
1180
1181 inc = 0;
1182 rptr = f->ftps_rptr;
1183 wptr = f->ftps_wptr;
1184 f->ftps_seq[0] = thseq;
1185 f->ftps_seq[1] = f->ftps_seq[0] + mlen;
1186 f->ftps_len = mlen;
1187
1188 while (mlen > 0) {
1051 len = MIN(mlen, FTP_BUFSZ / 2);
1052
1053#if !defined(_KERNEL)
1054 bcopy((char *)m + off, wptr, len);
1055#else
1056# if SOLARIS
1057 copyout_mblk(m, off, len, wptr);
1058# else
1059 m_copydata(m, off, len, wptr);
1060# endif
1061#endif
1189 len = MIN(mlen, sizeof(f->ftps_buf) - (wptr - rptr));
1190 COPYDATA(m, off, len, wptr);
1062 mlen -= len;
1063 off += len;
1064 wptr += len;
1191 mlen -= len;
1192 off += len;
1193 wptr += len;
1194
1195 if (ippr_ftp_debug > 3)
1196 printf("%s:len %d/%d off %d wptr %lx junk %d [%*.*s]\n",
1197 "ippr_ftp_process",
1198 len, mlen, off, (u_long)wptr, f->ftps_junk,
1199 len, len, rptr);
1200
1065 f->ftps_wptr = wptr;
1201 f->ftps_wptr = wptr;
1066 if (f->ftps_junk == 2)
1202 if (f->ftps_junk != 0) {
1203 i = f->ftps_junk;
1067 f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr,
1068 wptr - rptr);
1069
1204 f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr,
1205 wptr - rptr);
1206
1207 if (ippr_ftp_debug > 5)
1208 printf("%s:junk %d -> %d\n",
1209 "ippr_ftp_process", i, f->ftps_junk);
1210
1211 if (f->ftps_junk != 0) {
1212 if (wptr - rptr == sizeof(f->ftps_buf)) {
1213 if (ippr_ftp_debug > 4)
1214 printf("%s:full buffer\n",
1215 "ippr_ftp_process");
1216 f->ftps_rptr = f->ftps_buf;
1217 f->ftps_wptr = f->ftps_buf;
1218 rptr = f->ftps_rptr;
1219 wptr = f->ftps_wptr;
1220 /*
1221 * Because we throw away data here that
1222 * we would otherwise parse, set the
1223 * junk flag to indicate just ignore
1224 * any data upto the next CRLF.
1225 */
1226 f->ftps_junk = 1;
1227 continue;
1228 }
1229 }
1230 }
1231
1070 while ((f->ftps_junk == 0) && (wptr > rptr)) {
1232 while ((f->ftps_junk == 0) && (wptr > rptr)) {
1071 f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr,
1072 wptr - rptr);
1233 len = wptr - rptr;
1234 f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, len);
1235
1236 if (ippr_ftp_debug > 3) {
1237 printf("%s=%d len %d rv %d ptr %lx/%lx ",
1238 "ippr_ftp_valid",
1239 f->ftps_junk, len, rv, (u_long)rptr,
1240 (u_long)wptr);
1241 printf("buf [%*.*s]\n", len, len, rptr);
1242 }
1243
1073 if (f->ftps_junk == 0) {
1244 if (f->ftps_junk == 0) {
1074 f->ftps_cmds++;
1075 len = wptr - rptr;
1076 f->ftps_rptr = rptr;
1077 if (rv)
1078 inc += ippr_ftp_server(fin, ip, nat,
1079 ftp, len);
1080 else
1081 inc += ippr_ftp_client(fin, ip, nat,
1082 ftp, len);
1083 rptr = f->ftps_rptr;
1084 wptr = f->ftps_wptr;
1085 }
1086 }
1087
1088 /*
1089 * Off to a bad start so lets just forget about using the
1090 * ftp proxy for this connection.
1091 */
1092 if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) {
1093 /* f->ftps_seq[1] += inc; */
1245 f->ftps_rptr = rptr;
1246 if (rv)
1247 inc += ippr_ftp_server(fin, ip, nat,
1248 ftp, len);
1249 else
1250 inc += ippr_ftp_client(fin, ip, nat,
1251 ftp, len);
1252 rptr = f->ftps_rptr;
1253 wptr = f->ftps_wptr;
1254 }
1255 }
1256
1257 /*
1258 * Off to a bad start so lets just forget about using the
1259 * ftp proxy for this connection.
1260 */
1261 if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) {
1262 /* f->ftps_seq[1] += inc; */
1094#if !defined(_KERNEL) && !defined(KERNEL)
1095 fprintf(stdout,
1096 "ippr_ftp_process:cmds == 0 junk == 1\n");
1097#endif
1263
1264 if (ippr_ftp_debug > 1)
1265 printf("%s:cmds == 0 junk == 1\n",
1266 "ippr_ftp_process");
1098 return APR_ERR(2);
1099 }
1100
1267 return APR_ERR(2);
1268 }
1269
1101 while ((f->ftps_junk == 1) && (rptr < wptr)) {
1102 while ((rptr < wptr) && (*rptr != '\r'))
1103 rptr++;
1104
1105 if (*rptr == '\r') {
1106 if (rptr + 1 < wptr) {
1107 if (*(rptr + 1) == '\n') {
1108 rptr += 2;
1109 f->ftps_junk = 0;
1110 } else
1111 rptr++;
1112 } else
1270 if ((f->ftps_junk != 0) && (rptr < wptr)) {
1271 for (s = rptr; s < wptr; s++) {
1272 if ((*s == '\r') && (s + 1 < wptr) &&
1273 (*(s + 1) == '\n')) {
1274 rptr = s + 2;
1275 f->ftps_junk = 0;
1113 break;
1276 break;
1277 }
1114 }
1115 }
1278 }
1279 }
1116 f->ftps_rptr = rptr;
1117
1118 if (rptr == wptr) {
1119 rptr = wptr = f->ftps_buf;
1120 } else {
1280
1281 if (rptr == wptr) {
1282 rptr = wptr = f->ftps_buf;
1283 } else {
1121 if ((wptr > f->ftps_buf + FTP_BUFSZ / 2)) {
1122 i = wptr - rptr;
1123 if ((rptr == f->ftps_buf) ||
1124 (wptr - rptr > FTP_BUFSZ / 2)) {
1125 f->ftps_junk = 1;
1126 rptr = wptr = f->ftps_buf;
1127 } else {
1128 bcopy(rptr, f->ftps_buf, i);
1129 wptr = f->ftps_buf + i;
1130 rptr = f->ftps_buf;
1131 }
1284 /*
1285 * Compact the buffer back to the start. The junk
1286 * flag should already be set and because we're not
1287 * throwing away any data, it is preserved from its
1288 * current state.
1289 */
1290 if (rptr > f->ftps_buf) {
1291 bcopy(rptr, f->ftps_buf, len);
1292 wptr -= rptr - f->ftps_buf;
1293 rptr = f->ftps_buf;
1132 }
1294 }
1133 f->ftps_rptr = rptr;
1134 f->ftps_wptr = wptr;
1135 }
1295 }
1296 f->ftps_rptr = rptr;
1297 f->ftps_wptr = wptr;
1136 }
1137
1138 /* f->ftps_seq[1] += inc; */
1139 if (tcp->th_flags & TH_FIN)
1140 f->ftps_seq[1]++;
1298 }
1299
1300 /* f->ftps_seq[1] += inc; */
1301 if (tcp->th_flags & TH_FIN)
1302 f->ftps_seq[1]++;
1141#if PROXY_DEBUG
1142# ifndef _KERNEL
1143 mlen = mbuflen(m);
1144# else
1145# if SOLARIS
1146 mlen = msgdsize(m);
1147# else
1148 mlen = mbufchainlen(m);
1149# endif
1150# endif
1151 mlen -= off;
1152 printf("ftps_seq[1] = %x inc %d len %d\n", f->ftps_seq[1], inc, mlen);
1303 if (ippr_ftp_debug > 3) {
1304#ifdef __sgi
1305 mlen = fin->fin_plen;
1306#else
1307 mlen = MSGDSIZE(m);
1153#endif
1308#endif
1309 mlen -= off;
1310 printf("ftps_seq[1] = %x inc %d len %d\n",
1311 f->ftps_seq[1], inc, mlen);
1312 }
1154
1155 f->ftps_rptr = rptr;
1156 f->ftps_wptr = wptr;
1157 return APR_INC(inc);
1158}
1159
1160
1313
1314 f->ftps_rptr = rptr;
1315 f->ftps_wptr = wptr;
1316 return APR_INC(inc);
1317}
1318
1319
1161int ippr_ftp_out(fin, ip, aps, nat)
1320int ippr_ftp_out(fin, aps, nat)
1162fr_info_t *fin;
1321fr_info_t *fin;
1163ip_t *ip;
1164ap_session_t *aps;
1165nat_t *nat;
1166{
1167 ftpinfo_t *ftp;
1322ap_session_t *aps;
1323nat_t *nat;
1324{
1325 ftpinfo_t *ftp;
1326 int rev;
1168
1169 ftp = aps->aps_data;
1170 if (ftp == NULL)
1171 return 0;
1327
1328 ftp = aps->aps_data;
1329 if (ftp == NULL)
1330 return 0;
1172 return ippr_ftp_process(fin, ip, nat, ftp, 0);
1331
1332 rev = (nat->nat_dir == NAT_OUTBOUND) ? 0 : 1;
1333 if (ftp->ftp_side[1 - rev].ftps_ifp == NULL)
1334 ftp->ftp_side[1 - rev].ftps_ifp = fin->fin_ifp;
1335
1336 return ippr_ftp_process(fin, nat, ftp, rev);
1173}
1174
1175
1337}
1338
1339
1176int ippr_ftp_in(fin, ip, aps, nat)
1340int ippr_ftp_in(fin, aps, nat)
1177fr_info_t *fin;
1341fr_info_t *fin;
1178ip_t *ip;
1179ap_session_t *aps;
1180nat_t *nat;
1181{
1182 ftpinfo_t *ftp;
1342ap_session_t *aps;
1343nat_t *nat;
1344{
1345 ftpinfo_t *ftp;
1346 int rev;
1183
1184 ftp = aps->aps_data;
1185 if (ftp == NULL)
1186 return 0;
1347
1348 ftp = aps->aps_data;
1349 if (ftp == NULL)
1350 return 0;
1187 return ippr_ftp_process(fin, ip, nat, ftp, 1);
1351
1352 rev = (nat->nat_dir == NAT_OUTBOUND) ? 0 : 1;
1353 if (ftp->ftp_side[rev].ftps_ifp == NULL)
1354 ftp->ftp_side[rev].ftps_ifp = fin->fin_ifp;
1355
1356 return ippr_ftp_process(fin, nat, ftp, 1 - rev);
1188}
1189
1190
1191/*
1192 * ippr_ftp_atoi - implement a version of atoi which processes numbers in
1193 * pairs separated by commas (which are expected to be in the range 0 - 255),
1194 * returning a 16 bit number combining either side of the , as the MSB and
1195 * LSB.
1196 */
1197u_short ippr_ftp_atoi(ptr)
1198char **ptr;
1199{
1200 register char *s = *ptr, c;
1201 register u_char i = 0, j = 0;
1202
1357}
1358
1359
1360/*
1361 * ippr_ftp_atoi - implement a version of atoi which processes numbers in
1362 * pairs separated by commas (which are expected to be in the range 0 - 255),
1363 * returning a 16 bit number combining either side of the , as the MSB and
1364 * LSB.
1365 */
1366u_short ippr_ftp_atoi(ptr)
1367char **ptr;
1368{
1369 register char *s = *ptr, c;
1370 register u_char i = 0, j = 0;
1371
1203 while ((c = *s++) && isdigit(c)) {
1372 while (((c = *s++) != '\0') && ISDIGIT(c)) {
1204 i *= 10;
1205 i += c - '0';
1206 }
1207 if (c != ',') {
1208 *ptr = NULL;
1209 return 0;
1210 }
1373 i *= 10;
1374 i += c - '0';
1375 }
1376 if (c != ',') {
1377 *ptr = NULL;
1378 return 0;
1379 }
1211 while ((c = *s++) && isdigit(c)) {
1380 while (((c = *s++) != '\0') && ISDIGIT(c)) {
1212 j *= 10;
1213 j += c - '0';
1214 }
1215 *ptr = s;
1216 i &= 0xff;
1217 j &= 0xff;
1218 return (i << 8) | j;
1219}
1381 j *= 10;
1382 j += c - '0';
1383 }
1384 *ptr = s;
1385 i &= 0xff;
1386 j &= 0xff;
1387 return (i << 8) | j;
1388}
1389
1390
1391int ippr_ftp_epsv(fin, ip, nat, f, dlen)
1392fr_info_t *fin;
1393ip_t *ip;
1394nat_t *nat;
1395ftpside_t *f;
1396int dlen;
1397{
1398 char newbuf[IPF_FTPBUFSZ];
1399 char *s;
1400 u_short ap = 0;
1401
1402#define EPSV_REPLEN 33
1403 /*
1404 * Check for EPSV reply message.
1405 */
1406 if (dlen < IPF_MIN229LEN)
1407 return (0);
1408 else if (strncmp(f->ftps_rptr,
1409 "229 Entering Extended Passive Mode", EPSV_REPLEN))
1410 return (0);
1411
1412 /*
1413 * Skip the EPSV command + space
1414 */
1415 s = f->ftps_rptr + 33;
1416 while (*s && !ISDIGIT(*s))
1417 s++;
1418
1419 /*
1420 * As per RFC 2428, there are no addres components in the EPSV
1421 * response. So we'll go straight to getting the port.
1422 */
1423 while (*s && ISDIGIT(*s)) {
1424 ap *= 10;
1425 ap += *s++ - '0';
1426 }
1427
1428 if (!s)
1429 return 0;
1430
1431 if (*s == '|')
1432 s++;
1433 if (*s == ')')
1434 s++;
1435 if (*s == '\n')
1436 s--;
1437 /*
1438 * check for CR-LF at the end.
1439 */
1440 if ((*s == '\r') && (*(s + 1) == '\n')) {
1441 s += 2;
1442 } else
1443 return 0;
1444
1445#if defined(SNPRINTF) && defined(_KERNEL)
1446 SNPRINTF(newbuf, sizeof(newbuf), "%s (|||%u|)\r\n",
1447 "229 Entering Extended Passive Mode", ap);
1448#else
1449 (void) sprintf(newbuf, "%s (|||%u|)\r\n",
1450 "229 Entering Extended Passive Mode", ap);
1451#endif
1452
1453 return ippr_ftp_pasvreply(fin, ip, nat, f, (u_int)ap, newbuf, s,
1454 ip->ip_src.s_addr);
1455}