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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 }