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