sshlogin.c revision 76607
14Srgrimes/*
24Srgrimes * Author: Tatu Ylonen <ylo@cs.hut.fi>
34Srgrimes * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
44Srgrimes *                    All rights reserved
54Srgrimes * This file performs some of the things login(1) normally does.  We cannot
64Srgrimes * easily use something like login -p -h host -f user, because there are
74Srgrimes * several different logins around, and it is hard to determined what kind of
84Srgrimes * login the current system has.  Also, we want to be able to execute commands
94Srgrimes * on a tty.
104Srgrimes *
114Srgrimes * As far as I am concerned, the code I have written for this software
124Srgrimes * can be used freely for any purpose.  Any derived versions of this
134Srgrimes * software must be clearly marked as such, and if the derived work is
144Srgrimes * incompatible with the protocol description in the RFC file, it must be
154Srgrimes * called by a name other than "ssh" or "Secure Shell".
164Srgrimes *
174Srgrimes * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
184Srgrimes * Copyright (c) 1999 Markus Friedl.  All rights reserved.
194Srgrimes *
204Srgrimes * Redistribution and use in source and binary forms, with or without
214Srgrimes * modification, are permitted provided that the following conditions
224Srgrimes * are met:
234Srgrimes * 1. Redistributions of source code must retain the above copyright
244Srgrimes *    notice, this list of conditions and the following disclaimer.
254Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
264Srgrimes *    notice, this list of conditions and the following disclaimer in the
274Srgrimes *    documentation and/or other materials provided with the distribution.
284Srgrimes *
294Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
304Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
314Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
324Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
33621Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3450477Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
354Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
364Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37719Swollman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
385594Sbde * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39719Swollman */
404Srgrimes
414Srgrimes#include "includes.h"
424SrgrimesRCSID("$OpenBSD: sshlogin.c,v 1.2 2001/03/24 16:43:27 stevesk Exp $");
434SrgrimesRCSID("$FreeBSD: head/crypto/openssh/sshlogin.c 76607 2001-05-15 01:50:40Z green $");
444Srgrimes
454Srgrimes#include <libutil.h>
464Srgrimes#include <utmp.h>
474Srgrimes#include "sshlogin.h"
484Srgrimes#include "log.h"
494Srgrimes
504Srgrimes/*
514Srgrimes * Returns the time when the user last logged in.  Returns 0 if the
524Srgrimes * information is not available.  This must be called before record_login.
534Srgrimes * The host the user logged in from will be returned in buf.
544Srgrimes */
5524112Skato
5624112Skatou_long
5724112Skatoget_last_login_time(uid_t uid, const char *logname,
5824112Skato		    char *buf, u_int bufsize)
5924112Skato{
6024112Skato	struct lastlog ll;
612495Spst	char *lastlog;
622495Spst	int fd;
6319621Sdyson
6419621Sdyson	lastlog = _PATH_LASTLOG;
6519621Sdyson	buf[0] = '\0';
6619621Sdyson
6719621Sdyson	fd = open(lastlog, O_RDONLY);
6819621Sdyson	if (fd < 0)
6919621Sdyson		return 0;
7019621Sdyson	lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
7119621Sdyson	if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) {
7219621Sdyson		close(fd);
7319621Sdyson		return 0;
7451127Speter	}
7551127Speter	close(fd);
7619621Sdyson	if (bufsize > sizeof(ll.ll_host) + 1)
7719621Sdyson		bufsize = sizeof(ll.ll_host) + 1;
7819621Sdyson	strncpy(buf, ll.ll_host, bufsize - 1);
7919621Sdyson	buf[bufsize - 1] = 0;
8098650Smp	return ll.ll_time;
8198650Smp}
8298650Smp
8398650Smp/*
8498650Smp * Records that the user has logged in.  I these parts of operating systems
8598650Smp * were more standardized.
8698650Smp */
8798650Smp
8898650Smpvoid
8998650Smprecord_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
9098650Smp	     const char *host, struct sockaddr * addr)
9198650Smp{
9298650Smp	int fd;
9398650Smp	struct lastlog ll;
9498650Smp	char *lastlog;
9598650Smp	struct utmp u;
9698650Smp
9798650Smp	/* Construct an utmp/wtmp entry. */
9898650Smp	memset(&u, 0, sizeof(u));
9998650Smp	strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
10098650Smp	u.ut_time = time(NULL);
10198650Smp	strncpy(u.ut_name, user, sizeof(u.ut_name));
10298650Smp	realhostname_sa(u.ut_host, sizeof(u.ut_host), addr, addr->sa_len);
10398650Smp
10498650Smp	login(&u);
10598650Smp	lastlog = _PATH_LASTLOG;
10698650Smp
10798650Smp	/* Update lastlog unless actually recording a logout. */
10898650Smp	if (strcmp(user, "") != 0) {
109108909Sjhb		/*
11098650Smp		 * It is safer to bzero the lastlog structure first because
11198650Smp		 * some systems might have some extra fields in it (e.g. SGI)
11298650Smp		 */
11319621Sdyson		memset(&ll, 0, sizeof(ll));
11419621Sdyson
115109691Sjhb		/* Update lastlog. */
116108909Sjhb		ll.ll_time = time(NULL);
117108909Sjhb		strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
118108909Sjhb		strncpy(ll.ll_host, host, sizeof(ll.ll_host));
119108909Sjhb		fd = open(lastlog, O_RDWR);
120108909Sjhb		if (fd >= 0) {
121108909Sjhb			lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
122108909Sjhb			if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
12345406Smsmith				log("Could not write %.100s: %.100s", lastlog, strerror(errno));
12445406Smsmith			close(fd);
12545406Smsmith		}
12645406Smsmith	}
12745406Smsmith}
12845406Smsmith
12945406Smsmith/* Records that the user has logged out. */
13045406Smsmith
13145406Smsmithvoid
13245406Smsmithrecord_logout(pid_t pid, const char *ttyname)
13345406Smsmith{
13445406Smsmith	const char *line = ttyname + 5;	/* /dev/ttyq8 -> ttyq8 */
13545406Smsmith	if (logout(line))
13645406Smsmith		logwtmp(line, "", "");
13745406Smsmith}
13845406Smsmith