Security Enhanced Linux
What's New
Frequently Asked Questions
Background
Documents
License
Download
Participating
Mail List
Archives
Remaining Work
Contributors
Related Work
Press Releases
Information Assurance Research
NIARL In-house Research Areas
Mathematical Sciences Program
Sabbaticals
Computer & Information Sciences Research
Technology Transfer
Advanced Computing
Advanced Mathematics
Communications & Networking
Information Processing
Microelectronics
Other Technologies
Technology Fact Sheets
Publications
Related Links
|
SELinux Mailing List
subject: rule analyzer Date: Fri, 18 Oct 2002 11:50:49 -0600
It is primative, but it gets the job done. In a nutshell, it shows what can access what. (doesn't show type_transitions or anything else yet). I've been using it for awhile, but figured I should spruce it up a bit, throw it out there, and get some feedback. If it's used there are a few things I wouldn't mind adding (see todo list). Feedback and comments are welcome. Here are a few examples. (the name of the program is cando - as in what "cando" what). "..." added for readability.
################################### user_gpg_secret_t dir { rename create write getattr remove_name... } file { rename create write getattr ioctl append... } user_gpg_t user_gpg_secret_t dir { rename create write getattr remove_name... } user_t user_gpg_secret_t dir { write getattr remove_name search setattr read... } file { getattr } cando --src=user_t --dst=var.* user_t var_lib_nfs_t dir { read lock access getattr ioctl search poll } var_lib_rpm_t dir { read lock access getattr ioctl search poll } var_lib_t dir { read lock access getattr ioctl search poll } var_lock_t dir { read lock access getattr ioctl search poll } var_log_sa_t dir { read lock access getattr ioctl search poll } var_log_t dir { read lock access getattr ioctl search poll } var_run_t dir { read lock access getattr ioctl search poll } var_spool_t dir { read lock access getattr ioctl search poll } var_t dir { read lock access getattr ioctl search poll } var_yp_t dir { read lock access getattr ioctl search poll } cando --src=bootloader_t --dst=boot -d bootloader_t boot_t dir { write getattr remove_name search read... bootloader_exec_t file { getattr ioctl read execute lock... bootloader_tmp_t dir { rename create write getattr remove_name... etc_bootloader_t file { getattr ioctl read lock access poll } (-s means short -a means align) cando --src=httpd --dst=^user -sa allow httpd_t user_home_t: dir { search }; allow httpd_t user_home_t: file { read getattr }; allow httpd_user_script_process_t user_home_t: dir { getattr search }; allow httpd_user_script_process_t user_t: fd { use }; allow httpd_user_script_process_t user_t: fifo_file { write getattr ... }; allow httpd_user_script_process_t user_t: process { sigchld }; cando --dst=bin_t --class=file --perm=execute --l=1 this will show all of the domains that can execute a file of type bin_t -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message.From: Brian Fegler <fegler_at_bigfoot.com> subject: Re: rule analyzer Date: Fri, 18 Oct 2002 12:20:25 -0600
I've included it as an attachment and in the email body.
############################################
# Author: Brian Fegler (brianfegler@bigfoot.com) $| = 1;
##################################################### my $pfile = "/usr/src/selinux/policy/policy.conf";
#May not use this, keeping in here for now.
#List of source and destinations the user is
#set to one if the user wants to only match exact names
#if set to one there will be a short printout
#if set to one the permissions will be alligned when applicable
#this sets the width of a tab (useful for changing width of tabs when used)
#determines how many levels deep to print the rule set
#Make sure all exits call this incase I ever want the
##################################################### if($ARGV[$i] =~ /^-\w{2,}$/){ my @temp = split("",$ARGV[$i]); shift @temp; #get rid of leading - $_ = "-$_" foreach(@temp); #slap a - on each element splice(@ARGV,$i,1,@temp); #put switches back in $i+=$#temp; #don't read what you just put in} } foreach(@ARGV) { if(/^--help$/){
&help; killme();
&short_help; killme();
elsif(/^--todo$/){
&todo; killme();
print "$version\n"; killme(); } elsif(/^--src=/){
push @src, split(",",$');
push @dst, split(",",$');
push @class, split(",",$');
push @perm, split(",",$');
elsif(/^-f$/ || /^--full-name$/){
$full_name = 1;
elsif(/^--pfile=/){
$pfile = $';
#print options
$short_print_out = 1;
$align = 1;
$tab = " " x $1;
elsif(/^--l=(1|2|3|4)$/){ my $start = $1; if($start!=4){ $start++;} else{ next;} for($start .. 4){ $l{$_} = 0; } } #don't know if i'll use these #i don't thing they benefit speed in any way #elsif(/^-keep=/){ # push @keep, split(",",$'); #}elsif(/^-toss=/){ # push @toss, split(",",$'); #}
#used for general purpose debugging
foreach(split("",$')){ $ENV{"_d$_"}=1; } } else{ print "$_ is an unrecognized option\n"; killme(); } }#end - foreach(@ARGV)if(!-r $pfile){
print STDERR "can't read policy file: $pfile\n";
killme();
#what gets defined
#{source}{dest}{class} = LIST my %transitions; open(FILE, "<$pfile") or die "couldn't open $pfile: $!\n"; LINE: while(my $line=<FILE>){
chomp $line;
#not sure what'll I'll be using this for #just though I'd keep my options open my @temp = split(/ /, $line); @temp = split(/,|, /, $temp[1]); $defined{$temp[0]}=1; } elsif($line =~ /^allow /){ #TODO #try this at different locations in the program #to see where the most speed is gained #if(@keep and !doesExpMatchList($line,\@keep)){ # next LINE; #}elsif(@toss and doesExpMatchList($line,\@toss)){ # next LINE; #} #used for debugging #if($line !~ /kde_t/){next LINE;} #if($line !~ /user_gpg/){next LINE;} #i've left the print "$line\n"; in there for future debugging #i should try doing a single level hash, this might make # the code a little bit shorter, (cleaner?) #this could be tested with out deleting code, i suppose #test for speed if($line =~ /^allow\s*((\w*)|{(.*)})\s*((\w*)|{(.*)})(\s*:\s*)((\w*)|{(.*)})\s*((\w*)|{(.*)})\s*;/){ #print "1=($1) 2=($2) 3=($3) 4=($4) 5=($5) 6=($6) 7=($7) 8=($8) 9=($9) 10=($10) 11=($11) 12=($12) 13=($13)\n"; my $one = $1||$2||$3; my $two = $4||$5||$6; #: is 7 my $three = $8||$9||$10; my $four = $11||$12||$13; foreach my $src ( getAtoms($one) ){ foreach my $dst ( getAtoms($two) ){ foreach my $class ( getAtoms($three) ){ #push @{$rules{$src}{$dst}{$class}}, getAtoms($four); addRule($src,$dst,$class,getAtoms($four)); } } } }elsif($line =~ /^allow (\w*)\s*(\w*):(\w*) (\*|\~.*);$/){ #allow * *:* \* #allow * *:* ~* #push @{$rules{$1}{$2}{$3}}, "*"; addRule($1,$2,$3,getAtoms($4)); }elsif($line =~ /^allow \w* \w*;$/){ #should i do anything with these? }elsif($line =~ /^allow /){ #should i toggle this on or off with a switch? #print print "ignoring: $line\n"; next LINE; } }#end - elsif($line =~ /^allow /) #not sure how I'll implement this. # elsif($line =~ /^type_trans/){ # if($line =~ /^type_transition\s*((\w*)|{(.*)})\s*((\w*)|{(.*)})(\s*:\s*)((\w*)|{(.*)})\s*((\w*)|{(.*)})\s*;/){ # #print "1=($1) 2=($2) 3=($3) 4=($4) 5=($5) 6=($6) 7=($7) 8=($8) 9=($9) 10=($10) 11=($11) 12=($12) 13=($13)\n"; # my $one = $1||$2||$3; # my $two = $4||$5||$6; # #: is 7 # my $three = $8||$9||$10; # my $four = $11||$12||$13; # # }else{ # print "ignoring: $line\n"; # } # } # elsif($line =~ /^role /){ # # }elsif($line =~ /^dontaudit /){ # # }elsif($line =~ /^auditallow /){ # # }elsif($line =~ /^type_change /){ # # }elsif($line =~ /^\s*neverallow /){ # # }elsif($line =~ /^user /){ # # }elsif($line =~ /^attribute /){ # # } # else { # if($line !~ /^#|^$/){ # print "$line\n"; # } # }
}#end - while(my $line=<FILE>)
#keeping only unique permissions foreach my $dst (sort keys %{$rules{$src}}){ foreach my $class (sort keys %{$rules{$src}{$dst}}){ my %perms; PERM: foreach my $perm (@{$rules{$src}{$dst}{$class}}){ $perms{$perm}=1; } @{$rules{$src}{$dst}{$class}} = keys %perms; }#end - class loop }#end - dst loop }#end - src loop
################################################################
my %lists;
#1. collect all of the uniq src, dst and class #2. determin the widest src, dst and class SRC: foreach my $src (sort keys %rules){ $lists{src}{$src}=1; DST: foreach my $dst (sort keys %{$rules{$src}}){ $lists{dst}{$dst}=1; foreach my $class (sort keys %{$rules{$src}{$dst}}) { $lists{class}{$class}=1; } } }#end - SRC:
#these are global values
sub longest { #used only with in the scope of this block of code my ($item) = @_; my $longest = 0; for my $atom (keys %{$lists{$item}}){ my $length = length $atom; if($length > $longest){ $longest = $length; } } return $longest }#end - sbu longest }#end - if($align) if($short_print_out){ #because this print out puts a ":" after the dst #i am incrementing $wdst, I don't know if future print outs #will need this, so I'm just doing it here$wdst++; #print join("-",sort keys %rules) . "\n"; SRC: foreach my $src (sort keys %rules){ if($l{2}==0){ printf "%-${wsrc}s ", $src; print "\n"; next SRC; } DST: foreach my $dst (sort keys %{$rules{$src}}){ if($l{3}==0){ printf "%-${wsrc}s ", $src; printf "%-${wdst}s ", "$dst:"; print "\n"; next SRC; } CLASS: foreach my $class (sort keys %{$rules{$src}{$dst}}) { if($l{4}==1){print "allow ";} printf "%-${wsrc}s ", $src; printf "%-${wdst}s ", "$dst:"; printf "%-${wclass}s ", $class; if($l{4}==0){ print "\n"; next SRC; } print "{ @{$rules{$src}{$dst}{$class}} };\n"; } } }#end - SRC: killme(); }#end - if($short_print_out)
#printing out the rules
print "$src\n";
print "$tab$dst\n"; CLASS: foreach my $class (sort keys %{$rules{$src}{$dst}}) { print "$tab$tab"; printf "%-12s ", $class; if($l{4}==0){ print "\n"; next CLASS; } print "{ @{$rules{$src}{$dst}{$class}} }\n"; } }#end - DST: #only print out a new line if you are displaying # at least two levels deep #if you aren't displaying at least two levels deep # you are just displaying the src, so need for a double \nprint "\n" unless($l{2}==0); }#end - SRC:
killme();
sub addRule { #INPUT # $scalar: source # $scalar: destination # $scalar: class # $array: list of permission #RETURN # undef #DESCRIPTION # determines if this rule should be added to the rule set # if at anyone time it determines that it shouldn't it # returns with out adding it # if the rule should be added, it'll be done, and the program # will return my($src,$dst,$class,@these_perms) = @_; if(@src and !doesExpMatchList($src,\@src)){ return; } if(@dst and !doesExpMatchList($dst,\@dst)){ return; } if(@class and !doesExpMatchList($class,\@class)){ return; } if(@perm){ #if no permissions were selected don't bother with this my @keep_these_perm; PERM: foreach my $perm (@these_perms){ if(doesExpMatchList($perm,\@perm)){ push @keep_these_perm, $perm; } } if(!@keep_these_perm){ return; } @these_perms = @keep_these_perm;} if($l{4}){ push @{$rules{$src}{$dst}{$class}}, @these_perms; }elsif($l{3}){ @{$rules{$src}{$dst}{$class}} = (); }elsif($l{2}){
$rules{$src}{$dst} = undef;
$rules{$src} = undef;
return;
sub getAtoms { #INPUT # $scalar: a string coming from inside {}'s # It doesn't matter if there are embedded {}'s #RETURN # @array: the list of strings (not including {}'s) found # within the top {}'s my $list = shift; $list =~ s/{|}//g; return split(" ", $list); }#end - sub getAtoms sub doesExpMatchList { #INPUT # $scalar: the string you want to look for in the list # @array: list of reg exps you want to compare the scalar to # the list will be used as is, (as in it will not be # converted from a user reg exp to a perl reg expt #RETURN # 1 if a match occurred # 0 if no match found #DESCRIPTION # give it a string and a list of regular expressions # if the string matches any one reg exp return 1 # other wise return 0 # this is CASE INSENSITIVE #MISC # Uses the global variable "$full_name" to determine if # exact matches are required. my ($string,$l) = @_; foreach my $try(@{$l}){ if(!$full_name && $string =~ /$try/i){ return 1; } if( $full_name && $string =~ /^$try$/){ return 1; }} return 0; }#end - sub doesExpMatchList sub intersection { #INPUT: # two references to arrays #RETURN # 1 if any one element in the first array # matches any one element in the second array, using # the list compare that the rest of the program uses my ($first, $second) = @_; for my $f (@{$first}){ if(doesExpMatchList($f, \@{$second})){ return 1; } } }#end - sub intersection
sub todo {
";
sub short_help {
Displays SELinux rules. --src=LIST List of sources to display. --dst=LIST List of destinations to select from. --class=LIST List of classes to select from. --perm=LIST List of permissions to select from. -f,--full-name Match complete names only. --pfile=FILE Specify a policy file. -s, --short Condense the print out. -a, --align Aligns colums when applicable. --tab=INTEGER Sets width of tabs. --l=(1|2|3|4) Level of info you want to see. --todo Show the TODO list. -h Displays this screen. --help Displays full version of help. --version Prints version and exits.
";
sub help {
DESCRIPTION
Each LIST is made up of one or more comma separated strings. By default the compares of lists are case insensative and any match of any element is successful. \"-f\" or \"--full-name\" requires exact matches. This help file's nomenclature: allow source destination:class permissions abbreviated: allow src dst:class permissions As of this version ($version), backwards compatability is completely disregared, and not thought of for each subsequent release.
OPTIONS
Aligns colums when applicable. --dst=LIST Will keep only rules that interact with any destination in the supplied list. --class=LIST Will keep only rules that interact with any class in the supplied list. -f, --full-name When comparing a string to a list the full string will have match, including case. -h Display short help. --help Displays this help screen. --l=(1|2|3|4) How much info you want to see. src==1, dst==2, class=3, Perm=4. This is useful if all you want to see is the sources that can exececute bin_t files. Example: \"cando --dst=bin_t --perm=execute -s --l=1\" --perm=LIST List of permissions you'd like to see. --pfile=FILE Use a supplied file name instead of the default. Default: $pfile -s, --short Condense the print out. --scr=LIST Will keep all rules who's source in in LIST. --tab=INTEGER Sets width of tabs. --todo Display the TODO list for this program. --version Prints version and exits.
EXAMPLES
cando --src=rpm_t Shows all rules for rpm_tmpfs_t and rpm_t. cando --src=rpm_t -f Shows all the rules for rpm_t. cando --src=rpm_t --dst=tmpfs_t Shows: what rpm_tmpfs_t can do to tmpfs_t what rpm_t can do to tmpfs_t and rpm_tmpfs_t cando --src=rpm_t --dst=tmpfs_t -f Shows what rpm_t can do to tmpfs_t. cando --dst=user_gpg_secret_t Shows all sources that can do anything to a destination that mathes \"user_gpg_secret_t\". cando --dst=user_gpg_t Shows all sources that can do anything with the user_gpg_t type. cando --dst=gpg --perm=execute -sa Shows every domain that can execute any \"gpg\" type. The output is shortened (-s), and aligned (-a). cando --src=httpd --dst=^user Shows what any httpd domain can do to any domain that starts with user
AUTHOR
";
#############################################
-- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message.From: Russell Coker <russell_at_coker.com.au> subject: Re: rule analyzer Date: Fri, 18 Oct 2002 22:19:17 +0200
I've just had a quick play with it. It looks very promising. I have a few suggestions, firstly have a configuration file for the location of the policy.conf file and other configuration files. Next it would be good to parse the global_macros.te file and replace the permissions with rw_file_perms and other macros as appropriate. For displaying the output, it might be handy to use the same ordering as in access_vectors... -- http://www.coker.com.au/selinux/ My NSA Security Enhanced Linux packages http://www.coker.com.au/bonnie++/ Bonnie++ hard drive benchmark http://www.coker.com.au/postal/ Postal SMTP/POP benchmark http://www.coker.com.au/~russell/ My home page -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message.
|
|
Date Posted: Jan 15, 2009 | Last Modified: Jan 15, 2009 | Last Reviewed: Jan 15, 2009 |