Ejemplo n.º 1
0
int ssh_time_format(unsigned char *buf, int buf_size, SshTime input_time)
{
  struct SshCalendarTimeRec calendar[1];

  ssh_calendar_time(input_time, calendar, FALSE);
  return ssh_snprintf(buf, buf_size, "%04d%02d%02d%02d%02d%02d",
		      (int)calendar->year,
		      (int)calendar->month + 1,
		      (int)calendar->monthday,
		      (int)calendar->hour,
		      (int)calendar->minute,
		      (int)calendar->second);
}
Ejemplo n.º 2
0
char *ssh_readable_time_string(SshTime input_time, Boolean local_time)
{
  struct SshCalendarTimeRec calendar[1];
  unsigned char zoneid[8];
  unsigned char temp[100];

  ssh_calendar_time(input_time, calendar, local_time);

  if (calendar->utc_offset == 0)
    {
      zoneid[0] = '\0';
    }
  else if (calendar->utc_offset > 0)
    {
      ssh_snprintf(zoneid, sizeof (zoneid), " +%02d%02d",
                   (int)((calendar->utc_offset / 3600) % 100),
                   (int)((calendar->utc_offset / 60) % 60));
    }
  else
    {
      ssh_snprintf(zoneid, sizeof (zoneid), " -%02d%02d",
                   (int)(((- calendar->utc_offset) / 3600) % 100),
                   (int)(((- calendar->utc_offset) / 60) % 60));
    }

  ssh_snprintf(temp, sizeof(temp), "%s %s %02d %04d %02d:%02d:%02d%s",
               ssh_time_abbr_day[calendar->weekday % 7],
               ssh_time_abbr_month[calendar->month % 12],
               (int)calendar->monthday,
               (int)calendar->year,
               (int)calendar->hour,
               (int)calendar->minute,
               (int)calendar->second,
               zoneid);
  return ssh_strdup(temp);
}
Ejemplo n.º 3
0
void check_time(SshTime tv, int year, int month, int day)
{
  struct SshCalendarTimeRec ct[1], mt[1];
  SshTime cv;

  ssh_calendar_time(tv, ct, FALSE);
  if ((ct->year != year) ||
      ((ct->month + 1) != month) ||
      (ct->monthday != day))
    {
      fprintf(stderr, "ssh_calendar_time returns %04d-%02d-%02d\n",
              (int)ct->year, (int)ct->month + 1, (int)ct->monthday);
      fprintf(stderr, "reference value is %04d-%02d-%02d\n",
              year, month, day);
      exit(1);
    }
  *mt = *ct;
  if (!ssh_make_time(mt, &cv, FALSE))
    ssh_fatal("ssh_make_time fails");

  if (cv != tv)
    ssh_fatal("ssh_make_time returns different time than given "
              "to ssh_calendar_time");
  if (ct->year != mt->year ||
      ct->month != mt->month ||
      ct->monthday != mt->monthday ||
      ct->hour != mt->hour ||
      ct->minute != mt->minute ||
      ct->second != mt->second ||
      ct->weekday != mt->weekday ||
      ct->yearday != mt->yearday ||
      ct->dst != mt->dst ||
      ct->utc_offset != mt->utc_offset)
    ssh_fatal("Time values are different in struct");
  return;
}
Ejemplo n.º 4
0
/* Convert SshCalendarTime to SshTime. If the dst is set to TRUE then daylight
   saving time is assumed to be set, if dst field is set to FALSE then it is
   assumed to be off. It if it is set to -1 then the function tries to find out
   if the dst was on or off at the time given.

   Weekday and yearday fields are ignored in the conversion, but filled with
   approriate values during the conversion. All other values are normalized to
   their normal range during the conversion.

   If the local_time is set to TRUE then dst and utc_offset values
   are ignored.

   If the time cannot be expressed as SshTime this function returns FALSE,
   otherwise returns TRUE. */
Boolean ssh_make_time(SshCalendarTime calendar_time, SshTime *time_return,
                      Boolean local_time)
{
  SshCalendarTimeStruct test_time;
  SshTime estimate;

  SSH_DEBUG(SSH_D_MIDSTART, ("Original time is %04d-%02d-%02d %02d:%02d:%02d",
                             (int) calendar_time->year,
                             (int) calendar_time->month + 1,
                             (int) calendar_time->monthday,
                             (int) calendar_time->hour,
                             (int) calendar_time->minute,
                             (int) calendar_time->second));

  /* Normalize values first */
  while (calendar_time->second > 59)
    {
      SSH_DEBUG(SSH_D_UNCOMMON, ("Seconds too large, adjusting %d",
                                 calendar_time->second));
      calendar_time->second -= 60;
      calendar_time->minute++;
    }
  while (calendar_time->minute > 59)
    {
      SSH_DEBUG(SSH_D_UNCOMMON, ("Minutes too large, adjusting %d",
                                 calendar_time->minute));
      calendar_time->minute -= 60;
      calendar_time->hour++;
    }
  while (calendar_time->hour > 23)
    {
      SSH_DEBUG(SSH_D_UNCOMMON, ("Hours too large, adjusting %d",
                                 calendar_time->hour));
      calendar_time->hour -= 24;
      calendar_time->monthday++;
    }
  do {
    int days_per_month;

    while (calendar_time->month > 11)
      {
        SSH_DEBUG(SSH_D_UNCOMMON, ("Month too large, adjusting %d",
                                   calendar_time->month));
        calendar_time->month -= 12;
        calendar_time->year++;
      }
    days_per_month = monthdays[calendar_time->month] +
      ((calendar_time->month == 1 &&
        SSH_IS_LEAP_YEAR(calendar_time->year)) ? 1 : 0);
    if (calendar_time->monthday > days_per_month)
      {
        SSH_DEBUG(SSH_D_UNCOMMON, ("Month day too large, adjusting %d",
                                   calendar_time->monthday));
        calendar_time->monthday -= days_per_month;
        calendar_time->month++;
      }
    else if (calendar_time->monthday == 0)
      {
        SSH_DEBUG(SSH_D_UNCOMMON, ("Month day zero, adjusting %d",
                                   calendar_time->monthday));
        if (calendar_time->month == 0)
          {
            calendar_time->month = 11;
            calendar_time->year--;
          }
        else
          {
            calendar_time->month--;
          }
        calendar_time->monthday = monthdays[calendar_time->month] +
          ((calendar_time->month == 1 &&
            SSH_IS_LEAP_YEAR(calendar_time->year)) ? 1 : 0);
      }
    else
      {
        break;
      }
  } while (1);

  SSH_DEBUG(SSH_D_LOWOK, ("Adjusted time is %04d-%02d-%02d %02d:%02d:%02d",
                          (int) calendar_time->year,
                          (int) calendar_time->month + 1,
                          (int) calendar_time->monthday,
                          (int) calendar_time->hour,
                          (int) calendar_time->minute,
                          (int) calendar_time->second));

  /* Calculate estimate */
  estimate = calendar_time->monthday - 1 +
    30 * calendar_time->month +
    365 * (calendar_time->year - 1970) +
    ((calendar_time->year - 1970) / 4);
  estimate *= 24;
  estimate += calendar_time->hour;
  estimate *= 60;
  estimate += calendar_time->minute;
  estimate *= 60;
  estimate += calendar_time->second;

  do {
    SSH_DEBUG(SSH_D_LOWOK, ("Estimate is %ld", (unsigned long) estimate));
    ssh_calendar_time(estimate, &test_time, FALSE);
    SSH_DEBUG(SSH_D_LOWOK, ("Compare time is %04d-%02d-%02d %02d:%02d:%02d",
                            (int) test_time.year,
                            (int) test_time.month + 1,
                            (int) test_time.monthday,
                            (int) test_time.hour,
                            (int) test_time.minute,
                            (int) test_time.second));

    if (test_time.year == calendar_time->year &&
        test_time.month == calendar_time->month &&
        test_time.monthday == calendar_time->monthday &&
        test_time.hour == calendar_time->hour &&
        test_time.minute == calendar_time->minute &&
        test_time.second == calendar_time->second)
      break;
    if (test_time.year == calendar_time->year &&
        test_time.month == calendar_time->month &&
        test_time.monthday == calendar_time->monthday)
      {
        if (test_time.hour != calendar_time->hour)
          estimate += (calendar_time->hour - test_time.hour) * 3600;
        if (test_time.minute != calendar_time->minute)
          estimate += (calendar_time->minute - test_time.minute) * 60;
        if (test_time.hour != calendar_time->hour)
          estimate += (calendar_time->second - test_time.second);
        continue;
      }
    if (test_time.year != calendar_time->year)
      {
        estimate += (calendar_time->year - test_time.year) * 365 * 86400;
        continue;
      }
    if (test_time.month != calendar_time->month)
      {
        estimate += (calendar_time->month - test_time.month) * 28 * 86400;
        continue;
      }
    if (test_time.monthday != calendar_time->monthday)
      {
        estimate += (calendar_time->monthday - test_time.monthday) * 86400;
        continue;
      }
    ssh_fatal("Internal error in ssh_make_time");
  } while (1);

  if (local_time)
    {
      SshInt32 utc_offset;
      Boolean dst;

      ssh_get_local_timezone(estimate, &utc_offset, &dst);
      if (utc_offset != calendar_time->utc_offset && calendar_time->dst == -1)
        {
          SSH_DEBUG(SSH_D_UNCOMMON, ("Utc offset in input does not match "
                                     "current system timezone. Dst rules "
                                     "might be incorrect"));
        }
      SSH_DEBUG(SSH_D_LOWOK, ("Adding timezone informartion %d seconds",
                              (int) calendar_time->utc_offset));
      estimate += calendar_time->utc_offset;
      if (calendar_time->dst == TRUE ||
          (calendar_time->dst == -1 &&
           dst))
        estimate += 3600;
    }
  SSH_DEBUG(SSH_D_MIDSTART, ("Result is %ld", (unsigned long) estimate));
  *time_return =  estimate;
  calendar_time->yearday = test_time.yearday;
  calendar_time->weekday = test_time.weekday;
  return TRUE;
}
Ejemplo n.º 5
0
/* Returns seconds that local timezone is east from the UTC meridian
   and boolean which is TRUE if DST is in effect.
   This one is system dependent and yet even vulnerable to Y2K bug.
   Anyway, this is used only to retrieve current timezone.  If
   localtime(3) function freaks out with this call, we return just zero
   and assume that our localtime is UTC. */
void ssh_get_local_timezone(SshTime tv,
                            SshInt32 *utc_offset,
                            Boolean *dst)
{
#if ! defined (USE_SSH_INTERNAL_LOCALTIME) && defined (HAVE_LOCALTIME)
  struct tm *tm;
#if defined(_REENTRANT) && defined(__sun__) && defined(__svr4__)
  struct tm tms;
#endif
  time_t t;
  struct SshCalendarTimeRec ct[1];

  /* We trust localtime(3) for dst interpretation 1970-2037.
     Before this timeframe, we just check localtime for
     Jan 1 1998, which should work more or less everywhere.
     After 2037 we normalize this date to year 2037 and
     call system localtime(3) for that. */
  if ((tv > ((SshTime)0)) && (tv < ((SshTime)2145916800)))
    {
      t = (time_t)tv;
    }
  else if (tv >= ((SshTime)2145916800))
    {
      ssh_calendar_time(tv, ct, FALSE);
      if (SSH_IS_LEAP_YEAR(ct->year))
        t = (time_t)2082758400; /* 1.1.2036 */
      else
        t = (time_t)2114380800; /* 1.1.2037 */
      t += ((((time_t)86400) * ((time_t)(ct->yearday))) +
            (((time_t)3600) * ((time_t)(ct->hour))) +
            (((time_t)60) * ((time_t)(ct->minute))) +
            ((time_t)(ct->second)));
    }
  else
    {
      t = (time_t)883656061; /* Thu Jan 1 12:01:01 1998 UTC */
    }
#if defined(_REENTRANT) && defined(__sun__) && defined(__svr4__)
  tm = localtime_r(&t, &tms);
#else
#undef localtime
  tm = localtime(&t);
#endif
#ifdef HAVE_TM_GMTOFF_IN_STRUCT_TM
  if ((tm != NULL) &&
      (tm->tm_gmtoff >= (-50400)) &&
      (tm->tm_gmtoff <= 50400))
    {
      if (utc_offset != NULL)
        *utc_offset = (SshInt32)(tm->tm_gmtoff);
    }
  else
    {
      if (utc_offset != NULL)
        *utc_offset = (SshInt32)0;
    }
#else /* HAVE_TM_GMTOFF_IN_STRUCT_TM */
#ifdef HAVE_OLD_TM_GMTOFF_IN_STRUCT_TM
  if ((tm != NULL) &&
      (tm->__tm_gmtoff__ >= (-50400)) &&
      (tm->__tm_gmtoff__ <= 50400))
    {
      if (utc_offset != NULL)
        *utc_offset = (SshInt32)(tm->__tm_gmtoff__);
    }
  else
    {
      if (utc_offset != NULL)
        *utc_offset = (SshInt32)0;
    }
#else /* HAVE_OLD_TM_GMTOFF_IN_STRUCT_TM */
#ifdef HAVE_EXTERNAL_TIMEZONE
  if ((timezone >= (-50400))  && (timezone <= 50400))
    {
      if (utc_offset != NULL)
      {
        *utc_offset = (SshInt32) - timezone;
#ifdef HAVE_TM_ISDST_IN_STRUCT_TM
	/* 'timezone' is the difference between 
	   standard time and utc. */ 
	if (tm != NULL)
	  *utc_offset += (tm->tm_isdst != 0 ? 3600 : 0);
	else
	  *utc_offset = (SshUInt32)0;
#endif /* HAVE_TM_ISDST_IN_STRUCT_TM */
      }
    }
  else
    {
      if (utc_offset != NULL)
        *utc_offset = (SshInt32)0;
    }
#else /* HAVE_EXTERNAL_TIMEZONE */
  if (utc_offset != NULL)
    *utc_offset = (SshInt32)0;
#endif /* HAVE_EXTERNAL_TIMEZONE */
#endif /* HAVE_OLD_TM_GMTOFF_IN_STRUCT_TM */
#endif /* HAVE_TM_GMTOFF_IN_STRUCT_TM */
#ifdef HAVE_TM_ISDST_IN_STRUCT_TM
  if (tm != NULL)
    {
      if (dst != NULL)
        *dst = (tm->tm_isdst != 0);
    }
  else
    {
      if (dst != NULL)
        *dst = FALSE;
    }
#else /* HAVE_TM_ISDST_IN_STRUCT_TM */
  if (dst != NULL)
    *dst = FALSE;
#endif /* HAVE_TM_ISDST_IN_STRUCT_TM */
#else /* ! defined (USE_SSH_INTERNAL_LOCALTIME) && defined (HAVE_LOCALTIME) */
  if (utc_offset != NULL)
    *utc_offset = (SshInt32)0;
  if (dst != NULL)
    *dst = FALSE;
#endif /* ! defined (USE_SSH_INTERNAL_LOCALTIME) && defined (HAVE_LOCALTIME) */
}
Ejemplo n.º 6
0
int main()
{
  int i, j, k, d, y, p;
  char *a, *b, *first, *last, *rfirst, *rlast;
  SshTime t, t2;
  struct SshCalendarTimeRec ct[1], mt[1];

  ssh_debug_set_level_string("*=6");

  ssh_rand_seed(1234);
  for (i = 0; i < 1000; i++)
    {
      ct->year = 1900 + ssh_rand() % 200;
      ct->month = ssh_rand() % 12;
      ct->monthday = 1 + ssh_rand() % 28;
      ct->hour = ssh_rand() % 24;
      ct->minute = ssh_rand() % 60;
      ct->second = ssh_rand() % 60;
      ct->utc_offset = ((ssh_rand() % 96) - 48) * 900;
      ct->dst = (ssh_rand() % 3) - 1;
      if (!ssh_make_time(ct, &t, FALSE))
        ssh_fatal("ssh_make_time failed");
      ssh_calendar_time(t, mt, FALSE);
      if (ct->year != mt->year ||
          ct->month != mt->month ||
          ct->monthday != mt->monthday ||
          ct->hour != mt->hour ||
          ct->minute != mt->minute ||
          ct->second != mt->second ||
          ct->weekday != mt->weekday ||
          ct->yearday != mt->yearday)
        ssh_fatal("Time values are different in struct");
      if (!ssh_make_time(mt, &t2, TRUE))
        ssh_fatal("ssh_make_time failed");
      if (ct->year != mt->year ||
          ct->month != mt->month ||
          ct->monthday != mt->monthday ||
          ct->hour != mt->hour ||
          ct->minute != mt->minute ||
          ct->second != mt->second ||
          ct->weekday != mt->weekday ||
          ct->yearday != mt->yearday)
        ssh_fatal("Time values are different in struct with local time");
      if (mt->dst)
        t2 -= 3600;
      if (t2 - t != mt->utc_offset)
        ssh_fatal("Localtime vs gmtime values does not match!");
    }

  t = ssh_time();
  a = ssh_time_string(t);
  first = ssh_xstrdup(a);
  rfirst = ssh_readable_time_string(t, TRUE);
  printf("First value was \"%s\" (%s).\n", first, rfirst);
  for (i = 0; i < 5; i++)
    {
      for (j = 0; j < 100; j++)
        for (k = 0; k < 1000; k++)
          {
            b = ssh_time_string(ssh_time());
            if (strcmp(a, b) > 0)
              {
                fprintf(stderr,
                        "t-time: ssh_time_string returned value "
                        "\"%s\" after \"%s\", which doesn't sort right.\n",
                        b, a);
                exit(1);
              }
            ssh_xfree(a);
            a = b;
          }
      printf("Intermediate value #%d was \"%s\".\n", i + 1, a);
    }
  ssh_xfree(a);
  t = ssh_time();
  last = ssh_time_string(t);
  rlast = ssh_readable_time_string(t, TRUE);
  printf("First value was \"%s\" (%s).\n", first, rfirst);
  printf("Last value was \"%s\" (%s).\n", last, rlast);
  ssh_xfree(first);
  ssh_xfree(rfirst);
  ssh_xfree(last);
  ssh_xfree(rlast);
  check_time((SshTime)23200,       1970,  1,  1);   /* 01.01.1970 */
  check_time((SshTime)68212800,    1972,  2, 29);   /* 29.02.1972 */
  check_time((SshTime)946641600,   1999, 12, 31);   /* 31.12.1999 */
  check_time((SshTime)946728000,   2000,  1,  1);   /* 01.01.2000 */
  check_time((SshTime)951825600,   2000,  2, 29);   /* 29.02.2000 */
  check_time((SshTime)2147428800,  2038,  1, 18);   /* 18.01.2038 */
#define T_TIME_TEST_COUNT 25000
  {
    t = ((SshTime)43200) - (((SshTime)86400) * ((SshTime)T_TIME_TEST_COUNT));
    ssh_calendar_time(t, ct, FALSE);
    a = ssh_readable_time_string(t, TRUE);
    printf("Testing weekday consistency from: %s\n", a);
    printf("Be aware that days are in the Gregorian system "
           "even before the Gregorian era.\n");
    ssh_xfree(a);
    d = ct->weekday;
    y = ct->year;
    if ((d < 0) || (d > 6))
      {
        fprintf(stderr,
                "ssh_calendar_time returns %04d-%02d-%02d "
                "with wrong weekday %d\n",
                (int)ct->year,
                (int)ct->month + 1,
                (int)ct->monthday,
                (int)ct->weekday);
        exit(1);
      }
    p = d;
    for (i = 0; i < (T_TIME_TEST_COUNT * 2); i++)
      {
        t += 86400;
        ssh_calendar_time(t, ct, FALSE);
        d = (int)ct->weekday;
        if ((d < 0) || (d > 6) || (d != ((p + 1) % 7)))
          {
            fprintf(stderr,
                    "ssh_calendar_time returns %04d-%02d-%02d "
                    "with inconsistent weekday %d\n",
                    (int)ct->year,
                    (int)ct->month + 1,
                    (int)ct->monthday,
                    (int)ct->weekday);
            exit(1);
          }
#if 1
        if ((((ct->year % 100) == 0) &&
             (ct->month == 0) &&
             (ct->monthday == 1)) ||
            (((((ct->year - 20) % 100) == 0) &&
              (ct->month == 5) &&
              (ct->monthday == 24))))
#endif
          {
            a = ssh_readable_time_string(t, TRUE);
            b = ssh_readable_time_string(t, FALSE);
            printf("Intermediate: %s (universal)\n",b);
            printf("              %s (local)\n", a);
            ssh_xfree(a);
            ssh_xfree(b);
          }
        p = d;
        y = ct->year;
      }
  }
  a = ssh_readable_time_string(t, TRUE);
  printf("Weekday consistency tested until: %s\n", a);
  ssh_xfree(a);
  ssh_util_uninit();
  exit(0);
}
Ejemplo n.º 7
0
Boolean ssh_login_permitted(const char *user, SshUser uc)
{
  char passwd[20];              /* Only for account lock check */
 
  strncpy(passwd, uc->correct_encrypted_passwd, sizeof(passwd));
  passwd[sizeof(passwd) - 1] = '\0';

#ifdef HAVE_USERSEC_H
  {
    char *expiration, current_time[100], normalized[100];
    int rlogin_permitted;
    ssh_time t;
    struct SshCalendarTimeRec tm[1];
    int account_is_locked;
    
    if (setuserdb(S_READ) < 0)
      {
        if (getuid() == 0) /* It's OK to fail here if we are not root */
          {
            SSH_DEBUG(2, ("setuserdb S_READ failed: %.200s.", 
                          strerror(errno)));
          }
        return FALSE;
      }
    if (getuserattr((char *)user, S_RLOGINCHK, &rlogin_permitted,
                    SEC_BOOL) < 0)
      {
        if (getuid() == 0) /* It's OK to fail here if we are not root */
          {
            SSH_DEBUG(2, ("getuserattr S_RLOGINCHK failed: %.200s",
                          strerror(errno)));
          }
        enduserdb();
        return FALSE;
      }
    if (getuserattr((char *)user, S_EXPIRATION, &expiration, SEC_CHAR) < 0)
      {
        SSH_DEBUG(2, ("getuserattr S_EXPIRATION failed: %.200s.", 
                      strerror(errno)));
        enduserdb();
        return FALSE;
      }
#ifdef S_LOCKED
    if (getuserattr(user, S_LOCKED, &account_is_locked, SEC_BOOL) < 0)
      {
        SSH_DEBUG(2, ("getuserattr S_LOCKED failed: %.200s.", 
                      strerror(errno)));
        enduserdb();
        return FALSE;
      }
    if (account_is_locked)
      {
        SSH_DEBUG(2, ("Account %.100s is locked.", user));
        enduserdb();
        return FALSE;
      }
#endif /* S_LOCKED */
    if (!rlogin_permitted)
      {
        SSH_DEBUG(2, ("Remote logins to account %.100s not permitted by "
                      "user profile.",
                      user));
        enduserdb();
        return FALSE;
      }
    if (strcmp(expiration, "0") == 0)
      {
        /* The account does not expire - return success immediately. */
        enduserdb();
        return TRUE;
      }
    if (strlen(expiration) != 10)
      {
        SSH_DEBUG(2, ("Account %.100s expiration date is in wrong format.", 
                      user));
        enduserdb();
        return FALSE;
      }
    t = ssh_time();
    ssh_calendar_time(t, tm, TRUE);
    snprintf(current_time, sizeof(current_time), "%04d%02d%02d%02d%02d",
             tm->year, tm->month + 1, tm->monthday,
             tm->hour, tm->minute);
    if (expiration[8] < '7') /* Assume year < 70 is 20YY. */
      strcpy(normalized, "20");
    else
      strcpy(normalized, "19");
    strcat(normalized, expiration + 8);
    strcat(normalized, expiration);
    normalized[12] = '\0';
    if (strcmp(normalized, current_time) < 0)
      {
        SSH_DEBUG(2, ("Account %.100s has expired - access denied.", user));
        enduserdb();
        return FALSE;
      }
    enduserdb();
  }
#endif /* HAVE_USERSEC_H */
#ifdef HAVE_ETC_SHADOW
  {
    struct spwd *sp;
    
    sp = (struct spwd *)getspnam(user);
#if defined(SECURE_RPC) && defined(NIS_PLUS)
    if (geteuid() == UID_ROOT && ssh_user_uid(uc) != UID_ROOT
        && (!sp || !sp->sp_pwdp || !strcmp(sp->sp_pwdp,"*NP*")))
      {
        if (seteuid(ssh_user_uid(uc)) >= 0)
          {
            sp = getspnam(user); /* retry as user */
            seteuid(UID_ROOT); 
          }
      }
#endif /* SECURE_RPC && NIS_PLUS */
    if (!sp)
      {
        /*
         * Some systems, e.g.: IRIX, may or may not have /etc/shadow.
         * Just check if there is one. If such system is also an YP
         * client, then valid password might already be present in passwd
         * structure. Just check if it's other than "x". Assume that
         * YP server is always right if this is the case.
         *                                      [email protected]
         */
        struct stat sbf;
        
        if ((stat(SHADOW, &sbf) == 0) &&
            strcmp(uc->correct_encrypted_passwd, "x") == 0)
          {
            SSH_DEBUG(2, ("Can't find %.100s's shadow - access denied.", 
                          user));
            endspent();
            return FALSE;
          }
      }
    else
      {
        SshTime today = ssh_time()/24/60/60; /* what a day! */

#ifdef HAVE_STRUCT_SPWD_EXPIRE
        /* Check for expiration date */
        if (sp->sp_expire > 0 && today > sp->sp_expire)
          {
            SSH_DEBUG(2, ("Account %.100s has expired - access denied.", 
                          user));
            endspent();
            return FALSE;
          }
#endif
        
#ifdef HAVE_STRUCT_SPWD_INACT
        /* Check for last login */
        if (sp->sp_inact > 0)
          {
            char buf[64];
            SshTime llt;
            
            llt = ssh_user_get_last_login_time(uc, buf, sizeof(buf));
            if (llt && (today - llt/24/60/60) > sp->sp_inact)
              {
                SSH_DEBUG(2, ("Account %.100s was inactive for more than %d days.",
                              user, sp->sp_inact));
                endspent();
                return FALSE;
              }
          }
#endif
        
        /* Check if password is valid */
        if (sp->sp_lstchg == 0 ||
            (sp->sp_max > 0 && today > sp->sp_lstchg + sp->sp_max))
          {
            SSH_DEBUG(2, ("Account %.100s's password is too old - forced to change.",
                          user));
            uc->password_needs_change = TRUE;
          }
        strncpy(passwd, sp->sp_pwdp, sizeof(passwd));
        passwd[sizeof(passwd) - 1] = '\0';
      }
    endspent();
  }
#endif /* HAVE_ETC_SHADOW */
  /*
   * Check if account is locked. Check if encrypted password starts
   * with "*LK*".
   */
  {
    if (strncmp(passwd,"*LK*", 4) == 0)
      {
        SSH_DEBUG(2, ("Account %.100s is locked.", user));
        return FALSE;
      }
  }
#ifdef CHECK_ETC_SHELLS
  {
    int  invalid = 1;
    char *shell = pwd->pw_shell, *etc_shell, *getusershell();
    
    if (!shell || !*shell)
      shell = DEFAULT_SHELL;
    
    while (invalid && (etc_shell = getusershell()))
      invalid = strcmp(etc_shell, shell);
    endusershell();
    
    if (invalid)
      {
        SSH_DEBUG(2, ("Account %.100s doesn't have valid shell", user));
        return FALSE;
      }
  }
#endif /* CHECK_ETC_SHELLS */

  return TRUE;
}