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