Home | History | Annotate | Download | only in sshd
      1 /*
      2  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 /*
     25  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     26  * Use is subject to license terms.
     27  */
     28 
     29 #include "includes.h"
     30 RCSID("$OpenBSD: auth.c,v 1.45 2002/09/20 18:41:29 stevesk Exp $");
     31 
     32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     33 
     34 #ifdef HAVE_LOGIN_H
     35 #include <login.h>
     36 #endif
     37 #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
     38 #include <shadow.h>
     39 #endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
     40 
     41 #ifdef HAVE_LIBGEN_H
     42 #include <libgen.h>
     43 #endif
     44 
     45 #include "xmalloc.h"
     46 #include "match.h"
     47 #include "groupaccess.h"
     48 #include "log.h"
     49 #include "servconf.h"
     50 #include "auth.h"
     51 #include "auth-options.h"
     52 #include "canohost.h"
     53 #include "buffer.h"
     54 #include "bufaux.h"
     55 #include "uidswap.h"
     56 #include "tildexpand.h"
     57 #include "misc.h"
     58 #include "bufaux.h"
     59 #include "packet.h"
     60 
     61 #ifdef HAVE_BSM
     62 #include "bsmaudit.h"
     63 #include <bsm/adt.h>
     64 #endif /* HAVE_BSM */
     65 
     66 /* import */
     67 extern ServerOptions options;
     68 
     69 /* Debugging messages */
     70 Buffer auth_debug;
     71 int auth_debug_init;
     72 
     73 /*
     74  * Check if the user is allowed to log in via ssh. If user is listed
     75  * in DenyUsers or one of user's groups is listed in DenyGroups, false
     76  * will be returned. If AllowUsers isn't empty and user isn't listed
     77  * there, or if AllowGroups isn't empty and one of user's groups isn't
     78  * listed there, false will be returned.
     79  * If the user's shell is not executable, false will be returned.
     80  * Otherwise true is returned.
     81  */
     82 int
     83 allowed_user(struct passwd * pw)
     84 {
     85 	struct stat st;
     86 	const char *hostname = NULL, *ipaddr = NULL;
     87 	char *shell;
     88 	int i;
     89 #ifdef WITH_AIXAUTHENTICATE
     90 	char *loginmsg;
     91 #endif /* WITH_AIXAUTHENTICATE */
     92 #if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
     93 	!defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
     94 	struct spwd *spw;
     95 
     96 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
     97 	if (!pw || !pw->pw_name)
     98 		return 0;
     99 
    100 #define	DAY		(24L * 60 * 60) /* 1 day in seconds */
    101 	spw = getspnam(pw->pw_name);
    102 	if (spw != NULL) {
    103 		time_t today = time(NULL) / DAY;
    104 		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
    105 		    " sp_max %d", (int)today, (int)spw->sp_expire,
    106 		    (int)spw->sp_lstchg, (int)spw->sp_max);
    107 
    108 		/*
    109 		 * We assume account and password expiration occurs the
    110 		 * day after the day specified.
    111 		 */
    112 		if (spw->sp_expire != -1 && today > spw->sp_expire) {
    113 			log("Account %.100s has expired", pw->pw_name);
    114 			return 0;
    115 		}
    116 
    117 		if (spw->sp_lstchg == 0) {
    118 			log("User %.100s password has expired (root forced)",
    119 			    pw->pw_name);
    120 			return 0;
    121 		}
    122 
    123 		if (spw->sp_max != -1 &&
    124 		    today > spw->sp_lstchg + spw->sp_max) {
    125 			log("User %.100s password has expired (password aged)",
    126 			    pw->pw_name);
    127 			return 0;
    128 		}
    129 	}
    130 #else
    131 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
    132 	if (!pw || !pw->pw_name)
    133 		return 0;
    134 #endif
    135 
    136 	/*
    137 	 * Get the shell from the password data.  An empty shell field is
    138 	 * legal, and means /bin/sh.
    139 	 */
    140 	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
    141 
    142 	/* deny if shell does not exists or is not executable */
    143 	if (stat(shell, &st) != 0) {
    144 		log("User %.100s not allowed because shell %.100s does not exist",
    145 		    pw->pw_name, shell);
    146 		return 0;
    147 	}
    148 	if (S_ISREG(st.st_mode) == 0 ||
    149 	    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
    150 		log("User %.100s not allowed because shell %.100s is not executable",
    151 		    pw->pw_name, shell);
    152 		return 0;
    153 	}
    154 
    155 	if (options.num_deny_users > 0 || options.num_allow_users > 0) {
    156 		hostname = get_canonical_hostname(options.verify_reverse_mapping);
    157 		ipaddr = get_remote_ipaddr();
    158 	}
    159 
    160 	/* Return false if user is listed in DenyUsers */
    161 	if (options.num_deny_users > 0) {
    162 		for (i = 0; i < options.num_deny_users; i++)
    163 			if (match_user(pw->pw_name, hostname, ipaddr,
    164 			    options.deny_users[i])) {
    165 				log("User %.100s not allowed because listed in DenyUsers",
    166 				    pw->pw_name);
    167 				return 0;
    168 			}
    169 	}
    170 	/* Return false if AllowUsers isn't empty and user isn't listed there */
    171 	if (options.num_allow_users > 0) {
    172 		for (i = 0; i < options.num_allow_users; i++)
    173 			if (match_user(pw->pw_name, hostname, ipaddr,
    174 			    options.allow_users[i]))
    175 				break;
    176 		/* i < options.num_allow_users iff we break for loop */
    177 		if (i >= options.num_allow_users) {
    178 			log("User %.100s not allowed because not listed in AllowUsers",
    179 			    pw->pw_name);
    180 			return 0;
    181 		}
    182 	}
    183 	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
    184 		/* Get the user's group access list (primary and supplementary) */
    185 		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
    186 			log("User %.100s not allowed because not in any group",
    187 			    pw->pw_name);
    188 			return 0;
    189 		}
    190 
    191 		/* Return false if one of user's groups is listed in DenyGroups */
    192 		if (options.num_deny_groups > 0)
    193 			if (ga_match(options.deny_groups,
    194 			    options.num_deny_groups)) {
    195 				ga_free();
    196 				log("User %.100s not allowed because a group is listed in DenyGroups",
    197 				    pw->pw_name);
    198 				return 0;
    199 			}
    200 		/*
    201 		 * Return false if AllowGroups isn't empty and one of user's groups
    202 		 * isn't listed there
    203 		 */
    204 		if (options.num_allow_groups > 0)
    205 			if (!ga_match(options.allow_groups,
    206 			    options.num_allow_groups)) {
    207 				ga_free();
    208 				log("User %.100s not allowed because none of user's groups are listed in AllowGroups",
    209 				    pw->pw_name);
    210 				return 0;
    211 			}
    212 		ga_free();
    213 	}
    214 
    215 #ifdef WITH_AIXAUTHENTICATE
    216 	if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
    217 		if (loginmsg && *loginmsg) {
    218 			/* Remove embedded newlines (if any) */
    219 			char *p;
    220 			for (p = loginmsg; *p; p++) {
    221 				if (*p == '\n')
    222 					*p = ' ';
    223 			}
    224 			/* Remove trailing newline */
    225 			*--p = '\0';
    226 			log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
    227 		}
    228 		return 0;
    229 	}
    230 #endif /* WITH_AIXAUTHENTICATE */
    231 
    232 	/* We found no reason not to let this user try to log on... */
    233 	return 1;
    234 }
    235 
    236 Authctxt *
    237 authctxt_new(void)
    238 {
    239 	Authctxt *authctxt = xmalloc(sizeof(*authctxt));
    240 	memset(authctxt, 0, sizeof(*authctxt));
    241 	return authctxt;
    242 }
    243 
    244 void
    245 auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
    246 {
    247 	void (*authlog) (const char *fmt,...) = verbose;
    248 	char *authmsg, *user_str;
    249 
    250 	if (authctxt == NULL)
    251 		fatal("%s: INTERNAL ERROR", __func__);
    252 
    253 	/* Raise logging level */
    254 	if (authenticated == 1 || !authctxt->valid)
    255 		authlog = log;
    256 	else if (authctxt->failures >= AUTH_FAIL_LOG ||
    257 	    authctxt->attempt >= options.max_auth_tries_log ||
    258 	    authctxt->init_attempt >= options.max_init_auth_tries_log)
    259 		authlog = notice;
    260 
    261 	if (authctxt->method) {
    262 		authmsg = "Failed";
    263 		if (authctxt->method->postponed)
    264 			authmsg = "Postponed"; /* shouldn't happen */
    265 		if (authctxt->method->abandoned)
    266 			authmsg = "Abandoned";
    267 		if (authctxt->method->authenticated) {
    268 			if (userauth_check_partial_failure(authctxt))
    269 				authmsg = "Partially accepted";
    270 			else
    271 				authmsg = "Accepted";
    272 		}
    273 		else
    274 			authmsg = "Failed";
    275 	}
    276 	else {
    277 		authmsg = authenticated ? "Accepted" : "Failed";
    278 	}
    279 
    280 	if (authctxt->user == NULL || *authctxt->user == '\0')
    281 		user_str = "<implicit>";
    282 	else if (!authctxt->valid)
    283 		user_str =  "<invalid username>";
    284 	else
    285 		user_str =  authctxt->user;
    286 
    287 	authlog("%s %s for %s from %.200s port %d%s",
    288 	    authmsg,
    289 	    (method != NULL) ? method : "<unknown authentication method>",
    290 	    user_str,
    291 	    get_remote_ipaddr(),
    292 	    get_remote_port(),
    293 	    info);
    294 
    295 #ifdef WITH_AIXAUTHENTICATE
    296 	if (authenticated == 0 && strcmp(method, "password") == 0)
    297 	    loginfailed(authctxt->user,
    298 		get_canonical_hostname(options.verify_reverse_mapping),
    299 		"ssh");
    300 #endif /* WITH_AIXAUTHENTICATE */
    301 
    302 }
    303 
    304 #ifdef HAVE_BSM
    305 void
    306 audit_failed_login_cleanup(void *ctxt)
    307 {
    308 	Authctxt *authctxt = (Authctxt *)ctxt;
    309 	adt_session_data_t *ah;
    310 
    311 	if (authctxt == NULL)
    312 		/* Internal error */
    313 		audit_sshd_login_failure(&ah, PAM_ABORT);
    314 	else if (authctxt->pam == NULL && authctxt->pam_retval != PAM_SUCCESS)
    315 		audit_sshd_login_failure(&ah, authctxt->pam_retval);
    316 	else if (authctxt->pam == NULL && authctxt->pam_retval == PAM_SUCCESS)
    317 		audit_sshd_login_failure(&ah, PAM_PERM_DENIED);
    318 	else if (!authctxt->valid)
    319 		audit_sshd_login_failure(&ah, PAM_USER_UNKNOWN);
    320 	else
    321 		audit_sshd_login_failure(&ah, AUTHPAM_ERROR(authctxt,
    322 			    PAM_PERM_DENIED));
    323 }
    324 #endif /* HAVE_BSM */
    325 
    326 /*
    327  * Check whether root logins are disallowed.
    328  */
    329 int
    330 auth_root_allowed(char *method)
    331 {
    332 	switch (options.permit_root_login) {
    333 	case PERMIT_YES:
    334 		return 1;
    335 		break;
    336 	case PERMIT_NO_PASSWD:
    337 		if (strcmp(method, "password") != 0 &&
    338 		    strcmp(method, "keyboard-interactive") != 0)
    339 			return 1;
    340 		break;
    341 	case PERMIT_FORCED_ONLY:
    342 		if (forced_command) {
    343 			log("Root login accepted for forced command.");
    344 			return 1;
    345 		}
    346 		break;
    347 	}
    348 	log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
    349 	return 0;
    350 }
    351 
    352 
    353 /*
    354  * Given a template and a passwd structure, build a filename
    355  * by substituting % tokenised options. Currently, %% becomes '%',
    356  * %h becomes the home directory and %u the username.
    357  *
    358  * This returns a buffer allocated by xmalloc.
    359  */
    360 char *
    361 expand_filename(const char *filename, struct passwd *pw)
    362 {
    363 	Buffer buffer;
    364 	char *file;
    365 	const char *cp;
    366 
    367 	if (pw == 0)
    368 		return NULL; /* shouldn't happen */
    369 	/*
    370 	 * Build the filename string in the buffer by making the appropriate
    371 	 * substitutions to the given file name.
    372 	 */
    373 	buffer_init(&buffer);
    374 	for (cp = filename; *cp; cp++) {
    375 		if (cp[0] == '%' && cp[1] == '%') {
    376 			buffer_append(&buffer, "%", 1);
    377 			cp++;
    378 			continue;
    379 		}
    380 		if (cp[0] == '%' && cp[1] == 'h') {
    381 			buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir));
    382 			cp++;
    383 			continue;
    384 		}
    385 		if (cp[0] == '%' && cp[1] == 'u') {
    386 			buffer_append(&buffer, pw->pw_name,
    387 			    strlen(pw->pw_name));
    388 			cp++;
    389 			continue;
    390 		}
    391 		buffer_append(&buffer, cp, 1);
    392 	}
    393 	buffer_append(&buffer, "\0", 1);
    394 
    395 	/*
    396 	 * Ensure that filename starts anchored. If not, be backward
    397 	 * compatible and prepend the '%h/'
    398 	 */
    399 	file = xmalloc(MAXPATHLEN);
    400 	cp = buffer_ptr(&buffer);
    401 	if (*cp != '/')
    402 		snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp);
    403 	else
    404 		strlcpy(file, cp, MAXPATHLEN);
    405 
    406 	buffer_free(&buffer);
    407 	return file;
    408 }
    409 
    410 char *
    411 authorized_keys_file(struct passwd *pw)
    412 {
    413 	return expand_filename(options.authorized_keys_file, pw);
    414 }
    415 
    416 char *
    417 authorized_keys_file2(struct passwd *pw)
    418 {
    419 	return expand_filename(options.authorized_keys_file2, pw);
    420 }
    421 
    422 /* return ok if key exists in sysfile or userfile */
    423 HostStatus
    424 check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
    425     const char *sysfile, const char *userfile)
    426 {
    427 	Key *found;
    428 	char *user_hostfile;
    429 	struct stat st;
    430 	HostStatus host_status;
    431 
    432 	/* Check if we know the host and its host key. */
    433 	found = key_new(key->type);
    434 	host_status = check_host_in_hostfile(sysfile, host, key, found, NULL);
    435 
    436 	if (host_status != HOST_OK && userfile != NULL) {
    437 		user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
    438 		if (options.strict_modes &&
    439 		    (stat(user_hostfile, &st) == 0) &&
    440 		    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
    441 		    (st.st_mode & 022) != 0)) {
    442 			log("Authentication refused for %.100s: "
    443 			    "bad owner or modes for %.200s",
    444 			    pw->pw_name, user_hostfile);
    445 		} else {
    446 			temporarily_use_uid(pw);
    447 			host_status = check_host_in_hostfile(user_hostfile,
    448 			    host, key, found, NULL);
    449 			restore_uid();
    450 		}
    451 		xfree(user_hostfile);
    452 	}
    453 	key_free(found);
    454 
    455 	debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ?
    456 	    "ok" : "not found", host);
    457 	return host_status;
    458 }
    459 
    460 
    461 /*
    462  * Check a given file for security. This is defined as all components
    463  * of the path to the file must be owned by either the owner of
    464  * of the file or root and no directories must be group or world writable.
    465  *
    466  * XXX Should any specific check be done for sym links ?
    467  *
    468  * Takes an open file descriptor, the file name, a uid and and
    469  * error buffer plus max size as arguments.
    470  *
    471  * Returns 0 on success and -1 on failure
    472  */
    473 int
    474 secure_filename(FILE *f, const char *file, struct passwd *pw,
    475     char *err, size_t errlen)
    476 {
    477 	uid_t uid;
    478 	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
    479 	char *cp;
    480 	int comparehome = 0;
    481 	struct stat st;
    482 
    483 	if (pw == NULL)
    484 		return 0;
    485 
    486 	uid = pw->pw_uid;
    487 
    488 	if (realpath(file, buf) == NULL) {
    489 		snprintf(err, errlen, "realpath %s failed: %s", file,
    490 		    strerror(errno));
    491 		return -1;
    492 	}
    493 
    494 	/*
    495 	 * A user is not required to have all the files that are subject to
    496 	 * the strict mode checking in his/her home directory. If the
    497 	 * directory is not present at the moment, which might be the case if
    498 	 * the directory is not mounted until the user is authenticated, do
    499 	 * not perform the home directory check below.
    500 	 */
    501 	if (realpath(pw->pw_dir, homedir) != NULL)
    502 		comparehome = 1;
    503 
    504 	/* check the open file to avoid races */
    505 	if (fstat(fileno(f), &st) < 0 ||
    506 	    (st.st_uid != 0 && st.st_uid != uid) ||
    507 	    (st.st_mode & 022) != 0) {
    508 		snprintf(err, errlen, "bad ownership or modes for file %s",
    509 		    buf);
    510 		return -1;
    511 	}
    512 
    513 	/* for each component of the canonical path, walking upwards */
    514 	for (;;) {
    515 		if ((cp = dirname(buf)) == NULL) {
    516 			snprintf(err, errlen, "dirname() failed");
    517 			return -1;
    518 		}
    519 		strlcpy(buf, cp, sizeof(buf));
    520 
    521 		debug3("secure_filename: checking '%s'", buf);
    522 		if (stat(buf, &st) < 0 ||
    523 		    (st.st_uid != 0 && st.st_uid != uid) ||
    524 		    (st.st_mode & 022) != 0) {
    525 			snprintf(err, errlen,
    526 			    "bad ownership or modes for directory %s", buf);
    527 			return -1;
    528 		}
    529 
    530 		/* If we passed the homedir then we can stop. */
    531 		if (comparehome && strcmp(homedir, buf) == 0) {
    532 			debug3("secure_filename: terminating check at '%s'",
    533 			    buf);
    534 			break;
    535 		}
    536 		/*
    537 		 * dirname should always complete with a "/" path,
    538 		 * but we can be paranoid and check for "." too
    539 		 */
    540 		if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
    541 			break;
    542 	}
    543 	return 0;
    544 }
    545 
    546 struct passwd *
    547 getpwnamallow(const char *user)
    548 {
    549 #ifdef HAVE_LOGIN_CAP
    550 	extern login_cap_t *lc;
    551 #ifdef BSD_AUTH
    552 	auth_session_t *as;
    553 #endif
    554 #endif
    555 	struct passwd *pw;
    556 
    557 	if (user == NULL || *user == '\0')
    558 		return (NULL); /* implicit user, will be set later */
    559 
    560 	pw = getpwnam(user);
    561 	if (pw == NULL) {
    562 		log("Illegal user %.100s from %.100s",
    563 		    user, get_remote_ipaddr());
    564 		return (NULL);
    565 	}
    566 	if (!allowed_user(pw))
    567 		return (NULL);
    568 #ifdef HAVE_LOGIN_CAP
    569 	if ((lc = login_getclass(pw->pw_class)) == NULL) {
    570 		debug("unable to get login class: %s", user);
    571 		return (NULL);
    572 	}
    573 #ifdef BSD_AUTH
    574 	if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
    575 	    auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
    576 		debug("Approval failure for %s", user);
    577 		pw = NULL;
    578 	}
    579 	if (as != NULL)
    580 		auth_close(as);
    581 #endif
    582 #endif
    583 	if (pw != NULL)
    584 		return (pwcopy(pw));
    585 	return (NULL);
    586 }
    587 
    588 void
    589 auth_debug_add(const char *fmt,...)
    590 {
    591 	char buf[1024];
    592 	va_list args;
    593 
    594 	if (!auth_debug_init)
    595 		return;
    596 
    597 	va_start(args, fmt);
    598 	vsnprintf(buf, sizeof(buf), fmt, args);
    599 	va_end(args);
    600 	buffer_put_cstring(&auth_debug, buf);
    601 }
    602 
    603 void
    604 auth_debug_send(void)
    605 {
    606 	char *msg;
    607 
    608 	if (!auth_debug_init)
    609 		return;
    610 	while (buffer_len(&auth_debug)) {
    611 		msg = buffer_get_string(&auth_debug, NULL);
    612 		packet_send_debug("%s", msg);
    613 		xfree(msg);
    614 	}
    615 }
    616 
    617 void
    618 auth_debug_reset(void)
    619 {
    620 	if (auth_debug_init)
    621 		buffer_clear(&auth_debug);
    622 	else {
    623 		buffer_init(&auth_debug);
    624 		auth_debug_init = 1;
    625 	}
    626 }
    627