Deleted Added
full compact
ip_ftp_pxy.c (60857) ip_ftp_pxy.c (63523)
1/*
2 * Simple FTP transparent proxy for in-kernel use. For use with the NAT
3 * code.
1/*
2 * Simple FTP transparent proxy for in-kernel use. For use with the NAT
3 * code.
4 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 60857 2000-05-24 04:40:17Z darrenr $
4 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c 63523 2000-07-19 14:02:09Z darrenr $
5 */
6#if SOLARIS && defined(_KERNEL)
7extern kmutex_t ipf_rw;
8#endif
9
10#define isdigit(x) ((x) >= '0' && (x) <= '9')
5 */
6#if SOLARIS && defined(_KERNEL)
7extern kmutex_t ipf_rw;
8#endif
9
10#define isdigit(x) ((x) >= '0' && (x) <= '9')
11#define isupper(x) ((unsigned)((x) - 'A') <= 'Z' - 'A')
11#define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z'))
12#define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z'))
13#define isalpha(x) (isupper(x) || islower(x))
14#define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A')
12
13#define IPF_FTP_PROXY
14
15#define IPF_MINPORTLEN 18
16#define IPF_MAXPORTLEN 30
17#define IPF_MIN227LEN 39
18#define IPF_MAX227LEN 51
19#define IPF_FTPBUFSZ 96 /* This *MUST* be >= 53! */

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

29int ippr_ftp_port __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int));
30int ippr_ftp_process __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
31int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
32int ippr_ftp_valid __P((char *, size_t));
33u_short ippr_ftp_atoi __P((char **));
34
35static frentry_t natfr;
36int ippr_ftp_pasvonly = 0;
15
16#define IPF_FTP_PROXY
17
18#define IPF_MINPORTLEN 18
19#define IPF_MAXPORTLEN 30
20#define IPF_MIN227LEN 39
21#define IPF_MAX227LEN 51
22#define IPF_FTPBUFSZ 96 /* This *MUST* be >= 53! */

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

32int ippr_ftp_port __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int));
33int ippr_ftp_process __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
34int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int));
35int ippr_ftp_valid __P((char *, size_t));
36u_short ippr_ftp_atoi __P((char **));
37
38static frentry_t natfr;
39int ippr_ftp_pasvonly = 0;
40int ippr_ftp_insecure = 0;
37
38
39/*
40 * Initialize local structures.
41 */
42int ippr_ftp_init()
43{
44 bzero((char *)&natfr, sizeof(natfr));

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

91 int inc, off;
92 nat_t *ipn;
93 mb_t *m;
94#if SOLARIS
95 mb_t *m1;
96#endif
97
98 tcp = (tcphdr_t *)fin->fin_dp;
41
42
43/*
44 * Initialize local structures.
45 */
46int ippr_ftp_init()
47{
48 bzero((char *)&natfr, sizeof(natfr));

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

95 int inc, off;
96 nat_t *ipn;
97 mb_t *m;
98#if SOLARIS
99 mb_t *m1;
100#endif
101
102 tcp = (tcphdr_t *)fin->fin_dp;
99 off = f->ftps_seq - ntohl(tcp->th_seq);
100 if (off < 0)
101 return 0;
102 /*
103 * Check for client sending out PORT message.
104 */
105 if (dlen < IPF_MINPORTLEN)
106 return 0;
103 /*
104 * Check for client sending out PORT message.
105 */
106 if (dlen < IPF_MINPORTLEN)
107 return 0;
108 off = fin->fin_hlen + (tcp->th_off << 2);
107 /*
109 /*
108 * Count the number of bytes in the PORT message is.
109 */
110 if (off < 0)
111 return 0;
112
113 off += fin->fin_hlen + (tcp->th_off << 2);
114 /*
115 * Skip the PORT command + space
116 */
117 s = f->ftps_rptr + 5;
118 /*
119 * Pick out the address components, two at a time.
120 */
121 a1 = ippr_ftp_atoi(&s);
122 if (!s)

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

195 }
196 copyin_mblk(m, off, nlen, newbuf);
197#else
198 m = *((mb_t **)fin->fin_mp);
199 if (inc < 0)
200 m_adj(m, inc);
201 /* the mbuf chain will be extended if necessary by m_copyback() */
202 m_copyback(m, off, nlen, newbuf);
110 * Skip the PORT command + space
111 */
112 s = f->ftps_rptr + 5;
113 /*
114 * Pick out the address components, two at a time.
115 */
116 a1 = ippr_ftp_atoi(&s);
117 if (!s)

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

190 }
191 copyin_mblk(m, off, nlen, newbuf);
192#else
193 m = *((mb_t **)fin->fin_mp);
194 if (inc < 0)
195 m_adj(m, inc);
196 /* the mbuf chain will be extended if necessary by m_copyback() */
197 m_copyback(m, off, nlen, newbuf);
198# ifdef M_PKTHDR
199 if (!(m->m_flags & M_PKTHDR))
200 m->m_pkthdr.len += inc;
201# endif
203#endif
204 if (inc != 0) {
205#if SOLARIS || defined(__sgi)
206 register u_32_t sum1, sum2;
207
208 sum1 = ip->ip_len;
209 sum2 = ip->ip_len + inc;
210

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

269
270int ippr_ftp_client(fin, ip, nat, ftp, dlen)
271fr_info_t *fin;
272nat_t *nat;
273ftpinfo_t *ftp;
274ip_t *ip;
275int dlen;
276{
202#endif
203 if (inc != 0) {
204#if SOLARIS || defined(__sgi)
205 register u_32_t sum1, sum2;
206
207 sum1 = ip->ip_len;
208 sum2 = ip->ip_len + inc;
209

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

268
269int ippr_ftp_client(fin, ip, nat, ftp, dlen)
270fr_info_t *fin;
271nat_t *nat;
272ftpinfo_t *ftp;
273ip_t *ip;
274int dlen;
275{
277 char *rptr, *wptr;
276 char *rptr, *wptr, cmd[6], c;
278 ftpside_t *f;
277 ftpside_t *f;
279 int inc;
278 int inc, i;
280
281 inc = 0;
282 f = &ftp->ftp_side[0];
283 rptr = f->ftps_rptr;
284 wptr = f->ftps_wptr;
285
279
280 inc = 0;
281 f = &ftp->ftp_side[0];
282 rptr = f->ftps_rptr;
283 wptr = f->ftps_wptr;
284
286 if ((ftp->ftp_passok == 0) && !strncmp(rptr, "USER ", 5))
285 for (i = 0; (i < 5) && (i < dlen); i++) {
286 c = rptr[i];
287 if (isalpha(c)) {
288 cmd[i] = toupper(c);
289 } else {
290 cmd[i] = c;
291 }
292 }
293 cmd[i] = '\0';
294
295 if ((ftp->ftp_passok == 0) && !strncmp(cmd, "USER ", 5))
287 ftp->ftp_passok = 1;
296 ftp->ftp_passok = 1;
288 else if ((ftp->ftp_passok == 2) && !strncmp(rptr, "PASS ", 5))
297 else if ((ftp->ftp_passok == 2) && !strncmp(cmd, "PASS ", 5))
289 ftp->ftp_passok = 3;
290 else if ((ftp->ftp_passok == 4) && !ippr_ftp_pasvonly &&
298 ftp->ftp_passok = 3;
299 else if ((ftp->ftp_passok == 4) && !ippr_ftp_pasvonly &&
291 !strncmp(rptr, "PORT ", 5)) {
300 !strncmp(cmd, "PORT ", 5)) {
292 inc = ippr_ftp_port(fin, ip, nat, f, dlen);
301 inc = ippr_ftp_port(fin, ip, nat, f, dlen);
302 } else if (ippr_ftp_insecure && !ippr_ftp_pasvonly &&
303 !strncmp(cmd, "PORT ", 5)) {
304 inc = ippr_ftp_port(fin, ip, nat, f, dlen);
293 }
294
295 while ((*rptr++ != '\n') && (rptr < wptr))
296 ;
305 }
306
307 while ((*rptr++ != '\n') && (rptr < wptr))
308 ;
297 f->ftps_seq += rptr - f->ftps_rptr;
298 f->ftps_rptr = rptr;
299 return inc;
300}
301
302
303int ippr_ftp_pasv(fin, ip, nat, f, dlen)
304fr_info_t *fin;
305ip_t *ip;
306nat_t *nat;
307ftpside_t *f;
308int dlen;
309{
310 tcphdr_t *tcp, tcph, *tcp2 = &tcph;
311 struct in_addr swip, swip2;
312 u_short a5, a6, sp, dp;
313 u_int a1, a2, a3, a4;
314 fr_info_t fi;
309 f->ftps_rptr = rptr;
310 return inc;
311}
312
313
314int ippr_ftp_pasv(fin, ip, nat, f, dlen)
315fr_info_t *fin;
316ip_t *ip;
317nat_t *nat;
318ftpside_t *f;
319int dlen;
320{
321 tcphdr_t *tcp, tcph, *tcp2 = &tcph;
322 struct in_addr swip, swip2;
323 u_short a5, a6, sp, dp;
324 u_int a1, a2, a3, a4;
325 fr_info_t fi;
315 int inc, off;
316 nat_t *ipn;
326 nat_t *ipn;
327 int inc;
317 char *s;
318
319 /*
320 * Check for PASV reply message.
321 */
322 if (dlen < IPF_MIN227LEN)
323 return 0;
324 else if (strncmp(f->ftps_rptr, "227 Entering Passive Mode", 25))
325 return 0;
326
328 char *s;
329
330 /*
331 * Check for PASV reply message.
332 */
333 if (dlen < IPF_MIN227LEN)
334 return 0;
335 else if (strncmp(f->ftps_rptr, "227 Entering Passive Mode", 25))
336 return 0;
337
327 /*
328 * Count the number of bytes in the 227 reply is.
329 */
330 tcp = (tcphdr_t *)fin->fin_dp;
338 tcp = (tcphdr_t *)fin->fin_dp;
331 off = f->ftps_seq - ntohl(tcp->th_seq);
332 if (off < 0)
333 return 0;
334
339
335 off += fin->fin_hlen + (tcp->th_off << 2);
336 /*
337 * Skip the PORT command + space
338 */
339 s = f->ftps_rptr + 25;
340 while (*s && !isdigit(*s))
341 s++;
342 /*
343 * Pick out the address components, two at a time.

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

411 PANIC((m1->b_wptr < m1->b_rptr),
412 ("ippr_ftp_out: cannot handle fragmented data block"));
413
414 linkb(m1, nm);
415 } else {
416 m1->b_wptr += inc;
417 }
418 /*copyin_mblk(m, off, nlen, newbuf);*/
340 /*
341 * Skip the PORT command + space
342 */
343 s = f->ftps_rptr + 25;
344 while (*s && !isdigit(*s))
345 s++;
346 /*
347 * Pick out the address components, two at a time.

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

415 PANIC((m1->b_wptr < m1->b_rptr),
416 ("ippr_ftp_out: cannot handle fragmented data block"));
417
418 linkb(m1, nm);
419 } else {
420 m1->b_wptr += inc;
421 }
422 /*copyin_mblk(m, off, nlen, newbuf);*/
419#else
423#else /* SOLARIS */
420 m = *((mb_t **)fin->fin_mp);
421 if (inc < 0)
422 m_adj(m, inc);
423 /* the mbuf chain will be extended if necessary by m_copyback() */
424 /*m_copyback(m, off, nlen, newbuf);*/
424 m = *((mb_t **)fin->fin_mp);
425 if (inc < 0)
426 m_adj(m, inc);
427 /* the mbuf chain will be extended if necessary by m_copyback() */
428 /*m_copyback(m, off, nlen, newbuf);*/
425#endif
429#endif /* SOLARIS */
426 if (inc != 0) {
427#if SOLARIS || defined(__sgi)
428 register u_32_t sum1, sum2;
429
430 sum1 = ip->ip_len;
431 sum2 = ip->ip_len + inc;
432
433 /* Because ~1 == -2, We really need ~1 == -1 */
434 if (sum1 > sum2)
435 sum2--;
436 sum2 -= sum1;
437 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
438
439 fix_outcksum(&ip->ip_sum, sum2, 0);
430 if (inc != 0) {
431#if SOLARIS || defined(__sgi)
432 register u_32_t sum1, sum2;
433
434 sum1 = ip->ip_len;
435 sum2 = ip->ip_len + inc;
436
437 /* Because ~1 == -2, We really need ~1 == -1 */
438 if (sum1 > sum2)
439 sum2--;
440 sum2 -= sum1;
441 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
442
443 fix_outcksum(&ip->ip_sum, sum2, 0);
440#endif
444#endif /* SOLARIS || defined(__sgi) */
441 ip->ip_len += inc;
442 }
445 ip->ip_len += inc;
446 }
443#endif
447#endif /* 0 */
444
445 /*
446 * Add skeleton NAT entry for connection which will come back the
447 * other way.
448 */
449 sp = 0;
450 dp = htons(fin->fin_data[1] - 1);
451 ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip,

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

501 if ((ftp->ftp_passok == 1) && !strncmp(rptr, "331", 3))
502 ftp->ftp_passok = 2;
503 else if ((ftp->ftp_passok == 3) && !strncmp(rptr, "230", 3))
504 ftp->ftp_passok = 4;
505 else if ((ftp->ftp_passok == 3) && !strncmp(rptr, "530", 3))
506 ftp->ftp_passok = 0;
507 else if ((ftp->ftp_passok == 4) && !strncmp(rptr, "227 ", 4)) {
508 inc = ippr_ftp_pasv(fin, ip, nat, f, dlen);
448
449 /*
450 * Add skeleton NAT entry for connection which will come back the
451 * other way.
452 */
453 sp = 0;
454 dp = htons(fin->fin_data[1] - 1);
455 ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip,

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

505 if ((ftp->ftp_passok == 1) && !strncmp(rptr, "331", 3))
506 ftp->ftp_passok = 2;
507 else if ((ftp->ftp_passok == 3) && !strncmp(rptr, "230", 3))
508 ftp->ftp_passok = 4;
509 else if ((ftp->ftp_passok == 3) && !strncmp(rptr, "530", 3))
510 ftp->ftp_passok = 0;
511 else if ((ftp->ftp_passok == 4) && !strncmp(rptr, "227 ", 4)) {
512 inc = ippr_ftp_pasv(fin, ip, nat, f, dlen);
513 } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) {
514 inc = ippr_ftp_pasv(fin, ip, nat, f, dlen);
509 }
510 while ((*rptr++ != '\n') && (rptr < wptr))
511 ;
515 }
516 while ((*rptr++ != '\n') && (rptr < wptr))
517 ;
512 f->ftps_seq += rptr - f->ftps_rptr;
513 f->ftps_rptr = rptr;
514 return inc;
515}
516
517
518/*
519 * Look to see if the buffer starts with something which we recognise as
520 * being the correct syntax for the FTP protocol.

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

542 c = *s++;
543 i--;
544 if ((c != '-') && (c != ' '))
545 return 1;
546 } else
547 return 1;
548 } else
549 return 1;
518 f->ftps_rptr = rptr;
519 return inc;
520}
521
522
523/*
524 * Look to see if the buffer starts with something which we recognise as
525 * being the correct syntax for the FTP protocol.

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

547 c = *s++;
548 i--;
549 if ((c != '-') && (c != ' '))
550 return 1;
551 } else
552 return 1;
553 } else
554 return 1;
550 } else if (isupper(c)) {
555 } else if (isalpha(c)) {
551 c = *s++;
552 i--;
556 c = *s++;
557 i--;
553 if (isupper(c)) {
558 if (isalpha(c)) {
554 c = *s++;
555 i--;
559 c = *s++;
560 i--;
556 if (isupper(c)) {
561 if (isalpha(c)) {
557 c = *s++;
558 i--;
562 c = *s++;
563 i--;
559 if (isupper(c)) {
564 if (isalpha(c)) {
560 c = *s++;
561 i--;
562 if ((c != ' ') && (c != '\r'))
563 return 1;
564 } else if ((c != ' ') && (c != '\r'))
565 return 1;
566 } else
567 return 1;

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

580
581int ippr_ftp_process(fin, ip, nat, ftp, rv)
582fr_info_t *fin;
583ip_t *ip;
584nat_t *nat;
585ftpinfo_t *ftp;
586int rv;
587{
565 c = *s++;
566 i--;
567 if ((c != ' ') && (c != '\r'))
568 return 1;
569 } else if ((c != ' ') && (c != '\r'))
570 return 1;
571 } else
572 return 1;

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

585
586int ippr_ftp_process(fin, ip, nat, ftp, rv)
587fr_info_t *fin;
588ip_t *ip;
589nat_t *nat;
590ftpinfo_t *ftp;
591int rv;
592{
588 int mlen, len, off, inc, i;
593 int mlen, len, off, inc, i, sel;
589 char *rptr, *wptr;
594 char *rptr, *wptr;
595 ftpside_t *f, *t;
590 tcphdr_t *tcp;
596 tcphdr_t *tcp;
591 ftpside_t *f;
592 mb_t *m;
593
594 tcp = (tcphdr_t *)fin->fin_dp;
595 off = fin->fin_hlen + (tcp->th_off << 2);
596
597#if SOLARIS
598 m = fin->fin_qfm;
599#else
600 m = *((mb_t **)fin->fin_mp);
601#endif
602
603#if SOLARIS
604 mlen = msgdsize(m) - off;
605#else
606 mlen = mbufchainlen(m) - off;
607#endif
597 mb_t *m;
598
599 tcp = (tcphdr_t *)fin->fin_dp;
600 off = fin->fin_hlen + (tcp->th_off << 2);
601
602#if SOLARIS
603 m = fin->fin_qfm;
604#else
605 m = *((mb_t **)fin->fin_mp);
606#endif
607
608#if SOLARIS
609 mlen = msgdsize(m) - off;
610#else
611 mlen = mbufchainlen(m) - off;
612#endif
608 if (!mlen)
613 t = &ftp->ftp_side[1 - rv];
614 if (!mlen) {
615 t->ftps_seq = ntohl(tcp->th_ack);
609 return 0;
616 return 0;
617 }
610
611 inc = 0;
612 f = &ftp->ftp_side[rv];
613 rptr = f->ftps_rptr;
614 wptr = f->ftps_wptr;
618
619 inc = 0;
620 f = &ftp->ftp_side[rv];
621 rptr = f->ftps_rptr;
622 wptr = f->ftps_wptr;
615 if ((wptr == f->ftps_buf) && (f->ftps_seq <= ntohl(tcp->th_seq)))
616 f->ftps_seq = ntohl(tcp->th_seq);
617
623
624 sel = nat->nat_aps->aps_sel[1 - rv];
625 if (rv)
626 i = nat->nat_aps->aps_ackoff[sel];
627 else
628 i = nat->nat_aps->aps_seqoff[sel];
618 /*
619 * XXX - Ideally, this packet should get dropped because we now know
620 * that it is out of order (and there is no real danger in doing so
621 * apart from causing packets to go through here ordered).
622 */
629 /*
630 * XXX - Ideally, this packet should get dropped because we now know
631 * that it is out of order (and there is no real danger in doing so
632 * apart from causing packets to go through here ordered).
633 */
623 if (ntohl(tcp->th_seq) != f->ftps_seq + (wptr - rptr)) {
624 return APR_ERR(0);
634 if (ntohl(tcp->th_seq) + i != f->ftps_seq) {
635 return APR_ERR(-1);
625 }
626
627 while (mlen > 0) {
628 len = MIN(mlen, FTP_BUFSZ / 2);
629
630#if SOLARIS
631 copyout_mblk(m, off, len, wptr);
632#else

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

660
661 if ((*rptr == '\r') && (rptr + 1 < wptr)) {
662 if (*(rptr + 1) == '\n') {
663 rptr += 2;
664 f->ftps_junk = 0;
665 } else
666 rptr++;
667 }
636 }
637
638 while (mlen > 0) {
639 len = MIN(mlen, FTP_BUFSZ / 2);
640
641#if SOLARIS
642 copyout_mblk(m, off, len, wptr);
643#else

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

671
672 if ((*rptr == '\r') && (rptr + 1 < wptr)) {
673 if (*(rptr + 1) == '\n') {
674 rptr += 2;
675 f->ftps_junk = 0;
676 } else
677 rptr++;
678 }
668 f->ftps_seq += rptr - f->ftps_rptr;
669 f->ftps_rptr = rptr;
670 }
671
672 if (rptr == wptr) {
673 rptr = wptr = f->ftps_buf;
674 } else {
675 if ((wptr > f->ftps_buf + FTP_BUFSZ / 2)) {
676 i = wptr - rptr;
677 if ((rptr == f->ftps_buf) ||
678 (wptr - rptr > FTP_BUFSZ / 2)) {
679 f->ftps_rptr = rptr;
680 }
681
682 if (rptr == wptr) {
683 rptr = wptr = f->ftps_buf;
684 } else {
685 if ((wptr > f->ftps_buf + FTP_BUFSZ / 2)) {
686 i = wptr - rptr;
687 if ((rptr == f->ftps_buf) ||
688 (wptr - rptr > FTP_BUFSZ / 2)) {
679 f->ftps_seq += i;
680 f->ftps_junk = 1;
681 rptr = wptr = f->ftps_buf;
682 } else {
683 bcopy(rptr, f->ftps_buf, i);
684 wptr = f->ftps_buf + i;
685 rptr = f->ftps_buf;
686 }
687 }
688 f->ftps_rptr = rptr;
689 f->ftps_wptr = wptr;
690 }
691 }
692
689 f->ftps_junk = 1;
690 rptr = wptr = f->ftps_buf;
691 } else {
692 bcopy(rptr, f->ftps_buf, i);
693 wptr = f->ftps_buf + i;
694 rptr = f->ftps_buf;
695 }
696 }
697 f->ftps_rptr = rptr;
698 f->ftps_wptr = wptr;
699 }
700 }
701
702 t->ftps_seq = ntohl(tcp->th_ack);
693 f->ftps_rptr = rptr;
694 f->ftps_wptr = wptr;
695 return inc;
696}
697
698
699int ippr_ftp_out(fin, ip, aps, nat)
700fr_info_t *fin;

--- 55 unchanged lines hidden ---
703 f->ftps_rptr = rptr;
704 f->ftps_wptr = wptr;
705 return inc;
706}
707
708
709int ippr_ftp_out(fin, ip, aps, nat)
710fr_info_t *fin;

--- 55 unchanged lines hidden ---