Blame modules/pam_console/configfile.y

Packit Service b29381
%{
Packit Service b29381
/* Copyright 1999,2000 Red Hat, Inc.
Packit Service b29381
 * This software may be used under the terms of the GNU General Public
Packit Service b29381
 * License, available in the file COPYING accompanying this file
Packit Service b29381
 */
Packit Service b29381
#define YYSTYPE void *
Packit Service b29381
Packit Service b29381
#include <errno.h>
Packit Service b29381
#include <grp.h>
Packit Service b29381
#include <limits.h>
Packit Service b29381
#include <regex.h>
Packit Service b29381
#include <stdio.h>
Packit Service b29381
#include <stdarg.h>
Packit Service b29381
#include <sys/types.h>
Packit Service b29381
#include <sys/stat.h>
Packit Service b29381
#include <pwd.h>
Packit Service b29381
#include <chmod.h>
Packit Service b29381
#include <hashtable.h>
Packit Service b29381
Packit Service b29381
#include <security/pam_modules.h>
Packit Service b29381
#include <security/pam_modutil.h>
Packit Service b29381
Packit Service b29381
typedef struct hashtable GHashTable;
Packit Service b29381
Packit Service b29381
static GHashTable *namespace = NULL;
Packit Service b29381
static GSList *configList = NULL;
Packit Service b29381
static GSList *configListEnd = NULL;
Packit Service b29381
static GSList *consoleClassList = NULL;
Packit Service b29381
static GSList *consoleClassListEnd = NULL;
Packit Service b29381
static const char *consoleNameCache = NULL;
Packit Service b29381
static GHashTable *consoleHash = NULL;
Packit Service b29381
Packit Service b29381
static void
Packit Service b29381
do_yyerror(const char *format, ...);
Packit Service b29381
Packit Service b29381
static void
Packit Service b29381
empty_class(class *c);
Packit Service b29381
Packit Service b29381
static unsigned int
Packit Service b29381
str_hash(unsigned char *s)
Packit Service b29381
{
Packit Service b29381
        unsigned int hash = 5381;
Packit Service b29381
	int c;
Packit Service b29381
	                
Packit Service b29381
	while ((c = *s++))
Packit Service b29381
		hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
Packit Service b29381
	                                    
Packit Service b29381
	return hash;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
static int
Packit Service b29381
str_equal(void *a, void *b)
Packit Service b29381
{
Packit Service b29381
	return strcmp(a, b) == 0;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
static unsigned int
Packit Service b29381
ptr_hash(void *p)
Packit Service b29381
{
Packit Service b29381
	return (unsigned long)p >> 3;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
static int
Packit Service b29381
ptr_equal(void *a, void *b)
Packit Service b29381
{
Packit Service b29381
	return a == b;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
%}
Packit Service b29381
Packit Service b29381
%token EOL
Packit Service b29381
%token OBRACKET
Packit Service b29381
%token CBEQUALS
Packit Service b29381
%token CBRACKET
Packit Service b29381
%token STRING
Packit Service b29381
Packit Service b29381
%%
Packit Service b29381
lines:		lines line
Packit Service b29381
	|	/* empty */
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
line:		config
Packit Service b29381
	|	classdef
Packit Service b29381
	|	EOL
Packit Service b29381
	|	error
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
classdef:
Packit Service b29381
		OBRACKET string CBEQUALS stringlist EOL {
Packit Service b29381
		  class *c;
Packit Service b29381
Packit Service b29381
		  c = hashtable_search(namespace, $2);
Packit Service b29381
		  if (c) { 
Packit Service b29381
			empty_class(c);
Packit Service b29381
		  } else {
Packit Service b29381
			c = malloc(sizeof(class));
Packit Service b29381
			hashtable_insert(namespace, strdup($2), c);
Packit Service b29381
		  }
Packit Service b29381
		  c->name = $2;
Packit Service b29381
		  c->list = $4;
Packit Service b29381
		}
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
config:		classlist STRING classlist optstring optstring EOL {
Packit Service b29381
		  config *conf = malloc(sizeof(config));
Packit Service b29381
		  conf->console_class = $1;
Packit Service b29381
		  conf->mode = $2;
Packit Service b29381
		  conf->device_class = $3;
Packit Service b29381
		  conf->revert_mode = $4;
Packit Service b29381
		  conf->revert_owner = $5;
Packit Service b29381
                  if (conf->revert_owner != NULL) {
Packit Service b29381
                      conf->revert_group = strchr (conf->revert_owner, ':');
Packit Service b29381
                      if (conf->revert_group == NULL)
Packit Service b29381
                          conf->revert_group = strchr (conf->revert_owner, '.');
Packit Service b29381
                      if (conf->revert_group != NULL) {
Packit Service b29381
                          *(conf->revert_group) = '\0';
Packit Service b29381
                          conf->revert_group++;
Packit Service b29381
                          if (*(conf->revert_group) == '\0')
Packit Service b29381
                              conf->revert_group = NULL;
Packit Service b29381
                          if (*(conf->revert_owner) == '\0')
Packit Service b29381
                              conf->revert_owner = NULL;
Packit Service b29381
                      }
Packit Service b29381
                  } else {
Packit Service b29381
		      conf->revert_group = NULL;
Packit Service b29381
		  }
Packit Service b29381
		  configListEnd = g_slist_append(configListEnd, conf);
Packit Service b29381
		  if (configListEnd->next) configListEnd = configListEnd->next;
Packit Service b29381
		  if (!configList) configList = configListEnd;
Packit Service b29381
		  consoleClassListEnd =
Packit Service b29381
		    g_slist_append(consoleClassListEnd, conf->console_class);
Packit Service b29381
		  if (consoleClassListEnd->next)
Packit Service b29381
		    consoleClassListEnd = consoleClassListEnd->next;
Packit Service b29381
		  if (!consoleClassList) consoleClassList = consoleClassListEnd;
Packit Service b29381
		}
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
classlist:	OBRACKET string CBRACKET {
Packit Service b29381
		  class *c = hashtable_search(namespace, $2);
Packit Service b29381
		  if(!c) {
Packit Service b29381
		    _pam_log(NULL, LOG_ERR, FALSE,
Packit Service b29381
			  "unknown class \"%s\" at line %d in %s\n",
Packit Service b29381
			  (const char *)$2, lineno, filename);
Packit Service b29381
		    YYERROR;
Packit Service b29381
		  }
Packit Service b29381
		  $$ = c;
Packit Service b29381
		}
Packit Service b29381
	|	string {
Packit Service b29381
		  class *c = malloc(sizeof(class));
Packit Service b29381
		  c->name = $1;
Packit Service b29381
		  c->list = NULL;
Packit Service b29381
		  $$ = c;
Packit Service b29381
		}
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
Packit Service b29381
stringlist:	string	{$$ = g_slist_append(NULL, $1);}
Packit Service b29381
	|	stringlist string {$$ = g_slist_append($1, $2);}
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
optstring:	string	{$$=$1;}
Packit Service b29381
	|	/* empty */ {$$=NULL;}
Packit Service b29381
	;
Packit Service b29381
Packit Service b29381
string:		STRING {$$=$1;} ;
Packit Service b29381
Packit Service b29381
%%
Packit Service b29381
Packit Service b29381
/* exported functions */
Packit Service b29381
Packit Service b29381
/* parse a file given by a name */
Packit Service b29381
void
Packit Service b29381
parse_file(const char *name) {
Packit Service b29381
  FILE *infile;
Packit Service b29381
Packit Service b29381
  _pam_log(NULL, LOG_DEBUG, TRUE, "parsing config file %s", name);
Packit Service b29381
  infile = fopen(name, "r");
Packit Service b29381
  if (!infile) {
Packit Service b29381
    _pam_log(NULL, LOG_ERR, FALSE, "could not parse required file %s", name);
Packit Service b29381
    return;
Packit Service b29381
  }
Packit Service b29381
Packit Service b29381
  if (!namespace) namespace = create_hashtable(128, (unsigned int (*)(void *))str_hash, str_equal);
Packit Service b29381
Packit Service b29381
  lex_set_filename(name);
Packit Service b29381
  lex_file(infile);
Packit Service b29381
Packit Service b29381
  yyparse();
Packit Service b29381
  fclose(infile);
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
static int
Packit Service b29381
check_one_console_name (const char *name, char *classComponent) {
Packit Service b29381
    regex_t p;
Packit Service b29381
    int r_err;
Packit Service b29381
    char *class_exp;
Packit Service b29381
Packit Service b29381
    class_exp = _do_malloc(strlen(classComponent) + 3);
Packit Service b29381
    sprintf(class_exp, "^%s$", classComponent);
Packit Service b29381
    r_err = regcomp(&p, class_exp, REG_EXTENDED|REG_NOSUB);
Packit Service b29381
    if (r_err) do_regerror(r_err, &p);
Packit Service b29381
    r_err = regexec(&p, name, 0, NULL, 0);
Packit Service b29381
    regfree(&p);
Packit Service b29381
    free (class_exp);
Packit Service b29381
    return !r_err;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
int
Packit Service b29381
check_console_name (const char *consolename) {
Packit Service b29381
    GSList *this_class;
Packit Service b29381
    GSList *this_list;
Packit Service b29381
    class *c;
Packit Service b29381
    int found = 0;
Packit Service b29381
Packit Service b29381
    _pam_log(NULL, LOG_DEBUG, TRUE, "check console %s", consolename);
Packit Service b29381
    if (consoleNameCache != consolename) {
Packit Service b29381
	consoleNameCache = consolename;
Packit Service b29381
	if (consoleHash) hashtable_destroy(consoleHash, 0);
Packit Service b29381
	consoleHash = create_hashtable(128, ptr_hash, ptr_equal);
Packit Service b29381
    }
Packit Service b29381
    for (this_class = consoleClassList; this_class;
Packit Service b29381
	 this_class = this_class->next) {
Packit Service b29381
	c = this_class->data;
Packit Service b29381
        if (c->list) {
Packit Service b29381
	    for (this_list = c->list; this_list; this_list = this_list->next) {
Packit Service b29381
		if (check_one_console_name(consolename, this_list->data)) {
Packit Service b29381
		    hashtable_insert(consoleHash, c, c);
Packit Service b29381
		    found = 1;
Packit Service b29381
		}
Packit Service b29381
	    }
Packit Service b29381
	} else {
Packit Service b29381
	    if (check_one_console_name(consolename, c->name)) {
Packit Service b29381
		hashtable_insert(consoleHash, c, c);
Packit Service b29381
		found = 1;
Packit Service b29381
	    }
Packit Service b29381
	}
Packit Service b29381
    }
Packit Service b29381
Packit Service b29381
    if (found)
Packit Service b29381
	return 1;
Packit Service b29381
Packit Service b29381
    /* not found */
Packit Service b29381
    _pam_log(NULL, LOG_INFO, TRUE, "did not find console %s", consolename);
Packit Service b29381
    if (consoleHash) {
Packit Service b29381
	hashtable_destroy(consoleHash, 0);
Packit Service b29381
	consoleHash = NULL;
Packit Service b29381
    }
Packit Service b29381
    return 0;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
int
Packit Service b29381
set_permissions(const char *consolename, const char *username, GSList *files) {
Packit Service b29381
    struct passwd *pwd;
Packit Service b29381
    config *c;
Packit Service b29381
    GSList *cl;
Packit Service b29381
Packit Service b29381
    if (!consoleNameCache || strcmp(consolename, consoleNameCache)) {
Packit Service b29381
	if (!check_console_name(consolename)) return -1;
Packit Service b29381
    }
Packit Service b29381
Packit Service b29381
    pwd = getpwnam(username);
Packit Service b29381
    if (pwd == NULL) {
Packit Service b29381
	_pam_log(NULL, LOG_ERR, FALSE, "getpwnam failed for \"%s\"", username);
Packit Service b29381
	return -1;
Packit Service b29381
    }
Packit Service b29381
Packit Service b29381
    for (cl = configList; cl; cl = cl->next) {
Packit Service b29381
	c = cl->data;
Packit Service b29381
	if (hashtable_search(consoleHash, c->console_class)) {
Packit Service b29381
    	    if (c->device_class->list)
Packit Service b29381
	        chmod_files(c->mode, pwd->pw_uid, -1, NULL, c->device_class->list, files);
Packit Service b29381
	    else
Packit Service b29381
	        chmod_files(c->mode, pwd->pw_uid, -1, c->device_class->name, NULL, files);
Packit Service b29381
	}
Packit Service b29381
    }
Packit Service b29381
    return 0;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
int
Packit Service b29381
reset_permissions(const char *consolename, GSList *files) {
Packit Service b29381
    struct passwd *pwd;
Packit Service b29381
    struct group *grp;
Packit Service b29381
    config *c;
Packit Service b29381
    GSList *cl;
Packit Service b29381
Packit Service b29381
    if (!consoleNameCache || strcmp(consolename, consoleNameCache)) {
Packit Service b29381
	if (!check_console_name(consolename)) return -1;
Packit Service b29381
    }
Packit Service b29381
Packit Service b29381
    for (cl = configList; cl; cl = cl->next) {
Packit Service b29381
	c = cl->data;
Packit Service b29381
	if (hashtable_search(consoleHash, c->console_class)) {
Packit Service b29381
	    pwd = getpwnam(c->revert_owner ? c->revert_owner : "root");
Packit Service b29381
	    if (pwd == NULL) {
Packit Service b29381
		_pam_log(NULL, LOG_ERR, FALSE, "getpwnam failed for %s",
Packit Service b29381
			 c->revert_owner ? c->revert_owner : "root");
Packit Service b29381
		pwd = getpwuid(0);
Packit Service b29381
		if (pwd == NULL)
Packit Service b29381
		    return -1;
Packit Service b29381
	    }
Packit Service b29381
	    grp = getgrnam(c->revert_group ? c->revert_group : "root");
Packit Service b29381
	    if (grp == NULL) {
Packit Service b29381
                _pam_log(NULL, LOG_ERR, FALSE, "getgrnam failed for %s",
Packit Service b29381
                         c->revert_group ? c->revert_group : "root");
Packit Service b29381
		grp = getgrgid(0);
Packit Service b29381
		if (grp == NULL)
Packit Service b29381
            	    return -1;
Packit Service b29381
            }
Packit Service b29381
	    if (c->device_class->list)
Packit Service b29381
	        chmod_files(c->revert_mode ? c->revert_mode : "0600",
Packit Service b29381
		            pwd->pw_uid, grp->gr_gid, NULL, c->device_class->list, files);
Packit Service b29381
	    else
Packit Service b29381
	        chmod_files(c->revert_mode ? c->revert_mode : "0600",
Packit Service b29381
		            pwd->pw_uid, grp->gr_gid, c->device_class->name, NULL, files);
Packit Service b29381
	}
Packit Service b29381
    }
Packit Service b29381
    return 0;
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
Packit Service b29381
Packit Service b29381
Packit Service b29381
/* local, static functions */
Packit Service b29381
Packit Service b29381
static void
Packit Service b29381
do_yyerror(const char *format, ...) {
Packit Service b29381
  va_list ap;
Packit Service b29381
Packit Service b29381
  va_start(ap, format);
Packit Service b29381
  openlog("pam_console", LOG_CONS|LOG_PID, LOG_AUTHPRIV);
Packit Service b29381
  vsyslog(LOG_PID|LOG_AUTHPRIV|LOG_ERR, format, ap);
Packit Service b29381
  va_end(ap);
Packit Service b29381
}
Packit Service b29381
Packit Service b29381
static void
Packit Service b29381
empty_class(class *c) {
Packit Service b29381
  free(c->name);
Packit Service b29381
  c->name = NULL;
Packit Service b29381
  g_slist_free(c->list);
Packit Service b29381
  c->list = NULL;
Packit Service b29381
}