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} |
|