/* Copyright (C) 1999 Beau Kuiper
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "ftpd.h"
#include "auth.h"
/* This file contains code to autheticate against unix password files */
typedef struct
{
struct passwd *passent;
#ifdef HAVE_GETSPNAM
struct spwd *sppassent;
#endif
} PASSWDSTRUCT;
int getday(void)
{
time_t currenttime = time(NULL);
struct tm *currenttm = localtime(¤ttime);
int yeardif = currenttm->tm_year - 70;
int days;
days = yeardif * 365 + currenttm->tm_yday;
/* THIS STUFF IS Y2K COMPLIANT */
days += (yeardif + 1) / 4;
/* I don't ever expect this code to be used beyond 2100, but so did
too many cobol programmers in the 1970's !! */
if (currenttm->tm_year > 200) /* simple algorithm */
{
yeardif -= 31;
days -= (yeardif) / 100; /* take centaries off */
days += (yeardif) / 400; /* add on 400 year leapyears */
}
return(days);
}
void *unixauth_gethandle(FTPSTATE *peer, TOKENSET *tset, char *username, int *err)
{
PASSWDSTRUCT *newhandle;
char *passwdmode;
newhandle = mallocwrapper(sizeof(PASSWDSTRUCT));
passwdmode = mktokconfstr(tset, auth_getcursectionid(peer), "unix_passwdtype", "");
newhandle->passent = getpwnam(username);
if (newhandle->passent == NULL)
goto error;
#ifdef HAVE_GETSPNAM
/* this will try to autodetect shadow passwordness */
if ((strcasecmp(passwdmode, "shadow") == 0) ||
(strcmp(newhandle->passent->pw_passwd, "x") == 0))
{
if (strcasecmp(passwdmode, "normal") == 0)
newhandle->sppassent = NULL;
else
{
newhandle->sppassent = getspnam(username);
if (newhandle->sppassent == NULL)
goto error;
}
}
else
newhandle->sppassent = NULL;
#endif
freewrapper(passwdmode);
*err = AUTH_OK;
return(newhandle);
error:
*err = AUTH_USERNKNOW;
freewrapper(passwdmode);
freewrapper(newhandle);
return(NULL);
}
void unixauth_freehandle(void *handle)
{
freewrapper(handle);
}
int unixauth_checkpasswd(void *h, char *password, char **errmsg)
{
PASSWDSTRUCT *handle = (PASSWDSTRUCT *)h;
#ifdef HAVE_GETSPNAM
if (handle->sppassent)
{
int days = getday();
int expiredate = handle->sppassent->sp_max + handle->sppassent->sp_lstchg +
+ handle->sppassent->sp_inact;
/* do the account expiration checking! */
if ((days > handle->sppassent->sp_expire) &&
(handle->sppassent->sp_expire != -1))
{
*errmsg = safe_snprintf("Account has expired");
return(FALSE);
}
if ((handle->sppassent->sp_inact != -1) && (handle->sppassent->sp_max != -1)
&& (handle->sppassent->sp_lstchg != -1) && (days > expiredate))
{
*errmsg = safe_snprintf("Account disabled, needs new password");
return(FALSE);
}
return(chkpassword(handle->sppassent->sp_pwdp, password));
}
#endif
return(chkpassword(handle->passent->pw_passwd, password));
}
char *unixauth_gethomedir(void *h)
{
return(((PASSWDSTRUCT *)h)->passent->pw_dir);
}
char *unixauth_getrootdir(void *h)
{
return("/");
}
uid_t unixauth_getuseruid(void *h)
{
return(((PASSWDSTRUCT *)h)->passent->pw_uid);
}
gid_t unixauth_getusergid(void *h)
{
return(((PASSWDSTRUCT *)h)->passent->pw_gid);
}
gid_t *unixauth_getusersupgid(void *h)
{
return(getusergrouplist(((PASSWDSTRUCT *)h)->passent->pw_name));
}
PERMSTRUCT unixauth_commands =
{
unixauth_checkpasswd,
unixauth_gethomedir,
unixauth_getrootdir,
unixauth_getuseruid,
unixauth_getusergid,
unixauth_getusersupgid,
unixauth_gethandle,
unixauth_freehandle,
NULL,
};
syntax highlighted by Code2HTML, v. 0.9.1