int get_transfer_fd(session_t *pses) { int iret = 0; //可能是主动模式,或者被动模式 //检测是否收到PORT命令或者PASV命令 if((port_active(pses) < 0) && (pasv_active(pses) < 0)) { ftp_reply(pses->ctrl_fd, FTP_BADSENDCONN, "Use PORT or PASV first."); iret = -1; return iret; } //主动模式 if(port_active(pses) == 0) { //向nobody进程发送命令 priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_GET_DATA_SOCK); unsigned short port = ntohs(pses->port_addr->sin_port); char *ip = inet_ntoa(pses->port_addr->sin_addr); //发送port priv_sock_send_int(pses->child_fd, (int)port); //发送ip priv_sock_send_buf(pses->child_fd, ip, strlen(ip)); //接收应答 char res = priv_sock_get_result(pses->child_fd); if(res == PRIV_SOCK_RESULT_BAD) { iret = -1; } else if(res == PRIV_SOCK_RESULT_OK) { //接收文件描述符 pses->data_fd = priv_sock_recv_fd(pses->child_fd); } } else if(pasv_active(pses) == 0)//被动模式 { //发送命令给nobody进程,完成客户端和服务端的连接 priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_PASV_ACCEPT); //接收nobody进程的应答 char res = priv_sock_get_result(pses->child_fd); if(res == PRIV_SOCK_RESULT_BAD) { iret = -1; } else if(res == PRIV_SOCK_RESULT_OK) { pses->data_fd = priv_sock_recv_fd(pses->child_fd); } } //连接成功后,该内存空间就不需要了 if(pses->port_addr != NULL) { free(pses->port_addr); pses->port_addr = NULL; } return iret; }
static void privop_pasv_active(session_t *sess) { int active; if (sess->pasv_listen_fd != -1) active = 1; else active = 0; priv_sock_send_int(sess->nobody_fd, active); }
/** * 发送字符串,先发送长度 * @param fd [description] * @param buf [description] * @param len 字符串的长度 */ void priv_sock_send_buf(int fd, const char *buf, unsigned int len) { priv_sock_send_int(fd, (int)len); int ret = sysutil::writen(fd, buf, len); if (ret != (int)len) { FTPD_LOG(ERROR,"priv_sock_send_buf error\n"); } }
void priv_sock_send_buf(int fd, const char *buf, unsigned int len) { priv_sock_send_int(fd, (int)len); int ret = writen(fd, buf, len); if (ret != (int)len) { fprintf(stderr, "priv_sock_send_buf error\n"); exit(EXIT_FAILURE); } }
void vsf_two_process_login(struct vsf_session* p_sess, const struct mystr* p_pass_str) { char result; priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_LOGIN); priv_sock_send_str(p_sess->child_fd, &p_sess->user_str); priv_sock_send_str(p_sess->child_fd, p_pass_str); priv_sock_send_int(p_sess->child_fd, p_sess->control_use_ssl); priv_sock_send_int(p_sess->child_fd, p_sess->data_use_ssl); result = priv_sock_get_result(p_sess->child_fd); if (result == PRIV_SOCK_RESULT_OK) { /* Miracle. We don't emit the success message here. That is left to * process_post_login(). * Exit normally, unless we are remaining as the SSL read / write child. */ if (!p_sess->control_use_ssl) { vsf_sysutil_exit(0); } else { vsf_sysutil_clear_alarm(); vsf_sysutil_close(p_sess->child_fd); if (tunable_setproctitle_enable) { vsf_sysutil_setproctitle("SSL handler"); } process_ssl_slave_req(p_sess); } /* NOTREACHED */ } else if (result == PRIV_SOCK_RESULT_BAD) { /* Continue the processing loop.. */ return; } else { die("priv_sock_get_result"); } }
/*发送一个字符串*/ void priv_sock_send_buf(int fd, const char *buf, unsigned int len) { /*先发送字符串的长度*/ priv_sock_send_int(fd, len); /*发送字符串*/ int ret = writen(fd, buf, len); if (ret != (int)len) { fprintf(stderr, "priv_sock_send_buf error"); exit(EXIT_FAILURE); } }
static void privop_pasv_listen(session_t *sess) { sess->pasv_listen_fd = tcp_server(tunable_listen_address, 0); struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if (getsockname(sess->pasv_listen_fd, (struct sockaddr *)&addr, &addrlen) < 0) { priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); ERR_EXIT("getsockname"); } priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_int(sess->parent_fd, (int)addr.sin_port); }
void PrivPar::privop_pasv_active(session_t *sess) { int active; if (sess->pasv_listen_fd != -1) { active = 1; } else { active = 0; } priv_sock_send_int(sess->parent_fd, active); }
static void privop_pasv_listen(session_t *sess) { char ip[20] = {0}; getlocalip(ip); // 服务器 bind 的必须是随机端口,因此此时可能有多个nobody 进程在listen, 这样才不会冲突 sess->pasv_listen_fd = tcp_server(ip, 0); struct sockaddr_in localaddr; socklen_t addrlen = sizeof(localaddr); if (getsockname(sess->pasv_listen_fd, (struct sockaddr *)&localaddr, &addrlen) < 0) ERR_EXIT("getsockname"); unsigned short port = ntohs(localaddr.sin_port); priv_sock_send_int(sess->nobody_fd, (int)port); }
static void privop_pasv_listen(session_t *sess) { char ip[16]; getlocalip(ip); sess->pasv_listen_fd = tcp_server(ip, 0); struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if(getsockname(sess->pasv_listen_fd, (struct sockaddr *)&addr, &addrlen) < 0) { ERR_EXIT("getsockname"); } unsigned short port = ntohs(addr.sin_port); priv_sock_send_int(sess->parent_fd, (int)port); }
int get_port_fd(session_t* sess) { priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_GET_DATA_SOCK); unsigned short port = ntohs(sess->port_addr->sin_port); char* ip = inet_ntoa(sess->port_addr->sin_addr); priv_sock_send_int(sess->child_fd, (int)port); priv_sock_send_buf(sess->child_fd, ip, strlen(ip)); char res = priv_sock_get_result(sess->child_fd); if(res == PRIV_SOCK_RESULT_BAD) return 0; else if(res == PRIV_SOCK_RESULT_OK) sess->data_fd = priv_sock_recv_fd(sess->child_fd); return 1; }
int vsf_two_process_get_priv_data_sock(struct vsf_session* p_sess) { char res; unsigned short port = vsf_sysutil_sockaddr_get_port(p_sess->p_port_sockaddr); priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_GET_DATA_SOCK); priv_sock_send_int(p_sess->child_fd, port); res = priv_sock_get_result(p_sess->child_fd); if (res == PRIV_SOCK_RESULT_BAD) { return -1; } else if (res != PRIV_SOCK_RESULT_OK) { die("could not get privileged socket"); } return priv_sock_recv_fd(p_sess->child_fd); }
static void process_ssl_slave_req(struct vsf_session* p_sess) { while (1) { char cmd = priv_sock_get_cmd(p_sess->ssl_slave_fd); int retval; if (cmd == PRIV_SOCK_GET_USER_CMD) { ftp_getline(p_sess, &p_sess->ftp_cmd_str, p_sess->p_control_line_buf); priv_sock_send_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str); } else if (cmd == PRIV_SOCK_WRITE_USER_RESP) { priv_sock_get_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str); retval = ftp_write_str(p_sess, &p_sess->ftp_cmd_str, kVSFRWControl); priv_sock_send_int(p_sess->ssl_slave_fd, retval); } else { die("bad request in process_ssl_slave_req"); } } }
void priv_sock_send_str(int fd, const char *str, int len) { priv_sock_send_int(fd, len); if (writen(fd, str, len) != len) ERROR_EXIT("writen"); }
void ssl_slave(struct vsf_session* p_sess) { struct mystr data_str = INIT_MYSTR; str_reserve(&data_str, VSFTP_DATA_BUFSIZE); /* Before becoming the slave, clear the alarm for the FTP protocol. */ vsf_sysutil_clear_alarm(); /* No need for any further communications with the privileged parent. */ priv_sock_set_parent_context(p_sess); if (tunable_setproctitle_enable) { vsf_sysutil_setproctitle("SSL handler"); } while (1) { char cmd = priv_sock_get_cmd(p_sess->ssl_slave_fd); int ret; if (cmd == PRIV_SOCK_GET_USER_CMD) { ret = ftp_getline(p_sess, &p_sess->ftp_cmd_str, p_sess->p_control_line_buf); priv_sock_send_int(p_sess->ssl_slave_fd, ret); if (ret >= 0) { priv_sock_send_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str); } } else if (cmd == PRIV_SOCK_WRITE_USER_RESP) { priv_sock_get_str(p_sess->ssl_slave_fd, &p_sess->ftp_cmd_str); ret = ftp_write_str(p_sess, &p_sess->ftp_cmd_str, kVSFRWControl); priv_sock_send_int(p_sess->ssl_slave_fd, ret); } else if (cmd == PRIV_SOCK_DO_SSL_HANDSHAKE) { char result = PRIV_SOCK_RESULT_BAD; if (p_sess->data_fd != -1 || p_sess->p_data_ssl != 0) { bug("state not clean"); } p_sess->data_fd = priv_sock_recv_fd(p_sess->ssl_slave_fd); ret = ssl_accept(p_sess, p_sess->data_fd); if (ret == 1) { result = PRIV_SOCK_RESULT_OK; } else { vsf_sysutil_close(p_sess->data_fd); p_sess->data_fd = -1; } priv_sock_send_result(p_sess->ssl_slave_fd, result); } else if (cmd == PRIV_SOCK_DO_SSL_READ) { str_trunc(&data_str, VSFTP_DATA_BUFSIZE); ret = ssl_read_into_str(p_sess, p_sess->p_data_ssl, &data_str); priv_sock_send_int(p_sess->ssl_slave_fd, ret); priv_sock_send_str(p_sess->ssl_slave_fd, &data_str); } else if (cmd == PRIV_SOCK_DO_SSL_WRITE) { priv_sock_get_str(p_sess->ssl_slave_fd, &data_str); ret = ssl_write(p_sess->p_data_ssl, str_getbuf(&data_str), str_getlen(&data_str)); priv_sock_send_int(p_sess->ssl_slave_fd, ret); } else if (cmd == PRIV_SOCK_DO_SSL_CLOSE) { char result = PRIV_SOCK_RESULT_BAD; if (p_sess->data_fd == -1 && p_sess->p_data_ssl == 0) { result = PRIV_SOCK_RESULT_OK; } else { ret = ssl_data_close(p_sess); if (ret == 1) { result = PRIV_SOCK_RESULT_OK; } vsf_sysutil_close(p_sess->data_fd); p_sess->data_fd = -1; } priv_sock_send_result(p_sess->ssl_slave_fd, result); } else { die("bad request in process_ssl_slave_req"); } } }