mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
allow multiple profiles to be parsed from the command line
Signed-Off-By: Kees Cook <kees.cook@canonical.com>
This commit is contained in:
parent
af902dddf1
commit
33d01a980a
@ -219,6 +219,9 @@ extern int yyparse(void);
|
|||||||
extern void yyerror(char *msg, ...);
|
extern void yyerror(char *msg, ...);
|
||||||
extern int yylex(void);
|
extern int yylex(void);
|
||||||
|
|
||||||
|
/* parser_include.c */
|
||||||
|
extern char *basedir;
|
||||||
|
|
||||||
/* parser_regex.c */
|
/* parser_regex.c */
|
||||||
extern int process_regex(struct codomain *cod);
|
extern int process_regex(struct codomain *cod);
|
||||||
extern int post_process_entry(struct cod_entry *entry);
|
extern int post_process_entry(struct cod_entry *entry);
|
||||||
|
@ -67,67 +67,16 @@ static char *path[MAX_PATH] = { NULL };
|
|||||||
static int npath = 0;
|
static int npath = 0;
|
||||||
|
|
||||||
static int fgetline(FILE * f, char *buffer, size_t len);
|
static int fgetline(FILE * f, char *buffer, size_t len);
|
||||||
static int getincludestr(char **inc, int c, FILE *f, int line, char *name,
|
|
||||||
FILE *out);
|
|
||||||
static int stripcomment(char *s);
|
static int stripcomment(char *s);
|
||||||
static char *stripblanks(char *s);
|
static char *stripblanks(char *s);
|
||||||
static int preprocess(FILE *f, char *name, FILE * out, int nest);
|
|
||||||
|
|
||||||
int preprocess_only;
|
|
||||||
|
|
||||||
/* default base directory is /etc/subdomain.d, it can be overriden
|
/* default base directory is /etc/subdomain.d, it can be overriden
|
||||||
with the -b option. */
|
with the -b option. */
|
||||||
|
|
||||||
static char *basedir;
|
char *basedir;
|
||||||
static char *default_basedir = "/etc/apparmor.d";
|
static char *default_basedir = "/etc/apparmor.d";
|
||||||
static char *old_basedir = "/etc/subdomain.d";
|
static char *old_basedir = "/etc/subdomain.d";
|
||||||
|
|
||||||
/* start parsing. */
|
|
||||||
int do_include_preprocessing(char *profilename)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
FILE *tmp, *profile = NULL;
|
|
||||||
|
|
||||||
if (profilename) {
|
|
||||||
profile = fopen(profilename, "r");
|
|
||||||
if (!profile) {
|
|
||||||
PERROR(_("Error: Could not read profile %s: %s.\n"),
|
|
||||||
profilename, strerror(errno));
|
|
||||||
exit(errno);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
profile = stdin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Change to the base dir */
|
|
||||||
chdir(basedir);
|
|
||||||
|
|
||||||
if (preprocess_only) {
|
|
||||||
retval = preprocess(profile, profilename ? profilename : "stdin",
|
|
||||||
stdout, 0);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = tmpfile();
|
|
||||||
if (!tmp) {
|
|
||||||
PERROR(_("Error: Could not allocate temporary file.\n"));
|
|
||||||
exit(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = preprocess(profile, profilename ? profilename : "stdin",
|
|
||||||
tmp, 0);
|
|
||||||
|
|
||||||
rewind(tmp);
|
|
||||||
|
|
||||||
dup2(fileno(tmp), 0); /* stdin */
|
|
||||||
fclose(tmp);
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (profilename)
|
|
||||||
fclose(profile);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up basedir so that it can be overridden/used later. */
|
/* set up basedir so that it can be overridden/used later. */
|
||||||
void init_base_dir(void)
|
void init_base_dir(void)
|
||||||
@ -258,233 +207,24 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char incword[] = "include";
|
FILE *search_path(char *filename, char **fullpath)
|
||||||
|
|
||||||
/* getincludestr:
|
|
||||||
* returns !0 if error occurred
|
|
||||||
* include string (or not) is returned in 'inc'
|
|
||||||
*/
|
|
||||||
static int getincludestr(char **inc, int c, FILE *f, int line, char *name,
|
|
||||||
FILE *out)
|
|
||||||
{
|
|
||||||
char *b;
|
|
||||||
size_t i = 0, a;
|
|
||||||
int d;
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
*inc = NULL;
|
|
||||||
|
|
||||||
if (c != '#')
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
/* we either have a comment or an include, either process the include
|
|
||||||
or strip the comment to the eol. Leave the eol char so line count
|
|
||||||
gets properly incremented. */
|
|
||||||
|
|
||||||
for (i = 0; i < strlen(incword); i++) {
|
|
||||||
c = fgetc(f);
|
|
||||||
if (c == EOF || c == '\n' || c != incword[i]) {
|
|
||||||
ungetc(c, f);
|
|
||||||
goto comment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* found "#include" now search for the file name to include */
|
|
||||||
b = malloc(2048);
|
|
||||||
if (!b) {
|
|
||||||
PERROR(_("Error: Could not allocate buffer for include at line %d in %s.\n"),
|
|
||||||
line, name);
|
|
||||||
retval = 1;
|
|
||||||
goto comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = fgetc(f);
|
|
||||||
if (!isspace(c)) {
|
|
||||||
ungetc(c, f);
|
|
||||||
goto comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((c = fgetc(f)) != EOF && c != '\n' && isspace(c))
|
|
||||||
/* eat whitespace */ ;
|
|
||||||
if (c != '\"' && c != '<') {
|
|
||||||
free(b);
|
|
||||||
PERROR(_("Error: Bad include at line %d in %s.\n"), line, name);
|
|
||||||
if (c == '\n')
|
|
||||||
ungetc(c, f);
|
|
||||||
retval = 1;
|
|
||||||
goto comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
b[0] = c;
|
|
||||||
i = 1;
|
|
||||||
while ((d = fgetc(f)) != EOF && d != '\n'
|
|
||||||
&& d != (c == '<' ? '>' : '\"') && i < 2048)
|
|
||||||
b[i++] = d;
|
|
||||||
|
|
||||||
if (d == (c == '<' ? '>' : '\"')) {
|
|
||||||
b[i] = 0;
|
|
||||||
*inc = b;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(b);
|
|
||||||
PERROR(_("Error: Bad include at line %d in %s.\n"), line, name);
|
|
||||||
ungetc(d, f);
|
|
||||||
retval = 1;
|
|
||||||
/* fall through to comment - this makes trailing stuff a comment */
|
|
||||||
|
|
||||||
comment:
|
|
||||||
fputc('#', out);
|
|
||||||
for (a = 0; a < i; a++) {
|
|
||||||
fputc(incword[a], out);
|
|
||||||
}
|
|
||||||
while ((c = fgetc(f)) != EOF && c != '\n')
|
|
||||||
fputc(c, out);
|
|
||||||
if (c == '\n')
|
|
||||||
ungetc(c, f);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the include file or directory by searching the path. */
|
|
||||||
static int process_include(char *inc, char *name, int line, FILE *out, int nest)
|
|
||||||
{
|
{
|
||||||
FILE *newf = NULL;
|
FILE *newf = NULL;
|
||||||
int retval = 0;
|
char *buf = NULL;
|
||||||
char *buf;
|
int i;
|
||||||
struct stat my_stat;
|
for (i = 0; i < npath; i++) {
|
||||||
int err;
|
if (asprintf(&buf, "%s/%s", path[i], filename) < 0) {
|
||||||
|
perror("asprintf");
|
||||||
if (*inc == '\"') {
|
exit(1);
|
||||||
buf = strdup(inc + 1);
|
|
||||||
if (buf)
|
|
||||||
newf = fopen(buf, "r");
|
|
||||||
} else {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < npath; i++) {
|
|
||||||
if (asprintf(&buf, "%s/%s", path[i], inc + 1) != -1) {
|
|
||||||
newf = fopen(buf, "r");
|
|
||||||
if (newf)
|
|
||||||
break;
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
buf = NULL;
|
|
||||||
}
|
}
|
||||||
|
newf = fopen(buf, "r");
|
||||||
|
if (newf && fullpath) *fullpath = buf;
|
||||||
|
else free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
if (newf)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return newf;
|
||||||
if (!newf) {
|
|
||||||
PERROR(_("Error: #include %s%c not found at line %d in %s.\n"),
|
|
||||||
inc,
|
|
||||||
*inc == '<' ? '>' : '\"',
|
|
||||||
line,
|
|
||||||
name);
|
|
||||||
retval = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = fstat(fileno(newf), &my_stat);
|
|
||||||
if (err) {
|
|
||||||
retval = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISREG(my_stat.st_mode)) {
|
|
||||||
err = preprocess(newf, inc + 1, out, nest + 1);
|
|
||||||
if (err)
|
|
||||||
retval = err;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISDIR(my_stat.st_mode)) {
|
|
||||||
DIR *dir = NULL;
|
|
||||||
struct dirent *dirent;
|
|
||||||
|
|
||||||
/* XXX - fdopendir not available in glibc < 2.4 */
|
|
||||||
/* dir = fdopendir(fileno(newf)); */
|
|
||||||
fclose(newf);
|
|
||||||
dir = opendir(buf);
|
|
||||||
if (!dir) {
|
|
||||||
retval = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dirent = readdir(dir)) != NULL) {
|
|
||||||
char *dirbuf;
|
|
||||||
/* skip dotfiles. */
|
|
||||||
if (dirent->d_name[0] == '.')
|
|
||||||
continue;
|
|
||||||
asprintf(&dirbuf, "%s/%s", buf, dirent->d_name);
|
|
||||||
err = stat(dirbuf, &my_stat);
|
|
||||||
if (err) {
|
|
||||||
retval = errno;
|
|
||||||
free(dirbuf);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISREG(my_stat.st_mode)) {
|
|
||||||
newf = fopen(dirbuf, "r");
|
|
||||||
if (newf) {
|
|
||||||
err = preprocess(newf, inc + 1, out, nest + 1);
|
|
||||||
if (err)
|
|
||||||
retval = err;
|
|
||||||
fclose(newf);
|
|
||||||
} else {
|
|
||||||
retval = errno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(dirbuf);
|
|
||||||
}
|
|
||||||
newf = NULL;
|
|
||||||
closedir(dir);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
if (buf)
|
|
||||||
free(buf);
|
|
||||||
if (newf)
|
|
||||||
fclose(newf);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int preprocess(FILE * f, char *name, FILE * out, int nest)
|
|
||||||
{
|
|
||||||
int line = 1;
|
|
||||||
int c;
|
|
||||||
int retval = 0;
|
|
||||||
char *inc = NULL;
|
|
||||||
char *cwd;
|
|
||||||
|
|
||||||
if (nest > MAX_NEST_LEVEL) {
|
|
||||||
PERROR(_("Error: Exceeded %d levels of includes. Not processing %s include.\n"),
|
|
||||||
MAX_NEST_LEVEL, name);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nest == 0) {
|
|
||||||
fprintf(out, "\n#source %s\n", name);
|
|
||||||
} else {
|
|
||||||
fprintf(out, "\n#included %s\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((c = fgetc(f)) != EOF) {
|
|
||||||
int err = getincludestr(&inc, c, f, line, name, out);
|
|
||||||
if (err)
|
|
||||||
retval = err;
|
|
||||||
if (inc) {
|
|
||||||
cwd = get_current_dir_name();
|
|
||||||
err = process_include(inc, name, line, out, nest);
|
|
||||||
if (err)
|
|
||||||
retval = err;
|
|
||||||
chdir(cwd);
|
|
||||||
free(cwd);
|
|
||||||
free(inc);
|
|
||||||
} else {
|
|
||||||
if (c != '#')
|
|
||||||
fputc(c, out);
|
|
||||||
if (c == '\n')
|
|
||||||
line++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a line from the file. If it is to long truncate it. */
|
/* get a line from the file. If it is to long truncate it. */
|
||||||
|
@ -27,5 +27,6 @@ extern void init_base_dir(void);
|
|||||||
extern void set_base_dir(char *dir);
|
extern void set_base_dir(char *dir);
|
||||||
extern void parse_default_paths(void);
|
extern void parse_default_paths(void);
|
||||||
extern int do_include_preprocessing(char *profilename);
|
extern int do_include_preprocessing(char *profilename);
|
||||||
|
FILE *search_path(char *filename, char **fullpath);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,11 +28,19 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libintl.h>
|
#include <libintl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
#define _(s) gettext(s)
|
#define _(s) gettext(s)
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "parser_include.h"
|
||||||
#include "parser_yacc.h"
|
#include "parser_yacc.h"
|
||||||
|
|
||||||
|
#ifdef PDEBUG
|
||||||
|
#undef PDEBUG
|
||||||
|
#endif
|
||||||
/* #define DEBUG */
|
/* #define DEBUG */
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define PDEBUG(fmt, args...) printf("Lexer: " fmt, ## args)
|
#define PDEBUG(fmt, args...) printf("Lexer: " fmt, ## args)
|
||||||
@ -43,6 +51,100 @@
|
|||||||
|
|
||||||
int current_lineno = 1;
|
int current_lineno = 1;
|
||||||
|
|
||||||
|
struct ignored_suffix_t {
|
||||||
|
char * text;
|
||||||
|
int len;
|
||||||
|
int silent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ignored_suffix_t ignored_suffixes[] = {
|
||||||
|
/* Debian packging files, which are in flux during install
|
||||||
|
should be silently ignored. */
|
||||||
|
{ ".dpkg-new", 9, 1 },
|
||||||
|
{ ".dpkg-old", 9, 1 },
|
||||||
|
{ ".dpkg-dist", 10, 1 },
|
||||||
|
/* RPM packaging files have traditionally not been silently
|
||||||
|
ignored */
|
||||||
|
{ ".rpmnew", 7, 0 },
|
||||||
|
{ ".rpmsave", 8, 0 },
|
||||||
|
/* Backup files should be mentioned */
|
||||||
|
{ "~", 1, 0 },
|
||||||
|
{ NULL, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
void include_filename(char *filename, int search)
|
||||||
|
{
|
||||||
|
FILE *include_file = NULL;
|
||||||
|
struct stat my_stat;
|
||||||
|
char *fullpath = NULL;
|
||||||
|
|
||||||
|
if (search) include_file = search_path(filename, &fullpath);
|
||||||
|
else {
|
||||||
|
fullpath = strdup(filename);
|
||||||
|
include_file = fopen(fullpath, "r");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!include_file) yyerror(_("Could not open '%s'"), fullpath);
|
||||||
|
|
||||||
|
if (fstat(fileno(include_file), &my_stat))
|
||||||
|
yyerror(_("fstat failed for '%s'"), fullpath);
|
||||||
|
|
||||||
|
if (S_ISREG(my_stat.st_mode)) {
|
||||||
|
yyin = include_file;
|
||||||
|
PDEBUG("Opened include \"%s\"\n", fullpath);
|
||||||
|
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(my_stat.st_mode)) {
|
||||||
|
DIR *dir = NULL;
|
||||||
|
char *dirent_path = NULL;
|
||||||
|
struct dirent *dirent;
|
||||||
|
|
||||||
|
PDEBUG("Opened include directory \"%s\"\n", fullpath);
|
||||||
|
if (!(dir = opendir(fullpath)))
|
||||||
|
yyerror(_("opendir failed '%s'"), fullpath);
|
||||||
|
fclose(include_file);
|
||||||
|
include_file = NULL;
|
||||||
|
|
||||||
|
while ((dirent = readdir(dir)) != NULL) {
|
||||||
|
int name_len;
|
||||||
|
struct ignored_suffix_t *suffix;
|
||||||
|
/* skip dotfiles silently. */
|
||||||
|
if (dirent->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (dirent_path) free(dirent_path);
|
||||||
|
if (asprintf(&dirent_path, "%s/%s", fullpath, dirent->d_name)<0)
|
||||||
|
yyerror("Out of memory");
|
||||||
|
|
||||||
|
name_len = strlen(dirent->d_name);
|
||||||
|
/* skip blacklisted suffixes */
|
||||||
|
for (suffix = ignored_suffixes; suffix->text; suffix++) {
|
||||||
|
char *found;
|
||||||
|
if ( (found = strstr(dirent->d_name, suffix->text)) &&
|
||||||
|
found - dirent->d_name + suffix->len == name_len ) {
|
||||||
|
name_len = 0;
|
||||||
|
if (!suffix->silent)
|
||||||
|
PERROR("Ignoring: '%s'\n", dirent_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!name_len) continue;
|
||||||
|
|
||||||
|
if (stat(dirent_path, &my_stat))
|
||||||
|
yyerror(_("stat failed for '%s'"), dirent_path);
|
||||||
|
if (S_ISREG(my_stat.st_mode)) {
|
||||||
|
if (!(yyin = fopen(dirent_path,"r")))
|
||||||
|
yyerror(_("Could not open '%s'"), filename);
|
||||||
|
PDEBUG("Opened include \"%s\"\n", filename);
|
||||||
|
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dirent_path) free(dirent_path);
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
UP "^"
|
UP "^"
|
||||||
@ -88,9 +190,39 @@ LT_EQUAL <=
|
|||||||
%x ASSIGN_MODE
|
%x ASSIGN_MODE
|
||||||
%x RLIMIT_MODE
|
%x RLIMIT_MODE
|
||||||
%x CHANGE_PROFILE_MODE
|
%x CHANGE_PROFILE_MODE
|
||||||
|
%x INCLUDE
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
<INCLUDE>{
|
||||||
|
{WS}+ { /* Eat whitespace */ }
|
||||||
|
\<([^\> \t\n]+)\> { /* <filename> */
|
||||||
|
char *filename = strdup(yytext);
|
||||||
|
filename[strlen(filename)-1]='\0';
|
||||||
|
include_filename(filename+1, 1);
|
||||||
|
free(filename);
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
\"([^\" \t\n]+)\" { /* "filename" */
|
||||||
|
char *filename = strdup(yytext);
|
||||||
|
filename[strlen(filename)-1]='\0';
|
||||||
|
include_filename(filename+1, 0);
|
||||||
|
free(filename);
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
[^\<\>\"{WS}]+ { /* filename */
|
||||||
|
include_filename(yytext, 0);
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<<EOF>> {
|
||||||
|
yypop_buffer_state();
|
||||||
|
if ( !YY_CURRENT_BUFFER ) yyterminate();
|
||||||
|
}
|
||||||
|
|
||||||
<SUB_NAME>{
|
<SUB_NAME>{
|
||||||
{ID}+ {
|
{ID}+ {
|
||||||
/* Ugh, this is a gross hack. I used to use
|
/* Ugh, this is a gross hack. I used to use
|
||||||
@ -279,11 +411,18 @@ LT_EQUAL <=
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#.*\n { /* Comment - ignore */
|
#include/.*\r?\n { /* include */
|
||||||
|
PDEBUG("Matched #include\n");
|
||||||
current_lineno++;
|
current_lineno++;
|
||||||
PDEBUG("Line no++: %d\n", current_lineno);
|
BEGIN(INCLUDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#.*\r?\n { /* normal comment */
|
||||||
|
PDEBUG("comment(%d): %s\n", current_lineno, yytext);
|
||||||
|
current_lineno++;
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
|
||||||
{END_OF_RULE} { return TOK_END_OF_RULE; }
|
{END_OF_RULE} { return TOK_END_OF_RULE; }
|
||||||
|
|
||||||
{SEPERATOR} {
|
{SEPERATOR} {
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
#define PCRE "pattern=pcre"
|
#define PCRE "pattern=pcre"
|
||||||
#define AADFA "pattern=aadfa"
|
#define AADFA "pattern=aadfa"
|
||||||
|
|
||||||
#define UNPRIVILEGED_OPS (debug || preprocess_only || option == OPTION_STDOUT || names_only || \
|
#define UNPRIVILEGED_OPS (debug || option == OPTION_STDOUT || names_only || \
|
||||||
dump_vars || dump_expanded_vars)
|
dump_vars || dump_expanded_vars)
|
||||||
|
|
||||||
const char *parser_title = "Novell/SUSE AppArmor parser";
|
const char *parser_title = "Novell/SUSE AppArmor parser";
|
||||||
@ -57,7 +57,7 @@ const char *parser_copyright = "Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006
|
|||||||
|
|
||||||
char *progname;
|
char *progname;
|
||||||
int option = OPTION_ADD;
|
int option = OPTION_ADD;
|
||||||
int force_complain = 0;
|
int opt_force_complain = 0;
|
||||||
int binary_input = 0;
|
int binary_input = 0;
|
||||||
int names_only = 0;
|
int names_only = 0;
|
||||||
int dump_vars = 0;
|
int dump_vars = 0;
|
||||||
@ -70,16 +70,18 @@ int read_implies_exec = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *subdomainbase = NULL;
|
char *subdomainbase = NULL;
|
||||||
char *profilename;
|
|
||||||
char *match_string = NULL;
|
char *match_string = NULL;
|
||||||
char *flags_string = NULL;
|
char *flags_string = NULL;
|
||||||
int regex_type = AARE_DFA;
|
int regex_type = AARE_DFA;
|
||||||
char *profile_namespace = NULL;
|
char *profile_namespace = NULL;
|
||||||
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
|
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
|
||||||
|
|
||||||
|
|
||||||
extern int current_lineno;
|
extern int current_lineno;
|
||||||
|
|
||||||
|
/* per-profile settings */
|
||||||
|
int force_complain = 0;
|
||||||
|
char *profilename = NULL;
|
||||||
|
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{"add", 0, 0, 'a'},
|
{"add", 0, 0, 'a'},
|
||||||
{"binary", 0, 0, 'B'},
|
{"binary", 0, 0, 'B'},
|
||||||
@ -90,7 +92,6 @@ struct option long_options[] = {
|
|||||||
{"replace", 0, 0, 'r'},
|
{"replace", 0, 0, 'r'},
|
||||||
{"reload", 0, 0, 'r'}, /* undocumented reload option == replace */
|
{"reload", 0, 0, 'r'}, /* undocumented reload option == replace */
|
||||||
{"version", 0, 0, 'v'},
|
{"version", 0, 0, 'v'},
|
||||||
{"preprocess", 0, 0, 'p'},
|
|
||||||
{"complain", 0, 0, 'C'},
|
{"complain", 0, 0, 'C'},
|
||||||
{"Complain", 0, 0, 'C'}, /* Erk, apparently documented as --Complain */
|
{"Complain", 0, 0, 'C'}, /* Erk, apparently documented as --Complain */
|
||||||
{"dump-variables", 0, 0, 'D'},
|
{"dump-variables", 0, 0, 'D'},
|
||||||
@ -125,7 +126,6 @@ static void display_usage(char *command)
|
|||||||
"-R, --remove Remove apparmor definitions\n"
|
"-R, --remove Remove apparmor definitions\n"
|
||||||
"-C, --Complain Force the profile into complain mode\n"
|
"-C, --Complain Force the profile into complain mode\n"
|
||||||
"-B, --binary Input is precompiled profile\n"
|
"-B, --binary Input is precompiled profile\n"
|
||||||
"-p, --preprocess Dump profiles with includes expanded\n"
|
|
||||||
"-N, --names Dump names of profiles in input.\n"
|
"-N, --names Dump names of profiles in input.\n"
|
||||||
"-S, --stdout Dump compiled profile to stdout\n"
|
"-S, --stdout Dump compiled profile to stdout\n"
|
||||||
"-b n, --base n Set base dir and cwd\n"
|
"-b n, --base n Set base dir and cwd\n"
|
||||||
@ -199,10 +199,6 @@ static int process_args(int argc, char *argv[])
|
|||||||
display_version();
|
display_version();
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
|
||||||
count++;
|
|
||||||
preprocess_only = 1;
|
|
||||||
break;
|
|
||||||
case 'I':
|
case 'I':
|
||||||
add_search_dir(optarg);
|
add_search_dir(optarg);
|
||||||
break;
|
break;
|
||||||
@ -213,7 +209,7 @@ static int process_args(int argc, char *argv[])
|
|||||||
binary_input =1;
|
binary_input =1;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
force_complain = 1;
|
opt_force_complain = 1;
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
names_only = 1;
|
names_only = 1;
|
||||||
@ -251,27 +247,14 @@ static int process_args(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
PERROR("%s: Too many options given on the command line.\n",
|
PERROR("%s: Too many actions given on the command line.\n",
|
||||||
progname);
|
progname);
|
||||||
goto abort;
|
display_usage(progname);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDEBUG("optind = %d argc = %d\n", optind, argc);
|
PDEBUG("optind = %d argc = %d\n", optind, argc);
|
||||||
if (optind < argc) {
|
return optind;
|
||||||
/* we only support one profile at a time */
|
|
||||||
if (argc - optind == 1) {
|
|
||||||
PDEBUG("Using profile in '%s'\n", argv[optind]);
|
|
||||||
profilename = strndup(argv[optind], PATH_MAX);
|
|
||||||
} else {
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return option;
|
|
||||||
|
|
||||||
abort:
|
|
||||||
display_usage(progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *try_subdomainfs_mountpoint(const char *mntpnt,
|
static inline char *try_subdomainfs_mountpoint(const char *mntpnt,
|
||||||
@ -490,16 +473,83 @@ int process_binary(int option, char *profilename)
|
|||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
|
if (!conf_quiet) {
|
||||||
|
switch (option) {
|
||||||
|
case OPTION_ADD:
|
||||||
|
printf(_("Cached load succeeded for \"%s\".\n"),
|
||||||
|
profilename ? profilename : "stdin");
|
||||||
|
break;
|
||||||
|
case OPTION_REPLACE:
|
||||||
|
printf(_("Cached reload succeeded for \"%s\".\n"),
|
||||||
|
profilename ? profilename : "stdin");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset_parser(void)
|
||||||
|
{
|
||||||
|
free_aliases();
|
||||||
|
free_symtabs();
|
||||||
|
free_policies();
|
||||||
|
reset_regex();
|
||||||
|
}
|
||||||
|
|
||||||
int process_profile(int option, char *profilename)
|
int process_profile(int option, char *profilename)
|
||||||
{
|
{
|
||||||
|
struct stat stat_text;
|
||||||
|
struct stat stat_bin;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
retval = do_include_preprocessing(profilename);
|
/* per-profile states */
|
||||||
if (preprocess_only || retval != 0)
|
force_complain = opt_force_complain;
|
||||||
return retval;
|
|
||||||
|
if ( profilename ) {
|
||||||
|
if ( !(yyin = fopen(profilename, "r")) ) {
|
||||||
|
PERROR(_("Error: Could not read profile %s: %s.\n"),
|
||||||
|
profilename, strerror(errno));
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PERROR("%s: cannot disable or force-complain via stdin\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( profilename && option != OPTION_REMOVE ) {
|
||||||
|
/* make decisions about disabled or complain-mode profiles */
|
||||||
|
char *target = NULL;
|
||||||
|
char *basename = strrchr(profilename, '/');
|
||||||
|
if (basename) basename++;
|
||||||
|
else basename = profilename;
|
||||||
|
|
||||||
|
if (asprintf(&target, "%s/%s/%s", basedir, "disable", basename)<0) {
|
||||||
|
perror("asprintf");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (access(target, R_OK) == 0) {
|
||||||
|
PERROR("Skipped: %s\n", target);
|
||||||
|
free(target);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
free(target);
|
||||||
|
|
||||||
|
if (asprintf(&target, "%s/%s/%s", basedir, "force-complain", basename)<0) {
|
||||||
|
perror("asprintf");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (access(target, R_OK) == 0) {
|
||||||
|
PERROR("Warning: found %s, forcing complain mode\n", target);
|
||||||
|
force_complain = 1;
|
||||||
|
}
|
||||||
|
free(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yyin) yyrestart(yyin);
|
||||||
|
reset_parser();
|
||||||
|
|
||||||
retval = yyparse();
|
retval = yyparse();
|
||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
@ -517,7 +567,7 @@ int process_profile(int option, char *profilename)
|
|||||||
retval = post_process_policy();
|
retval = post_process_policy();
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
|
PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
|
||||||
return retval;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump_vars) {
|
if (dump_vars) {
|
||||||
@ -550,14 +600,15 @@ out:
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
int option;
|
int i;
|
||||||
|
int optind;
|
||||||
|
|
||||||
/* name of executable, for error reporting and usage display */
|
/* name of executable, for error reporting and usage display */
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
init_base_dir();
|
init_base_dir();
|
||||||
|
|
||||||
option = process_args(argc, argv);
|
optind = process_args(argc, argv);
|
||||||
|
|
||||||
setlocale(LC_MESSAGES, "");
|
setlocale(LC_MESSAGES, "");
|
||||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
@ -575,11 +626,26 @@ int main(int argc, char *argv[])
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binary_input) {
|
if (!binary_input) parse_default_paths();
|
||||||
retval = process_binary(option, profilename);
|
|
||||||
} else {
|
retval = 0;
|
||||||
parse_default_paths();
|
for (i = optind; retval == 0 && i <= argc; i++) {
|
||||||
retval = process_profile(option, profilename);
|
if (i < argc && !(profilename = strdup(argv[i]))) {
|
||||||
|
perror("strdup");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* skip stdin if we've seen other command line arguments */
|
||||||
|
if (i == argc && optind != argc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (binary_input) {
|
||||||
|
retval = process_binary(option, profilename);
|
||||||
|
} else {
|
||||||
|
retval = process_profile(option, profilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profilename) free(profilename);
|
||||||
|
profilename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user