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

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