2 * by Elliot Lee <sopwith@redhat.com>, Red Hat Software. July 25, 1996.
3 * log refused access error christopher mccrory <chrismcc@netus.com> 1998/7/11
5 * This code began life as the pam_rootok module.
12 #include <sys/types.h>
26 * here, we make a definition for the externally accessible function
27 * in this file (this definition is required for static a module
28 * but strongly encouraged generally) it is used to instruct the
29 * modules include file to define the function prototypes.
33 #define PAM_SM_ACCOUNT
34 #define PAM_SM_PASSWORD
35 #define PAM_SM_SESSION
37 #include <security/pam_modules.h>
38 #include <security/_pam_macros.h>
39 #include <security/pam_modutil.h>
40 #include <security/pam_ext.h>
42 /* --- authentication management functions (only) --- */
44 /* Extended Items that are not directly available via pam_get_item() */
45 #define EI_GROUP (1 << 0)
46 #define EI_SHELL (1 << 1)
48 /* Constants for apply= parameter */
49 #define APPLY_TYPE_NULL 0
50 #define APPLY_TYPE_NONE 1
51 #define APPLY_TYPE_USER 2
52 #define APPLY_TYPE_GROUP 3
54 #define LESSER(a, b) ((a) < (b) ? (a) : (b))
57 pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
58 int argc, const char **argv)
60 int retval, i, citem=0, extitem=0, onerr=PAM_SERVICE_ERR, sense=2, quiet=0;
61 const void *void_citemp;
65 char mybuf[256],myval[256];
71 /* Stuff for "extended" items */
72 struct passwd *userinfo;
74 apply_type=APPLY_TYPE_NULL;
75 memset(apply_val,0,sizeof(apply_val));
77 for(i=0; i < argc; i++) {
81 /* option quiet has no value */
82 if(!strcmp(argv[i],"quiet")) {
87 memset(mybuf,'\0',sizeof(mybuf));
88 memset(myval,'\0',sizeof(myval));
89 junk = strchr(argv[i], '=');
90 if((junk == NULL) || (junk - argv[i]) >= (int) sizeof(mybuf)) {
91 pam_syslog(pamh,LOG_ERR, "Bad option: \"%s\"",
95 strncpy(mybuf, argv[i],
96 LESSER(junk - argv[i], (int)sizeof(mybuf) - 1));
97 strncpy(myval, junk + 1, sizeof(myval) - 1);
99 if(!strcmp(mybuf,"onerr"))
100 if(!strcmp(myval,"succeed"))
102 else if(!strcmp(myval,"fail"))
103 onerr = PAM_SERVICE_ERR;
105 if (ifname) free (ifname);
106 return PAM_SERVICE_ERR;
108 else if(!strcmp(mybuf,"sense"))
109 if(!strcmp(myval,"allow"))
111 else if(!strcmp(myval,"deny"))
114 if (ifname) free (ifname);
117 else if(!strcmp(mybuf,"file")) {
118 if (ifname) free (ifname);
119 ifname = (char *)malloc(strlen(myval)+1);
122 strcpy(ifname,myval);
123 } else if(!strcmp(mybuf,"item"))
124 if(!strcmp(myval,"user"))
126 else if(!strcmp(myval,"tty"))
128 else if(!strcmp(myval,"rhost"))
130 else if(!strcmp(myval,"ruser"))
132 else { /* These items are related to the user, but are not
133 directly gettable with pam_get_item */
135 if(!strcmp(myval,"group"))
137 else if(!strcmp(myval,"shell"))
141 } else if(!strcmp(mybuf,"apply")) {
142 apply_type=APPLY_TYPE_NONE;
143 memset(apply_val,'\0',sizeof(apply_val));
145 apply_type=APPLY_TYPE_GROUP;
146 strncpy(apply_val,myval+1,sizeof(apply_val)-1);
148 apply_type=APPLY_TYPE_USER;
149 strncpy(apply_val,myval,sizeof(apply_val)-1);
153 pam_syslog(pamh,LOG_ERR, "Unknown option: %s",mybuf);
159 pam_syslog(pamh,LOG_ERR,
160 "Unknown item or item not specified");
164 pam_syslog(pamh,LOG_ERR, "List filename not specified");
166 } else if(sense == 2) {
167 pam_syslog(pamh,LOG_ERR,
168 "Unknown sense or sense not specified");
172 (apply_type==APPLY_TYPE_NONE) ||
173 ((apply_type!=APPLY_TYPE_NULL) && (*apply_val=='\0'))
175 pam_syslog(pamh,LOG_ERR,
176 "Invalid usage for apply= parameter");
181 /* Check if it makes sense to use the apply= parameter */
182 if (apply_type != APPLY_TYPE_NULL) {
183 if((citem==PAM_USER) || (citem==PAM_RUSER)) {
184 pam_syslog(pamh,LOG_WARNING,
185 "Non-sense use for apply= parameter");
186 apply_type=APPLY_TYPE_NULL;
188 if(extitem && (extitem==EI_GROUP)) {
189 pam_syslog(pamh,LOG_WARNING,
190 "Non-sense use for apply= parameter");
191 apply_type=APPLY_TYPE_NULL;
195 /* Short-circuit - test if this session apply for this user */
197 const char *user_name;
200 rval=pam_get_user(pamh,&user_name,NULL);
201 if((rval==PAM_SUCCESS) && user_name && user_name[0]) {
202 /* Got it ? Valid ? */
203 if(apply_type==APPLY_TYPE_USER) {
204 if(strcmp(user_name, apply_val)) {
205 /* Does not apply to this user */
207 pam_syslog(pamh,LOG_DEBUG,
208 "don't apply: apply=%s, user=%s",
209 apply_val,user_name);
210 #endif /* PAM_DEBUG */
214 } else if(apply_type==APPLY_TYPE_GROUP) {
215 if(!pam_modutil_user_in_group_nam_nam(pamh,user_name,apply_val)) {
216 /* Not a member of apply= group */
218 pam_syslog(pamh,LOG_DEBUG,
220 "don't apply: %s not a member of group %s",
221 user_name,apply_val);
222 #endif /* PAM_DEBUG */
230 retval = pam_get_item(pamh,citem,&void_citemp);
231 citemp = void_citemp;
232 if(retval != PAM_SUCCESS) {
236 if((citem == PAM_USER) && !citemp) {
237 retval = pam_get_user(pamh,&citemp,NULL);
238 if (retval != PAM_SUCCESS || !citemp) {
240 return PAM_SERVICE_ERR;
243 if((citem == PAM_TTY) && citemp) {
244 /* Normalize the TTY name. */
245 if(strncmp(citemp, "/dev/", 5) == 0) {
250 if(!citemp || (strlen(citemp) == 0)) {
252 /* The item was NULL - we are sure not to match */
253 return sense?PAM_SUCCESS:PAM_AUTH_ERR;
259 /* Just ignore, call pam_modutil_in_group... later */
262 /* Assume that we have already gotten PAM_USER in
263 pam_get_item() - a valid assumption since citem
264 gets set to PAM_USER in the extitem switch */
265 userinfo = pam_modutil_getpwnam(pamh, citemp);
266 if (userinfo == NULL) {
267 pam_syslog(pamh,LOG_ERR, "getpwnam(%s) failed",
272 citemp = userinfo->pw_shell;
275 pam_syslog(pamh,LOG_ERR,
277 "Internal weirdness, unknown extended item %d",
284 pam_syslog(pamh,LOG_INFO,
286 "Got file = %s, item = %d, value = %s, sense = %d",
287 ifname, citem, citemp, sense);
289 if(lstat(ifname,&fileinfo)) {
291 pam_syslog(pamh,LOG_ERR, "Couldn't open %s",ifname);
296 if((fileinfo.st_mode & S_IWOTH)
297 || !S_ISREG(fileinfo.st_mode)) {
298 /* If the file is world writable or is not a
299 normal file, return error */
300 pam_syslog(pamh,LOG_ERR,
301 "%s is either world writable or not a normal file",
307 inf = fopen(ifname,"r");
308 if(inf == NULL) { /* Check that we opened it successfully */
309 if (onerr == PAM_SERVICE_ERR) {
310 /* Only report if it's an error... */
311 pam_syslog(pamh,LOG_ERR, "Error opening %s", ifname);
316 /* There should be no more errors from here on */
318 /* This loop assumes that PAM_SUCCESS == 0
319 and PAM_AUTH_ERR != 0 */
321 assert(PAM_SUCCESS == 0);
322 assert(PAM_AUTH_ERR != 0);
324 while((fgets(aline,sizeof(aline),inf) != NULL)
328 if(strlen(aline) == 0)
330 if(aline[strlen(aline) - 1] == '\n')
331 aline[strlen(aline) - 1] = '\0';
332 if(strlen(aline) == 0)
334 if(aline[strlen(aline) - 1] == '\r')
335 aline[strlen(aline) - 1] = '\0';
336 if(citem == PAM_TTY) {
337 if(strncmp(a, "/dev/", 5) == 0)
340 if (extitem == EI_GROUP) {
341 retval = !pam_modutil_user_in_group_nam_nam(pamh,
344 retval = strcmp(a, citemp);
350 if ((sense && retval) || (!sense && !retval)) {
352 pam_syslog(pamh,LOG_INFO,
353 "Returning PAM_SUCCESS, retval = %d", retval);
359 const char *user_name;
361 pam_syslog(pamh,LOG_INFO,
362 "Returning PAM_AUTH_ERR, retval = %d", retval);
364 (void) pam_get_item(pamh, PAM_SERVICE, &service);
365 (void) pam_get_user(pamh, &user_name, NULL);
367 pam_syslog (pamh, LOG_ALERT, "Refused user %s for service %s",
368 user_name, (const char *)service);
374 pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
375 int argc UNUSED, const char **argv UNUSED)
381 pam_sm_acct_mgmt (pam_handle_t *pamh, int flags,
382 int argc, const char **argv)
384 return pam_sm_authenticate(pamh, flags, argc, argv);
388 pam_sm_open_session (pam_handle_t *pamh, int flags,
389 int argc, const char **argv)
391 return pam_sm_authenticate(pamh, flags, argc, argv);
395 pam_sm_close_session (pam_handle_t *pamh, int flags,
396 int argc, const char **argv)
398 return pam_sm_authenticate(pamh, flags, argc, argv);
402 pam_sm_chauthtok (pam_handle_t *pamh, int flags,
403 int argc, const char **argv)
405 return pam_sm_authenticate(pamh, flags, argc, argv);
410 /* static module data */
412 struct pam_module _pam_listfile_modstruct = {
418 pam_sm_close_session,
422 #endif /* PAM_STATIC */
424 /* end of module definition */