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 /* checks if a user is on a list of members */
43 static int is_on_list(char * const *list, const char *member)
46 if (strcmp(*list, member) == 0)
53 /* --- authentication management functions (only) --- */
55 /* Extended Items that are not directly available via pam_get_item() */
56 #define EI_GROUP (1 << 0)
57 #define EI_SHELL (1 << 1)
59 /* Constants for apply= parameter */
60 #define APPLY_TYPE_NULL 0
61 #define APPLY_TYPE_NONE 1
62 #define APPLY_TYPE_USER 2
63 #define APPLY_TYPE_GROUP 3
65 #define LESSER(a, b) ((a) < (b) ? (a) : (b))
68 pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
69 int argc, const char **argv)
71 int retval, i, citem=0, extitem=0, onerr=PAM_SERVICE_ERR, sense=2;
72 const void *void_citemp;
76 char mybuf[256],myval[256];
82 /* Stuff for "extended" items */
83 struct passwd *userinfo;
84 struct group *grpinfo;
85 char *itemlist[256]; /* Maximum of 256 items */
87 apply_type=APPLY_TYPE_NULL;
88 memset(apply_val,0,sizeof(apply_val));
90 for(i=0; i < argc; i++) {
94 memset(mybuf,'\0',sizeof(mybuf));
95 memset(myval,'\0',sizeof(mybuf));
96 junk = strchr(argv[i], '=');
97 if((junk == NULL) || (junk - argv[i]) >= (int) sizeof(mybuf)) {
98 pam_syslog(pamh,LOG_ERR, "Bad option: \"%s\"",
102 strncpy(mybuf, argv[i],
103 LESSER(junk - argv[i], (int)sizeof(mybuf) - 1));
104 strncpy(myval, junk + 1, sizeof(myval) - 1);
106 if(!strcmp(mybuf,"onerr"))
107 if(!strcmp(myval,"succeed"))
109 else if(!strcmp(myval,"fail"))
110 onerr = PAM_SERVICE_ERR;
112 if (ifname) free (ifname);
113 return PAM_SERVICE_ERR;
115 else if(!strcmp(mybuf,"sense"))
116 if(!strcmp(myval,"allow"))
118 else if(!strcmp(myval,"deny"))
121 if (ifname) free (ifname);
124 else if(!strcmp(mybuf,"file")) {
125 if (ifname) free (ifname);
126 ifname = (char *)malloc(strlen(myval)+1);
129 strcpy(ifname,myval);
130 } else if(!strcmp(mybuf,"item"))
131 if(!strcmp(myval,"user"))
133 else if(!strcmp(myval,"tty"))
135 else if(!strcmp(myval,"rhost"))
137 else if(!strcmp(myval,"ruser"))
139 else { /* These items are related to the user, but are not
140 directly gettable with pam_get_item */
142 if(!strcmp(myval,"group"))
144 else if(!strcmp(myval,"shell"))
148 } else if(!strcmp(mybuf,"apply")) {
149 apply_type=APPLY_TYPE_NONE;
150 memset(apply_val,'\0',sizeof(apply_val));
152 apply_type=APPLY_TYPE_GROUP;
153 strncpy(apply_val,myval+1,sizeof(apply_val)-1);
155 apply_type=APPLY_TYPE_USER;
156 strncpy(apply_val,myval,sizeof(apply_val)-1);
160 pam_syslog(pamh,LOG_ERR, "Unknown option: %s",mybuf);
166 pam_syslog(pamh,LOG_ERR,
167 "Unknown item or item not specified");
171 pam_syslog(pamh,LOG_ERR, "List filename not specified");
173 } else if(sense == 2) {
174 pam_syslog(pamh,LOG_ERR,
175 "Unknown sense or sense not specified");
179 (apply_type==APPLY_TYPE_NONE) ||
180 ((apply_type!=APPLY_TYPE_NULL) && (*apply_val=='\0'))
182 pam_syslog(pamh,LOG_ERR,
183 "Invalid usage for apply= parameter");
188 /* Check if it makes sense to use the apply= parameter */
189 if (apply_type != APPLY_TYPE_NULL) {
190 if((citem==PAM_USER) || (citem==PAM_RUSER)) {
191 pam_syslog(pamh,LOG_WARNING,
192 "Non-sense use for apply= parameter");
193 apply_type=APPLY_TYPE_NULL;
195 if(extitem && (extitem==EI_GROUP)) {
196 pam_syslog(pamh,LOG_WARNING,
197 "Non-sense use for apply= parameter");
198 apply_type=APPLY_TYPE_NULL;
202 /* Short-circuit - test if this session apply for this user */
204 const char *user_name;
207 rval=pam_get_user(pamh,&user_name,NULL);
208 if((rval==PAM_SUCCESS) && user_name && user_name[0]) {
209 /* Got it ? Valid ? */
210 if(apply_type==APPLY_TYPE_USER) {
211 if(strcmp(user_name, apply_val)) {
212 /* Does not apply to this user */
214 pam_syslog(pamh,LOG_DEBUG,
215 "don't apply: apply=%s, user=%s",
216 apply_val,user_name);
221 } else if(apply_type==APPLY_TYPE_GROUP) {
222 if(!pam_modutil_user_in_group_nam_nam(pamh,user_name,apply_val)) {
223 /* Not a member of apply= group */
225 pam_syslog(pamh,LOG_DEBUG,
227 "don't apply: %s not a member of group %s",
228 user_name,apply_val);
237 retval = pam_get_item(pamh,citem,&void_citemp);
238 citemp = void_citemp;
239 if(retval != PAM_SUCCESS) {
242 if((citem == PAM_USER) && !citemp) {
243 retval = pam_get_user(pamh,&citemp,NULL);
244 if (retval != PAM_SUCCESS || !citemp) {
246 return PAM_SERVICE_ERR;
249 if((citem == PAM_TTY) && citemp) {
250 /* Normalize the TTY name. */
251 if(strncmp(citemp, "/dev/", 5) == 0) {
256 if(!citemp || (strlen(citemp) == 0)) {
258 /* The item was NULL - we are sure not to match */
259 return sense?PAM_SUCCESS:PAM_AUTH_ERR;
265 userinfo = pam_modutil_getpwnam(pamh, citemp);
266 if (userinfo == NULL) {
267 pam_syslog(pamh,LOG_ERR, "getpwnam(%s) failed",
272 grpinfo = pam_modutil_getgrgid(pamh, userinfo->pw_gid);
273 if (grpinfo == NULL) {
274 pam_syslog(pamh,LOG_ERR, "getgrgid(%d) failed",
275 (int)userinfo->pw_gid);
279 itemlist[0] = x_strdup(grpinfo->gr_name);
281 for (i=1; (i < (int)(sizeof(itemlist)/sizeof(itemlist[0])-1)) &&
282 (grpinfo = getgrent()); ) {
283 if (is_on_list(grpinfo->gr_mem,citemp)) {
284 itemlist[i++] = x_strdup(grpinfo->gr_name);
291 /* Assume that we have already gotten PAM_USER in
292 pam_get_item() - a valid assumption since citem
293 gets set to PAM_USER in the extitem switch */
294 userinfo = pam_modutil_getpwnam(pamh, citemp);
295 if (userinfo == NULL) {
296 pam_syslog(pamh,LOG_ERR, "getpwnam(%s) failed",
301 citemp = userinfo->pw_shell;
304 pam_syslog(pamh,LOG_ERR,
306 "Internal weirdness, unknown extended item %d",
313 pam_syslog(pamh,LOG_INFO,
315 "Got file = %s, item = %d, value = %s, sense = %d",
316 ifname, citem, citemp, sense);
318 if(lstat(ifname,&fileinfo)) {
319 pam_syslog(pamh,LOG_ERR, "Couldn't open %s",ifname);
324 if((fileinfo.st_mode & S_IWOTH)
325 || !S_ISREG(fileinfo.st_mode)) {
326 /* If the file is world writable or is not a
327 normal file, return error */
328 pam_syslog(pamh,LOG_ERR,
329 "%s is either world writable or not a normal file",
335 inf = fopen(ifname,"r");
336 if(inf == NULL) { /* Check that we opened it successfully */
337 if (onerr == PAM_SERVICE_ERR) {
338 /* Only report if it's an error... */
339 pam_syslog(pamh,LOG_ERR, "Error opening %s", ifname);
344 /* There should be no more errors from here on */
346 /* This loop assumes that PAM_SUCCESS == 0
347 and PAM_AUTH_ERR != 0 */
349 assert(PAM_SUCCESS == 0);
350 assert(PAM_AUTH_ERR != 0);
352 if(extitem == EI_GROUP) {
353 while((fgets(aline,sizeof(aline),inf) != NULL)
355 if(strlen(aline) == 0)
357 if(aline[strlen(aline) - 1] == '\n')
358 aline[strlen(aline) - 1] = '\0';
359 for(i=0;itemlist[i];)
360 /* If any of the items match, strcmp() == 0, and we get out
362 retval = (strcmp(aline,itemlist[i++]) && retval);
364 for(i=0;itemlist[i];)
367 while((fgets(aline,sizeof(aline),inf) != NULL)
370 if(strlen(aline) == 0)
372 if(aline[strlen(aline) - 1] == '\n')
373 aline[strlen(aline) - 1] = '\0';
374 if(strlen(aline) == 0)
376 if(aline[strlen(aline) - 1] == '\r')
377 aline[strlen(aline) - 1] = '\0';
379 if(strncmp(a, "/dev/", 5) == 0)
381 retval = strcmp(a,citemp);
386 if ((sense && retval) || (!sense && !retval)) {
388 pam_syslog(pamh,LOG_INFO,
389 "Returning PAM_SUCCESS, retval = %d", retval);
395 const char *user_name;
397 pam_syslog(pamh,LOG_INFO,
398 "Returning PAM_AUTH_ERR, retval = %d", retval);
400 (void) pam_get_item(pamh, PAM_SERVICE, &service);
401 (void) pam_get_user(pamh, &user_name, NULL);
402 pam_syslog (pamh, LOG_ALERT, "Refused user %s for service %s",
403 user_name, (const char *)service);
409 pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
410 int argc UNUSED, const char **argv UNUSED)
416 pam_sm_acct_mgmt (pam_handle_t *pamh, int flags,
417 int argc, const char **argv)
419 return pam_sm_authenticate(pamh, flags, argc, argv);
423 pam_sm_open_session (pam_handle_t *pamh, int flags,
424 int argc, const char **argv)
426 return pam_sm_authenticate(pamh, flags, argc, argv);
430 pam_sm_close_session (pam_handle_t *pamh, int flags,
431 int argc, const char **argv)
433 return pam_sm_authenticate(pamh, flags, argc, argv);
437 pam_sm_chauthtok (pam_handle_t *pamh, int flags,
438 int argc, const char **argv)
440 return pam_sm_authenticate(pamh, flags, argc, argv);
445 /* static module data */
447 struct pam_module _pam_listfile_modstruct = {
453 pam_sm_close_session,
457 #endif /* PAM_STATIC */
459 /* end of module definition */