File: validate.c

package info (click to toggle)
mod-auth-shadow 1.4-1sarge1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 108 kB
  • ctags: 35
  • sloc: ansic: 390; makefile: 74; sh: 40
file content (136 lines) | stat: -rw-r--r-- 3,972 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* 
 * validate.c
 *
 * Validate a username/pw combination, using the /etc/shadow
 * file.
 *
 * Two lines are read from stdin.  The first is the user, and 
 * the second is the (unencrypted) password.
 *
 * We exit with 0 if they match, 1 otherwise.
 * Errors are written to either stderr or the error log, or both.
 */

#include <stdio.h>
#include <shadow.h>
#include <string.h>
#include <time.h>
#include "validate.h"
#ifdef LOG_FAILED_ATTEMPTS
#include <sys/syslog.h>
#include <sys/sysmacros.h>
#endif

/* USE_XOPEN makes crypt available from unistd.h. */
#define __USE_XOPEN 
#include <unistd.h>
static void stripreturn(char *str)
{
    if (strlen(str)==0)
        return;
    str[(strlen(str)-1)] = '\0';
    return;
}

int 
main(int argc, char **argv)
{
    FILE* fp;
    FILE* fptemp;
    struct spwd *ret = NULL;
    char user[MAX_USERNAME_LENGTH+2];
    char pw[MAX_PW_LENGTH+2];
    char *cryptpw;
    char *progname;
    long int secs, days;

    progname = argv[0];
    
    if (argc!=1) 
        exit(1);

    /* Read user,pw from fd */
    fp = stdin;
    fgets(user, MAX_USERNAME_LENGTH, fp);
    fgets(pw, MAX_PW_LENGTH, fp);

    /* Strip carriage return */
    stripreturn(user);
    stripreturn(pw);

    ret = getspnam(user);
#ifdef LOG_FAILED_ATTEMPTS
    openlog("mod_auth_shadow", LOG_ODELAY, LOG_AUTHPRIV);
#endif
    if (!ret) {
        /* Did the user not exist?  Or can we not read /etc/shadow?
         * Print a helpful message if the latter...
         */
        fptemp = fopen("/etc/shadow","r");
        if (!fptemp) {
            fprintf(stderr,
                "%s: No read access to /etc/shadow.  This program must be suid or sgid.\n",
                progname);
            exit(1);
        }
        fclose(fptemp);
         
        fprintf(stderr,"%s: Couldn't find user '%s'\n",progname, user);
#ifdef LOG_FAILED_ATTEMPTS
        syslog(LOG_ERR,"FAILED VALIDATE: unknown user: %s",user);
#endif
        if ( (SLEEP_SECONDS>0) && (sleep(SLEEP_SECONDS)!=0))
            fprintf(stderr,"%s: Error sleeping for %d seconds.\n", progname,SLEEP_SECONDS);
        exit(1);
        }
    cryptpw = crypt(pw,ret->sp_pwdp);
    if (strcmp(cryptpw,ret->sp_pwdp)!=0){
#ifdef LOG_FAILED_ATTEMPTS
        syslog(LOG_ERR,"VALIDATE: user: %s, Authentication failure",user);
#endif
        if ( (SLEEP_SECONDS>0) && (sleep(SLEEP_SECONDS)!=0))
            fprintf(stderr,"%s: Error sleeping for %d seconds.\n", progname,SLEEP_SECONDS);
        fprintf(stderr,"%s: User %s: authentication failure\n",progname,user);
        exit(1);
    }

    /*
     * Check password expiration information. See shadow(5)
     */
    secs = (long int) time(NULL);
    days = secs / (24L * 60L * 60L);
    /*
     *   An  account is considered to be inactive and is disabled if the
     *   password is not changed within the specified number of days after the
     *   password expires.
     */
    if (   ret->sp_max > 0
        && ret->sp_inact > 0
	&& days > ret->sp_lstchg + ret->sp_max + ret->sp_inact) {
#ifdef LOG_FAILED_ATTEMPTS
        syslog(LOG_ERR,"VALIDATE: user: %s, Account inactivity period expired",user);
#endif
        if ( (SLEEP_SECONDS>0) && (sleep(SLEEP_SECONDS)!=0))
            fprintf(stderr,"%s: Error sleeping for %d seconds.\n", progname,SLEEP_SECONDS);
        fprintf(stderr,"%s: User %s: account inactivity period expired\n",progname,user);
        exit(1);
    }

    /*
     * An account will also be disabled  on the specified day regardless of
     * other password expiration information.
     */
    if (ret->sp_expire > 0 && days > ret->sp_expire) {
#ifdef LOG_FAILED_ATTEMPTS
        syslog(LOG_ERR,"VALIDATE: user: %s, Account expired",user);
#endif
        if ( (SLEEP_SECONDS>0) && (sleep(SLEEP_SECONDS)!=0))
            fprintf(stderr,"%s: Error sleeping for %d seconds.\n", progname,SLEEP_SECONDS);
        fprintf(stderr,"%s: User %s: account expired\n",progname,user);
        exit(1);
    }
    
    exit(0);    
}