xref: /freebsd-src/crypto/openssh/auth-shadow.c (revision 4d3fc8b0570b29fb0d6ee9525f104d52176ff0d4)
1efcad6b7SDag-Erling Smørgrav /*
2efcad6b7SDag-Erling Smørgrav  * Copyright (c) 2004 Darren Tucker.  All rights reserved.
3efcad6b7SDag-Erling Smørgrav  *
4efcad6b7SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
5efcad6b7SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
6efcad6b7SDag-Erling Smørgrav  * are met:
7efcad6b7SDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
8efcad6b7SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
9efcad6b7SDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
10efcad6b7SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
11efcad6b7SDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
12efcad6b7SDag-Erling Smørgrav  *
13efcad6b7SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14efcad6b7SDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15efcad6b7SDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16efcad6b7SDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17efcad6b7SDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18efcad6b7SDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19efcad6b7SDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20efcad6b7SDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21efcad6b7SDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22efcad6b7SDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23efcad6b7SDag-Erling Smørgrav  */
24efcad6b7SDag-Erling Smørgrav 
25efcad6b7SDag-Erling Smørgrav #include "includes.h"
26efcad6b7SDag-Erling Smørgrav 
27efcad6b7SDag-Erling Smørgrav #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
28efcad6b7SDag-Erling Smørgrav #include <shadow.h>
29761efaa7SDag-Erling Smørgrav #include <stdarg.h>
30761efaa7SDag-Erling Smørgrav #include <string.h>
31d4af9e69SDag-Erling Smørgrav #include <time.h>
32efcad6b7SDag-Erling Smørgrav 
33761efaa7SDag-Erling Smørgrav #include "hostfile.h"
34efcad6b7SDag-Erling Smørgrav #include "auth.h"
35190cef3dSDag-Erling Smørgrav #include "sshbuf.h"
36190cef3dSDag-Erling Smørgrav #include "ssherr.h"
37efcad6b7SDag-Erling Smørgrav #include "log.h"
38efcad6b7SDag-Erling Smørgrav 
395e8dbd04SDag-Erling Smørgrav #ifdef DAY
405e8dbd04SDag-Erling Smørgrav # undef DAY
415e8dbd04SDag-Erling Smørgrav #endif
42efcad6b7SDag-Erling Smørgrav #define DAY	(24L * 60 * 60) /* 1 day in seconds */
43efcad6b7SDag-Erling Smørgrav 
44190cef3dSDag-Erling Smørgrav extern struct sshbuf *loginmsg;
45efcad6b7SDag-Erling Smørgrav 
46efcad6b7SDag-Erling Smørgrav /*
47efcad6b7SDag-Erling Smørgrav  * For the account and password expiration functions, we assume the expiry
48efcad6b7SDag-Erling Smørgrav  * occurs the day after the day specified.
49efcad6b7SDag-Erling Smørgrav  */
50efcad6b7SDag-Erling Smørgrav 
51efcad6b7SDag-Erling Smørgrav /*
52efcad6b7SDag-Erling Smørgrav  * Check if specified account is expired.  Returns 1 if account is expired,
53efcad6b7SDag-Erling Smørgrav  * 0 otherwise.
54efcad6b7SDag-Erling Smørgrav  */
55efcad6b7SDag-Erling Smørgrav int
auth_shadow_acctexpired(struct spwd * spw)56efcad6b7SDag-Erling Smørgrav auth_shadow_acctexpired(struct spwd *spw)
57efcad6b7SDag-Erling Smørgrav {
58efcad6b7SDag-Erling Smørgrav 	time_t today;
59*4d3fc8b0SEd Maste 	long long daysleft;
60190cef3dSDag-Erling Smørgrav 	int r;
61efcad6b7SDag-Erling Smørgrav 
62efcad6b7SDag-Erling Smørgrav 	today = time(NULL) / DAY;
63efcad6b7SDag-Erling Smørgrav 	daysleft = spw->sp_expire - today;
64*4d3fc8b0SEd Maste 	debug3("%s: today %lld sp_expire %lld days left %lld", __func__,
65*4d3fc8b0SEd Maste 	    (long long)today, (long long)spw->sp_expire, daysleft);
66efcad6b7SDag-Erling Smørgrav 
67efcad6b7SDag-Erling Smørgrav 	if (spw->sp_expire == -1) {
68efcad6b7SDag-Erling Smørgrav 		debug3("account expiration disabled");
69efcad6b7SDag-Erling Smørgrav 	} else if (daysleft < 0) {
70efcad6b7SDag-Erling Smørgrav 		logit("Account %.100s has expired", spw->sp_namp);
71efcad6b7SDag-Erling Smørgrav 		return 1;
72efcad6b7SDag-Erling Smørgrav 	} else if (daysleft <= spw->sp_warn) {
73*4d3fc8b0SEd Maste 		debug3("account will expire in %lld days", daysleft);
74190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_putf(loginmsg,
75*4d3fc8b0SEd Maste 		    "Your account will expire in %lld day%s.\n", daysleft,
76190cef3dSDag-Erling Smørgrav 		    daysleft == 1 ? "" : "s")) != 0)
77190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
78efcad6b7SDag-Erling Smørgrav 	}
79efcad6b7SDag-Erling Smørgrav 
80efcad6b7SDag-Erling Smørgrav 	return 0;
81efcad6b7SDag-Erling Smørgrav }
82efcad6b7SDag-Erling Smørgrav 
83efcad6b7SDag-Erling Smørgrav /*
84efcad6b7SDag-Erling Smørgrav  * Checks password expiry for platforms that use shadow passwd files.
85efcad6b7SDag-Erling Smørgrav  * Returns: 1 = password expired, 0 = password not expired
86efcad6b7SDag-Erling Smørgrav  */
87efcad6b7SDag-Erling Smørgrav int
auth_shadow_pwexpired(Authctxt * ctxt)88efcad6b7SDag-Erling Smørgrav auth_shadow_pwexpired(Authctxt *ctxt)
89efcad6b7SDag-Erling Smørgrav {
90efcad6b7SDag-Erling Smørgrav 	struct spwd *spw = NULL;
91efcad6b7SDag-Erling Smørgrav 	const char *user = ctxt->pw->pw_name;
92efcad6b7SDag-Erling Smørgrav 	time_t today;
93190cef3dSDag-Erling Smørgrav 	int r, daysleft, disabled = 0;
94efcad6b7SDag-Erling Smørgrav 
95efcad6b7SDag-Erling Smørgrav 	if ((spw = getspnam((char *)user)) == NULL) {
96efcad6b7SDag-Erling Smørgrav 		error("Could not get shadow information for %.100s", user);
97efcad6b7SDag-Erling Smørgrav 		return 0;
98efcad6b7SDag-Erling Smørgrav 	}
99efcad6b7SDag-Erling Smørgrav 
100efcad6b7SDag-Erling Smørgrav 	today = time(NULL) / DAY;
101*4d3fc8b0SEd Maste 	debug3_f("today %lld sp_lstchg %lld sp_max %lld", (long long)today,
102*4d3fc8b0SEd Maste 	    (long long)spw->sp_lstchg, (long long)spw->sp_max);
103efcad6b7SDag-Erling Smørgrav 
104efcad6b7SDag-Erling Smørgrav #if defined(__hpux) && !defined(HAVE_SECUREWARE)
105efcad6b7SDag-Erling Smørgrav 	if (iscomsec()) {
106efcad6b7SDag-Erling Smørgrav 		struct pr_passwd *pr;
107efcad6b7SDag-Erling Smørgrav 
108efcad6b7SDag-Erling Smørgrav 		pr = getprpwnam((char *)user);
109efcad6b7SDag-Erling Smørgrav 
110efcad6b7SDag-Erling Smørgrav 		/* Test for Trusted Mode expiry disabled */
111efcad6b7SDag-Erling Smørgrav 		if (pr != NULL && pr->ufld.fd_min == 0 &&
112efcad6b7SDag-Erling Smørgrav 		    pr->ufld.fd_lifetime == 0 && pr->ufld.fd_expire == 0 &&
113efcad6b7SDag-Erling Smørgrav 		    pr->ufld.fd_pw_expire_warning == 0 &&
114efcad6b7SDag-Erling Smørgrav 		    pr->ufld.fd_schange != 0)
115efcad6b7SDag-Erling Smørgrav 			disabled = 1;
116efcad6b7SDag-Erling Smørgrav 	}
117efcad6b7SDag-Erling Smørgrav #endif
118efcad6b7SDag-Erling Smørgrav 
119efcad6b7SDag-Erling Smørgrav 	/* TODO: check sp_inact */
120efcad6b7SDag-Erling Smørgrav 	daysleft = spw->sp_lstchg + spw->sp_max - today;
121efcad6b7SDag-Erling Smørgrav 	if (disabled) {
122efcad6b7SDag-Erling Smørgrav 		debug3("password expiration disabled");
123efcad6b7SDag-Erling Smørgrav 	} else if (spw->sp_lstchg == 0) {
124efcad6b7SDag-Erling Smørgrav 		logit("User %.100s password has expired (root forced)", user);
125efcad6b7SDag-Erling Smørgrav 		return 1;
126efcad6b7SDag-Erling Smørgrav 	} else if (spw->sp_max == -1) {
127efcad6b7SDag-Erling Smørgrav 		debug3("password expiration disabled");
128efcad6b7SDag-Erling Smørgrav 	} else if (daysleft < 0) {
129efcad6b7SDag-Erling Smørgrav 		logit("User %.100s password has expired (password aged)", user);
130efcad6b7SDag-Erling Smørgrav 		return 1;
131efcad6b7SDag-Erling Smørgrav 	} else if (daysleft <= spw->sp_warn) {
132efcad6b7SDag-Erling Smørgrav 		debug3("password will expire in %d days", daysleft);
133190cef3dSDag-Erling Smørgrav 		if ((r = sshbuf_putf(loginmsg,
134efcad6b7SDag-Erling Smørgrav 		    "Your password will expire in %d day%s.\n", daysleft,
135190cef3dSDag-Erling Smørgrav 		    daysleft == 1 ? "" : "s")) != 0)
136190cef3dSDag-Erling Smørgrav 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
137efcad6b7SDag-Erling Smørgrav 	}
138efcad6b7SDag-Erling Smørgrav 
139efcad6b7SDag-Erling Smørgrav 	return 0;
140efcad6b7SDag-Erling Smørgrav }
141efcad6b7SDag-Erling Smørgrav #endif	/* USE_SHADOW && HAS_SHADOW_EXPIRE */
142