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 >
Wrap
C/C++ Source or Header
|
2000-06-07
|
3KB
|
98 lines
/*
* is_valid_unix_pw - validate (userid password) provided via stdin. Return
* either 0 (ok, is valid) or 1 (failed) depending on whether id/passwd are
* accurate. Only do this when real-uid is that of "ciadmin", else return 1.
* The provided id/passwd are checked against the [/etc/passwd],NIS,NIS+ DB.
* If SHADOW_ONLY is #define'd, the lookup against /etc/passwd is skipped. If
* no users are expected to be locally registered in /etc/passwd, then using
* the shadow-only passwd lookups is a great optimization.
*
* Note: the Apache FAQ, question G7, explains why this is a bad idea! In
* essence, there are no governors to limit rapid dictionary attacks. At
* least, I refuse to validate the root's passwd. Further, Solaris won't
* allow dictionary words as passwords, ie, special chars or numerics are
* required. So a brute-force attack would be required, and we'd probably
* think we had a denial-of-service attack.
* Note2: This code was greatly influenced by Qualcomm's qpopper (ftp.eudora.com)
* and should work for Solaris 2.x, AUX and LINUX. See pop_pass.c.
* Note3: To enhance security, since this is suid-root, only the ciadmin
* user may invoke us. To keep things fast we test against a constant UID value
* Note4: See mods to invoke us in AuthenDBI.pm (esp. Auth_DBI_unixpw_priority).
* Compile by: gcc [-DSHADOW_ONLY] -O -o is_valid_unix_pw is_valid_unix_pw.c
* Install by: chown root:bin is_valid_unix_pw; chmod 4555 is_valid_unix_pw
* Written by: jpd@louisiana.edu 3/26/00
*/
#include <stdio.h>
#include <shadow.h>
#include <string.h>
#include <pwd.h>
extern char *crypt(char *, char *);
#define UID_ciadmin 197 /* set to the UID that runs Blackboard's Apache */
#define refuse_ROOT /* we refuse to authenticate root user */
char buf[128], *s;
#ifdef SHADOW_ONLY
#define pw pwd
#define pw_passwd sp_pwdp
#else
struct passwd *pw;
#endif
struct spwd *pwd;
time_t today;
main(int argc, char *argv[])
{
if (argc > 1) {
fprintf(stderr, "Usage: %s; provide clid \" \" passwd via stdin\n", argv[0]);
goto FAILED;
}
if (fgets(buf, sizeof buf, stdin) == NULL || getuid() != UID_ciadmin)
goto FAILED;
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
if ((s = strchr(buf, ' ')) == NULL)
goto FAILED;
*s++ = '\0';
#ifdef refuse_ROOT
if (strcmp(buf,"root") == 0) goto FAILED; /* disallow root */
#endif
#ifndef SHADOW_ONLY
if ((pw = getpwnam(buf)) == NULL)
goto FAILED;
endpwent();
#endif
if ((pwd = getspnam(buf)) == NULL) {
#ifndef SHADOW_ONLY
if (!strcmp(pw->pw_passwd, "x")) /* This may be an NIS
* entry */
#endif
goto FAILED; /* can't access shadow but need it */
} else {
today = (long) time((time_t *) NULL) / 24 / 60 / 60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
goto FAILED; /* account expired */
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg + pwd->sp_max) {
goto FAILED; /* account expired, passwd too old */
}
#ifndef SHADOW_ONLY
pw->pw_passwd = (char *) strdup(pwd->sp_pwdp);
#endif
endspent();
}
/* We don't allow users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(s, pw->pw_passwd), pw->pw_passwd)) {
FAILED:
return 1; /* failure to authenticate */
}
return 0;
}