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