1296781Sdes/* $OpenBSD: sshlogin.c,v 1.32 2015/12/26 20:51:35 guenther Exp $ */
276259Sgreen/*
376259Sgreen * Author: Tatu Ylonen <ylo@cs.hut.fi>
476259Sgreen * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
576259Sgreen *                    All rights reserved
676259Sgreen * This file performs some of the things login(1) normally does.  We cannot
776259Sgreen * easily use something like login -p -h host -f user, because there are
876259Sgreen * several different logins around, and it is hard to determined what kind of
976259Sgreen * login the current system has.  Also, we want to be able to execute commands
1076259Sgreen * on a tty.
1176259Sgreen *
1276259Sgreen * As far as I am concerned, the code I have written for this software
1376259Sgreen * can be used freely for any purpose.  Any derived versions of this
1476259Sgreen * software must be clearly marked as such, and if the derived work is
1576259Sgreen * incompatible with the protocol description in the RFC file, it must be
1676259Sgreen * called by a name other than "ssh" or "Secure Shell".
1776259Sgreen *
1876259Sgreen * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
1976259Sgreen * Copyright (c) 1999 Markus Friedl.  All rights reserved.
2076259Sgreen *
2176259Sgreen * Redistribution and use in source and binary forms, with or without
2276259Sgreen * modification, are permitted provided that the following conditions
2376259Sgreen * are met:
2476259Sgreen * 1. Redistributions of source code must retain the above copyright
2576259Sgreen *    notice, this list of conditions and the following disclaimer.
2676259Sgreen * 2. Redistributions in binary form must reproduce the above copyright
2776259Sgreen *    notice, this list of conditions and the following disclaimer in the
2876259Sgreen *    documentation and/or other materials provided with the distribution.
2976259Sgreen *
3076259Sgreen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3176259Sgreen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3276259Sgreen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3376259Sgreen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3476259Sgreen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3576259Sgreen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3676259Sgreen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3776259Sgreen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3876259Sgreen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3976259Sgreen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4076259Sgreen */
4176259Sgreen
4276259Sgreen#include "includes.h"
4376259Sgreen
44162856Sdes#include <sys/types.h>
45162856Sdes#include <sys/socket.h>
46162856Sdes
47162856Sdes#include <netinet/in.h>
48162856Sdes
49162856Sdes#include <errno.h>
50162856Sdes#include <fcntl.h>
51162856Sdes#include <stdarg.h>
52162856Sdes#include <stdio.h>
53162856Sdes#include <string.h>
54162856Sdes#include <time.h>
55162856Sdes#include <unistd.h>
56295367Sdes#include <limits.h>
57162856Sdes
5898941Sdes#include "loginrec.h"
59137019Sdes#include "log.h"
60137019Sdes#include "buffer.h"
61295367Sdes#include "misc.h"
62137019Sdes#include "servconf.h"
6376259Sgreen
64137019Sdesextern Buffer loginmsg;
65137019Sdesextern ServerOptions options;
66137019Sdes
6776259Sgreen/*
6876259Sgreen * Returns the time when the user last logged in.  Returns 0 if the
6976259Sgreen * information is not available.  This must be called before record_login.
7076259Sgreen * The host the user logged in from will be returned in buf.
7176259Sgreen */
72162856Sdestime_t
7376259Sgreenget_last_login_time(uid_t uid, const char *logname,
74162856Sdes    char *buf, size_t bufsize)
7576259Sgreen{
76128460Sdes	struct logininfo li;
7776259Sgreen
78128460Sdes	login_get_lastlog(&li, uid);
79128460Sdes	strlcpy(buf, li.hostname, bufsize);
80162856Sdes	return (time_t)li.tv_sec;
8176259Sgreen}
8276259Sgreen
8376259Sgreen/*
84137019Sdes * Generate and store last login message.  This must be done before
85137019Sdes * login_login() is called and lastlog is updated.
86137019Sdes */
87137019Sdesstatic void
88137019Sdesstore_lastlog_message(const char *user, uid_t uid)
89137019Sdes{
90197679Sdes#ifndef NO_SSH_LASTLOG
91295367Sdes	char *time_string, hostname[HOST_NAME_MAX+1] = "", buf[512];
92137019Sdes	time_t last_login_time;
93137019Sdes
94137019Sdes	if (!options.print_lastlog)
95137019Sdes		return;
96137019Sdes
97197679Sdes# ifdef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG
98197679Sdes	time_string = sys_auth_get_lastlogin_msg(user, uid);
99197679Sdes	if (time_string != NULL) {
100197679Sdes		buffer_append(&loginmsg, time_string, strlen(time_string));
101255767Sdes		free(time_string);
102197679Sdes	}
103197679Sdes# else
104137019Sdes	last_login_time = get_last_login_time(uid, user, hostname,
105137019Sdes	    sizeof(hostname));
106137019Sdes
107137019Sdes	if (last_login_time != 0) {
108137019Sdes		time_string = ctime(&last_login_time);
109181111Sdes		time_string[strcspn(time_string, "\n")] = '\0';
110137019Sdes		if (strcmp(hostname, "") == 0)
111137019Sdes			snprintf(buf, sizeof(buf), "Last login: %s\r\n",
112137019Sdes			    time_string);
113137019Sdes		else
114137019Sdes			snprintf(buf, sizeof(buf), "Last login: %s from %s\r\n",
115137019Sdes			    time_string, hostname);
116137019Sdes		buffer_append(&loginmsg, buf, strlen(buf));
117137019Sdes	}
118197679Sdes# endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */
119137019Sdes#endif /* NO_SSH_LASTLOG */
120137019Sdes}
121137019Sdes
122137019Sdes/*
123124211Sdes * Records that the user has logged in.  I wish these parts of operating
124124211Sdes * systems were more standardized.
12576259Sgreen */
12676259Sgreenvoid
127137019Sdesrecord_login(pid_t pid, const char *tty, const char *user, uid_t uid,
128162856Sdes    const char *host, struct sockaddr *addr, socklen_t addrlen)
12976259Sgreen{
130128460Sdes	struct logininfo *li;
13176259Sgreen
132137019Sdes	/* save previous login details before writing new */
133137019Sdes	store_lastlog_message(user, uid);
134137019Sdes
135137019Sdes	li = login_alloc_entry(pid, user, host, tty);
136128460Sdes	login_set_addr(li, addr, addrlen);
137128460Sdes	login_login(li);
138128460Sdes	login_free_entry(li);
13998941Sdes}
14076259Sgreen
14198941Sdes#ifdef LOGIN_NEEDS_UTMPX
14298941Sdesvoid
14398941Sdesrecord_utmp_only(pid_t pid, const char *ttyname, const char *user,
144162856Sdes		 const char *host, struct sockaddr *addr, socklen_t addrlen)
14598941Sdes{
146128460Sdes	struct logininfo *li;
14776259Sgreen
148128460Sdes	li = login_alloc_entry(pid, user, host, ttyname);
149128460Sdes	login_set_addr(li, addr, addrlen);
150128460Sdes	login_utmp_only(li);
151128460Sdes	login_free_entry(li);
15276259Sgreen}
15398941Sdes#endif
15476259Sgreen
15576259Sgreen/* Records that the user has logged out. */
15676259Sgreenvoid
157137019Sdesrecord_logout(pid_t pid, const char *tty, const char *user)
15876259Sgreen{
159128460Sdes	struct logininfo *li;
16098941Sdes
161137019Sdes	li = login_alloc_entry(pid, user, NULL, tty);
162128460Sdes	login_logout(li);
163128460Sdes	login_free_entry(li);
16476259Sgreen}
165