From 3baeeab4e76b39db7fbda889a35c22cddb29bc22 Mon Sep 17 00:00:00 2001 From: millert <> Date: Sun, 26 Nov 2000 01:27:19 +0000 Subject: [PATCH] login_check_expire(3), a helper function for use with BSD authentication. This lives in libutil because it uses pw_lock(3) and friends. Needs a man page (soon!). --- src/lib/libutil/Makefile | 8 +- src/lib/libutil/check_expire.c | 191 +++++++++++++++++++++++++++++++++ src/lib/libutil/util.h | 3 +- 3 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 src/lib/libutil/check_expire.c diff --git a/src/lib/libutil/Makefile b/src/lib/libutil/Makefile index 776a817a..2bb0ad8e 100644 --- a/src/lib/libutil/Makefile +++ b/src/lib/libutil/Makefile @@ -1,13 +1,13 @@ -# $OpenBSD: Makefile,v 1.19 1999/11/11 06:30:40 ericj Exp $ +# $OpenBSD: Makefile,v 1.20 2000/11/26 01:27:19 millert Exp $ # $NetBSD: Makefile,v 1.8 1996/05/16 07:03:28 thorpej Exp $ LIB= util CFLAGS+=-DLIBC_SCCS HDRS= util.h scsi.h -SRCS= getmaxpartitions.c getrawpartition.c login.c login_tty.c logout.c \ - logwtmp.c opendev.c passwd.c pty.c readlabel.c scsi.c login_fbtab.c \ - uucplock.c fparseln.c opendisk.c +SRCS= check_expire.c getmaxpartitions.c getrawpartition.c login.c \ + login_tty.c logout.c logwtmp.c opendev.c passwd.c pty.c readlabel.c \ + scsi.c login_fbtab.c uucplock.c fparseln.c opendisk.c MAN= getmaxpartitions.3 getrawpartition.3 login.3 opendev.3 openpty.3 \ pw_init.3 pw_lock.3 readlabelfs.3 scsi.3 pw_getconf.3 uucplock.3 \ diff --git a/src/lib/libutil/check_expire.c b/src/lib/libutil/check_expire.c new file mode 100644 index 00000000..dbc99754 --- /dev/null +++ b/src/lib/libutil/check_expire.c @@ -0,0 +1,191 @@ +/* $OpenBSD: check_expire.c,v 1.1 2000/11/26 01:27:19 millert Exp $ */ + +/* + * Copyright (c) 1997 Berkeley Software Design, Inc. 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 Berkeley Software Design, + * Inc. + * 4. The name of Berkeley Software Design, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``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 BERKELEY SOFTWARE DESIGN, INC. 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. + * + * BSDI $From: check_expire.c,v 2.1 1997/08/08 18:38:25 prb Exp $ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static char *pwd_update __P((struct passwd *)); + +int +login_check_expire(back, pwd, class, lastchance) + FILE *back; + struct passwd *pwd; + char *class; + int lastchance; +{ + auth_session_t *as; + login_cap_t *lc; + quad_t dead, expire, warn; + char *p; + + if ((as = auth_open()) == NULL) { + syslog(LOG_ERR, "failed to create auth session"); + return (1); + } + if (auth_setpwd(as, pwd) < 0) { + syslog(LOG_ERR, "failed to set pwd entry in auth session"); + return (1); + } + + expire = auth_check_change(as); + auth_close(as); + + if (expire != 0) { + fprintf(back, BI_VALUE " expire %qd\n", expire); + + if (class == NULL) + class = pwd->pw_class; + + if ((lc = login_getclass(class)) == NULL) { + dead = 0; + warn = 0; + } else { + dead = login_getcaptime(lc, "password-dead", 0, 0); + warn = login_getcaptime(lc, "password-warn", + 2 * DAYSPERWEEK * SECSPERDAY, + 2 * DAYSPERWEEK * SECSPERDAY); + if (dead < 0) { + syslog(LOG_ERR, "class %s password-dead is %qd", + lc->lc_class, dead); + dead = 0; + } + if (warn < 0) { + syslog(LOG_ERR, "class %s password-warn is %qd", + lc->lc_class, warn); + warn = 0; + } + } + + /* + * If their password is dead (expired longer than + * password-dead) then just reject them. If it is + * expired but not dead yet, reject them with a + * PWEXPIRED so login knows they can still sort of + * get in. + */ + if (expire < -dead) { + syslog(LOG_WARNING, "%s: dead password", pwd->pw_name); + fprintf(back, BI_VALUE + " errormsg Your password has expired\n"); + fprintf(back, BI_REJECT "\n"); + return (1); + } + if (expire < 0) { + if (lastchance) { + endpwent(); + + /* + * Only let them play this game once. + * Set their password change time to 1. + * This will most certainly cause any + * expired password to be dead, as well. + */ + pwd = pw_dup(pwd); + pwd->pw_change = 1; + p = pwd_update(pwd); + memset(pwd->pw_passwd, 0, + strlen(pwd->pw_passwd)); + free(pwd); + if (p != NULL) { + fprintf(back, BI_VALUE " errormsg %s", + auth_mkvalue(p)); + fprintf(back, BI_REJECT "\n"); + return (1); + } + } + syslog(LOG_WARNING, "%s: expired password", pwd->pw_name); + fprintf(back, BI_VALUE + " errormsg Your password has expired\n"); + fprintf(back, BI_PWEXPIRED "\n"); + return (1); + } + + /* + * If their password is not expired but is about to expire + * then warn them. + */ + if (expire <= warn) { + fprintf(back, BI_VALUE + " warnmsg Your password expires on %s\n", + ctime(&pwd->pw_change)); + } + } + return (0); +} + +static char * +pwd_update(pwd) + struct passwd *pwd; +{ + int tfd, pfd; + + pw_init(); + tfd = pw_lock(0); + if (tfd < 0) { + if (errno == EEXIST) + return("the passwd file is busy."); + else + return("can't open passwd temp file"); + } + + pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); + if (pfd < 0 || fcntl(pfd, F_SETFD, 1) == -1) { + pw_abort(); + return(strerror(errno)); + } + + pw_copy(pfd, tfd, pwd); + if (pw_mkdb(pwd->pw_name) < 0) { + pw_abort(); + return("unable to update password database"); + } + + return(NULL); +} diff --git a/src/lib/libutil/util.h b/src/lib/libutil/util.h index b8082ae4..070c0230 100644 --- a/src/lib/libutil/util.h +++ b/src/lib/libutil/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.11 2000/11/26 01:25:33 millert Exp $ */ +/* $OpenBSD: util.h,v 1.12 2000/11/26 01:27:19 millert Exp $ */ /* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */ /*- @@ -87,6 +87,7 @@ pid_t forkpty __P((int *, char *, struct termios *, struct winsize *)); int getmaxpartitions __P((void)); int getrawpartition __P((void)); void login_fbtab __P((char *, uid_t, gid_t)); +int login_check_expire __P((FILE *, struct passwd *, char *, int)); char *readlabelfs __P((char *, int)); const char *uu_lockerr __P((int _uu_lockresult)); int uu_lock __P((const char *_ttyname));