eurofile: drop eft_wuauth code
the copyright holders forbid commercial use of the code which makes it non-free
This commit is contained in:
parent
d8c54147aa
commit
3a0e53fd6c
|
@ -1,111 +0,0 @@
|
|||
src/authlib contains an authentication library derived from wu-ftpd.
|
||||
It has been adapted for use with eftd by Georg v.Zezschwitz
|
||||
|
||||
Source code in src/authlib carries copyright notices and license
|
||||
conditions of different people and organizations. This file is only
|
||||
a summary therof and does neither claim to be complete nor correct.
|
||||
Refer to the source files for the authoritative copyright
|
||||
and license statements.
|
||||
|
||||
|
||||
/* Copyright (c) 1989 The Regents of the University of California. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* University of California, Berkeley and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that: (1) source distributions retain this entire copyright
|
||||
* notice and comment, and (2) distributions including binaries display
|
||||
* the following acknowledgement: ``This product includes software
|
||||
* developed by the University of California, Berkeley and its contributors''
|
||||
* in the documentation or other materials provided with the distribution
|
||||
* and in all advertising materials mentioning features or use of this
|
||||
* software. Neither the name of the University nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 1993, 1994 Washington University in Saint Louis
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* Washington University in Saint Louis and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASHINGTON
|
||||
* UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This software is Copyright 1997 by Stan Barber.
|
||||
*
|
||||
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
|
||||
* use this software as long as: there is no monetary profit gained
|
||||
* specifically from the use or reproduction of this software, it is not
|
||||
* sold, rented, traded or otherwise marketed, and this copyright notice is
|
||||
* included prominently in any copy made.
|
||||
*
|
||||
* The author make no claims as to the fitness or correctness of this software
|
||||
* for any use whatsoever, and it is provided as is. Any use of this software
|
||||
* is at the user's own risk.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
.\" $Id: eft_wuauth.5,v 1.1 1999/06/30 16:51:02 he Exp $
|
||||
.\" Copyright (c) 1985, 1988 The Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms are permitted provided
|
||||
.\" that: (1) source distributions retain this entire copyright notice and
|
||||
.\" comment, and (2) distributions including binaries display the following
|
||||
.\" acknowledgement: ``This product includes software developed by the
|
||||
.\" University of California, Berkeley and its contributors'' in the
|
||||
.\" documentation or other materials provided with the distribution and in
|
||||
.\" all advertising materials mentioning features or use of this software.
|
||||
.\" Neither the name of the University nor the names of its contributors may
|
||||
.\" be used to endorse or promote products derived from this software without
|
||||
.\" specific prior written permission.
|
||||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" ORIGINAL: ftpd.8 6.8 (Berkeley) 6/24/90
|
||||
.\"
|
||||
.\" @(#)$Original-Id: ftpd.8,v 1.5 1997/01/14 22:45:27 sob Exp sob $
|
||||
.\"
|
||||
.TH EFT_WUAUTH 5 "Jan 10, 1997"
|
||||
.UC 5
|
||||
.SH NAME
|
||||
eft_wuauth \- authentication for eftp4linux Eurofile server based on wuftpd.
|
||||
.SH DESCRIPTION
|
||||
If the eftp4linux Eurofile server
|
||||
.I eftd
|
||||
is compiled with the CONFIG_EFTD_WUAUTH configuration option,
|
||||
it uses user authentication code derived from
|
||||
.I wuftpd,
|
||||
the Washington University ftp daemon.
|
||||
.PP
|
||||
In that case
|
||||
.I eftd
|
||||
authenticates users according to four rules.
|
||||
.IP 1)
|
||||
The user name must be in the password data base,
|
||||
.IR /etc/passwd ,
|
||||
or whatever is appropriate for the operating system,
|
||||
and the password must not be null. In this case a password
|
||||
must be provided by the client before any file operations
|
||||
may be performed.
|
||||
.IP 2)
|
||||
The user name must not appear in the file
|
||||
.IR /etc/isdn/eftusers .
|
||||
.IP 3)
|
||||
The user must have a standard shell returned by
|
||||
.IR getusershell (3).
|
||||
If login failed for certain users, maybe that's because their login
|
||||
shell is not listed in /etc/shells.
|
||||
.IP 4)
|
||||
If the user name is ``anonymous'' or ``ftp'', an
|
||||
anonymous ftp account must be present in the password
|
||||
file (user ``ftp''). In this case the user is allowed
|
||||
to log in by specifying any password (by convention this
|
||||
is given as the client host's name).
|
||||
.PP
|
||||
In the last case,
|
||||
.I eftd
|
||||
takes special measures to restrict the client's access privileges.
|
||||
The server performs a
|
||||
.IR chroot (2)
|
||||
command to the home directory of the ``ftp'' user.
|
||||
In order that system security is not breached, it is recommended
|
||||
that the ``ftp'' subtree be constructed with care; the following
|
||||
rules are recommended.
|
||||
.IP ~ftp)
|
||||
Make the home directory owned by super-user and unwritable by anyone.
|
||||
.IP ~ftp/bin)
|
||||
Make this directory owned by the super-user and unwritable by
|
||||
anyone. This contains auxilary programs that might be forked by
|
||||
.IR eftd(8)
|
||||
or
|
||||
.IR ftpd(8).
|
||||
These programs should have mode 111.
|
||||
.IR eftd(8)
|
||||
currently does not need any auxilary programs. Thus, you only need to
|
||||
put files here if you also want to provide anonymous ftp service.
|
||||
.IP ~ftp/etc)
|
||||
Make this directory owned by the super-user and unwritable by
|
||||
anyone. The files
|
||||
.IR passwd (5)
|
||||
and
|
||||
.IR group (5)
|
||||
must be present for eftd
|
||||
to be able to produce owner names rather than numbers in file headers
|
||||
and extended format directory (T-DIR primitive) listings. Depending
|
||||
on the operating system, there may be other required files. Check your
|
||||
manual page for the
|
||||
.IR getpwent (3)
|
||||
library routine.
|
||||
The password field in
|
||||
.I passwd
|
||||
is not used, and should not contain real encrypted passwords.
|
||||
These files should be mode 444 and owned by the super-user.
|
||||
Don't use the system's /etc/passwd file as the password file or
|
||||
the system's /etc/group file as the group file in the ~ftp/etc directory.
|
||||
.IP ~ftp/pub)
|
||||
Create a subdirectory in ~ftp/pub
|
||||
with the appropriate mode (777 or 733) if you want to allow normal
|
||||
users to upload files.
|
||||
|
||||
.PP
|
||||
The Eurofile file server also allows for finer grained access control
|
||||
by means of the files /etc/isdn/eftaccess and /etc/isdn/efthosts.
|
||||
|
||||
.SH "COPYING"
|
||||
The main part of eftp4linux is licensed under the LGPL. However,
|
||||
eft servers using the wuauth authentication libray also contain code
|
||||
copyrighted by the University of California, Berkeley,
|
||||
by the Washington University in Saint Louis, and their contributors.
|
||||
That code is subject to a BSD style licences with advertisment clause:
|
||||
|
||||
Copyright (c) 1990 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to Berkeley by
|
||||
Chris Torek.
|
||||
Redistribution and use in source and binary forms are permitted
|
||||
provided that: (1) source distributions retain this entire
|
||||
copyright notice and comment, and (2) distributions including binaries
|
||||
display the following acknowledgement: ``This product includes software
|
||||
developed by the University of California, Berkeley and its contributors''
|
||||
in the documentation or other materials provided with the distribution
|
||||
and in all advertising materials mentioning features or use of this
|
||||
software. Neither the name of the University nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
Copyright (c) 1993, 1994 Washington University in Saint Louis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met: 1. Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this
|
||||
software must display the following acknowledgement: This product
|
||||
includes software developed by the Washington University in Saint
|
||||
Louis and its contributors.
|
||||
4. Neither the name of the University nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASHINGTON
|
||||
UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR eftd(1) ,
|
||||
.BR shells(5) ,
|
||||
.BR getusershell(3) ,
|
||||
.BR eftaccess(5) ,
|
||||
.BR efthosts(5) ,
|
||||
.BR eft_xferlog(5) ,
|
||||
.BR umask(2)
|
||||
.SH BUGS
|
||||
The anonymous account is inherently dangerous and should be
|
||||
avoided when possible.
|
||||
|
||||
The eftaccess amd efthosts files are currently not yet working as documented.
|
|
@ -1,43 +0,0 @@
|
|||
#
|
||||
# Makefile for Linux 1.2.13 with gcc 2.6.3
|
||||
#
|
||||
# $Id: Makefile,v 1.2 2006/01/15 15:08:55 keil Exp $
|
||||
#
|
||||
CC = gcc
|
||||
AR = ar cq
|
||||
RANLIB = ranlib
|
||||
LIBC = /lib/libc.a
|
||||
IFLAGS =
|
||||
LFLAGS =
|
||||
MYCFLAGS = -O6 -fomit-frame-pointer -fno-strength-reduce -pipe ${IFLAGS} ${LFLAGS}
|
||||
CFLAGS = -g
|
||||
|
||||
SRCS = strcasestr.c access.c divfunc.c private.c acl.c main.c sigfix.c \
|
||||
# extensions.c
|
||||
|
||||
OBJS = strcasestr.o access.o divfunc.o private.o acl.o main.o sigfix.o \
|
||||
# extensions.o
|
||||
|
||||
libwuauth.a: $(OBJS)
|
||||
-rm -f libwuauth.a
|
||||
${AR} libwuauth.a $(OBJS)
|
||||
${RANLIB} libwuauth.a
|
||||
|
||||
clean:
|
||||
-rm -f *.o libwuauth.a *~ #*#
|
||||
|
||||
ftp.h:
|
||||
install -c -m 444 ftp.h /usr/include/arpa
|
||||
|
||||
.c.o:
|
||||
${CC} ${CFLAGS} ${MYCFLAGS} -c $<
|
||||
|
||||
strcasestr.o: strcasestr.c
|
||||
${CC} ${CFLAGS} ${MYCFLAGS} -c strcasestr.c
|
||||
|
||||
authuser.o: authuser.c
|
||||
${CC} ${CFLAGS} ${MYCFLAGS} -c authuser.c
|
||||
|
||||
snprintf.o: snprintf.c
|
||||
${CC} ${CFLAGS} ${MYCFLAGS} -c snprintf.c
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
AUTHLIB
|
||||
|
||||
Date: 980525
|
||||
|
||||
Changes:
|
||||
980622 some minor changes (name changes, pathnames) for ease
|
||||
inclusion in eftp4linux source tree by Henner Eisen.
|
||||
*/
|
||||
|
||||
|
||||
This library is derived from some parts of wu-ftpd, the FTP server
|
||||
of the Washington University. (See copyright restrictions at
|
||||
the beginning of any source file containing WU code).
|
||||
|
||||
It was written for use with eftd, the Euro File Transfer Daemon
|
||||
written by Henner Eisen for isdn4linux.
|
||||
|
||||
As eftd is rather tighly related to the Linux OS, some OS independent
|
||||
parts have been removed for more readability (E.g. an ANSI C compiler
|
||||
is required).
|
||||
|
||||
It passes the function "wuftp_check_user" to the outside as main
|
||||
benefit:
|
||||
|
||||
int wuftp_check_user (char *name, char *passwd, char *isdnno)
|
||||
|
||||
Arguments:
|
||||
- name = The user name.
|
||||
Use ftp, anonymous or blank for anonymous logins
|
||||
- passwd = The password the client issued
|
||||
- isdnno = Instead of an IP-no as when used with ftpd, the isdn
|
||||
number of the client can or should be passed.
|
||||
|
||||
Returns:
|
||||
- 0 On failure.
|
||||
The user/password combination is wrong or the user
|
||||
is not allowed to log in.
|
||||
See "autherrmsg" for further information.
|
||||
- 1 On successful login.
|
||||
If the user is using a guest account (e.g., an
|
||||
anonymous user), a chroot/chdir will have been
|
||||
performed by the library.
|
||||
The user id of the running program is set to the
|
||||
user id of the user logged in.
|
||||
|
||||
This library tries to keep close to the auth-schemes as used by
|
||||
wu-ftpd. However, some adaptions have taken place:
|
||||
|
||||
- Like with wu-ftpd, you might either set the pathnames of
|
||||
ftpaccess, ftphosts, ftpusers... in "pathnames.h" or
|
||||
declare their directory in config.h.
|
||||
|
||||
However, all files related to this library are starting with
|
||||
"eft" instead of "ftp". Therefore, e.g. users forbidden to
|
||||
login through this library are listed in "eftusers".
|
||||
|
||||
- The guest-server directive may be used to restrict anonymous
|
||||
access by isdn-nr (instead of alias or fqdn-dns-name).
|
||||
However, the user will not get informed about other servers.
|
||||
|
||||
- Whereever you might restrict or enable the access in the
|
||||
config files by ip-number or fqdn-name, the isdn-nr will
|
||||
be used instead of ip-name or ip-number.
|
||||
|
||||
List of exported variables:
|
||||
|
||||
IMPORTED:
|
||||
use_accessfile Defaults to 0
|
||||
If set to 1 before calling wuftp_check_user,
|
||||
eftaccess will be interpreted and applied.
|
||||
|
||||
EXPORTED:
|
||||
char *autherrmsg - Whenever authentication has proceeded, this string
|
||||
is set to either an explanation why access was
|
||||
not granted or a welcome message like
|
||||
"guest login o.k., access restrictions apply"
|
||||
|
||||
|
||||
int guest 0 if normal user, 1 if "chrooted"
|
||||
int anonymous 0 if normal user, 1 if anonymous login
|
||||
|
||||
|
||||
Enjoy!
|
||||
|
||||
Georg v.Zezschwitz, georg@auf-der-er.de
|
||||
|
||||
|
||||
This product includes software developed by the Washington University
|
||||
in Saint Louis and its contributors.
|
||||
|
||||
This product includes software developed by the University of
|
||||
California, Berkeley and its contributors.
|
||||
|
|
@ -1,924 +0,0 @@
|
|||
/* Copyright (c) 1993, 1994 Washington University in Saint Louis
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* Washington University in Saint Louis and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASHINGTON
|
||||
* UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#)$Id: access.c,v 1.2 1999/10/05 21:23:23 he Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#ifdef SYSSYSLOG
|
||||
#include <sys/syslog.h>
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#if defined(SVR4) || defined(ISC)
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
extern char remotehost[],
|
||||
remoteaddr[],
|
||||
*aclbuf;
|
||||
extern int nameserved,
|
||||
anonymous,
|
||||
guest,
|
||||
use_accessfile;
|
||||
char Shutdown[MAXPATHLEN];
|
||||
#define MAXLINE 80
|
||||
static char incline[MAXLINE];
|
||||
int pidfd = -1;
|
||||
|
||||
extern int fnmatch();
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : parse_time */
|
||||
/* PURPOSE : Check a single valid-time-string against the current time */
|
||||
/* and return whether or not a match occurs. */
|
||||
/* ARGUMENTS : a pointer to the time-string */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
parsetime(char *whattime)
|
||||
#else
|
||||
parsetime(whattime)
|
||||
char *whattime;
|
||||
#endif
|
||||
{
|
||||
static char *days[] = {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Wk"};
|
||||
time_t clock;
|
||||
struct tm *curtime;
|
||||
int wday,
|
||||
start,
|
||||
stop,
|
||||
ltime,
|
||||
validday,
|
||||
loop,
|
||||
match;
|
||||
|
||||
(void) time(&clock);
|
||||
curtime = localtime(&clock);
|
||||
wday = curtime->tm_wday;
|
||||
validday = 0;
|
||||
match = 1;
|
||||
|
||||
while (match && isalpha(*whattime) && isupper(*whattime)) {
|
||||
match = 0;
|
||||
for (loop = 0; loop < 8; loop++) {
|
||||
if (strncmp(days[loop], whattime, 2) == 0) {
|
||||
whattime += 2;
|
||||
match = 1;
|
||||
if ((wday == loop) || ((loop == 7) && wday && (wday < 6))) {
|
||||
validday = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!validday) {
|
||||
if (strncmp(whattime, "Any", 3) == 0) {
|
||||
validday = 1;
|
||||
whattime += 3;
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (sscanf(whattime, "%d-%d", &start, &stop) == 2) {
|
||||
ltime = curtime->tm_min + 100 * curtime->tm_hour;
|
||||
if ((start < stop) && ((ltime > start) && ltime < stop))
|
||||
return (1);
|
||||
if ((start > stop) && ((ltime > start) || ltime < stop))
|
||||
return (1);
|
||||
} else
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : validtime */
|
||||
/* PURPOSE : Break apart a set of valid time-strings and pass them to */
|
||||
/* parse_time, returning whether or not ANY matches occurred */
|
||||
/* ARGUMENTS : a pointer to the time-string */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
validtime(char *ptr)
|
||||
#else
|
||||
validtime(ptr)
|
||||
char *ptr;
|
||||
#endif
|
||||
{
|
||||
char *nextptr;
|
||||
int good;
|
||||
|
||||
while (1) {
|
||||
nextptr = strchr(ptr, '|');
|
||||
if (strchr(ptr, '|') == NULL)
|
||||
return (parsetime(ptr));
|
||||
*nextptr = '\0';
|
||||
good = parsetime(ptr);
|
||||
/* gotta restore the | or things get skipped! */
|
||||
*nextptr++ = '|';
|
||||
if (good)
|
||||
return (1);
|
||||
ptr = nextptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : hostmatch */
|
||||
/* PURPOSE : Match remote hostname or address against a glob string */
|
||||
/* ARGUMENTS : The string to match */
|
||||
/* RETURNS : 0 if no match, 1 if a match occurs */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
hostmatch(char *addr)
|
||||
#else
|
||||
hostmatch(addr)
|
||||
char *addr;
|
||||
#endif
|
||||
{
|
||||
FILE *incfile;
|
||||
char *ptr;
|
||||
int found = 0;
|
||||
|
||||
if (addr == NULL) return(0);
|
||||
|
||||
if (isdigit(*addr))
|
||||
return(!fnmatch(addr, remoteaddr, NULL));
|
||||
else if (*addr == '/') {
|
||||
/*
|
||||
* read addrglobs from named path using similar format as addrglobs
|
||||
* in access file
|
||||
*/
|
||||
if ((incfile = fopen(addr, "r")) == NULL) {
|
||||
if (errno != ENOENT) syslog(LOG_ERR,
|
||||
"cannot open addrglob file %s: %s", addr, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
while (!found && (fgets(incline, MAXLINE, incfile) != NULL)) {
|
||||
ptr = strtok(incline, " \t\n");
|
||||
if (ptr && hostmatch(ptr))
|
||||
found = 1;
|
||||
while (!found && ((ptr = strtok(NULL, " \t\n")) != NULL)) {
|
||||
if (ptr && hostmatch(ptr))
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
fclose(incfile);
|
||||
return(found);
|
||||
}
|
||||
else
|
||||
{ /* match a hostname or hostname glob */
|
||||
char *addrncase,*hostncase;
|
||||
int i,j;
|
||||
/* must convert both to lower case for match */
|
||||
if ((addrncase = (char *)malloc(strlen(addr)+1)) == NULL)
|
||||
return(0);
|
||||
if ((hostncase = (char *)malloc(strlen(remotehost)+1)) == NULL){
|
||||
free(addrncase);
|
||||
return(0);
|
||||
}
|
||||
j = strlen(addr) + 1;
|
||||
for (i = 0;i < j; i++)
|
||||
addrncase[i] = tolower(addr[i]);
|
||||
j = strlen(remotehost) + 1;
|
||||
for (i = 0;i < j; i++)
|
||||
hostncase[i] = tolower(remotehost[i]);
|
||||
found = !fnmatch(addrncase, hostncase, NULL);
|
||||
free(addrncase);
|
||||
free(hostncase);
|
||||
return(found);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_guestgroup */
|
||||
/* PURPOSE : If the real user is a member of any of the listed groups, */
|
||||
/* return 1. Otherwise return 0. */
|
||||
/* ARGUMENTS : pw, a pointer to the passwd struct for the user */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
acl_guestgroup(struct passwd *pw)
|
||||
#else
|
||||
acl_guestgroup(pw)
|
||||
struct passwd *pw;
|
||||
#endif
|
||||
{
|
||||
struct aclmember *entry = NULL;
|
||||
struct group *grp;
|
||||
int which;
|
||||
char **member;
|
||||
|
||||
/* guestgroup <group> [<group> ...] */
|
||||
while (getaclentry("guestgroup", &entry)) {
|
||||
for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
|
||||
if (!(grp = getgrnam(ARG[which])))
|
||||
continue;
|
||||
if (pw->pw_gid == grp->gr_gid)
|
||||
return (1);
|
||||
for (member = grp->gr_mem; *member; member++) {
|
||||
if (!strcmp(*member, pw->pw_name))
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_autogroup */
|
||||
/* PURPOSE : If the guest user is a member of any of the classes in */
|
||||
/* the autogroup comment, cause a setegid() to the specified */
|
||||
/* group. */
|
||||
/* ARGUMENTS : pw, a pointer to the passwd struct for the user */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
acl_autogroup(struct passwd *pw)
|
||||
#else
|
||||
acl_autogroup(pw)
|
||||
struct passwd *pw;
|
||||
#endif
|
||||
{
|
||||
char class[1024];
|
||||
|
||||
struct aclmember *entry = NULL;
|
||||
struct group *grp;
|
||||
int which;
|
||||
|
||||
(void) acl_getclass(class);
|
||||
|
||||
/* autogroup <group> <class> [<class> ...] */
|
||||
while (getaclentry("autogroup", &entry)) {
|
||||
if (!ARG0 || !ARG1)
|
||||
continue;
|
||||
if ((grp = getgrnam(ARG0))) {
|
||||
for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
|
||||
if (!strcmp(ARG[which], class)) {
|
||||
pw->pw_gid = grp->gr_gid;
|
||||
endgrent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
syslog(LOG_ERR, "autogroup: set group %s not found", ARG0);
|
||||
endgrent();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_setfunctions */
|
||||
/* PURPOSE : Scan the ACL buffer and determine what logging to perform */
|
||||
/* for this user, and whether or not user is allowed to use */
|
||||
/* the automatic TAR and COMPRESS functions. */
|
||||
/* ARGUMENTS : pointer to buffer to class name, pointer to ACL buffer */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
acl_setfunctions(void)
|
||||
#else
|
||||
acl_setfunctions()
|
||||
#endif
|
||||
{
|
||||
char class[1024];
|
||||
|
||||
extern int log_incoming_xfers,
|
||||
log_outbound_xfers,
|
||||
mangleopts,
|
||||
log_commands,
|
||||
lgi_failure_threshold;
|
||||
|
||||
struct aclmember *entry = NULL;
|
||||
|
||||
int l_compress,
|
||||
l_tar,
|
||||
inbound = 0,
|
||||
outbound = 0,
|
||||
which,
|
||||
set;
|
||||
|
||||
log_incoming_xfers = 0;
|
||||
log_outbound_xfers = 0;
|
||||
log_commands = 0;
|
||||
|
||||
memset((void *)&class[0], 0, sizeof(class));
|
||||
|
||||
(void) acl_getclass(class);
|
||||
|
||||
entry = (struct aclmember *) NULL;
|
||||
if (getaclentry("loginfails", &entry) && ARG0 != NULL) {
|
||||
lgi_failure_threshold = atoi(ARG0);
|
||||
}
|
||||
#ifndef NO_PRIVATE
|
||||
entry = (struct aclmember *) NULL;
|
||||
if (getaclentry("private", &entry) && !strcmp(ARG0, "yes"))
|
||||
priv_setup(_PATH_PRIVATE);
|
||||
#endif /* !NO_PRIVATE */
|
||||
|
||||
entry = (struct aclmember *) NULL;
|
||||
set = 0;
|
||||
while (!set && getaclentry("compress", &entry)) {
|
||||
l_compress = 0;
|
||||
if (!strcasecmp(ARG0, "yes"))
|
||||
l_compress = 1;
|
||||
for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
|
||||
if (!fnmatch(ARG[which], class, NULL)) {
|
||||
mangleopts |= l_compress * (O_COMPRESS | O_UNCOMPRESS);
|
||||
set = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entry = (struct aclmember *) NULL;
|
||||
set = 0;
|
||||
while (!set && getaclentry("tar", &entry)) {
|
||||
l_tar = 0;
|
||||
if (!strcasecmp(ARG0, "yes"))
|
||||
l_tar = 1;
|
||||
for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
|
||||
if (!fnmatch(ARG[which], class, NULL)) {
|
||||
mangleopts |= l_tar * O_TAR;
|
||||
set = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* plan on expanding command syntax to include classes for each of these */
|
||||
|
||||
entry = (struct aclmember *) NULL;
|
||||
while (getaclentry("log", &entry)) {
|
||||
if (!strcasecmp(ARG0, "commands")) {
|
||||
if (anonymous && strcasestr(ARG1, "anonymous"))
|
||||
log_commands = 1;
|
||||
if (guest && strcasestr(ARG1, "guest"))
|
||||
log_commands = 1;
|
||||
if (!guest && !anonymous && strcasestr(ARG1, "real"))
|
||||
log_commands = 1;
|
||||
}
|
||||
if (!strcasecmp(ARG0, "transfers")) {
|
||||
set = 0;
|
||||
if (strcasestr(ARG1, "anonymous") && anonymous)
|
||||
set = 1;
|
||||
if (strcasestr(ARG1, "guest") && guest)
|
||||
set = 1;
|
||||
if (strcasestr(ARG1, "real") && !guest && !anonymous)
|
||||
set = 1;
|
||||
if (strcasestr(ARG2, "inbound"))
|
||||
inbound = 1;
|
||||
if (strcasestr(ARG2, "outbound"))
|
||||
outbound = 1;
|
||||
if (set)
|
||||
log_incoming_xfers = inbound;
|
||||
if (set)
|
||||
log_outbound_xfers = outbound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_getclass */
|
||||
/* PURPOSE : Scan the ACL buffer and determine what class user is in */
|
||||
/* ARGUMENTS : pointer to buffer to class name, pointer to ACL buffer */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
acl_getclass(char *classbuf)
|
||||
#else
|
||||
acl_getclass(classbuf)
|
||||
char *classbuf;
|
||||
#endif
|
||||
{
|
||||
int which;
|
||||
struct aclmember *entry = NULL;
|
||||
|
||||
while (getaclentry("class", &entry)) {
|
||||
if (ARG0)
|
||||
strcpy(classbuf, ARG0);
|
||||
|
||||
for (which = 2; (which < MAXARGS) && ARG[which]; which++) {
|
||||
if (anonymous && strcasestr(ARG1, "anonymous") &&
|
||||
hostmatch(ARG[which]))
|
||||
return (1);
|
||||
|
||||
if (guest && strcasestr(ARG1, "guest") && hostmatch(ARG[which]))
|
||||
return (1);
|
||||
|
||||
if (!guest && !anonymous && strcasestr(ARG1, "real") &&
|
||||
hostmatch(ARG[which]))
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
*classbuf = (char) NULL;
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_getlimit */
|
||||
/* PURPOSE : Scan the ACL buffer and determine what limit applies to */
|
||||
/* the user */
|
||||
/* ARGUMENTS : pointer class name, pointer to ACL buffer */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
acl_getlimit(char *class, char *msgpathbuf)
|
||||
#else
|
||||
acl_getlimit(class,msgpathbuf)
|
||||
char *class;
|
||||
char *msgpathbuf;
|
||||
#endif
|
||||
{
|
||||
int limit;
|
||||
struct aclmember *entry = NULL;
|
||||
|
||||
if (msgpathbuf)
|
||||
*msgpathbuf = '\0';
|
||||
|
||||
/* limit <class> <n> <times> [<message_file>] */
|
||||
while (getaclentry("limit", &entry)) {
|
||||
if (!ARG0 || !ARG1 || !ARG2)
|
||||
continue;
|
||||
if (!strcmp(class, ARG0)) {
|
||||
limit = atoi(ARG1);
|
||||
if (validtime(ARG2)) {
|
||||
if (ARG3 && msgpathbuf)
|
||||
strcpy(msgpathbuf, ARG3);
|
||||
return (limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_deny */
|
||||
/* PURPOSE : Scan the ACL buffer and determine a deny command applies */
|
||||
/* ARGUMENTS : pointer class name, pointer to ACL buffer */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
acl_deny(char *msgpathbuf)
|
||||
#else
|
||||
acl_deny(msgpathbuf)
|
||||
char *msgpathbuf;
|
||||
#endif
|
||||
{
|
||||
struct aclmember *entry = NULL;
|
||||
|
||||
if (msgpathbuf)
|
||||
*msgpathbuf = (char) NULL;
|
||||
|
||||
/* deny <addrglob> [<message_file>] */
|
||||
while (getaclentry("deny", &entry)) {
|
||||
if (!ARG0)
|
||||
continue;
|
||||
if (!nameserved && !strcmp(ARG0, "!nameserved")) {
|
||||
if (ARG1)
|
||||
strcpy(msgpathbuf, entry->arg[1]);
|
||||
return (1);
|
||||
}
|
||||
if (hostmatch(ARG0)) {
|
||||
if (ARG1)
|
||||
strcpy(msgpathbuf, entry->arg[1]);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_countusers */
|
||||
/* PURPOSE : Check the anonymous FTP access lists to see if this */
|
||||
/* access is permitted. */
|
||||
/* ARGUMENTS : none */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
acl_countusers(char *class)
|
||||
#else
|
||||
acl_countusers(class)
|
||||
char *class;
|
||||
#endif
|
||||
{
|
||||
int count,
|
||||
which;
|
||||
char pidfile[MAXPATHLEN];
|
||||
pid_t buf[MAXUSERS];
|
||||
#ifndef HAVE_FLOCK
|
||||
struct flock arg;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if pidfd was not opened previously...
|
||||
* pidfd must stay open after the chroot(~ftp)
|
||||
*/
|
||||
|
||||
sprintf(pidfile, _PATH_PIDNAMES, class);
|
||||
|
||||
if (pidfd < 0) {
|
||||
pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
|
||||
}
|
||||
|
||||
if (pidfd < 0) {
|
||||
syslog(LOG_ERR, "cannot open pid file %s: %s", pidfile,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FLOCK
|
||||
while (flock(pidfd, LOCK_EX)) {
|
||||
syslog(LOG_ERR, "sleeping: flock of pid file failed: %s",
|
||||
#else
|
||||
arg.l_type = F_WRLCK;
|
||||
arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
while ( -1 == fcntl( pidfd, F_SETLK, &arg) ) {
|
||||
syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %s",
|
||||
#endif
|
||||
strerror(errno));
|
||||
sleep(1);
|
||||
}
|
||||
lseek(pidfd, 0, L_SET);
|
||||
|
||||
count = 0;
|
||||
|
||||
if (read(pidfd, buf, sizeof(buf)) == sizeof(buf)) {
|
||||
for (which = 0; which < MAXUSERS; which++)
|
||||
if (buf[which] && !kill(buf[which], 0))
|
||||
count++;
|
||||
}
|
||||
#ifdef HAVE_FLOCK
|
||||
flock(pidfd, LOCK_UN);
|
||||
#else
|
||||
arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
fcntl(pidfd, F_SETLK, &arg);
|
||||
#endif
|
||||
return (count);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_join */
|
||||
/* PURPOSE : Add the current process to the list of processes in the */
|
||||
/* specified class. */
|
||||
/* ARGUMENTS : The name of the class to join */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
acl_join(char *class)
|
||||
#else
|
||||
acl_join(class)
|
||||
char *class;
|
||||
#endif
|
||||
{
|
||||
int which,
|
||||
avail;
|
||||
pid_t buf[MAXUSERS];
|
||||
char pidfile[MAXPATHLEN];
|
||||
pid_t procid;
|
||||
#ifndef HAVE_FLOCK
|
||||
struct flock arg;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if pidfd was not opened previously...
|
||||
* pidfd must stay open after the chroot(~ftp)
|
||||
*/
|
||||
|
||||
sprintf(pidfile, _PATH_PIDNAMES, class);
|
||||
|
||||
if (pidfd < 0) {
|
||||
pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
|
||||
}
|
||||
|
||||
if (pidfd < 0) {
|
||||
syslog(LOG_ERR, "cannot open pid file %s: %s", pidfile,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FLOCK
|
||||
while (flock(pidfd, LOCK_EX)) {
|
||||
syslog(LOG_ERR, "sleeping: flock of pid file failed: %s",
|
||||
#else
|
||||
arg.l_type = F_WRLCK;
|
||||
arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
while ( -1 == fcntl( pidfd, F_SETLK, &arg) ) {
|
||||
syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %s",
|
||||
#endif
|
||||
strerror(errno));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
procid = getpid();
|
||||
|
||||
lseek(pidfd, 0, L_SET);
|
||||
if (read(pidfd, buf, sizeof(buf)) < sizeof(buf))
|
||||
for (which = 0; which < MAXUSERS; buf[which++] = 0)
|
||||
continue;
|
||||
|
||||
avail = 0;
|
||||
for (which = 0; which < MAXUSERS; which++) {
|
||||
if ((buf[which] == 0) || (kill(buf[which], 0) == -1)) {
|
||||
avail = which;
|
||||
buf[which] = 0;
|
||||
} else if (buf[which] == procid) {
|
||||
/* already exists in pid file... */
|
||||
#ifdef HAVE_FLOCK
|
||||
flock(pidfd, LOCK_UN);
|
||||
#else
|
||||
arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
fcntl(pidfd, F_SETLK, &arg);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
buf[avail] = procid;
|
||||
|
||||
lseek(pidfd, 0, L_SET);
|
||||
write(pidfd, buf, sizeof(buf));
|
||||
#ifdef HAVE_FLOCK
|
||||
flock(pidfd, LOCK_UN);
|
||||
#else
|
||||
arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
fcntl(pidfd, F_SETLK, &arg);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : acl_remove */
|
||||
/* PURPOSE : remove the current process to the list of processes in */
|
||||
/* the specified class. */
|
||||
/* ARGUMENTS : The name of the class to remove */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
acl_remove(void)
|
||||
#else
|
||||
acl_remove()
|
||||
#endif
|
||||
{
|
||||
char class[1024];
|
||||
int which,
|
||||
avail;
|
||||
pid_t buf[MAXUSERS];
|
||||
char pidfile[MAXPATHLEN];
|
||||
pid_t procid;
|
||||
#ifndef HAVE_FLOCK
|
||||
struct flock arg;
|
||||
#endif
|
||||
|
||||
if (!acl_getclass(class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if pidfd was not opened previously...
|
||||
* pidfd must stay open after the chroot(~ftp)
|
||||
*/
|
||||
|
||||
sprintf(pidfile, _PATH_PIDNAMES, class);
|
||||
|
||||
if (pidfd < 0) {
|
||||
pidfd = open(pidfile, O_RDWR | O_CREAT, 0644);
|
||||
}
|
||||
|
||||
if (pidfd < 0) {
|
||||
syslog(LOG_ERR, "cannot open pid file %s: %s", pidfile,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FLOCK
|
||||
while (flock(pidfd, LOCK_EX)) {
|
||||
syslog(LOG_ERR, "sleeping: flock of pid file failed: %s",
|
||||
#else
|
||||
arg.l_type = F_WRLCK;
|
||||
arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
while ( -1 == fcntl( pidfd, F_SETLK, &arg) ) {
|
||||
syslog(LOG_ERR, "sleeping: fcntl lock of pid file failed: %s",
|
||||
#endif
|
||||
strerror(errno));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
procid = getpid();
|
||||
|
||||
lseek(pidfd, 0, L_SET);
|
||||
if (read(pidfd, buf, sizeof(buf)) < sizeof(buf))
|
||||
for (which = 0; which < MAXUSERS; buf[which++] = 0)
|
||||
continue;
|
||||
|
||||
avail = 0;
|
||||
for (which = 0; which < MAXUSERS; which++) {
|
||||
if ((buf[which] == 0) || (kill(buf[which], 0) == -1)) {
|
||||
avail = which;
|
||||
buf[which] = 0;
|
||||
} else if (buf[which] == procid) {
|
||||
buf[which] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lseek(pidfd, 0, L_SET);
|
||||
write(pidfd, buf, sizeof(buf));
|
||||
#ifdef HAVE_FLOCK
|
||||
flock(pidfd, LOCK_UN);
|
||||
#else
|
||||
arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0;
|
||||
fcntl(pidfd, F_SETLK, &arg);
|
||||
#endif
|
||||
|
||||
close(pidfd);
|
||||
pidfd = -1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : pr_mesg */
|
||||
/* PURPOSE : Display a message to the user */
|
||||
/* ARGUMENTS : message code, name of file to display */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
pr_mesg(int msgcode, char *msgfile)
|
||||
#else
|
||||
pr_mesg(msgcode,msgfile)
|
||||
int msgcode;
|
||||
char *msgfile;
|
||||
#endif
|
||||
{
|
||||
FILE *infile;
|
||||
char inbuf[1024],
|
||||
outbuf[1024],
|
||||
*cr;
|
||||
|
||||
if (msgfile && (int)strlen(msgfile) > 0) {
|
||||
infile = fopen(msgfile, "r");
|
||||
if (infile) {
|
||||
while (fgets(inbuf, 255, infile) != NULL) {
|
||||
if ((cr = strchr(inbuf, '\n')) != NULL)
|
||||
*cr = '\0';
|
||||
/*
|
||||
msg_massage(inbuf, outbuf);
|
||||
lreply(msgcode, "%s", outbuf);
|
||||
*/
|
||||
}
|
||||
fclose(infile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : access_init */
|
||||
/* PURPOSE : Read and parse the access lists to set things up */
|
||||
/* ARGUMENTS : none */
|
||||
/* return: != 0 if error ist detected */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
access_init(void)
|
||||
#else
|
||||
access_init()
|
||||
#endif
|
||||
{
|
||||
struct aclmember *entry;
|
||||
extern char *eft_access;
|
||||
int ret;
|
||||
|
||||
/* if (!readacl(_PATH_FTPACCESS)) changed -- he */
|
||||
if (!readacl(eft_access)){
|
||||
if(use_accessfile){
|
||||
fprintf(stderr,"readacl() failed (file: %s)\n", eft_access);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ret = parseacl();
|
||||
|
||||
Shutdown[0] = '\0';
|
||||
entry = (struct aclmember *) NULL;
|
||||
if (getaclentry("shutdown", &entry) && ARG0 != NULL)
|
||||
(void) strncpy(Shutdown, ARG0, sizeof(Shutdown));
|
||||
if( ret && use_accessfile) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : access_ok */
|
||||
/* PURPOSE : Check the anonymous FTP access lists to see if this */
|
||||
/* access is permitted. */
|
||||
/* ARGUMENTS : none */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
access_ok(int msgcode)
|
||||
#else
|
||||
access_ok(msgcode)
|
||||
int msgcode;
|
||||
#endif
|
||||
{
|
||||
char class[1024],
|
||||
msgfile[MAXPATHLEN];
|
||||
int limit;
|
||||
|
||||
if (!use_accessfile)
|
||||
return (1);
|
||||
|
||||
if (aclbuf == NULL) {
|
||||
syslog(LOG_NOTICE,
|
||||
"ACCESS DENIED (error reading access file) TO %s [%s]",
|
||||
remotehost, remoteaddr);
|
||||
return (0);
|
||||
}
|
||||
if (acl_deny(msgfile)) {
|
||||
pr_mesg(msgcode, msgfile);
|
||||
syslog(LOG_NOTICE, "ACCESS DENIED (deny command) TO %s [%s]",
|
||||
remotehost, remoteaddr);
|
||||
return (0);
|
||||
}
|
||||
/* if user is not in any class, deny access */
|
||||
if (!acl_getclass(class)) {
|
||||
syslog(LOG_NOTICE, "ACCESS DENIED (not in any class) TO %s [%s]",
|
||||
remotehost, remoteaddr);
|
||||
return (0);
|
||||
}
|
||||
/* if no limits defined, no limits apply -- access OK */
|
||||
limit = acl_getlimit(class, msgfile);
|
||||
|
||||
if ((limit == -1) || (acl_countusers(class) < limit)) {
|
||||
acl_join(class);
|
||||
return (1);
|
||||
} else {
|
||||
#ifdef LOG_TOOMANY
|
||||
syslog(LOG_NOTICE, "ACCESS DENIED (user limit %d; class %s) TO %s [%s]",
|
||||
limit, class, remotehost, remoteaddr);
|
||||
#endif
|
||||
pr_mesg(msgcode, msgfile);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
/* Copyright (c) 1993, 1994 Washington University in Saint Louis
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* Washington University in Saint Louis and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASHINGTON
|
||||
* UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char * rcsid = "$Id: acl.c,v 1.2 1999/10/05 21:23:23 he Exp $";
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#ifdef SYSSYSLOG
|
||||
#include <sys/syslog.h>
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "extensions.h"
|
||||
|
||||
char *aclbuf = NULL;
|
||||
static struct aclmember *aclmembers;
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : getaclentry */
|
||||
/* PURPOSE : Retrieve a named entry from the ACL */
|
||||
/* ARGUMENTS : pointer to the keyword and a handle to the acl members */
|
||||
/* RETURNS : pointer to the acl member containing the keyword or NULL */
|
||||
/*************************************************************************/
|
||||
|
||||
struct aclmember *
|
||||
#ifdef __STDC__
|
||||
getaclentry(char *keyword, struct aclmember **next)
|
||||
#else
|
||||
getaclentry(keyword,next)
|
||||
char *keyword;
|
||||
struct aclmember **next;
|
||||
#endif
|
||||
{
|
||||
do {
|
||||
if (!*next)
|
||||
*next = aclmembers;
|
||||
else
|
||||
*next = (*next)->next;
|
||||
} while (*next && strcmp((*next)->keyword, keyword));
|
||||
|
||||
return (*next);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : parseacl */
|
||||
/* PURPOSE : Parse the acl buffer into its components */
|
||||
/* ARGUMENTS : A pointer to the acl file */
|
||||
/* RETURNS : != 0 if error is detected */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
parseacl(void)
|
||||
#else
|
||||
parseacl()
|
||||
#endif
|
||||
{
|
||||
char *ptr,
|
||||
*aclptr = aclbuf,
|
||||
*line;
|
||||
int cnt;
|
||||
struct aclmember *member,
|
||||
*acltail;
|
||||
|
||||
if (!aclbuf || !(*aclbuf))
|
||||
return 1;
|
||||
|
||||
aclmembers = (struct aclmember *) NULL;
|
||||
acltail = (struct aclmember *) NULL;
|
||||
|
||||
while (*aclptr != '\0') {
|
||||
line = aclptr;
|
||||
while (*aclptr && *aclptr != '\n')
|
||||
aclptr++;
|
||||
*aclptr++ = (char) NULL;
|
||||
|
||||
/* deal with comments */
|
||||
if ((ptr = strchr(line, '#')) != NULL)
|
||||
/* allowed escaped '#' chars for path-filter (DiB) */
|
||||
if (*(ptr-1) != '\\')
|
||||
*ptr = '\0';
|
||||
|
||||
ptr = strtok(line, " \t");
|
||||
if (ptr) {
|
||||
member = (struct aclmember *) calloc(1, sizeof(struct aclmember));
|
||||
|
||||
(void) strcpy(member->keyword, ptr);
|
||||
cnt = 0;
|
||||
while ((ptr = strtok(NULL, " \t")) != NULL) {
|
||||
if (cnt >= MAXARGS) {
|
||||
syslog(LOG_ERR,
|
||||
"Too many args (>%d) in ftpaccess: %s %s %s %s %s ...",
|
||||
MAXARGS - 1, member->keyword, member->arg[0],
|
||||
member->arg[1], member->arg[2], member->arg[3]);
|
||||
break;
|
||||
}
|
||||
member->arg[cnt++] = ptr;
|
||||
}
|
||||
if (acltail)
|
||||
acltail->next = member;
|
||||
acltail = member;
|
||||
if (!aclmembers)
|
||||
aclmembers = member;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : readacl */
|
||||
/* PURPOSE : Read the acl into memory */
|
||||
/* ARGUMENTS : The pathname of the acl */
|
||||
/* RETURNS : 0 if error, 1 if no error */
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
readacl(char *aclpath)
|
||||
#else
|
||||
readacl(aclpath)
|
||||
char *aclpath;
|
||||
#endif
|
||||
{
|
||||
FILE *aclfile;
|
||||
struct stat finfo;
|
||||
extern int use_accessfile;
|
||||
|
||||
if (!use_accessfile)
|
||||
return (0);
|
||||
|
||||
if ((aclfile = fopen(aclpath, "r")) == NULL) {
|
||||
syslog(LOG_ERR, "cannot open access file %s: %s", aclpath,
|
||||
strerror(errno));
|
||||
return (0);
|
||||
}
|
||||
if (fstat(fileno(aclfile), &finfo) != 0) {
|
||||
syslog(LOG_ERR, "cannot fstat access file %s: %s", aclpath,
|
||||
strerror(errno));
|
||||
(void) fclose(aclfile);
|
||||
return (0);
|
||||
}
|
||||
if (finfo.st_size == 0) {
|
||||
aclbuf = (char *) calloc(1, 1);
|
||||
} else {
|
||||
if (!(aclbuf = (char *)malloc((unsigned) finfo.st_size + 1))) {
|
||||
syslog(LOG_ERR, "could not malloc aclbuf (%d bytes)", finfo.st_size + 1);
|
||||
(void) fclose(aclfile);
|
||||
return (0);
|
||||
}
|
||||
if (!fread(aclbuf, (size_t) finfo.st_size, 1, aclfile)) {
|
||||
syslog(LOG_ERR, "error reading acl file %s: %s", aclpath,
|
||||
strerror(errno));
|
||||
aclbuf = NULL;
|
||||
(void) fclose(aclfile);
|
||||
return (0);
|
||||
}
|
||||
*(aclbuf + finfo.st_size) = '\0';
|
||||
}
|
||||
(void) fclose(aclfile);
|
||||
return (1);
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Linux configuration file
|
||||
* $Id: config.h,v 1.3 2002/07/06 00:11:18 keil Exp $
|
||||
*/
|
||||
#if 0
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define LINUX_VERSION_CODE 0x020404
|
||||
#endif
|
||||
#if defined(LINUX_VERSION_CODE)
|
||||
#if LINUX_VERSION_CODE >= 66061
|
||||
/* 1.2.13 or later */
|
||||
#define HAVE_DIRFD
|
||||
#endif
|
||||
#endif
|
||||
#undef BSD
|
||||
#define HAVE_DIRENT
|
||||
#define HAVE_FLOCK
|
||||
#define HAVE_FTW
|
||||
#define HAVE_GETCWD
|
||||
#define HAVE_GETDTABLESIZE
|
||||
#undef HAVE_PSTAT
|
||||
#define HAVE_ST_BLKSIZE
|
||||
#undef HAVE_SYSINFO
|
||||
#define HAVE_SYSCONF
|
||||
#define HAVE_UT_UT_HOST
|
||||
#define HAVE_VPRINTF
|
||||
#define HAVE_SNPRINTF
|
||||
#define LINUX
|
||||
#define OVERWRITE
|
||||
#undef REGEX
|
||||
#define SPT_TYPE SPT_REUSEARGV
|
||||
#define SHADOW_PASSWORD
|
||||
#define UPLOAD
|
||||
#undef USG
|
||||
#define SVR4
|
||||
#define FACILITY LOG_DAEMON
|
||||
#define HAVE_SYS_VFS
|
||||
#define HAVE_SYMLINK
|
||||
#define UTMAXTYPE
|
||||
/* #define USE_ETC */
|
||||
#define USE_LOG
|
||||
#define USE_VAR
|
||||
#define VAR_RUN
|
||||
#define VIRTUAL
|
||||
#define NEED_SIGFIX
|
||||
|
||||
#if !defined(__USE_POSIX)
|
||||
#define __USE_POSIX
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#ifndef NBBY
|
||||
#define NBBY 8
|
||||
#endif
|
||||
#ifndef NCARGS
|
||||
#ifdef _POSIX_ARG_MAX
|
||||
#define NCARGS _POSIX_ARG_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* here instead of in all the srcs. _H*/
|
||||
#include <unistd.h>
|
||||
|
||||
typedef void SIGNAL_TYPE;
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#define realpath realpath_on_steroids /* hack to work around unistd.h */
|
|
@ -1,231 +0,0 @@
|
|||
|
||||
/* Copyright (c) 1993, 1994 Washington University in Saint Louis
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* Washington University in Saint Louis and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASHINGTON
|
||||
* UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#ifdef SYSSYSLOG
|
||||
#include <sys/syslog.h>
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <pwd.h>
|
||||
#include <setjmp.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined(HAVE_STATVFS)
|
||||
#include <sys/statvfs.h>
|
||||
#elif defined(HAVE_SYS_VFS)
|
||||
#include <sys/vfs.h>
|
||||
#elif defined(HAVE_SYS_MOUNT)
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include <arpa/ftp.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "extensions.h"
|
||||
|
||||
extern char remotehost[];
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : msg_massage */
|
||||
/* PURPOSE : Scan a message line for magic cookies, replacing them as */
|
||||
/* needed. */
|
||||
/* ARGUMENTS : pointer input and output buffers */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
msg_massage(char *inbuf, char *outbuf)
|
||||
#else
|
||||
msg_massage(inbuf,outbuf)
|
||||
char *inbuf;
|
||||
char *outbuf;
|
||||
#endif
|
||||
{
|
||||
char *inptr = inbuf;
|
||||
char *outptr = outbuf;
|
||||
char buffer[MAXPATHLEN];
|
||||
time_t curtime;
|
||||
int limit;
|
||||
extern struct passwd *pw;
|
||||
struct aclmember *entry;
|
||||
|
||||
(void) acl_getclass(buffer);
|
||||
limit = acl_getlimit(buffer, NULL);
|
||||
|
||||
while (*inptr) {
|
||||
if (*inptr != '%')
|
||||
*outptr++ = *inptr;
|
||||
else {
|
||||
entry = NULL;
|
||||
switch (*++inptr) {
|
||||
case 'E':
|
||||
if ( (getaclentry("email", &entry)) && ARG0 )
|
||||
sprintf(outptr, "%s", ARG0);
|
||||
else
|
||||
*outptr = '\0';
|
||||
break;
|
||||
case 'N':
|
||||
sprintf(outptr, "%d", acl_countusers(buffer));
|
||||
break;
|
||||
case 'M':
|
||||
if (limit > 0){
|
||||
sprintf(outptr, "%d", limit);
|
||||
}else{
|
||||
strcpy(outptr,"unlimited");
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
(void) time(&curtime);
|
||||
strncpy(outptr, ctime(&curtime), 24);
|
||||
*(outptr + 24) = '\0';
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
#if defined(HAVE_STATVFS) || defined(HAVE_SYS_VFS) || defined(HAVE_SYS_MOUNT)
|
||||
sprintf(outptr, "%lu", getSize("."));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
#define HAVE_GETCWD 1 /* Hack by HE to force getcwd, #include'ing config.h
|
||||
* should be better but causes other problems */
|
||||
#ifdef HAVE_GETCWD
|
||||
(void) getcwd(outptr, MAXPATHLEN);
|
||||
#else
|
||||
(void) getwd(outptr);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
strcpy(outptr, remotehost);
|
||||
break;
|
||||
|
||||
/*
|
||||
case 'L':
|
||||
strcpy(outptr, hostname);
|
||||
break;
|
||||
*/
|
||||
|
||||
case 'U':
|
||||
if (pw)
|
||||
strcpy(outptr, pw->pw_name);
|
||||
else
|
||||
strcpy(outptr, "[unknown]");
|
||||
break;
|
||||
|
||||
/*
|
||||
case 's':
|
||||
strncpy(outptr, shuttime, 24);
|
||||
*(outptr + 24) = '\0';
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
strncpy(outptr, disctime, 24);
|
||||
*(outptr + 24) = '\0';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
strncpy(outptr, denytime, 24);
|
||||
*(outptr + 24) = '\0';
|
||||
break;
|
||||
*/
|
||||
|
||||
/* KH : cookie %u for RFC931 name */
|
||||
/*
|
||||
case 'u':
|
||||
if (authenticated) strncpy(outptr, authuser, 24);
|
||||
else strcpy(outptr,"[unknown]");
|
||||
*(outptr + 24) = '\0';
|
||||
break;
|
||||
*/
|
||||
|
||||
case '%':
|
||||
*outptr++ = '%';
|
||||
*outptr = '\0';
|
||||
break;
|
||||
|
||||
default:
|
||||
*outptr++ = '%';
|
||||
*outptr++ = '?';
|
||||
*outptr = '\0';
|
||||
break;
|
||||
}
|
||||
while (*outptr)
|
||||
outptr++;
|
||||
}
|
||||
inptr++;
|
||||
}
|
||||
*outptr = '\0';
|
||||
}
|
||||
|
||||
void reply (int msg, char *str) {
|
||||
fprintf (stderr, "%d - %s\n", msg, str);
|
||||
}
|
||||
|
||||
|
||||
void expand_id(void) {
|
||||
struct aclmember *entry = NULL;
|
||||
struct passwd *pwent;
|
||||
struct group *grent;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
|
||||
if (ARG3 && ARG4) {
|
||||
pwent = getpwnam(ARG3);
|
||||
grent = getgrnam(ARG4);
|
||||
|
||||
if (pwent) sprintf(buf, "%d", pwent->pw_uid);
|
||||
else sprintf(buf, "%d", 0);
|
||||
ARG3 = (char *) malloc(strlen(buf) + 1);
|
||||
strcpy(ARG3, buf);
|
||||
|
||||
if (grent) sprintf(buf, "%d", grent->gr_gid);
|
||||
else sprintf(buf, "%d", 0);
|
||||
ARG4 = (char *) malloc(strlen(buf) + 1);
|
||||
strcpy(ARG4, buf);
|
||||
endgrent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,44 +0,0 @@
|
|||
#ifndef FNM_PATHNAME
|
||||
#define FNM_PATHNAME 0x01 /* Slash must be matched by slash. */
|
||||
#endif
|
||||
#ifndef FNM_NOESCAPE
|
||||
#define FNM_NOESCAPE 0x02 /* Disable backslash escaping. */
|
||||
#endif
|
||||
#ifndef FNM_PERIOD
|
||||
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
|
||||
#endif
|
||||
|
||||
#define LOG_IN 0
|
||||
#define C_WD 1
|
||||
#define BANNER 2
|
||||
|
||||
#ifndef ALIGN
|
||||
#define ALIGN(x) ((x) + (sizeof(long) - (x) % sizeof(long)))
|
||||
#endif
|
||||
|
||||
#define O_COMPRESS (1 << 0) /* file was compressed */
|
||||
#define O_UNCOMPRESS (1 << 1) /* file was uncompressed */
|
||||
#define O_TAR (1 << 2) /* file was tar'ed */
|
||||
|
||||
#define MAXARGS 50
|
||||
#define MAXKWLEN 20
|
||||
|
||||
struct aclmember {
|
||||
struct aclmember *next;
|
||||
char keyword[MAXKWLEN];
|
||||
char *arg[MAXARGS];
|
||||
};
|
||||
|
||||
#define MAXUSERS 1024
|
||||
|
||||
#define ARG0 entry->arg[0]
|
||||
#define ARG1 entry->arg[1]
|
||||
#define ARG2 entry->arg[2]
|
||||
#define ARG3 entry->arg[3]
|
||||
#define ARG4 entry->arg[4]
|
||||
#define ARG5 entry->arg[5]
|
||||
#define ARG6 entry->arg[6]
|
||||
#define ARG7 entry->arg[7]
|
||||
#define ARG8 entry->arg[8]
|
||||
#define ARG9 entry->arg[9]
|
||||
#define ARG entry->arg
|
|
@ -1,369 +0,0 @@
|
|||
/*
|
||||
* @(#) hostacc.c - Implementation of host access for the
|
||||
* experimental FTP daemon developed at
|
||||
* Washington University.
|
||||
* $Id: hostacc.c,v 1.1 1999/06/30 17:19:34 he Exp $
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* AUTHOR
|
||||
* Bart Muijzer <bartm@cv.ruu.nl>
|
||||
*
|
||||
* HISTORY
|
||||
* 930316 BM Created
|
||||
* 930317 BM Converted to local naming convention;
|
||||
* added rhost_ok(), cleanup code in enghacc()
|
||||
* 930318 BM Ported to BSD; fixed memory leaks
|
||||
* 930322 BM Changed algorithm: not in configfile = allow
|
||||
* in configfile and match = allow|deny
|
||||
* in configfile and no match = deny
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HOST_ACCESS
|
||||
|
||||
#include "hostacc.h"
|
||||
|
||||
static char linbuf[MAXLEN]; /* Buffer to hold one line of config-file */
|
||||
static char unibuf[MAXLEN]; /* Buffer to hold unified line */
|
||||
static hacc_t *ha_arr; /* Array with host access information */
|
||||
|
||||
static FILE *ptFp; /* FILE * into host access config file */
|
||||
static int iHaInd = 0; /* Index in ha_arr */
|
||||
static int iHaSize; /* Will hold actual #elems in ha_arr */
|
||||
static int iFirstTim = 1; /* Used by gethacc() to see if index in */
|
||||
/* ha_arr needs to be reset */
|
||||
|
||||
/* ------------------------------------------------------------------------ *\
|
||||
* FUNCTION : rhost_ok *
|
||||
* PURPOSE : Check if a host is allowed to make a connection *
|
||||
* ARGUMENTS : Remote user name, remote host name, remote host address *
|
||||
* RETURNS : 1 if host is granted access, 0 if not *
|
||||
\* ------------------------------------------------------------------------ */
|
||||
|
||||
int rhost_ok(pcRuser, pcRhost, pcRaddr)
|
||||
char *pcRuser,
|
||||
*pcRhost,
|
||||
*pcRaddr;
|
||||
{
|
||||
hacc_t *ptHtmp;
|
||||
char *pcHost;
|
||||
char *ha_login;
|
||||
int iInd, iLineMatch = 0, iUserSeen = 0;
|
||||
|
||||
switch(sethacc()){
|
||||
case 1:
|
||||
/* no hostaccess file; disable mechanism */
|
||||
return(1);
|
||||
break;
|
||||
case -1:
|
||||
syslog(LOG_INFO, "rhost_ok: sethacc failed");
|
||||
endhacc();
|
||||
return(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* user names "ftp" and "anonymous" are equivalent */
|
||||
if (!strcasecmp(pcRuser, "anonymous"))
|
||||
pcRuser = "ftp";
|
||||
|
||||
while (((ptHtmp = gethacc()) != (hacc_t *)NULL) && !iLineMatch)
|
||||
{
|
||||
if (strcasecmp(ptHtmp->ha_login, "anonymous"))
|
||||
ha_login = ptHtmp->ha_login;
|
||||
else
|
||||
ha_login = "ftp";
|
||||
|
||||
if ((strcasecmp(pcRuser, ha_login)) && strcmp(ha_login, "*"))
|
||||
/* wrong user, check rest of file */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We have seen a line regarding the current user.
|
||||
* Remember this.
|
||||
*/
|
||||
iUserSeen = 1;
|
||||
|
||||
for(iInd=0, pcHost=ptHtmp->ha_hosts[0];
|
||||
((pcHost != NULL) && !iLineMatch);
|
||||
pcHost=ptHtmp->ha_hosts[++iInd])
|
||||
{
|
||||
if (isdigit(*pcHost))
|
||||
{
|
||||
iLineMatch = !fnmatch(pcHost, pcRaddr, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
iLineMatch = !fnmatch(pcHost, pcRhost, NULL);
|
||||
}
|
||||
if (iLineMatch)
|
||||
{
|
||||
iLineMatch = (ptHtmp->ha_type == ALLOW) ? 1 : 0;
|
||||
goto match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match:
|
||||
/*
|
||||
* At this point, iUserSeen == 1 if we've seen lines regarding
|
||||
* the current user, and 0 otherwise. If we reached the end of
|
||||
* the config file without a match we allow. Else, we allow or
|
||||
* deny according to the rule found.
|
||||
*/
|
||||
|
||||
if (endhacc())
|
||||
{
|
||||
syslog(LOG_INFO, "rhost_ok: endhacc failed");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (iUserSeen)
|
||||
return(ptHtmp == NULL) ? 0 : iLineMatch;
|
||||
else
|
||||
/* Nothing at all about user in configfile, allow */
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ *\
|
||||
* FUNCTION : sethacc *
|
||||
* PURPOSE : Initialize data structures for host access *
|
||||
* ARGUMENTS : None *
|
||||
* RETURNS : -1 on failure, 1 if host access file doesn't exist, *
|
||||
* 0 otherwise *
|
||||
\* ------------------------------------------------------------------------ */
|
||||
|
||||
static int sethacc()
|
||||
{
|
||||
int iHaHind = 0; /* Index in list of hosts */
|
||||
char *pcBegin, *pcEnd, *pcColon;
|
||||
char *pcTmp1, *pcTmp2;
|
||||
int iHaMalloc=0; /* how many elem malloced */
|
||||
|
||||
iHaInd = 0;
|
||||
iFirstTim = 1;
|
||||
/* Open config file */
|
||||
if ((ptFp = fopen(_PATH_FTPHOSTS, "r")) == NULL)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
return(1);
|
||||
else {
|
||||
fatal("Can't open host access file");
|
||||
iHaSize = iHaInd;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
ha_arr=(hacc_t*)malloc((iHaMalloc=10)*sizeof(hacc_t));
|
||||
|
||||
while (fgets(linbuf, MAXLEN, ptFp) != NULL)
|
||||
{
|
||||
iHaHind = 0;
|
||||
|
||||
/* Find first non-whitespace character */
|
||||
for (pcBegin=linbuf;
|
||||
((*pcBegin == '\t') || (*pcBegin == ' '));
|
||||
pcBegin++)
|
||||
;
|
||||
|
||||
/* Get rid of comments */
|
||||
if ((pcEnd = strchr(linbuf, '#')) != NULL)
|
||||
*pcEnd = '\0';
|
||||
|
||||
|
||||
/* Skip empty lines */
|
||||
if ((pcBegin == pcEnd) || (*pcBegin == '\n'))
|
||||
continue;
|
||||
|
||||
/* Substitute all whitespace by a single ":" so we can
|
||||
* easily break on words later on. The easiest way is
|
||||
* to copy the result into a temporary buffer (called
|
||||
* the "unified buffer" because it will store a line in
|
||||
* the same format, regardless of the format the original
|
||||
* line was in).
|
||||
* The result will look like: "allow:name:host:host:host"
|
||||
*/
|
||||
for (pcTmp1=pcBegin, pcTmp2=unibuf; *pcTmp1; pcTmp1++)
|
||||
{
|
||||
if (*pcTmp1 != '\t' && *pcTmp1 != ' ' && *pcTmp1 != '\n')
|
||||
*pcTmp2++ = *pcTmp1;
|
||||
else
|
||||
/* whitespace */
|
||||
if (*(pcTmp2-1) == ':')
|
||||
continue;
|
||||
else
|
||||
*pcTmp2++ = ':';
|
||||
}
|
||||
|
||||
/* Throw away trailing whitespace, now indicated by
|
||||
* the last character of the unified buffer being a
|
||||
* colon. Remember where the news string ends.
|
||||
*/
|
||||
pcEnd = (*(pcTmp2 - 1) == ':') ? (pcTmp2 - 1) : pcTmp2;
|
||||
*pcEnd = '\0'; /* Terminate new string */
|
||||
|
||||
/*
|
||||
* Check if we need to expand the array with
|
||||
* host access information
|
||||
*/
|
||||
if (iHaInd >= iHaMalloc)
|
||||
{
|
||||
ha_arr=(hacc_t*)realloc(ha_arr,(iHaMalloc+=10)*sizeof(hacc_t));
|
||||
if (!ha_arr)
|
||||
{
|
||||
fatal("Failed to realloc host access array");
|
||||
iHaSize = iHaInd;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store what's left of the line into the
|
||||
* hacc_t structure. First the access type,
|
||||
* then the loginname, and finally a list of
|
||||
* hosts to which all this applies.
|
||||
*/
|
||||
pcBegin = unibuf;
|
||||
if (!strncmp(pcBegin, "deny", 4))
|
||||
{
|
||||
ha_arr[iHaInd].ha_type = DENY;
|
||||
pcBegin += 5;
|
||||
} else
|
||||
if (!strncmp(pcBegin, "allow", 5))
|
||||
{
|
||||
ha_arr[iHaInd].ha_type = ALLOW;
|
||||
pcBegin += 6;
|
||||
}
|
||||
else {
|
||||
fatal("Format error in host access file");
|
||||
iHaSize = iHaInd;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if((pcColon = strchr(pcBegin, ':')) != NULL)
|
||||
ha_arr[iHaInd].ha_login =
|
||||
strnsav(pcBegin, (pcColon-pcBegin));
|
||||
else
|
||||
{
|
||||
fatal("Format error in host access file");
|
||||
iHaSize = iHaInd;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pcBegin = pcColon+1;
|
||||
while ((pcColon = strchr(pcBegin, ':')) != NULL)
|
||||
{
|
||||
ha_arr[iHaInd].ha_hosts[iHaHind++] =
|
||||
strnsav(pcBegin, (pcColon-pcBegin));
|
||||
pcBegin = pcColon+1;
|
||||
if (iHaHind >= MAXHST)
|
||||
{
|
||||
fatal("Line too long");
|
||||
iHaSize = iHaInd;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
ha_arr[iHaInd].ha_hosts[iHaHind++] =
|
||||
strnsav(pcBegin, (pcEnd-pcBegin));
|
||||
ha_arr[iHaInd].ha_hosts[iHaHind] = NULL;
|
||||
iHaInd++;
|
||||
}
|
||||
iHaSize = iHaInd; /* Record current size of ha_arr */
|
||||
return ((feof(ptFp)) ? 0 : -1);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ *\
|
||||
* FUNCTION : gethacc *
|
||||
* PURPOSE : return pointer to the next host_access structure *
|
||||
* ARGUMENTS : None *
|
||||
* RETURNS : NULL on failure, pointervalue otherwise *
|
||||
\* ------------------------------------------------------------------------ */
|
||||
|
||||
static hacc_t *gethacc()
|
||||
{
|
||||
static int iHaInd;
|
||||
static hacc_t ptTmp;
|
||||
|
||||
if (iFirstTim)
|
||||
{
|
||||
iFirstTim = 0;
|
||||
iHaInd = 0;
|
||||
}
|
||||
if (iHaInd >= iHaSize)
|
||||
return ((hacc_t *)NULL);
|
||||
else {
|
||||
#ifdef USG
|
||||
memmove(&ptTmp, &(ha_arr[iHaInd]), sizeof(hacc_t));
|
||||
#else
|
||||
bcopy(&(ha_arr[iHaInd]), &ptTmp, sizeof(hacc_t));
|
||||
#endif
|
||||
iHaInd++;
|
||||
return(&ptTmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ *\
|
||||
* FUNCTION : endhacc *
|
||||
* PURPOSE : Free allocated data structures for host access *
|
||||
* ARGUMENTS : None *
|
||||
* RETURNS : -1 on failure, 0 otherwise *
|
||||
\* ------------------------------------------------------------------------ */
|
||||
|
||||
static int endhacc()
|
||||
{
|
||||
int iInd;
|
||||
hacc_t *ptHtmp;
|
||||
|
||||
if (ha_arr == (hacc_t*)NULL)
|
||||
return(0);
|
||||
|
||||
for (ptHtmp = ha_arr;
|
||||
ptHtmp < ha_arr + iHaSize && ptHtmp->ha_type;
|
||||
ptHtmp++)
|
||||
{
|
||||
ptHtmp->ha_type = 0;
|
||||
if (ptHtmp->ha_login) {
|
||||
free(ptHtmp->ha_login);
|
||||
ptHtmp->ha_login = NULL;
|
||||
}
|
||||
for(iInd=0;
|
||||
iInd < MAXHST && ptHtmp->ha_hosts[iInd];
|
||||
iInd++) {
|
||||
free(ptHtmp->ha_hosts[iInd]);
|
||||
ptHtmp->ha_hosts[iInd] = NULL;
|
||||
}
|
||||
}
|
||||
free(ha_arr);
|
||||
ha_arr = NULL;
|
||||
|
||||
if (ptFp && fclose(ptFp))
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void fatal(pcMsg)
|
||||
char *pcMsg;
|
||||
{
|
||||
syslog(LOG_INFO, "host_access: %s", pcMsg);
|
||||
}
|
||||
|
||||
static char *strnsav(pcStr,iLen)
|
||||
char *pcStr;
|
||||
int iLen;
|
||||
{
|
||||
char *pcBuf;
|
||||
|
||||
if ((pcBuf = (char *)malloc(iLen+1)) == NULL)
|
||||
return(NULL);
|
||||
strncpy(pcBuf,pcStr,iLen);
|
||||
pcBuf[iLen] = '\0';
|
||||
return(pcBuf);
|
||||
}
|
||||
|
||||
#endif /* HOST_ACCESS */
|
|
@ -1,596 +0,0 @@
|
|||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#define FTP_NAMES
|
||||
#include <arpa/ftp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/telnet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <setjmp.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef SYSSYSLOG
|
||||
#include <sys/syslog.h>
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#ifdef SHADOW_PASSWORD
|
||||
#include <shadow.h>
|
||||
#endif
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
char * eft_access = _PATH_FTPACCESS;
|
||||
|
||||
char remoteaddr [MAXHOSTNAMELEN];
|
||||
char remotehost [MAXHOSTNAMELEN];
|
||||
/* nameserved==1: remoteaddr!=remotehost */
|
||||
/* nameserved==0: remoteaddr==remotehost */
|
||||
int nameserved = 1;
|
||||
char guestpw[MAXHOSTNAMELEN];
|
||||
char privatepw[MAXHOSTNAMELEN];
|
||||
|
||||
int log_commands = 0;
|
||||
int logging = 0;
|
||||
|
||||
/* File transfer logging */
|
||||
int xferlog = 0;
|
||||
int log_outbound_xfers = 0;
|
||||
int log_incoming_xfers = 0;
|
||||
/* --he char logfile[MAXPATHLEN];*/
|
||||
char * logfile = _PATH_XFERLOG;
|
||||
|
||||
|
||||
int guest;
|
||||
int anonymous = 1;
|
||||
/* Make use of /etc/eftaccess ? */
|
||||
int use_accessfile = 0;
|
||||
/* How many attempts for the user to login ? */
|
||||
int lgi_failure_threshold = 5;
|
||||
/* The password structure of the logged in user */
|
||||
struct passwd *pw;
|
||||
/* The options, if (un)compressing etc. is allowed */
|
||||
int mangleopts = 0;
|
||||
char autherrmsg [256];
|
||||
|
||||
#define SPT_NONE 0 /* don't use it at all */
|
||||
#define SPT_REUSEARGV 1 /* cover argv with title information */
|
||||
#define SPT_BUILTIN 2 /* use libc builtin */
|
||||
#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
|
||||
#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
|
||||
#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
|
||||
#define SPT_SCO 6 /* write kernel u. area */
|
||||
#define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf))
|
||||
|
||||
#ifdef HAVE_DIRENT
|
||||
#include <dirent.h>
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64 /* may be too big */
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE !TRUE
|
||||
#endif
|
||||
|
||||
extern int errno;
|
||||
extern int pidfd
|
||||
;
|
||||
extern char *ctime(const time_t *);
|
||||
#ifndef NO_CRYPT_PROTO
|
||||
extern char *crypt(const char *, const char *);
|
||||
#endif
|
||||
extern FILE *ftpd_popen(char *program, char *type, int closestderr),
|
||||
*fopen(const char *, const char *),
|
||||
*freopen(const char *, const char *, FILE *);
|
||||
extern int ftpd_pclose(FILE *iop),
|
||||
fclose(FILE *);
|
||||
extern char *wu_getline(),
|
||||
*realpath(const char *pathname, char *result);
|
||||
extern char version[];
|
||||
extern char *home; /* pointer to home directory for glob */
|
||||
extern char cbuf[];
|
||||
extern off_t restart_point;
|
||||
|
||||
#ifdef VIRTUAL
|
||||
int virtual_mode=0;
|
||||
char virtual_root[MAXPATHLEN];
|
||||
char virtual_banner[MAXPATHLEN];
|
||||
#endif
|
||||
|
||||
#ifdef LOG_FAILED
|
||||
#define MAXUSERNAMELEN 32
|
||||
char the_user[MAXUSERNAMELEN];
|
||||
#endif
|
||||
|
||||
SIGNAL_TYPE lostconn(int sig);
|
||||
SIGNAL_TYPE randomsig(int sig);
|
||||
SIGNAL_TYPE myoob(int sig);
|
||||
FILE *getdatasock(char *mode),
|
||||
*dataconn(char *name, off_t size, char *mode);
|
||||
void reply(int, char *fmt, ...);
|
||||
void lreply(int, char *fmt, ...);
|
||||
|
||||
#ifdef NEED_SIGFIX
|
||||
extern sigset_t block_sigmask; /* defined in sigfix.c */
|
||||
#endif
|
||||
|
||||
struct aclmember *entry = NULL;
|
||||
|
||||
void end_login(void);
|
||||
void send_data(FILE *, FILE *, off_t);
|
||||
void dolog(struct sockaddr_in *);
|
||||
|
||||
static char ttyline[20];
|
||||
|
||||
int checkuser(char *name)
|
||||
{
|
||||
register FILE *fd;
|
||||
register char *p;
|
||||
char line[BUFSIZ];
|
||||
|
||||
if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
|
||||
while (fgets(line, sizeof(line), fd) != NULL)
|
||||
if ((p = strchr(line, '\n')) != NULL) {
|
||||
*p = '\0';
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
if (strcmp(line, name) == 0) {
|
||||
(void) fclose(fd);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
(void) fclose(fd);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Helper function for sgetpwnam(). */
|
||||
char * sgetsave(char *s)
|
||||
{
|
||||
char *new;
|
||||
|
||||
new = (char *) malloc(strlen(s) + 1);
|
||||
|
||||
if (new == NULL) {
|
||||
strcpy (autherrmsg, "Local resource failure: malloc");
|
||||
return NULL;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
(void) strcpy(new, s);
|
||||
return (new);
|
||||
}
|
||||
|
||||
/* Save the result of a getpwnam. Used for USER command, since the data
|
||||
* returned must not be clobbered by any other command (e.g., globbing). */
|
||||
struct passwd * sgetpwnam(char *name)
|
||||
{
|
||||
static struct passwd save;
|
||||
register struct passwd *p;
|
||||
char *sgetsave(char *s);
|
||||
|
||||
if ((p = getpwnam(name)) == NULL)
|
||||
return p;
|
||||
|
||||
if (save.pw_name) free(save.pw_name);
|
||||
if (save.pw_gecos) free(save.pw_gecos);
|
||||
if (save.pw_dir) free(save.pw_dir);
|
||||
if (save.pw_shell) free(save.pw_shell);
|
||||
if (save.pw_passwd) free(save.pw_passwd);
|
||||
|
||||
save = *p;
|
||||
save.pw_name = sgetsave(p->pw_name);
|
||||
if (save.pw_name==NULL) return NULL;
|
||||
save.pw_passwd = sgetsave(p->pw_passwd);
|
||||
if (save.pw_passwd==NULL) return NULL;
|
||||
#ifdef SHADOW_PASSWORD
|
||||
if (p) {
|
||||
struct spwd *spw;
|
||||
setspent();
|
||||
if ((spw = getspnam(p->pw_name)) != NULL) {
|
||||
int expired = 0;
|
||||
/*XXX Does this work on all Shadow Password Implementations? */
|
||||
/* it is supposed to work on Solaris 2.x*/
|
||||
time_t now;
|
||||
long today;
|
||||
|
||||
now = time((time_t*) 0);
|
||||
today = now / (60*60*24);
|
||||
|
||||
if ((spw->sp_expire > 0) && (spw->sp_expire < today)) expired++;
|
||||
if ((spw->sp_max > 0) && (spw->sp_lstchg > 0) &&
|
||||
(spw->sp_lstchg + spw->sp_max < today)) expired++;
|
||||
free(save.pw_passwd);
|
||||
save.pw_passwd = sgetsave(expired?"":spw->sp_pwdp);
|
||||
if (save.pw_passwd==NULL) return NULL;
|
||||
}
|
||||
/* Don't overwrite the password if the shadow read fails, getpwnam() is NIS
|
||||
aware but getspnam() is not. */
|
||||
/* Shadow passwords are optional on Linux. --marekm */
|
||||
#if !defined(LINUX) && !defined(UNIXWARE)
|
||||
else{
|
||||
free(save.pw_passwd);
|
||||
save.pw_passwd = sgetsave("");
|
||||
if (save.pw_passwd==NULL) return NULL;
|
||||
}
|
||||
#endif
|
||||
/* marekm's fix for linux proc file system shadow passwd exposure problem */
|
||||
endspent();
|
||||
}
|
||||
#endif
|
||||
save.pw_gecos = sgetsave(p->pw_gecos);
|
||||
if (save.pw_gecos==NULL) return NULL;
|
||||
save.pw_dir = sgetsave(p->pw_dir);
|
||||
if (save.pw_dir==NULL) return NULL;
|
||||
save.pw_shell = sgetsave(p->pw_shell);
|
||||
if (save.pw_shell==NULL) return NULL;
|
||||
#ifdef M_UNIX
|
||||
ret = &save;
|
||||
DONE:
|
||||
endpwent();
|
||||
#endif
|
||||
return(&save);
|
||||
}
|
||||
#ifdef SKEY
|
||||
/*
|
||||
* From Wietse Venema, Eindhoven University of Technology.
|
||||
*/
|
||||
/* skey_challenge - additional password prompt stuff */
|
||||
char *skey_challenge(char *name, struct passwd *pwd, int pwok)
|
||||
{
|
||||
static char buf[128];
|
||||
char sbuf[40];
|
||||
struct skey skey;
|
||||
|
||||
/* Display s/key challenge where appropriate. */
|
||||
|
||||
if (pwd == NULL || skeychallenge(&skey, pwd->pw_name, sbuf))
|
||||
sprintf(buf, "Password required for %s.", name);
|
||||
else
|
||||
sprintf(buf, "%s %s for %s.", sbuf,
|
||||
pwok ? "allowed" : "required", name);
|
||||
return (buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
int login_attempts; /* number of failed login attempts */
|
||||
int askpasswd; /* had user command, ask for passwd */
|
||||
|
||||
|
||||
int wuftp_check_user (char *user, char *passw, char *isdnno) {
|
||||
char *shell;
|
||||
char *getusershell();
|
||||
int passwarn = 0;
|
||||
int rval = 1;
|
||||
char *xpasswd, *salt;
|
||||
|
||||
if(access_init()) return 0;
|
||||
|
||||
strcpy (remotehost, isdnno);
|
||||
strcpy (remoteaddr, isdnno);
|
||||
nameserved = 0;
|
||||
anonymous = 0;
|
||||
acl_remove ();
|
||||
if (!strcasecmp(user, "ftp") || !strcasecmp(user, "anonymous") ||
|
||||
!user[0]) {
|
||||
struct aclmember *entry = NULL;
|
||||
int machineok=1;
|
||||
|
||||
if (checkuser("ftp") || checkuser("anonymous")) {
|
||||
sprintf (autherrmsg, "User %s access denied.", user);
|
||||
syslog(LOG_NOTICE,
|
||||
"EFT LOGIN REFUSED (eft in %s) FROM %s, %s",
|
||||
_PATH_FTPUSERS, remotehost, user);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
** Algorithm used:
|
||||
** - if no "guestserver" directive is present,
|
||||
** anonymous access is allowed, for backward compatibility.
|
||||
** - if a "guestserver" directive is present,
|
||||
** anonymous access is restricted to the isdn-numbers listed.
|
||||
**
|
||||
** the format of the "guestserver" line is
|
||||
** guestserver [<isdn-number-rule1> [<isdn-number-ruleN>]]
|
||||
** that is, "guestserver" will forbid anonymous access on all machines
|
||||
** while "guestserver 40* 30*" will allow anonymous access on
|
||||
** all callers coming from Hamburg or Berlin.
|
||||
**
|
||||
*/
|
||||
} else if (getaclentry("guestserver", &entry)
|
||||
&& entry->arg[0] && (int)strlen(entry->arg[0]) > 0) {
|
||||
int machinecount = 0;
|
||||
|
||||
machineok=0;
|
||||
for (machinecount=0;
|
||||
entry->arg[machinecount] && (entry->arg[machinecount])[0];
|
||||
machinecount++) {
|
||||
|
||||
if (!fnmatch(entry->arg[machinecount], isdnno,0)) {
|
||||
machineok++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!machineok) {
|
||||
strcpy (autherrmsg, "Guest login not allowed from given number.");
|
||||
syslog(LOG_NOTICE,
|
||||
"EFT LOGIN REFUSED (number not in guestservers) FROM %s, %s",
|
||||
remotehost, user);
|
||||
return 0;
|
||||
} else if ((pw = sgetpwnam("ftp")) != NULL) {
|
||||
anonymous = 1; /* for the access_ok call */
|
||||
if (access_ok(530) < 1) {
|
||||
sprintf (autherrmsg, "User %s access denied.", user);
|
||||
syslog(LOG_NOTICE,
|
||||
"EFT LOGIN REFUSED (access denied) FROM %s, %s",
|
||||
remotehost, user);
|
||||
return 0;
|
||||
} else {
|
||||
askpasswd = 1;
|
||||
if (use_accessfile)
|
||||
acl_setfunctions();
|
||||
}
|
||||
} else {
|
||||
sprintf (autherrmsg, "User %s unknown.", user);
|
||||
syslog(LOG_NOTICE,
|
||||
"EFT LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s",
|
||||
remotehost, user);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifdef ANON_ONLY
|
||||
/* H* fix: define the above to completely DISABLE logins by real users,
|
||||
despite ftpusers, shells, or any of that rot. You can always hang your
|
||||
"real" server off some other port, and access-control it. */
|
||||
|
||||
else { /* "ftp" or "anon" -- MARK your conditionals, okay?! */
|
||||
sprintf (autherrmsg, "User %s unknown.", user);
|
||||
syslog (LOG_NOTICE,
|
||||
"EFT LOGIN REFUSED (not anonymous) FROM %s, %s",
|
||||
remotehost, user);
|
||||
return 0;
|
||||
}
|
||||
/* fall here if username okay in any case */
|
||||
#endif /* ANON_ONLY */
|
||||
|
||||
if ((pw = sgetpwnam(user)) != NULL) {
|
||||
char *cp;
|
||||
|
||||
if ((shell = pw->pw_shell) == NULL || *shell == 0)
|
||||
shell = _PATH_BSHELL;
|
||||
while ((cp = getusershell()) != NULL)
|
||||
if (strcmp(cp, shell) == 0)
|
||||
break;
|
||||
endusershell();
|
||||
if (cp == NULL || checkuser(user)) {
|
||||
sprintf (autherrmsg, "User %s access denied.", user);
|
||||
syslog(LOG_NOTICE,
|
||||
"EFT LOGIN REFUSED (bad shell or username in %s) FROM %s, %s",
|
||||
_PATH_FTPUSERS, remotehost, user);
|
||||
pw = (struct passwd *) NULL;
|
||||
return 0;
|
||||
}
|
||||
/* if user is a member of any of the guestgroups, cause a chroot() */
|
||||
/* after they log in successfully */
|
||||
if (use_accessfile) /* see above. _H*/
|
||||
guest = acl_guestgroup(pw);
|
||||
}
|
||||
if (access_ok(530) < 1) {
|
||||
sprintf (autherrmsg, "User %s access denied.", user);
|
||||
syslog(LOG_NOTICE, "EFT LOGIN REFUSED (access denied) FROM %s, %s",
|
||||
remotehost, user);
|
||||
return 0;
|
||||
} else
|
||||
if (use_accessfile) /* see above. _H*/
|
||||
acl_setfunctions();
|
||||
|
||||
#ifdef SKEY
|
||||
#ifdef SKEY_NAME
|
||||
/* this is the old way, but freebsd uses it */
|
||||
pwok = skeyaccess(user, NULL, remotehost, remoteaddr);
|
||||
#else
|
||||
/* this is the new way */
|
||||
pwok = skeyaccess(pw, NULL, remotehost, remoteaddr);
|
||||
#endif
|
||||
#else
|
||||
#endif
|
||||
askpasswd = 1;
|
||||
/* Delay before reading passwd after first failed attempt to slow down
|
||||
* passwd-guessing programs. */
|
||||
if (login_attempts)
|
||||
sleep((unsigned) login_attempts);
|
||||
|
||||
if (!askpasswd) return 1; /* Hey man, we got it! */
|
||||
|
||||
|
||||
if (!anonymous) { /* "ftp" is only account allowed no password */
|
||||
*guestpw = '\0';
|
||||
if (pw == NULL)
|
||||
salt = "xx";
|
||||
else
|
||||
salt = pw->pw_passwd;
|
||||
xpasswd = crypt(passw, salt);
|
||||
/* The strcmp does not catch null passwords! */
|
||||
if (pw !=NULL && *pw->pw_passwd != '\0' &&
|
||||
strcmp(xpasswd, pw->pw_passwd) == 0) {
|
||||
rval = 0;
|
||||
}
|
||||
if(rval){
|
||||
strcpy (autherrmsg, "Login incorrect.");
|
||||
#ifdef LOG_FAILED
|
||||
if (! strcmp (passw, "NULL"))
|
||||
syslog(LOG_NOTICE, "REFUSED \"NULL\" from %s, %s",
|
||||
remotehost, the_user);
|
||||
else
|
||||
syslog(LOG_INFO, "failed login from %s, %s",
|
||||
remotehost, the_user);
|
||||
#endif
|
||||
acl_remove();
|
||||
|
||||
pw = NULL;
|
||||
if (++login_attempts >= lgi_failure_threshold) {
|
||||
syslog(LOG_NOTICE, "repeated login failures from %s",
|
||||
remotehost);
|
||||
exit(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* ANONYMOUS USER PROCESSING STARTS HERE */
|
||||
} else {
|
||||
char *pwin, *pwout = guestpw;
|
||||
struct aclmember *entry = NULL;
|
||||
int valid;
|
||||
|
||||
if (!*passw) {
|
||||
strcpy(guestpw, "[none_given]");
|
||||
} else {
|
||||
int cnt = sizeof(guestpw) - 2;
|
||||
|
||||
for (pwin = passw; *pwin && cnt--; pwin++)
|
||||
if (!isgraph(*pwin))
|
||||
*pwout++ = '_';
|
||||
else
|
||||
*pwout++ = *pwin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* if logging is enabled, open logfile before chroot or set group ID */
|
||||
if (log_outbound_xfers || log_incoming_xfers) {
|
||||
xferlog = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0660);
|
||||
if (xferlog < 0) {
|
||||
syslog(LOG_ERR, "cannot open logfile %s: %s", logfile,
|
||||
strerror(errno));
|
||||
xferlog = 0;
|
||||
}
|
||||
}
|
||||
|
||||
enable_signaling(); /* we can allow signals once again: kinch */
|
||||
/* if autogroup command applies to user's class change pw->pw_gid */
|
||||
if (anonymous && use_accessfile) { /* see above. _H*/
|
||||
(void) acl_autogroup(pw);
|
||||
guest = acl_guestgroup(pw); /* the new group may be a guest */
|
||||
anonymous=!guest;
|
||||
}
|
||||
|
||||
/* END AUTHENTICATION */
|
||||
login_attempts = 0; /* this time successful */
|
||||
/* SET GROUP ID STARTS HERE */
|
||||
(void) setegid((gid_t) pw->pw_gid);
|
||||
(void) initgroups(pw->pw_name, pw->pw_gid);
|
||||
|
||||
expand_id();
|
||||
|
||||
if (anonymous || guest) {
|
||||
char *sp;
|
||||
/* We MUST do a chdir() after the chroot. Otherwise the old current
|
||||
* directory will be accessible as "." outside the new root! */
|
||||
#ifdef VIRTUAL
|
||||
if (virtual_mode && !guest) {
|
||||
if (pw->pw_dir)
|
||||
free(pw->pw_dir);
|
||||
pw->pw_dir = sgetsave(virtual_root);
|
||||
}
|
||||
#endif
|
||||
/* determine root and home directory */
|
||||
|
||||
if ((sp = strstr(pw->pw_dir, "/./")) == NULL) {
|
||||
if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
|
||||
strcpy (autherrmsg, "Can't set guest privileges.");
|
||||
goto bad;
|
||||
}
|
||||
} else{
|
||||
*sp++ = '\0';
|
||||
if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
|
||||
strcpy (autherrmsg, "Can't set guest privileges.");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETREUID
|
||||
if (setreuid(-1, (uid_t) pw->pw_uid) < 0) {
|
||||
#else
|
||||
if (seteuid((uid_t) pw->pw_uid) < 0) {
|
||||
#endif
|
||||
strcpy (autherrmsg, "Can't set uid.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!anonymous && !guest) {
|
||||
if (chdir(pw->pw_dir) < 0) {
|
||||
if (chdir("/") < 0) {
|
||||
sprintf(autherrmsg, "User %s: can't change directory to %s.",
|
||||
pw->pw_name, pw->pw_dir);
|
||||
goto bad;
|
||||
} else
|
||||
strcpy(autherrmsg, "No directory! Logging in with home=/");
|
||||
}
|
||||
}
|
||||
|
||||
if (anonymous) {
|
||||
strcpy (autherrmsg, "Guest login ok, access restrictions apply.");
|
||||
if (logging)
|
||||
syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
|
||||
remotehost, passw);
|
||||
} else {
|
||||
sprintf (autherrmsg, "User %s logged in.%s", pw->pw_name, guest ?
|
||||
" Access restrictions apply." : "");
|
||||
if (logging)
|
||||
syslog(LOG_INFO, "FTP LOGIN FROM %s [%s], %s",
|
||||
remotehost, remoteaddr, pw->pw_name);
|
||||
} /* anonymous */
|
||||
|
||||
/* home = pw->pw_dir; */ /* home dir for globbing */
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
/* Forget all about it... */
|
||||
if (xferlog)
|
||||
close(xferlog);
|
||||
xferlog = 0;
|
||||
delay_signaling(); /* we can't allow any signals while euid==0: kinch */
|
||||
(void) seteuid((uid_t) 0);
|
||||
pw = NULL;
|
||||
anonymous = 0;
|
||||
guest = 0;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/* Copyright (c) 1989 The Regents of the University of California. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* University of California, Berkeley and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)$Id: pathnames.h,v 1.1 1999/06/30 17:19:36 he Exp $ based on
|
||||
* pathnames.h 5.2 (Berkeley) 6/1/90
|
||||
*/
|
||||
|
||||
|
||||
#define _PATH_EXECPATH "/bin/eft-exec"
|
||||
|
||||
#ifdef USE_ETC
|
||||
#define _PATH_FTPUSERS "/etc/eftusers"
|
||||
#define _PATH_FTPACCESS "/etc/eftaccess"
|
||||
#define _PATH_CVT "/etc/eftconversions"
|
||||
#define _PATH_PRIVATE "/etc/eftgroups"
|
||||
#else
|
||||
#ifdef USE_I4L_CONFDIR
|
||||
#define _PATH_FTPUSERS CONFIG_I4L_CONFDIR "/eftusers"
|
||||
#define _PATH_FTPACCESS CONFIG_I4L_CONFDIR "/eftaccess"
|
||||
#define _PATH_CVT CONFIG_I4L_CONFDIR "/eftconversions"
|
||||
#define _PATH_PRIVATE CONFIG_I4L_CONFDIR "/eftgroups"
|
||||
#else
|
||||
#ifdef USE_ETC_EFTD
|
||||
#define _PATH_FTPUSERS "/etc/eftd/eftusers"
|
||||
#define _PATH_FTPACCESS "/etc/eftd/eftaccess"
|
||||
#define _PATH_CVT "/etc/eftd/eftconversions"
|
||||
#define _PATH_PRIVATE "/etc/eftd/eftgroups"
|
||||
#else
|
||||
#ifdef USE_LOCAL_ETC
|
||||
#define _PATH_FTPUSERS "/usr/local/etc/eftusers"
|
||||
#define _PATH_FTPACCESS "/usr/local/etc/eftaccess"
|
||||
#define _PATH_CVT "/usr/local/etc/eftconversions"
|
||||
#define _PATH_PRIVATE "/usr/local/etc/eftgroups"
|
||||
#else
|
||||
#define _PATH_FTPUSERS "/usr/local/lib/eftd/eftusers"
|
||||
#define _PATH_FTPACCESS "/usr/local/lib/eftd/eftaccess"
|
||||
#define _PATH_CVT "/usr/local/lib/eftd/eftconversions"
|
||||
#define _PATH_PRIVATE "/usr/local/lib/eftd/eftgroups"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_VAR
|
||||
#ifdef USE_PID
|
||||
#define _PATH_PIDNAMES "/var/pid/eft.pids-%s"
|
||||
#else
|
||||
#ifdef VAR_RUN
|
||||
#define _PATH_PIDNAMES "/var/run/eft.pids-%s"
|
||||
#else
|
||||
#define _PATH_PIDNAMES "/var/adm/eft.pids-%s"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_LOG
|
||||
#define _PATH_XFERLOG "/var/log/xferlog"
|
||||
#else
|
||||
#define _PATH_XFERLOG "/var/adm/xferlog"
|
||||
#endif
|
||||
#else
|
||||
#ifndef _PATH_PIDNAMES
|
||||
#define _PATH_PIDNAMES "/usr/local/lib/eftd/pids/%s"
|
||||
#endif
|
||||
#ifndef _PATH_XFERLOG
|
||||
#define _PATH_XFERLOG "/usr/local/logs/xferlog"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_UTMP
|
||||
#ifdef UTMP_FILE
|
||||
#define _PATH_UTMP UTMP_FILE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_WTMP
|
||||
#ifdef WTMP_FILE
|
||||
#define _PATH_WTMP WTMP_FILE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_UTMP
|
||||
#define _PATH_UTMP "/etc/utmp"
|
||||
#endif
|
||||
#ifndef _PATH_WTMP
|
||||
#define _PATH_WTMP "/usr/adm/wtmp"
|
||||
#endif
|
||||
#ifndef _PATH_LASTLOG
|
||||
#ifdef SOLARIS_2
|
||||
#define _PATH_LASTLOG "/var/adm/lastlog"
|
||||
#else
|
||||
#define _PATH_LASTLOG "/usr/adm/lastlog"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_BSHELL
|
||||
#define _PATH_BSHELL "/bin/sh"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_DEVNULL
|
||||
#define _PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
#ifdef HOST_ACCESS
|
||||
#ifdef USE_ETC
|
||||
#define _PATH_FTPHOSTS "/etc/efthosts"
|
||||
#else
|
||||
#ifdef USE_I4L_CONFDIR
|
||||
#define _PATH_FTPHOSTS CONFIG_I4L_CONFDIR "/efthosts"
|
||||
#else
|
||||
#ifdef USE_ETC_FTPD
|
||||
#define _PATH_FTPHOSTS "/etc/eftd/efthosts"
|
||||
#else
|
||||
#ifdef USE_LOCAL_ETC
|
||||
#define _PATH_FTPHOSTS "/usr/local/etc/efthosts"
|
||||
#else
|
||||
#define _PATH_FTPHOSTS "/usr/local/lib/eftd/efthosts"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -1,326 +0,0 @@
|
|||
/* Copyright (c) 1993, 1994 Washington University in Saint Louis
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer. 2.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution. 3. All advertising
|
||||
* materials mentioning features or use of this software must display the
|
||||
* following acknowledgement: This product includes software developed by the
|
||||
* Washington University in Saint Louis and its contributors. 4. Neither the
|
||||
* name of the University nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASHINGTON
|
||||
* UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#)$Id: private.c,v 1.1 1999/06/30 17:19:37 he Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_PRIVATE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#ifdef SYSSYSLOG
|
||||
#include <sys/syslog.h>
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <grp.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#define MAXGROUPLEN 100
|
||||
char *passbuf = NULL;
|
||||
char groupname[MAXGROUPLEN];
|
||||
int group_given = 0;
|
||||
|
||||
struct acgrp {
|
||||
char gname[MAXGROUPLEN]; /* access group name */
|
||||
char gpass[MAXGROUPLEN]; /* access group password */
|
||||
char gr_name[MAXGROUPLEN]; /* group to setgid() to */
|
||||
gid_t gr_gid;
|
||||
struct acgrp *next;
|
||||
};
|
||||
|
||||
struct acgrp *privptr;
|
||||
|
||||
extern int lgi_failure_threshold,
|
||||
autospout_free;
|
||||
extern char remotehost[],
|
||||
remoteaddr[],
|
||||
*autospout;
|
||||
int group_attempts;
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
parsepriv(void)
|
||||
#else
|
||||
parsepriv()
|
||||
#endif
|
||||
{
|
||||
char *ptr;
|
||||
char *acptr = passbuf,
|
||||
*line;
|
||||
char *argv[3],
|
||||
*p,
|
||||
*val;
|
||||
struct acgrp *aptr,
|
||||
*privtail = (struct acgrp *) NULL;
|
||||
struct group *gr;
|
||||
int n;
|
||||
|
||||
if (!passbuf || !(*passbuf))
|
||||
return;
|
||||
|
||||
/* read through passbuf, stripping comments. */
|
||||
while (*acptr != '\0') {
|
||||
line = acptr;
|
||||
while (*acptr && *acptr != '\n')
|
||||
acptr++;
|
||||
*acptr++ = '\0';
|
||||
|
||||
/* deal with comments */
|
||||
if ((ptr = strchr(line, '#')) != NULL)
|
||||
*ptr = '\0';
|
||||
|
||||
if (*line == '\0')
|
||||
continue;
|
||||
|
||||
/* parse the lines... */
|
||||
for (n = 0, p = line; n < 3 && p != NULL; n++) {
|
||||
while ((val = (char *) strsep(&p, ":\n")) != NULL
|
||||
&& *val == '\0' && p != NULL)
|
||||
;
|
||||
argv[n] = val;
|
||||
if (argv[n][0] == ' ')
|
||||
argv[n] = NULL;
|
||||
}
|
||||
/* check their were 3 fields, if not skip the line... */
|
||||
if (n != 3 || p != NULL)
|
||||
continue;
|
||||
|
||||
if ((gr = getgrnam((char *) argv[2])) != NULL) {
|
||||
aptr = (struct acgrp *) calloc(1, sizeof(struct acgrp));
|
||||
|
||||
/* add element to end of list */
|
||||
if (privtail)
|
||||
privtail->next = aptr;
|
||||
privtail = aptr;
|
||||
if (!privptr)
|
||||
privptr = aptr;
|
||||
|
||||
strcpy(aptr->gname, (char *) argv[0]);
|
||||
strcpy(aptr->gpass, (char *) argv[1]);
|
||||
strcpy(aptr->gr_name, (char *) argv[2]);
|
||||
aptr->gr_gid = gr->gr_gid;
|
||||
}
|
||||
endgrent();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : priv_setup */
|
||||
/* PURPOSE : Set things up to use the private access password file. */
|
||||
/* ARGUMENTS : path, the path to the private access password file */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
priv_setup(char *path)
|
||||
#else
|
||||
priv_setup(path)
|
||||
char *path;
|
||||
#endif
|
||||
{
|
||||
FILE *prvfile;
|
||||
struct stat finfo;
|
||||
|
||||
passbuf = (char *) NULL;
|
||||
|
||||
if ((prvfile = fopen(path, "r")) == NULL) {
|
||||
if (errno != ENOENT)
|
||||
syslog(LOG_ERR, "cannot open private access file %s: %s",
|
||||
path, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (fstat(fileno(prvfile), &finfo) != 0) {
|
||||
syslog(LOG_ERR, "cannot fstat private access file %s: %s", path,
|
||||
strerror(errno));
|
||||
(void) fclose(prvfile);
|
||||
return;
|
||||
}
|
||||
if (finfo.st_size == 0) {
|
||||
passbuf = (char *) calloc(1, 1);
|
||||
} else {
|
||||
if (!(passbuf = (char *)malloc((unsigned) finfo.st_size + 1))) {
|
||||
(void) syslog(LOG_ERR, "could not malloc passbuf (%d bytes)",
|
||||
finfo.st_size + 1);
|
||||
(void) fclose(prvfile);
|
||||
return;
|
||||
}
|
||||
if (!fread(passbuf, (size_t) finfo.st_size, 1, prvfile)) {
|
||||
(void) syslog(LOG_ERR, "error reading private access file %s: %s",
|
||||
path, strerror(errno));
|
||||
(void) fclose(prvfile);
|
||||
return;
|
||||
}
|
||||
*(passbuf + finfo.st_size) = '\0';
|
||||
}
|
||||
(void) fclose(prvfile);
|
||||
(void) parsepriv();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : priv_getent */
|
||||
/* PURPOSE : Retrieve an entry from the in-memory copy of the group */
|
||||
/* access file. */
|
||||
/* ARGUMENTS : pointer to group name */
|
||||
/*************************************************************************/
|
||||
|
||||
struct acgrp *
|
||||
#ifdef __STDC__
|
||||
priv_getent(char *group)
|
||||
#else
|
||||
priv_getent(group)
|
||||
char *group;
|
||||
#endif
|
||||
{
|
||||
struct acgrp *ptr;
|
||||
|
||||
for (ptr = privptr; ptr; ptr=ptr->next)
|
||||
if (!strcmp(group, ptr->gname))
|
||||
return(ptr);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : priv_group */
|
||||
/* PURPOSE : */
|
||||
/* ARGUMENTS : */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
priv_group(char *group)
|
||||
#else
|
||||
priv_group(group)
|
||||
char *group;
|
||||
#endif
|
||||
{
|
||||
if ((int)strlen(group) < MAXGROUPLEN) {
|
||||
strncpy(groupname, group, MAXGROUPLEN);
|
||||
group_given = 1;
|
||||
reply(200, "Request for access to group %s accepted.", group);
|
||||
} else {
|
||||
group_given = 0;
|
||||
reply(500, "Illegal group name");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* FUNCTION : priv_gpass */
|
||||
/* PURPOSE : validate the group access request, and if OK place user */
|
||||
/* in the proper group. */
|
||||
/* ARGUMENTS : group access password */
|
||||
/*************************************************************************/
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
priv_gpass(char *gpass)
|
||||
#else
|
||||
priv_gpass(gpass)
|
||||
char *gpass;
|
||||
#endif
|
||||
{
|
||||
char *xgpass,
|
||||
*salt;
|
||||
#ifndef NO_CRYPT_PROTO
|
||||
#ifdef __STDC__
|
||||
char *crypt(const char *, const char *);
|
||||
#else
|
||||
#ifdef _M_UNIX
|
||||
char *crypt(char *, char *);
|
||||
#else
|
||||
char *crypt();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
struct acgrp *grp;
|
||||
struct group *gr;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
if (group_given == 0) {
|
||||
reply(503, "Give group name with SITE GROUP first.");
|
||||
return;
|
||||
}
|
||||
/* OK, now they're getting a chance to specify a password. Make them
|
||||
* give the group name again if they fail... */
|
||||
group_given = 0;
|
||||
|
||||
if (passbuf != NULL) {
|
||||
grp = priv_getent(groupname);
|
||||
|
||||
if (grp == NULL)
|
||||
salt = "xx"; /* XXX */
|
||||
else
|
||||
salt = grp->gpass;
|
||||
|
||||
xgpass = crypt(gpass, salt);
|
||||
} else
|
||||
grp = NULL;
|
||||
|
||||
/* The strcmp does not catch null passwords! */
|
||||
if (grp == NULL || *grp->gpass == '\0' || strcmp(xgpass, grp->gpass)) {
|
||||
reply(530, "Group access request incorrect.");
|
||||
grp = NULL;
|
||||
if (++group_attempts >= lgi_failure_threshold) {
|
||||
syslog(LOG_NOTICE,
|
||||
"repeated group access failures from %s [%s], group %s",
|
||||
remotehost, remoteaddr, groupname);
|
||||
exit(0);
|
||||
}
|
||||
sleep(group_attempts); /* slow down password crackers */
|
||||
return;
|
||||
}
|
||||
|
||||
uid = geteuid();
|
||||
gid = grp->gr_gid;
|
||||
|
||||
delay_signaling(); /* we can't allow any signals while euid==0: kinch */
|
||||
seteuid(0);
|
||||
setegid(gid);
|
||||
seteuid(uid);
|
||||
enable_signaling(); /* we can allow signals once again: kinch */
|
||||
|
||||
reply(200, "Group access enabled.");
|
||||
group_attempts = 0;
|
||||
}
|
||||
#endif /* !NO_PRIVATE */
|
|
@ -1,80 +0,0 @@
|
|||
/* This software is Copyright 1997 by Stan Barber.
|
||||
*
|
||||
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
|
||||
* use this software as long as: there is no monetary profit gained
|
||||
* specifically from the use or reproduction of this software, it is not
|
||||
* sold, rented, traded or otherwise marketed, and this copyright notice is
|
||||
* included prominently in any copy made.
|
||||
*
|
||||
* The author make no claims as to the fitness or correctness of this software
|
||||
* for any use whatsoever, and it is provided as is. Any use of this software
|
||||
* is at the user's own risk.
|
||||
*/
|
||||
#ifndef lint
|
||||
static char * rcsid = "$Id: sigfix.c,v 1.1 1999/06/30 17:19:37 he Exp $";
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* delay_signaling(), enable_signaling - delay signal delivery for a while
|
||||
*
|
||||
* Original Author: Wietse Venema with small changes by Dave Kinchlea and
|
||||
* Stan Barber
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some folks (notably those who do Linux hacking) say this fix is needed.
|
||||
* Others (notably the FreeBSD and BSDI folks) say if isn't.
|
||||
* I am making it possible to include of exclude it.
|
||||
* Just define NEED_SIGFIX and you get it.
|
||||
*/
|
||||
#ifdef NEED_SIGFIX
|
||||
#include <sys/types.h>
|
||||
#include <sys/signal.h>
|
||||
#include <syslog.h>
|
||||
|
||||
static sigset_t saved_sigmask;
|
||||
sigset_t block_sigmask; /* used in ftpd.c */
|
||||
static int delaying;
|
||||
static int init_done;
|
||||
#endif
|
||||
/* enable_signaling - deliver delayed signals and disable signal delay */
|
||||
|
||||
#ifdef __STDC__
|
||||
int enable_signaling(void)
|
||||
#else
|
||||
int enable_signaling()
|
||||
#endif
|
||||
{
|
||||
#ifdef NEED_SIGFIX
|
||||
if (delaying != 0) {
|
||||
delaying = 0;
|
||||
if (sigprocmask(SIG_SETMASK, &saved_sigmask, (sigset_t *) 0) < 0) {
|
||||
syslog(LOG_ERR, "sigprocmask: %m");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* delay_signaling - save signal mask and block all signals */
|
||||
#ifdef __STDC__
|
||||
int delay_signaling(void)
|
||||
#else
|
||||
int delay_signaling()
|
||||
#endif
|
||||
{
|
||||
#ifdef NEED_SIGFIX
|
||||
if (delaying == 0) {
|
||||
delaying = 1;
|
||||
if (sigprocmask(SIG_BLOCK, &block_sigmask, &saved_sigmask) < 0) {
|
||||
syslog(LOG_ERR, "sigprocmask: %m");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that: (1) source distributions retain this entire copyright
|
||||
* notice and comment, and (2) distributions including binaries display
|
||||
* the following acknowledgement: ``This product includes software
|
||||
* developed by the University of California, Berkeley and its contributors''
|
||||
* in the documentation or other materials provided with the distribution
|
||||
* and in all advertising materials mentioning features or use of this
|
||||
* software. Neither the name of the University nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)strcasestr.c 5.1 (Berkeley) 5/15/90";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <string.h>
|
||||
/*
|
||||
* Find the first occurrence of find in s.
|
||||
*/
|
||||
char *
|
||||
#ifdef __STDC__
|
||||
strcasestr(register char *s, register char *find)
|
||||
#else
|
||||
strcasestr(s,find)
|
||||
register char *s;
|
||||
register char *find;
|
||||
#endif
|
||||
{
|
||||
register char c,
|
||||
sc;
|
||||
register size_t len;
|
||||
|
||||
if ((c = *find++) != 0) {
|
||||
len = strlen(find);
|
||||
do {
|
||||
do {
|
||||
if ((sc = *s++) == 0)
|
||||
return (NULL);
|
||||
} while (sc != c);
|
||||
} while (strncasecmp(s, find, len) != 0);
|
||||
s--;
|
||||
}
|
||||
return ((char *) s);
|
||||
}
|
Loading…
Reference in New Issue