int ftp_list(struct ftpconnection *connection, char *params, char showthem) { char *buffer = NULL; int response = 0, index = 0; char *outputformat = NULL; if (!ftp_check_ready(connection, 1)) return -1; ftp_sendline(connection, "TYPE A\r\n"); // Go to ASCII mode ftp_getrc(connection, NULL, 0, 0); buffer = config(connection->variables, "passive"); if (!buffer || strcasecmp(buffer, "true") == 0) response = ftp_open_data_pasv(connection, NULL, 0); else response = ftp_open_data(connection); if (response) { log(LOG_ALERT, "ftp_list: bad response from ftp_open_data (%d)\n", response); return -response; // Can't open a data connection } if (params && *params) { buffer = (char *)malloc(MAX_LINE_SIZE); sprintf(buffer, "LIST %s\r\n", params); ftp_sendline(connection, buffer); free(buffer); } else ftp_sendline(connection, "LIST\r\n"); response = ftp_getrc(connection, NULL, 0, 0); switch (response) { case 125 : /* Already a data connection */ break; case 150 : ftp_wait_data(connection); /* Wait for the data connection */ break; case 250 : case 226 : log(LOG_INFO, "No files available\n"); return response; break; case 425 : case 426 : case 451 : case 450 : log(LOG_ALERT, "Could not list directory\n"); return response; break; case 421 : log(LOG_ALERT, "Service unavailable\n"); ftp_disconnect(connection); return response; break; case 500 : log(LOG_ALERT, "Server doesn't understand LIST\n"); return response; break; case 501 : log(LOG_ALERT, "Server doesn't understand LIST parameters\n"); return response; break; case 502 : log(LOG_ALERT, "Server doesn't understand LIST\n"); return response; break; case 530 : log(LOG_ALERT, "Not logged in\n"); return 0; break; default : log(LOG_ALERT, "Unknown response to LIST: %d\n", response); return response; break; } log(LOG_MESSAGE, "ftp_list: processing list\n"); buffer = (char *)malloc(4096); outputformat = config(connection->variables, "lsformat"); while (1) { char *temp; memset(buffer, 0, 4096); if ((response = ftp_read_data_line(connection, buffer, 4096)) == 0) break; /* Read Line */ if (strlen(buffer) == 0) continue; /* Got crap? */ if (ftp_parse_permissions(buffer) < 0) continue; /* Parse -rw-r--r-- etc */ temp = strchr(buffer, '\n'); if (temp) *temp = 0; if (showthem) { if (outputformat && *outputformat) printf("%s\n", listoutput(buffer, outputformat)); else printf("%s\n", buffer); } index++; /* Keep a count of files */ } free(buffer); ftp_close_data(connection); /* Close the data connection */ response = ftp_getrc(connection, NULL, 0, 0); /* Server says ok? */ return index; }
int ftp_open_data_pasv(struct ftpconnection *connection, char *address, int port) { int response; struct sockaddr_in dataaddr; char *buffer = NULL, *line, *temp, *temp2; int length; if (!ftp_check_ready(connection, 1)) return 0; if (!address) { ftp_sendline(connection, "PASV\r\n"); line = (char *)malloc(MAX_LINE_SIZE); if(NULL == line) { return 1; } response = ftp_getrc(connection, line, MAX_LINE_SIZE, 0); switch (response) { case 227 : temp = strstr(line, "("); temp++; temp2 = strstr(temp, ")"); length = temp2-temp; buffer = (char *)malloc(length + 1); if(NULL == buffer) { return 1; } memcpy(buffer, temp, length); buffer[length] = 0; address = (char *)malloc(20); if(NULL == address) { return 1; } port = ftp_parse_pasv(buffer, address); FREE(line); FREE(buffer); break; case 421 : printf("Service unavailable\n"); FREE(line); ftp_disconnect(connection); return 0; break; case 500 : printf("Server doesn't understand PASV\n"); FREE(line); return 0; break; case 501 : printf("Server doesn't understand PASV parameters\n"); FREE(line); return 0; break; case 502 : printf("Server doesn't understand PASV\n"); FREE(line); return 0; break; case 530 : printf("Not logged in\n"); FREE(line); return 0; break; default : printf("Unknown response to PASV: %d\n", response); FREE(line); return 0; break; } } if ((connection->datafd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return 1; } printf("Opening a data connection to %s:%d\n",address, port); memset(&dataaddr, 0, sizeof(dataaddr)); dataaddr.sin_family = AF_INET; dataaddr.sin_port = htons(port); if (inet_aton(address, &dataaddr.sin_addr) <= 0) { perror("inet_aton"); return 1; } if (connect(connection->datafd,(SOCKADDR *)&dataaddr, sizeof(dataaddr)) < 0) { printf("Can't open a data connection to %s\n", address); return 1; } connection->status = STATUS_TRANSFER; FREE(address); return 0; }
int ftp_nlst(struct ftpconnection *connection, char *params, char *list[], int max_items) { char *buffer; int index, response; if (!ftp_check_ready(connection, 0)) return -1; if (max_items > 0) memset(list, 0, sizeof(*list) * max_items); ftp_sendline(connection, "TYPE A\r\n"); ftp_getrc(connection, NULL, 0, 0); buffer = config(connection->variables, "passive"); if (!buffer || strcasecmp(buffer, "true") == 0) response = ftp_open_data_pasv(connection, NULL, 0); else response = ftp_open_data(connection); index = 0; if (params && *params) { buffer = (char *)malloc(MAX_LINE_SIZE); sprintf(buffer, "NLST %s\r\n", params); ftp_sendline(connection, buffer); free(buffer); } else ftp_sendline(connection, "NLST\r\n"); response = ftp_getrc(connection, NULL, 0, 0); switch (response) { case 125 : /* Already a data connection */ break; case 150 : ftp_wait_data(connection); /* Wait for the data connection */ break; case 250 : case 226 : printf("No files available\n"); connection->status = STATUS_IDLE; return response; break; case 425 : case 426 : case 451 : case 450 : log(LOG_ALERT, "Could not list directory\n"); connection->status = STATUS_IDLE; return response; break; case 421 : log(LOG_ALERT, "Service unavailable\n"); ftp_disconnect(connection); return response; break; case 500 : log(LOG_ALERT, "Server doesn't understand NLST\n"); connection->status = STATUS_IDLE; return response; break; case 501 : log(LOG_ALERT, "Server doesn't understand NLST parameters\n"); connection->status = STATUS_IDLE; return response; break; case 502 : log(LOG_ALERT, "Server doesn't understand NLST\n"); connection->status = STATUS_IDLE; return response; break; case 530 : log(LOG_ALERT, "Not logged in\n"); ftp_disconnect(connection); return 0; break; case 550 : /* log(LOG_ALERT, "No files found matching %s\n", params); */ connection->status = STATUS_IDLE; return 0; break; default : log(LOG_ALERT, "Unknown response to NLST: %d\n", response); connection->status = STATUS_IDLE; return response; break; } buffer = (char *)malloc(4096); while ((response = ftp_read_data_line(connection, buffer, 4096) > 0)) { if (strlen(buffer) == 0) continue; if (strcmp(buffer, ".") == 0) continue; if (strcmp(buffer, "..") == 0) continue; if (max_items > 0) list[index] = strdup(buffer); index++; if (max_items > 0) if (index > max_items) break; } if (index >= max_items) index = max_items; /* else for (temp = index; temp < max_items; temp++) list[temp] = 0; */ list[index] = NULL; ftp_getrc(connection, NULL, 0, 0); free(buffer); ftp_close_data(connection); return index; }
int ftp_open_data(struct ftpconnection *connection) { struct sockaddr_in servaddr; struct in_addr sin; char *line; int h1, h2, h3, h4, p1, p2, port; int response; SOCKLEN len; if ((connection->dataconfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = 0; if (bind(connection->dataconfd, (SOCKADDR *)&servaddr, sizeof(servaddr)) < 0) { perror("bind"); return -1; } if (listen(connection->dataconfd, 1) < 0) { perror("listen"); return -1; } len = 128; if (getsockname(connection->dataconfd, (SOCKADDR *)&servaddr, &len) < 0) { perror("getsockname"); return -1; } line = (char *)malloc(MAX_LINE_SIZE); if(NULL == line) { return -1; } port = servaddr.sin_port; sin.s_addr = connection->localip; sprintf(line, "%s.%d\r\n", inet_ntoa(sin), port); sscanf(line, "%d.%d.%d.%d.%d", &h1, &h2, &h3, &h4, &port); p1 = (port / 256); p2 = port - (256 * p1); sprintf(line, "PORT %d,%d,%d,%d,%d,%d\r\n", h1, h2, h3, h4, p2, p1); connection->status = STATUS_WAITING; ftp_sendline(connection, line); FREE(line); response = ftp_getrc(connection, NULL, 0, 0); switch (response) { case 200 : return 0; case 421 : printf("Service unavailable\n"); ftp_disconnect(connection); return response; break; case 500 : printf("Server doesn't understand PORT\n"); return response; break; case 501 : printf("Server doesn't understand PORT parameters\n"); return response; break; case 502 : printf("Server doesn't understand PORT\n"); return response; break; case 530 : printf("Not logged in\n"); return response; break; default : printf("Unknown response to PORT: %d\n", response); return response; break; } }