📄 access.c
字号:
/**************************************************************************** Copyright (c) 1999,2000 WU-FTPD Development Group. All rights reserved. Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994 The Regents of the University of California. Portions Copyright (c) 1993, 1994 Washington University in Saint Louis. Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc. Portions Copyright (c) 1989 Massachusetts Institute of Technology. Portions Copyright (c) 1998 Sendmail, Inc. Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P. Allman. Portions Copyright (c) 1997 by Stan Barber. Portions Copyright (c) 1997 by Kent Landfield. Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. Use and distribution of this software and its source code are governed by the terms and conditions of the WU-FTPD Software License ("LICENSE"). If you did not receive a copy of the license, it may be obtained online at http://www.wu-ftpd.org/license.html. $Id: access.c,v 1.30 2000/07/01 18:17:38 wuftpd Exp $ ****************************************************************************/#include "config.h"#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#ifdef HAVE_SYS_SYSLOG_H#include <sys/syslog.h>#elif defined(HAVE_SYSLOG_H) || !defined(AUTOCONF)#include <syslog.h>#endif#ifdef TIME_WITH_SYS_TIME#include <time.h>#include <sys/time.h>#elif defined(HAVE_SYS_TIME_H)#include <sys/time.h>#else#include <time.h>#endif#include <ctype.h>#include <pwd.h>#include <grp.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#include <sys/param.h>#ifdef HAVE_PATHS_H#include <paths.h>#endif#include "pathnames.h"#include "extensions.h"#include "proto.h"#if defined(HAVE_FCNTL_H)#include <fcntl.h>#endif#ifdef OTHER_PASSWD#include "getpwnam.h"extern char _path_passwd[];#ifdef SHADOW_PASSWORDextern char _path_shadow[];#endif#endif#if defined(USE_PAM) && defined(OTHER_PASSWD)extern int use_pam;#endifextern char remotehost[], remoteaddr[], *remoteident, *aclbuf;extern int nameserved, anonymous, guest, TCPwindowsize, use_accessfile;extern mode_t defumask;char Shutdown[MAXPATHLEN];int keepalive = 0;#define MAXLINE 80static char incline[MAXLINE];int pidfd = -1;extern int Bypass_PID_Files;#ifndef HELP_CRACKERSextern char DelayedMessageFile[];#endif#include "wu_fnmatch.h"extern void load_timeouts(void);/*************************************************************************//* FUNCTION : parse_time *//* PURPOSE : Check a single valid-time-string against the current time *//* and return whether or not a match occurs. *//* ARGUMENTS : a pointer to the time-string *//*************************************************************************/int parsetime(char *whattime){ static char *days[] = {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Wk"}; time_t clock; struct tm *curtime; int wday, start, stop, ltime, validday, loop, match; (void) time(&clock); curtime = localtime(&clock); wday = curtime->tm_wday; validday = 0; match = 1; while (match && isalpha(*whattime) && isupper(*whattime)) { match = 0; for (loop = 0; loop < 8; loop++) { if (strncmp(days[loop], whattime, 2) == 0) { whattime += 2; match = 1; if ((wday == loop) || ((loop == 7) && wday && (wday < 6))) { validday = 1; } } } } if (!validday) { if (strncmp(whattime, "Any", 3) == 0) { validday = 1; whattime += 3; } else return (0); } if (sscanf(whattime, "%d-%d", &start, &stop) == 2) { ltime = curtime->tm_min + 100 * curtime->tm_hour; if ((start < stop) && ((ltime >= start) && ltime < stop)) return (1); if ((start > stop) && ((ltime >= start) || ltime < stop)) return (1); } else return (1); return (0);}/*************************************************************************//* FUNCTION : validtime *//* PURPOSE : Break apart a set of valid time-strings and pass them to *//* parse_time, returning whether or not ANY matches occurred *//* ARGUMENTS : a pointer to the time-string *//*************************************************************************/int validtime(char *ptr){ char *nextptr; int good; while (1) { nextptr = strchr(ptr, '|'); if (strchr(ptr, '|') == NULL) return (parsetime(ptr)); *nextptr = '\0'; good = parsetime(ptr); /* gotta restore the | or things get skipped! */ *nextptr++ = '|'; if (good) return (1); ptr = nextptr; }}/*************************************************************************//* FUNCTION : hostmatch *//* PURPOSE : Match remote hostname or address against a glob string *//* ARGUMENTS : The string to match *//* RETURNS : 0 if no match, 1 if a match occurs *//*************************************************************************/int hostmatch(char *addr, char *remoteaddr, char *remotehost){ FILE *incfile; char *ptr; int found = 1; int not_found = 0; int match = 0; int i, a[4], m[4], r[4], cidr; if (addr == NULL) return (0); if (*addr == '!') { found = 0; not_found = 1; addr++; } if (sscanf(addr, "%d.%d.%d.%d/%d", a, a + 1, a + 2, a + 3, &cidr) == 5) { m[0] = 0; m[1] = 0; m[2] = 0; m[3] = 0; if (cidr < 0) cidr = 0; else if (cidr > 32) cidr = 32; for (i = 0; cidr > 8; i++) { m[i] = 255; cidr -= 8; } switch (cidr) { case 8: m[i] += 1; case 7: m[i] += 2; case 6: m[i] += 4; case 5: m[i] += 8; case 4: m[i] += 16; case 3: m[i] += 32; case 2: m[i] += 64; case 1: m[i] += 128; } sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3); for (i = 0; i < 4; i++) if ((a[i] & m[i]) != (r[i] & m[i])) return not_found; return found; } else if (sscanf(addr, "%d.%d.%d.%d:%d.%d.%d.%d", a, a + 1, a + 2, a + 3, m, m + 1, m + 2, m + 3) == 8) { sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3); for (i = 0; i < 4; i++) if ((a[i] & m[i]) != (r[i] & m[i])) return not_found; return found; } else if (sscanf(addr, "%d.%d.%d.%d", a, a + 1, a + 2, a + 3) == 4) { sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3); for (i = 0; i < 4; i++) if (a[i] != r[i]) return not_found; return found; } else if (sscanf(addr, "%d.%d.%d.*", a, a + 1, a + 2) == 3) { sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3); for (i = 0; i < 3; i++) if (a[i] != r[i]) return not_found; return found; } else if (sscanf(addr, "%d.%d.*.*", a, a + 1) == 2) { sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3); for (i = 0; i < 2; i++) if (a[i] != r[i]) return not_found; return found; } else if (sscanf(addr, "%d.*.*.*", a) == 1) { sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3); for (i = 0; i < 1; i++) if (a[i] != r[i]) return not_found; return found; } else if (*addr == '/') { /* * read addrglobs from named path using similar format as addrglobs * in access file */ if ((incfile = fopen(addr, "r")) == NULL) { if (errno != ENOENT) syslog(LOG_ERR, "cannot open addrglob file %s: %m", addr); return (0); } while (!match && (fgets(incline, MAXLINE, incfile) != NULL)) { ptr = strtok(incline, " \t\n"); if (ptr && hostmatch(ptr, remoteaddr, remotehost)) match = 1; while (!match && ((ptr = strtok(NULL, " \t\n")) != NULL)) { if (ptr && hostmatch(ptr, remoteaddr, remotehost)) match = 1; } } fclose(incfile); return (match ? found : not_found); } else { /* match a hostname or hostname glob */ match = !wu_fnmatch(addr, remotehost, FNM_CASEFOLD); return (match ? found : not_found); }}/*************************************************************************//* FUNCTION : acl_guestgroup *//* PURPOSE : If the real user is a member of any of the listed groups, *//* return 1. Otherwise return 0. *//* ARGUMENTS : pw, a pointer to the passwd struct for the user *//*************************************************************************/int acl_guestgroup(struct passwd *pw){ struct aclmember *entry = NULL; struct group *grp; int which; char **member; /* * guestuser <name> [<name> ...] * * If name begins with '%' treat as numeric. * Numeric names may be ranges. * %<uid> A single numeric UID * %<uid>+ All UIDs greater or equal to UID * %<uid>- All UIDs greater or equal to UID * %-<uid> All UIDs less or equal to UID * %<uid>-<uid> All UIDs between the two (inclusive) * * All UIDs */ while (getaclentry("guestuser", &entry)) { for (which = 0; (which < MAXARGS) && ARG[which]; which++) { if (!strcmp(ARG[which], "*")) return (1); if (ARG[which][0] == '%') { char *ptr = strchr(ARG[which] + 1, '-'); if (!ptr) { ptr = strchr(ARG[which] + 1, '+'); if (!ptr) { if (pw->pw_uid == strtoul(ARG[which] + 1, NULL, 0)) return (1); } else { *ptr++ = '\0'; if ((ARG[which][1] == '\0') || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) { *--ptr = '+'; return (1); } *--ptr = '+'; } } else { *ptr++ = '\0'; if (((ARG[which][1] == '\0') || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) && ((*ptr == '\0') || (pw->pw_uid <= strtoul(ptr, NULL, 0)))) { *--ptr = '-'; return (1); } *--ptr = '-'; } } else {#ifdef OTHER_PASSWD struct passwd *g_pw = bero_getpwnam(ARG[which], _path_passwd);#else struct passwd *g_pw = getpwnam(ARG[which]);#endif if (g_pw && (g_pw->pw_uid == pw->pw_uid)) return (1); } } } /* * guestgroup <group> [<group> ...] * * If group begins with '%' treat as numeric. * Numeric groups may be ranges. * %<gid> A single GID * %<gid>+ All GIDs greater or equal to GID * %<gid>- All GIDs greater or equal to GID * %-<gid> All GIDs less or equal to GID * %<gid>-<gid> All GIDs between the two (inclusive) * * All GIDs */ while (getaclentry("guestgroup", &entry)) { for (which = 0; (which < MAXARGS) && ARG[which]; which++) { if (!strcmp(ARG[which], "*")) return (1); if (ARG[which][0] == '%') { char *ptr = strchr(ARG[which] + 1, '-'); if (!ptr) { ptr = strchr(ARG[which] + 1, '+'); if (!ptr) { if (pw->pw_gid == strtoul(ARG[which] + 1, NULL, 0)) return (1); } else { *ptr++ = '\0'; if ((ARG[which][1] == '\0') || (pw->pw_gid >= strtoul(ARG[which] + 1, NULL, 0))) { *--ptr = '+'; return (1); } *--ptr = '+'; } } else { *ptr++ = '\0'; if (((ARG[which][1] == '\0') || (pw->pw_gid >= strtoul(ARG[which] + 1, NULL, 0))) && ((*ptr == '\0') || (pw->pw_gid <= strtoul(ptr, NULL, 0)))) { *--ptr = '-'; return (1); } *--ptr = '-'; } } else { if ((grp = getgrnam(ARG[which]))) { if (grp->gr_gid == pw->pw_gid) return (1); for (member = grp->gr_mem; *member; member++) if (!strcasecmp(*member, pw->pw_name)) return (1); } } } } return (0);}int acl_realgroup(struct passwd *pw){ struct aclmember *entry = NULL; struct group *grp; int which; char **member; /* * realuser <name> [<name> ...] * * If name begins with '%' treat as numeric. * Numeric names may be ranges. * %<uid> A single numeric UID * %<uid>+ All UIDs greater or equal to UID * %<uid>- All UIDs greater or equal to UID * %-<uid> All UIDs less or equal to UID * %<uid>-<uid> All UIDs between the two (inclusive) * * All UIDs */ while (getaclentry("realuser", &entry)) { for (which = 0; (which < MAXARGS) && ARG[which]; which++) { if (!strcmp(ARG[which], "*")) return (1); if (ARG[which][0] == '%') { char *ptr = strchr(ARG[which] + 1, '-'); if (!ptr) { ptr = strchr(ARG[which] + 1, '+'); if (!ptr) { if (pw->pw_uid == strtoul(ARG[which] + 1, NULL, 0)) return (1); } else { *ptr++ = '\0'; if ((ARG[which][1] == '\0') || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) { *--ptr = '+'; return (1); } *--ptr = '+'; } } else { *ptr++ = '\0'; if (((ARG[which][1] == '\0') || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) && ((*ptr == '\0') || (pw->pw_uid <= strtoul(ptr, NULL, 0)))) { *--ptr = '-'; return (1); } *--ptr = '-'; } } else {#ifdef OTHER_PASSWD struct passwd *g_pw = bero_getpwnam(ARG[which], _path_passwd);#else struct passwd *g_pw = getpwnam(ARG[which]);#endif if (g_pw && (g_pw->pw_uid == pw->pw_uid)) return (1); } } } /* * realgroup <group> [<group> ...] * * If group begins with '%' treat as numeric. * Numeric groups may be ranges.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -