summaryrefslogtreecommitdiff
path: root/modules/pam_shells/pam_shells.c
blob: eec86dc46b97d750f487a9d7a57a48a70e7458ea (plain)
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
/*
 * pam_shells module
 *
 * by Erik Troan <ewt@redhat.com>, Red Hat Software.
 * August 5, 1996.
 * This code shamelessly ripped from the pam_securetty module.
 */

#include "config.h"

#include <pwd.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>

#include <security/pam_modules.h>
#include <security/pam_modutil.h>
#include <security/pam_ext.h>

#define SHELL_FILE "/etc/shells"

#define DEFAULT_SHELL "/bin/sh"

static int perform_check(pam_handle_t *pamh)
{
    int retval = PAM_AUTH_ERR;
    const char *userName;
    const char *userShell;
    char shellFileLine[256];
    struct stat sb;
    struct passwd * pw;
    FILE * shellFile;

    retval = pam_get_user(pamh, &userName, NULL);
    if (retval != PAM_SUCCESS) {
	return PAM_SERVICE_ERR;
    }

    if (!userName || (userName[0] == '\0')) {

	/* Don't let them use a NULL username... */
	retval = pam_get_user(pamh,&userName,NULL);
        if (retval != PAM_SUCCESS)
	    return PAM_SERVICE_ERR;

	/* It could still be NULL the second time. */
	if (!userName || (userName[0] == '\0'))
	    return PAM_SERVICE_ERR;
    }

    pw = pam_modutil_getpwnam(pamh, userName);
    if (pw == NULL || pw->pw_shell == NULL) {
	return PAM_AUTH_ERR;		/* user doesn't exist */
    }
    userShell = pw->pw_shell;
    if (userShell[0] == '\0')
	userShell = DEFAULT_SHELL;

    if (stat(SHELL_FILE,&sb)) {
	pam_syslog(pamh, LOG_ERR, "Cannot stat %s: %m", SHELL_FILE);
	return PAM_AUTH_ERR;		/* must have /etc/shells */
    }

    if ((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) {
	pam_syslog(pamh, LOG_ERR,
		   "%s is either world writable or not a normal file",
		   SHELL_FILE);
	return PAM_AUTH_ERR;
    }

    shellFile = fopen(SHELL_FILE,"r");
    if (shellFile == NULL) {       /* Check that we opened it successfully */
	pam_syslog(pamh, LOG_ERR, "Error opening %s: %m", SHELL_FILE);
	return PAM_SERVICE_ERR;
    }

    retval = 1;

    while(retval && (fgets(shellFileLine, 255, shellFile) != NULL)) {
	if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
	    shellFileLine[strlen(shellFileLine) - 1] = '\0';
	retval = strcmp(shellFileLine, userShell);
    }

    fclose(shellFile);

    if (retval) {
	return PAM_AUTH_ERR;
    } else {
	return PAM_SUCCESS;
    }
}

/* --- authentication management functions (only) --- */

int pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
		        int argc UNUSED, const char **argv UNUSED)
{
    return perform_check(pamh);
}

int pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
		   int argc UNUSED, const char **argv UNUSED)
{
     return PAM_SUCCESS;
}

/* --- account management functions (only) --- */

int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
		     int argc UNUSED, const char **argv UNUSED)
{
    return perform_check(pamh);
}

/* end of module definition */