/********************************************************************* auth.c # gcc auth.c -o auth -lcrypt # chmod 4755 auth reads two lines containing login and password returns 0 on success, or sleeps 3 seconds and returns 1 *********************************************************************/ #define _XOPEN_SOURCE /* define before 1st #include */ #include #include #include #include /* crypt() */ #define SKIP 20 /* skip this many lines at the beginning of the shadow file */ char user[129], pass[513], line[1024]; int auth(char *user, char *pass) { FILE *f; int len; int val = 1; int count = 0; if ((f = fopen("/etc/shadow", "r")) == NULL) return 1; strcat(user, ":"); len = strlen(user); while (fgets(line, sizeof line, f)) { if (++count > SKIP && strncmp(line, user, len) == 0) { int cmplen = 13; if (strncmp(&line[len], "$1$", 3) == 0) cmplen = 34; if (strncmp(crypt(pass, &line[len]), &line[len], cmplen) == 0) val = 0; break; } } fclose(f); return val; /* 0=good, 1=bad */ } void mygets(char *s, int size) { int i; fgets(s, size, stdin); for (i = 0; i < size; i++) { if (s[i] == '\n' || s[i] == '\r') { s[i] = '\0'; break; } } } int main() { #ifdef SOLARIS /* On Solaris 7, it seems necessary to explicitly setuid(0) */ setuid(0); #endif mygets(user, sizeof(user) - 1); /* keep room to append ":" */ mygets(pass, sizeof(pass)); if (auth(user, pass) != 0) { sleep(3); return 1; /* bad */ } return 0; /* good */ }