Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / libpam / modules / pam_shells / pam_shells.c
1 /* pam_shells module */
2
3 #define SHELL_FILE "/etc/shells"
4
5 /*
6  * by Erik Troan <ewt@redhat.com>, Red Hat Software.
7  * August 5, 1996.
8  * This code shamelessly ripped from the pam_securetty module.
9  * $FreeBSD: src/contrib/libpam/modules/pam_shells/pam_shells.c,v 1.3.2.2 2001/06/11 15:28:28 markm Exp $
10  */
11
12 #define _BSD_SOURCE
13
14 #include <pwd.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <sys/stat.h>
19 #include <syslog.h>
20 #include <unistd.h>
21
22 /*
23  * here, we make a definition for the externally accessible function
24  * in this file (this definition is required for static a module
25  * but strongly encouraged generally) it is used to instruct the
26  * modules include file to define the function prototypes.
27  */
28
29 #define PAM_SM_AUTH
30
31 #include <security/pam_modules.h>
32
33 /* some syslogging */
34
35 static void _pam_log(int err, const char *format, ...)
36 {
37     va_list args;
38
39     va_start(args, format);
40     openlog("PAM-shells", LOG_CONS|LOG_PID, LOG_AUTH);
41     vsyslog(err, format, args);
42     va_end(args);
43     closelog();
44 }
45
46 /* --- authentication management functions (only) --- */
47
48 PAM_EXTERN
49 int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
50                         ,const char **argv)
51 {
52      int retval = PAM_AUTH_ERR;
53      const char *userName;
54      char *userShell;
55      char shellFileLine[256];
56      struct stat sb;
57      struct passwd * pw;
58      FILE * shellFile;
59
60      retval = pam_get_user(pamh,&userName,NULL);
61      if(retval != PAM_SUCCESS) 
62        return PAM_SERVICE_ERR;
63
64      if(!userName || (strlen(userName) <= 0)) {
65        /* Don't let them use a NULL username... */
66        pam_get_user(pamh,&userName,NULL);
67         if (retval != PAM_SUCCESS)
68           return PAM_SERVICE_ERR;
69      }
70
71      pw = getpwnam(userName);
72      if (!pw)
73         return PAM_AUTH_ERR;            /* user doesn't exist */
74      userShell = pw->pw_shell;
75
76      if(stat(SHELL_FILE,&sb)) {
77         _pam_log(LOG_ERR,
78                 "%s cannot be stat'd (it probably does not exist)", SHELL_FILE);
79         return PAM_AUTH_ERR;            /* must have /etc/shells */
80      }
81
82      if((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) {
83         _pam_log(LOG_ERR,
84                 "%s is either world writable or not a normal file", SHELL_FILE);
85         return PAM_AUTH_ERR;
86      }
87
88      shellFile = fopen(SHELL_FILE,"r");
89      if(shellFile == NULL) { /* Check that we opened it successfully */
90         _pam_log(LOG_ERR,
91                 "Error opening %s", SHELL_FILE);
92        return PAM_SERVICE_ERR;
93      }
94      /* There should be no more errors from here on */
95      retval=PAM_AUTH_ERR;
96      /* This loop assumes that PAM_SUCCESS == 0
97         and PAM_AUTH_ERR != 0 */
98      while((fgets(shellFileLine,255,shellFile) != NULL) 
99            && retval) {
100        if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
101            shellFileLine[strlen(shellFileLine) - 1] = '\0';
102        retval = strcmp(shellFileLine, userShell);
103      }
104      fclose(shellFile);
105      if(retval)
106        retval = PAM_AUTH_ERR;
107      return retval;
108 }
109
110 PAM_EXTERN
111 int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
112                    ,const char **argv)
113 {
114      return PAM_SUCCESS;
115 }
116
117
118 #ifdef PAM_STATIC
119
120 /* static module data */
121
122 struct pam_module _pam_shells_modstruct = {
123      "pam_shells",
124      pam_sm_authenticate,
125      pam_sm_setcred,
126      NULL,
127      NULL,
128      NULL,
129      NULL,
130 };
131
132 #endif
133
134 /* end of module definition */