ia64/xen-unstable

view tools/security/labelfuncs.sh @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 8aac8746047b
children 909664b50602
line source
1 # *
2 # * labelfuncs.sh
3 # *
4 # * Copyright (C) 2005 IBM Corporation
5 # *
6 # * Authors:
7 # * Stefan Berger <stefanb@us.ibm.com>
8 # *
9 # * This program is free software; you can redistribute it and/or
10 # * modify it under the terms of the GNU General Public License as
11 # * published by the Free Software Foundation, version 2 of the
12 # * License.
13 # *
14 # *
15 # * A collection of functions to handle polcies, mapfiles,
16 # * and ssidrefs.
17 #
20 #Some global variables for tools using this module
21 ACM_DEFAULT_ROOT="/etc/xen/acm-security"
23 # Set the policy and policydir variables
24 # Parameters:
25 # 1st : possible policy name
26 # 2nd : possible policy directory
27 # Results:
28 # The variables policy and policydir will hold the values for locating
29 # policy information
30 # If there are no errors, the functions returns a '1',
31 # a '0' otherwise.
32 setPolicyVars ()
33 {
34 local ret
35 # Set default values
36 policydir="$ACM_DEFAULT_ROOT/policies"
37 policy=""
39 if [ "$1" == "" ]; then
40 findGrubConf
41 ret=$?
42 if [ $ret -eq 0 ]; then
43 echo "Could not find grub.conf."
44 return 0;
45 fi
46 findPolicyInGrub $grubconf
47 if [ "$policy" == "" ]; then
48 echo "Could not find policy in grub.conf. Looked for entry using kernel $linux."
49 return 0;
50 fi
51 echo "Assuming policy to be '$policy'.";
52 else
53 policy=$1
54 if [ "$2" != "" ]; then
55 policydir=$2
56 fi
57 fi
59 return 1
60 }
62 # Find the mapfile given a policy nmame
63 # Parameters:
64 # 1st : the name of the policy whose map file is to be found, i.e.,
65 # chwall
66 # 2nd : the policy directory for locating the map file
67 # Results:
68 # The variable mapfile will hold the realtive path to the mapfile
69 # for the given policy.
70 # In case the mapfile could be found, the functions returns a '1',
71 # a '0' otherwise.
72 findMapFile ()
73 {
74 mapfile="$2/$1/$1.map"
75 if [ -r "$mapfile" ]; then
76 return 1
77 fi
78 return 0
79 }
82 # Determine the name of the primary policy
83 # Parameters
84 # 1st : the path to the mapfile; the path may be relative
85 # to the current directory
86 # Results
87 # The variable primary will hold the name of the primary policy
88 getPrimaryPolicy ()
89 {
90 local mapfile=$1
91 primary=`cat $mapfile | \
92 awk ' \
93 { \
94 if ( $1 == "PRIMARY" ) { \
95 res=$2; \
96 } \
97 } END { \
98 print res; \
99 } '`
100 }
103 # Determine the name of the secondary policy
104 # Parameters
105 # 1st : the path to the mapfile; the path may be relative
106 # to the current directory
107 # Results
108 # The variable secondary will hold the name of the secondary policy
109 getSecondaryPolicy ()
110 {
111 local mapfile=$1
112 secondary=`cat $mapfile | \
113 awk ' \
114 { \
115 if ( $1 == "SECONDARY" ) { \
116 res=$2; \
117 } \
118 } END { \
119 print res; \
120 } '`
121 }
124 #Return where the grub.conf file is.
125 #I only know of one place it can be.
126 #Returns:
127 # 1 : if the file is writeable and readable
128 # 2 : if the file is only readable
129 # 0 : if the file does not exist
130 findGrubConf()
131 {
132 grubconf="/boot/grub/grub.conf"
133 if [ -w $grubconf ]; then
134 return 1
135 fi
136 if [ -r $grubconf ]; then
137 return 2
138 fi
139 return 0
140 }
143 # This function sets the global variable 'linux'
144 # to the name and version of the Linux kernel that was compiled
145 # for domain 0.
146 # If this variable could not be found, the variable 'linux'
147 # will hold a pattern
148 # Parameters:
149 # 1st: the path to reach the root directory of the XEN build tree
150 # where linux-*-xen0 is located at
151 # Results:
152 # The variable linux holds then name and version of the compiled
153 # kernel, i.e., 'vmlinuz-2.6.12-xen0'
154 getLinuxVersion ()
155 {
156 local path
157 local versionfile
158 local lnx
159 if [ "$1" == "" ]; then
160 path="/lib/modules/*-xen0"
161 else
162 path="/lib/modules/$1"
163 fi
165 linux=""
166 for f in $path/linux-*-xen0 ; do
167 versionfile=$f/build/include/linux/version.h
168 if [ -r $versionfile ]; then
169 lnx=`cat $versionfile | \
170 grep UTS_RELEASE | \
171 awk '{ \
172 len=length($3); \
173 version=substr($3,2,len-2); \
174 split(version,numbers,"."); \
175 if (numbers[4]=="") { \
176 printf("%s.%s.%s", \
177 numbers[1], \
178 numbers[2], \
179 numbers[3]); \
180 } else { \
181 printf("%s.%s.%s[.0-9]*-xen0",\
182 numbers[1], \
183 numbers[2], \
184 numbers[3]); \
185 } \
186 }'`
187 fi
188 if [ "$lnx" != "" ]; then
189 linux="[./0-9a-zA-z]*$lnx"
190 return;
191 fi
192 done
194 #Last resort.
195 linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$"
196 }
199 # Find out with which policy the hypervisor was booted with.
200 # Parameters
201 # 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf
202 # Result:
203 # Sets the variable 'policy' to the name of the policy
204 findPolicyInGrub ()
205 {
206 local grubconf=$1
207 local linux=`uname -r`
208 policy=`cat $grubconf | \
209 awk -vlinux=$linux '{ \
210 if ( $1 == "title" ) { \
211 kernelfound = 0; \
212 policymaycome = 0; \
213 } \
214 else if ( $1 == "kernel" ) { \
215 if ( match($2,"xen.gz$") ) { \
216 pathlen=RSTART; \
217 kernelfound = 1; \
218 } \
219 } \
220 else if ( $1 == "module" && \
221 kernelfound == 1 && \
222 match($2,linux) ) { \
223 policymaycome = 1; \
224 } \
225 else if ( $1 == "module" && \
226 kernelfound == 1 && \
227 policymaycome == 1 && \
228 match($2,"[0-9a-zA-Z_]*.bin$") ) { \
229 policymaycome = 0; \
230 kernelfound = 0; \
231 polname = substr($2,pathlen); \
232 len=length(polname); \
233 polname = substr(polname,0,len-4); \
234 } \
235 } END { \
236 print polname \
237 }'`
238 }
241 # Get the SSID of a domain
242 # Parameters:
243 # 1st : domain ID, i.e. '1'
244 # Results
245 # If the ssid could be found, the variable 'ssid' will hold
246 # the currently used ssid in the hex format, i.e., '0x00010001'.
247 # The funtion returns '1' on success, '0' on failure
248 getSSIDUsingSecpolTool ()
249 {
250 local domid=$1
251 export PATH=$PATH:.
252 ssid=`xensec_tool getssid -d $domid -f | \
253 grep -E "SSID:" | \
254 awk '{ print $4 }'`
256 if [ "$ssid" != "" ]; then
257 return 1
258 fi
259 return 0
260 }
263 # Break the ssid identifier into its high and low values,
264 # which are equal to the secondary and primary policy references.
265 # Parameters:
266 # 1st: ssid to break into high and low value, i.e., '0x00010002'
267 # Results:
268 # The variable ssidlo_int and ssidhi_int will hold the low and
269 # high ssid values as integers.
270 getSSIDLOHI ()
271 {
272 local ssid=$1
273 ssidlo_int=`echo $ssid | awk \
274 '{ \
275 len=length($0); \
276 beg=substr($0,1,2); \
277 if ( beg == "0x" ) { \
278 dig = len - 2; \
279 if (dig <= 0) { \
280 exit; \
281 } \
282 if (dig > 4) { \
283 dig=4; \
284 } \
285 lo=sprintf("0x%s",substr($0,len-dig+1,dig)); \
286 print strtonum(lo);\
287 } else { \
288 lo=strtonum($0); \
289 if (lo < 65536) { \
290 print lo; \
291 } else { \
292 hi=lo; \
293 hi2= (hi / 65536);\
294 hi2_str=sprintf("%d",hi2); \
295 hi2=strtonum(hi2_str);\
296 lo=hi-(hi2*65536); \
297 printf("%d",lo); \
298 } \
299 } \
300 }'`
301 ssidhi_int=`echo $ssid | awk \
302 '{ \
303 len=length($0); \
304 beg=substr($0,1,2); \
305 if ( beg == "0x" ) { \
306 dig = len - 2; \
307 if (dig <= 0 || \
308 dig > 8) { \
309 exit; \
310 } \
311 if (dig < 4) { \
312 print 0; \
313 exit; \
314 } \
315 dig -= 4; \
316 hi=sprintf("0x%s",substr($0,len-4-dig+1,dig)); \
317 print strtonum(hi);\
318 } else { \
319 hi=strtonum($0); \
320 if (hi >= 65536) { \
321 hi = hi / 65536; \
322 printf ("%d",hi);\
323 } else { \
324 printf ("0"); \
325 } \
326 } \
327 }'`
328 if [ "$ssidhi_int" == "" -o \
329 "$ssidlo_int" == "" ]; then
330 return 0;
331 fi
332 return 1
333 }
336 #Update the grub configuration file.
337 #Search for existing entries and replace the current
338 #policy entry with the policy passed to this script
339 #
340 #Arguments passed to this function
341 # 1st : the grub configuration file with full path
342 # 2nd : the binary policy file name, i.e. chwall.bin
343 # 3rd : the name or pattern of the linux kernel name to match
344 # (this determines where the module entry will be made)
345 #
346 # The algorithm here is based on pattern matching
347 # and is working correctly if
348 # - under a title a line beginning with 'kernel' is found
349 # whose following item ends with "xen.gz"
350 # Example: kernel /xen.gz dom0_mem=....
351 # - a module line matching the 3rd parameter is found
352 #
353 updateGrub ()
354 {
355 local grubconf=$1
356 local policyfile=$2
357 local linux=$3
359 local tmpfile="/tmp/new_grub.conf"
361 cat $grubconf | \
362 awk -vpolicy=$policyfile \
363 -vlinux=$linux '{ \
364 if ( $1 == "title" ) { \
365 kernelfound = 0; \
366 if ( policymaycome == 1 ){ \
367 printf ("\tmodule %s%s\n", path, policy); \
368 } \
369 policymaycome = 0; \
370 } \
371 else if ( $1 == "kernel" ) { \
372 if ( match($2,"xen.gz$") ) { \
373 path=substr($2,1,RSTART-1); \
374 kernelfound = 1; \
375 } \
376 } \
377 else if ( $1 == "module" && \
378 kernelfound == 1 && \
379 match($2,linux) ) { \
380 policymaycome = 1; \
381 } \
382 else if ( $1 == "module" && \
383 kernelfound == 1 && \
384 policymaycome == 1 && \
385 match($2,"[0-9a-zA-Z]*.bin$") ) { \
386 printf ("\tmodule %s%s\n", path, policy); \
387 policymaycome = 0; \
388 kernelfound = 0; \
389 dontprint = 1; \
390 } \
391 else if ( $1 == "" && \
392 kernelfound == 1 && \
393 policymaycome == 1) { \
394 dontprint = 1; \
395 } \
396 if (dontprint == 0) { \
397 printf ("%s\n", $0); \
398 } \
399 dontprint = 0; \
400 } END { \
401 if ( policymaycome == 1 ) { \
402 printf ("\tmodule %s%s\n", path, policy); \
403 } \
404 }' > $tmpfile
405 if [ ! -r $tmpfile ]; then
406 echo "Could not create temporary file! Aborting."
407 exit -1
408 fi
409 diff $tmpfile $grubconf > /dev/null
410 RES=$?
411 if [ "$RES" == "0" ]; then
412 echo "No changes were made to $grubconf."
413 else
414 echo "Successfully updated $grubconf."
415 mv -f $tmpfile $grubconf
416 fi
417 }
420 #Compile a policy into its binary representation
421 # Parameters:
422 # 1st: The directory where the ./policies directory is located at
423 # 2nd: The name of the policy
424 genBinPolicy ()
425 {
426 local root=$1
427 local policy=$2
428 pushd $root > /dev/null
429 xensec_xml2bin -d policies $policy > /dev/null
430 popd > /dev/null
431 }
434 # Copy the bootpolicy into the destination directory
435 # Generate the policy's .bin and .map files if necessary
436 # Parameters:
437 # 1st: Destination directory
438 # 2nd: The root directory of the security tools; this is where the
439 # policies directory is located at
440 # 3rd: The policy name
441 # Returns '1' on success, '0' on failure.
442 cpBootPolicy ()
443 {
444 local dest=$1
445 local root=$2
446 local policy=$3
447 local binfile=$root/policies/$policy/$policy.bin
448 local dstfile=$dest/$policy.bin
449 if [ ! -e $binfile ]; then
450 genBinPolicy $root $policy
451 if [ ! -e $binfile ]; then
452 echo "Could not compile policy '$policy'."
453 return 0
454 fi
455 fi
457 if [ ! -e $dstfile -o \
458 $binfile -nt $dstfile ]; then
459 cp -f $binfile $dstfile
460 fi
461 return 1
462 }
465 # Display all the labels in a given mapfile
466 # Parameters
467 # 1st: Full or relative path to the policy's mapfile
468 showLabels ()
469 {
470 local mapfile=$1
471 local line
472 local ITEM
473 local found=0
475 if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
476 echo "Cannot read from vm configuration file $vmfile."
477 return -1
478 fi
480 getPrimaryPolicy $mapfile
481 getSecondaryPolicy $mapfile
483 echo "The following labels are available:"
484 let line=1
485 while [ 1 ]; do
486 ITEM=`cat $mapfile | \
487 awk -vline=$line \
488 -vprimary=$primary \
489 '{ \
490 if ($1 == "LABEL->SSID" && \
491 $2 == "VM" && \
492 $3 == primary ) { \
493 ctr++; \
494 if (ctr == line) { \
495 print $4; \
496 } \
497 } \
498 } END { \
499 }'`
501 if [ "$ITEM" == "" ]; then
502 break
503 fi
504 if [ "$secondary" != "NULL" ]; then
505 LABEL=`cat $mapfile | \
506 awk -vitem=$ITEM \
507 '{
508 if ($1 == "LABEL->SSID" && \
509 $2 == "VM" && \
510 $3 == "CHWALL" && \
511 $4 == item ) { \
512 result = item; \
513 } \
514 } END { \
515 print result \
516 }'`
517 else
518 LABEL=$ITEM
519 fi
521 if [ "$LABEL" != "" ]; then
522 echo "$LABEL"
523 found=1
524 fi
525 let line=line+1
526 done
527 if [ "$found" != "1" ]; then
528 echo "No labels found."
529 fi
530 }
533 # Get the default SSID given a mapfile and the policy name
534 # Parameters
535 # 1st: Full or relative path to the policy's mapfile
536 # 2nd: the name of the policy
537 getDefaultSsid ()
538 {
539 local mapfile=$1
540 local pol=$2
541 RES=`cat $mapfile \
542 awk -vpol=$pol \
543 { \
544 if ($1 == "LABEL->SSID" && \
545 $2 == "ANY" && \
546 $3 == pol && \
547 $4 == "DEFAULT" ) {\
548 res=$5; \
549 } \
550 } END { \
551 printf "%04x", strtonum(res) \
552 }'`
553 echo "default NULL mapping is $RES"
554 defaultssid=$RES
555 }
558 #Relabel a VM configuration file
559 # Parameters
560 # 1st: Full or relative path to the VM configuration file
561 # 2nd: The label to translate into an ssidref
562 # 3rd: Full or relative path to the policy's map file
563 # 4th: The mode this function is supposed to operate in:
564 # 'relabel' : Relabels the file without querying the user
565 # other : Prompts the user whether to proceed
566 relabel ()
567 {
568 local vmfile=$1
569 local label=$2
570 local mapfile=$3
571 local mode=$4
572 local SSIDLO
573 local SSIDHI
574 local RES
576 if [ ! -r "$vmfile" ]; then
577 echo "Cannot read from vm configuration file $vmfile."
578 return -1
579 fi
581 if [ ! -w "$vmfile" ]; then
582 echo "Cannot write to vm configuration file $vmfile."
583 return -1
584 fi
586 if [ ! -r "$mapfile" ] ; then
587 echo "Cannot read mapping file $mapfile."
588 return -1
589 fi
591 # Determine which policy is primary, which sec.
592 getPrimaryPolicy $mapfile
593 getSecondaryPolicy $mapfile
595 # Calculate the primary policy's SSIDREF
596 if [ "$primary" == "NULL" ]; then
597 SSIDLO="0001"
598 else
599 SSIDLO=`cat $mapfile | \
600 awk -vlabel=$label \
601 -vprimary=$primary \
602 '{ \
603 if ( $1 == "LABEL->SSID" && \
604 $2 == "VM" && \
605 $3 == primary && \
606 $4 == label ) { \
607 result=$5 \
608 } \
609 } END { \
610 if (result != "" ) \
611 {printf "%04x", strtonum(result)}\
612 }'`
613 fi
615 # Calculate the secondary policy's SSIDREF
616 if [ "$secondary" == "NULL" ]; then
617 if [ "$primary" == "NULL" ]; then
618 SSIDHI="0001"
619 else
620 SSIDHI="0000"
621 fi
622 else
623 SSIDHI=`cat $mapfile | \
624 awk -vlabel=$label \
625 -vsecondary=$secondary \
626 '{ \
627 if ( $1 == "LABEL->SSID" && \
628 $2 == "VM" && \
629 $3 == secondary && \
630 $4 == label ) { \
631 result=$5 \
632 } \
633 } END { \
634 if (result != "" ) \
635 {printf "%04x", strtonum(result)}\
636 }'`
637 fi
639 if [ "$SSIDLO" == "" -o \
640 "$SSIDHI" == "" ]; then
641 echo "Could not map the given label '$label'."
642 return -1
643 fi
645 ACM_POLICY=`cat $mapfile | \
646 awk ' { if ( $1 == "POLICY" ) { \
647 result=$2 \
648 } \
649 } \
650 END { \
651 if (result != "") { \
652 printf result \
653 } \
654 }'`
656 if [ "$ACM_POLICY" == "" ]; then
657 echo "Could not find 'POLICY' entry in map file."
658 return -1
659 fi
661 SSIDREF="0x$SSIDHI$SSIDLO"
663 if [ "$mode" != "relabel" ]; then
664 RES=`cat $vmfile | \
665 awk '{ \
666 if ( substr($1,0,7) == "ssidref" ) {\
667 print $0; \
668 } \
669 }'`
670 if [ "$RES" != "" ]; then
671 echo "Do you want to overwrite the existing mapping ($RES)? (y/N)"
672 read user
673 if [ "$user" != "y" -a "$user" != "Y" ]; then
674 echo "Aborted."
675 return 0
676 fi
677 fi
678 fi
680 #Write the output
681 local vmtmp1="/tmp/__setlabel.tmp1"
682 local vmtmp2="/tmp/__setlabel.tmp2"
683 touch $vmtmp1
684 touch $vmtmp2
685 if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
686 echo "Cannot create temporary files. Aborting."
687 return -1
688 fi
689 RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
690 RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
691 RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
692 echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
693 echo "#ACM_LABEL=$label" >> $vmtmp1
694 echo "ssidref = $SSIDREF" >> $vmtmp1
695 mv -f $vmtmp1 $vmfile
696 rm -rf $vmtmp1 $vmtmp2
697 echo "Mapped label '$label' to ssidref '$SSIDREF'."
698 }
701 # Translate an ssidref into its label. This does the reverse lookup
702 # to the relabel function above.
703 # This function displays the results.
704 # Parameters:
705 # 1st: The ssidref to translate; must be in the form '0x00010002'
706 # 2nd: Full or relative path to the policy's mapfile
707 translateSSIDREF ()
708 {
709 local ssidref=$1
710 local mapfile=$2
711 local line1
712 local line2
714 if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
715 echo "Cannot read from vm configuration file $vmfile."
716 return -1
717 fi
719 getPrimaryPolicy $mapfile
720 getSecondaryPolicy $mapfile
722 if [ "$primary" == "NULL" -a "$secondary" == "NULL" ]; then
723 echo "There are no labels for the NULL policy."
724 return
725 fi
727 getSSIDLOHI $ssidref
728 ret=$?
729 if [ $ret -ne 1 ]; then
730 echo "Error while parsing the ssid ref number '$ssidref'."
731 fi;
733 let line1=0
734 let line2=0
735 while [ 1 ]; do
736 ITEM1=`cat $mapfile | \
737 awk -vprimary=$primary \
738 -vssidlo=$ssidlo_int \
739 -vline=$line1 \
740 '{ \
741 if ( $1 == "LABEL->SSID" && \
742 $3 == primary && \
743 int($5) == ssidlo ) { \
744 if (l == line) { \
745 print $4; \
746 exit; \
747 } \
748 l++; \
749 } \
750 }'`
752 ITEM2=`cat $mapfile | \
753 awk -vsecondary=$secondary \
754 -vssidhi=$ssidhi_int \
755 -vline=$line2 \
756 '{ \
757 if ( $1 == "LABEL->SSID" && \
758 $3 == secondary && \
759 int($5) == ssidhi ) { \
760 if (l == line) { \
761 print $4; \
762 exit; \
763 } \
764 l++; \
765 } \
766 }'`
768 if [ "$secondary" != "NULL" ]; then
769 if [ "$ITEM1" == "" ]; then
770 let line1=0
771 let line2=line2+1
772 else
773 let line1=line1+1
774 fi
776 if [ "$ITEM1" == "" -a \
777 "$ITEM2" == "" ]; then
778 echo "Could not determine the referenced label."
779 break
780 fi
782 if [ "$ITEM1" == "$ITEM2" ]; then
783 echo "Label: $ITEM1"
784 break
785 fi
786 else
787 if [ "$ITEM1" != "" ]; then
788 echo "Label: $ITEM1"
789 else
790 if [ "$found" == "0" ]; then
791 found=1
792 else
793 break
794 fi
795 fi
796 let line1=line1+1
797 fi
798 done
799 }