static void ftp_pass_info(struct connection *c, struct read_buffer *rb) { int g = get_ftp_response(c, rb, 0); if (g == -1) { setcstate(c, S_FTP_ERROR); abort_connection(c); return; } if (!g) { read_from_socket(c, c->sock1, rb, ftp_pass_info); setcstate(c, S_LOGIN); return; } if (g >= 530 && g < 540) { setcstate(c, S_FTP_LOGIN); abort_connection(c); return; } if (g >= 400) { setcstate(c, S_FTP_UNAVAIL); abort_connection(c); return; } if (ftp_options.fast_ftp) ftp_retr_file(c, rb); else ftp_send_retr_req(c, S_GETH); }
void ftp_got_user_info(struct connection *c, struct read_buffer *rb) { int g = get_ftp_response(c, rb, 0); if (g == -1) { setcstate(c, S_FTP_ERROR); abort_connection(c); return; } if (!g) { read_from_socket(c, c->sock1, rb, ftp_got_user_info); return; } if (g >= 530 && g < 540) { setcstate(c, S_FTP_LOGIN); retry_connection(c); return; } if (g >= 400) { setcstate(c, S_FTP_UNAVAIL); retry_connection(c); return; } if (g >= 200 && g < 300) { if (ftp_options.fast_ftp) ftp_dummy_info(c, rb); else ftp_send_retr_req(c, S_GETH); } else { if (ftp_options.fast_ftp) ftp_pass_info(c, rb); else { unsigned char *login; unsigned char *u; int logl = 0; login = init_str(); add_to_str(&login, &logl, "PASS "); if ((u = get_pass(c->url)) && *u) add_to_str(&login, &logl, u); else add_to_str(&login, &logl, ftp_options.anon_pass); if (u) mem_free(u); add_to_str(&login, &logl, "\r\n"); write_to_socket(c, c->sock1, login, strlen(login), ftp_sent_passwd); mem_free(login); setcstate(c, S_LOGIN); } } }
void ftp_retr_file(struct connection *c, struct read_buffer *rb) { int g; struct ftp_connection_info *inf = c->info; if (0) { rep: if (!ftp_options.fast_ftp) { ftp_send_retr_req(c, S_GETH); return; } } if (inf->pending_commands > 1) { unsigned char pc[6]; if (inf->pasv && inf->opc - (inf->pending_commands - 1) == 2) { int i = 3, j; while (i < rb->len) { if (rb->data[i] >= '0' && rb->data[i] <= '9') { for (j = 0; j < 6; j++) { int n = 0; while (rb->data[i] >= '0' && rb->data[i] <= '9') { n = n * 10 + rb->data[i] - '0'; if (n >= 256) goto no_pasv; if (++i >= rb->len) goto no_pasv; } pc[j] = n; if (j != 5) { if (rb->data[i] != ',') goto xa; if (++i >= rb->len) goto xa; if (rb->data[i] < '0' || rb->data[i] > '9') { xa: if (j != 1) goto no_pasv; pc[4] = pc[0]; pc[5] = pc[1]; { unsigned a; struct sockaddr_in sa; socklen_t nl = sizeof(sa); if (getpeername(c->sock1, (struct sockaddr *)(void *)&sa, &nl)) goto no_pasv; if (nl != sizeof(sa)) goto no_pasv; a = ntohl(sa.sin_addr.s_addr); pc[0] = a >> 24; pc[1] = a >> 16; pc[2] = a >> 8; pc[3] = a; goto pasv_ok; } } } } goto pasv_ok; } i++; }
void ftp_func(struct connection *c) { /*setcstate(c, S_CONN);*/ /*set_timeout(c);*/ if (get_keepalive_socket(c)) { int p; if ((p = get_port(c->url)) == -1) { setcstate(c, S_INTERNAL); abort_connection(c); return; } make_connection(c, p, &c->sock1, ftp_options.fast_ftp ? ftp_login : ftp_get_banner); } else ftp_send_retr_req(c, S_SENT); }
static void ftp_retr_file(struct connection *c, struct read_buffer *rb) { int g; struct ftp_connection_info *inf = c->info; if (0) { rep: if (!ftp_options.fast_ftp) { ftp_send_retr_req(c, S_GETH); return; } } if (inf->pending_commands > 1) { unsigned char pc[6]; if (inf->pasv && inf->opc - (inf->pending_commands - 1) == 2) { int i, j; i = 3; if (!inf->eprt_epsv) while (i < rb->len) { if (rb->data[i] >= '0' && rb->data[i] <= '9') { for (j = 0; j < 6; j++) { int n = 0; while (rb->data[i] >= '0' && rb->data[i] <= '9') { n = n * 10 + rb->data[i] - '0'; if (n >= 256) goto no_pasv; if (++i >= rb->len) goto no_pasv; } pc[j] = n; if (j != 5) { if (rb->data[i] != ',') goto xa; if (++i >= rb->len) goto xa; if (rb->data[i] < '0' || rb->data[i] > '9') { xa: if (j != 1) goto no_pasv; pc[4] = pc[0]; pc[5] = pc[1]; pc[0] = pc[1] = pc[2] = pc[3] = 0; goto pasv_ok; } } } goto pasv_ok; } i++; } no_pasv: i = 3; while (i < rb->len - 5) { if (rb->data[i] == '(' && (rb->data[i + 1] < '0' || rb->data[i + 1] > '9') && rb->data[i + 1] == rb->data[i + 2] && rb->data[i + 2] == rb->data[i + 3]) { unsigned char delim = rb->data[i + 1]; int n = 0; i += 4; while (rb->data[i] >= '0' && rb->data[i] <= '9') { n = n * 10 + rb->data[i] - '0'; if (n >= 65536) goto no_epsv; if (++i >= rb->len) goto no_epsv; } if (rb->data[i] != delim) goto no_epsv; pc[4] = n >> 8; pc[5] = n & 0xff; pc[0] = pc[1] = pc[2] = pc[3] = 0; goto pasv_ok; } i++; }