123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- /*
- * 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);
- }
|