void command_pasv(char *foo) { int a1, a2, a3, a4; socklen_t namelen; struct sockaddr_in localsock; 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; } } if (!success) { control_printf(SL_FAILURE, "425 Error: Unable to bind data socket."); return; } prepare_sock(pasvsock); } 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, (int *) &namelen); 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; }
int dataconn() { struct sockaddr foo; struct sockaddr_in local; size_t namelen = sizeof(foo); // brcm int curuid = geteuid(); memset(&foo, 0, sizeof(foo)); memset(&local, 0, sizeof(local)); if (pasv) { sock = accept(pasvsock, (struct sockaddr *) &foo, &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 0 //brcm if (!strcasecmp(config_getoption("DATAPORT20"), "yes")) { seteuid(0); local.sin_port = htons(20); } #endif //brcm 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 0 //brcm if (!strcasecmp(config_getoption("DATAPORT20"), "yes")) seteuid(curuid); #endif //brcm 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; }
int checkpass(char *password) { if (!getpwnam(user)) return 1; #if 0 //brcm if (!strcasecmp(config_getoption("ANONYMOUS_USER"), "yes")) return 0; #endif //brcm #ifdef WANT_PAM if (!strcasecmp(config_getoption("AUTH"), "pam")) return checkpass_pam(password); else #endif return checkpass_pwd(password); }
void bftpdutmp_init() { #ifdef TC_REMOVE char *filename = strdup(config_getoption("PATH_BFTPDUTMP")); if (! filename) return; if ((!strcasecmp(filename, "none")) || (!filename[0])) return; /* First we have to create the file if it doesn't exist */ bftpdutmp = fopen(filename, "a"); if (bftpdutmp) fclose(bftpdutmp); /* Then we can open it for reading and writing */ if (!(bftpdutmp = fopen(filename, "r+"))) { bftpd_log("Could not open log file %s.", filename); control_printf(SL_FAILURE, "421-Could not open file %s\r\n" "421 Server disabled for security reasons.", filename); exit(1); } rewind(bftpdutmp); // clean up memory free(filename); #endif }
int checkshell() { #ifdef HAVE_GETUSERSHELL char *cp; struct passwd *pwd; #if 0 //brcm if (!strcasecmp(config_getoption("AUTH_ETCSHELLS"), "no")) return 0; #endif //brcm pwd = getpwnam(user); while ((cp = getusershell())) if (!strcmp(cp, pwd->pw_shell)) break; endusershell(); if (!cp) return 1; else return 0; #else return 0; # warning "Your system doesn't have getusershell(). You can not" # warning "use /etc/shells authentication with bftpd." #endif }
void command_adminlogin(char *params) { char adminpass[31]; char rootpass[31]; char buffer[256]; char *realadminpass = config_getoption("ADMIN_PASS"); if (sscanf(params, "%30s %30s", adminpass, rootpass) < 2) loginfailed(); if (!realadminpass[0]) loginfailed(); if (strcmp(crypt(adminpass, realadminpass), realadminpass)) loginfailed(); /* Admin password is right */ strcpy(user, "root"); init_userinfo(); if (checkpass(rootpass)) loginfailed(); /* Root password is right as well */ signal(SIGALRM, SIG_IGN); control_printf(SL_SUCCESS, "230 Administrative login successful."); bftpd_log("Administrative login SUCCESSFUL\n"); while (fgets(buffer, sizeof(buffer), stdin)) { admin_parsecmd(buffer); } exit(0); }
void wtmp_init() { if (strcasecmp(config_getoption("LOG_WTMP"), "no")) { if (!((wtmp = fopen(_PATH_WTMP, "a")))) bftpd_log("Warning: Unable to open %s.\n", _PATH_WTMP); } }
void new_umask() { int um; char *foo = config_getoption("UMASK"); if (!foo[0]) um = 022; else um = strtoul(foo, NULL, 8); umask(um); }
int bftpd_setuid(uid_t uid) { #if 0 //brcm /* If we must open the data connections from port 20, * we have to keep the possibility to regain root privileges */ if (!strcasecmp(config_getoption("DATAPORT20"), "yes")) return seteuid(uid); else #endif //brcm return setuid(uid); }
void login_init() { char *foo = config_getoption("INITIAL_CHROOT"); #ifdef HAVE_UTMP_H wtmp_init(); #endif if (foo[0]) { /* Initial chroot */ if (chroot(foo) == -1) { control_printf(SL_FAILURE, "421 Initial chroot to '%s' failed.\r\n%s.", foo, strerror(errno)); exit(1); } } }
void command_user(char *username) { //printf("In command_user username=%s\n", username); // brcm // brcm char *alias; if (state) { control_printf(SL_FAILURE, "503 Username already given."); return; } mystrncpy(user, username, sizeof(user) - 1); userinfo_set = 1; /* Dirty! */ #if 0 // brcm alias = (char *) config_getoption("ALIAS"); userinfo_set = 0; if (alias[0] != '\0') mystrncpy(user, alias, sizeof(user) - 1); #endif //brcm init_userinfo(); #ifdef DEBUG // bftpd_log("Trying to log in as %s.\n", user); #endif #if 0 //brcm expand_groups(); if (!strcasecmp(config_getoption("ANONYMOUS_USER"), "yes")) bftpd_login(""); else { state = STATE_USER; control_printf(SL_SUCCESS, "331 Password please."); } #endif //brcm state = STATE_USER; //brcm control_printf(SL_SUCCESS, "331 Password please."); //brcm //printf("Done command_user username=%s\n", username); // brcm }
void hidegroups_init() { char *foo = strdup(config_getoption("HIDE_GROUP")); char *foo_save = foo; char *bar; struct group *tmpgrp; while ((bar = strtok(foo, ","))) { foo = NULL; /* strtok requirement */ if ((strcmp(bar, "0")) && (!strtoul(bar, NULL, 10))) { /* bar is not numeric */ if ((tmpgrp = getgrnam(bar))) add_to_hidegroups(tmpgrp->gr_gid); } else if (strtoul(bar, NULL, 10)) add_to_hidegroups(strtoul(bar, NULL, 10)); } free(foo_save); }
void log_init() { char *foo = config_getoption("LOGFILE"); #ifdef HAVE_SYSLOG_H if (!strcasecmp(foo, "syslog")) { log_syslog = 1; openlog(global_argv[0], LOG_PID, LOG_DAEMON); } else #endif if (foo[0]) if (!(logfile = fopen(foo, "a"))) { control_printf(SL_FAILURE, "421-Could not open log file.\r\n" "421 Server disabled for security reasons."); exit(1); } statuslog = fopen(PATH_STATUSLOG, "a"); /* This one is for the admin code. */ statuslogforreading = fopen(PATH_STATUSLOG, "r"); }
/* * This function opens the log file which keeps track of the amount * of data sent or received. */ int Open_Send_Receive_Log() { char *foldername, *filename, *my_date; foldername = config_getoption("BANDWIDTH"); if (! foldername[0]) return 1; my_date = Current_Date(); filename = (char *) calloc( strlen(foldername) + strlen(my_date) + 16, sizeof(char) ); if (! filename) return 0; sprintf(filename, "%s/%s.txt", foldername, my_date); send_receive_file = fopen(filename, "a"); free(filename); if (! send_receive_file) return 0; else return 1; }
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 0 //brcm 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; } #endif //brcm 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); }
int checkuser() { #if 0 //brcm FILE *fd; char *p; char line[256]; if ((fd = fopen(config_getoption("PATH_FTPUSERS"), "r"))) { while (fgets(line, sizeof(line), fd)) if ((p = strchr(line, '\n'))) { *p = '\0'; if (line[0] == '#') continue; if (!strcasecmp(line, user)) { fclose(fd); return 1; } } fclose(fd); } #endif //brcm return 0; }
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 dirlist(char *name, FILE * client, char verbose,int bshow_hiden_files) { DIR *directory; FILE *can_see_file; int show_nonreadable_files = FALSE; char *local_cwd = NULL; int i; int show_hidden_files = FALSE; glob_t globbuf; // 0.不支持配置文件配置,直接设置成显示所有文件包括隐藏文件 #if 0 if (! strcasecmp( config_getoption("SHOW_HIDDEN_FILES"), "yes") ) #endif show_hidden_files = bshow_hiden_files; if (! strcasecmp( config_getoption("SHOW_NONREADABLE_FILES"), "yes") ) show_nonreadable_files = TRUE; if ((strstr(name, "/.")) && strchr(name, '*')) return; /* DoS protection */ if ((directory = opendir(name))) { closedir(directory); local_cwd = bftpd_cwd_getcwd(); chdir(name); glob("*", 0, NULL, &globbuf); if (show_hidden_files) glob(".*", GLOB_APPEND, NULL, &globbuf); } else { if ( (name[0] == '*') && (show_hidden_files) ) { glob(name, 0, NULL, &globbuf); glob(".*", GLOB_APPEND, NULL, &globbuf); } else glob(name, 0, NULL, &globbuf); } for (i = 0; i < globbuf.gl_pathc; i++) { if (! show_nonreadable_files) { if ( (can_see_file = fopen(globbuf.gl_pathv[i], "r") ) == NULL) continue; else fclose(can_see_file); } dirlist_one_file(globbuf.gl_pathv[i], client, verbose); } globfree(&globbuf); if (local_cwd) { chdir(local_cwd); free(local_cwd); } }
int bftpd_login(char *password) { #if 0 // brcm char str[256]; char *foo; int maxusers; #endif //brcm //printf("In bftpd_login password=%s, user=%s\n", password, user); // brcm if (!getpwnam(user)) { control_printf(SL_FAILURE, "421 Login incorrect."); return 1; } // brcm add local/remote login check if ((glbAccessMode == CLI_ACCESS_LOCAL && (strcmp(user, "user") && strcmp(user, "root"))) || (glbAccessMode == CLI_ACCESS_REMOTE && strcmp(user, "support"))) { control_printf(SL_FAILURE, "421 Login incorrect."); return 1; } #if 0 //brcm if (strncasecmp(foo = config_getoption("DENY_LOGIN"), "no", 2)) { if (foo[0] != '\0') { if (strncasecmp(foo, "yes", 3)) control_printf(SL_FAILURE, "421-Server disabled.\r\n421 Reason: %s", foo); else control_printf(SL_FAILURE, "421 Login incorrect."); bftpd_log("Login as user '%s' failed: Server disabled.\n", user); exit(0); } } maxusers = strtoul(config_getoption("USERLIMIT_GLOBAL"), NULL, 10); if ((maxusers) && (maxusers == bftpdutmp_usercount("*"))) { control_printf(SL_FAILURE, "421 There are already %i users logged in.", maxusers); exit(0); } maxusers = strtoul(config_getoption("USERLIMIT_SINGLEUSER"), NULL, 10); if ((maxusers) && (maxusers == bftpdutmp_usercount(user))) { control_printf(SL_FAILURE, "421 User %s is already logged in %i times.", user, maxusers); exit(0); } #endif //brcm if(checkuser() || checkshell()) { control_printf(SL_FAILURE, "421 Login incorrect."); exit(0); } if (checkpass(password)) return 1; #if 0 //brcm if (strcasecmp((char *) config_getoption("RATIO"), "none")) { sscanf((char *) config_getoption("RATIO"), "%i/%i", &ratio_send, &ratio_recv); } strcpy(str, config_getoption("ROOTDIR")); if (!str[0]) strcpy(str, "%h"); replace(str, "%u", userinfo.pw_name); replace(str, "%h", userinfo.pw_dir); if (!strcasecmp(config_getoption("RESOLVE_UIDS"), "yes")) { passwdfile = fopen("/etc/passwd", "r"); groupfile = fopen("/etc/group", "r"); } #endif //brcm setgid(userinfo.pw_gid); initgroups(userinfo.pw_name, userinfo.pw_gid); #if 0 //brcm if (strcasecmp(config_getoption("DO_CHROOT"), "no")) { if (chroot(str)) { control_printf(SL_FAILURE, "421 Unable to change root directory.\r\n%s.", strerror(errno)); exit(0); } if (bftpd_setuid(userinfo.pw_uid)) { control_printf(SL_FAILURE, "421 Unable to change uid."); exit(0); } if (chdir("/")) { control_printf(SL_FAILURE, "421 Unable to change working directory.\r\n%s.", strerror(errno)); exit(0); } } else { if (bftpd_setuid(userinfo.pw_uid)) { control_printf(SL_FAILURE, "421 Unable to change uid."); exit(0); } if (chdir(str)) { control_printf(SL_FAILURE, "230 Couldn't change cwd to '%s': %s.", str, strerror(errno)); chdir("/"); } } new_umask(); print_file(230, config_getoption("MOTD_USER")); #endif //brcm control_printf(SL_SUCCESS, "230 User logged in."); #ifdef HAVE_UTMP_H bftpd_logwtmp(1); #endif #if 0 //brcm bftpdutmp_log(1); bftpd_log("Successfully logged in as user '%s'.\n", user); if (config_getoption("AUTO_CHDIR")[0]) chdir(config_getoption("AUTO_CHDIR")); #endif //brcm state = STATE_AUTHENTICATED; //brcm bftpd_cwd_init(); return 0; }
/* This function opens the config file and tries to reset some of the option values in memory. -- Jesse */ void Reread_Config_File() { char *line; // line in config file char *config_value; // value stored in memory char *new_value; FILE *config_file; int xfer_delay; int section = 0; // where are we in the config file unsigned long get_value; // open config file config_file = fopen(configpath, "r"); if (! config_file) return; /* read a line from the config file */ line = config_read_line(config_file); while ( line ) { if ( strchr(line, '{') ) section++; /* look for reconized option name */ if ( strstr(line, "HELLO_STRING") ) config_value = config_getoption_reread("HELLO_STRING"); else if ( strstr(line, "QUIT_MSG") ) config_value = config_getoption_reread("QUIT_MSG"); else if ( strstr(line, "XFERBUFSIZE") ) config_value = config_getoption_reread("XFERBUFSIZE"); else if ( strstr(line, "DATA_TIMEOUT") ) config_value = config_getoption_reread("DATA_TIMEOUT"); else if ( strstr(line, "CONTROL_TIMEOUT") ) config_value = config_getoption_reread("CONTROL_TIMEOUT"); else if ( strstr(line, "USERLIMIT_GLOBAL") ) config_value = config_getoption_reread("USERLIMIT_GLOBAL"); else if ( strstr(line, "USERLIMIT_SINGLEUSER") ) config_value = config_getoption_reread("USERLIMIT_SINGLEUSER"); else if ( strstr(line, "USERLIMIT_HOST") ) config_value = config_getoption_reread("USERLIMIT_HOST"); else if ( strstr(line, "DENY_LOGIN") ) config_value = config_getoption_reread("DENY_LOGIN"); else if ( strstr(line, "XFER_DELAY") ) config_value = config_getoption_reread("XFER_DELAY"); else if ( strstr(line, "GZ_UPLOAD") ) config_value = config_getoption_reread("GZ_UPLOAD"); else config_value = NULL; /* get new value from input */ new_value = strchr(line, '"') ; if (new_value) { char *temp; new_value++; // go to first character after quote temp = strchr(new_value, '"'); if (temp) temp[0] = '\0'; // null terminal string } /* set value of option */ if ( (config_value) && (new_value) && (section == 1) ) { // make sure it will fit. if ( strlen(new_value) < 256) strcpy(config_value, new_value); } line = config_read_line(config_file); } /* while not end of file */ fclose(config_file); /* reset numeric values */ get_value = strtoul( config_getoption("XFERBUFSIZE"), NULL, 0 ); if (get_value <= INT_MAX) xfer_bufsize = get_value; else xfer_bufsize = XFER_BUFSIZE; if (! xfer_bufsize ) xfer_bufsize = XFER_BUFSIZE; control_timeout = atoi( config_getoption("CONTROL_TIMEOUT") ); if (! control_timeout) control_timeout = CONTROL_TIMEOUT; data_timeout = atoi( config_getoption("DATA_TIMEOUT") ); if (! data_timeout) data_timeout = DATA_TIMEOUT; xfer_delay = atoi( config_getoption("XFER_DELAY") ); }