1*b7041c07Sderaadt /* $OpenBSD: check_expire.c,v 1.14 2021/10/24 21:24:20 deraadt Exp $ */
2acc2517fSmillert
3acc2517fSmillert /*
4acc2517fSmillert * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
5acc2517fSmillert *
6acc2517fSmillert * Redistribution and use in source and binary forms, with or without
7acc2517fSmillert * modification, are permitted provided that the following conditions
8acc2517fSmillert * are met:
9acc2517fSmillert * 1. Redistributions of source code must retain the above copyright
10acc2517fSmillert * notice, this list of conditions and the following disclaimer.
11acc2517fSmillert * 2. Redistributions in binary form must reproduce the above copyright
12acc2517fSmillert * notice, this list of conditions and the following disclaimer in the
13acc2517fSmillert * documentation and/or other materials provided with the distribution.
14acc2517fSmillert * 3. All advertising materials mentioning features or use of this software
15acc2517fSmillert * must display the following acknowledgement:
16acc2517fSmillert * This product includes software developed by Berkeley Software Design,
17acc2517fSmillert * Inc.
18acc2517fSmillert * 4. The name of Berkeley Software Design, Inc. may not be used to endorse
19acc2517fSmillert * or promote products derived from this software without specific prior
20acc2517fSmillert * written permission.
21acc2517fSmillert *
22acc2517fSmillert * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
23acc2517fSmillert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24acc2517fSmillert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25acc2517fSmillert * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
26acc2517fSmillert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27acc2517fSmillert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28acc2517fSmillert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29acc2517fSmillert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30acc2517fSmillert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31acc2517fSmillert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32acc2517fSmillert * SUCH DAMAGE.
33acc2517fSmillert *
34acc2517fSmillert * BSDI $From: check_expire.c,v 2.1 1997/08/08 18:38:25 prb Exp $
35acc2517fSmillert */
36acc2517fSmillert
37acc2517fSmillert #include <sys/types.h>
38acc2517fSmillert
39acc2517fSmillert #include <errno.h>
40acc2517fSmillert #include <fcntl.h>
41acc2517fSmillert #include <pwd.h>
42acc2517fSmillert #include <signal.h>
43acc2517fSmillert #include <stdio.h>
44acc2517fSmillert #include <stdlib.h>
45acc2517fSmillert #include <string.h>
46acc2517fSmillert #include <time.h>
47acc2517fSmillert #include <login_cap.h>
48acc2517fSmillert #include <bsd_auth.h>
49acc2517fSmillert
5079822b59Smillert #include "util.h"
5179822b59Smillert
529a60272cSmillert static char *pwd_update(const struct passwd *, const struct passwd *);
53acc2517fSmillert
54f7055df5Smillert #define SECSPERDAY (24 * 60 * 60)
55f7055df5Smillert #define TWOWEEKS (2 * 7 * SECSPERDAY)
56f7055df5Smillert
57acc2517fSmillert int
login_check_expire(FILE * back,struct passwd * pwd,char * class,int lastchance)589a60272cSmillert login_check_expire(FILE *back, struct passwd *pwd, char *class, int lastchance)
59acc2517fSmillert {
60acc2517fSmillert auth_session_t *as;
61acc2517fSmillert login_cap_t *lc;
62acc2517fSmillert quad_t dead, expire, warn;
63acc2517fSmillert char *p;
64acc2517fSmillert
65acc2517fSmillert if ((as = auth_open()) == NULL) {
661e50994aSmillert fprintf(back, BI_VALUE
671e50994aSmillert " errormsg Unable to create auth session\n");
681e50994aSmillert fprintf(back, BI_REJECT "\n");
69acc2517fSmillert return (1);
70acc2517fSmillert }
71acc2517fSmillert if (auth_setpwd(as, pwd) < 0) {
721e50994aSmillert fprintf(back, BI_VALUE
731e50994aSmillert " errormsg Unable to set pwd entry in auth session\n");
741e50994aSmillert fprintf(back, BI_REJECT "\n");
75acc2517fSmillert return (1);
76acc2517fSmillert }
77acc2517fSmillert
78acc2517fSmillert expire = auth_check_change(as);
79acc2517fSmillert auth_close(as);
80acc2517fSmillert
81acc2517fSmillert if (expire != 0) {
82acc2517fSmillert fprintf(back, BI_VALUE " expire %qd\n", expire);
83acc2517fSmillert
84acc2517fSmillert if (class == NULL)
85acc2517fSmillert class = pwd->pw_class;
86acc2517fSmillert
87acc2517fSmillert if ((lc = login_getclass(class)) == NULL) {
88acc2517fSmillert dead = 0;
89acc2517fSmillert warn = 0;
90acc2517fSmillert } else {
91acc2517fSmillert dead = login_getcaptime(lc, "password-dead", 0, 0);
92acc2517fSmillert warn = login_getcaptime(lc, "password-warn",
93f7055df5Smillert TWOWEEKS, TWOWEEKS);
941e50994aSmillert if (dead < 0)
95acc2517fSmillert dead = 0;
961e50994aSmillert if (warn < 0)
97acc2517fSmillert warn = 0;
98acc2517fSmillert }
99a7d05627Smpech login_close(lc);
100acc2517fSmillert
101acc2517fSmillert /*
102acc2517fSmillert * If their password is dead (expired longer than
103acc2517fSmillert * password-dead) then just reject them. If it is
104acc2517fSmillert * expired but not dead yet, reject them with a
105acc2517fSmillert * PWEXPIRED so login knows they can still sort of
106acc2517fSmillert * get in.
107acc2517fSmillert */
108acc2517fSmillert if (expire < -dead) {
109acc2517fSmillert fprintf(back, BI_VALUE
110acc2517fSmillert " errormsg Your password has expired\n");
111acc2517fSmillert fprintf(back, BI_REJECT "\n");
112acc2517fSmillert return (1);
113acc2517fSmillert }
114acc2517fSmillert if (expire < 0) {
115acc2517fSmillert if (lastchance) {
116ed05f6fdSmarkus struct passwd *npwd;
117ed05f6fdSmarkus
118acc2517fSmillert endpwent();
119acc2517fSmillert
120acc2517fSmillert /*
121acc2517fSmillert * Only let them play this game once.
122acc2517fSmillert * Set their password change time to 1.
123acc2517fSmillert * This will most certainly cause any
124acc2517fSmillert * expired password to be dead, as well.
125acc2517fSmillert */
126ed05f6fdSmarkus npwd = pw_dup(pwd);
127ed05f6fdSmarkus npwd->pw_change = 1;
1289a60272cSmillert p = pwd_update(npwd, pwd);
1298fbd7fcbSdoug explicit_bzero(npwd->pw_passwd,
130ed05f6fdSmarkus strlen(npwd->pw_passwd));
131ed05f6fdSmarkus free(npwd);
132acc2517fSmillert if (p != NULL) {
1331e50994aSmillert char *errval = auth_mkvalue(p);
1341e50994aSmillert if (errval != NULL) {
1351e50994aSmillert fprintf(back, BI_VALUE
1361e50994aSmillert " errormsg %s", errval);
1371e50994aSmillert free(errval);
1381e50994aSmillert }
139acc2517fSmillert fprintf(back, BI_REJECT "\n");
140acc2517fSmillert return (1);
141acc2517fSmillert }
142acc2517fSmillert }
143acc2517fSmillert fprintf(back, BI_VALUE
144acc2517fSmillert " errormsg Your password has expired\n");
145acc2517fSmillert fprintf(back, BI_PWEXPIRED "\n");
146acc2517fSmillert return (1);
147acc2517fSmillert }
148acc2517fSmillert
149acc2517fSmillert /*
150acc2517fSmillert * If their password is not expired but is about to expire
151acc2517fSmillert * then warn them.
152acc2517fSmillert */
153acc2517fSmillert if (expire <= warn) {
154acc2517fSmillert fprintf(back, BI_VALUE
155acc2517fSmillert " warnmsg Your password expires on %s\n",
156acc2517fSmillert ctime(&pwd->pw_change));
157acc2517fSmillert }
158acc2517fSmillert }
159acc2517fSmillert return (0);
160acc2517fSmillert }
161acc2517fSmillert
162acc2517fSmillert static char *
pwd_update(const struct passwd * pwd,const struct passwd * opwd)1639a60272cSmillert pwd_update(const struct passwd *pwd, const struct passwd *opwd)
164acc2517fSmillert {
165acc2517fSmillert int tfd, pfd;
166acc2517fSmillert
167acc2517fSmillert pw_init();
168acc2517fSmillert tfd = pw_lock(0);
169df69c215Sderaadt if (tfd == -1) {
170acc2517fSmillert if (errno == EEXIST)
171acc2517fSmillert return("the passwd file is busy.");
172acc2517fSmillert else
173acc2517fSmillert return("can't open passwd temp file");
174acc2517fSmillert }
175acc2517fSmillert
176*b7041c07Sderaadt pfd = open(_PATH_MASTERPASSWD, O_RDONLY|O_CLOEXEC);
177df69c215Sderaadt if (pfd == -1) {
178acc2517fSmillert pw_abort();
179acc2517fSmillert return(strerror(errno));
180acc2517fSmillert }
181acc2517fSmillert
1829a60272cSmillert pw_copy(pfd, tfd, pwd, opwd);
183df69c215Sderaadt if (pw_mkdb(pwd->pw_name, 0) == -1) {
184acc2517fSmillert pw_abort();
185acc2517fSmillert return("unable to update password database");
186acc2517fSmillert }
187acc2517fSmillert
188acc2517fSmillert return(NULL);
189acc2517fSmillert }
190