]> granicus.if.org Git - linux-pam/blob - modules/pam_securetty/pam_securetty.c
Relevant BUGIDs:
[linux-pam] / 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  */
12
13 #define _GNU_SOURCE
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <syslog.h>
21 #include <stdarg.h>
22 #include <pwd.h>
23 #include <string.h>
24 #include <ctype.h>
25
26 /*
27  * here, we make a definition for the externally accessible function
28  * in this file (this definition is required for static a module
29  * but strongly encouraged generally) it is used to instruct the
30  * modules include file to define the function prototypes.
31  */
32
33 #define PAM_SM_AUTH
34 #define PAM_SM_ACCOUNT
35
36 #include <security/pam_modules.h>
37 #include <security/_pam_modutil.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 static int securetty_perform_check(pam_handle_t *pamh, int flags, int ctrl,
76                                    const char *function_name)
77 {
78     int retval = PAM_AUTH_ERR;
79     const char *username;
80     char *uttyname;
81     char ttyfileline[256];
82     char ptname[256];
83     struct stat ttyfileinfo;
84     struct passwd *user_pwd;
85     FILE *ttyfile;
86
87     /* log a trail for debugging */
88     if (ctrl & PAM_DEBUG_ARG) {
89         _pam_log(LOG_DEBUG, "pam_securetty called via %s function",
90                  function_name);
91     }
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 ? PAM_INCOMPLETE:PAM_SERVICE_ERR);
99     }
100
101     user_pwd = _pammodutil_getpwnam(pamh, username);
102     if (user_pwd == NULL) {
103         return PAM_IGNORE;
104     } else if (user_pwd->pw_uid != 0) { /* If the user is not root,
105                                            securetty's does not apply
106                                            to them */
107         return PAM_SUCCESS;
108     }
109
110     retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname);
111     if (retval != PAM_SUCCESS || uttyname == NULL) {
112         if (ctrl & PAM_DEBUG_ARG) {
113             _pam_log(LOG_WARNING, "cannot determine user's tty");
114         }
115         return PAM_SERVICE_ERR;
116     }
117
118     /* The PAM_TTY item may be prefixed with "/dev/" - skip that */
119     if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0) {
120         uttyname += sizeof(TTY_PREFIX)-1;
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) || !S_ISREG(ttyfileinfo.st_mode)) {
131         /* If the file is world writable or is not a
132            normal file, return error */
133         _pam_log(LOG_ERR, SECURETTY_FILE
134                  " is either world writable or not a normal file");
135         return PAM_AUTH_ERR;
136     }
137
138     ttyfile = fopen(SECURETTY_FILE,"r");
139     if (ttyfile == NULL) { /* Check that we opened it successfully */
140         _pam_log(LOG_ERR,
141                  "Error opening " SECURETTY_FILE);
142         return PAM_SERVICE_ERR;
143     }
144
145     if (isdigit(uttyname[0])) {
146         snprintf(ptname, sizeof(ptname), "pts/%s", uttyname);
147     } else {
148         ptname[0] = '\0';
149     }
150
151     retval = 1;
152
153     while ((fgets(ttyfileline, sizeof(ttyfileline)-1, ttyfile) != NULL)
154            && retval) {
155         if (ttyfileline[strlen(ttyfileline) - 1] == '\n')
156             ttyfileline[strlen(ttyfileline) - 1] = '\0';
157
158         retval = ( strcmp(ttyfileline, uttyname)
159                    && (!ptname[0] || strcmp(ptname, uttyname)) );
160     }
161     fclose(ttyfile);
162
163     if (retval) {
164         if (ctrl & PAM_DEBUG_ARG) {
165             _pam_log(LOG_WARNING, "access denied: tty '%s' is not secure !",
166                      uttyname);
167         }
168         retval = PAM_AUTH_ERR;
169
170     } else {
171         if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG)) {
172             _pam_log(LOG_DEBUG, "access allowed for '%s' on '%s'",
173                      username, uttyname);
174         }
175         retval = PAM_SUCCESS;
176
177     }
178
179     return retval;
180 }
181
182 /* --- authentication management functions --- */
183
184 PAM_EXTERN
185 int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
186                         const char **argv)
187 {
188     int ctrl;
189
190     /* parse the arguments */
191     ctrl = _pam_parse(argc, argv);
192
193     return securetty_perform_check(pamh, flags, ctrl, __FUNCTION__);
194 }
195
196 PAM_EXTERN
197 int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
198 {
199     return PAM_SUCCESS;
200 }
201
202 /* --- account management functions --- */
203
204 PAM_EXTERN
205 int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
206                      const char **argv)
207 {
208     int ctrl;
209
210     /* parse the arguments */
211     ctrl = _pam_parse(argc, argv);
212
213     /* take the easy route */
214     return securetty_perform_check(pamh, flags, ctrl, __FUNCTION__);
215 }
216
217
218 #ifdef PAM_STATIC
219
220 /* static module data */
221
222 struct pam_module _pam_securetty_modstruct = {
223      "pam_securetty",
224      pam_sm_authenticate,
225      pam_sm_setcred,
226      pam_sm_acct_mgmt,
227      NULL,
228      NULL,
229      NULL,
230 };
231
232 #endif /* PAM_STATIC */
233
234 /* end of module definition */