xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/in.ftpd/access.c (revision 0:68f95e015346)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /****************************************************************************
9 
10   Copyright (c) 1999,2000 WU-FTPD Development Group.
11   All rights reserved.
12 
13   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
14     The Regents of the University of California.
15   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
16   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
17   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
18   Portions Copyright (c) 1998 Sendmail, Inc.
19   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
20   Portions Copyright (c) 1997 by Stan Barber.
21   Portions Copyright (c) 1997 by Kent Landfield.
22   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
23     Free Software Foundation, Inc.
24 
25   Use and distribution of this software and its source code are governed
26   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
27 
28   If you did not receive a copy of the license, it may be obtained online
29   at http://www.wu-ftpd.org/license.html.
30 
31   $Id: access.c,v 1.30 2000/07/01 18:17:38 wuftpd Exp $
32 
33 ****************************************************************************/
34 #include "config.h"
35 
36 #include <stdio.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <stdlib.h>
40 
41 #ifdef HAVE_SYS_SYSLOG_H
42 #include <sys/syslog.h>
43 #endif
44 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
45 #include <syslog.h>
46 #endif
47 
48 #ifdef TIME_WITH_SYS_TIME
49 #include <time.h>
50 #include <sys/time.h>
51 #elif defined(HAVE_SYS_TIME_H)
52 #include <sys/time.h>
53 #else
54 #include <time.h>
55 #endif
56 
57 #include <ctype.h>
58 #include <pwd.h>
59 #include <grp.h>
60 #include <limits.h>
61 
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <sys/file.h>
65 #include <sys/param.h>
66 
67 #ifdef HAVE_PATHS_H
68 #include <paths.h>
69 #endif
70 
71 #include "pathnames.h"
72 #include "extensions.h"
73 #include "proto.h"
74 
75 #if defined(HAVE_FCNTL_H)
76 #include <fcntl.h>
77 #endif
78 
79 #ifdef OTHER_PASSWD
80 #include "getpwnam.h"
81 extern char _path_passwd[];
82 #ifdef SHADOW_PASSWORD
83 extern char _path_shadow[];
84 #endif
85 #endif
86 
87 #if defined(USE_PAM) && defined(OTHER_PASSWD)
88 extern int use_pam;
89 #endif
90 
91 extern char remotehost[], remoteaddr[], *remoteident, *aclbuf;
92 extern int nameserved, anonymous, guest, TCPwindowsize, use_accessfile;
93 extern mode_t defumask;
94 char Shutdown[MAXPATHLEN];
95 int keepalive = 0;
96 #define MAXLINE	80
97 static char incline[MAXLINE];
98 static int pidfd = -1;
99 extern int Bypass_PID_Files;
100 
101 #ifndef HELP_CRACKERS
102 extern char DelayedMessageFile[];
103 #endif
104 
105 #include "wu_fnmatch.h"
106 
107 #define ACL_COUNT	0
108 #define ACL_JOIN	1
109 #define ACL_REMOVE	2
110 
111 /*************************************************************************/
112 /* FUNCTION  : parse_time                                                */
113 /* PURPOSE   : Check a single valid-time-string against the current time */
114 /*             and return whether or not a match occurs.                 */
115 /* ARGUMENTS : a pointer to the time-string                              */
116 /*************************************************************************/
117 
parsetime(char * whattime)118 int parsetime(char *whattime)
119 {
120     static char *days[] =
121     {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Wk"};
122     time_t clock;
123     struct tm *curtime;
124     int wday, start, stop, ltime, validday, loop, match;
125 
126     (void) time(&clock);
127     curtime = localtime(&clock);
128     wday = curtime->tm_wday;
129     validday = 0;
130     match = 1;
131 
132     while (match && isalpha(*whattime) && isupper(*whattime)) {
133 	match = 0;
134 	for (loop = 0; loop < 8; loop++) {
135 	    if (strncmp(days[loop], whattime, 2) == 0) {
136 		whattime += 2;
137 		match = 1;
138 		if ((wday == loop) || ((loop == 7) && wday && (wday < 6))) {
139 		    validday = 1;
140 		}
141 	    }
142 	}
143     }
144 
145     if (!validday) {
146 	if (strncmp(whattime, "Any", 3) == 0) {
147 	    validday = 1;
148 	    whattime += 3;
149 	}
150 	else
151 	    return (0);
152     }
153 
154     if (sscanf(whattime, "%d-%d", &start, &stop) == 2) {
155 	ltime = curtime->tm_min + 100 * curtime->tm_hour;
156 	if ((start < stop) && ((ltime >= start) && ltime < stop))
157 	    return (1);
158 	if ((start > stop) && ((ltime >= start) || ltime < stop))
159 	    return (1);
160     }
161     else
162 	return (1);
163 
164     return (0);
165 }
166 
167 /*************************************************************************/
168 /* FUNCTION  : validtime                                                 */
169 /* PURPOSE   : Break apart a set of valid time-strings and pass them to  */
170 /*             parse_time, returning whether or not ANY matches occurred */
171 /* ARGUMENTS : a pointer to the time-string                              */
172 /*************************************************************************/
173 
validtime(char * ptr)174 int validtime(char *ptr)
175 {
176     char *nextptr;
177     int good;
178 
179     while (1) {
180 	nextptr = strchr(ptr, '|');
181 	if (strchr(ptr, '|') == NULL)
182 	    return (parsetime(ptr));
183 	*nextptr = '\0';
184 	good = parsetime(ptr);
185 	/* gotta restore the | or things get skipped! */
186 	*nextptr++ = '|';
187 	if (good)
188 	    return (1);
189 	ptr = nextptr;
190     }
191 }
192 
193 #ifdef INET6
194 /*************************************************************************/
195 /* FUNCTION  : ipv6str                                                   */
196 /* PURPOSE   : Convert an IPv6 address string with optional /CIDR suffix */
197 /*             into an IPv6 address and a CIDR, which are returned in    */
198 /*             the arguments pointed to by in6p and cidrp.               */
199 /* ARGUMENTS : The IPv6 address string and pointers to in6_addr and CIDR */
200 /* RETURNS   : 1 if addr is an IPv6 address string, 0 if not             */
201 /*************************************************************************/
202 
ipv6str(char * addr,struct in6_addr * in6p,int * cidrp)203 static int ipv6str(char *addr, struct in6_addr *in6p, int *cidrp)
204 {
205     int cidr = 128;	/* IPv6 addresses are 128-bits long */
206     char *ptr;
207 
208     if ((ptr = strstr(addr, "/")))
209 	*ptr = '\0';
210 
211     if (inet_pton(AF_INET6, addr, in6p) != 1) {
212 	if (ptr)
213 	    *ptr = '/';
214 	return 0;
215     }
216 
217     if (ptr) {
218 	*ptr++ = '/';
219 	cidr = atoi(ptr);
220 	if (cidr < 0)
221 	    cidr = 0;
222 	else if (cidr > 128)
223 	    cidr = 128;
224     }
225     *cidrp = cidr;
226     return 1;
227 }
228 #endif
229 
230 /*************************************************************************/
231 /* FUNCTION  : hostmatch                                                 */
232 /* PURPOSE   : Match remote hostname or address against a glob string    */
233 /* ARGUMENTS : The string to match, remote address, remote hostname      */
234 /* RETURNS   : 0 if no match, 1 if a match occurs                        */
235 /*************************************************************************/
236 
hostmatch(char * addr,char * remoteaddr,char * remotehost)237 int hostmatch(char *addr, char *remoteaddr, char *remotehost)
238 {
239     FILE *incfile;
240     char *ptr, junk, s[4][4];
241     int found = 1;
242     int not_found = 0;
243     int match = 0;
244     int i, a[4], m[4], r[4], cidr;
245 #ifdef INET6
246     struct in6_addr addr_in6;
247 #endif
248 
249     if (addr == NULL)
250 	return (0);
251 
252     if (*addr == '!') {
253 	found = 0;
254 	not_found = 1;
255 	addr++;
256     }
257 
258     if (sscanf(addr, "%d.%d.%d.%d/%d", a, a + 1, a + 2, a + 3, &cidr) == 5) {
259 	m[0] = 0;
260 	m[1] = 0;
261 	m[2] = 0;
262 	m[3] = 0;
263 	if (cidr < 0)
264 	    cidr = 0;
265 	else if (cidr > 32)
266 	    cidr = 32;
267 	for (i = 0; cidr > 8; i++) {
268 	    m[i] = 255;
269 	    cidr -= 8;
270 	}
271 	switch (cidr) {
272 	case 8:
273 	    m[i] += 1;
274 	case 7:
275 	    m[i] += 2;
276 	case 6:
277 	    m[i] += 4;
278 	case 5:
279 	    m[i] += 8;
280 	case 4:
281 	    m[i] += 16;
282 	case 3:
283 	    m[i] += 32;
284 	case 2:
285 	    m[i] += 64;
286 	case 1:
287 	    m[i] += 128;
288 	}
289 	/* make sure remoteaddr is an IPv4 address */
290 	if (sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3) != 4)
291 	    return not_found;
292 	for (i = 0; i < 4; i++)
293 	    if ((a[i] & m[i]) != (r[i] & m[i]))
294 		return not_found;
295 	return found;
296     }
297     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) {
298 	/* make sure remoteaddr is an IPv4 address */
299 	if (sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3) != 4)
300 	    return not_found;
301 	for (i = 0; i < 4; i++)
302 	    if ((a[i] & m[i]) != (r[i] & m[i]))
303 		return not_found;
304 	return found;
305     }
306     else if (sscanf(addr, "%3[0-9*].%3[0-9*].%3[0-9*].%3[0-9*]%c",
307 		    s[0], s[1], s[2], s[3], &junk) == 4 &&
308 	    (!strcmp(s[0],"*") || !strchr(s[0],'*')) &&
309 	    (!strcmp(s[1],"*") || !strchr(s[1],'*')) &&
310 	    (!strcmp(s[2],"*") || !strchr(s[2],'*')) &&
311 	    (!strcmp(s[3],"*") || !strchr(s[3],'*'))  ) {
312 	/* make sure remoteaddr is an IPv4 address */
313 	if (sscanf(remoteaddr, "%d.%d.%d.%d", r, r + 1, r + 2, r + 3) != 4)
314 	    return not_found;
315 	for (i = 0; i < 4; i++)
316 	    if ( (strcmp(s[i],"*")) && (atoi(s[i]) != r[i]) )
317 		return not_found;
318 	return found;
319     }
320 #ifdef INET6
321     else if (ipv6str(addr, &addr_in6, &cidr)) {
322 	struct in6_addr rem_in6;
323 	uint32_t addr32[4], rem32[4];
324 	int bitstozero;
325 
326 	if (inet_pton6(remoteaddr, &rem_in6) != 1)
327 	    return not_found;
328 
329 	memcpy(addr32, addr_in6.s6_addr, sizeof(addr32));
330 	memcpy(rem32, rem_in6.s6_addr, sizeof(rem32));
331 
332 	/* IPv6 addresses are 128-bits long */
333 	bitstozero = 128 - cidr;
334 
335 	/* zero bits starting with the least significant */
336 	for (i = 3; (bitstozero > 0) && (i >= 0); i--, bitstozero -= 32) {
337 	    if (bitstozero >= 32)
338 		addr32[i] = rem32[i] = 0;
339 	    else {
340 		addr32[i] = (ntohl(addr32[i]) >> bitstozero) << bitstozero;
341 		rem32[i] = (ntohl(rem32[i]) >> bitstozero) << bitstozero;
342 	    }
343 	}
344 	if (memcmp(addr32, rem32, sizeof(addr32)))
345 	    return not_found;
346 	return found;
347     }
348 #endif
349     else if (*addr == '/') {
350 	/*
351 	 * read addrglobs from named path using similar format as addrglobs
352 	 * in access file
353 	 */
354 	if ((incfile = fopen(addr, "r")) == NULL) {
355 	    if (errno != ENOENT)
356 		syslog(LOG_ERR,
357 		       "cannot open addrglob file %s: %m", addr);
358 	    return (0);
359 	}
360 
361 	while (!match && (fgets(incline, MAXLINE, incfile) != NULL)) {
362 	    ptr = strtok(incline, " \t\n");
363 	    if (ptr && hostmatch(ptr, remoteaddr, remotehost))
364 		match = 1;
365 	    while (!match && ((ptr = strtok(NULL, " \t\n")) != NULL)) {
366 		if (ptr && hostmatch(ptr, remoteaddr, remotehost))
367 		    match = 1;
368 	    }
369 	}
370 	fclose(incfile);
371 	return (match ? found : not_found);
372     }
373     else {			/* match a hostname or hostname glob */
374 	match = (!wu_fnmatch(addr, remotehost, FNM_CASEFOLD)) ||
375 		(!wu_fnmatch(addr, remoteaddr, 0));
376 	return (match ? found : not_found);
377     }
378 }
379 
380 /*************************************************************************/
381 /* FUNCTION  : acl_guestgroup                                            */
382 /* PURPOSE   : If the real user is a member of any of the listed groups, */
383 /*             return 1.  Otherwise return 0.                            */
384 /* ARGUMENTS : pw, a pointer to the passwd struct for the user           */
385 /*************************************************************************/
386 
acl_guestgroup(struct passwd * pw)387 int acl_guestgroup(struct passwd *pw)
388 {
389     /*
390      * guestuser <name> [<name> ...]
391      *
392      * If name begins with '%' treat as numeric.
393      * Numeric names may be ranges.
394      *   %<uid>       A single numeric UID
395      *   %<uid>+      All UIDs greater or equal to UID
396      *   %<uid>-      All UIDs greater or equal to UID
397      *   %-<uid>      All UIDs less or equal to UID
398      *   %<uid>-<uid> All UIDs between the two (inclusive)
399      *   *            All UIDs
400      */
401     if (uid_match("guestuser", pw->pw_uid))
402 	return (1);
403 
404     /*
405      * guestgroup <group> [<group> ...]
406      *
407      * If group begins with '%' treat as numeric.
408      * Numeric groups may be ranges.
409      *   %<gid>       A single GID
410      *   %<gid>+      All GIDs greater or equal to GID
411      *   %<gid>-      All GIDs greater or equal to GID
412      *   %-<gid>      All GIDs less or equal to GID
413      *   %<gid>-<gid> All GIDs between the two (inclusive)
414      *   *            All GIDs
415      */
416     if (gid_match("guestgroup", pw->pw_gid, pw->pw_name))
417 	return (1);
418 
419     return (0);
420 }
421 
acl_realgroup(struct passwd * pw)422 int acl_realgroup(struct passwd *pw)
423 {
424     /*
425      * realuser <name> [<name> ...]
426      *
427      * If name begins with '%' treat as numeric.
428      * Numeric names may be ranges.
429      *   %<uid>       A single numeric UID
430      *   %<uid>+      All UIDs greater or equal to UID
431      *   %<uid>-      All UIDs greater or equal to UID
432      *   %-<uid>      All UIDs less or equal to UID
433      *   %<uid>-<uid> All UIDs between the two (inclusive)
434      *   *            All UIDs
435      */
436     if (uid_match("realuser", pw->pw_uid))
437 	return (1);
438 
439     /*
440      * realgroup <group> [<group> ...]
441      *
442      * If group begins with '%' treat as numeric.
443      * Numeric groups may be ranges.
444      *   %<gid>       A single GID
445      *   %<gid>+      All GIDs greater or equal to GID
446      *   %<gid>-      All GIDs greater or equal to GID
447      *   %-<gid>      All GIDs less or equal to GID
448      *   %<gid>-<gid> All GIDs between the two (inclusive)
449      *   *            All GIDs
450      */
451     if (gid_match("realgroup", pw->pw_gid, pw->pw_name))
452 	return (1);
453 
454     return (0);
455 }
456 
457 /*************************************************************************/
458 /* FUNCTION  : acl_autogroup                                             */
459 /* PURPOSE   : If the guest user is a member of any of the classes in    */
460 /*             the autogroup comment, cause a setegid() to the specified */
461 /*             group.                                                    */
462 /* ARGUMENTS : pw, a pointer to the passwd struct for the user           */
463 /*************************************************************************/
464 
acl_autogroup(struct passwd * pw)465 void acl_autogroup(struct passwd *pw)
466 {
467     char class[BUFSIZ];
468 
469     struct aclmember *entry = NULL;
470     struct group *grp;
471     int which;
472 
473     (void) acl_getclass(class);
474 
475     /* autogroup <group> <class> [<class> ...] */
476     while (getaclentry("autogroup", &entry)) {
477 	if (!ARG0 || !ARG1)
478 	    continue;
479 	for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
480 	    if (!strcasecmp(ARG[which], class)) {
481 		if (ARG0[0] == '%')
482 		    pw->pw_gid = atoi(ARG0 + 1);
483 		else {
484 		    if ((grp = getgrnam(ARG0)))
485 			pw->pw_gid = grp->gr_gid;
486 		    else
487 			syslog(LOG_ERR, "autogroup: set group %s not found", ARG0);
488 		    endgrent();
489 		}
490 		return;
491 	    }
492 	}
493     }
494 }
495 
496 /*************************************************************************/
497 /* FUNCTION  : acl_setfunctions                                          */
498 /* PURPOSE   : Scan the ACL buffer and determine what logging to perform */
499 /*             for this user, and whether or not user is allowed to use  */
500 /*             the automatic TAR and COMPRESS functions.  Also, set the  */
501 /*             current process priority of this copy of the ftpd server  */
502 /*             to a `nice' value value if this user is a member of a     */
503 /*             group which the ftpaccess file says should be nice'd.     */
504 /* ARGUMENTS : none                                                      */
505 /*************************************************************************/
506 
acl_setfunctions(void)507 void acl_setfunctions(void)
508 {
509     char class[BUFSIZ];
510 
511     extern int log_incoming_xfers, log_outbound_xfers, mangleopts, log_commands,
512         log_security, syslogmsg, lgi_failure_threshold;
513 
514     struct aclmember *entry = NULL;
515 
516     int l_compress, l_tar, inbound = 0, outbound = 0, which, set;
517 
518     log_security = 0;
519 
520     /* Initialize to the logging value specified on the command line, can't
521        just use the current value as it may have been set by a previous call. */
522     log_incoming_xfers = (log_incoming_xfers & 2) ? 3 : 0;
523     log_outbound_xfers = (log_outbound_xfers & 2) ? 3 : 0;
524     log_commands = (log_commands & 2) ? 3 : 0;
525 
526     memset((void *) &class[0], 0, sizeof(class));
527 
528     (void) acl_getclass(class);
529 
530     entry = (struct aclmember *) NULL;
531     if (getaclentry("loginfails", &entry) && ARG0 != NULL) {
532 	lgi_failure_threshold = atoi(ARG0);
533     }
534 #ifndef NO_PRIVATE
535     entry = (struct aclmember *) NULL;
536     if (getaclentry("private", &entry) && ARG0 != NULL)
537 	if (!strcasecmp(ARG0, "yes"))
538 	    priv_setup(_path_private);
539 #endif /* !NO_PRIVATE */
540 
541     entry = (struct aclmember *) NULL;
542     set = 0;
543     while (!set && getaclentry("compress", &entry)) {
544 	if (!ARG0)
545 	    continue;
546 	l_compress = 0;
547 	if (!strcasecmp(ARG0, "yes"))
548 	    l_compress = 1;
549 	for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
550 	    if (!wu_fnmatch(ARG[which], class, FNM_CASEFOLD)) {
551 		mangleopts |= l_compress * (O_COMPRESS | O_UNCOMPRESS);
552 		set = 1;
553 	    }
554 	}
555     }
556 
557     entry = (struct aclmember *) NULL;
558     set = 0;
559     while (!set && getaclentry("tar", &entry)) {
560 	if (!ARG0)
561 	    continue;
562 	l_tar = 0;
563 	if (!strcasecmp(ARG0, "yes"))
564 	    l_tar = 1;
565 	for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
566 	    if (!wu_fnmatch(ARG[which], class, FNM_CASEFOLD)) {
567 		mangleopts |= l_tar * O_TAR;
568 		set = 1;
569 	    }
570 	}
571     }
572 
573     /* plan on expanding command syntax to include classes for each of these */
574 
575     entry = (struct aclmember *) NULL;
576     while (getaclentry("log", &entry)) {
577 	if (!ARG0)
578 	    continue;
579 	if (!strcasecmp(ARG0, "commands")) {
580 	    if (!ARG1)
581 		continue;
582 	    if (anonymous && strcasestr(ARG1, "anonymous"))
583 		log_commands |= 1;
584 	    if (guest && strcasestr(ARG1, "guest"))
585 		log_commands |= 1;
586 	    if (!guest && !anonymous && strcasestr(ARG1, "real"))
587 		log_commands |= 1;
588 	}
589 	if (!strcasecmp(ARG0, "transfers")) {
590 	    if (!ARG1 || !ARG2)
591 		continue;
592 	    set = 0;
593 	    if (strcasestr(ARG1, "anonymous") && anonymous)
594 		set = 1;
595 	    if (strcasestr(ARG1, "guest") && guest)
596 		set = 1;
597 	    if (strcasestr(ARG1, "real") && !guest && !anonymous)
598 		set = 1;
599 	    if (strcasestr(ARG2, "inbound"))
600 		inbound = 1;
601 	    if (strcasestr(ARG2, "outbound"))
602 		outbound = 1;
603 	    if (set)
604 		log_incoming_xfers |= inbound;
605 	    if (set)
606 		log_outbound_xfers |= outbound;
607 	}
608 	if (!strcasecmp(ARG0, "security")) {
609 	    if (!ARG1)
610 		continue;
611 	    if (strcasestr(ARG1, "anonymous") && anonymous)
612 		log_security = 1;
613 	    if (strcasestr(ARG1, "guest") && guest)
614 		log_security = 1;
615 	    if (strcasestr(ARG1, "real") && !guest && !anonymous)
616 		log_security = 1;
617 	}
618 	if (!strcasecmp(ARG0, "syslog"))
619 	    syslogmsg = 1;
620 	if (!strcasecmp(ARG0, "xferlog"))
621 	    syslogmsg = 0;
622 	if (!strcasecmp(ARG0, "syslog+xferlog")
623 	    || !strcasecmp(ARG0, "xferlog+syslog"))
624 	    syslogmsg = 2;
625     }
626 }
627 
628 /*************************************************************************/
629 /* FUNCTION  : acl_getclass                                              */
630 /* PURPOSE   : Scan the ACL buffer and determine what class user is in   */
631 /* ARGUMENTS : pointer to buffer to class name, pointer to ACL buffer    */
632 /*************************************************************************/
633 
acl_getclass(char * classbuf)634 int acl_getclass(char *classbuf)
635 {
636     int which;
637     struct aclmember *entry = NULL;
638 
639     while (getaclentry("class", &entry)) {
640 	if (ARG0)
641 	    strlcpy(classbuf, ARG0, BUFSIZ);
642 
643 	for (which = 2; (which < MAXARGS) && ARG[which]; which++) {
644 	    if (anonymous && strcasestr(ARG1, "anonymous") &&
645 		hostmatch(ARG[which], remoteaddr, remotehost))
646 		return (1);
647 
648 	    if (guest && strcasestr(ARG1, "guest") && hostmatch(ARG[which], remoteaddr, remotehost))
649 		return (1);
650 
651 	    if (!guest && !anonymous && strcasestr(ARG1, "real") &&
652 		hostmatch(ARG[which], remoteaddr, remotehost))
653 		return (1);
654 	}
655     }
656 
657     *classbuf = (char) NULL;
658     return (0);
659 
660 }
661 
662 /*************************************************************************/
663 /* FUNCTION  : acl_getlimit                                              */
664 /* PURPOSE   : Scan the ACL buffer and determine what limit applies to   */
665 /*             the user                                                  */
666 /* ARGUMENTS : pointer class name, pointer to ACL buffer                 */
667 /*************************************************************************/
668 
acl_getlimit(char * class,char * msgpathbuf)669 int acl_getlimit(char *class, char *msgpathbuf)
670 {
671     int limit;
672     struct aclmember *entry = NULL;
673 
674     if (msgpathbuf)
675 	*msgpathbuf = '\0';
676 
677     /* limit <class> <n> <times> [<message_file>] */
678     while (getaclentry("limit", &entry)) {
679 	if (!ARG0 || !ARG1 || !ARG2)
680 	    continue;
681 	if (!strcasecmp(class, ARG0)) {
682 	    limit = atoi(ARG1);
683 	    if (validtime(ARG2)) {
684 		if (ARG3 && msgpathbuf)
685 		    strcpy(msgpathbuf, ARG3);
686 		return (limit);
687 	    }
688 	}
689     }
690     return (-1);
691 }
692 
693 /*************************************************************************/
694 /* FUNCTION  : acl_getnice                                               */
695 /* PURPOSE   : Scan the ACL buffer and determine what nice value applies */
696 /*             to the user                                               */
697 /* ARGUMENTS : pointer class name                                        */
698 /*************************************************************************/
699 
acl_getnice(char * class)700 int acl_getnice(char *class)
701 {
702     int nice_delta_for_class_found = 0;
703     int nice_delta = 0;
704     int default_nice_delta = 0;
705 
706     struct aclmember *entry = NULL;
707 
708     /* nice <nice_delta> [<class>] */
709     while (getaclentry("nice", &entry)) {
710 	if (!ARG0)
711 	    continue;
712 	if (!ARG1)
713 	    default_nice_delta = atoi(ARG0);
714 	else if (!strcasecmp(class, ARG1)) {
715 	    nice_delta_for_class_found = 1;
716 	    nice_delta = atoi(ARG0);
717 	}
718     }
719     if (!nice_delta_for_class_found)
720 	nice_delta = default_nice_delta;
721     return nice_delta;
722 }
723 
724 
725 /*************************************************************************/
726 /* FUNCTION  : acl_getdefumask                                           */
727 /* PURPOSE   : Scan the ACL buffer to determine what umask value applies */
728 /*             to the user                                               */
729 /* ARGUMENTS : pointer to class name                                     */
730 /*************************************************************************/
731 
acl_getdefumask(char * class)732 void acl_getdefumask(char *class)
733 {
734     struct aclmember *entry = NULL;
735     char *ptr;
736     unsigned int val;
737 
738     /* defumask <umask> [<class>] */
739     while (getaclentry("defumask", &entry)) {
740 	if (!ARG0)
741 	    continue;
742 	if (!ARG1 || !strcasecmp(class, ARG1)) {
743 	    ptr = ARG0;
744 	    val = 0;
745 	    while (*ptr && *ptr >= '0' && *ptr <= '7')
746 		val = val * 8 + *ptr++ - '0';
747 	    if (!*ptr && val <= 0777) {
748 		defumask = val;
749 		if (ARG1)
750 		    break;
751 	    }
752 	    else
753 		syslog(LOG_WARNING, "bad umask in %s ignored: defumask %s",
754 		       _path_ftpaccess, ARG0);
755 	}
756     }
757     umask(defumask);
758 }
759 
760 /*************************************************************************/
761 /* FUNCTION  : acl_tcpwindow                                             */
762 /* PURPOSE   : Scan the ACL buffer and determine what TCP window size to */
763 /*             use based upon the class                                  */
764 /* ARGUMENTS : pointer to class name                                     */
765 /*************************************************************************/
766 
acl_tcpwindow(char * class)767 void acl_tcpwindow(char *class)
768 {
769     struct aclmember *entry = NULL;
770 
771     /* tcpwindow <size> [<class>] */
772     while (getaclentry("tcpwindow", &entry)) {
773 	if (!ARG0)
774 	    continue;
775 	if (!ARG1)
776 	    TCPwindowsize = strtoul(ARG0, NULL, 0);
777 	else if (!strcasecmp(class, ARG1)) {
778 	    TCPwindowsize = strtoul(ARG0, NULL, 0);
779 	    break;
780 	}
781     }
782 }
783 
784 /*************************************************************************/
785 /* FUNCTION  : acl_bufsize                                               */
786 /* PURPOSE   : Scan the ACL buffer and determine the send and receive    */
787 /*             buffer sizes to use                                       */
788 /* ARGUMENTS : None                                                      */
789 /*************************************************************************/
790 
acl_bufsize()791 static void acl_bufsize()
792 {
793     struct aclmember *entry;
794     extern size_t sendbufsz, recvbufsz;
795 
796     /* sendbuf <size> [<typelist>] */
797     entry = (struct aclmember *) NULL;
798     sendbufsz = 0;
799     while (getaclentry("sendbuf", &entry)) {
800 	if (!ARG0)
801 	    continue;
802 	if (!ARG1)
803 	    sendbufsz = strtoul(ARG0, NULL, 0);
804 	else if (type_match(ARG1)) {
805 	    sendbufsz = strtoul(ARG0, NULL, 0);
806 	    break;
807 	}
808     }
809 
810     /* recvbuf <size> [<typelist>] */
811     entry = (struct aclmember *) NULL;
812     recvbufsz = 0;
813     while (getaclentry("recvbuf", &entry)) {
814 	if (!ARG0)
815 	    continue;
816 	if (!ARG1)
817 	    recvbufsz = strtoul(ARG0, NULL, 0);
818 	else if (type_match(ARG1)) {
819 	    recvbufsz = strtoul(ARG0, NULL, 0);
820 	    break;
821 	}
822     }
823 }
824 
825 #ifdef TRANSFER_COUNT
826 #ifdef TRANSFER_LIMIT
827 
828 /*************************************************************************/
829 /* FUNCTION  : acl_filelimit                                             */
830 /* PURPOSE   : Scan the ACL buffer and determine what file limit to use  */
831 /*             based upon the class                                      */
832 /* ARGUMENTS : pointer to class name                                     */
833 /*************************************************************************/
834 
acl_filelimit(char * class)835 void acl_filelimit(char *class)
836 {
837     struct aclmember *entry = NULL;
838     int raw_in = 0;
839     int raw_out = 0;
840     int raw_total = 0;
841     int data_in = 0;
842     int data_out = 0;
843     int data_total = 0;
844     extern int file_limit_raw_in;
845     extern int file_limit_raw_out;
846     extern int file_limit_raw_total;
847     extern int file_limit_data_in;
848     extern int file_limit_data_out;
849     extern int file_limit_data_total;
850 
851     /* file-limit [<raw>] <in|out|total> <count> [<class>] */
852     while (getaclentry("file-limit", &entry)) {
853 	if (!ARG0 || !ARG1)
854 	    continue;
855 	if (!strcasecmp(ARG0, "raw")) {
856 	    if (!ARG2)
857 		continue;
858 	    if (!strcasecmp(ARG1, "in")) {
859 		if (!ARG3) {
860 		    if (!raw_in)
861 			file_limit_raw_in = atoi(ARG2);
862 		}
863 		else if (!strcasecmp(class, ARG3)) {
864 		    raw_in = 1;
865 		    file_limit_raw_in = atoi(ARG2);
866 		}
867 	    }
868 	    else if (!strcasecmp(ARG1, "out")) {
869 		if (!ARG3) {
870 		    if (!raw_out)
871 			file_limit_raw_out = atoi(ARG2);
872 		}
873 		else if (!strcasecmp(class, ARG3)) {
874 		    raw_out = 1;
875 		    file_limit_raw_out = atoi(ARG2);
876 		}
877 	    }
878 	    else if (!strcasecmp(ARG1, "total")) {
879 		if (!ARG3) {
880 		    if (!raw_total)
881 			file_limit_raw_total = atoi(ARG2);
882 		}
883 		else if (!strcasecmp(class, ARG3)) {
884 		    raw_total = 1;
885 		    file_limit_raw_total = atoi(ARG2);
886 		}
887 	    }
888 	}
889 	else if (!strcasecmp(ARG0, "in")) {
890 	    if (!ARG2) {
891 		if (!data_in)
892 		    file_limit_data_in = atoi(ARG1);
893 	    }
894 	    else if (!strcasecmp(class, ARG2)) {
895 		data_in = 1;
896 		file_limit_data_in = atoi(ARG1);
897 	    }
898 	}
899 	else if (!strcasecmp(ARG0, "out")) {
900 	    if (!ARG2) {
901 		if (!data_out)
902 		    file_limit_data_out = atoi(ARG1);
903 	    }
904 	    else if (!strcasecmp(class, ARG2)) {
905 		data_out = 1;
906 		file_limit_data_out = atoi(ARG1);
907 	    }
908 	}
909 	else if (!strcasecmp(ARG0, "total")) {
910 	    if (!ARG2) {
911 		if (!data_total)
912 		    file_limit_data_total = atoi(ARG1);
913 	    }
914 	    else if (!strcasecmp(class, ARG2)) {
915 		data_total = 1;
916 		file_limit_data_total = atoi(ARG1);
917 	    }
918 	}
919     }
920 }
921 
922 /*************************************************************************/
923 /* FUNCTION  : acl_datalimit                                             */
924 /* PURPOSE   : Scan the ACL buffer and determine what data limit to use  */
925 /*             based upon the class                                      */
926 /* ARGUMENTS : pointer to class name                                     */
927 /*************************************************************************/
928 
acl_datalimit(char * class)929 void acl_datalimit(char *class)
930 {
931     struct aclmember *entry = NULL;
932     int raw_in = 0;
933     int raw_out = 0;
934     int raw_total = 0;
935     int data_in = 0;
936     int data_out = 0;
937     int data_total = 0;
938     extern off_t data_limit_raw_in;
939     extern off_t data_limit_raw_out;
940     extern off_t data_limit_raw_total;
941     extern off_t data_limit_data_in;
942     extern off_t data_limit_data_out;
943     extern off_t data_limit_data_total;
944 
945     /* data-limit [<raw>] <in|out|total> <count> [<class>] */
946     while (getaclentry("data-limit", &entry)) {
947 	if (!ARG0 || !ARG1)
948 	    continue;
949 	if (!strcasecmp(ARG0, "raw")) {
950 	    if (!ARG2)
951 		continue;
952 	    if (!strcasecmp(ARG1, "in")) {
953 		if (!ARG3) {
954 		    if (!raw_in)
955 			data_limit_raw_in = atoi(ARG2);
956 		}
957 		else if (!strcasecmp(class, ARG3)) {
958 		    raw_in = 1;
959 		    data_limit_raw_in = atoi(ARG2);
960 		}
961 	    }
962 	    else if (!strcasecmp(ARG1, "out")) {
963 		if (!ARG3) {
964 		    if (!raw_out)
965 			data_limit_raw_out = atoi(ARG2);
966 		}
967 		else if (!strcasecmp(class, ARG3)) {
968 		    raw_out = 1;
969 		    data_limit_raw_out = atoi(ARG2);
970 		}
971 	    }
972 	    else if (!strcasecmp(ARG1, "total")) {
973 		if (!ARG3) {
974 		    if (!raw_total)
975 			data_limit_raw_total = atoi(ARG2);
976 		}
977 		else if (!strcasecmp(class, ARG3)) {
978 		    raw_total = 1;
979 		    data_limit_raw_total = atoi(ARG2);
980 		}
981 	    }
982 	}
983 	else if (!strcasecmp(ARG0, "in")) {
984 	    if (!ARG2) {
985 		if (!data_in)
986 		    data_limit_data_in = atoi(ARG1);
987 	    }
988 	    else if (!strcasecmp(class, ARG2)) {
989 		data_in = 1;
990 		data_limit_data_in = atoi(ARG1);
991 	    }
992 	}
993 	else if (!strcasecmp(ARG0, "out")) {
994 	    if (!ARG2) {
995 		if (!data_out)
996 		    data_limit_data_out = atoi(ARG1);
997 	    }
998 	    else if (!strcasecmp(class, ARG2)) {
999 		data_out = 1;
1000 		data_limit_data_out = atoi(ARG1);
1001 	    }
1002 	}
1003 	else if (!strcasecmp(ARG0, "total")) {
1004 	    if (!ARG2) {
1005 		if (!data_total)
1006 		    data_limit_data_total = atoi(ARG1);
1007 	    }
1008 	    else if (!strcasecmp(class, ARG2)) {
1009 		data_total = 1;
1010 		data_limit_data_total = atoi(ARG1);
1011 	    }
1012 	}
1013     }
1014 }
1015 
1016 
1017 #ifdef RATIO
1018 
1019 /*************************************************************************/
1020 /* FUNCTION  : acl_downloadrate                                          */
1021 /* PURPOSE   : Scan the ACL buffer and determine what data limit to use  */
1022 /*             based upon the class                                      */
1023 /* ARGUMENTS : pointer to class name                                     */
1024 /*************************************************************************/
1025 
acl_downloadrate(char * class)1026 void acl_downloadrate(char *class)
1027 {
1028     struct aclmember *entry = NULL;
1029     extern int upload_download_rate;
1030     int which;
1031 
1032     /* ul-dl-rate <rate> [<class> ...] */
1033     while (getaclentry("ul-dl-rate", &entry)) {
1034 	if (!ARG0 )
1035 	    continue;
1036 
1037 	if (!ARG1) {
1038 	    upload_download_rate = atol(ARG0);
1039 	}
1040 	else {
1041 	    for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
1042 		if (!strcasecmp(ARG[which], class))
1043 		    upload_download_rate = atol(ARG0);
1044 	    }
1045 	}
1046 
1047     }
1048 }
1049 #endif /* RATIO */
1050 
1051 #endif
1052 #endif
1053 
1054 /*************************************************************************/
1055 /* FUNCTION  : acl_deny                                                  */
1056 /* PURPOSE   : Scan the ACL buffer and determine if access is denied.    */
1057 /* ARGUMENTS : Pointer to buffer into which the path of the message file */
1058 /*             is copied.                                                */
1059 /*************************************************************************/
1060 
acl_deny(char * msgpathbuf)1061 int acl_deny(char *msgpathbuf)
1062 {
1063     struct aclmember *entry = NULL;
1064 
1065     if (msgpathbuf)
1066 	*msgpathbuf = (char) NULL;
1067 
1068     /* deny <addrglob> [<message_file>] */
1069     while (getaclentry("deny", &entry)) {
1070 	if (!ARG0)
1071 	    continue;
1072 	if (strcasecmp(ARG0, "!nameserved") == 0) {
1073 	    if (!nameserved) {
1074 		if (ARG1)
1075 		    strcpy(msgpathbuf, entry->arg[1]);
1076 		return (1);
1077 	    }
1078 	}
1079 	else if (hostmatch(ARG0, remoteaddr, remotehost)) {
1080 	    if (ARG1)
1081 		strcpy(msgpathbuf, entry->arg[1]);
1082 	    return (1);
1083 	}
1084     }
1085     return (0);
1086 }
1087 
1088 /*************************************************************************/
1089 /* FUNCTION  : lock_fd                                                   */
1090 /* PURPOSE   : Lock a file.                                              */
1091 /* ARGUMENTS : File descriptor of file to lock.                          */
1092 /*************************************************************************/
1093 
lock_fd(int fd)1094 static void lock_fd(int fd)
1095 {
1096 #if !defined(HAVE_FLOCK)
1097     struct flock arg;
1098 #endif /* !defined(HAVE_FLOCK) */
1099 
1100 #if defined(HAVE_FLOCK)
1101     while (flock(fd, LOCK_EX)) {
1102 #  if !defined(NO_PID_SLEEP_MSGS)
1103 	syslog(LOG_ERR, "sleeping: flock of pid file failed: %m");
1104 #  endif /* !defined(NO_PID_SLEEP_MSGS) */
1105 #else /* !(defined(HAVE_FLOCK)) */
1106     arg.l_type = F_WRLCK;
1107     arg.l_whence = arg.l_start = arg.l_len = 0;
1108     while (-1 == fcntl(fd, F_SETLK, &arg)) {
1109 #  if !defined(NO_PID_SLEEP_MSGS)
1110 	syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %m");
1111 #  endif /* !defined(NO_PID_SLEEP_MSGS) */
1112 #endif /* !(defined(HAVE_FLOCK)) */
1113 	sleep(1);
1114     }
1115 }
1116 
1117 /*************************************************************************/
1118 /* FUNCTION  : unlock_fd                                                 */
1119 /* PURPOSE   : Unlock a file locked by lock_fd.                          */
1120 /* ARGUMENTS : File descriptor of file to unlock.                        */
1121 /*************************************************************************/
1122 
1123 static void unlock_fd(int fd)
1124 {
1125 #if !defined(HAVE_FLOCK)
1126     struct flock arg;
1127 #endif /* !defined(HAVE_FLOCK) */
1128 
1129 #if defined(HAVE_FLOCK)
1130     flock(fd, LOCK_UN);
1131 #else /* !(defined(HAVE_FLOCK)) */
1132     arg.l_type = F_UNLCK;
1133     arg.l_whence = arg.l_start = arg.l_len = 0;
1134     fcntl(fd, F_SETLK, &arg);
1135 #endif /* !(defined(HAVE_FLOCK)) */
1136 }
1137 
1138 /*************************************************************************/
1139 /* FUNCTION  : limit_op                                                  */
1140 /* PURPOSE   : Carry out the specified limit operation, returning the    */
1141 /*             number of users in the class or -1 on failure.            */
1142 /* ARGUMENTS : Operation (ACL_COUNT/ACL_JOIN/ACL_REMOVE), user limit     */
1143 /*************************************************************************/
1144 
1145 static int limit_op(int operation, int limit)
1146 {
1147     int i, j, n, count;
1148     int bit_changed, toomany, write_all_header;
1149     off_t offset;
1150     pid_t pid, procid;
1151     time_t now;
1152     struct pidfile_header hdr;
1153     unsigned char bits, buf[BUFSIZ];
1154 
1155     if (pidfd < 0)
1156 	return (-1);
1157 
1158     if (lseek(pidfd, (off_t)0, SEEK_SET) != 0)
1159 	return (-1);
1160 
1161     if (operation == ACL_COUNT) {
1162 	lock_fd(pidfd);
1163 	n = read(pidfd, (void *)&hdr.count, sizeof(hdr.count));
1164 	unlock_fd(pidfd);
1165 	if (n != sizeof(hdr.count))
1166 	    return (-1);
1167 	return (hdr.count);
1168     }
1169 
1170     toomany = 0;
1171     write_all_header = 0;
1172     lock_fd(pidfd);
1173     if (read(pidfd, (void *)&hdr, sizeof(hdr)) != sizeof(hdr)) {
1174 	hdr.count = 0;
1175 	hdr.last_checked = 0;
1176     }
1177     now = time(NULL);
1178 
1179     /* check bitmap accuracy and re-calculate the count every 15 minutes */
1180     if ((now >= (hdr.last_checked + (15 * 60))) || (now < hdr.last_checked)) {
1181 	count = 0;
1182 	procid = 0;
1183 	bit_changed = 0;
1184 	while ((n = read(pidfd, (void *)buf, sizeof(buf))) > 0) {
1185 	    for (i = 0; i < n; i++) {
1186 		if (buf[i] == 0) {
1187 		    procid += CHAR_BIT;
1188 		}
1189 		else {
1190 		    bits = 1;
1191 		    for (j = 0; j < CHAR_BIT; j++) {
1192 			if ((buf[i] & bits) != 0) {
1193 			    if (kill(procid, 0) == 0) {
1194 				count++;
1195 			    }
1196 			    else {
1197 				bit_changed = 1;
1198 				buf[i] &= ~bits;
1199 			    }
1200 			}
1201 			bits <<= 1;
1202 			procid++;
1203 		    }
1204 		}
1205 	    }
1206 	    if (bit_changed) {
1207 		lseek(pidfd, (off_t)-n, SEEK_CUR);
1208 		write(pidfd, (void *)buf, n);
1209 		bit_changed = 0;
1210 	    }
1211 	}
1212 	if (hdr.count != count) {
1213 	    syslog(LOG_INFO, "pid file header count (%d) corrected to %d",
1214 		   hdr.count, count);
1215 	    hdr.count = count;
1216 	}
1217 	hdr.last_checked = time(NULL);
1218 	write_all_header = 1;
1219     }
1220 
1221     /* limit set to -1 when no limit defined */
1222     if ((operation == ACL_JOIN) && (limit != -1) && (hdr.count >= limit)) {
1223 	/* return if no need to update the header */
1224 	if (write_all_header == 0) {
1225 	    unlock_fd(pidfd);
1226 	    return (-1);
1227 	}
1228 	toomany = 1;
1229     }
1230     else {
1231 	/* update the count */
1232 	if (operation == ACL_JOIN)
1233 	    hdr.count++;
1234 	else if (hdr.count > 0) /* ACL_REMOVE */
1235 	    hdr.count--;
1236     }
1237 
1238     /* update the header */
1239     lseek(pidfd, (off_t)0, SEEK_SET);
1240     if (write_all_header)
1241 	write(pidfd, (void *)&hdr, sizeof(hdr));
1242     else
1243 	write(pidfd, (void *)&hdr.count, sizeof(hdr.count));
1244 
1245     /* return if no need to update the bitmap */
1246     if (toomany) {
1247 	unlock_fd(pidfd);
1248 	return (-1);
1249     }
1250 
1251     /* update the bitmap entry for the process */
1252     pid = getpid();
1253     offset = (off_t)(sizeof(hdr) + (pid/CHAR_BIT));
1254     lseek(pidfd, offset, SEEK_SET);
1255     if (read(pidfd, (void *)&bits, sizeof(bits)) != sizeof(bits))
1256 	bits = 0;
1257     if (operation == ACL_JOIN)
1258 	bits |= (1 << (pid%CHAR_BIT));
1259     else /* ACL_REMOVE */
1260 	bits &= ~(1 << (pid%CHAR_BIT));
1261     lseek(pidfd, offset, SEEK_SET);
1262     write(pidfd, (void *)&bits, sizeof(bits));
1263     unlock_fd(pidfd);
1264     return (hdr.count);
1265 }
1266 
1267 /*************************************************************************/
1268 /* FUNCTION  : open_pidfile                                              */
1269 /* PURPOSE   : Return a file descriptor of an opened PID file.           */
1270 /* ARGUMENTS : Users class.                                              */
1271 /*************************************************************************/
1272 
1273 static int open_pidfile(char *class)
1274 {
1275     int fd;
1276     mode_t oldmask;
1277     char pidfile[MAXPATHLEN];
1278 
1279     snprintf(pidfile, sizeof(pidfile), _PATH_PIDNAMES, class);
1280     oldmask = umask(0);
1281     fd = open(pidfile, O_RDWR | O_CREAT, 0644);
1282     (void) umask(oldmask);
1283     if (fd < 0)
1284 	    syslog(LOG_ERR, "cannot open pid file %s: %m", pidfile);
1285     return (fd);
1286 }
1287 
1288 /*************************************************************************/
1289 /* FUNCTION  : acl_countusers                                            */
1290 /* PURPOSE   : Return the number of users in the specified class.        */
1291 /* ARGUMENTS : The name of the class to count.                           */
1292 /*************************************************************************/
1293 
1294 int acl_countusers(char *class)
1295 {
1296     int count = 0, opidfd = pidfd;
1297 
1298     if (Bypass_PID_Files)
1299 	return (0);
1300 
1301     if (pidfd < 0) {
1302 	if ((pidfd = open_pidfile(class)) < 0)
1303 	    return (-1);
1304     }
1305 
1306     count = limit_op(ACL_COUNT, 0);
1307 
1308     /*
1309      * acl_countusers may be called from msg_massage before the correct class
1310      * is known, so close the pid file if we opened it.
1311      */
1312     if (opidfd < 0) {
1313 	close(pidfd);
1314 	pidfd = -1;
1315     }
1316     return (count);
1317 }
1318 
1319 /*************************************************************************/
1320 /* FUNCTION  : acl_join                                                  */
1321 /* PURPOSE   : Add the current process to the list of processes in the   */
1322 /*             specified class.                                          */
1323 /* ARGUMENTS : The name of the class to join, user limit for the class.  */
1324 /* RETURNS   : 0 on success, -1 on failure                               */
1325 /*************************************************************************/
1326 
1327 int acl_join(char *class, int limit)
1328 {
1329     if (Bypass_PID_Files)
1330 	return (0);
1331 
1332     if (pidfd < 0) {
1333 	if ((pidfd = open_pidfile(class)) < 0)
1334 	    return (-1);
1335     }
1336 
1337     if (limit_op(ACL_JOIN, limit) < 0) {
1338 	/* no need to leave the pid file open as we were not added to it */
1339 	close(pidfd);
1340 	pidfd = -1;
1341 	return (-1);
1342     }
1343     /* pidfd left open so can be updated after a chroot */
1344     return (0);
1345 }
1346 
1347 /*************************************************************************/
1348 /* FUNCTION  : acl_remove                                                */
1349 /* PURPOSE   : Remove the current process from the list of processes in  */
1350 /*             our class.                                                */
1351 /* ARGUMENTS : None.                                                     */
1352 /*************************************************************************/
1353 
1354 void acl_remove(void)
1355 {
1356     if (pidfd < 0)
1357 	return;
1358     (void) limit_op(ACL_REMOVE, 0);
1359     close(pidfd);
1360     pidfd = -1;
1361 }
1362 
1363 /*************************************************************************/
1364 /* FUNCTION  : pr_mesg                                                   */
1365 /* PURPOSE   : Display a message to the user                             */
1366 /* ARGUMENTS : message code, name of file to display                     */
1367 /*************************************************************************/
1368 
1369 void pr_mesg(int msgcode, char *msgfile)
1370 {
1371     FILE *infile;
1372     char inbuf[BUFSIZ], outbuf[BUFSIZ], *cr;
1373 
1374     if (msgfile && (int) strlen(msgfile) > 0) {
1375 	infile = fopen(msgfile, "r");
1376 	if (infile) {
1377 	    while (fgets(inbuf, sizeof(inbuf), infile) != NULL) {
1378 		if ((cr = strchr(inbuf, '\n')) != NULL)
1379 		    *cr = '\0';
1380 		msg_massage(inbuf, outbuf, sizeof(outbuf));
1381 		lreply(msgcode, "%s", outbuf);
1382 	    }
1383 	    fclose(infile);
1384 	}
1385     }
1386 }
1387 
1388 /*************************************************************************/
1389 /* FUNCTION  : access_init                                               */
1390 /* PURPOSE   : Read and parse the access lists to set things up          */
1391 /* ARGUMENTS : none                                                      */
1392 /*************************************************************************/
1393 
1394 void access_init(void)
1395 {
1396     struct aclmember *entry;
1397     static struct stat sbuf_last;
1398     struct stat sbuf_cur;
1399 
1400     if (!use_accessfile)
1401 	return;
1402 
1403     if (stat(_path_ftpaccess, &sbuf_cur) != 0) {
1404 	syslog(LOG_ERR, "cannot stat access file %s: %s", _path_ftpaccess,
1405                strerror(errno));
1406 	return;
1407     }
1408     /* only reload the ftpaccess file if its changed */
1409     if ((sbuf_last.st_mtime == sbuf_cur.st_mtime) &&
1410 	(sbuf_last.st_ino == sbuf_cur.st_ino) &&
1411 	(sbuf_last.st_dev == sbuf_cur.st_dev))
1412 	return;
1413 
1414     sbuf_last = sbuf_cur;
1415 
1416 #ifdef OTHER_PASSWD
1417     strcpy(_path_passwd, "/etc/passwd");
1418 #ifdef SHADOW_PASSWORD
1419     strcpy(_path_shadow, "/etc/shadow");
1420 #endif
1421 #endif
1422 #if defined(USE_PAM) && defined(OTHER_PASSWD)
1423     use_pam = 1;
1424 #endif
1425     Shutdown[0] = '\0';
1426     keepalive = 0;
1427 
1428     if (!readacl(_path_ftpaccess))
1429 	return;
1430     (void) parseacl();
1431 
1432     entry = (struct aclmember *) NULL;
1433     if (getaclentry("shutdown", &entry) && ARG0 != NULL)
1434 	(void) strncpy(Shutdown, ARG0, sizeof(Shutdown));
1435 #ifdef OTHER_PASSWD
1436     entry = (struct aclmember *) NULL;
1437     while (getaclentry("passwd", &entry) && ARG0 != NULL) {
1438 	    strcpy(_path_passwd, ARG0);
1439 #ifdef USE_PAM
1440 	    use_pam = 0;
1441 #endif
1442     }
1443 #ifdef SHADOW_PASSWORD
1444     entry = (struct aclmember *) NULL;
1445     while (getaclentry("shadow", &entry) && ARG0 != NULL) {
1446 	    strcpy(_path_shadow, ARG0);
1447 #ifdef USE_PAM
1448 	    use_pam = 0;
1449 #endif
1450     }
1451 #endif
1452 #endif
1453     entry = (struct aclmember *) NULL;
1454     if (getaclentry("keepalive", &entry) && ARG0 != NULL)
1455 	if (!strcasecmp(ARG0, "yes"))
1456 	    keepalive = 1;
1457 }
1458 
1459 /*************************************************************************/
1460 /* FUNCTION  : access_ok                                                 */
1461 /* PURPOSE   : Check the anonymous FTP access lists to see if this       */
1462 /*             access is permitted.                                      */
1463 /* ARGUMENTS : reply code to use                                         */
1464 /*************************************************************************/
1465 
1466 int access_ok(int msgcode)
1467 {
1468     char class[BUFSIZ], msgfile[MAXPATHLEN];
1469     int limit;
1470     int nice_delta;
1471 
1472     if (!use_accessfile)
1473 	return (1);
1474 
1475     if (aclbuf == NULL) {
1476 	syslog(LOG_NOTICE,
1477 	       "ACCESS DENIED (error reading access file) TO %s",
1478 	       remoteident);
1479 	return (0);
1480     }
1481     if (acl_deny(msgfile)) {
1482 #ifndef HELP_CRACKERS
1483 	memcpy(DelayedMessageFile, msgfile, sizeof(msgfile));
1484 #else
1485 	pr_mesg(msgcode, msgfile);
1486 #endif
1487 	syslog(LOG_NOTICE, "ACCESS DENIED (deny command) TO %s",
1488 	       remoteident);
1489 	return (0);
1490     }
1491     /* if user is not in any class, deny access */
1492     if (!acl_getclass(class)) {
1493 	syslog(LOG_NOTICE, "ACCESS DENIED (not in any class) TO %s",
1494 	       remoteident);
1495 	return (0);
1496     }
1497 
1498     limit = acl_getlimit(class, msgfile);
1499     if (acl_join(class, limit) < 0) {
1500 #ifdef LOG_TOOMANY
1501 	syslog(LOG_NOTICE, "ACCESS DENIED (user limit %d; class %s) TO %s",
1502 	       limit, class, remoteident);
1503 #endif
1504 #ifndef HELP_CRACKERS
1505 	memcpy(DelayedMessageFile, msgfile, sizeof(msgfile));
1506 #else
1507 	pr_mesg(msgcode, msgfile);
1508 #endif
1509 	return (-1);
1510     }
1511 
1512     if ((nice_delta = acl_getnice(class))) {
1513 	if (nice_delta < 0)
1514 	    syslog(LOG_NOTICE, "Process nice value adjusted by %d", nice_delta);
1515 	nice(nice_delta);
1516     }
1517     acl_getdefumask(class);
1518     acl_tcpwindow(class);
1519 #ifdef TRANSFER_COUNT
1520 #ifdef TRANSFER_LIMIT
1521     acl_filelimit(class);
1522     acl_datalimit(class);
1523 #ifdef RATIO
1524     acl_downloadrate(class);
1525 #endif
1526 #endif
1527 #endif
1528     acl_bufsize();
1529     get_xferlog_format();
1530     return (1);
1531 }
1532