[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.2

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