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