[BACK]Return to login.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/login.c, Revision 1.1

1.1     ! deraadt     1: /*
        !             2:
        !             3: login.c
        !             4:
        !             5: Author: Tatu Ylonen <ylo@cs.hut.fi>
        !             6:
        !             7: Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
        !             8:                    All rights reserved
        !             9:
        !            10: Created: Fri Mar 24 14:51:08 1995 ylo
        !            11:
        !            12: This file performs some of the things login(1) normally does.  We cannot
        !            13: easily use something like login -p -h host -f user, because there are
        !            14: several different logins around, and it is hard to determined what kind of
        !            15: login the current system has.  Also, we want to be able to execute commands
        !            16: on a tty.
        !            17:
        !            18: */
        !            19:
        !            20: #include "includes.h"
        !            21: RCSID("$Id: login.c,v 1.3 1999/05/04 11:58:49 bg Exp $");
        !            22:
        !            23: #ifdef HAVE_UTMP_H
        !            24: #include <utmp.h>
        !            25: #ifdef HAVE_LASTLOG_H
        !            26: #include <lastlog.h> /* Some have the definitions in utmp.h. */
        !            27: #endif /* HAVE_LASTLOG_H */
        !            28: #endif /* HAVE_UTMP_H */
        !            29: #ifdef HAVE_UTMPX_H
        !            30: #include <utmpx.h>
        !            31: #endif /* HAVE_UTMPX_H */
        !            32: #ifdef HAVE_USERSEC_H
        !            33: #include <usersec.h>
        !            34: #endif /* HAVE_USERSEC_H */
        !            35: #include "ssh.h"
        !            36:
        !            37: /* Returns the time when the user last logged in.  Returns 0 if the
        !            38:    information is not available.  This must be called before record_login.
        !            39:    The host the user logged in from will be returned in buf. */
        !            40:
        !            41: #ifdef LASTLOG_IS_DIR
        !            42: unsigned long get_last_login_time(uid_t uid, const char *name,
        !            43:                                  char *buf, unsigned int bufsize)
        !            44: {
        !            45: #if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
        !            46:   struct lastlog ll;
        !            47:   char lastlogfile[500];
        !            48:   int fd;
        !            49:
        !            50: #ifdef _PATH_LASTLOG
        !            51:   sprintf(lastlogfile, "%.200s/%.200s", _PATH_LASTLOG, name);
        !            52: #else
        !            53: #ifdef LASTLOG_FILE
        !            54:   sprintf(lastlogfile, "%.200s/%.200s", LASTLOG_FILE, name);
        !            55: #else
        !            56:   sprintf(lastlogfile, "%.200s/%.200s", SSH_LASTLOG, name);
        !            57: #endif
        !            58: #endif
        !            59:
        !            60:   strcpy(buf, "");
        !            61:
        !            62:   fd = open(lastlogfile, O_RDONLY);
        !            63:   if (fd < 0)
        !            64:     return 0;
        !            65:   if (read(fd, &ll, sizeof(ll)) != sizeof(ll))
        !            66:     {
        !            67:       close(fd);
        !            68:       return 0;
        !            69:     }
        !            70:   close(fd);
        !            71:   if (bufsize > sizeof(ll.ll_host) + 1)
        !            72:     bufsize = sizeof(ll.ll_host) + 1;
        !            73:   strncpy(buf, ll.ll_host, bufsize - 1);
        !            74:   buf[bufsize - 1] = 0;
        !            75:   return ll.ll_time;
        !            76:
        !            77: #else /* HAVE_LASTLOG_H || HAVE_LASTLOG */
        !            78:
        !            79:   return 0;
        !            80:
        !            81: #endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
        !            82: }
        !            83:
        !            84: #else /* LASTLOG_IS_DIR */
        !            85:
        !            86: /* Returns the time when the user last logged in (or 0 if no previous login
        !            87:    is found).  The name of the host used last time is returned in buf. */
        !            88:
        !            89: unsigned long get_last_login_time(uid_t uid, const char *logname,
        !            90:                                  char *buf, unsigned int bufsize)
        !            91: {
        !            92: #if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
        !            93:
        !            94:   struct lastlog ll;
        !            95:   char *lastlog;
        !            96:   int fd;
        !            97:
        !            98: #ifdef _PATH_LASTLOG
        !            99:   lastlog = _PATH_LASTLOG;
        !           100: #else
        !           101: #ifdef LASTLOG_FILE
        !           102:   lastlog = LASTLOG_FILE;
        !           103: #else
        !           104:   lastlog = SSH_LASTLOG;
        !           105: #endif
        !           106: #endif
        !           107:
        !           108:   strcpy(buf, "");
        !           109:
        !           110:   fd = open(lastlog, O_RDONLY);
        !           111:   if (fd < 0)
        !           112:     return 0;
        !           113:   lseek(fd, (off_t)((long)uid * sizeof(ll)), 0);
        !           114:   if (read(fd, &ll, sizeof(ll)) != sizeof(ll))
        !           115:     {
        !           116:       close(fd);
        !           117:       return 0;
        !           118:     }
        !           119:   close(fd);
        !           120:   if (bufsize > sizeof(ll.ll_host) + 1)
        !           121:     bufsize = sizeof(ll.ll_host) + 1;
        !           122:   strncpy(buf, ll.ll_host, bufsize - 1);
        !           123:   buf[bufsize - 1] = 0;
        !           124:   return ll.ll_time;
        !           125:
        !           126: #else /* HAVE_LASTLOG_H || HAVE_LASTLOG */
        !           127:
        !           128: #ifdef HAVE_USERSEC_H
        !           129:
        !           130:   char *lasthost;
        !           131:   int lasttime;
        !           132:   if (setuserdb(S_READ) < 0)
        !           133:     return 0;
        !           134:   if (getuserattr((char *)logname, S_LASTTIME, &lasttime, SEC_INT) < 0)
        !           135:     {
        !           136:       enduserdb();
        !           137:       return 0;
        !           138:     }
        !           139:   if (getuserattr((char *)logname, S_LASTHOST, &lasthost, SEC_CHAR) < 0)
        !           140:     {
        !           141:       enduserdb();
        !           142:       return 0;
        !           143:     }
        !           144:   strncpy(buf, lasthost, bufsize);
        !           145:   buf[bufsize - 1] = 0;
        !           146:   if (enduserdb() < 0)
        !           147:     return 0;
        !           148:   return lasttime;
        !           149:
        !           150: #else /* HAVE_USERSEC_H */
        !           151:
        !           152:   return 0;
        !           153:
        !           154: #endif /* HAVE_USERSEC_H */
        !           155:
        !           156: #endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
        !           157: }
        !           158: #endif /* LASTLOG_IS_DIR */
        !           159:
        !           160: /* Records that the user has logged in.  I these parts of operating systems
        !           161:    were more standardized. */
        !           162:
        !           163: void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
        !           164:                  const char *host, struct sockaddr_in *addr)
        !           165: {
        !           166:   int fd;
        !           167:
        !           168: #if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
        !           169:   struct lastlog ll;
        !           170:   char *lastlog;
        !           171: #ifdef LASTLOG_IS_DIR
        !           172:   char lastlogfile[100];
        !           173: #endif /* LASTLOG_IS_DIR */
        !           174: #endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
        !           175:
        !           176: #if defined(HAVE_UTMP_H) && !defined(HAVE_UTMPX_H)
        !           177:   struct utmp u, u2;
        !           178:   off_t offset;
        !           179:   const char *utmp, *wtmp;
        !           180:
        !           181:   /* Construct an utmp/wtmp entry. */
        !           182:   memset(&u, 0, sizeof(u));
        !           183: #ifdef DEAD_PROCESS
        !           184:   if (strcmp(user, "") == 0)
        !           185:     u.ut_type = DEAD_PROCESS; /* logout */
        !           186:   else
        !           187:     u.ut_type = USER_PROCESS;
        !           188: #endif /* LOGIN_PROCESS */
        !           189: #ifdef HAVE_PID_IN_UTMP
        !           190:   u.ut_pid = pid;
        !           191: #endif /* PID_IN_UTMP */
        !           192: #ifdef HAVE_ID_IN_UTMP
        !           193: #ifdef __sgi
        !           194:     strncpy(u.ut_id, ttyname + 8, sizeof(u.ut_id)); /* /dev/ttyq99 -> q99 */
        !           195: #else /* __sgi */
        !           196:     if (sizeof(u.ut_id) > 4)
        !           197:       strncpy(u.ut_id, ttyname + 5, sizeof(u.ut_id));
        !           198:     else
        !           199:       strncpy(u.ut_id, ttyname + strlen(ttyname) - 2, sizeof(u.ut_id));
        !           200: #endif /* __sgi */
        !           201: #endif /* HAVE_ID_IN_UTMP */
        !           202:   strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
        !           203:   u.ut_time = time(NULL);
        !           204: #ifdef HAVE_NAME_IN_UTMP
        !           205:   strncpy(u.ut_name, user, sizeof(u.ut_name));
        !           206: #else /* HAVE_NAME_IN_UTMP */
        !           207:   strncpy(u.ut_user, user, sizeof(u.ut_user));
        !           208: #endif /* HAVE_NAME_IN_UTMP */
        !           209: #ifdef HAVE_HOST_IN_UTMP
        !           210:   strncpy(u.ut_host, host, sizeof(u.ut_host));
        !           211: #endif /* HAVE_HOST_IN_UTMP */
        !           212: #ifdef HAVE_ADDR_IN_UTMP
        !           213:   if (addr)
        !           214:     memcpy(&u.ut_addr, &addr->sin_addr, sizeof(u.ut_addr));
        !           215:   else
        !           216:     memset(&u.ut_addr, 0, sizeof(u.ut_addr));
        !           217: #endif
        !           218:
        !           219:   /* Figure out the file names. */
        !           220: #ifdef _PATH_UTMP
        !           221:   utmp = _PATH_UTMP;
        !           222:   wtmp = _PATH_WTMP;
        !           223: #else
        !           224: #ifdef UTMP_FILE
        !           225:   utmp = UTMP_FILE;
        !           226:   wtmp = WTMP_FILE;
        !           227: #else
        !           228:   utmp = SSH_UTMP;
        !           229:   wtmp = SSH_WTMP;
        !           230: #endif
        !           231: #endif
        !           232:
        !           233: #ifdef HAVE_LIBUTIL_LOGIN
        !           234:   login(&u);
        !           235: #else /* HAVE_LIBUTIL_LOGIN */
        !           236:   /* Append an entry to wtmp. */
        !           237:   fd = open(wtmp, O_WRONLY|O_APPEND);
        !           238:   if (fd >= 0)
        !           239:     {
        !           240:       if (write(fd, &u, sizeof(u)) != sizeof(u))
        !           241:        log("Could not write %.100s: %.100s", wtmp, strerror(errno));
        !           242:       close(fd);
        !           243:     }
        !           244:
        !           245:   /* Replace the proper entry in utmp, as identified by ut_line.  Append a
        !           246:      new entry if the line could not be found. */
        !           247:   fd = open(utmp, O_RDWR);
        !           248:   if (fd >= 0)
        !           249:     {
        !           250:       while (1)
        !           251:        {
        !           252:          offset = lseek(fd, (off_t)0L, 1);
        !           253:          if (read(fd, &u2, sizeof(u2)) != sizeof(u2))
        !           254:            {
        !           255:              lseek(fd, offset, 0);
        !           256:              if (write(fd, &u, sizeof(u)) != sizeof(u))
        !           257:                log("Could not append to %.100s: %.100s",
        !           258:                    utmp, strerror(errno));
        !           259:              break;
        !           260:            }
        !           261:          if (strncmp(u2.ut_line, ttyname + 5, sizeof(u2.ut_line)) == 0)
        !           262:            {
        !           263:              lseek(fd, offset, 0);
        !           264:              if (write(fd, &u, sizeof(u)) != sizeof(u))
        !           265:                log("Could not write to %.100s: %.100s",
        !           266:                    utmp, strerror(errno));
        !           267:              break;
        !           268:            }
        !           269:        }
        !           270:       close(fd);
        !           271:     }
        !           272: #endif /* HAVE_LIBUTIL_LOGIN */
        !           273: #endif /* HAVE_UTMP_H && !HAVE_UTMPX_H */
        !           274:
        !           275: #ifdef HAVE_UTMPX_H
        !           276:   {
        !           277:     struct utmpx ux, *uxp;
        !           278:     memset(&ux, 0, sizeof(ux));
        !           279:     strncpy(ux.ut_line, ttyname + 5, sizeof(ux.ut_line));
        !           280:     uxp = getutxline(&ux);
        !           281:     if (uxp)
        !           282:       ux = *uxp;
        !           283:     strncpy(ux.ut_user, user, sizeof(ux.ut_user));
        !           284: #ifdef __sgi
        !           285:     strncpy(ux.ut_id, ttyname + 8, sizeof(ux.ut_id)); /* /dev/ttyq99 -> q99 */
        !           286: #else /* __sgi */
        !           287:     if (sizeof(ux.ut_id) > 4)
        !           288:       strncpy(ux.ut_id, ttyname + 5, sizeof(ux.ut_id));
        !           289:     else
        !           290:       strncpy(ux.ut_id, ttyname + strlen(ttyname) - 2, sizeof(ux.ut_id));
        !           291: #endif /* __sgi */
        !           292:     ux.ut_pid = pid;
        !           293:     if (strcmp(user, "") == 0)
        !           294:       ux.ut_type = DEAD_PROCESS;
        !           295:     else
        !           296:       ux.ut_type = USER_PROCESS;
        !           297:     gettimeofday(&ux.ut_tv, NULL);
        !           298: #if HAVE_UT_SESSION
        !           299:     ux.ut_session = pid;
        !           300: #endif
        !           301:     strncpy(ux.ut_host, host, sizeof(ux.ut_host));
        !           302:     ux.ut_host[sizeof(ux.ut_host) - 1] = 0;
        !           303: #ifdef HAVE_UT_SYSLEN
        !           304:     ux.ut_syslen = strlen(ux.ut_host);
        !           305: #endif
        !           306:     pututxline(&ux);
        !           307: #ifdef WTMPX_FILE
        !           308:     updwtmpx(WTMPX_FILE, &ux);
        !           309: #endif
        !           310:     endutxent();
        !           311:   }
        !           312: #endif /* HAVE_UTMPX_H */
        !           313:
        !           314: #if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
        !           315:
        !           316: #ifdef _PATH_LASTLOG
        !           317:   lastlog = _PATH_LASTLOG;
        !           318: #else
        !           319: #ifdef LASTLOG_FILE
        !           320:   lastlog = LASTLOG_FILE;
        !           321: #else
        !           322:   lastlog = SSH_LASTLOG;
        !           323: #endif
        !           324: #endif
        !           325:
        !           326:   /* Update lastlog unless actually recording a logout. */
        !           327:   if (strcmp(user, "") != 0)
        !           328:     {
        !           329:       /* It is safer to bzero the lastlog structure first because some
        !           330:         systems might have some extra fields in it (e.g. SGI) */
        !           331:       memset(&ll, 0, sizeof(ll));
        !           332:
        !           333:       /* Update lastlog. */
        !           334:       ll.ll_time = time(NULL);
        !           335:       strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
        !           336:       strncpy(ll.ll_host, host, sizeof(ll.ll_host));
        !           337: #ifdef LASTLOG_IS_DIR
        !           338:       sprintf(lastlogfile, "%.100s/%.100s", lastlog, user);
        !           339:       fd = open(lastlogfile, O_WRONLY | O_CREAT, 0644);
        !           340:       if (fd >= 0)
        !           341:        {
        !           342:          if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
        !           343:            log("Could not write %.100s: %.100s",
        !           344:                lastlogfile, strerror(errno));
        !           345:          close(fd);
        !           346:        }
        !           347:       else
        !           348:        {
        !           349:          log("Could not open %.100s: %.100s", lastlogfile, strerror(errno));
        !           350:        }
        !           351: #else /* LASTLOG_IS_DIR */
        !           352:       fd = open(lastlog, O_RDWR);
        !           353:       if (fd >= 0)
        !           354:        {
        !           355:          lseek(fd, (off_t)((long)uid * sizeof(ll)), 0);
        !           356:          if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
        !           357:            log("Could not write %.100s: %.100s", lastlog, strerror(errno));
        !           358:          close(fd);
        !           359:        }
        !           360: #endif /* LASTLOG_IS_DIR */
        !           361:     }
        !           362: #endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
        !           363:
        !           364: #ifdef HAVE_USERSEC_H
        !           365:
        !           366:   if (strcmp(user, "") != 0)
        !           367:     {
        !           368:       int lasttime = time(NULL);
        !           369:       if (setuserdb(S_WRITE) < 0)
        !           370:        log("setuserdb S_WRITE failed: %.100s", strerror(errno));
        !           371:       if (putuserattr((char *)user, S_LASTTIME, (void *)lasttime, SEC_INT) < 0)
        !           372:        log("putuserattr S_LASTTIME failed: %.100s", strerror(errno));
        !           373:       if (putuserattr((char *)user, S_LASTTTY, (void *)(ttyname + 5),
        !           374:                      SEC_CHAR) < 0)
        !           375:        log("putuserattr S_LASTTTY %.900s failed: %.100s",
        !           376:            ttyname, strerror(errno));
        !           377:       if (putuserattr((char *)user, S_LASTHOST, (void *)host, SEC_CHAR) < 0)
        !           378:        log("putuserattr S_LASTHOST %.900s failed: %.100s",
        !           379:            host, strerror(errno));
        !           380:       if (putuserattr((char *)user, 0, NULL, SEC_COMMIT) < 0)
        !           381:        log("putuserattr SEC_COMMIT failed: %.100s", strerror(errno));
        !           382:       if (enduserdb() < 0)
        !           383:        log("enduserdb failed: %.100s", strerror(errno));
        !           384:     }
        !           385: #endif
        !           386: }
        !           387:
        !           388: /* Records that the user has logged out. */
        !           389:
        !           390: void record_logout(int pid, const char *ttyname)
        !           391: {
        !           392: #ifdef HAVE_LIBUTIL_LOGIN
        !           393:   const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
        !           394:   if (logout(line))
        !           395:     logwtmp(line, "", "");
        !           396: #else /* HAVE_LIBUTIL_LOGIN */
        !           397:   record_login(pid, ttyname, "", -1, "", NULL);
        !           398: #endif /* HAVE_LIBUTIL_LOGIN */
        !           399: }