char test_abort(char selectbefore, int file, int sock) { char str[256]; fd_set rfds; struct timeval tv; 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; } fgets(str, sizeof(str), stdin); if (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"); printf("Client aborted file transmission. \n"); alarm(control_timeout); return 1; } return 0; }
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; }
void command_type(char *params) { if ((*params == 'I') || (*params == 'i')) { control_printf(SL_SUCCESS, "200 Transfer type changed to BINARY"); xfertype = TYPE_BINARY; } else { #ifdef SUPPORT_FTPD_STORAGE control_printf(SL_SUCCESS, "200 Transfer type changed to ASCII"); xfertype = TYPE_ASCII; #else control_printf(SL_FAILURE, "500 Type '%c' not supported. Only support BINARY mode", *params); #endif } }
void command_pass(char *password) { //printf("In command_pass password=%s\n", password); // brcm if (state > STATE_USER) { control_printf(SL_FAILURE, "503 Already logged in."); return; } if (bftpd_login(password)) { //brcm bftpd_log("Login as user '%s' failed.\n", user); control_printf(SL_FAILURE, "421 Login incorrect."); syslog(LOG_WARNING,"104051 FTP Server Login UserName or Password Error\n"); exit(0); } }
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; }
void bftpdutmp_init() { //---start--- add by w145036 //char *filename = strdup(config_getoption("PATH_BFTPDUTMP")); char *filename = strdup(PATH_BFTPDUTMP); //---end--- 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); }
int admin_parsecmd(char *str) { int i; char *p, *pp; int string_length; string_length = strlen(str) - 2; if (string_length < 0) string_length = 0; str[string_length] = '\0'; /* Remove \r\n */ p = pp = str; /* Remove garbage in the string */ while (*p) if ((unsigned char) *p < 32) p++; else *pp++ = *p++; *pp++ = 0; for (i = 0; admin_commands[i].name; i++) { /* Parse command */ if (!strncasecmp(str, admin_commands[i].name, strlen(admin_commands[i].name))) { cutto(str, strlen(admin_commands[i].name)); p = str; while ((*p) && ((*p == ' ') || (*p == '\t'))) p++; memmove(str, p, strlen(str) - (p - str) + 1); admin_commands[i].function(str); return 0; } } control_printf(SL_FAILURE, "500 Unknown command: \"%s\"", str); return 1; }
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 displayMessage(UPLOAD_RESULT result) { switch (result) { case UPLOAD_OK: control_printf(SL_SUCCESS, "Ftp image done. PLEASE TYPE 'bye' or 'quit' NOW to quit ftp and the Router will start writing the image to flash."); break; case UPLOAD_FAIL_NO_MEM: control_printf(SL_FAILURE, "Not enough memory error."); break; case UPLOAD_FAIL_ILLEGAL_IMAGE: control_printf(SL_FAILURE, "Image updating failed. The selected file contains an illegal image. PLEASE TYPE 'bye' or 'quit' NOW to quit ftp"); break; case UPLOAD_FAIL_FLASH: case UPLOAD_FAIL_FTP: control_printf(SL_FAILURE, "ftp connection failed."); break; } }
void command_adminkick(char *strpid) { unsigned long int get_pid = strtoul(strpid, NULL, 10); int pid; if (get_pid <= INT_MAX) pid = get_pid; else pid = 0; if (!pid) control_printf(SL_FAILURE, "500 Error: Given PID is not valid."); else if (bftpdutmp_pidexists(pid)) { if (kill(pid, SIGTERM)) control_printf(SL_FAILURE, "500 Error: %s.", strerror(errno)); else control_printf(SL_FAILURE, "200 OK"); } else control_printf(SL_FAILURE, "500 Error: The given PID does not belong to bftpd."); }
void command_epsv(char *params) { struct sockaddr_in localsock; int 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, (int *) &namelen); control_printf(SL_SUCCESS, "229 Entering extended passive mode (|||%i|)", ntohs(localsock.sin_port)); pasv = 1; }
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_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); }
void config_init() { FILE *configfile; char *str; struct group_of_users *grp = NULL; struct user *usr = NULL; config_global.options = NULL; config_global.directories = NULL; if (!configpath) return; configfile = fopen(configpath, "r"); if (!configfile) { control_printf(SL_FAILURE, "421 Unable to open configuration file."); exit(1); } while ((str = config_read_line(configfile))) { if (strchr(str, '{')) { replace(str, " {", "{"); replace(str, "{ ", "{"); replace(str, " }", "}"); replace(str, "} ", "}"); if (!strcasecmp(str, "global{\n")) { create_options(configfile, &(config_global.options), &(config_global.directories)); } else if (strstr(str, "user ") == str) { if (usr) { usr = usr->next = malloc(sizeof(struct user)); } else { config_users = usr = malloc(sizeof(struct user)); } usr->name = strdup(str + 5); *strchr(usr->name, '{') = 0; create_options(configfile, &(usr->options), &(usr->directories)); } else if (strstr(str, "group ") == str) { if (grp) { grp = grp->next = malloc(sizeof(struct group_of_users)); } else { config_groups = grp = malloc(sizeof(struct group_of_users)); } cutto(str, 6); *strchr(str, '{') = 0; grp->users = NULL; grp->next = NULL; grp->temp_members = strdup(str); create_options(configfile, &(grp->options), &(grp->directories)); } } } fclose(configfile); }
void command_adminlog(char *params) { fd_set rfds; struct timeval tv; char buffer[256]; control_printf(SL_SUCCESS, "200 Starting logfile transmission."); mystatuslog = statuslogforreading; fseek(mystatuslog, 0, SEEK_END); while (mystatuslog) { while (fgets(buffer, sizeof(buffer), mystatuslog)) /* Don't use control_printf here, as it would generate an infinite loop */ fprintf(stderr, "%s", buffer); FD_ZERO(&rfds); FD_SET(0, &rfds); tv.tv_sec = 1; tv.tv_usec = 0; if (select(1, &rfds, NULL, NULL, &tv) > 0) { if (!fgets(buffer, sizeof(buffer), stdin)) exit(0); admin_parsecmd(buffer); } } control_printf(SL_SUCCESS, "202 Logfile transmission stopped."); }
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 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"); }
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_adminquit(char *params) { control_printf(SL_SUCCESS, "221 See you later..."); exit(0); }
void command_adminstoplog(char *params) { mystatuslog = NULL; control_printf(SL_SUCCESS, "201 Stopping logfile transmission."); }
void command_admingetconf(char *params) { control_printf(SL_FAILURE, "500 Not implemented yet."); }
void command_pwd(char *params) { control_printf(SL_SUCCESS, "257 \"%s\" is the current working directory.", bftpd_cwd_getcwd()); }
void loginfailed() { control_printf(SL_FAILURE, "421 Login incorrect."); bftpd_log("Administrative login FAILED\n"); exit(1); }
void do_fwUpdate(void) { int byteRd = 0; char *curPtr = NULL; unsigned int totalAllocatedSize = 0; char *buffer; int max; fd_set rfds; struct timeval tv; UBOOL8 isConfigFile; /* reset all of our globals before starting another download */ imageFormat = CMS_IMAGE_FORMAT_INVALID; if (imagePtr) free(imagePtr); imagePtr = NULL; uploadSize = 0; if (dataconn()) return; alarm(0); if ((buffer = malloc(xfer_bufsize)) == NULL) { displayMessage(UPLOAD_FAIL_NO_MEM); return; } max = (sock > fileno(stdin) ? sock : fileno(stdin)) + 1; for (;;) { FD_ZERO(&rfds); FD_SET(sock, &rfds); FD_SET(fileno(stdin), &rfds); tv.tv_sec = data_timeout; tv.tv_usec = 0; if (!select(max, &rfds, NULL, NULL, &tv)) { close(sock); control_printf(SL_FAILURE, "426 Kicked due to data transmission timeout."); if (imagePtr) free(imagePtr); free(buffer); displayMessage(UPLOAD_FAIL_FTP); return; // exit ? } if (!((byteRd = recv(sock, buffer, xfer_bufsize, 0)))) break; if (curPtr == NULL) { // Also look in tftpd.c, which does about the same thing isConfigFile = cmsImg_isConfigFileLikely(buffer); cmsLog_debug("isConfigFile = %d", isConfigFile); if (isConfigFile) { totalAllocatedSize = cmsImg_getConfigFlashSize(); } else { totalAllocatedSize = cmsImg_getImageFlashSize() + cmsImg_getBroadcomImageTagSize(); // let smd know that we are about to start a big download cmsImg_sendLoadStartingMsg(msgHandle, connIfName); } if ((curPtr = (char *) malloc(totalAllocatedSize)) == NULL) { cmsLog_error("Not enough memory (%d bytes needed)", totalAllocatedSize); free(buffer); cmsImg_sendLoadDoneMsg(msgHandle); return; } printf("%d bytes allocated for image\n", totalAllocatedSize); imagePtr = curPtr; } if (uploadSize + byteRd < totalAllocatedSize) { memcpy(curPtr, buffer, byteRd); curPtr += byteRd; uploadSize += byteRd; } else { printf("Image could not fit into %d byte buffer.\n", totalAllocatedSize); free(buffer); free(imagePtr); imagePtr = NULL; cmsImg_sendLoadDoneMsg(msgHandle); return; } } // end for loop to read in complete image free(buffer); /* * Now we have the entire image. Validate it. */ if ((imageFormat = cmsImg_validateImage(imagePtr, uploadSize, msgHandle)) == CMS_IMAGE_FORMAT_INVALID) { displayMessage(UPLOAD_FAIL_ILLEGAL_IMAGE); free(imagePtr); imagePtr = NULL; cmsImg_sendLoadDoneMsg(msgHandle); } else { printf("Image validated, size=%u format=%d, waiting for quit before flashing.\n", uploadSize, imageFormat); displayMessage(UPLOAD_OK); // flash image will be done when user types bye or OK } close(sock); // this tells the ftp client that the transfer is complete alarm(control_timeout); }
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; }