auth.c revision 113911
191094Sdes/*
292289Sdes * Copyright (c) 2000 Markus Friedl.  All rights reserved.
391094Sdes *
491094Sdes * Redistribution and use in source and binary forms, with or without
591094Sdes * modification, are permitted provided that the following conditions
691094Sdes * are met:
791094Sdes * 1. Redistributions of source code must retain the above copyright
891094Sdes *    notice, this list of conditions and the following disclaimer.
991094Sdes * 2. Redistributions in binary form must reproduce the above copyright
1091094Sdes *    notice, this list of conditions and the following disclaimer in the
1191094Sdes *    documentation and/or other materials provided with the distribution.
1291094Sdes *
1391094Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1491094Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1591094Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1691094Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1791094Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1891094Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1991094Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2091094Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2191094Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2291094Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2391094Sdes */
2491094Sdes
2591094Sdes#include "includes.h"
2691094SdesRCSID("$OpenBSD: auth.c,v 1.46 2002/11/04 10:07:53 markus Exp $");
2791094SdesRCSID("$FreeBSD: head/crypto/openssh/auth.c 113911 2003-04-23 17:13:13Z des $");
2891094Sdes
2991094Sdes#ifdef HAVE_LOGIN_H
3091094Sdes#include <login.h>
3191094Sdes#endif
3291094Sdes#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
3391094Sdes#include <shadow.h>
3494532Sdes#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
3591094Sdes
3691094Sdes#ifdef HAVE_LIBGEN_H
3791094Sdes#include <libgen.h>
3891094Sdes#endif
3991094Sdes
4091094Sdes#include "xmalloc.h"
4191094Sdes#include "match.h"
4291094Sdes#include "groupaccess.h"
4391094Sdes#include "log.h"
4491094Sdes#include "servconf.h"
4591094Sdes#include "auth.h"
4691094Sdes#include "auth-options.h"
4791094Sdes#include "canohost.h"
4891094Sdes#include "buffer.h"
4994209Sdes#include "bufaux.h"
5094209Sdes#include "uidswap.h"
5191094Sdes#include "tildexpand.h"
5291094Sdes#include "misc.h"
5391094Sdes#include "bufaux.h"
5494209Sdes#include "packet.h"
5594209Sdes
5694209Sdes/* import */
5794209Sdesextern ServerOptions options;
5894209Sdes
5994209Sdes/* Debugging messages */
6094209SdesBuffer auth_debug;
6194209Sdesint auth_debug_init;
6294209Sdes
6391100Sdes/*
6491100Sdes * Check if the user is allowed to log in via ssh. If user is listed
6591100Sdes * in DenyUsers or one of user's groups is listed in DenyGroups, false
6691100Sdes * will be returned. If AllowUsers isn't empty and user isn't listed
6791094Sdes * there, or if AllowGroups isn't empty and one of user's groups isn't
6894209Sdes * listed there, false will be returned.
6994209Sdes * If the user's shell is not executable, false will be returned.
7094209Sdes * Otherwise true is returned.
7191100Sdes */
7291100Sdesint
7391100Sdesallowed_user(struct passwd * pw)
7491100Sdes{
7591100Sdes	struct stat st;
7691094Sdes	const char *hostname = NULL, *ipaddr = NULL;
7791094Sdes	char *shell;
7891094Sdes	int i;
7991094Sdes#ifdef WITH_AIXAUTHENTICATE
8091094Sdes	char *loginmsg;
8191094Sdes#endif /* WITH_AIXAUTHENTICATE */
8293982Sdes#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
8391094Sdes    !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
8491094Sdes	struct spwd *spw;
8591094Sdes	time_t today;
8691094Sdes#endif
8791094Sdes
8891094Sdes	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
8991094Sdes	if (!pw || !pw->pw_name)
9091094Sdes		return 0;
9191094Sdes
9291094Sdes#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
9391094Sdes    !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
9491094Sdes#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
9591094Sdes	if ((spw = getspnam(pw->pw_name)) != NULL) {
9691094Sdes		today = time(NULL) / DAY;
9791094Sdes		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
9891094Sdes		    " sp_max %d", (int)today, (int)spw->sp_expire,
9991094Sdes		    (int)spw->sp_lstchg, (int)spw->sp_max);
10091094Sdes
10191094Sdes		/*
10291094Sdes		 * We assume account and password expiration occurs the
10391094Sdes		 * day after the day specified.
10491094Sdes		 */
10591094Sdes		if (spw->sp_expire != -1 && today > spw->sp_expire) {
10691094Sdes			log("Account %.100s has expired", pw->pw_name);
10791094Sdes			return 0;
10891094Sdes		}
10991094Sdes
11091094Sdes		if (spw->sp_lstchg == 0) {
11191094Sdes			log("User %.100s password has expired (root forced)",
11291094Sdes			    pw->pw_name);
11391094Sdes			return 0;
11491094Sdes		}
11591094Sdes
11691094Sdes		if (spw->sp_max != -1 &&
11791094Sdes		    today > spw->sp_lstchg + spw->sp_max) {
11891094Sdes			log("User %.100s password has expired (password aged)",
11991094Sdes			    pw->pw_name);
12091094Sdes			return 0;
12191094Sdes		}
12291094Sdes	}
12391094Sdes#endif
12491094Sdes
12591094Sdes	/*
12691094Sdes	 * Get the shell from the password data.  An empty shell field is
12791094Sdes	 * legal, and means /bin/sh.
12891094Sdes	 */
12991094Sdes	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
13091094Sdes
13191094Sdes	/* deny if shell does not exists or is not executable */
13291094Sdes	if (stat(shell, &st) != 0) {
13391094Sdes		log("User %.100s not allowed because shell %.100s does not exist",
13493982Sdes		    pw->pw_name, shell);
13593982Sdes		return 0;
13691094Sdes	}
13791094Sdes	if (S_ISREG(st.st_mode) == 0 ||
13891094Sdes	    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
13991094Sdes		log("User %.100s not allowed because shell %.100s is not executable",
14093982Sdes		    pw->pw_name, shell);
14191094Sdes		return 0;
14291094Sdes	}
14393982Sdes
14493982Sdes	if (options.num_deny_users > 0 || options.num_allow_users > 0) {
14593982Sdes		hostname = get_canonical_hostname(options.verify_reverse_mapping);
14693982Sdes		ipaddr = get_remote_ipaddr();
14791094Sdes	}
14893982Sdes
14991094Sdes	/* Return false if user is listed in DenyUsers */
15093982Sdes	if (options.num_deny_users > 0) {
15193982Sdes		for (i = 0; i < options.num_deny_users; i++)
15293982Sdes			if (match_user(pw->pw_name, hostname, ipaddr,
15393982Sdes			    options.deny_users[i])) {
15491094Sdes				log("User %.100s not allowed because listed in DenyUsers",
15591094Sdes				    pw->pw_name);
15691094Sdes				return 0;
15791094Sdes			}
15891094Sdes	}
15991094Sdes	/* Return false if AllowUsers isn't empty and user isn't listed there */
16091094Sdes	if (options.num_allow_users > 0) {
16191094Sdes		for (i = 0; i < options.num_allow_users; i++)
16291094Sdes			if (match_user(pw->pw_name, hostname, ipaddr,
16391094Sdes			    options.allow_users[i]))
16491094Sdes				break;
16591094Sdes		/* i < options.num_allow_users iff we break for loop */
16691094Sdes		if (i >= options.num_allow_users) {
16791094Sdes			log("User %.100s not allowed because not listed in AllowUsers",
16891094Sdes			    pw->pw_name);
16991094Sdes			return 0;
17091094Sdes		}
17191094Sdes	}
17291094Sdes	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
17391094Sdes		/* Get the user's group access list (primary and supplementary) */
17491094Sdes		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
17591094Sdes			log("User %.100s not allowed because not in any group",
17691094Sdes			    pw->pw_name);
17791094Sdes			return 0;
17891094Sdes		}
17991094Sdes
18091094Sdes		/* Return false if one of user's groups is listed in DenyGroups */
18191094Sdes		if (options.num_deny_groups > 0)
18291094Sdes			if (ga_match(options.deny_groups,
18391094Sdes			    options.num_deny_groups)) {
18491094Sdes				ga_free();
18591094Sdes				log("User %.100s not allowed because a group is listed in DenyGroups",
18691094Sdes				    pw->pw_name);
18791094Sdes				return 0;
18891094Sdes			}
18991094Sdes		/*
19091094Sdes		 * Return false if AllowGroups isn't empty and one of user's groups
19191094Sdes		 * isn't listed there
19291094Sdes		 */
19391094Sdes		if (options.num_allow_groups > 0)
19491094Sdes			if (!ga_match(options.allow_groups,
19591094Sdes			    options.num_allow_groups)) {
19691094Sdes				ga_free();
19791094Sdes				log("User %.100s not allowed because none of user's groups are listed in AllowGroups",
19891094Sdes				    pw->pw_name);
19991094Sdes				return 0;
20091094Sdes			}
20191094Sdes		ga_free();
20291684Sdes	}
20391094Sdes
20491094Sdes#ifdef WITH_AIXAUTHENTICATE
20591094Sdes	/*
20691094Sdes	 * Don't check loginrestrictions() for root account (use
20791094Sdes	 * PermitRootLogin to control logins via ssh), or if running as
20891094Sdes	 * non-root user (since loginrestrictions will always fail).
20991094Sdes	 */
21091094Sdes	if ((pw->pw_uid != 0) && (geteuid() == 0) &&
21194532Sdes	    loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
21294532Sdes		int loginrestrict_errno = errno;
21394532Sdes
21494532Sdes		if (loginmsg && *loginmsg) {
21594532Sdes			/* Remove embedded newlines (if any) */
21694532Sdes			char *p;
21794532Sdes			for (p = loginmsg; *p; p++) {
21894532Sdes				if (*p == '\n')
21994532Sdes					*p = ' ';
22094532Sdes			}
22194532Sdes			/* Remove trailing newline */
22294532Sdes			*--p = '\0';
22394532Sdes			log("Login restricted for %s: %.100s", pw->pw_name,
22494532Sdes			    loginmsg);
22594532Sdes		}
22694532Sdes		/* Don't fail if /etc/nologin  set */
22794532Sdes	    	if (!(loginrestrict_errno == EPERM &&
22894532Sdes		    stat(_PATH_NOLOGIN, &st) == 0))
22994532Sdes			return 0;
23094532Sdes	}
23194532Sdes#endif /* WITH_AIXAUTHENTICATE */
23294532Sdes
23394532Sdes	/* We found no reason not to let this user try to log on... */
23494532Sdes	return 1;
23594532Sdes}
23694532Sdes
23794532SdesAuthctxt *
23894532Sdesauthctxt_new(void)
23994532Sdes{
24094532Sdes	Authctxt *authctxt = xmalloc(sizeof(*authctxt));
24194532Sdes	memset(authctxt, 0, sizeof(*authctxt));
24294532Sdes	return authctxt;
24394532Sdes}
24494532Sdes
24594532Sdesvoid
24694532Sdesauth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
24794532Sdes{
24894532Sdes	void (*authlog) (const char *fmt,...) = verbose;
24994532Sdes	char *authmsg;
25094532Sdes
25191094Sdes	/* Raise logging level */
25291094Sdes	if (authenticated == 1 ||
25391094Sdes	    !authctxt->valid ||
25491094Sdes	    authctxt->failures >= AUTH_FAIL_LOG ||
25591094Sdes	    strcmp(method, "password") == 0)
25691094Sdes		authlog = log;
25793982Sdes
25893982Sdes	if (authctxt->postponed)
25991094Sdes		authmsg = "Postponed";
26093982Sdes	else
26193982Sdes		authmsg = authenticated ? "Accepted" : "Failed";
26291094Sdes
26391094Sdes	authlog("%s %s for %s%.100s from %.200s port %d%s",
26491094Sdes	    authmsg,
26591094Sdes	    method,
26691094Sdes	    authctxt->valid ? "" : "illegal user ",
26791094Sdes	    authctxt->user,
26891684Sdes	    get_remote_ipaddr(),
26991684Sdes	    get_remote_port(),
27094532Sdes	    info);
27194532Sdes
27291094Sdes#ifdef WITH_AIXAUTHENTICATE
27391100Sdes	if (authenticated == 0 && strcmp(method, "password") == 0)
27491094Sdes	    loginfailed(authctxt->user,
27591094Sdes		get_canonical_hostname(options.verify_reverse_mapping),
27691094Sdes		"ssh");
27791094Sdes#endif /* WITH_AIXAUTHENTICATE */
27891094Sdes
27991094Sdes}
28091094Sdes
28191094Sdes/*
28291094Sdes * Check whether root logins are disallowed.
28391094Sdes */
28491094Sdesint
285auth_root_allowed(char *method)
286{
287	switch (options.permit_root_login) {
288	case PERMIT_YES:
289		return 1;
290		break;
291	case PERMIT_NO_PASSWD:
292		if (strcmp(method, "password") != 0)
293			return 1;
294		break;
295	case PERMIT_FORCED_ONLY:
296		if (forced_command) {
297			log("Root login accepted for forced command.");
298			return 1;
299		}
300		break;
301	}
302	log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
303	return 0;
304}
305
306
307/*
308 * Given a template and a passwd structure, build a filename
309 * by substituting % tokenised options. Currently, %% becomes '%',
310 * %h becomes the home directory and %u the username.
311 *
312 * This returns a buffer allocated by xmalloc.
313 */
314char *
315expand_filename(const char *filename, struct passwd *pw)
316{
317	Buffer buffer;
318	char *file;
319	const char *cp;
320
321	/*
322	 * Build the filename string in the buffer by making the appropriate
323	 * substitutions to the given file name.
324	 */
325	buffer_init(&buffer);
326	for (cp = filename; *cp; cp++) {
327		if (cp[0] == '%' && cp[1] == '%') {
328			buffer_append(&buffer, "%", 1);
329			cp++;
330			continue;
331		}
332		if (cp[0] == '%' && cp[1] == 'h') {
333			buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir));
334			cp++;
335			continue;
336		}
337		if (cp[0] == '%' && cp[1] == 'u') {
338			buffer_append(&buffer, pw->pw_name,
339			    strlen(pw->pw_name));
340			cp++;
341			continue;
342		}
343		buffer_append(&buffer, cp, 1);
344	}
345	buffer_append(&buffer, "\0", 1);
346
347	/*
348	 * Ensure that filename starts anchored. If not, be backward
349	 * compatible and prepend the '%h/'
350	 */
351	file = xmalloc(MAXPATHLEN);
352	cp = buffer_ptr(&buffer);
353	if (*cp != '/')
354		snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp);
355	else
356		strlcpy(file, cp, MAXPATHLEN);
357
358	buffer_free(&buffer);
359	return file;
360}
361
362char *
363authorized_keys_file(struct passwd *pw)
364{
365	return expand_filename(options.authorized_keys_file, pw);
366}
367
368char *
369authorized_keys_file2(struct passwd *pw)
370{
371	return expand_filename(options.authorized_keys_file2, pw);
372}
373
374/* return ok if key exists in sysfile or userfile */
375HostStatus
376check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
377    const char *sysfile, const char *userfile)
378{
379	Key *found;
380	char *user_hostfile;
381	struct stat st;
382	HostStatus host_status;
383
384	/* Check if we know the host and its host key. */
385	found = key_new(key->type);
386	host_status = check_host_in_hostfile(sysfile, host, key, found, NULL);
387
388	if (host_status != HOST_OK && userfile != NULL) {
389		user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
390		if (options.strict_modes &&
391		    (stat(user_hostfile, &st) == 0) &&
392		    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
393		    (st.st_mode & 022) != 0)) {
394			log("Authentication refused for %.100s: "
395			    "bad owner or modes for %.200s",
396			    pw->pw_name, user_hostfile);
397		} else {
398			temporarily_use_uid(pw);
399			host_status = check_host_in_hostfile(user_hostfile,
400			    host, key, found, NULL);
401			restore_uid();
402		}
403		xfree(user_hostfile);
404	}
405	key_free(found);
406
407	debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ?
408	    "ok" : "not found", host);
409	return host_status;
410}
411
412
413/*
414 * Check a given file for security. This is defined as all components
415 * of the path to the file must be owned by either the owner of
416 * of the file or root and no directories must be group or world writable.
417 *
418 * XXX Should any specific check be done for sym links ?
419 *
420 * Takes an open file descriptor, the file name, a uid and and
421 * error buffer plus max size as arguments.
422 *
423 * Returns 0 on success and -1 on failure
424 */
425int
426secure_filename(FILE *f, const char *file, struct passwd *pw,
427    char *err, size_t errlen)
428{
429	uid_t uid = pw->pw_uid;
430	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
431	char *cp;
432	int comparehome = 0;
433	struct stat st;
434
435	if (realpath(file, buf) == NULL) {
436		snprintf(err, errlen, "realpath %s failed: %s", file,
437		    strerror(errno));
438		return -1;
439	}
440	if (realpath(pw->pw_dir, homedir) != NULL)
441		comparehome = 1;
442
443	/* check the open file to avoid races */
444	if (fstat(fileno(f), &st) < 0 ||
445	    (st.st_uid != 0 && st.st_uid != uid) ||
446	    (st.st_mode & 022) != 0) {
447		snprintf(err, errlen, "bad ownership or modes for file %s",
448		    buf);
449		return -1;
450	}
451
452	/* for each component of the canonical path, walking upwards */
453	for (;;) {
454		if ((cp = dirname(buf)) == NULL) {
455			snprintf(err, errlen, "dirname() failed");
456			return -1;
457		}
458		strlcpy(buf, cp, sizeof(buf));
459
460		debug3("secure_filename: checking '%s'", buf);
461		if (stat(buf, &st) < 0 ||
462		    (st.st_uid != 0 && st.st_uid != uid) ||
463		    (st.st_mode & 022) != 0) {
464			snprintf(err, errlen,
465			    "bad ownership or modes for directory %s", buf);
466			return -1;
467		}
468
469		/* If are passed the homedir then we can stop */
470		if (comparehome && strcmp(homedir, buf) == 0) {
471			debug3("secure_filename: terminating check at '%s'",
472			    buf);
473			break;
474		}
475		/*
476		 * dirname should always complete with a "/" path,
477		 * but we can be paranoid and check for "." too
478		 */
479		if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
480			break;
481	}
482	return 0;
483}
484
485struct passwd *
486getpwnamallow(const char *user)
487{
488#ifdef HAVE_LOGIN_CAP
489	extern login_cap_t *lc;
490#ifdef BSD_AUTH
491	auth_session_t *as;
492#endif
493#endif
494	struct passwd *pw;
495
496	pw = getpwnam(user);
497	if (pw == NULL) {
498		log("Illegal user %.100s from %.100s",
499		    user, get_remote_ipaddr());
500#ifdef WITH_AIXAUTHENTICATE
501		loginfailed(user,
502		    get_canonical_hostname(options.verify_reverse_mapping),
503		    "ssh");
504#endif
505		return (NULL);
506	}
507	if (!allowed_user(pw))
508		return (NULL);
509#ifdef HAVE_LOGIN_CAP
510	if ((lc = login_getpwclass(pw)) == NULL) {
511		debug("unable to get login class: %s", user);
512		return (NULL);
513	}
514#ifdef BSD_AUTH
515	if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
516	    auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
517		debug("Approval failure for %s", user);
518		pw = NULL;
519	}
520	if (as != NULL)
521		auth_close(as);
522#endif
523#endif
524	if (pw != NULL)
525		return (pwcopy(pw));
526	return (NULL);
527}
528
529void
530auth_debug_add(const char *fmt,...)
531{
532	char buf[1024];
533	va_list args;
534
535	if (!auth_debug_init)
536		return;
537
538	va_start(args, fmt);
539	vsnprintf(buf, sizeof(buf), fmt, args);
540	va_end(args);
541	buffer_put_cstring(&auth_debug, buf);
542}
543
544void
545auth_debug_send(void)
546{
547	char *msg;
548
549	if (!auth_debug_init)
550		return;
551	while (buffer_len(&auth_debug)) {
552		msg = buffer_get_string(&auth_debug, NULL);
553		packet_send_debug("%s", msg);
554		xfree(msg);
555	}
556}
557
558void
559auth_debug_reset(void)
560{
561	if (auth_debug_init)
562		buffer_clear(&auth_debug);
563	else {
564		buffer_init(&auth_debug);
565		auth_debug_init = 1;
566	}
567}
568