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