]> granicus.if.org Git - linux-pam/blob - modules/pam_securetty/pam_securetty.c
Initial revision
[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
25 #define PAM_SM_AUTH
26
27 /*
28  * here, we make a definition for the externally accessible function
29  * in this file (this definition is required for static a module
30  * but strongly encouraged generally) it is used to instruct the
31  * modules include file to define the function prototypes.
32  */
33
34 #define PAM_SM_AUTH
35
36 #include <security/pam_modules.h>
37
38 /* some syslogging */
39
40 static void _pam_log(int err, const char *format, ...)
41 {
42     va_list args;
43
44     va_start(args, format);
45     openlog("PAM-securetty", LOG_CONS|LOG_PID, LOG_AUTH);
46     vsyslog(err, format, args);
47     va_end(args);
48     closelog();
49 }
50
51 /* argument parsing */
52
53 #define PAM_DEBUG_ARG       0x0001
54
55 static int _pam_parse(int argc, const char **argv)
56 {
57     int ctrl=0;
58
59     /* step through arguments */
60     for (ctrl=0; argc-- > 0; ++argv) {
61
62         /* generic options */
63
64         if (!strcmp(*argv,"debug"))
65             ctrl |= PAM_DEBUG_ARG;
66         else {
67             _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
68         }
69     }
70
71     return ctrl;
72 }
73
74 /* --- authentication management functions (only) --- */
75
76 PAM_EXTERN
77 int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
78                         ,const char **argv)
79 {
80     int retval = PAM_AUTH_ERR;
81     const char *username;
82     char *uttyname;
83     char ttyfileline[256];
84     struct stat ttyfileinfo;
85     struct passwd *user_pwd;
86     FILE *ttyfile;
87     int ctrl;
88
89     /* parse the arguments */
90     ctrl = _pam_parse(argc, argv);
91
92     retval = pam_get_user(pamh, &username, NULL);
93     if (retval != PAM_SUCCESS || username == NULL) {
94         if (ctrl & PAM_DEBUG_ARG) {
95             _pam_log(LOG_WARNING, "cannot determine username");
96         }
97         return (retval == PAM_CONV_AGAIN
98                 ? PAM_INCOMPLETE:PAM_SERVICE_ERR);
99     }
100
101     retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname);
102     if (retval != PAM_SUCCESS || uttyname == NULL) {
103         if (ctrl & PAM_DEBUG_ARG) {
104             _pam_log(LOG_WARNING, "cannot determine user's tty");
105         }
106         return PAM_SERVICE_ERR;
107     }
108
109     /* The PAM_TTY item may be prefixed with "/dev/" - skip that */
110     if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0)
111         uttyname += sizeof(TTY_PREFIX)-1;
112
113     user_pwd = getpwnam(username);
114     if (user_pwd == NULL) {
115         return PAM_IGNORE;
116     } else if (user_pwd->pw_uid != 0) { /* If the user is not root,
117                                            securetty's does not apply
118                                            to them */
119         return PAM_SUCCESS;
120     }
121
122     if (stat(SECURETTY_FILE, &ttyfileinfo)) {
123         _pam_log(LOG_NOTICE, "Couldn't open " SECURETTY_FILE);
124         return PAM_SUCCESS; /* for compatibility with old securetty handling,
125                                this needs to succeed.  But we still log the
126                                error. */
127     }
128
129     if ((ttyfileinfo.st_mode & S_IWOTH)
130         || !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     /* There should be no more errors from here on */
145     retval=PAM_AUTH_ERR;
146     /* This loop assumes that PAM_SUCCESS == 0
147        and PAM_AUTH_ERR != 0 */
148     while((fgets(ttyfileline,sizeof(ttyfileline)-1, ttyfile) != NULL) 
149           && retval) {
150         if(ttyfileline[strlen(ttyfileline) - 1] == '\n')
151             ttyfileline[strlen(ttyfileline) - 1] = '\0';
152         retval = strcmp(ttyfileline,uttyname);
153     }
154     fclose(ttyfile);
155     if(retval) {
156         if (ctrl & PAM_DEBUG_ARG)
157             _pam_log(LOG_WARNING, "access denied: tty '%s' is not secure !",
158                      uttyname);
159         retval = PAM_AUTH_ERR;
160     }
161     if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG))
162         _pam_log(LOG_DEBUG, "access allowed for '%s' on '%s'",
163                  username, uttyname);
164     return retval;
165 }
166
167 PAM_EXTERN
168 int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
169                    ,const char **argv)
170 {
171      return PAM_SUCCESS;
172 }
173
174
175 #ifdef PAM_STATIC
176
177 /* static module data */
178
179 struct pam_module _pam_securetty_modstruct = {
180      "pam_securetty",
181      pam_sm_authenticate,
182      pam_sm_setcred,
183      NULL,
184      NULL,
185      NULL,
186      NULL,
187 };
188
189 #endif
190
191 /* end of module definition */