diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 12:01:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 12:01:37 +0000 |
commit | de848d9e9146434817c65d74d1d0313e9d729462 (patch) | |
tree | dcbd0efb229b17f696f7195671f05b354b4f70fc /modules/pam_listfile/pam_listfile.c | |
parent | Initial commit. (diff) | |
download | pam-de848d9e9146434817c65d74d1d0313e9d729462.tar.xz pam-de848d9e9146434817c65d74d1d0313e9d729462.zip |
Adding upstream version 1.4.0.upstream/1.4.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/pam_listfile/pam_listfile.c')
-rw-r--r-- | modules/pam_listfile/pam_listfile.c | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/modules/pam_listfile/pam_listfile.c b/modules/pam_listfile/pam_listfile.c new file mode 100644 index 0000000..28fd58f --- /dev/null +++ b/modules/pam_listfile/pam_listfile.c @@ -0,0 +1,397 @@ +/* + * pam_listfile module + * + * by Elliot Lee <sopwith@redhat.com>, Red Hat Software. July 25, 1996. + * log refused access error christopher mccrory <chrismcc@netus.com> 1998/7/11 + * + * This code began life as the pam_rootok module. + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <syslog.h> +#include <stdarg.h> +#include <string.h> +#include <pwd.h> +#include <grp.h> + +#ifdef PAM_DEBUG +#include <assert.h> +#endif + +#include <security/pam_modules.h> +#include <security/_pam_macros.h> +#include <security/pam_modutil.h> +#include <security/pam_ext.h> +#include "pam_inline.h" + +/* --- authentication management functions (only) --- */ + +/* Extended Items that are not directly available via pam_get_item() */ +#define EI_GROUP (1 << 0) +#define EI_SHELL (1 << 1) + +/* Constants for apply= parameter */ +#define APPLY_TYPE_NULL 0 +#define APPLY_TYPE_NONE 1 +#define APPLY_TYPE_USER 2 +#define APPLY_TYPE_GROUP 3 + +#define LESSER(a, b) ((a) < (b) ? (a) : (b)) + +int +pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) +{ + int retval, i, citem=0, extitem=0, onerr=PAM_SERVICE_ERR, sense=2, quiet=0; + const void *void_citemp; + const char *citemp; + char *ifname=NULL; + char aline[256]; + char mybuf[256],myval[256]; + struct stat fileinfo; + FILE *inf; + const char *apply_val; + int apply_type; + + /* Stuff for "extended" items */ + struct passwd *userinfo; + + apply_type=APPLY_TYPE_NULL; + apply_val=""; + + for(i=0; i < argc; i++) { + { + const char *junk; + + /* option quiet has no value */ + if(!strcmp(argv[i],"quiet")) { + quiet = 1; + continue; + } + + memset(mybuf,'\0',sizeof(mybuf)); + memset(myval,'\0',sizeof(myval)); + junk = strchr(argv[i], '='); + if((junk == NULL) || (junk - argv[i]) >= (int) sizeof(mybuf)) { + pam_syslog(pamh,LOG_ERR, "Bad option: \"%s\"", + argv[i]); + continue; + } + strncpy(mybuf, argv[i], + LESSER(junk - argv[i], (int)sizeof(mybuf) - 1)); + strncpy(myval, junk + 1, sizeof(myval) - 1); + } + if(!strcmp(mybuf,"onerr")) + if(!strcmp(myval,"succeed")) + onerr = PAM_SUCCESS; + else if(!strcmp(myval,"fail")) + onerr = PAM_SERVICE_ERR; + else { + if (ifname) free (ifname); + return PAM_SERVICE_ERR; + } + else if(!strcmp(mybuf,"sense")) + if(!strcmp(myval,"allow")) + sense=0; + else if(!strcmp(myval,"deny")) + sense=1; + else { + if (ifname) free (ifname); + return onerr; + } + else if(!strcmp(mybuf,"file")) { + if (ifname) free (ifname); + ifname = (char *)malloc(strlen(myval)+1); + if (!ifname) + return PAM_BUF_ERR; + strcpy(ifname,myval); + } else if(!strcmp(mybuf,"item")) + if(!strcmp(myval,"user")) + citem = PAM_USER; + else if(!strcmp(myval,"tty")) + citem = PAM_TTY; + else if(!strcmp(myval,"rhost")) + citem = PAM_RHOST; + else if(!strcmp(myval,"ruser")) + citem = PAM_RUSER; + else { /* These items are related to the user, but are not + directly gettable with pam_get_item */ + citem = PAM_USER; + if(!strcmp(myval,"group")) + extitem = EI_GROUP; + else if(!strcmp(myval,"shell")) + extitem = EI_SHELL; + else + citem = 0; + } else if(!strcmp(mybuf,"apply")) { + apply_type=APPLY_TYPE_NONE; + if (myval[0]=='@') { + apply_type=APPLY_TYPE_GROUP; + apply_val=myval+1; + } else { + apply_type=APPLY_TYPE_USER; + apply_val=myval; + } + } else { + free(ifname); + pam_syslog(pamh,LOG_ERR, "Unknown option: %s",mybuf); + return onerr; + } + } + + if(!citem) { + pam_syslog(pamh,LOG_ERR, + "Unknown item or item not specified"); + free(ifname); + return onerr; + } else if(!ifname) { + pam_syslog(pamh,LOG_ERR, "List filename not specified"); + return onerr; + } else if(sense == 2) { + pam_syslog(pamh,LOG_ERR, + "Unknown sense or sense not specified"); + free(ifname); + return onerr; + } else if( + (apply_type==APPLY_TYPE_NONE) || + ((apply_type!=APPLY_TYPE_NULL) && (*apply_val=='\0')) + ) { + pam_syslog(pamh,LOG_ERR, + "Invalid usage for apply= parameter"); + free (ifname); + return onerr; + } + + /* Check if it makes sense to use the apply= parameter */ + if (apply_type != APPLY_TYPE_NULL) { + if((citem==PAM_USER) || (citem==PAM_RUSER)) { + pam_syslog(pamh,LOG_WARNING, + "Non-sense use for apply= parameter"); + apply_type=APPLY_TYPE_NULL; + } + if(extitem && (extitem==EI_GROUP)) { + pam_syslog(pamh,LOG_WARNING, + "Non-sense use for apply= parameter"); + apply_type=APPLY_TYPE_NULL; + } + } + + /* Short-circuit - test if this session apply for this user */ + { + const char *user_name; + int rval; + + rval=pam_get_user(pamh,&user_name,NULL); + if(rval==PAM_SUCCESS && user_name[0]) { + /* Got it ? Valid ? */ + if(apply_type==APPLY_TYPE_USER) { + if(strcmp(user_name, apply_val)) { + /* Does not apply to this user */ +#ifdef PAM_DEBUG + pam_syslog(pamh,LOG_DEBUG, + "don't apply: apply=%s, user=%s", + apply_val,user_name); +#endif /* PAM_DEBUG */ + free(ifname); + return PAM_IGNORE; + } + } else if(apply_type==APPLY_TYPE_GROUP) { + if(!pam_modutil_user_in_group_nam_nam(pamh,user_name,apply_val)) { + /* Not a member of apply= group */ +#ifdef PAM_DEBUG + pam_syslog(pamh,LOG_DEBUG, + + "don't apply: %s not a member of group %s", + user_name,apply_val); +#endif /* PAM_DEBUG */ + free(ifname); + return PAM_IGNORE; + } + } + } + } + + retval = pam_get_item(pamh,citem,&void_citemp); + citemp = void_citemp; + if(retval != PAM_SUCCESS) { + free(ifname); + return onerr; + } + if((citem == PAM_USER) && !citemp) { + retval = pam_get_user(pamh,&citemp,NULL); + if (retval != PAM_SUCCESS) { + free(ifname); + return PAM_SERVICE_ERR; + } + } + if((citem == PAM_TTY) && citemp) { + /* Normalize the TTY name. */ + const char *str = pam_str_skip_prefix(citemp, "/dev/"); + if (str != NULL) + citemp = str; + } + + if(!citemp || (strlen(citemp) == 0)) { + free(ifname); + /* The item was NULL - we are sure not to match */ + return sense?PAM_SUCCESS:PAM_AUTH_ERR; + } + + if(extitem) { + switch(extitem) { + case EI_GROUP: + /* Just ignore, call pam_modutil_in_group... later */ + break; + case EI_SHELL: + /* Assume that we have already gotten PAM_USER in + pam_get_item() - a valid assumption since citem + gets set to PAM_USER in the extitem switch */ + userinfo = pam_modutil_getpwnam(pamh, citemp); + if (userinfo == NULL) { + pam_syslog(pamh, LOG_NOTICE, "getpwnam(%s) failed", + citemp); + free(ifname); + return onerr; + } + citemp = userinfo->pw_shell; + break; + default: + pam_syslog(pamh,LOG_ERR, + + "Internal weirdness, unknown extended item %d", + extitem); + free(ifname); + return onerr; + } + } +#ifdef PAM_DEBUG + pam_syslog(pamh,LOG_INFO, + + "Got file = %s, item = %d, value = %s, sense = %d", + ifname, citem, citemp, sense); +#endif + if(lstat(ifname,&fileinfo)) { + if(!quiet) + pam_syslog(pamh,LOG_ERR, "Couldn't open %s",ifname); + free(ifname); + return onerr; + } + + if((fileinfo.st_mode & S_IWOTH) + || !S_ISREG(fileinfo.st_mode)) { + /* If the file is world writable or is not a + normal file, return error */ + pam_syslog(pamh,LOG_ERR, + "%s is either world writable or not a normal file", + ifname); + free(ifname); + return PAM_AUTH_ERR; + } + + inf = fopen(ifname,"r"); + if(inf == NULL) { /* Check that we opened it successfully */ + if (onerr == PAM_SERVICE_ERR) { + /* Only report if it's an error... */ + pam_syslog(pamh,LOG_ERR, "Error opening %s", ifname); + } + free(ifname); + return onerr; + } + /* There should be no more errors from here on */ + retval=PAM_AUTH_ERR; + /* This loop assumes that PAM_SUCCESS == 0 + and PAM_AUTH_ERR != 0 */ +#ifdef PAM_DEBUG + assert(PAM_SUCCESS == 0); + assert(PAM_AUTH_ERR != 0); +#endif + while((fgets(aline,sizeof(aline),inf) != NULL) + && retval) { + const char *a = aline; + + if(strlen(aline) == 0) + continue; + if(aline[strlen(aline) - 1] == '\n') + aline[strlen(aline) - 1] = '\0'; + if(strlen(aline) == 0) + continue; + if(aline[strlen(aline) - 1] == '\r') + aline[strlen(aline) - 1] = '\0'; + if(citem == PAM_TTY) { + const char *str = pam_str_skip_prefix(a, "/dev/"); + if (str != NULL) + a = str; + } + if (extitem == EI_GROUP) { + retval = !pam_modutil_user_in_group_nam_nam(pamh, + citemp, aline); + } else { + retval = strcmp(a, citemp); + } + } + + fclose(inf); + free(ifname); + if ((sense && retval) || (!sense && !retval)) { +#ifdef PAM_DEBUG + pam_syslog(pamh,LOG_INFO, + "Returning PAM_SUCCESS, retval = %d", retval); +#endif + return PAM_SUCCESS; + } + else { + const void *service; + const char *user_name; +#ifdef PAM_DEBUG + pam_syslog(pamh,LOG_INFO, + "Returning PAM_AUTH_ERR, retval = %d", retval); +#endif + (void) pam_get_item(pamh, PAM_SERVICE, &service); + (void) pam_get_user(pamh, &user_name, NULL); + if (!quiet) + pam_syslog (pamh, LOG_NOTICE, "Refused user %s for service %s", + user_name, (const char *)service); + return PAM_AUTH_ERR; + } +} + +int +pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED, + int argc UNUSED, const char **argv UNUSED) +{ + return PAM_SUCCESS; +} + +int +pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +int +pam_sm_open_session (pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +int +pam_sm_close_session (pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return pam_sm_authenticate(pamh, flags, argc, argv); +} + +int +pam_sm_chauthtok (pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return pam_sm_authenticate(pamh, flags, argc, argv); +} |