xref: /freebsd/crypto/openssh/auth.c (revision ca3176e7c8c53ffd5e822c8bad53fa885faf7ae0)
1a04a10f8SKris Kennaway /*
2a04a10f8SKris Kennaway  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3e8aafc91SKris Kennaway  *
4c2d3a559SKris Kennaway  * Redistribution and use in source and binary forms, with or without
5c2d3a559SKris Kennaway  * modification, are permitted provided that the following conditions
6c2d3a559SKris Kennaway  * are met:
7c2d3a559SKris Kennaway  * 1. Redistributions of source code must retain the above copyright
8c2d3a559SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
9c2d3a559SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
10c2d3a559SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
11c2d3a559SKris Kennaway  *    documentation and/or other materials provided with the distribution.
12c2d3a559SKris Kennaway  *
13c2d3a559SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14c2d3a559SKris Kennaway  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15c2d3a559SKris Kennaway  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16c2d3a559SKris Kennaway  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17c2d3a559SKris Kennaway  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18c2d3a559SKris Kennaway  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19c2d3a559SKris Kennaway  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20c2d3a559SKris Kennaway  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21c2d3a559SKris Kennaway  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22c2d3a559SKris Kennaway  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23a04a10f8SKris Kennaway  */
24a04a10f8SKris Kennaway 
25a04a10f8SKris Kennaway #include "includes.h"
26ca3176e7SBrian Feldman RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
27c2d3a559SKris Kennaway RCSID("$FreeBSD$");
28a04a10f8SKris Kennaway 
29a04a10f8SKris Kennaway #include "xmalloc.h"
30a04a10f8SKris Kennaway #include "match.h"
31ca3176e7SBrian Feldman #include "groupaccess.h"
32ca3176e7SBrian Feldman #include "log.h"
33ca3176e7SBrian Feldman #include "servconf.h"
34a04a10f8SKris Kennaway #include "auth.h"
35ca3176e7SBrian Feldman #include "auth-options.h"
36ca3176e7SBrian Feldman #include "canohost.h"
37a04a10f8SKris Kennaway 
38a04a10f8SKris Kennaway /* import */
39a04a10f8SKris Kennaway extern ServerOptions options;
40a04a10f8SKris Kennaway 
41a04a10f8SKris Kennaway /*
42ca3176e7SBrian Feldman  * Check if the user is allowed to log in via ssh. If user is listed
43ca3176e7SBrian Feldman  * in DenyUsers or one of user's groups is listed in DenyGroups, false
44ca3176e7SBrian Feldman  * will be returned. If AllowUsers isn't empty and user isn't listed
45ca3176e7SBrian Feldman  * there, or if AllowGroups isn't empty and one of user's groups isn't
46ca3176e7SBrian Feldman  * listed there, false will be returned.
47a04a10f8SKris Kennaway  * If the user's shell is not executable, false will be returned.
48a04a10f8SKris Kennaway  * Otherwise true is returned.
49a04a10f8SKris Kennaway  */
50a04a10f8SKris Kennaway int
51a04a10f8SKris Kennaway allowed_user(struct passwd * pw)
52a04a10f8SKris Kennaway {
53a04a10f8SKris Kennaway 	struct stat st;
54c322fe35SKris Kennaway 	char *shell;
55a04a10f8SKris Kennaway 	int i;
56a04a10f8SKris Kennaway 
57a04a10f8SKris Kennaway 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
58ca3176e7SBrian Feldman 	if (!pw || !pw->pw_name)
59a04a10f8SKris Kennaway 		return 0;
60a04a10f8SKris Kennaway 
61c322fe35SKris Kennaway 	/*
62c322fe35SKris Kennaway 	 * Get the shell from the password data.  An empty shell field is
63c322fe35SKris Kennaway 	 * legal, and means /bin/sh.
64c322fe35SKris Kennaway 	 */
65c322fe35SKris Kennaway 	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
66c322fe35SKris Kennaway 
67a04a10f8SKris Kennaway 	/* deny if shell does not exists or is not executable */
68c322fe35SKris Kennaway 	if (stat(shell, &st) != 0)
69a04a10f8SKris Kennaway 		return 0;
70a04a10f8SKris Kennaway 	if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
71a04a10f8SKris Kennaway 		return 0;
72a04a10f8SKris Kennaway 
73a04a10f8SKris Kennaway 	/* Return false if user is listed in DenyUsers */
74a04a10f8SKris Kennaway 	if (options.num_deny_users > 0) {
75a04a10f8SKris Kennaway 		for (i = 0; i < options.num_deny_users; i++)
76a04a10f8SKris Kennaway 			if (match_pattern(pw->pw_name, options.deny_users[i]))
77a04a10f8SKris Kennaway 				return 0;
78a04a10f8SKris Kennaway 	}
79a04a10f8SKris Kennaway 	/* Return false if AllowUsers isn't empty and user isn't listed there */
80a04a10f8SKris Kennaway 	if (options.num_allow_users > 0) {
81a04a10f8SKris Kennaway 		for (i = 0; i < options.num_allow_users; i++)
82a04a10f8SKris Kennaway 			if (match_pattern(pw->pw_name, options.allow_users[i]))
83a04a10f8SKris Kennaway 				break;
84a04a10f8SKris Kennaway 		/* i < options.num_allow_users iff we break for loop */
85a04a10f8SKris Kennaway 		if (i >= options.num_allow_users)
86a04a10f8SKris Kennaway 			return 0;
87a04a10f8SKris Kennaway 	}
88a04a10f8SKris Kennaway 	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
89ca3176e7SBrian Feldman 		/* Get the user's group access list (primary and supplementary) */
90ca3176e7SBrian Feldman 		if (ga_init(pw->pw_name, pw->pw_gid) == 0)
91a04a10f8SKris Kennaway 			return 0;
92a04a10f8SKris Kennaway 
93ca3176e7SBrian Feldman 		/* Return false if one of user's groups is listed in DenyGroups */
94ca3176e7SBrian Feldman 		if (options.num_deny_groups > 0)
95ca3176e7SBrian Feldman 			if (ga_match(options.deny_groups,
96ca3176e7SBrian Feldman 			    options.num_deny_groups)) {
97ca3176e7SBrian Feldman 				ga_free();
98a04a10f8SKris Kennaway 				return 0;
99a04a10f8SKris Kennaway 			}
100a04a10f8SKris Kennaway 		/*
101ca3176e7SBrian Feldman 		 * Return false if AllowGroups isn't empty and one of user's groups
102a04a10f8SKris Kennaway 		 * isn't listed there
103a04a10f8SKris Kennaway 		 */
104ca3176e7SBrian Feldman 		if (options.num_allow_groups > 0)
105ca3176e7SBrian Feldman 			if (!ga_match(options.allow_groups,
106ca3176e7SBrian Feldman 			    options.num_allow_groups)) {
107ca3176e7SBrian Feldman 				ga_free();
108a04a10f8SKris Kennaway 				return 0;
109a04a10f8SKris Kennaway 			}
110ca3176e7SBrian Feldman 		ga_free();
111a04a10f8SKris Kennaway 	}
112a04a10f8SKris Kennaway 	/* We found no reason not to let this user try to log on... */
113a04a10f8SKris Kennaway 	return 1;
114a04a10f8SKris Kennaway }
115ca3176e7SBrian Feldman 
116ca3176e7SBrian Feldman Authctxt *
117ca3176e7SBrian Feldman authctxt_new(void)
118ca3176e7SBrian Feldman {
119ca3176e7SBrian Feldman 	Authctxt *authctxt = xmalloc(sizeof(*authctxt));
120ca3176e7SBrian Feldman 	memset(authctxt, 0, sizeof(*authctxt));
121ca3176e7SBrian Feldman 	return authctxt;
122ca3176e7SBrian Feldman }
123ca3176e7SBrian Feldman 
124ca3176e7SBrian Feldman void
125ca3176e7SBrian Feldman auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
126ca3176e7SBrian Feldman {
127ca3176e7SBrian Feldman 	void (*authlog) (const char *fmt,...) = verbose;
128ca3176e7SBrian Feldman 	char *authmsg;
129ca3176e7SBrian Feldman 
130ca3176e7SBrian Feldman 	/* Raise logging level */
131ca3176e7SBrian Feldman 	if (authenticated == 1 ||
132ca3176e7SBrian Feldman 	    !authctxt->valid ||
133ca3176e7SBrian Feldman 	    authctxt->failures >= AUTH_FAIL_LOG ||
134ca3176e7SBrian Feldman 	    strcmp(method, "password") == 0)
135ca3176e7SBrian Feldman 		authlog = log;
136ca3176e7SBrian Feldman 
137ca3176e7SBrian Feldman 	if (authctxt->postponed)
138ca3176e7SBrian Feldman 		authmsg = "Postponed";
139ca3176e7SBrian Feldman 	else
140ca3176e7SBrian Feldman 		authmsg = authenticated ? "Accepted" : "Failed";
141ca3176e7SBrian Feldman 
142ca3176e7SBrian Feldman 	authlog("%s %s for %s%.100s from %.200s port %d%s",
143ca3176e7SBrian Feldman 	    authmsg,
144ca3176e7SBrian Feldman 	    method,
145ca3176e7SBrian Feldman 	    authctxt->valid ? "" : "illegal user ",
146ca3176e7SBrian Feldman 	    authctxt->valid && authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user,
147ca3176e7SBrian Feldman 	    get_remote_ipaddr(),
148ca3176e7SBrian Feldman 	    get_remote_port(),
149ca3176e7SBrian Feldman 	    info);
150ca3176e7SBrian Feldman }
151ca3176e7SBrian Feldman 
152ca3176e7SBrian Feldman /*
153ca3176e7SBrian Feldman  * Check whether root logins are disallowed.
154ca3176e7SBrian Feldman  */
155ca3176e7SBrian Feldman int
156ca3176e7SBrian Feldman auth_root_allowed(char *method)
157ca3176e7SBrian Feldman {
158ca3176e7SBrian Feldman 	switch (options.permit_root_login) {
159ca3176e7SBrian Feldman 	case PERMIT_YES:
160ca3176e7SBrian Feldman 		return 1;
161ca3176e7SBrian Feldman 		break;
162ca3176e7SBrian Feldman 	case PERMIT_NO_PASSWD:
163ca3176e7SBrian Feldman 		if (strcmp(method, "password") != 0)
164ca3176e7SBrian Feldman 			return 1;
165ca3176e7SBrian Feldman 		break;
166ca3176e7SBrian Feldman 	case PERMIT_FORCED_ONLY:
167ca3176e7SBrian Feldman 		if (forced_command) {
168ca3176e7SBrian Feldman 			log("Root login accepted for forced command.");
169ca3176e7SBrian Feldman 			return 1;
170ca3176e7SBrian Feldman 		}
171ca3176e7SBrian Feldman 		break;
172ca3176e7SBrian Feldman 	}
173ca3176e7SBrian Feldman 	log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
174ca3176e7SBrian Feldman 	return 0;
175ca3176e7SBrian Feldman }
176