alias_ftp.c (124621) | alias_ftp.c (127094) |
---|---|
1/*- 2 * Copyright (c) 2001 Charles Mott <cm@linktel.net> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001 Charles Mott <cm@linktel.net> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_ftp.c 124621 2004-01-17 10:52:21Z phk $"); | 28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_ftp.c 127094 2004-03-16 21:30:41Z des $"); |
29 30/* 31 Alias_ftp.c performs special processing for FTP sessions under 32 TCP. Specifically, when a PORT/EPRT command from the client 33 side or 227/229 reply from the server is sent, it is intercepted 34 and modified. The address is changed to the gateway machine 35 and an aliasing port is used. 36 --- 45 unchanged lines hidden (view full) --- 82 83#define FTP_CONTROL_PORT_NUMBER 21 84#define MAX_MESSAGE_SIZE 128 85 86/* FTP protocol flags. */ 87#define WAIT_CRLF 0x01 88 89enum ftp_message_type { | 29 30/* 31 Alias_ftp.c performs special processing for FTP sessions under 32 TCP. Specifically, when a PORT/EPRT command from the client 33 side or 227/229 reply from the server is sent, it is intercepted 34 and modified. The address is changed to the gateway machine 35 and an aliasing port is used. 36 --- 45 unchanged lines hidden (view full) --- 82 83#define FTP_CONTROL_PORT_NUMBER 21 84#define MAX_MESSAGE_SIZE 128 85 86/* FTP protocol flags. */ 87#define WAIT_CRLF 0x01 88 89enum ftp_message_type { |
90 FTP_PORT_COMMAND, 91 FTP_EPRT_COMMAND, 92 FTP_227_REPLY, 93 FTP_229_REPLY, 94 FTP_UNKNOWN_MESSAGE | 90 FTP_PORT_COMMAND, 91 FTP_EPRT_COMMAND, 92 FTP_227_REPLY, 93 FTP_229_REPLY, 94 FTP_UNKNOWN_MESSAGE |
95}; 96 | 95}; 96 |
97static int ParseFtpPortCommand(struct libalias *la, char *, int); 98static int ParseFtpEprtCommand(struct libalias *la, char *, int); 99static int ParseFtp227Reply(struct libalias *la, char *, int); 100static int ParseFtp229Reply(struct libalias *la, char *, int); 101static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int); | 97static int ParseFtpPortCommand(struct libalias *la, char *, int); 98static int ParseFtpEprtCommand(struct libalias *la, char *, int); 99static int ParseFtp227Reply(struct libalias *la, char *, int); 100static int ParseFtp229Reply(struct libalias *la, char *, int); 101static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int); |
102 103void 104AliasHandleFtpOut( | 102 103void 104AliasHandleFtpOut( |
105struct libalias *la, 106struct ip *pip, /* IP packet to examine/patch */ 107struct alias_link *link, /* The link to go through (aliased port) */ 108int maxpacketsize /* The maximum size this packet can grow to (including headers) */) | 105 struct libalias *la, 106 struct ip *pip, /* IP packet to examine/patch */ 107 struct alias_link *link, /* The link to go through (aliased port) */ 108 int maxpacketsize /* The maximum size this packet can grow to 109 (including headers) */ ) |
109{ | 110{ |
110 int hlen, tlen, dlen, pflags; 111 char *sptr; 112 struct tcphdr *tc; 113 int ftp_message_type; | 111 int hlen, tlen, dlen, pflags; 112 char *sptr; 113 struct tcphdr *tc; 114 int ftp_message_type; |
114 115/* Calculate data length of TCP packet */ | 115 116/* Calculate data length of TCP packet */ |
116 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 117 hlen = (pip->ip_hl + tc->th_off) << 2; 118 tlen = ntohs(pip->ip_len); 119 dlen = tlen - hlen; | 117 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2)); 118 hlen = (pip->ip_hl + tc->th_off) << 2; 119 tlen = ntohs(pip->ip_len); 120 dlen = tlen - hlen; |
120 121/* Place string pointer and beginning of data */ | 121 122/* Place string pointer and beginning of data */ |
122 sptr = (char *) pip; 123 sptr += hlen; | 123 sptr = (char *)pip; 124 sptr += hlen; |
124 125/* 126 * Check that data length is not too long and previous message was 127 * properly terminated with CRLF. 128 */ | 125 126/* 127 * Check that data length is not too long and previous message was 128 * properly terminated with CRLF. 129 */ |
129 pflags = GetProtocolFlags(link); 130 if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) { 131 ftp_message_type = FTP_UNKNOWN_MESSAGE; | 130 pflags = GetProtocolFlags(link); 131 if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) { 132 ftp_message_type = FTP_UNKNOWN_MESSAGE; |
132 | 133 |
133 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) { | 134 if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) { |
134/* 135 * When aliasing a client, check for the PORT/EPRT command. 136 */ | 135/* 136 * When aliasing a client, check for the PORT/EPRT command. 137 */ |
137 if (ParseFtpPortCommand(la, sptr, dlen)) 138 ftp_message_type = FTP_PORT_COMMAND; 139 else if (ParseFtpEprtCommand(la, sptr, dlen)) 140 ftp_message_type = FTP_EPRT_COMMAND; 141 } else { | 138 if (ParseFtpPortCommand(la, sptr, dlen)) 139 ftp_message_type = FTP_PORT_COMMAND; 140 else if (ParseFtpEprtCommand(la, sptr, dlen)) 141 ftp_message_type = FTP_EPRT_COMMAND; 142 } else { |
142/* 143 * When aliasing a server, check for the 227/229 reply. 144 */ | 143/* 144 * When aliasing a server, check for the 227/229 reply. 145 */ |
145 if (ParseFtp227Reply(la, sptr, dlen)) 146 ftp_message_type = FTP_227_REPLY; 147 else if (ParseFtp229Reply(la, sptr, dlen)) { 148 ftp_message_type = FTP_229_REPLY; 149 la->true_addr.s_addr = pip->ip_src.s_addr; 150 } 151 } | 146 if (ParseFtp227Reply(la, sptr, dlen)) 147 ftp_message_type = FTP_227_REPLY; 148 else if (ParseFtp229Reply(la, sptr, dlen)) { 149 ftp_message_type = FTP_229_REPLY; 150 la->true_addr.s_addr = pip->ip_src.s_addr; 151 } 152 } |
152 | 153 |
153 if (ftp_message_type != FTP_UNKNOWN_MESSAGE) 154 NewFtpMessage(la, pip, link, maxpacketsize, ftp_message_type); 155 } 156 | 154 if (ftp_message_type != FTP_UNKNOWN_MESSAGE) 155 NewFtpMessage(la, pip, link, maxpacketsize, ftp_message_type); 156 } |
157/* Track the msgs which are CRLF term'd for PORT/PASV FW breach */ 158 | 157/* Track the msgs which are CRLF term'd for PORT/PASV FW breach */ 158 |
159 if (dlen) { /* only if there's data */ 160 sptr = (char *) pip; /* start over at beginning */ 161 tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may have grown */ 162 if (sptr[tlen-2] == '\r' && sptr[tlen-1] == '\n') 163 pflags &= ~WAIT_CRLF; 164 else 165 pflags |= WAIT_CRLF; 166 SetProtocolFlags(link, pflags); 167 } | 159 if (dlen) { /* only if there's data */ 160 sptr = (char *)pip; /* start over at beginning */ 161 tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may 162 * have grown */ 163 if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n') 164 pflags &= ~WAIT_CRLF; 165 else 166 pflags |= WAIT_CRLF; 167 SetProtocolFlags(link, pflags); 168 } |
168} 169 170static int 171ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen) 172{ | 169} 170 171static int 172ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen) 173{ |
173 char ch; 174 int i, state; 175 u_int32_t addr; 176 u_short port; 177 u_int8_t octet; | 174 char ch; 175 int i, state; 176 u_int32_t addr; 177 u_short port; 178 u_int8_t octet; |
178 | 179 |
179 /* Format: "PORT A,D,D,R,PO,RT". */ | 180 /* Format: "PORT A,D,D,R,PO,RT". */ |
180 | 181 |
181 /* Return if data length is too short. */ 182 if (dlen < 18) 183 return 0; | 182 /* Return if data length is too short. */ 183 if (dlen < 18) 184 return 0; |
184 | 185 |
185 addr = port = octet = 0; 186 state = -4; 187 for (i = 0; i < dlen; i++) { 188 ch = sptr[i]; 189 switch (state) { 190 case -4: if (ch == 'P') state++; else return 0; break; 191 case -3: if (ch == 'O') state++; else return 0; break; 192 case -2: if (ch == 'R') state++; else return 0; break; 193 case -1: if (ch == 'T') state++; else return 0; break; | 186 addr = port = octet = 0; 187 state = -4; 188 for (i = 0; i < dlen; i++) { 189 ch = sptr[i]; 190 switch (state) { 191 case -4: 192 if (ch == 'P') 193 state++; 194 else 195 return 0; 196 break; 197 case -3: 198 if (ch == 'O') 199 state++; 200 else 201 return 0; 202 break; 203 case -2: 204 if (ch == 'R') 205 state++; 206 else 207 return 0; 208 break; 209 case -1: 210 if (ch == 'T') 211 state++; 212 else 213 return 0; 214 break; |
194 | 215 |
195 case 0: 196 if (isspace(ch)) 197 break; 198 else 199 state++; 200 case 1: case 3: case 5: case 7: case 9: case 11: 201 if (isdigit(ch)) { 202 octet = ch - '0'; 203 state++; 204 } else 205 return 0; 206 break; 207 case 2: case 4: case 6: case 8: 208 if (isdigit(ch)) 209 octet = 10 * octet + ch - '0'; 210 else if (ch == ',') { 211 addr = (addr << 8) + octet; 212 state++; 213 } else 214 return 0; 215 break; 216 case 10: case 12: 217 if (isdigit(ch)) 218 octet = 10 * octet + ch - '0'; 219 else if (ch == ',' || state == 12) { 220 port = (port << 8) + octet; 221 state++; 222 } else 223 return 0; 224 break; | 216 case 0: 217 if (isspace(ch)) 218 break; 219 else 220 state++; 221 case 1: 222 case 3: 223 case 5: 224 case 7: 225 case 9: 226 case 11: 227 if (isdigit(ch)) { 228 octet = ch - '0'; 229 state++; 230 } else 231 return 0; 232 break; 233 case 2: 234 case 4: 235 case 6: 236 case 8: 237 if (isdigit(ch)) 238 octet = 10 * octet + ch - '0'; 239 else if (ch == ',') { 240 addr = (addr << 8) + octet; 241 state++; 242 } else 243 return 0; 244 break; 245 case 10: 246 case 12: 247 if (isdigit(ch)) 248 octet = 10 * octet + ch - '0'; 249 else if (ch == ',' || state == 12) { 250 port = (port << 8) + octet; 251 state++; 252 } else 253 return 0; 254 break; 255 } |
225 } | 256 } |
226 } | |
227 | 257 |
228 if (state == 13) { 229 la->true_addr.s_addr = htonl(addr); 230 la->true_port = port; 231 return 1; 232 } else 233 return 0; | 258 if (state == 13) { 259 la->true_addr.s_addr = htonl(addr); 260 la->true_port = port; 261 return 1; 262 } else 263 return 0; |
234} 235 236static int 237ParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen) 238{ | 264} 265 266static int 267ParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen) 268{ |
239 char ch, delim; 240 int i, state; 241 u_int32_t addr; 242 u_short port; 243 u_int8_t octet; | 269 char ch, delim; 270 int i, state; 271 u_int32_t addr; 272 u_short port; 273 u_int8_t octet; |
244 | 274 |
245 /* Format: "EPRT |1|A.D.D.R|PORT|". */ | 275 /* Format: "EPRT |1|A.D.D.R|PORT|". */ |
246 | 276 |
247 /* Return if data length is too short. */ 248 if (dlen < 18) 249 return 0; | 277 /* Return if data length is too short. */ 278 if (dlen < 18) 279 return 0; |
250 | 280 |
251 addr = port = octet = 0; 252 delim = '|'; /* XXX gcc -Wuninitialized */ 253 state = -4; 254 for (i = 0; i < dlen; i++) { 255 ch = sptr[i]; 256 switch (state) 257 { 258 case -4: if (ch == 'E') state++; else return 0; break; 259 case -3: if (ch == 'P') state++; else return 0; break; 260 case -2: if (ch == 'R') state++; else return 0; break; 261 case -1: if (ch == 'T') state++; else return 0; break; | 281 addr = port = octet = 0; 282 delim = '|'; /* XXX gcc -Wuninitialized */ 283 state = -4; 284 for (i = 0; i < dlen; i++) { 285 ch = sptr[i]; 286 switch (state) { 287 case -4: 288 if (ch == 'E') 289 state++; 290 else 291 return 0; 292 break; 293 case -3: 294 if (ch == 'P') 295 state++; 296 else 297 return 0; 298 break; 299 case -2: 300 if (ch == 'R') 301 state++; 302 else 303 return 0; 304 break; 305 case -1: 306 if (ch == 'T') 307 state++; 308 else 309 return 0; 310 break; |
262 | 311 |
263 case 0: 264 if (!isspace(ch)) { 265 delim = ch; 266 state++; 267 } 268 break; 269 case 1: 270 if (ch == '1') /* IPv4 address */ 271 state++; 272 else 273 return 0; 274 break; 275 case 2: 276 if (ch == delim) 277 state++; 278 else 279 return 0; 280 break; 281 case 3: case 5: case 7: case 9: 282 if (isdigit(ch)) { 283 octet = ch - '0'; 284 state++; 285 } else 286 return 0; 287 break; 288 case 4: case 6: case 8: case 10: 289 if (isdigit(ch)) 290 octet = 10 * octet + ch - '0'; 291 else if (ch == '.' || state == 10) { 292 addr = (addr << 8) + octet; 293 state++; 294 } else 295 return 0; 296 break; 297 case 11: 298 if (isdigit(ch)) { 299 port = ch - '0'; 300 state++; 301 } else 302 return 0; 303 break; 304 case 12: 305 if (isdigit(ch)) 306 port = 10 * port + ch - '0'; 307 else if (ch == delim) 308 state++; 309 else 310 return 0; 311 break; | 312 case 0: 313 if (!isspace(ch)) { 314 delim = ch; 315 state++; 316 } 317 break; 318 case 1: 319 if (ch == '1') /* IPv4 address */ 320 state++; 321 else 322 return 0; 323 break; 324 case 2: 325 if (ch == delim) 326 state++; 327 else 328 return 0; 329 break; 330 case 3: 331 case 5: 332 case 7: 333 case 9: 334 if (isdigit(ch)) { 335 octet = ch - '0'; 336 state++; 337 } else 338 return 0; 339 break; 340 case 4: 341 case 6: 342 case 8: 343 case 10: 344 if (isdigit(ch)) 345 octet = 10 * octet + ch - '0'; 346 else if (ch == '.' || state == 10) { 347 addr = (addr << 8) + octet; 348 state++; 349 } else 350 return 0; 351 break; 352 case 11: 353 if (isdigit(ch)) { 354 port = ch - '0'; 355 state++; 356 } else 357 return 0; 358 break; 359 case 12: 360 if (isdigit(ch)) 361 port = 10 * port + ch - '0'; 362 else if (ch == delim) 363 state++; 364 else 365 return 0; 366 break; 367 } |
312 } | 368 } |
313 } | |
314 | 369 |
315 if (state == 13) { 316 la->true_addr.s_addr = htonl(addr); 317 la->true_port = port; 318 return 1; 319 } else 320 return 0; | 370 if (state == 13) { 371 la->true_addr.s_addr = htonl(addr); 372 la->true_port = port; 373 return 1; 374 } else 375 return 0; |
321} 322 323static int 324ParseFtp227Reply(struct libalias *la, char *sptr, int dlen) 325{ | 376} 377 378static int 379ParseFtp227Reply(struct libalias *la, char *sptr, int dlen) 380{ |
326 char ch; 327 int i, state; 328 u_int32_t addr; 329 u_short port; 330 u_int8_t octet; | 381 char ch; 382 int i, state; 383 u_int32_t addr; 384 u_short port; 385 u_int8_t octet; |
331 | 386 |
332 /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */ | 387 /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */ |
333 | 388 |
334 /* Return if data length is too short. */ 335 if (dlen < 17) 336 return 0; | 389 /* Return if data length is too short. */ 390 if (dlen < 17) 391 return 0; |
337 | 392 |
338 addr = port = octet = 0; | 393 addr = port = octet = 0; |
339 | 394 |
340 state = -3; 341 for (i = 0; i < dlen; i++) { 342 ch = sptr[i]; 343 switch (state) 344 { 345 case -3: if (ch == '2') state++; else return 0; break; 346 case -2: if (ch == '2') state++; else return 0; break; 347 case -1: if (ch == '7') state++; else return 0; break; | 395 state = -3; 396 for (i = 0; i < dlen; i++) { 397 ch = sptr[i]; 398 switch (state) { 399 case -3: 400 if (ch == '2') 401 state++; 402 else 403 return 0; 404 break; 405 case -2: 406 if (ch == '2') 407 state++; 408 else 409 return 0; 410 break; 411 case -1: 412 if (ch == '7') 413 state++; 414 else 415 return 0; 416 break; |
348 | 417 |
349 case 0: 350 if (ch == '(') 351 state++; 352 break; 353 case 1: case 3: case 5: case 7: case 9: case 11: 354 if (isdigit(ch)) { 355 octet = ch - '0'; 356 state++; 357 } else 358 return 0; 359 break; 360 case 2: case 4: case 6: case 8: 361 if (isdigit(ch)) 362 octet = 10 * octet + ch - '0'; 363 else if (ch == ',') { 364 addr = (addr << 8) + octet; 365 state++; 366 } else 367 return 0; 368 break; 369 case 10: case 12: 370 if (isdigit(ch)) 371 octet = 10 * octet + ch - '0'; 372 else if (ch == ',' || (state == 12 && ch == ')')) { 373 port = (port << 8) + octet; 374 state++; 375 } else 376 return 0; 377 break; | 418 case 0: 419 if (ch == '(') 420 state++; 421 break; 422 case 1: 423 case 3: 424 case 5: 425 case 7: 426 case 9: 427 case 11: 428 if (isdigit(ch)) { 429 octet = ch - '0'; 430 state++; 431 } else 432 return 0; 433 break; 434 case 2: 435 case 4: 436 case 6: 437 case 8: 438 if (isdigit(ch)) 439 octet = 10 * octet + ch - '0'; 440 else if (ch == ',') { 441 addr = (addr << 8) + octet; 442 state++; 443 } else 444 return 0; 445 break; 446 case 10: 447 case 12: 448 if (isdigit(ch)) 449 octet = 10 * octet + ch - '0'; 450 else if (ch == ',' || (state == 12 && ch == ')')) { 451 port = (port << 8) + octet; 452 state++; 453 } else 454 return 0; 455 break; 456 } |
378 } | 457 } |
379 } | |
380 | 458 |
381 if (state == 13) { 382 la->true_port = port; 383 la->true_addr.s_addr = htonl(addr); 384 return 1; 385 } else 386 return 0; | 459 if (state == 13) { 460 la->true_port = port; 461 la->true_addr.s_addr = htonl(addr); 462 return 1; 463 } else 464 return 0; |
387} 388 389static int 390ParseFtp229Reply(struct libalias *la, char *sptr, int dlen) 391{ | 465} 466 467static int 468ParseFtp229Reply(struct libalias *la, char *sptr, int dlen) 469{ |
392 char ch, delim; 393 int i, state; 394 u_short port; | 470 char ch, delim; 471 int i, state; 472 u_short port; |
395 | 473 |
396 /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */ | 474 /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */ |
397 | 475 |
398 /* Return if data length is too short. */ 399 if (dlen < 11) 400 return 0; | 476 /* Return if data length is too short. */ 477 if (dlen < 11) 478 return 0; |
401 | 479 |
402 port = 0; 403 delim = '|'; /* XXX gcc -Wuninitialized */ | 480 port = 0; 481 delim = '|'; /* XXX gcc -Wuninitialized */ |
404 | 482 |
405 state = -3; 406 for (i = 0; i < dlen; i++) { 407 ch = sptr[i]; 408 switch (state) 409 { 410 case -3: if (ch == '2') state++; else return 0; break; 411 case -2: if (ch == '2') state++; else return 0; break; 412 case -1: if (ch == '9') state++; else return 0; break; | 483 state = -3; 484 for (i = 0; i < dlen; i++) { 485 ch = sptr[i]; 486 switch (state) { 487 case -3: 488 if (ch == '2') 489 state++; 490 else 491 return 0; 492 break; 493 case -2: 494 if (ch == '2') 495 state++; 496 else 497 return 0; 498 break; 499 case -1: 500 if (ch == '9') 501 state++; 502 else 503 return 0; 504 break; |
413 | 505 |
414 case 0: 415 if (ch == '(') 416 state++; 417 break; 418 case 1: 419 delim = ch; 420 state++; 421 break; 422 case 2: case 3: 423 if (ch == delim) 424 state++; 425 else 426 return 0; 427 break; 428 case 4: 429 if (isdigit(ch)) { 430 port = ch - '0'; 431 state++; 432 } else 433 return 0; 434 break; 435 case 5: 436 if (isdigit(ch)) 437 port = 10 * port + ch - '0'; 438 else if (ch == delim) 439 state++; 440 else 441 return 0; 442 break; 443 case 6: 444 if (ch == ')') 445 state++; 446 else 447 return 0; 448 break; | 506 case 0: 507 if (ch == '(') 508 state++; 509 break; 510 case 1: 511 delim = ch; 512 state++; 513 break; 514 case 2: 515 case 3: 516 if (ch == delim) 517 state++; 518 else 519 return 0; 520 break; 521 case 4: 522 if (isdigit(ch)) { 523 port = ch - '0'; 524 state++; 525 } else 526 return 0; 527 break; 528 case 5: 529 if (isdigit(ch)) 530 port = 10 * port + ch - '0'; 531 else if (ch == delim) 532 state++; 533 else 534 return 0; 535 break; 536 case 6: 537 if (ch == ')') 538 state++; 539 else 540 return 0; 541 break; 542 } |
449 } | 543 } |
450 } | |
451 | 544 |
452 if (state == 7) { 453 la->true_port = port; 454 return 1; 455 } else 456 return 0; | 545 if (state == 7) { 546 la->true_port = port; 547 return 1; 548 } else 549 return 0; |
457} 458 459static void 460NewFtpMessage(struct libalias *la, struct ip *pip, | 550} 551 552static void 553NewFtpMessage(struct libalias *la, struct ip *pip, |
461 struct alias_link *link, 462 int maxpacketsize, 463 int ftp_message_type) | 554 struct alias_link *link, 555 int maxpacketsize, 556 int ftp_message_type) |
464{ | 557{ |
465 struct alias_link *ftp_link; | 558 struct alias_link *ftp_link; |
466 467/* Security checks. */ | 559 560/* Security checks. */ |
468 if (pip->ip_src.s_addr != la->true_addr.s_addr) 469 return; | 561 if (pip->ip_src.s_addr != la->true_addr.s_addr) 562 return; |
470 | 563 |
471 if (la->true_port < IPPORT_RESERVED) 472 return; | 564 if (la->true_port < IPPORT_RESERVED) 565 return; |
473 474/* Establish link to address and port found in FTP control message. */ | 566 567/* Establish link to address and port found in FTP control message. */ |
475 ftp_link = FindUdpTcpOut(la, la->true_addr, GetDestAddress(link), 476 htons(la->true_port), 0, IPPROTO_TCP, 1); | 568 ftp_link = FindUdpTcpOut(la, la->true_addr, GetDestAddress(link), 569 htons(la->true_port), 0, IPPROTO_TCP, 1); |
477 | 570 |
478 if (ftp_link != NULL) 479 { 480 int slen, hlen, tlen, dlen; 481 struct tcphdr *tc; | 571 if (ftp_link != NULL) { 572 int slen, hlen, tlen, dlen; 573 struct tcphdr *tc; |
482 483#ifndef NO_FW_PUNCH | 574 575#ifndef NO_FW_PUNCH |
484 /* Punch hole in firewall */ 485 PunchFWHole(ftp_link); | 576 /* Punch hole in firewall */ 577 PunchFWHole(ftp_link); |
486#endif 487 488/* Calculate data length of TCP packet */ | 578#endif 579 580/* Calculate data length of TCP packet */ |
489 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); 490 hlen = (pip->ip_hl + tc->th_off) << 2; 491 tlen = ntohs(pip->ip_len); 492 dlen = tlen - hlen; | 581 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2)); 582 hlen = (pip->ip_hl + tc->th_off) << 2; 583 tlen = ntohs(pip->ip_len); 584 dlen = tlen - hlen; |
493 494/* Create new FTP message. */ | 585 586/* Create new FTP message. */ |
495 { 496 char stemp[MAX_MESSAGE_SIZE + 1]; 497 char *sptr; 498 u_short alias_port; 499 u_char *ptr; 500 int a1, a2, a3, a4, p1, p2; 501 struct in_addr alias_address; | 587 { 588 char stemp[MAX_MESSAGE_SIZE + 1]; 589 char *sptr; 590 u_short alias_port; 591 u_char *ptr; 592 int a1, a2, a3, a4, p1, p2; 593 struct in_addr alias_address; |
502 503/* Decompose alias address into quad format */ | 594 595/* Decompose alias address into quad format */ |
504 alias_address = GetAliasAddress(link); 505 ptr = (u_char *) &alias_address.s_addr; 506 a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr; | 596 alias_address = GetAliasAddress(link); 597 ptr = (u_char *) & alias_address.s_addr; 598 a1 = *ptr++; 599 a2 = *ptr++; 600 a3 = *ptr++; 601 a4 = *ptr; |
507 | 602 |
508 alias_port = GetAliasPort(ftp_link); | 603 alias_port = GetAliasPort(ftp_link); |
509 | 604 |
510 switch (ftp_message_type) 511 { 512 case FTP_PORT_COMMAND: 513 case FTP_227_REPLY: 514 /* Decompose alias port into pair format. */ 515 ptr = (char *) &alias_port; 516 p1 = *ptr++; p2=*ptr; | 605 switch (ftp_message_type) { 606 case FTP_PORT_COMMAND: 607 case FTP_227_REPLY: 608 /* Decompose alias port into pair format. */ 609 ptr = (char *)&alias_port; 610 p1 = *ptr++; 611 p2 = *ptr; |
517 | 612 |
518 if (ftp_message_type == FTP_PORT_COMMAND) { 519 /* Generate PORT command string. */ 520 sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n", 521 a1,a2,a3,a4,p1,p2); 522 } else { 523 /* Generate 227 reply string. */ 524 sprintf(stemp, 525 "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", 526 a1,a2,a3,a4,p1,p2); 527 } 528 break; 529 case FTP_EPRT_COMMAND: 530 /* Generate EPRT command string. */ 531 sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n", 532 a1,a2,a3,a4,ntohs(alias_port)); 533 break; 534 case FTP_229_REPLY: 535 /* Generate 229 reply string. */ 536 sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n", 537 ntohs(alias_port)); 538 break; 539 } | 613 if (ftp_message_type == FTP_PORT_COMMAND) { 614 /* Generate PORT command string. */ 615 sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n", 616 a1, a2, a3, a4, p1, p2); 617 } else { 618 /* Generate 227 reply string. */ 619 sprintf(stemp, 620 "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", 621 a1, a2, a3, a4, p1, p2); 622 } 623 break; 624 case FTP_EPRT_COMMAND: 625 /* Generate EPRT command string. */ 626 sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n", 627 a1, a2, a3, a4, ntohs(alias_port)); 628 break; 629 case FTP_229_REPLY: 630 /* Generate 229 reply string. */ 631 sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n", 632 ntohs(alias_port)); 633 break; 634 } |
540 541/* Save string length for IP header modification */ | 635 636/* Save string length for IP header modification */ |
542 slen = strlen(stemp); | 637 slen = strlen(stemp); |
543 544/* Copy modified buffer into IP packet. */ | 638 639/* Copy modified buffer into IP packet. */ |
545 sptr = (char *) pip; sptr += hlen; 546 strncpy(sptr, stemp, maxpacketsize-hlen); 547 } | 640 sptr = (char *)pip; 641 sptr += hlen; 642 strncpy(sptr, stemp, maxpacketsize - hlen); 643 } |
548 549/* Save information regarding modified seq and ack numbers */ | 644 645/* Save information regarding modified seq and ack numbers */ |
550 { 551 int delta; | 646 { 647 int delta; |
552 | 648 |
553 SetAckModified(link); 554 delta = GetDeltaSeqOut(pip, link); 555 AddSeq(pip, link, delta+slen-dlen); 556 } | 649 SetAckModified(link); 650 delta = GetDeltaSeqOut(pip, link); 651 AddSeq(pip, link, delta + slen - dlen); 652 } |
557 558/* Revise IP header */ | 653 654/* Revise IP header */ |
559 { 560 u_short new_len; | 655 { 656 u_short new_len; |
561 | 657 |
562 new_len = htons(hlen + slen); 563 DifferentialChecksum(&pip->ip_sum, 564 &new_len, 565 &pip->ip_len, 566 1); 567 pip->ip_len = new_len; 568 } | 658 new_len = htons(hlen + slen); 659 DifferentialChecksum(&pip->ip_sum, 660 &new_len, 661 &pip->ip_len, 662 1); 663 pip->ip_len = new_len; 664 } |
569 570/* Compute TCP checksum for revised packet */ | 665 666/* Compute TCP checksum for revised packet */ |
571 tc->th_sum = 0; 572 tc->th_sum = TcpChecksum(pip); 573 } 574 else 575 { | 667 tc->th_sum = 0; 668 tc->th_sum = TcpChecksum(pip); 669 } else { |
576#ifdef DEBUG | 670#ifdef DEBUG |
577 fprintf(stderr, 578 "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n"); | 671 fprintf(stderr, 672 "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n"); |
579#endif | 673#endif |
580 } | 674 } |
581} | 675} |