📄 access.c
字号:
} } } else if (!strcasecmp(ARG0, "in")) { if (!ARG2) { if (!data_in) data_limit_data_in = atoi(ARG1); } else if (!strcasecmp(class, ARG2)) { data_in = 1; data_limit_data_in = atoi(ARG1); } } else if (!strcasecmp(ARG0, "out")) { if (!ARG2) { if (!data_out) data_limit_data_out = atoi(ARG1); } else if (!strcasecmp(class, ARG2)) { data_out = 1; data_limit_data_out = atoi(ARG1); } } else if (!strcasecmp(ARG0, "total")) { if (!ARG2) { if (!data_total) data_limit_data_total = atoi(ARG1); } else if (!strcasecmp(class, ARG2)) { data_total = 1; data_limit_data_total = atoi(ARG1); } } }}#ifdef RATIO/*************************************************************************//* FUNCTION : acl_downloadrate *//* PURPOSE : Scan the ACL buffer and determine what data limit to use *//* based upon the class *//* ARGUMENTS : pointer to class name *//*************************************************************************/void acl_downloadrate(char *class){ struct aclmember *entry = NULL; extern int upload_download_rate; int which; /* ul-dl-rate <rate> [<class> ...] */ while (getaclentry("ul-dl-rate", &entry)) { if (!ARG0 ) continue; if (!ARG1) { upload_download_rate = atol(ARG0); } else { for (which = 1; (which < MAXARGS) && ARG[which]; which++) { if (!strcasecmp(ARG[which], class)) upload_download_rate = atol(ARG0); } } }}#endif /* RATIO */#endif#endif/*************************************************************************//* FUNCTION : acl_deny *//* PURPOSE : Scan the ACL buffer and determine a deny command applies *//* ARGUMENTS : pointer class name, pointer to ACL buffer *//*************************************************************************/int acl_deny(char *msgpathbuf){ struct aclmember *entry = NULL; if (msgpathbuf) *msgpathbuf = (char) NULL; /* deny <addrglob> [<message_file>] */ while (getaclentry("deny", &entry)) { if (!ARG0) continue; if (strcasecmp(ARG0, "!nameserved") == 0) { if (!nameserved) { if (ARG1) strcpy(msgpathbuf, entry->arg[1]); return (1); } } else if (hostmatch(ARG0, remoteaddr, remotehost)) { if (ARG1) strcpy(msgpathbuf, entry->arg[1]); return (1); } } return (0);}/*************************************************************************//* FUNCTION : acl_countusers *//* PURPOSE : Check the anonymous FTP access lists to see if this *//* access is permitted. *//* ARGUMENTS : none *//*************************************************************************/int acl_countusers(char *class){ int count, which; char pidfile[MAXPATHLEN]; pid_t buf[MAXUSERS];#ifndef HAVE_FLOCK struct flock arg;#endif if (Bypass_PID_Files) return (0); /* * if pidfd was not opened previously... * pidfd must stay open after the chroot(~ftp) */ sprintf(pidfile, _PATH_PIDNAMES, class); if (pidfd < 0) { mode_t oldmask; oldmask = umask(0); pidfd = open(pidfile, O_RDWR | O_CREAT, 0644); (void) umask(oldmask); } if (pidfd < 0) { syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile); return -1; }#ifdef HAVE_FLOCK while (flock(pidfd, LOCK_EX)) {#ifndef NO_PID_SLEEP_MSGS syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");#endif#else arg.l_type = F_WRLCK; arg.l_whence = arg.l_start = arg.l_len = 0; while (-1 == fcntl(pidfd, F_SETLK, &arg)) {#ifndef NO_PID_SLEEP_MSGS syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");#endif#endif sleep(1); } lseek(pidfd, (off_t) 0, SEEK_SET); count = 0; if (read(pidfd, (void *) buf, sizeof(buf)) == sizeof(buf)) { for (which = 0; which < MAXUSERS; which++) if (buf[which] && !kill(buf[which], 0)) count++; }#ifdef HAVE_FLOCK flock(pidfd, LOCK_UN);#else arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0; fcntl(pidfd, F_SETLK, &arg);#endif return (count);}/*************************************************************************//* FUNCTION : acl_join *//* PURPOSE : Add the current process to the list of processes in the *//* specified class. *//* ARGUMENTS : The name of the class to join *//*************************************************************************/void acl_join(char *class){ int which, avail; pid_t buf[MAXUSERS]; char pidfile[MAXPATHLEN]; pid_t procid;#ifndef HAVE_FLOCK struct flock arg;#endif if (Bypass_PID_Files) return; /* * if pidfd was not opened previously... * pidfd must stay open after the chroot(~ftp) */ sprintf(pidfile, _PATH_PIDNAMES, class); if (pidfd < 0) { mode_t oldmask; oldmask = umask(0); pidfd = open(pidfile, O_RDWR | O_CREAT, 0644); (void) umask(oldmask); } if (pidfd < 0) { syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile); return; }#ifdef HAVE_FLOCK while (flock(pidfd, LOCK_EX)) {#ifndef NO_PID_SLEEP_MSGS syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");#endif#else arg.l_type = F_WRLCK; arg.l_whence = arg.l_start = arg.l_len = 0; while (-1 == fcntl(pidfd, F_SETLK, &arg)) {#ifndef NO_PID_SLEEP_MSGS syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");#endif#endif sleep(1); } procid = getpid(); lseek(pidfd, (off_t) 0, SEEK_SET); if (read(pidfd, (void *) buf, sizeof(buf)) < sizeof(buf)) for (which = 0; which < MAXUSERS; buf[which++] = 0) continue; avail = 0; for (which = 0; which < MAXUSERS; which++) { if ((buf[which] == 0) || (kill(buf[which], 0) == -1)) { avail = which; buf[which] = 0; } else if (buf[which] == procid) { /* already exists in pid file... */#ifdef HAVE_FLOCK flock(pidfd, LOCK_UN);#else arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0; fcntl(pidfd, F_SETLK, &arg);#endif return; } } buf[avail] = procid; lseek(pidfd, (off_t) 0, SEEK_SET); write(pidfd, (void *) buf, sizeof(buf));#ifdef HAVE_FLOCK flock(pidfd, LOCK_UN);#else arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0; fcntl(pidfd, F_SETLK, &arg);#endif}/*************************************************************************//* FUNCTION : acl_remove *//* PURPOSE : remove the current process to the list of processes in *//* the specified class. *//* ARGUMENTS : The name of the class to remove *//*************************************************************************/void acl_remove(void){ char class[1024]; int which, avail; pid_t buf[MAXUSERS]; char pidfile[MAXPATHLEN]; pid_t procid;#ifndef HAVE_FLOCK struct flock arg;#endif if (Bypass_PID_Files) return; if (!acl_getclass(class)) { return; } /* * if pidfd was not opened previously... * pidfd must stay open after the chroot(~ftp) */ sprintf(pidfile, _PATH_PIDNAMES, class); if (pidfd < 0) { mode_t oldmask; oldmask = umask(0); pidfd = open(pidfile, O_RDWR | O_CREAT, 0644); (void) umask(oldmask); } if (pidfd < 0) { syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile); return; }#ifdef HAVE_FLOCK while (flock(pidfd, LOCK_EX)) {#ifndef NO_PID_SLEEP_MSGS syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");#endif#else arg.l_type = F_WRLCK; arg.l_whence = arg.l_start = arg.l_len = 0; while (-1 == fcntl(pidfd, F_SETLK, &arg)) {#ifndef NO_PID_SLEEP_MSGS syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");#endif#endif sleep(1); } procid = getpid(); lseek(pidfd, (off_t) 0, SEEK_SET); if (read(pidfd, (void *) buf, sizeof(buf)) < sizeof(buf)) for (which = 0; which < MAXUSERS; buf[which++] = 0) continue; avail = 0; for (which = 0; which < MAXUSERS; which++) { if ((buf[which] == 0) || (kill(buf[which], 0) == -1)) { avail = which; buf[which] = 0; } else if (buf[which] == procid) { buf[which] = 0; } } lseek(pidfd, (off_t) 0, SEEK_SET); write(pidfd, (void *) buf, sizeof(buf));#ifdef HAVE_FLOCK flock(pidfd, LOCK_UN);#else arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0; fcntl(pidfd, F_SETLK, &arg);#endif close(pidfd); pidfd = -1;}/*************************************************************************//* FUNCTION : pr_mesg *//* PURPOSE : Display a message to the user *//* ARGUMENTS : message code, name of file to display *//*************************************************************************/void pr_mesg(int msgcode, char *msgfile){ FILE *infile; char inbuf[1024], outbuf[1024], *cr; if (msgfile && (int) strlen(msgfile) > 0) { infile = fopen(msgfile, "r"); if (infile) { while (fgets(inbuf, sizeof(inbuf), infile) != NULL) { if ((cr = strchr(inbuf, '\n')) != NULL) *cr = '\0'; msg_massage(inbuf, outbuf, sizeof(outbuf)); lreply(msgcode, "%s", outbuf); } fclose(infile); } }}/*************************************************************************//* FUNCTION : access_init *//* PURPOSE : Read and parse the access lists to set things up *//* ARGUMENTS : none *//*************************************************************************/void access_init(void){ struct aclmember *entry; if (!readacl(_path_ftpaccess)) return; (void) parseacl(); Shutdown[0] = '\0'; entry = (struct aclmember *) NULL; if (getaclentry("shutdown", &entry) && ARG0 != NULL) (void) strncpy(Shutdown, ARG0, sizeof(Shutdown));#ifdef OTHER_PASSWD entry = (struct aclmember *) NULL; while (getaclentry("passwd", &entry) && ARG0 != NULL) { strcpy(_path_passwd, ARG0);#ifdef USE_PAM use_pam = 0;#endif }#ifdef SHADOW_PASSWORD entry = (struct aclmember *) NULL; while (getaclentry("shadow", &entry) && ARG0 != NULL) { strcpy(_path_shadow, ARG0);#ifdef USE_PAM use_pam = 0;#endif }#endif#endif entry = (struct aclmember *) NULL; if (getaclentry("keepalive", &entry) && ARG0 != NULL) if (!strcasecmp(ARG0, "yes")) keepalive = 1; load_timeouts();}/*************************************************************************//* FUNCTION : access_ok *//* PURPOSE : Check the anonymous FTP access lists to see if this *//* access is permitted. *//* ARGUMENTS : none *//*************************************************************************/int access_ok(int msgcode){ char class[1024], msgfile[MAXPATHLEN]; int limit; int nice_delta; if (!use_accessfile) return (1); if (aclbuf == NULL) { syslog(LOG_NOTICE, "ACCESS DENIED (error reading access file) TO %s", remoteident); return (0); } if (acl_deny(msgfile)) {#ifndef HELP_CRACKERS memcpy(DelayedMessageFile, msgfile, sizeof(msgfile));#else pr_mesg(msgcode, msgfile);#endif syslog(LOG_NOTICE, "ACCESS DENIED (deny command) TO %s", remoteident); return (0); } /* if user is not in any class, deny access */ if (!acl_getclass(class)) { syslog(LOG_NOTICE, "ACCESS DENIED (not in any class) TO %s", remoteident); return (0); } if ((nice_delta = acl_getnice(class))) { if (nice_delta < 0) syslog(LOG_NOTICE, "Process nice value adjusted by %d", nice_delta); nice(nice_delta); } acl_getdefumask(class); acl_tcpwindow(class);#ifdef TRANSFER_COUNT#ifdef TRANSFER_LIMIT acl_filelimit(class); acl_datalimit(class);#ifdef RATIO acl_downloadrate(class);#endif#endif#endif /* if no limits defined, no limits apply -- access OK */ limit = acl_getlimit(class, msgfile); if ((limit == -1) || (acl_countusers(class) < limit)) { acl_join(class); return (1); } else {#ifdef LOG_TOOMANY syslog(LOG_NOTICE, "ACCESS DENIED (user limit %d; class %s) TO %s", limit, class, remoteident);#endif#ifndef HELP_CRACKERS memcpy(DelayedMessageFile, msgfile, sizeof(msgfile));#else pr_mesg(msgcode, msgfile);#endif return (-1); } /* NOTREACHED */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -