Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / libpam / modules / pam_securetty / pam_securetty.c
1 /* pam_securetty module */
2
3 #define SECURETTY_FILE "/etc/securetty"
4 #define TTY_PREFIX     "/dev/"
5
6 /*
7  * by Elliot Lee <sopwith@redhat.com>, Red Hat Software.
8  * July 25, 1996.
9  * This code shamelessly ripped from the pam_rootok module.
10  * Slight modifications AGM. 1996/12/3
11  * $FreeBSD: src/contrib/libpam/modules/pam_securetty/pam_securetty.c,v 1.3.2.2 2001/06/11 15:28:27 markm Exp $
12  */
13
14 #define _GNU_SOURCE
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <syslog.h>
22 #include <stdarg.h>
23 #include <pwd.h>
24 #include <string.h>
25
26 #define PAM_SM_AUTH
27
28 /*
29  * here, we make a definition for the externally accessible function
30  * in this file (this definition is required for static a module
31  * but strongly encouraged generally) it is used to instruct the
32  * modules include file to define the function prototypes.
33  */
34
35 #define PAM_SM_AUTH
36
37 #include <security/pam_modules.h>
38
39 /* some syslogging */
40
41 static void _pam_log(int err, const char *format, ...)
42 {
43     va_list args;
44
45     va_start(args, format);
46     openlog("PAM-securetty", LOG_CONS|LOG_PID, LOG_AUTH);
47     vsyslog(err, format, args);
48     va_end(args);
49     closelog();
50 }
51
52 /* argument parsing */
53
54 #define PAM_DEBUG_ARG       0x0001
55
56 static int _pam_parse(int argc, const char **argv)
57 {
58     int ctrl=0;
59
60     /* step through arguments */
61     for (ctrl=0; argc-- > 0; ++argv) {
62
63         /* generic options */
64
65         if (!strcmp(*argv,"debug"))
66             ctrl |= PAM_DEBUG_ARG;
67         else {
68             _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
69         }
70     }
71
72     return ctrl;
73 }
74
75 /* --- authentication management functions (only) --- */
76
77 PAM_EXTERN
78 int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
79                         ,const char **argv)
80 {
81     int retval = PAM_AUTH_ERR;
82     const char *username;
83     char *uttyname;
84     char ttyfileline[256];
85     struct stat ttyfileinfo;
86     struct passwd *user_pwd;
87     FILE *ttyfile;
88     int ctrl;
89
90     /* parse the arguments */
91     ctrl = _pam_parse(argc, argv);
92
93     retval = pam_get_user(pamh, &username, NULL);
94     if (retval != PAM_SUCCESS || username == NULL) {
95         if (ctrl & PAM_DEBUG_ARG) {
96             _pam_log(LOG_WARNING, "cannot determine username");
97         }
98         return (retval == PAM_CONV_AGAIN
99                 ? PAM_INCOMPLETE:PAM_SERVICE_ERR);
100     }
101
102     retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname);
103     if (retval != PAM_SUCCESS || uttyname == NULL) {
104         if (ctrl & PAM_DEBUG_ARG) {
105             _pam_log(LOG_WARNING, "cannot determine user's tty");
106         }
107         return PAM_SERVICE_ERR;
108     }
109
110     /* The PAM_TTY item may be prefixed with "/dev/" - skip that */
111     if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0)
112         uttyname += sizeof(TTY_PREFIX)-1;
113
114     user_pwd = getpwnam(username);
115     if (user_pwd == NULL) {
116         return PAM_IGNORE;
117     } else if (user_pwd->pw_uid != 0) { /* If the user is not root,
118                                            securetty's does not apply
119                                            to them */
120         return PAM_SUCCESS;
121     }
122
123     if (stat(SECURETTY_FILE, &ttyfileinfo)) {
124         _pam_log(LOG_NOTICE, "Couldn't open " SECURETTY_FILE);
125         return PAM_SUCCESS; /* for compatibility with old securetty handling,
126                                this needs to succeed.  But we still log the
127                                error. */
128     }
129
130     if ((ttyfileinfo.st_mode & S_IWOTH)
131         || !S_ISREG(ttyfileinfo.st_mode)) {
132         /* If the file is world writable or is not a
133            normal file, return error */
134         _pam_log(LOG_ERR, SECURETTY_FILE
135                  " is either world writable or not a normal file");
136         return PAM_AUTH_ERR;
137     }
138
139     ttyfile = fopen(SECURETTY_FILE,"r");
140     if(ttyfile == NULL) { /* Check that we opened it successfully */
141         _pam_log(LOG_ERR,
142                  "Error opening " SECURETTY_FILE);
143         return PAM_SERVICE_ERR;
144     }
145     /* There should be no more errors from here on */
146     retval=PAM_AUTH_ERR;
147     /* This loop assumes that PAM_SUCCESS == 0
148        and PAM_AUTH_ERR != 0 */
149     while((fgets(ttyfileline,sizeof(ttyfileline)-1, ttyfile) != NULL) 
150           && retval) {
151         if(ttyfileline[strlen(ttyfileline) - 1] == '\n')
152             ttyfileline[strlen(ttyfileline) - 1] = '\0';
153         retval = strcmp(ttyfileline,uttyname);
154     }
155     fclose(ttyfile);
156     if(retval) {
157         if (ctrl & PAM_DEBUG_ARG)
158             _pam_log(LOG_WARNING, "access denied: tty '%s' is not secure !",
159                      uttyname);
160         retval = PAM_AUTH_ERR;
161     }
162     if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG))
163         _pam_log(LOG_DEBUG, "access allowed for '%s' on '%s'",
164                  username, uttyname);
165     return retval;
166 }
167
168 PAM_EXTERN
169 int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
170                    ,const char **argv)
171 {
172      return PAM_SUCCESS;
173 }
174
175
176 #ifdef PAM_STATIC
177
178 /* static module data */
179
180 struct pam_module _pam_securetty_modstruct = {
181      "pam_securetty",
182      pam_sm_authenticate,
183      pam_sm_setcred,
184      NULL,
185      NULL,
186      NULL,
187      NULL,
188 };
189
190 #endif
191
192 /* end of module definition */