Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "mystring.h"
- #include "login.h"
- #include "logging.h"
- #include "dirlist.h"
- #include "options.h"
- #include "main.h"
- #include "targzip.h"
- #include "cwd.h"
- #include "bftpdutmp.h"
- #include "md5.h"
- int state = STATE_CONNECTED;
- char user[USERLEN + 1];
- struct sockaddr_in sa;
- char pasv = 0;
- int sock;
- int pasvsock;
- char *philename = NULL;
- unsigned long offset = 0;
- short int xfertype = TYPE_BINARY;
- int ratio_send = 1, ratio_recv = 1;
- /* long unsigned bytes_sent = 0, bytes_recvd = 0; */
- double bytes_sent = 0.0, bytes_recvd = 0.0;
- int epsvall = 0;
- int xfer_bufsize;
- void control_printf(char success, char *format, ...)
- {
- char buffer[MAX_STRING_LENGTH];
- va_list val;
- va_start(val, format);
- vsnprintf(buffer, sizeof(buffer), format, val);
- va_end(val);
- fprintf(stderr, "%s\r\n", buffer);
- replace(buffer, "\r", "", MAX_STRING_LENGTH);
- bftpd_statuslog(3, success, "%s", buffer);
- }
- void new_umask()
- {
- int um;
- unsigned long get_um;
- char *foo = config_getoption("UMASK");
- if (!foo[0])
- um = 022;
- else
- {
- get_um = strtoul(foo, NULL, 8);
- if (get_um <= INT_MAX)
- um = get_um;
- else
- {
- bftpd_log("Error with umask value. Setting to 022.\n", 0);
- um = 022;
- }
- }
- umask(um);
- }
- void prepare_sock(int sock)
- {
- int on = 1;
- #ifdef TCP_NODELAY
- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on));
- #endif
- #ifdef TCP_NOPUSH
- setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, (void *) &on, sizeof(on));
- #endif
- #ifdef SO_REUSEADDR
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
- #endif
- #ifdef SO_REUSEPORT
- setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *) &on, sizeof(on));
- #endif
- #ifdef SO_SNDBUF
- on = 65536;
- setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *) &on, sizeof(on));
- #endif
- }
- int dataconn()
- {
- struct sockaddr foo;
- struct sockaddr_in local;
- socklen_t namelen = sizeof(foo);
- int curuid = geteuid();
- memset(&foo, 0, sizeof(foo));
- memset(&local, 0, sizeof(local));
- if (pasv) {
- sock = accept(pasvsock, (struct sockaddr *) &foo, (socklen_t *) &namelen);
- if (sock == -1) {
- control_printf(SL_FAILURE, "425-Unable to accept data connection.\r\n425 %s.",
- strerror(errno));
- return 1;
- }
- close(pasvsock);
- prepare_sock(sock);
- } else {
- sock = socket(AF_INET, SOCK_STREAM, 0);
- prepare_sock(sock);
- local.sin_addr.s_addr = name.sin_addr.s_addr;
- local.sin_family = AF_INET;
- if (!strcasecmp(config_getoption("DATAPORT20"), "yes")) {
- seteuid(0);
- local.sin_port = htons(20);
- }
- if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
- control_printf(SL_FAILURE, "425-Unable to bind data socket.\r\n425 %s.",
- strerror(errno));
- return 1;
- }
- if (!strcasecmp(config_getoption("DATAPORT20"), "yes"))
- seteuid(curuid);
- sa.sin_family = AF_INET;
- if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
- control_printf(SL_FAILURE, "425-Unable to establish data connection.\r\n"
- "425 %s.", strerror(errno));
- return 1;
- }
- }
- control_printf(SL_SUCCESS, "150 %s data connection established.",
- xfertype == TYPE_BINARY ? "BINARY" : "ASCII");
- return 0;
- }
- void init_userinfo()
- {
- #ifndef NO_GETPWNAM
- struct passwd *temp = getpwnam(user);
- if (temp) {
- userinfo.pw_name = strdup(temp->pw_name);
- userinfo.pw_passwd = strdup(temp->pw_passwd);
- userinfo.pw_uid = temp->pw_uid;
- userinfo.pw_gid = temp->pw_gid;
- userinfo.pw_gecos = strdup(temp->pw_gecos);
- userinfo.pw_dir = strdup(temp->pw_dir);
- userinfo.pw_shell = strdup(temp->pw_shell);
- userinfo_set = 1;
- }
- #endif
- }
- void command_user(char *username)
- {
- char *alias;
- if (state) {
- control_printf(SL_FAILURE, "503 Username already given.");
- return;
- }
- mystrncpy(user, username, sizeof(user) - 1);
- userinfo_set = 1; /* Dirty! */
- alias = (char *) config_getoption("ALIAS");
- userinfo_set = 0;
- if (alias[0] != '\0')
- mystrncpy(user, alias, sizeof(user) - 1);
- init_userinfo();
- userinfo_set = 1; /* just in case we missed it */
- #ifdef DEBUG
- bftpd_log("Trying to log in as %s.\n", user);
- #endif
- expand_groups();
- if (!strcasecmp(config_getoption("ANONYMOUS_USER"), "yes"))
- {
- state = STATE_USER;
- control_printf(SL_SUCCESS, "331 Password please.");
- /* bftpd_login(""); */
- }
- else {
- state = STATE_USER;
- control_printf(SL_SUCCESS, "331 Password please.");
- }
- }
- void command_pass(char *password)
- {
- if (state > STATE_USER) {
- control_printf(SL_FAILURE, "503 Already logged in.");
- return;
- }
- if (bftpd_login(password)) {
- bftpd_log("Login as user '%s' failed.\n", user);
- control_printf(SL_FAILURE, "530 Login incorrect.");
- // exit(0);
- state = STATE_CONNECTED;
- return;
- }
- }
- void command_pwd(char *params)
- {
- char *my_cwd = NULL;
- my_cwd = bftpd_cwd_getcwd();
- if (my_cwd)
- {
- control_printf(SL_SUCCESS, "257 \"%s\" is the current working directory.", my_cwd);
- free(my_cwd);
- }
- }
- void command_type(char *params)
- {
- if ((*params == 'A') || (*params == 'a')) {
- control_printf(SL_SUCCESS, "200 Transfer type changed to ASCII");
- xfertype = TYPE_ASCII;
- } else if ((*params == 'I') || (*params == 'i')) {
- control_printf(SL_SUCCESS, "200 Transfer type changed to BINARY");
- xfertype = TYPE_BINARY;
- } else
- control_printf(SL_FAILURE, "500 Type '%c' not supported.", *params);
- }
- void command_port(char *params) {
- unsigned long a0, a1, a2, a3, p0, p1, addr;
- if (epsvall) {
- control_printf(SL_FAILURE, "500 EPSV ALL has been called.");
- return;
- }
- sscanf(params, "%lu,%lu,%lu,%lu,%lu,%lu", &a0, &a1, &a2, &a3, &p0, &p1);
- addr = htonl((a0 << 24) + (a1 << 16) + (a2 << 8) + a3);
- if((addr != remotename.sin_addr.s_addr) &&( strncasecmp(config_getoption("ALLOW_FXP"), "yes", 3))) {
- control_printf(SL_FAILURE, "500 The given address is not yours.");
- return;
- }
- sa.sin_addr.s_addr = addr;
- sa.sin_port = htons((p0 << 8) + p1);
- if (pasv) {
- close(sock);
- pasv = 0;
- }
- control_printf(SL_SUCCESS, "200 PORT %lu.%lu.%lu.%lu:%lu OK",
- a0, a1, a2, a3, (p0 << 8) + p1);
- }
- void command_eprt(char *params) {
- char delim;
- int af;
- char addr[51];
- char foo[20];
- int port;
- if (epsvall) {
- control_printf(SL_FAILURE, "500 EPSV ALL has been called.");
- return;
- }
- if (strlen(params) < 5) {
- control_printf(SL_FAILURE, "500 Syntax error.");
- return;
- }
- delim = params[0];
- sprintf(foo, "%c%%i%c%%50[^%c]%c%%i%c", delim, delim, delim, delim, delim);
- if (sscanf(params, foo, &af, addr, &port) < 3) {
- control_printf(SL_FAILURE, "500 Syntax error.");
- return;
- }
- if (af != 1) {
- control_printf(SL_FAILURE, "522 Protocol unsupported, use (1)");
- return;
- }
- sa.sin_addr.s_addr = inet_addr(addr);
- if ((sa.sin_addr.s_addr != remotename.sin_addr.s_addr) && (strncasecmp(config_getoption("ALLOW_FXP"), "yes", 3))) {
- control_printf(SL_FAILURE, "500 The given address is not yours.");
- return;
- }
- sa.sin_port = htons(port);
- if (pasv) {
- close(sock);
- pasv = 0;
- }
- control_printf(SL_FAILURE, "200 EPRT %s:%i OK", addr, port);
- }
- void command_pasv(char *foo)
- {
- int a1, a2, a3, a4;
- socklen_t namelen;
- struct sockaddr_in localsock;
- char *my_override_ip;
- if (epsvall) {
- control_printf(SL_FAILURE, "500 EPSV ALL has been called.");
- return;
- }
- pasvsock = socket(AF_INET, SOCK_STREAM, 0);
- sa.sin_addr.s_addr = INADDR_ANY;
- sa.sin_family = AF_INET;
- if (!config_getoption("PASSIVE_PORTS") || !strlen(config_getoption("PASSIVE_PORTS"))) {
- /* bind to any port */
- sa.sin_port = 0;
- if (bind(pasvsock, (struct sockaddr *) &sa, sizeof(sa)) == -1)
- {
- control_printf(SL_FAILURE, "425-Error: Unable to bind data socket.\r\n425 %s", strerror(errno));
- return;
- }
- }
- else {
- int i = 0, success = 0, port;
- for (;;) {
- port = int_from_list(config_getoption("PASSIVE_PORTS"), i++);
- if (port < 0)
- break;
- sa.sin_port = htons(port);
- if (bind(pasvsock, (struct sockaddr *) &sa, sizeof(sa)) == 0) {
- success = 1;
- #ifdef DEBUG
- bftpd_log("Passive mode: Successfully bound port %d\n", port);
- #endif
- break;
- }
- } /* end of for loop */
- if (!success) {
- control_printf(SL_FAILURE, "425 Error: Unable to bind data socket.");
- return;
- }
- prepare_sock(pasvsock);
- } /* end of else using list of ports */
- if (listen(pasvsock, 1)) {
- control_printf(SL_FAILURE, "425-Error: Unable to make socket listen.\r\n425 %s",
- strerror(errno));
- return;
- }
- namelen = sizeof(localsock);
- getsockname(pasvsock, (struct sockaddr *) &localsock, (socklen_t *) &namelen);
- /* see if we should over-ride the IP address sent to the client */
- my_override_ip = config_getoption("OVERRIDE_IP");
- if (my_override_ip[0])
- {
- sscanf( my_override_ip, "%i.%i.%i.%i",
- &a1, &a2, &a3, &a4);
- }
- else /* noraml, no over-ride */
- {
- sscanf((char *) inet_ntoa(name.sin_addr), "%i.%i.%i.%i",
- &a1, &a2, &a3, &a4);
- }
- control_printf(SL_SUCCESS, "227 Entering Passive Mode (%i,%i,%i,%i,%i,%i)", a1, a2, a3, a4,
- ntohs(localsock.sin_port) >> 8, ntohs(localsock.sin_port) & 0xFF);
- pasv = 1;
- }
- void command_epsv(char *params)
- {
- struct sockaddr_in localsock;
- socklen_t namelen;
- int af;
- if (params[0]) {
- if (!strncasecmp(params, "ALL", 3))
- epsvall = 1;
- else {
- if (sscanf(params, "%i", &af) < 1) {
- control_printf(SL_FAILURE, "500 Syntax error.");
- return;
- } else {
- if (af != 1) {
- control_printf(SL_FAILURE, "522 Protocol unsupported, use (1)");
- return;
- }
- }
- }
- }
- pasvsock = socket(AF_INET, SOCK_STREAM, 0);
- sa.sin_addr.s_addr = INADDR_ANY;
- sa.sin_port = 0;
- sa.sin_family = AF_INET;
- if (bind(pasvsock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
- control_printf(SL_FAILURE, "500-Error: Unable to bind data socket.\r\n425 %s",
- strerror(errno));
- return;
- }
- if (listen(pasvsock, 1)) {
- control_printf(SL_FAILURE, "500-Error: Unable to make socket listen.\r\n425 %s",
- strerror(errno));
- return;
- }
- namelen = sizeof(localsock);
- getsockname(pasvsock, (struct sockaddr *) &localsock, (socklen_t *) &namelen);
- control_printf(SL_SUCCESS, "229 Entering extended passive mode (|||%i|)",
- ntohs(localsock.sin_port));
- pasv = 1;
- }
- char test_abort(char selectbefore, int file, int sock)
- {
- char str[256];
- fd_set rfds;
- struct timeval tv;
- char *result;
- if (selectbefore) {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- FD_ZERO(&rfds);
- FD_SET(fileno(stdin), &rfds);
- if (!select(fileno(stdin) + 1, &rfds, NULL, NULL, &tv))
- return 0;
- }
- result = fgets(str, sizeof(str), stdin);
- if ( (result) && (strstr(str, "ABOR")) ) {
- control_printf(SL_SUCCESS, "426 Transfer aborted.");
- close(file);
- close(sock);
- control_printf(SL_SUCCESS, "226 Aborted.");
- bftpd_log("Client aborted file transmission.\n");
- alarm(control_timeout);
- return 1;
- }
- return 0;
- }
- void command_allo(char *foo)
- {
- command_noop(foo);
- }
- /* This function allows the storage of multiple files on the server. */
- void command_mput(char *filenames)
- {
- char filename[MAXCMD]; /* single filename */
- int from_index, to_index; /* position in "filenames" and "filename" */
- from_index = 0; /* start at begining of filenames */
- memset(filename, 0, MAXCMD); /* clear filename */
- to_index = 0;
- /* go until we find a NULL character */
- while ( filenames[from_index] > 0)
- {
- /* copy filename until we hit a space */
- if (filenames[from_index] == ' ')
- {
- /* got a full filename */
- command_stor(filename);
- /* clear filename and reset to_index */
- to_index = 0;
- memset(filename, 0, MAXCMD);
- while (filenames[from_index] == ' ')
- from_index++; /* goto next position */
- }
- /* if we haven't hit a space, then copy the letter */
- else
- {
- filename[to_index] = filenames[from_index];
- to_index++;
- from_index++;
- /* if the next character is a NULL, then this is the end of the filename */
- if (! filenames[from_index])
- {
- command_stor(filename); /* get the file */
- to_index = 0; /* reset filename index */
- memset(filename, 0, MAXCMD); /* clear filename buffer */
- from_index++; /* goto next character */
- }
- }
- /* if the buffer is getting too big, then stop */
- if (to_index > (MAXCMD - 2) )
- {
- bftpd_log("Error: Filename in '%s' too long.\n", filenames);
- return;
- }
- } /* end of while */
- }
- void do_stor(char *filename, int flags)
- {
- char *buffer;
- int fd, i, max;
- fd_set rfds;
- struct timeval tv;
- char *p, *pp;
- char *mapped = bftpd_cwd_mappath(filename);
- int my_buffer_size; /* total transfer buffer size divided by number of clients */
- int num_clients = 1; /* number of clients connected to the server */
- int new_num_clients = 1;
- int xfer_delay;
- int attempt_gzip = FALSE;
- unsigned long get_value;
- int change_buffer_size = FALSE;
- int stdin_fileno;
- int write_result;
- #ifdef HAVE_ZLIB_H
- gzFile my_zip_file = NULL;
- #endif
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- #ifdef HAVE_ZLIB_H
- if (! strcmp( config_getoption("GZ_UPLOAD"), "yes") )
- {
- attempt_gzip = TRUE;
- strcat(mapped, ".gz");
- }
- else
- attempt_gzip = FALSE;
- #endif
- /* See if we should delay between data transfers */
- get_value = strtoul( config_getoption("XFER_DELAY"), NULL, 0);
- if (get_value <= INT_MAX)
- xfer_delay = get_value;
- else
- {
- bftpd_log("Error getting xfer_delay in do_stor().\n", 0);
- xfer_delay = 0;
- }
- /* Check to see if the file exists and if we can over-write
- it, if it does. -- Jesse */
- fd = open(mapped, O_RDONLY);
- if (fd >= 0) /* file exists */
- {
- /* close the file */
- close(fd);
- /* check if we can over-write it */
- if ( !strcasecmp( config_getoption("ALLOWCOMMAND_DELE"), "no") )
- {
- bftpd_log("Not allowed to over-write '%s'.\n", filename);
- control_printf(SL_FAILURE,
- "553 Error: Remote file is write protected.");
- free(mapped);
- close(sock);
- return;
- }
- }
- if (! attempt_gzip)
- {
- fd = open(mapped, flags, 00666);
- /*
- do this below
- if (mapped)
- free(mapped);
- */
- if (fd == -1) {
- bftpd_log("Error: '%s' while trying to store file '%s'.\n",
- strerror(errno), filename);
- control_printf(SL_FAILURE, "553 Error: %s.", strerror(errno));
- close(fd); /* make sure it is not open */
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- return;
- }
- }
- #ifdef HAVE_ZLIB_H
- if ( attempt_gzip )
- {
- my_zip_file = gzopen(mapped, "wb+");
- if (mapped)
- {
- free(mapped);
- mapped = NULL;
- }
- if (! my_zip_file)
- {
- control_printf(SL_FAILURE, "553 Error: An error occured creating compressed file.");
- close(sock);
- close(fd);
- return;
- }
- }
- #endif
- bftpd_log("Client is storing file '%s'.\n", filename);
- if (dataconn())
- {
- close(fd);
- if (post_write_script)
- run_script(post_write_script, mapped);
- if (mapped)
- free(mapped);
- return;
- }
- /* decide if the transfer buffer size should change. */
- if (! strcasecmp( config_getoption("CHANGE_BUFSIZE"), "yes") )
- change_buffer_size = TRUE;
- /* Figure out how big the transfer buffer should be.
- This will be the total size divided by the number of clients connected.
- -- Jesse
- */
- if (change_buffer_size)
- {
- num_clients = bftpdutmp_usercount("*");
- my_buffer_size = get_buffer_size(num_clients);
- }
- else
- my_buffer_size = xfer_bufsize;
- alarm(0);
- buffer = malloc(xfer_bufsize);
- /* Check to see if we are out of memory. -- Jesse */
- if (! buffer)
- {
- bftpd_log("Unable to create buffer to receive file.\n", 0);
- control_printf(SL_FAILURE, "553 Error: An unknown error occured on the server.");
- if (fd >= 0)
- close(fd);
- close(sock);
- if (mapped)
- free(mapped);
- return;
- }
- lseek(fd, offset, SEEK_SET);
- offset = 0;
- /* Do not use the whole buffer, because a null byte has to be
- * written after the string in ASCII mode. */
- stdin_fileno = fileno(stdin);
- max = (sock > stdin_fileno ? sock : stdin_fileno) + 1;
- for (;;) /* start receiving loop */
- {
- FD_ZERO(&rfds);
- FD_SET(sock, &rfds);
- FD_SET( stdin_fileno, &rfds);
- tv.tv_sec = data_timeout;
- tv.tv_usec = 0;
- if (!select(max, &rfds, NULL, NULL, &tv)) {
- close(sock);
- close(fd);
- control_printf(SL_FAILURE, "426 Kicked due to data transmission timeout.");
- bftpd_log("Kicked due to data transmission timeout.\n");
- /* Before we exit, let's remove our entry in the log file. -- Jesse */
- if (post_write_script)
- run_script(post_write_script, mapped);
- bftpdutmp_end();
- // Update_Send_Recv(user, bytes_sent, bytes_recvd);
- exit(0);
- }
- if (FD_ISSET(stdin_fileno, &rfds)) {
- test_abort(0, fd, sock);
- if (buffer)
- free(buffer);
- close(fd);
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- return;
- }
- if (!((i = recv(sock, buffer, my_buffer_size - 1, 0))))
- break;
- bytes_recvd += i;
- if (xfertype == TYPE_ASCII) {
- buffer[i] = '\0';
- /* on ASCII stransfer, strip character 13 */
- p = pp = buffer;
- while (*p) {
- if ((unsigned char) *p == 13)
- p++;
- else
- *pp++ = *p++;
- }
- *pp++ = 0;
- i = strlen(buffer);
- } // end of if ASCII type transfer
- #ifdef HAVE_ZLIB_H
- if (my_zip_file)
- gzwrite( my_zip_file, buffer, i );
- #endif
- if(! attempt_gzip)
- {
- write_result = write(fd, buffer, i);
- if (write_result == -1)
- break;
- }
- /* Check to see if our bandwidth usage should change. -- Jesse */
- if (change_buffer_size)
- {
- new_num_clients = bftpdutmp_usercount("*");
- if (new_num_clients != num_clients)
- {
- num_clients = new_num_clients;
- my_buffer_size = get_buffer_size(num_clients);
- }
- }
- /* check for transfer delay */
- if ( xfer_delay )
- {
- struct timeval wait_time;
- wait_time.tv_sec = 0;
- wait_time.tv_usec = xfer_delay;
- select( 0, NULL, NULL, NULL, &wait_time);
- }
- } // end of for loop, reading
- free(buffer);
- #ifdef HAVE_ZLIB_H
- gzclose(my_zip_file);
- #else
- close(fd);
- #endif
- close(sock);
- alarm(control_timeout);
- offset = 0;
- control_printf(SL_SUCCESS, "226 File transmission successful.");
- bftpd_log("File transmission successful.\n");
- if (post_write_script)
- run_script(post_write_script, mapped);
- if (mapped)
- free(mapped);
- // Update_Send_Recv(user, bytes_sent, bytes_recvd);
- }
- void command_stor(char *filename)
- {
- do_stor(filename, O_CREAT | O_WRONLY | O_TRUNC);
- }
- void command_appe(char *filename)
- {
- do_stor(filename, O_CREAT | O_WRONLY | O_APPEND);
- }
- /* Send multpile files to the client. */
- void command_mget(char *filenames)
- {
- char filename[MAXCMD]; /* single filename */
- int from_index, to_index; /* position in "filenames" and "filename" */
- from_index = 0; /* start at begining of filenames */
- memset(filename, 0, MAXCMD); /* clear filename */
- to_index = 0;
- /* go until we find a NULL character */
- while ( filenames[from_index] > 0)
- {
- /* copy filename until we hit a space */
- if (filenames[from_index] == ' ')
- {
- /* got a full filename */
- command_retr(filename);
- /* clear filename and reset to_index */
- to_index = 0;
- memset(filename, 0, MAXCMD);
- while (filenames[from_index] == ' ')
- from_index++; /* goto next position */
- }
- /* if we haven't hit a space, then copy the letter */
- else
- {
- filename[to_index] = filenames[from_index];
- to_index++;
- from_index++;
- /* if the next character is a NULL, then this is the end of the filename */
- if (! filenames[from_index])
- {
- command_retr(filename); /* send the file */
- to_index = 0; /* reset filename index */
- memset(filename, 0, MAXCMD); /* clear filename buffer */
- from_index++; /* goto next character */
- }
- }
- /* if the buffer is getting too big, then stop */
- if (to_index > (MAXCMD - 2) )
- {
- bftpd_log("Error: Filename in '%s' too long.\n", filenames);
- return;
- }
- } /* end of while */
- }
- void command_retr(char *filename)
- {
- int num_clients = 1;
- int new_num_clients = 1; /* number of connectiosn to the server */
- int my_buffer_size; /* size of the transfer buffer to use */
- char *mapped = NULL;
- char *buffer;
- int xfer_delay;
- struct timeval wait_time;
- unsigned long get_value;
- ssize_t send_status;
- int change_buffer_size = FALSE;
- #if (defined(WANT_GZIP) || defined(HAVE_ZLIB_H))
- gzFile gzfile;
- #endif
- int phile;
- int i, whattodo = DO_NORMAL;
- struct stat statbuf;
- #if (defined(WANT_TAR) && defined(WANT_GZIP))
- int filedes[2];
- #endif
- #if (defined(WANT_TAR) || defined(WANT_GZIP))
- char *foo;
- #endif
- #ifdef WANT_TAR
- char *argv[4];
- #endif
- get_value = strtoul( config_getoption("XFER_DELAY"), NULL, 0);
- if (get_value <= INT_MAX)
- xfer_delay = get_value;
- else
- {
- bftpd_log("Error getting XFER_DELAY in command_retr().\n", 0);
- xfer_delay = 0;
- }
- mapped = bftpd_cwd_mappath(filename);
- if (! mapped)
- {
- bftpd_log("Memory error in sending file.\n", 0);
- control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 9);
- return;
- }
- if (! strcasecmp( config_getoption("CHANGE_BUFSIZE"), "yes") )
- change_buffer_size = TRUE;
- phile = open(mapped, O_RDONLY);
- if (phile == -1) { // failed to open a file
- #if (defined(WANT_TAR) && defined(WANT_GZIP))
- if ((foo = strstr(filename, ".tar.gz")))
- if (strlen(foo) == 7) {
- whattodo = DO_TARGZ;
- *foo = '\0';
- }
- #endif
- #ifdef WANT_TAR
- if ((foo = strstr(filename, ".tar")))
- if (strlen(foo) == 4) {
- whattodo = DO_TARONLY;
- *foo = '\0';
- }
- #endif
- #ifdef WANT_GZIP
- if ((foo = strstr(filename, ".gz")))
- if (strlen(foo) == 3) {
- whattodo = DO_GZONLY;
- *foo = '\0';
- }
- #endif
- if (whattodo == DO_NORMAL) {
- bftpd_log("Error: '%s' while trying to receive file '%s'.\n",
- strerror(errno), filename);
- control_printf(SL_FAILURE, "553 Error: %s.", strerror(errno));
- if (mapped)
- free(mapped);
- return;
- }
- }
- #ifdef HAVE_ZLIB_H
- else // we did open a file
- {
- char *my_temp;
- char *zip_option;
- my_temp = strstr(filename, ".gz");
- zip_option = config_getoption("GZ_DOWNLOAD");
- if (my_temp)
- {
- if ( ( strlen(my_temp) == 3) && (! strcasecmp(zip_option, "yes") ) )
- whattodo = DO_GZUNZIP;
- }
- }
- #endif
- stat(mapped, (struct stat *) &statbuf);
- if (S_ISDIR(statbuf.st_mode)) {
- control_printf(SL_FAILURE, "550 Error: Is a directory.");
- if (mapped)
- free(mapped);
- return;
- }
- if ((((statbuf.st_size - offset) * ratio_send) / ratio_recv > bytes_recvd
- - bytes_sent) && (strcmp((char *) config_getoption("RATIO"), "none"))) {
- bftpd_log("Error: 'File too big (ratio)' while trying to receive file "
- "'%s'.\n", filename);
- control_printf(SL_FAILURE, "553 File too big. Send at least %lf bytes first.",
- (double) (((statbuf.st_size - offset) * ratio_send) / ratio_recv)
- - bytes_recvd);
- if (mapped)
- free(mapped);
- return;
- }
- bftpd_log("Client is receiving file '%s'.\n", filename);
- switch (whattodo) {
- #if (defined(WANT_TAR) && defined(WANT_GZIP))
- case DO_TARGZ:
- close(phile);
- if (dataconn()) {
- if (mapped)
- free(mapped);
- return;
- }
- alarm(0);
- pipe(filedes);
- if (fork()) {
- buffer = malloc(xfer_bufsize);
- /* check to make sure alloc worked */
- if (! buffer)
- {
- if (mapped)
- free(mapped);
- bftpd_log("Memory error in sending file.\n", 0);
- control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 9);
- return;
- }
- /* find the size of the transfer buffer divided by number of connections */
- if (change_buffer_size)
- {
- num_clients = bftpdutmp_usercount("*");
- my_buffer_size = get_buffer_size(num_clients);
- }
- else
- my_buffer_size = xfer_bufsize;
- close(filedes[1]);
- gzfile = gzdopen(sock, "wb");
- while ((i = read(filedes[0], buffer, my_buffer_size))) {
- gzwrite(gzfile, buffer, i);
- test_abort(1, phile, sock);
- /* check for a change in number of connections */
- if (change_buffer_size)
- {
- new_num_clients = bftpdutmp_usercount("*");
- if (new_num_clients != num_clients)
- {
- num_clients = new_num_clients;
- my_buffer_size = get_buffer_size(num_clients);
- }
- }
- /* pause between transfers */
- if (xfer_delay)
- {
- wait_time.tv_sec = 0;
- wait_time.tv_usec = xfer_delay;
- select( 0, NULL, NULL, NULL, &wait_time);
- }
- } // end of while
- free(buffer);
- gzclose(gzfile);
- wait(NULL); /* Kill the zombie */
- } else {
- stderr = devnull;
- close(filedes[0]);
- close(fileno(stdout));
- dup2(filedes[1], fileno(stdout));
- setvbuf(stdout, NULL, _IONBF, 0);
- argv[0] = "tar";
- argv[1] = "cf";
- argv[2] = "-";
- argv[3] = mapped;
- exit(pax_main(4, argv));
- }
- break;
- #endif
- #ifdef WANT_TAR
- case DO_TARONLY:
- if (dataconn()) {
- if (mapped)
- free(mapped);
- return;
- }
- alarm(0);
- if (fork())
- wait(NULL);
- else {
- stderr = devnull;
- dup2(sock, fileno(stdout));
- argv[0] = "tar";
- argv[1] = "cf";
- argv[2] = "-";
- argv[3] = mapped;
- exit(pax_main(4, argv));
- }
- break;
- #endif
- #ifdef WANT_GZIP
- case DO_GZONLY:
- if (mapped)
- {
- free(mapped);
- mapped = NULL;
- }
- if ((phile = open(mapped, O_RDONLY)) < 0) {
- control_printf(SL_FAILURE, "553 Error: %s.", strerror(errno));
- return;
- }
- if (dataconn()) {
- if (mapped)
- free(mapped);
- return;
- }
- alarm(0);
- buffer = malloc(xfer_bufsize);
- /* check for alloc error */
- if (! buffer)
- {
- bftpd_log("Memory error while sending file.", 0);
- control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 0);
- if (phile) close(phile);
- return;
- }
- /* check buffer size based on number of connections */
- if (change_buffer_size)
- {
- num_clients = bftpdutmp_usercount("*");
- my_buffer_size = get_buffer_size(num_clients);
- }
- else
- my_buffer_size = xfer_bufsize;
- /* Use "wb9" for maximum compression, uses more CPU time... */
- gzfile = gzdopen(sock, "wb");
- while ((i = read(phile, buffer, my_buffer_size))) {
- gzwrite(gzfile, buffer, i);
- test_abort(1, phile, sock);
- if (change_buffer_size)
- {
- new_num_clients = bftpdutmp_usercount("*");
- if ( new_num_clients != num_clients )
- {
- num_clients = new_num_clients;
- my_buffer_size = get_buffer_size(num_clients);
- }
- }
- /* pause between transfers */
- if (xfer_delay)
- {
- wait_time.tv_sec = 0;
- wait_time.tv_usec = xfer_delay;
- select( 0, NULL, NULL, NULL, &wait_time);
- }
- }
- free(buffer);
- close(phile);
- gzclose(gzfile);
- break;
- #endif
- #ifdef HAVE_ZLIB_H
- case DO_GZUNZIP:
- if ( dataconn() )
- return;
- gzfile = gzdopen(phile, "rb");
- if (! gzfile)
- {
- close(phile);
- bftpd_log("Memory error while sending file.", 0);
- control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 0);
- return;
- }
- alarm(0);
- buffer = malloc(xfer_bufsize);
- if (! buffer)
- {
- close(phile);
- gzclose(gzfile);
- bftpd_log("Memory error while sending file.", 0);
- control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 0);
- return;
- }
- /* check buffer size based on number of connections */
- if (change_buffer_size)
- {
- num_clients = bftpdutmp_usercount("*");
- my_buffer_size = get_buffer_size(num_clients);
- }
- else
- my_buffer_size = xfer_bufsize;
- i = gzread(gzfile, buffer, my_buffer_size);
- while ( i )
- {
- write(sock, buffer, i);
- // test_abort(1, phile, sock);
- if (change_buffer_size)
- {
- new_num_clients = bftpdutmp_usercount("*");
- if ( new_num_clients != num_clients )
- {
- num_clients = new_num_clients;
- my_buffer_size = get_buffer_size(num_clients);
- }
- }
- /* pause between transfers */
- if (xfer_delay)
- {
- wait_time.tv_sec = 0;
- wait_time.tv_usec = xfer_delay;
- select( 0, NULL, NULL, NULL, &wait_time);
- }
- i = gzread(gzfile, buffer, my_buffer_size);
- } // end of while not end of file
- free(buffer);
- close(phile);
- gzclose(gzfile);
- break; // send file and unzip on the fly
- #endif
- case DO_NORMAL:
- /* used to be commented out */
- if (mapped)
- {
- free(mapped);
- mapped = NULL;
- }
- if (dataconn())
- return;
- alarm(0);
- lseek(phile, offset, SEEK_SET);
- offset = 0;
- buffer = malloc(xfer_bufsize * 2 + 1);
- /* make sure buffer was created */
- if (! buffer)
- {
- control_printf(SL_FAILURE, "553 An unknown error occured.");
- bftpd_log("Memory error while trying to send file.", 0);
- close(sock);
- close(phile);
- return;
- }
- if (change_buffer_size)
- {
- num_clients = bftpdutmp_usercount("*");
- my_buffer_size = get_buffer_size(num_clients);
- }
- else
- my_buffer_size = xfer_bufsize;
- while ((i = read(phile, buffer, my_buffer_size))) {
- if (test_abort(1, phile, sock)) {
- free(buffer);
- return;
- }
- if (xfertype == TYPE_ASCII) {
- buffer[i] = '\0';
- i += replace(buffer, "\n", "\r\n", xfer_bufsize);
- }
- send_status = send(sock, buffer, i, 0);
- // check for dropped connection
- if (send_status < 0)
- {
- free(buffer);
- close(phile);
- close(sock);
- alarm(control_timeout);
- control_printf(SL_SUCCESS, "426 Transfer aborted.");
- control_printf(SL_SUCCESS, "226 Aborted.");
- bftpd_log("File transmission interrupted. Send failed.\n");
- return;
- }
- bytes_sent += i;
- if (change_buffer_size)
- {
- new_num_clients = bftpdutmp_usercount("*");
- my_buffer_size = get_buffer_size(num_clients);
- }
- /* pause between transfers */
- if (xfer_delay)
- {
- wait_time.tv_sec = 0;
- wait_time.tv_usec = xfer_delay;
- select( 0, NULL, NULL, NULL, &wait_time);
- }
- } // end of while
- free(buffer);
- }
- close(phile);
- close(sock);
- offset = 0;
- alarm(control_timeout);
- control_printf(SL_SUCCESS, "226 File transmission successful.");
- bftpd_log("File transmission of '%s' successful.\n", filename);
- if (mapped) free(mapped);
- // Update_Send_Recv(user, bytes_sent, bytes_recvd);
- }
- void do_dirlist(char *dirname, char verbose)
- {
- int show_hidden = FALSE;
- FILE *datastream;
- if (dirname[0] != '\0') {
- /* check for show hidden files flag */
- if ( (dirname[0] == '-' ) && (dirname[1] == 'a') )
- {
- show_hidden = TRUE;
- while ((dirname[0] != ' ') && (dirname[0] != '\0'))
- dirname++;
- if (dirname[0] != '\0')
- dirname++;
- }
- /* skip other arguments */
- else if (dirname[0] == '-') {
- while ((dirname[0] != ' ') && (dirname[0] != '\0'))
- dirname++;
- if (dirname[0] != '\0')
- dirname++;
- }
- }
- if (dataconn())
- return;
- alarm(0);
- datastream = fdopen(sock, "w");
- if (dirname[0] == '\0')
- dirlist("*", datastream, verbose, show_hidden);
- else {
- char *mapped = bftpd_cwd_mappath(dirname);
- dirlist(mapped, datastream, verbose, show_hidden);
- free(mapped);
- }
- fclose(datastream);
- alarm(control_timeout);
- control_printf(SL_SUCCESS, "226 Directory list has been submitted.");
- }
- void command_list(char *dirname)
- {
- do_dirlist(dirname, 1);
- }
- void command_nlst(char *dirname)
- {
- do_dirlist(dirname, 0);
- }
- void command_syst(char *params)
- {
- control_printf(SL_SUCCESS, "215 UNIX Type: L8");
- }
- void command_mdtm(char *filename)
- {
- struct stat statbuf;
- struct tm *filetime;
- char *fullfilename = bftpd_cwd_mappath(filename);
- if (!stat(fullfilename, (struct stat *) &statbuf)) {
- filetime = gmtime((time_t *) & statbuf.st_mtime);
- control_printf(SL_SUCCESS, "213 %04i%02i%02i%02i%02i%02i",
- filetime->tm_year + 1900, filetime->tm_mon + 1,
- filetime->tm_mday, filetime->tm_hour, filetime->tm_min,
- filetime->tm_sec);
- } else {
- control_printf(SL_FAILURE, "550 Error while determining the modification time: %s",
- strerror(errno));
- }
- free(fullfilename);
- }
- void command_cwd(char *dir)
- {
- if (bftpd_cwd_chdir(dir)) {
- bftpd_log("Error: '%s' while changing directory to '%s'.\n",
- strerror(errno), dir);
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- } else {
- bftpd_log("Changed directory to '%s'.\n", dir);
- control_printf(SL_SUCCESS, "250 OK");
- }
- }
- void command_cdup(char *params)
- {
- bftpd_log("Changed directory to '..'.\n");
- bftpd_cwd_chdir("..");
- control_printf(SL_SUCCESS, "250 OK");
- }
- void command_dele(char *filename)
- {
- struct stat sbuf;
- char *mapped = bftpd_cwd_mappath(filename);
- if (! mapped)
- {
- control_printf(SL_FAILURE, "451 Error: Unable to perform delete..");
- return;
- }
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- /*
- if (unlink(mapped)) {
- bftpd_log("Error: '%s' while trying to delete file '%s'.\n",
- strerror(errno), filename);
- */
- if ( lstat(mapped, &sbuf) == -1 ) {
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- } else {
- /*
- bftpd_log("Deleted file '%s'.\n", filename);
- control_printf(SL_SUCCESS, "200 OK");
- */
- if (S_ISDIR(sbuf.st_mode))
- {
- bftpd_log("Error: '%s' while trying to delete folder '%s' with DELE.\n", strerror(errno), filename);
- control_printf(SL_FAILURE, "550 %s: Is a directory", filename);
- }
- else
- {
- if (unlink(mapped))
- {
- bftpd_log("Error: '%s' while trying to delete file '%s'.\n", strerror(errno), filename);
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- }
- else
- {
- bftpd_log("Deleted file '%s'.\n", filename);
- control_printf(SL_SUCCESS, "200 OK");
- }
- }
- }
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- }
- void command_mkd(char *dirname)
- {
- char *mapped = bftpd_cwd_mappath(dirname);
- if (! mapped)
- {
- control_printf(SL_FAILURE, "451 Error: Unable to create directory.");
- return;
- }
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- if (mkdir(mapped, 0777)) {
- bftpd_log("Error: '%s' while trying to create directory '%s'.\n",
- strerror(errno), dirname);
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- } else {
- bftpd_log("Created directory '%s'.\n", dirname);
- control_printf(SL_SUCCESS, "257 \"%s\" has been created.", dirname);
- }
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- }
- void command_rmd(char *dirname)
- {
- char *mapped = bftpd_cwd_mappath(dirname);
- if (! mapped)
- {
- control_printf(SL_FAILURE, "451 Error: Unable to remove directory.");
- return;
- }
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- if (rmdir(mapped)) {
- /*
- bftpd_log("Error: '%s' while trying to remove directory '%s'.\n", strerror(errno), dirname);
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- */
- if (errno == ENOTEMPTY)
- {
- bftpd_log("Error: '%s' while trying to remove directory '%s': not empty.\n", strerror(errno), dirname);
- control_printf(SL_FAILURE, "550 %s: Directory not empty", dirname);
- }
- else
- {
- bftpd_log("Error: '%s' while trying to remove directory '%s'.\n", strerror(errno), dirname);
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- }
- } else {
- bftpd_log("Removed directory '%s'.\n", dirname);
- control_printf(SL_SUCCESS, "250 OK");
- }
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- }
- void command_noop(char *params)
- {
- control_printf(SL_SUCCESS, "200 OK");
- }
- void command_rnfr(char *oldname)
- {
- FILE *file;
- char *mapped = bftpd_cwd_mappath(oldname);
- if (! mapped)
- {
- control_printf(SL_FAILURE, "451 Error: Unable to locate file.");
- return;
- }
- if ((file = fopen(mapped, "r"))) {
- fclose(file);
- if (philename)
- free(philename);
- philename = mapped;
- state = STATE_RENAME;
- control_printf(SL_SUCCESS, "350 File exists, ready for destination name");
- } else {
- free(mapped);
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- }
- }
- void command_rnto(char *newname)
- {
- char *mapped = bftpd_cwd_mappath(newname);
- if ( (! mapped) || (! philename) )
- {
- control_printf(SL_FAILURE, "451 Error: Unable to rename file.");
- return;
- }
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- if (rename(philename, mapped)) {
- bftpd_log("Error: '%s' while trying to rename '%s' to '%s'.\n",
- strerror(errno), philename, mapped);
- // strerror(errno), philename, bftpd_cwd_mappath(newname));
- control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
- } else {
- bftpd_log("Successfully renamed '%s' to '%s'.\n", // philename, bftpd_cwd_mappath(newname));
- philename, mapped);
- control_printf(SL_SUCCESS, "250 OK");
- state = STATE_AUTHENTICATED;
- }
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(philename);
- free(mapped);
- philename = NULL;
- }
- void command_rest(char *params)
- {
- offset = strtoul(params, NULL, 10);
- control_printf(SL_SUCCESS, "350 Restarting at offset %i.", offset);
- }
- void command_size(char *filename)
- {
- struct stat statbuf;
- char *mapped = bftpd_cwd_mappath(filename);
- if (! mapped)
- {
- control_printf(SL_FAILURE, "451 Error: Unable to locate file.");
- return;
- }
- if (!stat(mapped, &statbuf)) {
- control_printf(SL_SUCCESS, "213 %i", (int) statbuf.st_size);
- } else {
- control_printf(SL_FAILURE, "550 Error: %s.", strerror(errno));
- }
- free(mapped);
- }
- void command_quit(char *params)
- {
- control_printf(SL_SUCCESS, "221 %s", config_getoption("QUIT_MSG"));
- /* Make sure we log user out. -- Jesse <slicer69@hotmail.com> */
- bftpdutmp_end();
- // Update_Send_Recv(user, bytes_sent, bytes_recvd);
- exit(0);
- }
- void command_stat(char *filename)
- {
- char *mapped = bftpd_cwd_mappath(filename);
- if (! mapped)
- {
- control_printf(SL_FAILURE, "451 Error: Unable to discover status.");
- return;
- }
- control_printf(SL_SUCCESS, "213-Status of %s:", filename);
- bftpd_stat(mapped, stderr);
- control_printf(SL_SUCCESS, "213 End of Status.");
- free(mapped);
- }
- /* SITE commands */
- void command_chmod(char *params)
- {
- int permissions;
- char *mapped;
- char *my_string;
- if (!strchr(params, ' ')) {
- control_printf(SL_FAILURE, "550 Usage: SITE CHMOD <permissions> <filename>");
- return;
- }
- my_string = strdup(strchr(params, ' ') + 1);
- if (! my_string)
- {
- control_printf(SL_FAILURE, "550: An error occured on the server trying to CHMOD.");
- return;
- }
- /* mapped = bftpd_cwd_mappath(strdup(strchr(params, ' ') + 1)); */
- mapped = bftpd_cwd_mappath(my_string);
- free(my_string);
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- *strchr(params, ' ') = '\0';
- sscanf(params, "%o", &permissions);
- if (chmod(mapped, permissions))
- control_printf(SL_FAILURE, "Error: %s.", strerror(errno));
- else {
- bftpd_log("Changed permissions of '%s' to '%o'.\n", mapped,
- permissions);
- control_printf(SL_SUCCESS, "200 CHMOD successful.");
- }
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- }
- void command_chown(char *params)
- {
- char foo[MAXCMD + 1], owner[MAXCMD + 1], group[MAXCMD + 1],
- filename[MAXCMD + 1], *mapped;
- int uid, gid;
- if (!strchr(params, ' ')) {
- control_printf(SL_FAILURE, "550 Usage: SITE CHOWN <owner>[.<group>] <filename>");
- return;
- }
- sscanf(params, "%[^ ] %s", foo, filename);
- if (strchr(foo, '.'))
- sscanf(foo, "%[^.].%s", owner, group);
- else {
- strcpy(owner, foo);
- group[0] = '\0';
- }
- if (!sscanf(owner, "%i", &uid)) /* Is it a number? */
- if (((uid = mygetpwnam(owner, passwdfile))) < 0) {
- control_printf(SL_FAILURE, "550 User '%s' not found.", owner);
- return;
- }
- if (!sscanf(group, "%i", &gid))
- if (((gid = mygetpwnam(group, groupfile))) < 0) {
- control_printf(SL_FAILURE, "550 Group '%s' not found.", group);
- return;
- }
- mapped = bftpd_cwd_mappath(filename);
- if (pre_write_script)
- run_script(pre_write_script, mapped);
- if (chown(mapped, uid, gid))
- control_printf(SL_FAILURE, "550 Error: %s.", strerror(errno));
- else {
- bftpd_log("Changed owner of '%s' to UID %i GID %i.\n", filename, uid,
- gid);
- control_printf(SL_SUCCESS, "200 CHOWN successful.");
- }
- if (post_write_script)
- run_script(post_write_script, mapped);
- free(mapped);
- }
- /*
- Send the md5sum check of a given file to the
- client.
- */
- void command_md5(char *philename)
- {
- FILE *myphile;
- md5_t my_md5;
- char buffer[1024];
- int bytes_read = 0;
- char md5_result[16];
- char output_string[64];
- if (! philename)
- {
- control_printf(SL_FAILURE, "550 File not found.");
- return;
- }
- philename++;
- myphile = fopen(philename, "r");
- if (! myphile)
- {
- control_printf(SL_FAILURE, "550 Unable to open file `%s'.", philename);
- return;
- }
- md5_init(&my_md5);
- bytes_read = fread(buffer, sizeof(char), 1024, myphile);
- while (bytes_read > 0)
- {
- md5_process(&my_md5, buffer, bytes_read);
- bytes_read = fread(buffer, sizeof(char), 1024, myphile);
- }
- md5_finish(&my_md5, md5_result);
- md5_sig_to_string(md5_result, output_string, sizeof(output_string) );
- control_printf(SL_SUCCESS, "200 MD5 finger print: %s.", output_string);
- fclose(myphile);
- }
- void command_site(char *str)
- {
- const struct command subcmds[] = {
- {"chmod ", NULL, command_chmod, STATE_AUTHENTICATED},
- {"chown ", NULL, command_chown, STATE_AUTHENTICATED},
- {"md5", NULL, command_md5, STATE_AUTHENTICATED},
- {NULL, NULL, 0}
- };
- int i;
- if (!strcasecmp(config_getoption("ENABLE_SITE"), "no")) {
- control_printf(SL_FAILURE, "550 SITE commands are disabled.");
- return;
- }
- for (i = 0; subcmds[i].name; i++) {
- if (!strncasecmp(str, subcmds[i].name, strlen(subcmds[i].name))) {
- cutto(str, strlen(subcmds[i].name));
- subcmds[i].function(str);
- return;
- }
- }
- /* see if the user needs help */
- if (! strcasecmp(str, "help") )
- {
- control_printf(SL_SUCCESS, "211-Possible usages for SITE command:");
- control_printf(SL_SUCCESS, "211-site chmod <mask> <filename>");
- control_printf(SL_SUCCESS, "211-site chown <owner> <filename>");
- control_printf(SL_SUCCESS, "211 site md5 <filename>");
- return;
- }
- control_printf(SL_FAILURE, "550 Unknown command: 'SITE %s'.", str);
- }
- void command_auth(char *type)
- {
- control_printf(SL_FAILURE, "550 Not implemented yet\r\n");
- }
- /* Command parsing */
- const struct command commands[] = {
- {"USER", "<sp> username", command_user, STATE_CONNECTED, 0},
- {"PASS", "<sp> password", command_pass, STATE_USER, 0},
- {"XPWD", "(returns cwd)", command_pwd, STATE_AUTHENTICATED, 1},
- {"PWD", "(returns cwd)", command_pwd, STATE_AUTHENTICATED, 0},
- {"TYPE", "<sp> type-code (A or I)", command_type, STATE_AUTHENTICATED, 0},
- {"PORT", "<sp> h1,h2,h3,h4,p1,p2", command_port, STATE_AUTHENTICATED, 0},
- {"EPRT", "<sp><d><net-prt><d><ip><d><tcp-prt><d>", command_eprt, STATE_AUTHENTICATED, 1},
- {"PASV", "(returns address/port)", command_pasv, STATE_AUTHENTICATED, 0},
- {"EPSV", "(returns address/post)", command_epsv, STATE_AUTHENTICATED, 1},
- {"ALLO", "<sp> size", command_allo, STATE_AUTHENTICATED, 1},
- {"STOR", "<sp> pathname", command_stor, STATE_AUTHENTICATED, 0},
- {"APPE", "<sp> pathname", command_appe, STATE_AUTHENTICATED, 1},
- {"RETR", "<sp> pathname", command_retr, STATE_AUTHENTICATED, 0},
- {"LIST", "[<sp> pathname]", command_list, STATE_AUTHENTICATED, 0},
- {"NLST", "[<sp> pathname]", command_nlst, STATE_AUTHENTICATED, 0},
- {"SYST", "(returns system type)", command_syst, STATE_CONNECTED, 0},
- {"MDTM", "<sp> pathname", command_mdtm, STATE_AUTHENTICATED, 1},
- {"XCWD", "<sp> pathname", command_cwd, STATE_AUTHENTICATED, 1},
- {"CWD", "<sp> pathname", command_cwd, STATE_AUTHENTICATED, 0},
- {"XCUP", "(up one directory)", command_cdup, STATE_AUTHENTICATED, 1},
- {"CDUP", "(up one directory)", command_cdup, STATE_AUTHENTICATED, 0},
- {"DELE", "<sp> pathname", command_dele, STATE_AUTHENTICATED, 0},
- {"XMKD", "<sp> pathname", command_mkd, STATE_AUTHENTICATED, 1},
- {"MKD", "<sp> pathname", command_mkd, STATE_AUTHENTICATED, 0},
- {"XRMD", "<sp> pathname", command_rmd, STATE_AUTHENTICATED, 1},
- {"RMD", "<sp> pathname", command_rmd, STATE_AUTHENTICATED, 0},
- {"NOOP", "(no operation)", command_noop, STATE_AUTHENTICATED, 0},
- {"OPTS", "<sp> string <sp> val", command_opts, STATE_AUTHENTICATED, 0},
- {"RNFR", "<sp> pathname", command_rnfr, STATE_AUTHENTICATED, 0},
- {"RNTO", "<sp> pathname", command_rnto, STATE_RENAME, 0},
- {"REST", "<sp> byte-count", command_rest, STATE_AUTHENTICATED, 1},
- {"SIZE", "<sp> pathname", command_size, STATE_AUTHENTICATED, 1},
- {"QUIT", "(close control connection)", command_quit, STATE_CONNECTED, 0},
- {"HELP", "[<sp> command]", command_help, STATE_AUTHENTICATED, 0},
- {"STAT", "<sp> pathname", command_stat, STATE_AUTHENTICATED, 0},
- {"SITE", "<sp> string", command_site, STATE_AUTHENTICATED, 0},
- {"FEAT", "(returns list of extensions)", command_feat, STATE_AUTHENTICATED, 1},
- /* {"AUTH", "<sp> authtype", command_auth, STATE_CONNECTED, 0},
- {"ADMIN_LOGIN", "(admin)", command_adminlogin, STATE_CONNECTED, 0},*/
- {"MGET", "<sp> pathname", command_mget, STATE_AUTHENTICATED, 0},
- {"MPUT", "<sp> pathname", command_mput, STATE_AUTHENTICATED, 0},
- {NULL, NULL, NULL, 0, 0}
- };
- void command_feat(char *params)
- {
- int i;
- control_printf(SL_SUCCESS, "211-Extensions supported:");
- for (i = 0; commands[i].name; i++)
- if (commands[i].showinfeat)
- control_printf(SL_SUCCESS, " %s", commands[i].name);
- control_printf(SL_SUCCESS, " UTF8");
- control_printf(SL_SUCCESS, "211 End");
- }
- void command_opts(char *params)
- {
- if (! strcasecmp(params, "utf8 on") )
- control_printf(SL_SUCCESS, "200 UTF8 ON");
- else
- control_printf(SL_SUCCESS, "550 %s not implemented", params);
- }
- void command_help(char *params)
- {
- int i;
- if (params[0] == '\0') {
- control_printf(SL_SUCCESS, "214-The following commands are recognized.");
- for (i = 0; commands[i].name; i++)
- control_printf(SL_SUCCESS, "214-%s", commands[i].name);
- control_printf(SL_SUCCESS, "214 End of help");
- } else {
- for (i = 0; commands[i].name; i++)
- if (!strcasecmp(params, commands[i].name))
- control_printf(SL_SUCCESS, "214 Syntax: %s", commands[i].syntax);
- }
- }
- int parsecmd(char *str)
- {
- int i;
- char *p, *pp, confstr[64]; /* strlen("ALLOWCOMMAND_XXXX") + 1 == 18 */
- p = pp = str; /* Remove garbage in the string */
- while (*p)
- if ((unsigned char) *p < 32)
- p++;
- else
- *pp++ = *p++;
- *pp++ = 0;
- for (i = 0; commands[i].name; i++) { /* Parse command */
- if (!strncasecmp(str, commands[i].name, strlen(commands[i].name))) {
- sprintf(confstr, "ALLOWCOMMAND_%s", commands[i].name);
- if (!strcasecmp(config_getoption(confstr), "no")) {
- control_printf(SL_FAILURE, "550 The command '%s' is disabled.",
- commands[i].name);
- return 1;
- }
- cutto(str, strlen(commands[i].name));
- p = str;
- while ((*p) && ((*p == ' ') || (*p == '\t')))
- p++;
- memmove(str, p, strlen(str) - (p - str) + 1);
- if (state >= commands[i].state_needed) {
- commands[i].function(str);
- return 0;
- } else {
- switch (state) {
- case STATE_CONNECTED: {
- control_printf(SL_FAILURE, "503 USER expected.");
- return 1;
- }
- case STATE_USER: {
- control_printf(SL_FAILURE, "503 PASS expected.");
- return 1;
- }
- case STATE_AUTHENTICATED: {
- control_printf(SL_FAILURE, "503 RNFR before RNTO expected.");
- return 1;
- }
- }
- }
- }
- }
- control_printf(SL_FAILURE, "500 Unknown command: \"%s\"", str);
- return 0;
- }
- int get_buffer_size(int num_connections)
- {
- int buffer_size;
- if (num_connections < 1)
- num_connections = 1;
- buffer_size = xfer_bufsize / num_connections;
- if ( buffer_size < 2)
- buffer_size = 2;
- return buffer_size;
- }
- /*
- This function forks and runs a script. On success it
- returns TRUE, if an error occures, it returns FALSE.
- */
- int run_script(char *script, char *path)
- {
- pid_t process_id;
- char *command_args[] = { script, path, NULL } ;
- /* sighandler_t save_quit, save_int, save_chld; */
- sig_t save_quit, save_int, save_chld;
- /* save original signal handler values */
- save_quit = signal(SIGQUIT, SIG_IGN);
- save_int = signal(SIGINT, SIG_IGN);
- save_chld = signal(SIGCHLD, SIG_DFL);
- process_id = fork();
- /* check for failure */
- if (process_id < 0)
- {
- signal(SIGQUIT, save_quit);
- signal(SIGINT, save_int);
- signal(SIGCHLD, save_chld);
- return FALSE;
- }
- /* child process */
- if (process_id == 0)
- {
- signal(SIGQUIT, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
- execv(script, command_args);
- bftpd_log("Error trying to run script: %s\n", script);
- exit(127);
- }
- /* parent process */
- do
- {
- // process_id = wait4(process_id, NULL, 0, NULL);
- process_id = waitpid(process_id, NULL, 0);
- } while ( (process_id == -1) && (errno == EINTR) );
- signal(SIGQUIT, save_quit);
- signal(SIGINT, save_int);
- signal(SIGCHLD, save_chld);
- return TRUE;
- }
- void Force_Update_Sent_Recv_Log()
- {
- Update_Send_Recv(user, bytes_sent, bytes_recvd);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement