📄 extensions.c
字号:
return (0); } return (1); } curptr = (struct dirlist *) malloc(strlen(cwd) + 1 + sizeof(struct dirlist)); if (curptr != NULL) { curptr->next = head; head = curptr; curptr->dircode = dircode; strcpy(curptr->dirname, cwd); } return (0);}/*************************************************************************//* FUNCTION : show_banner *//* PURPOSE : Display a banner on the user's terminal before login *//* ARGUMENTS : reply code to use *//*************************************************************************/void show_banner(int msgcode){ char *crptr, linebuf[1024], outbuf[1024]; struct aclmember *entry = NULL; FILE *infile;#ifdef VIRTUAL extern int virtual_mode; extern int virtual_ftpaccess; extern char virtual_banner[]; if (virtual_mode && !virtual_ftpaccess) { infile = fopen(virtual_banner, "r"); if (infile) { while (fgets(linebuf, sizeof(linebuf), infile) != NULL) { if ((crptr = strchr(linebuf, '\n')) != NULL) *crptr = '\0'; msg_massage(linebuf, outbuf, sizeof(outbuf)); lreply(msgcode, "%s", outbuf); } fclose(infile);#ifndef NO_SUCKING_NEWLINES lreply(msgcode, "");#endif } } else {#endif /* banner <path> */ while (getaclentry("banner", &entry)) { infile = fopen(ARG0, "r"); if (infile) { while (fgets(linebuf, sizeof(linebuf), infile) != NULL) { if ((crptr = strchr(linebuf, '\n')) != NULL) *crptr = '\0'; msg_massage(linebuf, outbuf, sizeof(outbuf)); lreply(msgcode, "%s", outbuf); } fclose(infile);#ifndef NO_SUCKING_NEWLINES lreply(msgcode, "");#endif } }#ifdef VIRTUAL }#endif}/*************************************************************************//* FUNCTION : show_message *//* PURPOSE : Display a message on the user's terminal if the current *//* conditions are right *//* ARGUMENTS : reply code to use, LOG_IN|CMD *//*************************************************************************/void show_message(int msgcode, int mode){ char *crptr, linebuf[1024], outbuf[1024], class[MAXPATHLEN], cwd[MAXPATHLEN]; int show, which; struct aclmember *entry = NULL; FILE *infile; if (mode == C_WD && cwd_beenhere(1) != 0) return;#ifdef HAVE_GETCWD (void) getcwd(cwd, MAXPATHLEN - 1);#else (void) getwd(cwd);#endif (void) acl_getclass(class); /* message <path> [<when> [<class>]] */ while (getaclentry("message", &entry)) { if (!ARG0) continue; show = 0; if (mode == LOG_IN && (!ARG1 || !strcasecmp(ARG1, "login"))) if (!ARG2) show++; else { for (which = 2; (which < MAXARGS) && ARG[which]; which++) if (strcasecmp(class, ARG[which]) == 0) show++; } if (mode == C_WD && ARG1 && !strncasecmp(ARG1, "cwd=", 4) && (!strcmp((ARG1) + 4, cwd) || *(ARG1 + 4) == '*' || !wu_fnmatch((ARG1) + 4, cwd, FNM_PATHNAME))) if (!ARG2) show++; else { for (which = 2; (which < MAXARGS) && ARG[which]; which++) if (strcasecmp(class, ARG[which]) == 0) show++; } if (show && (int) strlen(ARG0) > 0) { infile = fopen(ARG0, "r"); if (infile) { while (fgets(linebuf, sizeof(linebuf), infile) != NULL) { if ((crptr = strchr(linebuf, '\n')) != NULL) *crptr = '\0'; msg_massage(linebuf, outbuf, sizeof(outbuf)); lreply(msgcode, "%s", outbuf); } fclose(infile);#ifndef NO_SUCKING_NEWLINES lreply(msgcode, "");#endif } } }}/*************************************************************************//* FUNCTION : show_readme *//* PURPOSE : Display a message about a README file to the user if the *//* current conditions are right *//* ARGUMENTS : pointer to ACL buffer, reply code, LOG_IN|C_WD *//*************************************************************************/void show_readme(int code, int mode){ char **filelist, **sfilelist, class[MAXPATHLEN], cwd[MAXPATHLEN]; int show, which, days; time_t clock; struct stat buf; struct tm *tp; struct aclmember *entry = NULL; if (cwd_beenhere(2) != 0) return;#ifdef HAVE_GETCWD (void) getcwd(cwd, MAXPATHLEN - 1);#else (void) getwd(cwd);#endif (void) acl_getclass(class); /* readme <path> {<when>} */ while (getaclentry("readme", &entry)) { if (!ARG0) continue; show = 0; if (mode == LOG_IN && (!ARG1 || !strcasecmp(ARG1, "login"))) if (!ARG2) show++; else { for (which = 2; (which < MAXARGS) && ARG[which]; which++) if (strcasecmp(class, ARG[which]) == 0) show++; } if (mode == C_WD && ARG1 && !strncasecmp(ARG1, "cwd=", 4) && (!strcmp((ARG1) + 4, cwd) || *(ARG1 + 4) == '*' || !wu_fnmatch((ARG1) + 4, cwd, FNM_PATHNAME))) if (!ARG2) show++; else { for (which = 2; (which < MAXARGS) && ARG[which]; which++) if (strcasecmp(class, ARG[which]) == 0) show++; } if (show) { globerr = NULL; filelist = ftpglob(ARG0); sfilelist = filelist; /* save to free later */ if (!globerr) { while (filelist && *filelist) { errno = 0; if (!stat(*filelist, &buf) && (buf.st_mode & S_IFMT) == S_IFREG) { lreply(code, "Please read the file %s", *filelist); (void) time(&clock); tp = localtime(&clock); days = 365 * tp->tm_year + tp->tm_yday; tp = localtime((time_t *) & buf.st_mtime); days -= 365 * tp->tm_year + tp->tm_yday;/* if (days == 0) { lreply(code, " it was last modified on %.24s - Today", ctime((time_t *)&buf.st_mtime)); } else { */ lreply(code, " it was last modified on %.24s - %d day%s ago", ctime((time_t *) & buf.st_mtime), days, days == 1 ? "" : "s");/* } */ } filelist++; } } if (sfilelist) { blkfree(sfilelist); free((char *) sfilelist); } } }}/*************************************************************************//* FUNCTION : deny_badxfertype *//* PURPOSE : If user is in ASCII transfer mode and tries to retrieve a *//* binary file, abort transfer and display appropriate error *//* ARGUMENTS : message code to use for denial, path of file to check for *//* binary contents or NULL to assume binary file *//*************************************************************************/int deny_badasciixfer(int msgcode, char *filepath){ if (type == TYPE_A && !*filepath) { reply(msgcode, "This is a BINARY file, using ASCII mode to transfer will corrupt it."); return (1); } /* The hooks are here to prevent transfers of actual binary files, not * just TAR or COMPRESS mode files... */ return (0);}/*************************************************************************//* FUNCTION : is_shutdown *//* PURPOSE : *//* ARGUMENTS : *//*************************************************************************/int is_shutdown(int quiet, int new){ static struct tm tmbuf; static struct stat s_last; static time_t last = 0, shut, deny, disc; static int valid; static char text[2048]; struct stat s_cur; extern char *autospout, Shutdown[]; FILE *fp; int deny_off, disc_off; time_t curtime = time(NULL); char buf[1024], linebuf[1024]; if (Shutdown[0] == '\0' || stat(Shutdown, &s_cur)) return (0); if (s_last.st_mtime != s_cur.st_mtime) { s_last = s_cur; valid = 0; fp = fopen(Shutdown, "r"); if (fp == NULL) return (0); fgets(buf, sizeof(buf), fp); if (sscanf(buf, "%d %d %d %d %d %ld %ld", &tmbuf.tm_year, &tmbuf.tm_mon, &tmbuf.tm_mday, &tmbuf.tm_hour, &tmbuf.tm_min, &deny, &disc) != 7) { (void) fclose(fp); return (0); } valid = 1; deny_off = 3600 * (deny / 100) + 60 * (deny % 100); disc_off = 3600 * (disc / 100) + 60 * (disc % 100); tmbuf.tm_year -= 1900; tmbuf.tm_isdst = -1; shut = mktime(&tmbuf); strcpy(shuttime, ctime(&shut)); disc = shut - disc_off; strcpy(disctime, ctime(&disc)); deny = shut - deny_off; strcpy(denytime, ctime(&deny)); text[0] = '\0'; while (fgets(buf, sizeof(buf), fp) != NULL) { msg_massage(buf, linebuf, sizeof(linebuf)); if ((strlen(text) + strlen(linebuf)) < sizeof(text)) strcat(text, linebuf); } (void) fclose(fp); } if (!valid) return (0); /* if last == 0, then is_shutdown() only called with quiet == 1 so far */ if (last == 0 && !quiet) { autospout = text; /* warn them for the first time */ autospout_free = 0; last = curtime; } /* if a new connection and past deny time, tell caller to drop 'em */ if (new && curtime > deny) return (1); /* if past disconnect time, tell caller to drop 'em */ if (curtime > disc) return (1); /* if less than 60 seconds to disconnection, warn 'em continuously */ if (curtime > (disc - 60) && !quiet) { autospout = text; autospout_free = 0; last = curtime; } /* if less than 15 minutes to disconnection, warn 'em every 5 mins */ if (curtime > (disc - 60 * 15)) { if ((curtime - last) > (60 * 5) && !quiet) { autospout = text; autospout_free = 0; last = curtime; } } /* if less than 24 hours to disconnection, warn 'em every 30 mins */ if (curtime < (disc - 24 * 60 * 60) && !quiet) { if ((curtime - last) > (60 * 30)) { autospout = text; autospout_free = 0; last = curtime; } } /* if more than 24 hours to disconnection, warn 'em every 60 mins */ if (curtime > (disc - 24 * 60 * 60) && !quiet) { if ((curtime - last) >= (24 * 60 * 60)) { autospout = text; autospout_free = 0; last = curtime; } } return (0);}void newer(char *date, char *path, int showlots){ extern int ftw(const char *path, int (*fn) (char *, struct stat *, int), int depth); struct tm tm; if (sscanf(date, "%04d%02d%02d%02d%02d%02d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) { tm.tm_year -= 1900; tm.tm_mon--; tm.tm_isdst = -1; newer_time = mktime(&tm); dout = dataconn("file list", (off_t) - 1, "w"); if (dout != NULL) { /* As ftw allocates storage it needs a chance to cleanup, setting * ftwflag prevents myoob from calling longjmp, incrementing * ftwflag instead which causes check_newer to return non-zero * which makes ftw return. */ ftwflag = 1; transflag++; show_fullinfo = showlots;#if defined(HAVE_FTW) ftw(path, check_newer, -1);#else treewalk(path, check_newer, -1, NULL);#endif /* don't send a reply if myoob has already replied */ if (ftwflag == 1) { if (ferror(dout) != 0) perror_reply(550, "Data connection"); else reply(226, "Transfer complete."); } (void) fclose(dout); data = -1; pdata = -1; transflag = 0; ftwflag = 0; } } else reply(501, "Bad DATE format");}int type_match(char *typelist){ if (anonymous && strcasestr(typelist, "anonymous")) return (1); if (guest && strcasestr(typelist, "guest")) return (1); if (!guest && !anonymous && strcasestr(typelist, "real")) return (1); if (strncasecmp(typelist, "class=", 6) == 0) { char class[1024]; (void) acl_getclass(class); if (strcasecmp(typelist + 6, class) == 0) return (1); } return (0);}int path_compare(char *p1, char *p2){ if ((strcmp(p1, "*") == 0) || (wu_fnmatch(p1, p2, FNM_PATHNAME) == 0)) /* 0 means they matched */ return (strlen(p1)); else return (-2);}void expand_id(void){ char class[1024]; struct aclmember *entry = NULL; (void) acl_getclass(class); while (getaclentry("upload", &entry)) { char *q; int i = 0; int options = 1; int classfound = 0; int classmatched = 0; while (options && (i < MAXARGS) && ((q = entry->arg[i]) != (char *) NULL) && (q[0] != '\0')) { if (strcasecmp(q, "absolute") == 0) i++; else if (strcasecmp(q, "relative") == 0) i++; else if (strncasecmp(q, "class=", 6) == 0) { i++; classfound = 1; if (strcasecmp(q + 6, class) == 0) classmatched = 1; } else if (strcmp(q, "-") == 0) { i++; options = 0; } else options = 0; } if (!classfound || classmatched) { char buf[BUFSIZ]; /* * UID */ if (((i + 3) < MAXARGS) && ((q = entry->arg[i + 3]) != (char *) NULL) && (q[0] != '\0') && (strcmp(q, "*") != 0)) { if (q[0] == '%') sprintf(buf, "%s", q + 1); else { struct passwd *pwent = getpwnam(q); if (pwent) sprintf(buf, "%" PW_UID_FORMAT, pwent->pw_uid); else sprintf(buf, "%d", 0); } entry->arg[i + 3] = (char *) malloc(strlen(buf) + 1); if (entry->arg[i + 3] == NULL) { syslog(LOG_ERR, "calloc error in expand_id"); exit(0); } strcpy(entry->arg[i + 3], buf); } /* * GID */ if (((i + 4) < MAXARGS) && ((q = entry->arg[i + 4]) != (char *) NULL) && (q[0] != '\0') && (strcmp(q, "*") != 0)) { if (q[0] == '%') sprintf(buf, "%s", q + 1); else { struct group *grent = getgrnam(q); if (grent) sprintf(buf, "%" GR_GID_FORMAT, grent->gr_gid); else sprintf(buf, "%d", 0); endgrent(); } entry->arg[i + 4] = (char *) malloc(strlen(buf) + 1); if (entry->arg[i + 4] == NULL) { syslog(LOG_ERR, "calloc error in expand_id"); exit(0); } strcpy(entry->arg[i + 4], buf); } } }}int fn_check(char *name){ /* check to see if this is a valid file name... path-filter <type> * <message_file> <allowed_charset> <disallowed> */ struct aclmember *entry = NULL; int j; char *path;#if ! defined(HAVE_REGEXEC) char *sp;#endif#ifdef M_UNIX#ifdef HAVE_REGEX char *regp;#endif#endif#ifdef HAVE_REGEXEC regex_t regexbuf; regmatch_t regmatchbuf;#endif#ifdef LINUX re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;#endif while (getaclentry("path-filter", &entry) && ARG0 != NULL) { if (type_match(ARG0) && ARG1 && ARG2) { /* * check *only* the basename */ if ((path = strrchr(name, '/'))) ++path; else path = name; /* is it in the allowed character set? */#if defined(HAVE_REGEXEC) if (regcomp(®exbuf, ARG2, REG_EXTENDED) != 0) { reply(550, "HAVE_REGEX error");#elif defined(HAVE_REGEX) if ((sp = regcmp(ARG2, (char *) 0)) == NULL) { reply(550, "HAVE_REGEX error");#else if ((sp = re_comp(ARG2)) != 0) { perror_reply(550, sp);#endif return (0); }#if defined(HAVE_REGEXEC) if (regexec(®exbuf, path, 1, ®matchbuf, 0) != 0) {#elif defined(HAVE_REGEX)#ifdef M_UNIX regp = regex(sp, path); free(sp); if (regp == NULL) {#else if ((regex(sp, path)) == NULL) {#endif#else if ((re_exec(path)) != 1) {#endif pr_mesg(550, ARG1); reply(550, "%s: Permission denied on server. (Filename (accept))", name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -