home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / ci40_shadow_pw.zip / is_valid_unix_pw.c < prev    next >
C/C++ Source or Header  |  2000-06-07  |  3KB  |  98 lines

  1. /*
  2.  * is_valid_unix_pw  -  validate (userid password) provided via stdin. Return
  3.  * either 0 (ok, is valid) or 1 (failed) depending on whether id/passwd are
  4.  * accurate. Only do this when real-uid is that of "ciadmin", else return 1.
  5.  * The provided id/passwd are checked against the [/etc/passwd],NIS,NIS+ DB.
  6.  * If SHADOW_ONLY is #define'd, the lookup against /etc/passwd is skipped. If
  7.  * no users are expected to be locally registered in /etc/passwd, then using
  8.  * the shadow-only passwd lookups is a great optimization.
  9.  * 
  10.  * Note: the Apache FAQ, question G7, explains why this is a bad idea!  In
  11.  * essence, there are no governors to limit rapid dictionary attacks.  At
  12.  * least, I refuse to validate the root's passwd.  Further, Solaris won't
  13.  * allow dictionary words as passwords, ie, special chars or numerics are
  14.  * required.  So a brute-force attack would be required, and we'd probably
  15.  * think we had a denial-of-service attack.
  16.  * Note2: This code was greatly influenced by Qualcomm's qpopper (ftp.eudora.com)
  17.  * and should work for Solaris 2.x, AUX and LINUX.  See pop_pass.c.
  18.  * Note3: To enhance security, since this is suid-root, only the ciadmin
  19.  * user may invoke us.  To keep things fast we test against a constant UID value
  20.  * Note4: See mods to invoke us in AuthenDBI.pm (esp. Auth_DBI_unixpw_priority).
  21.  * Compile by:  gcc [-DSHADOW_ONLY] -O -o is_valid_unix_pw is_valid_unix_pw.c
  22.  * Install by:  chown root:bin is_valid_unix_pw; chmod 4555 is_valid_unix_pw
  23.  * Written by:  jpd@louisiana.edu  3/26/00
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <shadow.h>
  28. #include <string.h>
  29. #include <pwd.h>
  30. extern char    *crypt(char *, char *);
  31.  
  32. #define UID_ciadmin 197   /* set to the UID that runs Blackboard's Apache */
  33. #define refuse_ROOT    /* we refuse to authenticate root user */
  34.  
  35. char            buf[128], *s;
  36. #ifdef SHADOW_ONLY
  37. #define pw pwd
  38. #define pw_passwd sp_pwdp
  39. #else
  40. struct passwd  *pw;
  41. #endif
  42. struct spwd    *pwd;
  43. time_t          today;
  44.  
  45. main(int argc, char *argv[])
  46. {
  47.     if (argc > 1) {
  48.         fprintf(stderr, "Usage: %s; provide clid \" \" passwd via stdin\n", argv[0]);
  49.         goto FAILED;
  50.     }
  51.     if (fgets(buf, sizeof buf, stdin) == NULL || getuid() != UID_ciadmin)
  52.         goto FAILED;
  53.     if (buf[strlen(buf) - 1] == '\n')
  54.         buf[strlen(buf) - 1] = '\0';
  55.     if ((s = strchr(buf, ' ')) == NULL)
  56.         goto FAILED;
  57.     *s++ = '\0';
  58. #ifdef refuse_ROOT
  59.     if (strcmp(buf,"root") == 0) goto FAILED;  /* disallow root */
  60. #endif
  61. #ifndef SHADOW_ONLY
  62.     if ((pw = getpwnam(buf)) == NULL)
  63.         goto FAILED;
  64.     endpwent();
  65. #endif
  66.  
  67.     if ((pwd = getspnam(buf)) == NULL) {
  68. #ifndef SHADOW_ONLY
  69.         if (!strcmp(pw->pw_passwd, "x"))    /* This may be an NIS
  70.                              * entry */
  71. #endif
  72.             goto FAILED;    /* can't access shadow but need it */
  73.     } else {
  74.         today = (long) time((time_t *) NULL) / 24 / 60 / 60;
  75.  
  76.         /* Check for expiration date */
  77.         if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  78.             goto FAILED;    /* account expired */
  79.         }
  80.         /* Check if password is valid */
  81.         if (pwd->sp_max > 0 && today > pwd->sp_lstchg + pwd->sp_max) {
  82.             goto FAILED;    /* account expired, passwd too old */
  83.         }
  84. #ifndef SHADOW_ONLY
  85.         pw->pw_passwd = (char *) strdup(pwd->sp_pwdp);
  86. #endif
  87.         endspent();
  88.     }
  89.     /* We don't allow users with null passwords */
  90.     /* Compare the supplied password with the password file entry */
  91.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  92.         strcmp(crypt(s, pw->pw_passwd), pw->pw_passwd)) {
  93. FAILED:
  94.         return 1;    /* failure to authenticate */
  95.     }
  96.     return 0;
  97. }
  98.