home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3345 / age.c next >
Encoding:
C/C++ Source or Header  |  1991-05-17  |  6.0 KB  |  281 lines

  1. /*
  2.  * Copyright 1989, 1990, 1991, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #include <sys/types.h>
  13. #include <stdio.h>
  14. #include <errno.h>
  15. #include "config.h"
  16. #include "pwd.h"
  17. #include "shadow.h"
  18.  
  19. #ifndef    lint
  20. static    char    sccsid[] = "@(#)age.c    3.3    07:52:49    1/30/91";
  21. #endif
  22.  
  23. #define    DAY    (24L*3600L)
  24. #ifdef    ITI_AGING
  25. #define    SCALE    (DAY)
  26. #else
  27. #define    SCALE    (1)
  28. #endif
  29.  
  30. #ifndef    WARNAGE
  31. #define    WARNAGE    10
  32. #endif
  33.  
  34. extern    time_t    time ();
  35. extern    char    *strdup();
  36.  
  37. /*
  38.  * pwd_to_spwd - create entries for new spwd structure
  39.  *
  40.  *    pwd_to_spwd() creates a new (struct spwd) containing the
  41.  *    information in the pointed-to (struct passwd).
  42.  */
  43.  
  44. static struct spwd *
  45. pwd_to_spwd (pw)
  46. struct    passwd    *pw;
  47. {
  48.     static    struct    spwd    tspwd;
  49.     struct    spwd    *sp = &tspwd;
  50.     time_t    t;
  51.  
  52.     /*
  53.      * Nice, easy parts first.  The name and passwd map directly
  54.      * from the old password structure to the new one.
  55.      */
  56.  
  57.     sp->sp_namp = strdup (pw->pw_name);
  58.     sp->sp_pwdp = strdup (pw->pw_passwd);
  59. #ifdef    ATT_AGE
  60.  
  61.     /*
  62.      * AT&T-style password aging maps the sp_min, sp_max, and
  63.      * sp_lstchg information from the pw_age field, which appears
  64.      * after the encrypted password.
  65.      */
  66.  
  67.     if (pw->pw_age[0]) {
  68.         t = (c64i (pw->pw_age[0]) * 7) * SCALE;
  69.         sp->sp_max = t;
  70.  
  71.         if (pw->pw_age[1]) {
  72.             t = (c64i (pw->pw_age[1]) * 7) * SCALE;
  73.             sp->sp_min = t;
  74.         } else
  75.             sp->sp_min = (10000L) * SCALE;
  76.  
  77.         if (pw->pw_age[1] && pw->pw_age[2]) {
  78.             t = (a64l (pw->pw_age + 2) * 7) * SCALE;
  79.             sp->sp_lstchg = t;
  80.         } else
  81.             sp->sp_lstchg = time ((time_t *) 0) / (DAY/SCALE);
  82.     } else {
  83.         sp->sp_min = 0;
  84.         sp->sp_max = (10000L * SCALE);
  85.         sp->sp_lstchg = time ((time_t *) 0) / (DAY/SCALE);
  86.     }
  87. #else    /* !ATT_AGE */
  88.     /*
  89.      * BSD does not use the pw_age field and has no aging information
  90.      * anywheres.  The default values are used to initialize the
  91.      * fields which are in the missing pw_age field;
  92.      */
  93.  
  94.     sp->sp_min = 0;
  95.     sp->sp_max = (10000L * SCALE);
  96.     sp->sp_lstchg = time ((time_t *) 0) / (DAY/SCALE);
  97. #endif    /* ATT_AGE */
  98.  
  99.     /*
  100.      * These fields have no corresponding information in the password
  101.      * file.  They are set to uninitialized values.
  102.      */
  103.  
  104.     sp->sp_warn = -1;
  105.     sp->sp_inact = -1;
  106.     sp->sp_expire = -1;
  107.     sp->sp_flag = -1;
  108. }
  109.  
  110. /*
  111.  * isexpired - determine if account is expired yet
  112.  *
  113.  *    isexpired calculates the expiration date based on the
  114.  *    password expiration criteria.
  115.  */
  116.  
  117. int
  118. isexpired (pw, sp)
  119. struct    passwd    *pw;
  120. struct    spwd    *sp;
  121. {
  122.     long    clock;
  123.  
  124.     clock = time ((time_t *) 0) / (DAY/SCALE);
  125.  
  126.     /*
  127.      * Quick and easy - there is an expired account field
  128.      * along with an inactive account field.  Do the expired
  129.      * one first since it is worse.
  130.      */
  131.  
  132.     if (sp->sp_expire > 0 && sp->sp_expire < clock)
  133.         return 3;
  134.  
  135.     if (sp->sp_inact > 0 && sp->sp_lstchg > 0 && sp->sp_max > 0 &&
  136.             sp->sp_inact + sp->sp_lstchg + sp->sp_max < clock)
  137.         return 2;
  138.  
  139.     /*
  140.      * The last and max fields must be present for an account
  141.      * to have an expired password.  A maximum of >10000 days
  142.      * is considered to be infinite.
  143.      */
  144.  
  145.     if (sp->sp_lstchg == -1 ||
  146.             sp->sp_max == -1 || sp->sp_max >= (10000L*SCALE))
  147.         return 0;
  148.  
  149.     /*
  150.      * Calculate today's day and the day on which the password
  151.      * is going to expire.  If that date has already passed,
  152.      * the password has expired.
  153.      */
  154.  
  155.     if (sp->sp_lstchg + sp->sp_max < clock)
  156.         return 1;
  157.  
  158.     return 0;
  159. }
  160.  
  161. /*
  162.  * expire - force password change if password expired
  163.  *
  164.  *    expire() calls /bin/passwd to change the user's password
  165.  *    if it has expired.
  166.  */
  167.  
  168. int
  169. expire (pw, sp)
  170. struct    passwd    *pw;
  171. struct    spwd    *sp;
  172. {
  173.     int    status;
  174.     int    child;
  175.     int    pid;
  176.  
  177.     if (! sp)
  178.         sp = pwd_to_spwd (pw);
  179.  
  180.     /*
  181.      * See if the user's password has expired, and if so
  182.      * force them to change their password.
  183.      */
  184.  
  185.     switch (status = isexpired (pw, sp)) {
  186.         case 0:
  187.             return 0;
  188.         case 1:
  189.             printf ("Your password has expired.");
  190.             break;
  191.         case 2:
  192.             printf ("Your password is inactive.");
  193.             break;
  194.         case 3:
  195.             printf ("Your login has expired.");
  196.             break;
  197.     }
  198.  
  199.     /*
  200.      * Setting the maximum valid period to less than the minimum
  201.      * valid period means that the minimum period will never
  202.      * occur while the password is valid, so the user can never
  203.      * change that password.
  204.      */
  205.  
  206.     if (status > 1 || sp->sp_max < sp->sp_min) {
  207.         puts ("  Contact the system administrator.\n");
  208.         exit (1);
  209.     }
  210.     puts ("  Choose a new one.\n");
  211.     fflush (stdout);
  212.  
  213.     /*
  214.      * Close all the files so that unauthorized access won't
  215.      * occur.  This needs to be done anyway because those files
  216.      * might become stale after "passwd" is executed.
  217.      */
  218.  
  219.     endspent ();
  220.     endpwent ();
  221.     endsgent ();
  222.     endgrent ();
  223.  
  224.     /*
  225.      * Execute the /bin/passwd command.  The exit status will be
  226.      * examined to see what the result is.  If there are any
  227.      * errors the routine will exit.  This forces the user to
  228.      * change their password before being able to use the account.
  229.      */
  230.  
  231.     if ((pid = fork ()) == 0) {
  232.         execl ("/bin/passwd", "passwd", pw->pw_name, (char *) 0);
  233.         puts ("Can't execute /bin/passwd");
  234.         exit (errno);
  235.     } else if (pid == -1) {
  236.         perror ("passwd");
  237.         exit (errno);
  238.     }
  239.     while ((child = wait (&status)) != pid && child != -1)
  240.         ;
  241.  
  242.     if (child == pid && status == 0)
  243.         return 1;
  244.  
  245.     exit (1);
  246. }
  247.  
  248. /*
  249.  * agecheck - see if warning is needed for password expiration
  250.  *
  251.  *    agecheck sees how many days until the user's password is going
  252.  *    to expire and warns the user of the pending password expiration.
  253.  */
  254.  
  255. void
  256. agecheck (pw, sp)
  257. struct    passwd    *pw;
  258. struct    spwd    *sp;
  259. {
  260.     long    clock = time ((long *) 0) / (DAY/SCALE);
  261.     long    remain;
  262.  
  263.     if (! sp)
  264.         sp = pwd_to_spwd (pw);
  265.  
  266.     /*
  267.      * The last, max, and warn fields must be supported or the
  268.      * warning period cannot be calculated.
  269.      */
  270.  
  271.     if (sp->sp_lstchg == -1 || sp->sp_max == -1 || sp->sp_warn == -1)
  272.         return;
  273.  
  274.     if ((remain = (sp->sp_lstchg + sp->sp_max) - clock) <= sp->sp_warn) {
  275.         remain /= SCALE;
  276.         if (remain >= 0)
  277.             printf ("Your password will expire in %d %s.\n",
  278.                 remain, remain == 1 ? "day":"days");
  279.     }
  280. }
  281.