📄 ftpd.c
字号:
route_vectored = routevector(); conv_init();#ifdef MAIL_ADMIN incmails = 0; mailfrom = NULL;#endif /* MAIL_ADMIN */#ifdef VIRTUAL /* ** If virtual_mode is set at this point then an alternate ftpaccess ** is in use. Otherwise we need to check the Master ftpaccess file ** to see if the site is only using the "virtual" directives to ** specify virtual site directives. ** ** In this manner an admin can put a virtual site in the ftpservers ** file if they need expanded configuration support or can use the ** minimal root/banner/logfile if they do not need any more than that. */ if (virtual_mode) { /* Get the root of the virtual server directory */ entry = (struct aclmember *) NULL; if (getaclentry("root", &entry)) { if (ARG0) strcpy(virtual_root, ARG0); } /* Get the logfile to use */ entry = (struct aclmember *) NULL; if (getaclentry("logfile", &entry)) { if (ARG0) strcpy(logfile, ARG0); } } else { virtual_hostname[0] = '\0'; virtual_address[0] = '\0'; virtual_len = sizeof(virtual_addr); if (getsockname(0, (struct sockaddr *) &virtual_addr, &virtual_len) == 0) { virtual_ptr = (struct sockaddr_in *) &virtual_addr; strcpy(virtual_address, inet_ntoa(virtual_ptr->sin_addr)); shp = gethostbyaddr((char *) &virtual_ptr->sin_addr, sizeof(struct in_addr), AF_INET); if (shp != NULL) { (void) strncpy(virtual_hostname, shp->h_name, sizeof(virtual_hostname)); virtual_hostname[sizeof(virtual_hostname) - 1] = '\0'; } entry = (struct aclmember *) NULL; while (getaclentry("virtual", &entry)) { if (!ARG0 || !ARG1 || !ARG2) continue; if (hostmatch(ARG0, virtual_address, virtual_hostname)) { if (!strcasecmp(ARG1, "root")) { syslog(LOG_NOTICE, "VirtualFTP Connect to: %s [%s]", virtual_hostname, virtual_address); virtual_mode = 1; strncpy(virtual_root, ARG2, sizeof(virtual_root)); virtual_root[sizeof(virtual_root) - 1] = '\0'; /* reset hostname to this virtual name */ (void) strcpy(hostname, virtual_hostname); virtual_email[0] = '\0'; } if (!strcasecmp(ARG1, "banner")) { strncpy(virtual_banner, ARG2, sizeof(virtual_banner)); virtual_banner[sizeof(virtual_banner) - 1] = '\0'; } if (!strcasecmp(ARG1, "logfile")) { strncpy(logfile, ARG2, sizeof(logfile)); logfile[sizeof(logfile) - 1] = '\0'; } if (!strcasecmp(ARG1, "hostname")) { strncpy(hostname, ARG2, sizeof(hostname)); hostname[sizeof(hostname) - 1] = '\0'; } if (!strcasecmp(ARG1, "email")) { strncpy(virtual_email, ARG2, sizeof(virtual_email)); virtual_email[sizeof(virtual_email) - 1] = '\0'; }#ifdef OTHER_PASSWD if (!strcasecmp(ARG1, "passwd")) { strncpy(_path_passwd, ARG2, sizeof(_path_passwd)); _path_passwd[sizeof(_path_passwd) - 1] = '\0';#ifdef USE_PAM use_pam = 0;#endif }#ifdef SHADOW_PASSWORD if (!strcasecmp(ARG1, "shadow")) { strncpy(_path_shadow, ARG2, sizeof(_path_shadow)); _path_shadow[sizeof(_path_shadow) - 1] = '\0';#ifdef USE_PAM use_pam = 0;#endif }#endif#endif#ifdef MAIL_ADMIN if (mailfrom == NULL) if (!strcasecmp(ARG1, "mailfrom")) { mailfrom = strdup(ARG2); } if (!strcasecmp(ARG1, "incmail")) { if (incmails < INCMAILS) incmail[incmails++] = strdup(ARG2); }#endif } } if (!virtual_mode) { entry = (struct aclmember *) NULL; while (getaclentry("defaultserver", &entry)) { if (!ARG0 || !ARG1) continue;#ifdef MAIL_ADMIN if (mailfrom == NULL) if (!strcasecmp(ARG0, "mailfrom")) { mailfrom = strdup(ARG1); } if (!strcasecmp(ARG0, "incmail")) { if (incmails < INCMAILS) incmail[incmails++] = strdup(ARG1); }#endif } } } }#ifdef VIRTUAL_DEBUG lreply(220, "_path_ftpaccess == %s", _path_ftpaccess); lreply(220, "_path_ftpusers == %s", _path_ftpusers); lreply(220, "_path_ftphosts == %s", _path_ftphosts); lreply(220, "_path_private == %s", _path_private); lreply(220, "_path_cvt == %s", _path_cvt); if (virtual_mode) { if (virtual_ftpaccess) lreply(220, "VIRTUAL Mode: Using %s specific %s access file", hostname, _path_ftpaccess); else lreply(220, "VIRTUAL Mode: Using Master access file %s", _path_ftpaccess); lreply(220, "virtual_root == %s", virtual_root); if (!virtual_ftpaccess) lreply(220, "virtual_banner == %s", virtual_banner); } lreply(220, "logfile == %s", logfile);#endif#endif if (is_shutdown(1, 1) != 0) { syslog(LOG_INFO, "connection refused (server shut down) from %s", remoteident); reply(500, "%s FTP server shut down -- please try again later.", hostname); exit(0); }#ifdef OPIE af_pwok = opieaccessfile(remotehost);#endif#ifdef HAVE_LIBRESOLV /* check permitted access based on remote host DNS information */ if (!check_reverse_dns()) { exit(0); } if (!check_matching_dns()) { exit(0); }#endif /* HAVE_LIBRESOLV */ show_banner(220);#ifndef INTERNAL_LS entry = (struct aclmember *) NULL; if (getaclentry("lslong", &entry) && ARG0 && (int) strlen(ARG0) > 0) { strcpy(ls_long, ARG0); for (which = 1; (which < MAXARGS) && ARG[which]; which++) { strcat(ls_long, " "); strcat(ls_long, ARG[which]); } } else {#if defined(SVR4) || defined(ISC)#if defined(AIX) || defined(SOLARIS2) strcpy(ls_long, "/bin/ls -lA");#else strcpy(ls_long, "/bin/ls -la");#endif#else strcpy(ls_long, "/bin/ls -lgA");#endif } strcat(ls_long, " %s"); entry = (struct aclmember *) NULL; if (getaclentry("lsshort", &entry) && ARG0 && (int) strlen(ARG0) > 0) { strcpy(ls_short, ARG0); for (which = 1; (which < MAXARGS) && ARG[which]; which++) { strcat(ls_short, " "); strcat(ls_short, ARG[which]); } } else {#if defined(SVR4) || defined(ISC)#if defined(AIX) || defined(SOLARIS2) strcpy(ls_short, "/bin/ls -lA");#else strcpy(ls_short, "/bin/ls -la");#endif#else strcpy(ls_short, "/bin/ls -lgA");#endif } strcat(ls_short, " %s"); entry = (struct aclmember *) NULL; if (getaclentry("lsplain", &entry) && ARG0 && (int) strlen(ARG0) > 0) { strcpy(ls_plain, ARG0); for (which = 1; (which < MAXARGS) && ARG[which]; which++) { strcat(ls_plain, " "); strcat(ls_plain, ARG[which]); } } else strcpy(ls_plain, "/bin/ls"); strcat(ls_plain, " %s");#endif /* ! INTERNAL_LS */#ifdef MAIL_ADMIN mailservers = 0; entry = (struct aclmember *) NULL; while (getaclentry("mailserver", &entry) && ARG0 && mailservers < MAILSERVERS) mailserver[mailservers++] = strdup(ARG0); if (mailservers == 0) mailserver[mailservers++] = strdup("localhost"); if (incmails == 0) { entry = (struct aclmember *) NULL; while (getaclentry("incmail", &entry) && ARG0 && incmails < INCMAILS) incmail[incmails++] = strdup(ARG0); } if (mailfrom == NULL) { entry = (struct aclmember *) NULL; if (getaclentry("mailfrom", &entry) && ARG0) mailfrom = strdup(ARG0); else mailfrom = strdup("wu-ftpd"); }#endif /* MAIL_ADMIN */ {#define OUTPUT_LEN 1024 int version_option = 0; char output_text[OUTPUT_LEN + 1]; int arg_count, output_len; entry = NULL; if (getaclentry("greeting", &entry) && ARG0) { if (!strcasecmp(ARG0, "full")) version_option = 0; else if (!strcasecmp(ARG0, "text") && ARG1) version_option = 3; else if (!strcasecmp(ARG0, "terse")) version_option = 2; else if (!strcasecmp(ARG0, "brief")) version_option = 1; } switch (version_option) { default: reply(220, "%s FTP server (%s) ready.", hostname, version); break; case 1: reply(220, "%s FTP server ready.", hostname); break; case 2: reply(220, "FTP server ready."); break; case 3: output_text[0] = '\0'; output_len = 0; for (arg_count = 1; ARG[arg_count] != NULL; arg_count++) { int arg_len; arg_len = strlen(ARG[arg_count]); if ((output_len + arg_len) > OUTPUT_LEN) { /* avoid possible buffer overflow */ break; } /* append the text to the greeting */ strcat(output_text, ARG[arg_count]); output_len += arg_len; if (ARG[arg_count + 1] != NULL) { if ((output_len + 2) > OUTPUT_LEN) { /* avoid possible buffer overflow and adding a trailing space */ break; } /* if the next entry exists, add a white space */ strcat(output_text, " "); output_len += 1; } } reply(220, "%s", output_text); break; } } (void) setjmp(errcatch); for (;;) (void) yyparse(); /* NOTREACHED */}SIGNAL_TYPE randomsig(int sig){#ifdef HAVE_SIGLIST syslog(LOG_ERR, "exiting on signal %d: %s", sig, sys_siglist[sig]);#else syslog(LOG_ERR, "exiting on signal %d", sig);#endif chdir("/"); signal(SIGIOT, SIG_DFL); signal(SIGILL, SIG_DFL); exit(1); /* dologout(-1); *//* NOTREACHED */}SIGNAL_TYPE lostconn(int sig){#ifdef VERBOSE_ERROR_LOGING syslog(LOG_INFO, "lost connection to %s", remoteident);#else if (debug) syslog(LOG_DEBUG, "lost connection to %s", remoteident);#endif dologout(-1);}static char ttyline[20];#ifdef MAPPING_CHDIR/* Keep track of the path the user has chdir'd into and respond with * that to pwd commands. This is to avoid having the absolue disk * path returned, which I want to avoid. */char mapped_path[MAXPATHLEN] = "/";char *mapping_getwd(char *path){ strcpy(path, mapped_path); return path;}char *mapping_getcwd(char *path, size_t size){ strncpy(path, mapped_path, size); path[size - 1] = '\0'; return path;}/* Make these globals rather than local to mapping_chdir to avoid stack overflow */char pathspace[MAXPATHLEN];char old_mapped_path[MAXPATHLEN];void do_elem(char *dir){ /* . */ if (dir[0] == '.' && dir[1] == '\0') { /* ignore it */ return; } /* .. */ if (dir[0] == '.' && dir[1] == '.' && dir[2] == '\0') { char *last; /* lop the last directory off the path */ if ((last = strrchr(mapped_path, '/'))) { /* If start of pathname leave the / */ if (last == mapped_path) last++; *last = '\0'; } return; } /* append the dir part with a leading / unless at root */ if (!(mapped_path[0] == '/' && mapped_path[1] == '\0')) if (strlen(mapped_path) < sizeof(mapped_path) - 1) strcat(mapped_path, "/"); if (sizeof(mapped_path) - strlen(mapped_path) > 1) strncat(mapped_path, dir, sizeof(mapped_path) - strlen(mapped_path) - 1);}int mapping_chdir(char *orig_path){ int ret; char *sl, *path; strcpy(old_mapped_path, mapped_path); path = &pathspace[0]; strcpy(path, orig_path); /* / at start of path, set the start of the mapped_path to / */ if (path[0] == '/') { mapped_path[0] = '/'; mapped_path[1] = '\0'; path++; } while ((sl = strchr(path, '/'))) { char *dir; dir = path; *sl = '\0'; path = sl + 1; if (*dir) do_elem(dir); if (*path == '\0') break; } if (*path) do_elem(path); if ((ret = chdir(mapped_path)) < 0) { strcpy(mapped_path, old_mapped_path); } return ret;}/* From now on use the mapping version */#define chdir(d) mapping_chdir(d)#define getwd(d) mapping_getwd(d)#define getcwd(d,u) mapping_getcwd((d),(u))#endif /* MAPPING_CHDIR *//* Helper function for sgetpwnam(). */char *sgetsave(char *s){ char *new; new = (char *) malloc(strlen(s) + 1); if (new == NULL) { perror_reply(421, "Local resource failure: malloc"); dologout(1); /* NOTREACHED */ } (void) strcpy(new, s); return (new);}/* Save the result of a getpwnam. Used for USER command, since the data * returned must not be clobbered by any other command (e.g., globbing). */struct passwd *sgetpwnam(char *name){ static struct passwd save; register struct passwd *p;#ifdef M_UNIX struct passwd *ret = (struct passwd *) NULL;#endif char *sgetsave(char *s);#ifdef KERBEROS register struct authorization *q;#endif /* KERBEROS */#if defined(SecureWare) || defined(HPUX_10_TRUSTED) struct pr_passwd *pr;#endif#ifdef KERBEROS init_krb(); q = getauthuid(p->pw_uid); end_krb();#endif /* KERBEROS */#ifdef M_UNIX#if defined(SecureWare) || defined(HPUX_10_TRUSTED) if ((pr = getprpwnam(name)) == NULL) goto DONE;#endif /* SecureWare || HPUX_10_TRUSTED */#ifdef OTHER_PASSWD if ((p = bero_getpwnam(name, _path_passwd)) == NULL)#else if ((p = getpwnam(name)) == NULL)#endif goto DONE;#else /* M_UNIX */#if defined(SecureWare) || defined(HPUX_10_TRUSTED) if ((pr = getprpwnam(name)) == NULL) return ((struct passwd *) pr);#endif /* SecureWare || HPUX_10_TRUSTED */#ifdef OTHER_PASSWD if ((p = bero_getpwnam(name, _path_passwd)) == NULL)#else if ((p = getpwnam(name)) == NULL)#endif return (p);#endif /* M_UNIX */ if (save.pw_name) free(save.pw_name); if (save.pw_gecos) free(save.pw_gecos); if (save.pw_dir) free(save.pw_dir); if (save.pw_shell) free(save.pw_shell); if (save.pw_passwd) free(save.pw_passwd); save = *p; save.pw_name = sgetsave(p->pw_name);#ifdef KERBEROS save.pw_passwd = sgetsave(q->a_password);#elif defined(SecureWare) || defined(HPUX_10_TRUSTED) if (pr->uflg.fg_encrypt && pr->ufld.fd_encrypt && *pr->ufld.fd_encrypt) save.pw_passwd = sgetsave(pr->ufld.fd_encrypt); else save.pw_passwd = sgetsave("");#else save.pw_passwd = sgetsave(p->pw_passwd);#endif#ifdef SHADOW_PASSWORD if (p && (p->pw_passwd==NULL || strlen(p->pw_passwd)<8)) { struct spwd *spw;#ifdef OTHER_PASSWD if ((spw = bero_getspnam(p->pw_name, _path_shadow)) != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -