aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Config.mk6
-rw-r--r--docs/figs/acm_ezpolicy_gui.eps1756
-rw-r--r--docs/figs/acm_overview.eps1463
-rw-r--r--docs/man/xm.pod.1378
-rw-r--r--docs/misc/xsm-flask.txt1
-rw-r--r--docs/src/interface.tex41
-rw-r--r--docs/src/user.tex1921
-rw-r--r--tools/Makefile1
-rw-r--r--tools/check/Makefile4
-rwxr-xr-xtools/check/check_xml22
-rw-r--r--tools/libxc/Makefile1
-rw-r--r--tools/libxc/xc_acm.c132
-rw-r--r--tools/libxc/xenctrl.h4
-rw-r--r--tools/libxen/include/xen/api/xen_acmpolicy.h132
-rw-r--r--tools/libxen/src/xen_acmpolicy.c269
-rw-r--r--tools/python/setup.py11
-rw-r--r--tools/python/xen/lowlevel/acm/acm.c403
-rw-r--r--tools/python/xen/xm/messages/xen-xm.pot3
-rw-r--r--tools/security/Makefile94
-rw-r--r--tools/security/policies/example/client_v1-security_policy.xml195
-rw-r--r--tools/security/policies/example/test-security_policy.xml97
-rw-r--r--tools/security/policies/security_policy.xsd146
-rw-r--r--tools/security/policy.txt296
-rw-r--r--tools/security/policytools.txt148
-rw-r--r--tools/security/python/setup.py30
-rw-r--r--tools/security/python/xensec_gen/__init__.py1
-rw-r--r--tools/security/python/xensec_gen/cgi-bin/policy.cgi2376
-rw-r--r--tools/security/python/xensec_gen/index.html72
-rw-r--r--tools/security/python/xensec_gen/main.py185
-rw-r--r--tools/security/python/xensec_tools/acm_getlabel44
-rw-r--r--tools/security/readme.txt33
-rw-r--r--tools/security/secpol_tool.c561
-rw-r--r--tools/security/xensec_ezpolicy1636
-rw-r--r--tools/security/xensec_gen.py22
-rw-r--r--tools/xm-test/README32
-rw-r--r--tools/xm-test/configure.ac15
-rw-r--r--tools/xm-test/grouptest/default1
-rw-r--r--tools/xm-test/grouptest/security1
-rw-r--r--tools/xm-test/lib/XmTestLib/XenAPIDomain.py4
-rw-r--r--tools/xm-test/lib/XmTestLib/XenDomain.py5
-rw-r--r--tools/xm-test/lib/XmTestLib/acm.py101
-rw-r--r--tools/xm-test/lib/XmTestLib/block_utils.py2
-rwxr-xr-xtools/xm-test/runtest.sh6
-rw-r--r--tools/xm-test/tests/Makefile.am1
-rw-r--r--tools/xm-test/tests/security-acm/01_security-acm_basic.py121
-rw-r--r--tools/xm-test/tests/security-acm/02_security-acm_dom_start.py64
-rw-r--r--tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py60
-rw-r--r--tools/xm-test/tests/security-acm/04_security-acm_dom_res.py69
-rw-r--r--tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py38
-rw-r--r--tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py82
-rw-r--r--tools/xm-test/tests/security-acm/07_security-acm_pol_update.py313
-rw-r--r--tools/xm-test/tests/security-acm/08_security-acm_xapi.py358
-rw-r--r--tools/xm-test/tests/security-acm/09_security-acm_pol_update.py437
-rw-r--r--tools/xm-test/tests/security-acm/10_security-acm_pol_update.py354
-rw-r--r--tools/xm-test/tests/security-acm/Makefile.am33
-rw-r--r--tools/xm-test/tests/security-acm/acm_utils.py16
-rw-r--r--tools/xm-test/tests/security-acm/xm-test-new-security_policy.xml97
-rw-r--r--tools/xm-test/tests/security-acm/xm-test-security_policy.xml111
-rw-r--r--tools/xm-test/tests/security-acm/xm-test-update-security_policy.xml117
-rw-r--r--xen/Rules.mk1
-rw-r--r--xen/arch/ia64/xen/xensetup.c3
-rw-r--r--xen/arch/x86/setup.c3
-rw-r--r--xen/common/domain.c2
-rw-r--r--xen/include/public/xsm/acm.h223
-rw-r--r--xen/include/public/xsm/acm_ops.h159
-rw-r--r--xen/include/xen/sched.h3
-rw-r--r--xen/include/xsm/acm/acm_core.h197
-rw-r--r--xen/include/xsm/acm/acm_endian.h69
-rw-r--r--xen/include/xsm/acm/acm_hooks.h374
-rw-r--r--xen/xsm/Makefile1
-rw-r--r--xen/xsm/acm/Makefile7
-rw-r--r--xen/xsm/acm/acm_chinesewall_hooks.c721
-rw-r--r--xen/xsm/acm/acm_core.c406
-rw-r--r--xen/xsm/acm/acm_null_hooks.c95
-rw-r--r--xen/xsm/acm/acm_ops.c212
-rw-r--r--xen/xsm/acm/acm_policy.c893
-rw-r--r--xen/xsm/acm/acm_simple_type_enforcement_hooks.c924
-rw-r--r--xen/xsm/acm/acm_xsm_hooks.c74
-rw-r--r--xen/xsm/xsm_policy.c1
79 files changed, 12 insertions, 19258 deletions
diff --git a/Config.mk b/Config.mk
index 02feb1ba72..0693b34c82 100644
--- a/Config.mk
+++ b/Config.mk
@@ -153,11 +153,9 @@ CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
EMBEDDED_EXTRA_CFLAGS := -nopie -fno-stack-protector -fno-stack-protector-all
EMBEDDED_EXTRA_CFLAGS += -fno-exceptions
-# Enable XSM security module. Enabling XSM requires selection of an
-# XSM security module (FLASK_ENABLE or ACM_SECURITY).
+# Enable XSM security module (by default, Flask).
XSM_ENABLE ?= n
-FLASK_ENABLE ?= n
-ACM_SECURITY ?= n
+FLASK_ENABLE ?= $(XSM_ENABLE)
# Download GIT repositories via HTTP or GIT's own protocol?
# GIT's protocol is faster and more robust, when it works at all (firewalls
diff --git a/docs/figs/acm_ezpolicy_gui.eps b/docs/figs/acm_ezpolicy_gui.eps
deleted file mode 100644
index aac6d4f0d3..0000000000
--- a/docs/figs/acm_ezpolicy_gui.eps
+++ /dev/null
@@ -1,1756 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0
-%%BoundingBox: 0 0 635 339
-%%Creator: bmeps
-%%Title: acm1.jpg
-%%Pages: 1
-%%PageOrder: Ascend
-%%DocumentData: Clean7Bit
-%%EndComments
-%%BeginProlog
-%%EndProlog
-%%BeginSetup
-%%EndSetup
-%%Page: 1 1
-{
-gsave
-0 339 translate
-635 339 scale
-13 dict begin
-/fa currentfile /ASCII85Decode filter def
-/fb fa << >> /DCTDecode filter def
-/DeviceGray setcolorspace
-<<
-/ImageType 1
-/Width 635
-/Height 339
-/ImageMatrix [635 0 0 -339 0 0]
-/MultipleDataSources false
-/DataSource fb
-/BitsPerComponent 8
-/Decode [0 1]
->>
-image
-fb closefile
-fa flushfile fa closefile
-end
-grestore
-} exec
-s4IA0!"_al8O`[\!<E@K"aC"Is4[N@!!**$!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%
-!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!<E3%!WTq8$O?c3!daqK&HMjL
-!$;1@!<iK)!<E3%!!!!!!!!!!!<N?+"U52;#mq(?_uR1V!!30'!s/T-"U,#3!!!%J
-!<N?'";(eM+Yc7e'2`0C,&n;PJWZW3,=8ZO'iNHK,VrnMJdDc"(Dn#.,pjuf.4R/3
-2E*TU3^Z;(7Rp!@8lJ\h<``C+>%;)SAnPdkC3+K>G'A1VH@pm)L51SAMNX0fQ'Rc(
-R@9kFUnsrdW2Zf&Za@-K\%&u[_Sa=2`lH0Bb0nbge^i@)g"PEEj5f=akNM0qnac;D
-p%J.Tq>1-F!!iT+!!#4`q&B%@rr@Y4r'^Lp^+OZB`Oap6Xm-u1/c8sq0>XiE\uE3f
-r#Oag#j??qep\%ZHqE7#?$foIcDC&Go>CF\r4XoUPNj([TQNtE>L7aXYM/aQ*tNUC
-8b,R\`a0UiM-KroQc!M_*-mbC2bK>*Wl0WAX?LGS!L,%hN.M-'o))\\oI(Hg)LO(T
-$atQD#gukbI)P)VJ4K,@R61n:o7oQMcOMH*h[=lL0uc$L!!l>]#9AO1B9H';JW`<t
-J)PTrC]90'_XICH[#b25O8*#;)ZKf3=n'''!!o\Orr@nNrYKd5^Z^u20)kpg.nK[?
-ib8>lL#(^kqB_aA^[R-/5PU[3iHKN^reY:)n,+B:O8^Jepg)_prrAcrn@S]##d#?O
-!/[KM(O(VKka$TKrrBnd8H/\LB`A'dh;PR6-(bR[n;>XYpmOG+GBdp&M.a]or$&M/
-r[*^$?/?M"!2<Wc]Dhj:XX!iGM51%dGD<lrQ@(=b!5^6WrrD%lrr@c/iNN)(T*rF'
-MUF`aRQobTG\d;8B>X-8,.*F1-BIq-hAZCoU06utrr<>,,Q@b#U])'RL;2r<HnPF!
-_CJ1W!9.\l!/97fYPKQ;$bu1gdQdMq5N-g2C]90'_XICH[#b25O8*#;)ZKf3=n'''
-!!o\Orr@nNrYKd5^Z^u20)kpg.nK[?ib8>lL#(^kqB_aA^[R-/5PU[3iHKN^reY:)
-n,+B:O8^Jepg)_prrAcrn@S]##d#?O!/[KM(O(VKka$TKrrBnd8H/\LBn,)dG\MF&
-!/4SFZe(fPBZ0nK9crl;]J]]h7(;,^rXg&%rr="5rYLoU^Z_!]/,oUd,=VV4j)fdf
-o'k90'&SCmpdAf1r,.Sj?="QM!2<]eYQ"S.N>MTpNR@b+$d6FpoLjWJrrD!iUAk5`
-\j,/!G\d;8Do09e+uE[+2b3d!0+EEY/biEI!/*h"rrC(&rr@c7iNN)(^C'u@n;,JA
-pt[%]]Y$-%!(=<T?iCWU0E2"kU])'rL;2r<r%%dI_BVML!980N_Xd3Jr=\"AJ+uEF
-^\hu1pg.8FrrActn?;il#`TZ#!0,D+!"6uf?h@!?(&n9m&Yf:*n[^sDH$F-(M/U8G
-r$!t)r\m@F0/!cad4P,prr@^AMuNdskl1X:jl*E>-,0fe!:YflJ,%hAn@ZCkrr>Hr
-iEuQr)DD*j)l*BKQ\N9=QM`95!5]sLrrD)$J&:dGfDQ?>Kn&kcBYXI_O8*$f)ZKf3
->O\ir!!nQ#rrA&+rr<GM_dE%/IMMk_i=Vga!:dWbiH]Z`reYR1^\f94?iDuSr%B]4
-J'fkC=8r8R7Z79H`p+f=^Ve!Q4rAYr!0`!6!!kKH_"?U$r.#i=FJSp:L#(_VqBd9k
-J+/3@^\Hn4n@Q=rrr>I)iD9Fag/n:S*2EKLGDErsR!^@_!5][IrrD)DJ&:XCp\ba9
-Kg5?"Bj^dYO8*#;*rc57@IU2p!!mElrrA'Vrr<G=_r()[4r""si=2W5n]F)TGBeK6
-M2/s?r#rGNr]*LH0(0=#d4k>orr@^1Q2^j)./s:$h;Ri!-6ESEn:oB+puNUe]=^<,
-!(=``:]:pZ=8r7?U])'RLVN&?Hn#'q_Ac,I!99;n_X?pfr=]]q5PRT[?i4r*pg)_t
-rrAd%n>H9d#]2*l!00qV!"6EVht0T+'`S0l%AeREb!4j/G^KFHLVf\]+geHP3Cj!"
-mgjoq0_eTH!/*7qrrC(frr@c/iU?Ui*t!MeL=3j3jWF!(]KQ8p7)RtZrXddbrr=%B
-VS3[j/,6sN]>BbVlbIuNIKILHf_$bs+qG@b5hA1(r#X6CD,.niI7hi'g5j5A+*\^Y
-`7&EelHj:`_pW:08pe0Pob20gbR5eJ-g]%Hc7Je+%0$<9kcb@WBC.q\$`3pL8_s81
-$iu!Q9HQW,:Q>>dr)iG!L%X=?C7bb2!+jIfkaiTtMc0'pr%Ii3q_EP4f).\+bB",Z
-r$33<Kt\+G<q4Ln1p7>(HZNh2HfAi.)@ZdE]Y;k^Dm^O2NC(cJo_\aZ-f_,CT*=H9
-&@<O0T<kDSi@be\-/XK#08VkOrLEis>\j1X<tj8X@mn_Y/ppF`7_,R5;I/#4>2*iD
-)K!KTGB7J@"g.FFgJ5$G;LZji!$#IoS+,&'*KM&`RJTg0_T@bs);Y0VNk$#"aRp;0
-^D+<mnJC.#K]_fkMZ+*7cJ#a]D7*#B(KBo8_VZ40cMmk`/:9IWl;>kSO_<[qrX=&G
-iWoB)dd'PAGVg:#<?@8D]fh+D%[-RLf\T%%B;GOL5IF:D4?9-\Y1rYirL:/742`%S
-T!P<KHqO0rq^[%EnMJs+UBFZpAbGMEIO0AFn:uq/QuD=D/amfUeT<;p[H[9d?eV<a
-Zb[oOYCC()g52R42o.`2Xs1FPO6nh%#Xu;.8IVnRcs(Hk(;\)q&f>2dni,qVi@g-s
-Zd#\/p!8FY$N;,l7nrLgcDd`:?fDm<0->QrnXbpS[prs2C7ZN*i_R?#*;I!4d<n_"
-T6h=7rr@cA2=3V83[UU*mDbUk5,'@7jSUV0!!Q-e*f&_Q1Iq4qUA1V_`]A2NCTLn<
-B>a]]I3/=*1nqk`,Ce^t%V<;ddf.4.X$mef@:KeN/bE4W"&2EXDS,lS"oC-$?hUf(
-W."r"ce^M0Ffu>NBAs)UNXhhdpj1[d\^de=_LDi=D<$U8gI&/Yg:!1(>u/@]G.2JH
-fZ[[AH]K?.\S.mrqXXXdLiYdmKi3j!^Z-6q+c>L`!"8A?83:iS)tJQ1!(*F\JdtM(
-62pr$@_^iiT*^!Trr<+J#M4DApm]3*rU7ZX)u/_geqUqX@hXb01Ieb&Ca4f(G+`,(
-Y!0gA[OC:$ehqgOMu2\/mVgB($\$<,$)7BX+T8U[0mm7$Vr=`c;uNb75@k97iV122
-JR/ZXYMrd4&]O6J^,8:;X6i^'hm@UC4VLW<gI0N`rA*Nd4.H-B0C8>OJT##J/d@NQ
-n>#\LpaP`;p/V'c5A>fGdIEjE&:Vlr%D3X^Gc&C<+7/7]k=tF^N4q(Brn2D^$N(;,
-Dt+@U^U8QK28+??eN@n)[tS>^#-ICD_oid[rgVmtN<U6m$V`B_2tgtaOQ-564q%AB
-*u+*k+tnZChq:re?Bt%qhn["rM%+W(Ln5T%X_L'8\CWt(-IL_fZ$9$m9XDC#k\,Dk
-9AukO0,C,>/@RiQr)E[rJjX:f#35Z\meh(p\6*I;ZUaAGnB^foQL0,<@Jjp#?]&iJ
-P>C]2_L#C&4s=.NTtL@[n<U]F-p1oaeuJIG(<La6&rG[r(r%_O;=H7!=+U8]iK&i0
-2>B9'8&?>Wr,;9Npd74fpnQgBM`a5^Nu*:\C"$hnBD`tq/Ch+c9a>&)dF)m72+o%X
-X8BZ>l-N.ODrt7lnupQX%0$=cT)Sd/[EBZG2c9A+i?*rLZYU]`rr?Rog&q&PZ&dmW
-_1*9bpKnN7^&V8[5>g#p$_Y>qRCj;Pm]U$gY)=Uo]klELnGHA!CtC]oip)hEfO"c2
-@K-=`T+_&Tn^#4I&8_8_n6<d0!"&Z*@W.7@[_IIfY8$mdfABC!bMaOq<aH]YP=P+*
-m]V&t>:\Mc`)6;ubf/UJ,3Qm*I[Yut#+;FgZ5"HCpnQbS`ifL>,JtT:Hu&4qifAaV
-)u/=W5OaDT61II_mhU.t_&b6.eC1;Fo[!;%4B\_!(7G`JrM-1C>\]QhfiRotCX\rF
-p>=*&M<.tA!#%S0Di`cZXRsb-iuc(ON'@WUrGHeddBENrHnt5iJF)rUP_l;bI5:--
-3[U*qr948FbmgGk,/fHa:l7g?#NCg2.IfLXL[95XIam6loUd6'/FaO65AH++fsa9B
-1%>e55D]4PY3Hp:cbWs"r*b6;S3"uQmkh)uF:4f$NF0Qr<`]24\?rlt/?\DNnHaJ5
-[.3Sa!!e#3SR2_Q,'Y(#(Y&@uqbcXn%)*m6htJ36oUgd8*4Yb[BAu.2g*_`k#(07p
-IM[LN2re8$bOM>qf;ro)+DW#Jn?VgY>pJ<_ZYjmnqqWVsHWRT'me*cAr'gK/rm=mY
-pVnWJrXO<EnW/Gh"+3E0Q12iRLVushp_UpK/GNr<Nu!*fT(tKuBrLgi9@0K]X<R0$
-Q%[lRV#$Y,K[q1dG]fQD$VMp:Q-\7bc(D@+QAb8,`0[(rr\Rf'GN.J]iV`l;:;:l>
-Zc<Vj^CtbI(.ID2=%2n2Wlq(^O,Z#8'1;ZS&*^eIT2N>Q@f>G[%Ee9KfC?3H$1[mn
-HkZIQ]LD]Mcg[:@586:2G^I<](QK9Wi6QuR+aE`VnJ?h#bpuB!D\dRhiUD#_X*BQ>
-qBiDG9Alq%`4CDZq?EMNXV\ns(`JY5g/Rn;rr<6%c<mpp`-m!O^(pEgn0?s@O*jg_
-$eNk?GN$:?r%ITLMKS@kC(Xb/fLoZ4h&f#2n$O5HhT(&@C6hY2XBX@QQ[3NI]1+-R
-\4HS$e,B[Pqbpl$c1ZXom>o-!(>j?q;>Bm$q`ANK'=%%.`!bIZ(]H8(Q>IN\B%t4(
-Se%:;]GTN;U6"6dCQ`Hfgg#5>]<q?GCSom3Sl96_r)*EM^+<sT*W@_i*;C!4oCdq;
-TX=0?hscFdLce7Eq^d,-piGGQ.rQ2J01PJ:(]GoZ:Z=MIqo6>Oe(WgY<RWcth\8Ln
-DrR6,&l0/(O$8JMBdrT`LHi+Hm1o/H6bDkQ_G>\H)La,[C;Wo_dI4_8nE8b;NdPc=
-g$7:&QCFi<>$^!eiLL3PYd`,(rBFH4n*d?T\4`;a/QYZXSg`O2[?=ltrJEgMX7+d6
-p9aU=q^Um&._GIGWHdFka7^F4M(ecK2i2Ic/UcP1!-lQ(f6160&\-G?,B5m%pDsp1
-6FjOs>17*4B"NDh;KoH_)ih,]&+";pfmdTuJUb)2m+Lo9=nqOVe)Q5&BRU+fpd83Z
->!=!TC[f*Y4\N\5pqO`'!n=q*pi"3f(UVFs<nI70D(_SmSfI9\V_"lkUF!=]htFEQ
-'Ygt%lj*&bj(Ib7n>GtDpp6fAoCc_bB>k<E`Ho`Eh\/0gG`pBYde$<Ep_1[(1kSkf
-^tpBKn33\Kl2&W<#h1[m42fXMXTd+^R4^*1_J<6E9kX0&nY5q:rK99Ci6Mc.FRak!
-Dq_\;hE17nNUX)Xfq79]L>(+ohB/(LeGL&[Hogf3USZ5.r-F.=ScS?jT9&CdpgXL*
-*XgAkZqYjY>u+8.\DhZ2!83G,ORSt6ReWZOHhcFU[eOj:krpBfL:[Bb_LEV?kJ2Ne
-fB9oWd'`<[NCQ7B4r;UhX.:b?\'fCnF6keGPko7p<ccM3S\iFmlX(#^;t/hd^(8T)
-3d<mKB>Qef`4"MBnMJ\[?Oh2tIhp5sj':(Th"]dCrXeUSU#8Rn(gB^IBrXnd_#>Y,
-1bTGU)LL_h`>VugC"+^uX8(ZN0n.Dt#JXlSfus)G[J8)F8U.C6g;h+GZqdUiDrLNj
-QG*iB3kh5crm'@UdCp]<G$c"B`r3Di>oUXA7u7(Ci]RaXNF0LrnOHHcnEn3WX*rsV
-eEiO>pHLN[a7aNOTY;H4*XhK3`".D@)12gqr(+Cl+,?:,N.)W=hnpAQO)JU@e#[#b
-n6VNbka"0A.Ct]:=41p5ha<"l=1Zp=lZGQHmBTCWBC*b;!IRrCg&#4U.K,=A/EpJ(
-rL#cNnO$+B?F'h0`6X-d-*u3F]bA;4"S&s\+P#K@2i2GM&#j<TI^:\Z2%:&@nMMgI
-6$-uk98eP/RaqB<d][MqNAF>[XO^aaC6fW]NN\eI-2Tjm]QZ&TL`(e9j\!/71BhTF
-`u1rW=T7R`B_'4<:[:N:5Iu>J4L+k6qU+Dcm[r'k/:Vd@[!?0YVtHh.+5K/`*a&F+
-rFkcBpJ:*FQ9Vs1>!0(ge,%JRO7&XkO">d&rj6r\qks+^b9,P)XWCUDl2>;da7iBq
-8!ZBNIp+t>rR:VlI(&DZrrBd&rr@m4CiB.35OYKL!9,EZht,'AhbF+N`)3eSkEu8L
-^75-&LneI0cS>G"I5h0+&Ose?!1m^"qJZ?WNK*r<4NIEmhu#n^)ub,DqrtljMDdEk
-o,m_UJ+44hDu&N[n#$*bi[EI:o?;^A:&b43;6dn!R/[0#S,WJEULSf"1&h6%2u`ji
-7`PH.Sn%crDuLr?NW/u@a8PYfr'_PDrcsS%l+d"N2E1R*+8=66nJ#eXq;sp1VZ-YU
-.+mGKb^\MErrBu=oKhssiWT5rrK.$ZAK;5-Q;($GGO^+(`@@sc*<+YV[KLV56&&4W
-YXYeJ!JG,MD202kr'L1TX]nF_fq>b]QHj>E`X?G.(aH$+I.cadrr<=I\\(T*6XRL<
-<:`oP_u"g+`eYj22L`KW[&q8^.KP;:gd;7`=UjK=$o9Nh,E.]:++RF!#4]0Y4pq3=
-poCR_^)ZodDu1i0c(6QXL;0BO%,1E/iU6mK!5U\0(48K`]<Fj`57tQ-!RMm%m30jL
-)p>:+\VA,RhG8%Tk^Fc'J)H7mA6i:1`VBCB#pImW_#>R@7KF>0Iq>[^A%!6F#@9^o
-?hisFr@?jaMEg%!T+84iSOW?CphTAg`;Teb0"#CF-Im"@hZWrZ_+=S+A)@Z.3ej[]
-KpJ9>2R=a"Cr5W.b>,:NBl<ACXf\Z<27e8.CO5He*ut:-rr<mb)uO"3c/6F@#4pjc
-a.3`.n\)VjRsh/I4trJc5D^u)06-#1^R>1Ai:s2Z*ij?%p:a9R@_UC*2l&X6i_:B7
-F[+Oq`.&..ipVoBCsN^&_@M7u!"7u(nCEf&GX`](>k*Ti%j(#)45]ft7JJTGW['96
-3aL5K>3f@XX/juhbAV<;W;(^=:CYXDr'g,d_]S(1p:#$kq\+@%]-sj5rmcM'F/l8'
-A))GLrr@Y&$%.EB.+\[[f?F\U.CQ_C\AKBFjm0o7;oG,fZBQKcAOmr&f\7H5!0$)#
-`u3oprf05$OoGEg=+\1t5MB&oJ*e?J#=.gGMS(&#o$>>5g3OjYgFWY-nU@2p?gs]-
-IKctTaKk>+M#8Qm8mp139kATsp>6JHq_ZBtA@FKVEEh)OIp3Nb!5Z^*Z36qCIa:6e
-GmC8F;-s;a*e\2"PK=XajCDc6IR3u6_-?p>i2"*n^YkfW)>G$,DhPk5IQMcqItg-:
-nY_4+6%/9A6hkMnC"IO>p49.+()Ha6p`ne%O705i<oVtKR4`<W@#c81QS/)o^1He`
-`X`4*rrBkk/q7EdDq`N>rL(ADpp]tQnQ3[_L_b/;5OFFFLW!QQcW'k1Qf3+qi2q4A
-^Tr@*YDQ4bkoM2Am\-=Z?halG''\+&]r(R*rqfQI@qDLjhq%SanItV1]`!J4Ama63
-i8<o:iVa6N$eT]Vp6klT4;G$s%/mObrZM,7rM09\iEJj#*T13^<q(>"c`[1!]s@EW
-iS31,_%pbEmi1Nf1u9Wf%Vj^PUS&ui,hAm=rr@XXr*oFqq`92T(\cgo(q,L`&&l;9
-h\CSFHt\uC8_/8dC;'i@c\K6d27:JZ4?9,1LKO'M[]Q]G)CC5bVV5`CAZYPdMj\("
-XdpR!^Y::<$7YK%p6PZ32=CNK:T=,Ap5&[?Iq_V`?\iR&GW3Rp(9=0YahJ9K5(%8H
-V13-;4&bYWpd3HI:At@IINnPK^tp+$?E:3^po;Kn?P$t])K_<lAufoo[JP,rgYVup
-.XWrK\*Z?sHsuf0nL)<U!4Q$crr?JU;nu`AF\da!&i;f^rl8=XrLEM0#>O_Tb>[rO
-MM*&X/uJ00kCrh$V_4>*DcbM4$2d*Kq`F]"2c7tW[Gi\hK>\l$;D3Qd?gpmQpaULT
-2lg`*VoMS`r[e#0]R0.3p1a;;nJC0A`bfe458LnIWr*P/PI/#)i8plS4_MS)>.9:"
-"n>gV8&KfnG^IGVp&>#FoR?o-2V,I#Lc'Tij%$VeeS]EA."9\gZ>[ZgMuNdc0?4H=
-N*[aU]OC\WrrBk]r\XW"rZgo.MnC/%Zc0WrrLH,4poD71%e.eu^)#or-dfXGl7qR2
-$#VU@(L5NJbC>9#=,;lrX'YR^`#>e0Ud'cRXek?uBqO.tp-S<I?aRf=rr<W0/c9YY
-kO#VGF8cKnibPaNMD'`l'Ds4rq_!71rL,,/H`2D?*YV>*?73MWrrBpWotQ?0=+pK_
-iU&hTi6R<'<_jJ*j%e+lQ1UI:T,$UVIPcN,^TkJ-JA)ZkGN%Gtrr<;iRW$"apa\"J
-rr?i,#(.$X*W$iOfAMF<mJd/urr<ORCKf2[pfAN;Wd#K!rXnZJNpQ-dU%,&!%uMD`
-nKa3@gYt*9UZ%1K;E>4M*jj;n:&VeT4+>M)555NU(ZA`=+5-s"q#0^nin+)D(ZL5;
-[Vd&C0C9))7e!n'Ii<d[h[t5LiU7<PO2\jJ^)^ln&:9Im(KulP^(TWf4s'6K\RBjD
-SL_TriM\="q`R;3n@^dZ]C__I^U)hq'0j?@!W4&/HcMbcL[=!YJ(m`m`L\gZ^[T"u
-7uASjT4[l#n_:m/,4Itt35;ijVo-9$Rb*M2GG/2GCZeOElom#d^'t#AKKDdaqKIVI
-<7R]4(Q3Nnp4p"^pa4OXm-,&!rr='8naGIer"Oe(IiWthBmP32Nie(rrXF+Up/CK_
-KtM-Z%u=OKd<'/2!++p(0DM`Ll&b1Z$J+n2^Xr-]'2aP&2`c)Fh:hhNqf[GChZ,hi
-HnbN.m62D8@JGiP-cQ)c[o\Cc!+C:S^g@.c:PN3h1d;HKa'KDWSFh:9:%:Qn;t7nc
-KHCLQVX^5?L&=<9/sl'G=4VL#r'B?>48[8];:1-+i[ZZZnJCSpq]^9?p8.chJu`\\
-58^bu(W2lRp4`AVpohKJ(:Bcf?aa+ar"CIEp#*"XpfGGL$N;5OHk4!jT"[;P]&p,9
-iQZjPdpr.nnL%W;Gs7^IV-/&p`;5J-Xl>Cs=.VqPDt^s@=o2!B5PXd-:DnW7P'dr5
-::L6'"U"N]qc2<sFnfhN/cO56%(mbRBAnohhq?o'T*F[>%0PP/KtLd_Zf?gp4A4UN
-*V_D1j/7[>hh\kYfer5S\dsO<$X8Yp?=-4'p`ne%M#RGeILc.FrX$]Grm105<n4i[
-nN0/=!.pm#IahONq"MR2(,*=#nW2Z.Z1'9^*s_-pB\JK;iI;s5^(g+=hCI4ErZLun
-fAbDA]IoXBQ"-mhHrI"hXt;"kepgm$C&\/:%K2@%+F_[%*'@G<qb)<*pc%,,#lan@
-;SQfcgG6gh=td\Kg)F"Pp6tbTn=TCrpa>Pm`P2QBr%m:B$/51B4!aU%i-e)SC]=AT
-GZm=e\q4YI3nBQS]4aq3T?0;-rr?t5L,OK$pe,ZUN')1NX'5&.r"ns,rOKR\i*/te
-Gj%l\0A,#]n:-9J,`gphZgdtp:"R#cGohZ^Hf:"pl@0<24AW(oqY%Coq>MJ_26.Ze
-De&>;!8-3&RJ8<%p\kNUikO4ua5/AtZlafW?aR$(bOGg1nV$lApkL2rh[[@E>lN)N
-?OLeGph?W#53(X-Dm!e<-h*(@IY?Pe9n(Y66JqZ19=/B8KIQd'rrBl$oe-FFA,V'6
-4u.LHph0(pp0@Qc2*VfMK2)+on-?bC40[020B,3R57"[cL6DI#nZVjB:Plh%^*`XT
-!61T7LW%Ij22t8JPO#L;M60(ABQr1cf%/:J:%0\,g&7K@&Ur+,!:WU1&*k=E#ESjI
-pb2=^n42koVYkoAX1V0rYN#;3V"+HbN.5O,D0"ON<r,=A4s\cPnWUo]GR&B6CYH;F
-FZgN&cc$f=Se]e`RI,.!2bN\VfrOhPrL\NTIa*AIJ*bL[Htr1)K=lKfrrDgA\,6t:
-p1!Q9a'SlF1\f?ETDL`u7fB350`2R84pV!jdI479-fBIglXp#epj(j.HUuSt$qJ7.
-&$3?\r$8j$KC7obX\\^>-CgOfm=D'^cMe:JTCG/>`;Q;,14IF<Ia4Rm?1]0JpuC<D
-%K&BaAT=DNB^;Mi(=V9+pj^8S*r(0Q=2e6I)RJpo`=5b^h?_Q&[IIS,A`8[ZBj-h;
-&\@`Zp@A"A2skth?[Qtjhd^Y?ESt'i(uBKJi7_mk^720:M==U*I'WMliRY!$l5FN@
-(@p]R44A;@O,?fhM7!@mHfNlH#^%ZP>A,@%GJ=$O^(=t,(&n8c.;:^3CHaH(Iq!mD
-rmQ?05!Ja2a239LL+OWAnUKqAn5J=rK6/%S'DR>TdJO++9ln<\&Fa=gY,ufJ(W?06
-l"b1!pm>a3lJ0Y\;;qNTpaFb\\aZ*K\&-$)`p\aK[*FT.J&+m0BqO-Ya'Ld>peC9S
-_qIo%:P1kM^'K*apeC8Pi5V1)nT#X#;"94q!S75spg_6^_sii<?LZO<TR8cO+LJK(
-25frHPHT5_^n9@kp3?@$qa:A`_(!#]XFAM;55=s3^Y!bH+1;*;nb`$_nMe=gMuFc]
-a8RajU[<3YD[>*2hAl<S@jf8l'$&oNe&SZX"$tHo9<0]Zl-afX<RrP+f!O6\q=!hA
-_tc,0"%:L*V5J)r6di@?)uF8B[+?jNm9JmVYui#F::'ISPMtC3>?GVEgtgXNYP<T7
-el((4QVu6glbPHS4!3sL9Bd8WrrC$crr<>#^6*l:r*:E6MG*1Ml2Lb&dJj1PUqVt?
-TDVt:n;9m'([:r"`R4\c#c,1sI\6OD+7P.\kniUa!6*@c!!oC7Oa`r#>p&Qn9Bd8W
-rrC$crr<>#^6*l:r*:E6MG*1Ml2Lb&dJj1PUqVt?TDVt:n;9m'([:r"`R4\c#c,1s
-I\6OD+7P.\kniUa!6*@c!!oC7Oa`r#>p&Qn9Bd8WrrC$crr<>#^6*l:r*:E6MG*1M
-l2Lb&dJj1PUqVt?TDVtrD[ai,NK.sKb/C-$4c\r#U$a?oi>S3bH--'dITQG\rr@^e
-Du&QDrV9gjU](k)^ZV,ZpZ6nEO8)2ArrAX2J)?Ok!#e)\)Op_Oao;?i=8Zb3!/,**
-q<'.(q-WZerXl-EkFA1=jaY:2pdV.\!1n4\hj+3A)F*1!S,R]Trr@LLr+Q*1KPGH$
-k9p6(?h'oj&ZNP.S=fQ;J&[QE7]-1cSoT><Q2^h&5N*NMrcuWc!.J#IB`A'cC2`q2
--iNjJnY?'qWP@VdTD.Gs`fKmaVZ-XfEduu3rr<s%i>S3bH--'dITQG\rr@^eDu&QD
-rV9gjYLd]J]'k3WD'/``h;KH53q`6%4rrqG!ZF9ElagnN-EEkc0)kqFq>IMaHrI-2
-[a8`WgsY*ERN#SifgQC1X2us30s#\4o9!fAfRL:NJj81Xg2FfW)XF$%n*MduCWF1-
-XTjB))rX!qBY)HTL\58hnOA@JiZIOqS%jM<%Y>j4iG%u0:=m_[2OhGWcIiog40G3"
-q)RpL<joR6o7*LgaH!_oZT%:H!0!shrrBq<rmPCdGff-H6gP)^d!l+E:[i:Srr?_>
-&*P&snU?h_N=,FR%eq4*QLQ<2A`>:39%!<MLnF0/T81,enD2*bA)SF=`82bV5#2gd
-P=i<tQV#PH>FS92Uq?LTOM`D-S&ISu^'j3;41FUBq_gi;j18S,rmmo8Ee!23m'e_-
-%R*XUi:O3"pp'?"_Z'TP4u*';_-B*&i,)IOcNj6siFe4aDrFDrD6L#FX5VA;J&+g.
-A%ceKe:iXTCLaAHS*`!)f&uCGQ&VX=Z'7P"CB_RJ')naUMgbY%qeU`1d=0Lb+kO*i
-LHZ@Gp\RGG2]<3]1u"Qg=RkOWU3oi.1n%L`k\i$?XX3K/?6t\+"PVVVB,jJRp1nFb
-(HR`S[mK^_)?/?^!C(=i&&nPK#lam>Igp)+$@X&\pA0NCq_S$EiJ3.d<7S`r>E'T>
-[^p@?i!FLB2Vu<#)0ct9p3IdJCTCTA_5"hfiWhk0hAXarKJgMt++YLQ-]c1fZ)?t(
-DN2=\rr?epfTQJ6IeU\Y!;Is-(rHH9Hi'Ce/,\)qo$/am(@*m:D@oYGL,i/Lm$?]F
-2npUXP$#!Sa)O!6C&8QmaWIp?m60CNRD3AVKT#@Ef>2cGL$h&t1%FGE^B_3:+,Nb'
-CS8f2pufU[*Ga3>\aZMR+PWfrbdN:!o5;ba?eCj/cmp45-,9?m!noM'5@lc_TF?mA
-5I9>/#9s]J3"?6SocAd(2d?7fJ,]KP3Gr'p:q.m5#KHcDg"`OP>]0>-T22Z!!3/qH
-_(C/pVf(0pfg\s]rU5agZeeJ<);4OS7XF.eSiUtlrrD$/J+-CoqDC8tnFuq.hu*.\
-rr@gWrrBl2J*>DCrrBsoq`fT%eYE*aBE%r84oYMW;j74]%tEsErrCAGO8*jir"So)
-ND<:I4oYMgp\t4V>!LusJ+-CoqDC8tnFuq.hu*.\rr@gWrrBl2J*>DCrrBsoq`fT%
-eYE*aBE%r84oYMW;j74]%tEsErrCAGO8*jir"So)ND<:I4oYMgp\t4V>!LusJ+-Co
-qDC8tnFuq.hu*.\rr@gWrrBl2J*>DCrrBsoq`fT%eYE*aBE%r84oYMW;j74]%tEsE
-rrCAGO8*jir"So)ND<:I4oYMgp\t4V>!LusJ+-CoqDC8tnFuq.hu*.\rr@gWrrBl2
-J*>DCrrBsoq`fT%eYE*aBE%r84oYMW;j74]%tEsErrCAGO8*jir"So)ND<:I4oYMg
-p\t4V>!LusJ+-CoqDC8tnFuq.hu*.\rr@gWrrBl2J*>DCrrBsoq`fT%eYE*aBE%r8
-4oYMW;j74]%tEsErrCAGO8*jir"So)ND<:I4oYMgp\t4V>!LusJ+-CoqDC8tnFuq.
-hu*._T[82HS3QLDmg6/*^(0oKj,X>XM0)l_2<$-I"FehW#eV%%YBXf17nqO:r&(Q_
-pg<&VPC';(F&CFDI59h^cn@!udPYC9gVp,Eh*R]9k+M_SJl[B;:$l>Cg=u<rnh'7g
-NX-b_j(I`S*)ONc#i^^ie)I$"N\ja(70-CR:]LJn^\e_ZrX*nj-h^K*VEa.Mrm+*F
-mf*8$am\PVesZO<%^#a2Jt;oAdA]e=!/IoSGQ.[+V+:GE\,H_Yrr>Nb0E*$=g#)f0
-Ss:DelJM@chu+IX^\E.?B7Ko,<.DfdJ)I5SoP.;(!9*;CSc8]cku%H\%^#a2Jt;oA
-dA]e=!/IoSGQ.[+V+:GE\,H_Yrr>Nb0E*$=g#)f0Ss:DelJM@chu+IX^\E.?B7Ko,
-<.DfdJ)I5SoP.;(!9*;CSc8]cku%H\%^#a2Jt;oAdA]e=!/IoSGQ.[+V+:GE\,H_Y
-rr>Nb0E*$=g#)f0Ss:DelJM@chu+IX^\E.?B7Ko,<.DfdJ)I5SoP.;(!9*;CSc8]c
-ku%H\%^#a2Jt;oAdA]e=!/IoSGQ.[+V+:GE\,H_Yrr>Nb0E*$=g#)f0Ss:DelJM@c
-hu+IX^\E.?B7Ko,<.DfdJ)I5SoP.;(!9*;CSc8]cku%H\%^#a2Jt;oAdA]e=!/IoS
-GQ.[+V+:GE\,H_Yrr>Nb0E*$=g#)f0Ss:DelJM@chu+IX^\E.?B7Ko,<.DfdJ)I5S
-oP.;(!9*;CSc8]cku%H\%^#a2Jt;oAdA]e=!/IoSGQ.[+V+:GE\,H_Yrr>Nb0E*$=
-g#)f0Ss:DelJM@chu+IX^\E.?B7Ko,<>kf:JldH<:bm%f-nuUtT8k#"a<YrMrr@bA
-E.,$3l=g1tLKAuA:d=0mci,".g#rA8Sn0#5lL4Kt#Q5QdrrBssq`OlYo?=!/*F8[F
-"[N(fUJF,LI",e$rcs`X_lLQ1W#tYGkPkMmO6lK<!7*E]piUfY'a+Gp4T>E?nbo&/
-q;tQS!"Q13!.pkndANW75!QC"rr>1(5N1/Mn5Kqp2"U_ILWB+6rrD5M8,PE[rX+5V
-!(NQ0nG*"/5Q(+$rr@gUJ&+rGkgRlW+!92!rrAX%+7SRapaQOI)L;>__rLVVrrDZ7
-U])9>rr<3frrAfi5PTVUB:o0KP^gTO^Yl%4oP*Lg!"Y.WoD\g:16;3QGPi0Xrf'&?
-!9*JHSq$Ru;?$V+Y5\KRTRY@eTDUl;Zd8XO4N]nIe_fjq&,J-Srr@hpp3HZ<kF"j<
-3kP@uJc>^>Sq$8)rm*h,o-jV=LKAuA:d=0mci,".g#rA8Sn0#5lL4Kt#Q5QdrrBss
-q`OlYo?=C_nDERirr<3O[.'E;HlMT'rX$:-S)^B6i1m9hi#CR0^U,VWiN7IC3_m/`
-hWqc!LGYQGi+MFin8hLX4>VKH*Cius'NuT:BCRR.Mlu?6hP]>RZtl9Fpjr*4<rI]d
-D-%Z`rWq-Q2mDItqd=eomW*UQ!/Ha#YN=KETCs*$!.p&@QC@\u-N='t?[NU`+6%b_
-phO1)?E<,T"+JYl4tZ;Tn:->fq6YVfG]u]hpuhNdr*[pb2fI]h$L7B'SflQG2kk"M
-,Leh1WU!k.I;*d4G?WJ'$eE(t5Pu4:;UYJ)D=L!m$%q_Gj%kJY0B)j[_AZ424Djsc
-h0;T3n)4cf=i%!1>JloB^B8t%mt<_,M!_i*Ut],;RKfnR*<T:224'*#1sZZ?]/G;9
-BR4ijks&SegJV$%-i=RWp2=Le"<ZA'j07R+e:5;+60NXX29YcQp'1NsJs"16?PN8s
-iFi'%KAec)9de!TqG*[Q'(=f*m/a$XP@!e)M4n]C?7"$I26:Tn!$&ahDiB"VS)K94
-'Bsg-M/GF?iEOV=BmS@FT_NS/nI;q1Hf;X>>r0lH5@n3s.G'A.?X*;\rr<24rLX!:
-GjA0sS&IT(r(HoXGb;jE.Ik-JMGddmpnpg\6i1s&2XhF[-.ET=Rb#$GpbPOVnID3>
-f6fk:X5XRU;Uo\8c2/N2_*MZP?iC?.q_9i;^oMq8IiNK#+"7W5n5;-Zi,0KS7W@.(
-o8i8bq\Oau9M`L>'oW(lfRr.4m.Kim^p31>)L`pp^C.b4G]1MYg9pC"r%"r=n\9s(
-+,PKSB?";8IO;\rGD'nI=`<8Y!lJ<59[R;#r(K4/iOF#K'l-`_J''^g<a#?9YK2Y&
-qc$*dJIJhOBl=]aE!hbk,G?U2NJsVfON76lrr@[]5NJ;_d!ta?rm.55I/Te?oQU9R
-/*$W8qf@.!p^L`mh$_+"!";%(IaUFarXW`>#*Joc"O-hT^M'`:`L[t;a1r5=YN$^\
-n%;NpA,IPGZ_i2r?N`7@h.u%@M**e:F7BdVmAKk3nBR6Vhh[m91sK[N3g*49I,4:e
-rX2fso>/-FfDL!m627Y_''ml%IQI6sXaC-<QeT8dn(CM'h[6cPpa5J-';tP^plBq'
-U&.T6e"7/"'PP87T,%A+C=tIOpf=u8m6U9'it]'$/>):D#3oP.^)[&+nOJL")uH>u
-^Z&=HIP^mXpil7`iNBTg!!t$jT8NUOn;kMk!-jG!4''c/!4Vk>j/iDZnOJ:UYO%6t
-_b/O&YO,U'<Ns4:cITAI4'&WXrlqEE=l)S)]RMkhhgZ^FH2BGtbduuVIti_FO2b&p
-=8eNc*,5/=,5>70(ZUgRV.or0*5?4VK>.N$8$:VE)>HY[?O2$TpoCR]*Z=a2XD<8$
-pjM'r&D25s`P*\'dPO*=Df0Jl:V-+X!rgf$'0J53T8*%\1%;B,^MA=Yrr<s%iG3]0
-iTJ+.JH#VTI_YacGhZ!g.I_O^pj:q+Ld!B[\&+d4."CVSiS2TbrXg6.h[k/OV_uc+
-nLMMK/Fh;TnOp]%f>HL!g@'X+5N;\CLf&P6q[*9&_+_R+r+=N0@ipFh+n-PbnbZ>]
-Sbk?Z4sg!misuB>-fK!]IhR&?a,p;D+7MgnN>MTp'fE&L'E6@M&b'^s^(a"WqgJ86
-`'4fo__6aJ+2h9($h"8o$fR/^9iF[ZDm+ESid^E6HtiINIasm:m'#pqiHD^#DY$3a
-O6jR>081LU-ElIeM)Q>#M7cF>D&;3p_-[6<CZFl94>3LDrXkJuet5:Z5A%*RJ$s:6
-D\66(_@N_6F/XI0n@s^brr<XEr[mXfKtJZ#(ZBN:!.qiH?aK3R/3H)mChWY]LAq6g
-)guqHSd=l$_9WMaTD!0t%H3odq"%#SN^%#\O+4M@S`/Ib5IDm+S)I.pIhD<+!;o4_
-X#rJ;kms]i=7G[s?"Zt'4hcd2mtJLh]I!'&iXa*.J*QJ'J&+j/AWM\:c[dqA#C(l,
-^='_AHroeZ_Z'T?GcOcJdC_3/C79Xjn(D4/GO82a08hbmDi/p.UA2o!peg$TDq].'
-EW)MGFcCmf\mL;Xp8@]Wn9a)qf7^:!?\og9e9-8A^&raknB^J4n2K:Oa8Z,C=R3P*
-K75h../8#VLVd5-MCl440,&'V)>KWY%3NU$%?H=HoUSc^d]GC]9e0GT\(0lQc"C,,
-i7'!]MU,59[RfiJnrMO$p4Lo1A`&&Xr*e#1TC't0I!#=NHi^D7YkU/sh[oHp]G'hA
-p9+0@n4VaLhA,N5_hd`.FlM:!=a1bB+,I,5!MF[E9^r=hWVG3%5de)jYD[eJnBS0*
-^Q*g%Z6'66(jo$PaUaDRIiWcPiGXB3$i;7(Hns0b/GpseBC'@&1WM]ur]KNH!4M"h
-!0$h?F00oKHDg,7n@(mV/rfA0p/n]l=+pK[isgLR*Y[+Ir@c3_!:^!gNdQ-B93:V$
-_c4MB:](rc6LjNb.pN#RKY@rkYPUk<0_jDlU\7s^n%aF+*s\G3DNi#mDo]Om`W#r-
-<dDGnbDYhG?8qZ$nFtlhLpS`9_r%[epP(<5;;mRrr]U$\i]TZE3bH(p.p)85L4"B_
-1%@3fkJ9BA4rO.anEWgDNT"XnG=K$1?1HNur'TG8'O,;FhBq_^`*\4)4RkAIYDW>[
-%t$ce9i#*bc1\d=n)AhKr*A6/?Wur3M0rIa4b$;trPl>)0,XK!_7GAVib_cIkb<q_
-U5C@nMC>3V.&)SIU5C@nMC>3V.&)SIU5C@nMC>3V.&)SIU5C@nMC>Zp5Ai.M19]F7
-rloNXJH#W":ZC+.!%)%mrrC.!i]m;Ih1+X2rR:cH_6KX'9tt@+q\FZoci$%Vd8g&g
-2hSk\mt9L8Iq_+\HiWpJq_rmln8I[pnR'/j(j/%Tr*fQ3^*ih3nM0PlPP[H>$MY'U
-@q5#s_-c\-YDX<#K_-d#/)ZGHD69s).es#D:t>4FF[$O4WTZ7omAGO5.Dl!=rr@XP
-HnG+4Tm0`OJH#Tjrr?aTKAJf]G(no4"mDQq]K:E.'?,D_O5\ZPq_ruFT<g_lnFkm2
-poj/li[;T9N=3dU*rUi.B0RJ_UKVSj"36^7&UZ%.al&3spcH8T/+F.#DuTf.]J&7"
-5JeHZnF)%;RuMU[9(9QKUj.)W]CACK4AFjs'3seu-D,4R=kn7[`kF=\r'B?r([JD3
->=U$Dif=l@g>@b"6)ZZ\XflL9QE,4RGrO"*[a2d>)gm)4SNKL5n):CpfR>&2j0+$+
-'"e7EJ&94RIM@9BGh_/+a,btI)gj0<J&6?3rm*g:DM=s;@dCc>Cc,Sdm;)EEplD6G
-U[3L"MJ?014eB,AM6pWSIM71PT=+u`^<PYUg101+NkQEZDtnJT!"!7kn<`j,pau$:
-p2TlrnM9:d=2jY'5kPYGrr<3b9Ar)QrrBk`5A$P@rr>@S/`2K#$%*W\erAZ7pa>,%
-!/su?rg0YL[U0aH(Z;La:C29h](d*A!!L:948Uqkr%ut'%fB9#l/?Opr%n?QKHEOi
-nSHpW_QA;gnR'/:$\$FZZ01K<ifA\_.b";an;gT=ZM56qf7gtJ:YFdI*^B02KmYu@
-Di@k4NO0.Dj5F(Y5DFV&nP6:H3PS+ciIBUgi4$YNO1kqi-\-RVn3c,@`_?f\a'(E^
-Hr9nD$^9W-^[OGM8H/[C;c_<FdGXs:q]kf%rN'i5@GkLRIh$TsMI-@5BTE\h2LYo2
-!/.-@Ie\uo&)gaKlZsAd57rBSn@B.s5Hjj[?h#6*&$L6X!68HPL[AmI,KF+InTTsT
-9D^So8,-`ef0Ji6J`@8qJ$W4mD\;n"n6WHu9)cntrYF)_$fg+PI`=UY=2^.3l5h2K
-TBq"RG['0?LGeH0_1*%KINN>$p6FX/lc#Lc:G:Du`IIBcDBs-@BmT6e?\*Y.pa6T3
-ipe>(M#J`K2:]D]I@9^<g+VF2`@i=sr\F8.D>RC>hKV!QI+@oi!87Op?7>?ANP%W^
-rl>$=Z7h$ACQ#<=i(&KD(&KZ$rYP(MJc%=_hZ\6T_n$Y;4<*5g$V9d%KY/ViI3VPW
-rr@e$0B&N6l1XsKKAk\tkW2GOVNmlh=sfMKBr5S_7[[t-Vs1d@[Cr-%]Je-W)Yd\,
-A+7+Kh\X!92hl\piVa/'?8D$=`IHRmit$gU3T?*Vg5!Mj%-nr]rL\RQO+j2IF;l;6
-HplD3%K(\*F?KtJ=5gicea9`iKj+JLi[m8tG\59#n7BnO+-&HBnY#iE^M"^L^U+K]
-n^$7)KR=1)13i*9^qU.k4rJ`YrKf`a>G$tJ2Y_4NDh9o4[,-Amm7Y?h$bp?cpa:!t
-rr@bZrrBoSn@/,DrM=lHj5"M12#dOj[$t>K;=Kga$M\Dqh]5g%Hqs1inSA+1XfqM`
-iih_AnRpgIm5sje_I!nf&`^%ph>CLPe$&P-iLc)n.dB22pi#YGrX)/j=nmWb)HXkL
-JNjfs'O1@ua$1==!8sMV+h$oBKC=0mU3m[E0>ZC6HmeeUp`&/iT7D;"iMh;mIL5on
-nB\n2LK\W6T*o"A]$7TCmuG%piZAhYU?>=_nMcI,,5bI2kD?o&r)`ZIiZY%1RLb-h
-Fl/"I'DuS(mi6*=07uAEiBIA,)Ma,$1f"-s42N$Je+>j5l!CP^'N%:5;+20r72/Tf
-'N%:5;+20r72/Tf'N%:5;+20r72/Tf'N%:5;+20r7=;ZCEIZ)qIb5b9CS.s=ri1G`
-fD./rhu6+V')qsaB)_l2!(n<I]0H'K!r@7.L;1)[Pa67MG\d##%JHnf_YXBtHhNF,
-jo)XAj3$>@rr=Q^R>(5kCe_[p+84OZr:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-
-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq
-8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5n
-d!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3
-dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_
-h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'W
-q--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"
-n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-
-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq
-8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5n
-d!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3
-dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_
-h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'W
-q--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"
-n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-
-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq
-8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5n
-d!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3
-dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_
-h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'W
-q--A_h=(:3dQd5nd!tjq8+td-r:/3"n=S'Wq--A_h=(:3dQd5nd!tjq8+td-r:/3"
-n=S'Wq-.2WrnQ5HgqU*Qm=uWJV1k-,=oG"UN-ZP'%"VdE08l'ZQ7Y6GM82>,Oh+)C
-L.52DO7H*:^\j*5-3!tLc2ReCPWaM<rrDP)=8\7hg(42%^Y/Verr>jp!46$]:Mm81
-QWI5!I\!EPVT%+*]8I?#V5uUD1HhA&J#HJNf.\UR\W5H=/W>h41F0r7=8r88?[pG3
-Xaf7.!"T#/o)=^;9CM]morn8m!9)i7?d\hOIK':6hR3@`J,DD.!6b4'[4f;Y>LpRX
-rr@h(q0tp.V>'orHIr,q!:]IW!&*R8e@tq_Tl4-7!5JLRrrD0Z+53(=oI]B9p\t62
-^\kjAqbm=jKtV:$rrDh<rrADXIqi>?d'p-,hu<ZdrrDWhO6oU/qA/b-qu6ZThu7!1
-rMb5F!(,PMrr@QH49#<(qEMA@^Z\nQ^[M1&LO],L8+reRr<mr'rVllen,EA@kl0)G
-rrAa2>5nT;rZ2"=jo$:TQf%EelX0Dd!5lSL^SC[(qu2;_C]=>6pil`<Qh5cB?[pG3
-Xaf7.!"T#/o)=^;9CM]morn8m!9)i7?d\hOIK':6hR3@`J,DD.!6b4'[4f;Y>LpRX
-rr@h(q0tp.V>'orHIr,q!:]IW!&*R8e@tq_Tl4-7!5JLRrrD0Z+53(=oI]B9p\t62
-^\kjAqbm=jKtV:$rrDh<rrADXIqi>?d'p-,hu<ZdrrDWhO6oU/qA/b-qu6ZThu7!1
-rMb5F!(,PMrr@QH49#<(qEMA@^Z\nQ^[M1&LO],L8+reRr<mr'rVllen,EA@kl0)G
-rrAa2>5nT;rZ2"=jo$:TQf%EelX0Dd!5lSL^SC[(qu2;_C]=>6pil`<Qh5cB?[pG3
-Xaf7.!"T#/o)=^;9CM]morn8m!9)i7?d\hOIK':6hR3@`J,DD.!6b4'[4f;Y>LpRX
-rr@h(q0u+EEFZSf[F@&#6V9;?d+V9CFSE23kQ"N0c`knPQ5c7AZ*m;f#e;\&:p\ET
-2VbCY93&IMIa!impK)RF#V<&/(-+$#S7/7-dTI`M+h!>tY-)E+)gchF1.n_>,Jj>X
-IK':6hR3@`J,DD.!6b4'[4f;Y>LpRXrr@h(q0tp.V>'orHIr,q!:]IW!&*R8e@tq_
-Tl4-7!5JLRrrD0Z+53(=oI]B9p\t62^\kjAqbm=jKtV:$rrDh<rrADXIqi>?d'p-,
-hu<ZdrrDWhO6oU/qA/b-qu6ZThu7!1rMb5F!(,PMrr@QH49#<(qEMA@^Z\nQ^[M1&
-LO],L8+reRr<mr'rVllen,EA@kl0)GrrAa2>5nT;rZ2"=jo$:TQf%EelX0Dd!5lSL
-^SC[(qu2;_C]=>6pil`<Qh5cB?[pG3Xaf7.!"T#/o)=^;9CM]morn8m!9)i7?d\hO
-IK':6hR3@`J,DD.!6b4'[4f;Y>LpRXrr@h(q0tp.V>'orHIr,q!:]IW!&*R8e@tq_
-Tl4-7!5JLRrrD0Z+53(=oI]B9p\t62^\kjAqbm=jKtV:$rrDh<rrADXIqi>?d'p-,
-hu<ZdrrDWhO6oU/qA/b-qu6ZThu7!1rMb5F!(,PMrr@QH49#<(qEMA@^Z\nQ^[M1&
-LO],L8+reRr<mr'rVllen,EA@kl0)GrrAa2>5nT;rZ2"=jo$:TQf%EelX0Dd!5lSL
-^SC[(qu2;_C]=>6pil`<Qh5cB?[pG3Xaf7.!"T#/o)=^;9CM]morn8m!9)i7?d\hO
-IK':6hR3@`J,DD.!6b4'[4f;Y>LpRXrr@h(q0tp.V>'orHIr,q!:]IW!&*R8e@tq_
-Tl4-7!5JLRrrD0Z1/26O.,IG_f"+m=B42bC1ItL[YmD+*j3&s7%bTc2OkU5#bWnBP
-IbND>\qfW<qcr"29U?OH+0s5[!@1R?E5VYi5DtbXX958S_5!;F'kE1jGi_>U)+XK\
-Gi/Kj%hemBfOk-`rr>Y4^Uepi2CnbuYO)Sp!+OjPrrE'!VuHbN0#+=O"9(DqrrB:T
-M*LYWeSAoW.&)SIU5C@nMC>3V.&)SIU5CG&o.o!*16NMlDAbtj&Af5+JiNrF#U>J_
-^,5eQIq;E0+1+Q)bO>W-K)!UMrrCb7`*X0A48^&mC%7\3[iQ@aY.n_4KO,GBoj<Rt
-%FKQAET,4PGQZme`a8`@)aj,p!/DY$3^/^m4roCOimQ7:NCN'ml:,@]#Q>b,q^d6C
-rrDFdrr@r[rP&:3qBfnU!/Gk!b9-?U!;fcGik[it^]'(Y5N1IKZH)nC!<1MUpomQK
-n,EB^Atf5)LNS'g+7o%";Ld\Urnegr'(g[k]"_eeq=sof5Ogu<!,mqtM0_DFh-[IC
-r;;#nTD5&Y!4U#K!(=M3leh2-?eN$B6Ih^G?7PoS4=@;6NQZ"l,.IN]5A_JU^5&_U
-QrrXK_gXK<rSfI9CSJu3b+81>&nj>7OaN:\Hg<->G"Ulr!,!C0)XkY;fg#1ApoWP.
-DL>1K6f@.onaRR:B$M7\XZs;-F5c!ZGb\@VQLQ5?>M>',<Oin77#;m;m#;TW5T`X"
-/H5_@0kk"g"kWbSoXi"`[7(d,72/Tf'N%:5;+20r72/Tf'N%:5;+5kJnB9b9K`;$e
-Di=Vq[?]pp:DS=grl+XYn[l]R"o]S<8)]NLYDllj1g:tE?eO>p5K8[a`*1F+_!`@m
-3n=..iXJi)*uQqA/2rE.%9CYHdBm13hbLV36S*lG&,[*Yp/NX`hL<uY^qb$k!!NH&
-^5E$<!PdTj1']1WH_45C6h$;Wp>62V!,9d5&)[\H]M%;2&:?;'Vnufo_rC-<XaVPj
-pVpPS]MILgBB&*3^M,n:Gdfqna57JOh\:>(>4C_t!dm57kr.BCnK+ejQ[Q#PE*:?n
-S?YDg^MH^A1!eSrrls3kV#LGE-fPSbPOFM2!9A+h0E$WDrrD\blhdU[!/"aqjI6(p
-J+bJnci4"AJ,Q,-qL6dUj2QTG%="*:!)bCL[]$CNDtktEa$5KSZ\SGkA+m\4]C7Jo
-Rd\-9M>AQQn@-<H&!$Q@//Fg(nFiLE,NH8MmtRDc\FApc,SOGXIpKVSDi=NZVs,6N
-d@/+ohA+NmmJKK59j^<Y2OC6*(-eEun5:?bIh;V[i0OBC[9)^Ci\/u/iciF;:I=i-
-q^DIE_-T6RnO)9%m1]@lrmX0?2o@k9]!q%&q]4r$!43!ILilK(IaC:t4s8^,8,E\R
-2hu6f06R9pKj)7/h]$=!"oc!iH]JmN$X2%2Vs^D]!.pL9!5V>+/,M.%`h+88.""5W
-L&=18!"UFOl2L_dchItH/RA,UDi`ce^Yr&i!5hq6"'Y5M`p\e7+1r'B*D>@(r$Hk_
-p,8Nr_S:b2%fRi#C]4nF!;K/>1k-<hAb_Df!!k\.+S^ZHBclhDIubZZIPq-*_+B,h
-Dq]-h2sd;Xih+n*a'\=3^OtFMkJViTr!!%nr'12]$VTJlmE+<MDoE?'(8%pOK75D$
-e))#A3;DgURWKcRn2J/?KK@tBYP_;u!/*;L(0]n>+,'V/f!TFQT*p*Ff>$7S5IMnm
-nQ3XnZfd&A)gi%gRIM65^[P,Spa8;mRq(JcM-g=6C9Q9N8bdr-ch?`#47QClf/e)_
-n/p[$Ld!)3DuH<@Fl8l1r$o5)FRP+d,*1`dJ`8<cpn#CC>"?Af?I$_f4ta_NXM8Y6
-MI%_0XF;.<`a?+I_OoMnj/7jNA5DtPTDT;u_`e_.`Sl:UI!bWAiKf,i[J2EF;rVDA
-j0&sj-.79W58S(G5K/,(]!$k]rBEj&]Pm=Yih+(P*,5C"\,QG]Qf+Am3WsM=?_h$8
-5A\*gqd06+r,M5h;u"9-)LPliNIPKp$fXjpn5(dlP=#5>^*ip(h?3O#nJB*W%(t-_
-07f`*IOY'Lp<`U5i89>t(&SM]p3o""VdR+*erS`Rg%41QT[>l;j3&O%hB]>pDNWn-
-$pW[OIinY9Ib$`g\%lnlC7bhq:Z1.*-qD.8g1SAH$2eRYq[\/2hZLMIn/K='%R(87
-*uk1oG`,,fPP[prPMpDErr<33pecC7?"tE$nJ8=tMno>mZF6IdI6LF7r'YmmKU1II
-d<lOGq18E!HuA`Lj"L0Rn,*aOim7!hiZA7$fDbj?[m/fVhm76SIN%Ld)'JmPkP3Zu
-VdHh0Tmpk8%:B$1nP@/q2tj)/rYK4-]Kc@MV-A<le,3;*4WiXTJp\pJpeSpP%fS)/
-T1.=Q?dN/3rrDOihqItIhZ5t"S):[;MgRV`2bWW^rX'hK!!NPT5@[nng!@RN%K7a=
-h\SHcG\?"H`@m;P!"4/hj#`=UB2eTmi]dYF8_8>/F7>efnILL.,Q3pW+)1^:K)YgP
-d570aGpKhEc'B14hu<Z[L&JOZDu22;_(S#hO,Q7,rKMfj>lNS%[mu.%@G_ZE.JR];
-T8VE9NNGG(5PU$(hr4!cn_Ze1OlDFY]&&/!+8A73hhLu=Nhu4lqr-/Gn+]U6T+BiS
-ZJ4EkJZh6`g\;TCrrD[+qb$d#rr@e%paP6!MADd%rr@`8`B&MH,G#SDA+8saBDrL8
-pf]m#r[7KM624aT0B"kf-.;$]et(`kpfcPlr+4f)LO\fbG_8eA$2>J=&o[P<]O>lZ
-pfg5=2%*@VCA9C\!"Abo;o*qkmef`X!"$u/FT2@98GlW\45qX]2uFmbn?dX%r(lj#
-^%"VQVo>;'6t4\hXZO?`n?otbprg]B&O54VnG]*['C[sY,iA*IpcdG.n@"=Ol1Vm5
-Do+_s^E,QJJ&/et!!`H'i3/RSm4nK>GdmCdpeBeHnTM<)`R!8Ep5A^bn5J@jJTL^,
-Gc17Ee:&3]AG?E"/)kc0^)#uT"k5^OpmMmk6bj``pj)Bc6h+fCr%6qn$N*<=4@Nh2
-IB!1mj%oG$QgM2]lJK&M!/\I'msmXl[X[7trr?qt(4OF*')e#A!W*0%g`IO6D=Qf*
-56lRQnAiCq'KfGUmG79(`%leeIg#[liXHu7pke%5"2Omdpa>'\>JM.POl9S)<RST*
-IrFQIf81#ohsa`TgQ0.BZ`!^8VtS"-!/)<b;7cN_rr<2`rr@Y5Gjk?#rr@asrr<>N
-`T]Q5IaDF1r&O<-i4m//!:91L9>BFtgA"n1=,spRiGXPpgRmuCrrD!pq!4T#7+_,#
-m*GH(*t%Z/LAq8-*uB?4rX(%Q!!SSVTBr\XrmF"GIKXHd!"(nEp]pL]poj2-iA\]Y
-KfV`jYPVi-9@NfEibQjRHm6#o^Ypg[J&+I!*@HQUA09KCikL2Srr@pXrY`3??a"]e
-p41XT1#d*ZG]`_Q=M41u`4<SdHoUeKf`Urbrr@Y;rn3n^rr?fY/&D'(ln@l&p2g2"
-Ir:>%X7e^-r-@:-1ZS4d^,=gJ!5bN#Ss=0i4):9d_JLsEqA4^*hs<!:CVCnAIPg>6
-Ii<\Vrr<Ec_Kr)ciNE?.A)Q4KiEIrNGgl6dp)X+GrrCuN5750`P999eO,<U\)a4s`
-D"3kZ_uB]?"n423CS:IKp5Si[n[mf$`*\:+)>Kcmg\.f>[u5WHnLqqgIb"9!X7>(Q
-d^<EbGUcLE<YfY%+Og63i&r:Q^cIs0ZKC=AnTKKVGCohpi30o'ooFsD*o6`]nF,`"
-ih$G>^[PGjC]4U9nR"TO?c.AMrW;UKNBBp!U#R"Q4o86,4n3F#n_<%mQ12g\de'U/
-L\?&Gm.K@6"ajS)2=3cK4u(RRIQi!sgW*JEPOS#Kp.,,_K#rJr?aU)hq\sp%n?9VL
-pfK`jIqdfo\mL-j!#!!MHoq:[Ir5WYph%k*qd&ubnOqi;LW99[rX(BZG_a4%ZF@ff
-pf*FOHb^[FpnMVtHm/!=[^#e/ipR?$(W+qQ%dR;rL6($&rX0,2EVSGb?N1"W?@LQL
-(jlei./s:a\c'0*DN>/(_nI>i;t/DV58U]Q)d7a.J+4'0^VekPj1^HA,K1`<FhJ0u
-5OaMF^CBhY*D><bpVX1mhsd(K4s.Q0A[f^`"($@J\*u&errAjEi/'WXrNEpZGan[>
-@<_8A!;;8r^+oCAiLg#^rrDc9par@V3fej+-`;g.*trlT;#!m6TDU1r(AQMTM>340
-HnkSh[(Rsd=gRTfm+616Y7YLj$e.%(eDg8PX4n#q-N!PGMQ)+*!$4)6p$$Pt!2<f4
-Qi7<OF;+?JrIu+5O4`dlA0"HaK"_O5d_D6EnU(6B_=/Q,=n-G./AE8*dD)n5mDo5,
-"f`XPJ)M_<1%DB\`=M_kDhpRgrrBlK8&7Fb<o[B_dFU6-:\I<WUOESu+o_Or6@9gI
-SIa\.Q/W;pJ&2<dSac&q9^+dL?bQH]^[P;Xpac[;>PgNtJ$q;RDqH;M4tHT'I!b?!
-p@e%6_dT9RROl%j_nV'N""esKrrBqgGW*J:"89\'^W0.),Q8HCNW'j*_-`&U*RK:H
-0A,a3,KCiPdsP*`mdj?GIB!*nKDs2Hn8TiCTCMO4cg6AD:C_aRn.)LlIb.pJ^Yk]4
-"ScWh/N<B5rN,Y9,N:r)rEJ4"]m9VX"blK5__2mCIP+D$lbDr-J$_)9O5ShU`)cW$
-[thU0i,c$qMoA_H'f6p];Xrn7qHNL)=7Le-#QFc-h!iANCZEa!?QQQbfrMtSn4>3I
-p6sFD)uL9GTtWO9bbFRdQG<<+ks#OD]PleZ(k0`e&:P=<qo6Vd!9gk;%ZB;L)>L+:
-n:ubrm9<QZmX_3M>5l.4l9C^Zn4"Mp.^/aaU\9[spa>7kU:5UQIPUp'_GC%5?%18[
-)h'erd<`RGh*9p]GU)16r"U=58*lf,7aa0?"'b(p2oS!&VsN$n9fKuh$aT<RLZ(C+
-`*X:&#lZLT=8:D,O6iuq_-[a;RJhtli3PYV8*r8*KDl0)Xn]fO^U#hNn-Aq"Vm$+#
-_+<uGIMqp!iMXX_pqcG)_Z'V@<$"//"6fJD*-FK,RZE("/F39g\^>L*Hr]/s^Lsa)
-)KJ+JZ#?F_<lRj7b3MIpRWZ6dkuXMirh9>lM#(398*ibG!%%sJ%tE98rlDkNY!*cU
-g!u!Fr/=f\rIK+k!<"P>h/-"X'N%;K$i8KB(&L[LZc/QFLVl?3?P5S@N<AmopmM-^
-"jm&5q_*E7^U8!<5ASRekTB:ic[qeYXSt*T+7[96ZbOJOLRojkUqbkhrrC.mrr@b9
-^'".%i_S6/ib/0A]f0<,pgrrM_uB]M4@PoX4ppeOmr+-a!8sZ&*5"N+5Q2&8i2]'L
-r$[n(rr@XVIa-aT^+fHb\@U&b?M]G8r(Z\dp-JJ7nc&SlZ1u3f?93hq`#9B"N4^=2
-BprVBJuq3YC(U/PHg<c,:A7bShc[D_?f<sA(&.\7'Cj]5\*`GM"2\@brJ`oSV1-@t
-n5$7?]CssjeGMc)hrAp>2%LT"S)`Dm#2ch<NIDCBpb,>9mGSFgD%"9'15B2@n@uq6
-4s@b@HmA.,L3/IclJDtu4DMSp]^aUk5M9t*+1C(FrrA)Y"9"_g+R,N&O6n/6K7@Pf
-KcdYa`@3tupik^.m";D;,Oe0pn]TnCJinI^4iI=OrM@4KI!F98083;K^@O\]7\a\p
-4BQit?_>3H^&J(a]Fh@%?Ka-/^W[5-09"eqp!<OK]D`2_j'UN4`ubXQCp/R8#J]2p
-rr<a^$V0\ninoI)BrrUUS&F/%rMoktA.'t:rXaQ"pe1>*e,3eHX7gH#S[Pl'l<b##
-!+rtQh7fTA%hf=4btI(mMYo7W^#8nj&:T5Urr<4FrOCV%hC?:L[/H4upiC`\!!Ua>
-rrDs/CV_&,S)CKhl25DWn*M,C?\dTYm4%%u+/eKhD4u3trXdn/kJI(VO8]W'*t<T*
-rr<EW8^[50(W4!&4qq=JP>9a-.>8$)(C0Z*^A*WUg\,*gn8H1'"6//"r"KtH$:4P-
-r'U8Vi4ms;p6trW4>X!^BD)W#++nr\V>/Bqn*E"&9B&C\a+i2p.S9/G_-/1n@;#-!
-iYJ0Ua%u2+N-o]G[_(Me&K?4SrrB@^n4kXj;tc%GVS3Z?<S,!"Dh@iS_ESoc2#X5!
-/c6^[LPRg;K&7GqB0AKQJbVaoC%P,4iKrp@iI?E.+$STP5N-d>j1c#tT%ciHn=PMa
->N;^L]M7?l&P2mG[CMml_O_YCC&\0b(g_[=+!,o>5DHq[%%:8bQfF.\b$TiE[0Ei(
-bP%V-XM8Y&N5#pR@P<W=!#IKLM*D`()#Q,X^Q$!@^CPeI?8(i6c@t6SBsaEU`0VD:
-m%**[/CWSPM#:Q;0+gk;Fmp3(4A!EDrrBmOJ$b8nIq8$&"897o-c/+$]34WAlpLY/
-HkH-dnW1RKO,gS!8&X-Er"Q'gYK!1DHn*`1:[kah*Vf6rX%Mo+r"JD6H<.;NGc/A!
-0%M\g-fQe>3ei[o)Ye%:>>_iXr,q";!IZ3m!!Q]Xrr?bm)u^jHV1-fU0)-7Q)fPWj
-6iID8W-CPIT*;qLq#:?P\"EB?pg*UM+RkGKIM6thifD.+ZMspA48keGCH=Dm9eYO$
-kPQZVn<`FS)SPoOi'7!<2P)JpVL0fl!.r)ediLRM!.oLr!5TlZ!,G;9^u#4\^*A*a
-5O_Q(L;1"^`Z5jjnB[0Sn5"f<)>MD8J*dL1f2L9b)X5j<'5oba+3.2k?OAnWG@@KG
-UVr`Zcm%#DFfFdk0m.,M@pu9[?])VVWh1=r-i>"`]`%q\gA_-_rWW3,ptl>CU]1;t
-$h4D@r"GR[Do*%=0B#E\]M7loiP375N&P&Zn^#(5g@N4s)mt0N5ITa+Hr"D6=[!r&
-^=2#lLOWlr(3l<?ZhWAHa5KgQ1k,[V&^hKTH2BLL_+MIWm:5inrLu.;frN"tZB)eN
-LHk9$DtkV#lkApLrX^.kr$M4'n^maU^9-p,p'K86Bs7:uHlq@OphJ]?g@)mc!r+iD
-n@jPE\&77GO8D4fg@O\*IQ-d=NHM;Fhs:V1Y6TQn@=N/Zg&o6bn54+\?O+4Qq^D@l
-piH<KI_u*bZ7kUaiS..b?5`OOnUJR4a8@b)lm6fO>&+';!]?o=0C_!Z`eCVp]3UIr
-d<+i;ei3R7rr@b$V"d^&::^--nRD+L7E:6K'RQbU'qb32pmL-Vpc$+0hmTH!m=3/`
-Z_t`[MZ3YXrr?N3NBSAtphTC=?d\dgnCRXU?cCpUhceS.25:"@n@W':f5?&^Tm4aZ
-n;a?Hf\(M!rXp4uHhd#NX#iI:j%`sN^(5\AIiQ0Dr*97%K!KcCp]kU38Gk7<&,QP1
-!5Uk3Dl7tJrK0>&U;+&gMuNcj?]/XqIXF>3ibui_LS#9fD[uQ+p6GTOrZV&`p29D%
-_)iTQ)16A]%ud+i4r\luK2L+j?\V/B)G^NDGh^$Sr"Ms+$:jX0`#l5XlrDuEcO0Ru
-Mb=!LJti8F_'-SOUAk31IQuUlBRVU/6c'lkpjN/B"N5rQrf(FWH<GW<27JA5/"[](
-^JiT=4)Z%kHpQ7/nB;Y+G++tfWtiX\F5_VSn,*njp9`3G!(ZoFrltEJd#P1(%tDDL
-5N&$B^VfLHg]#%h!4I[Mal76mDrTs"+4t3qps#^]?WZd,m(q`NLV=5rPr("lOl4Q?
-SfP?9V53mh%;Se(`?%.LnJ(h#OfS7]_d@!Q:&b3F^OF_j$beLr1P>CWpc78>pa<93
-rrDRZi*YiOj,\mX2#XGg%=E9mL[`XLfBi\1Vo!6/c\WaL^Vo$`hr4$^qurdC_L=Q8
-7_:"VnBnXNN1[E]`G;(NBHIT\-@X@7&H!uSpdT`7r&!q6oSH!N;+25ka6\"0MrJ[Q
-'HgofIr,Vpocp[,/c-3AhbWEBO<:\cr"IPqrr<<hi2Ib[:B>^Tq\)9q!.oB=$XD/g
-mu&:W\pap49`;Cai1kc95N&9XXaG*_MrP?C.?B9K)Gf>\M(.@9JlfBAAZtIjnDE8m
-_EARN4u`"<Oe_hsnAiLT''MM"D[ok7#D_C3IrF5uM8/?*^L@f,5P%s+i1MIoejo+a
-rr=B+qd]X+ft2^_TDF6=6Efs.n\>!^*[UgdYg*1JrffQqFT2@1CfgOu?eQ%i`P:++
-!<3$prrBE3Io"c'r-6Qf!+E&DJ*KJ&f$tMs*ut7aHmATd^(L/3i((h;!U*l(4q`6:
-d&$7#NI2K#.&VJX<R]fL0.ee.m]>TYeT=N07+H-*2=CqJUHuZCr(Z-''5;b_M>T*/
-koM"r1sJeIjW![`-.hKjiXJ7Re\$=gT8NXK)"h0)iCCm0Jp)I4m/d)brmm^K5,$pG
-LL7CnL2FR<nXE8JAU3gdj,_+dT7jfE`(pTk8)Z*4q!6mlSe:MRhAMXR6%d,&Bj-Oj
-Bl\[NT<Un>4Ce7>Hl)aO^(br5peg'9#6)n/n%if.KO51;."#(jjm[n!n>;iI.n9NR
-pg'ls-iL.G'?T8VNut^c`IEWJ>BkL!dJbi`SfINniboS,B1)3-_EDqk9Xa`,Wr,KY
-GJa@[ZKM,tS&,qJ&V"Z$M1;p__f(5I?BtC`r)`iY4t$7bpdssNj%m]K*Vc,^Di[+n
-%ftrVIZO@ml+aZEWSu1Vlh6"]Iq^!^?P:"[j0'Kulf)6=UZ`d3DtOQH`7h,K4tHP*
-eUB#nn&tS]8cJdB8H-Fd=,j$NQ#Z;ca'L=lNBbHZg%4p&^%)+&`37m!p8.Pfj)%lX
-?gOhhprbr$TDWE*GcThB`h+%4]&3E9I1+*P.+*/*%Vkb4^(]%=S')7&`**YUB:sKq
-*@n_kVu.34p*oclnZQ9tU3pD=?i+?n+,R]mIa)6,Y.*F%pfQDhFT2?Lr+l7m4=B,Q
-"+JPP2#dQ/InT=fQ\DQViEgb5`P*JCrrD!t[*^K'-fX%N&%;8r61Hk.Bk;L*L%%n;
-$$H+]rm)W'ds`D:.e$6QI4sP+Q_AZi_X[O-nOMtNqc\A@rL:2:%/`fJr(X)6qnp,l
-rL86`r,M7f^jd*_?7V)V4sn"ooT'Z54Os*"p"`s7`.Hf-6BGr%*t&#Ji0RfUJ&/=E
-^B$MJpaa0F(%-H\q^lJf-1J\9jX7tgg:-d_pqbp]Jt<kMIt5k_%h\S\iQ$It/pq[/
-a+/OjTk[m7>>GYcOf!A8*Br4Rd^163Df9^Ur=XN@dD+V*T<QXsFT2=EkW1*-rHD!*
-Do4fn8&=)j^V[1/[bi%<5Gu@_KKgOU"laHV?8:rqM`qZ!+?pR0iJ59U$K&eZ'g-K:
-C4?[V*;E1E57;j15,i$6M0p,?gN[eW0^.\OrrCuCT<QYZrr<^[4n0&:^(9P<RTI?J
-MYbrF5D3AMocK1N+8eS)2gcqH\ZP-<1"G1%T*p-[D\;nFe\>_"LH=jWXa'jG`S0L,
--1GQaN=lbWRdREVhghBhhQ(@gh:ccAF8cKJq\8fui2>qlq`B%Pi4nu8_9^d:j/.J+
-9)d,m&,uW`NU^WLrY=V9^C9nD`h#3<4DFfq#mKdXmX.smhm%F(iZF+::\[FBF055,
-_KS6!+(Dk/DD^`F9=2#!:EOs"rr@b.nZUj]`=6b(]DO8M"9'(6M`a5nn,"&BgO;$T
-kJDCl$bRSOBDrP09ifG7[f6>]H15mo^U-eS^\C(_FT#jhIP(R"L$em?$$N:bC#Yb>
-*X:+G^!aYSIM)S[_'FM<T7R"Bn>>S8!Uu`%?gru&cTXC>ME_5-)#3:fQMme3/Gp4W
-?h#rO.[b.&,'Z?1=2g5[4uW0rV"j7Ie9l,mY7Pr.`R+B!qgZM4/Cs7e@A%?RDi/qE
-@Qs*Urr@XgI`M;GNP6]`h)kf"XUG+E:QDXX-%'A#F5YBu(\WmY+7/srO2foAPG78I
-1=j/kI`u+)ppHcDc@6KliFZd"#+_Z>?dlZ+n@)]OIPKS8W1Od*4CA'!XrU$kJ(^=j
-#g)!6.ouVWn,EB(X+0nLH5Grfrr<3Hpu2*YGU)0SL-K?ig0oJDm8r8=MnEob5DYp>
-F?bh9ZXS0G^d#1*!5sp=BV$jGPA4DWdl_:4fA^\!WnUX#CIQ#.5Dlg"+&:9AYH,Ai
-J&*C[@%WH$n@:,5J+0)N?gru&d,$fZME`'Z)#,'DQMme3'7:MhU%'r<.;<\6,'_#`
-=2KHH4ph!EX*Er2e9hqg?P%I7`RB&NqgZPU/C?%3@B\r7Q\p1H@Sa&=#6)kS"[?VV
-pfp&QV7[WE!!m680@,ZN&:\D$Ma-`/pp7nGn<Noepo"(Qrr<AgNBcF(f<sN&0C@Z`
-/M$fLcOGA6GY_$10DnDK*C%l\o=f+i^YkEMYg8)Hrr<5d3[_cBG>7RF_`ujF_;DZ8
-_QS^&h]'9oVntZO59B_+ibsWZ1%<MI4qE#`589UGLVd=(ho+Ce4E7E:IgnR]pe/Lh
-$[bN0WFI$,Hl&j<G]UbVkki-am;LXTreS>ehadT,VuB:I`LlrhDu)%-nid!QjuNGA
-P"krV;C*CoJ)HfgZ2Xg?rED_'pi546*I)56hAPk7V=?(Qrr<3GrLn^Sm6gSRn?7hZ
-%i\mR9XiTc/,LW-rr<hB&(ulY5OaX09@Op?:Ok:h$fNG)V#3+FLSs>W3;@o1iL^hZ
-B>_<hQ?[KM$*F(=pe0PCm+(tpG^nYdp4'p)f`U93KDS:?cJB*3!/6F&B(,^6kJk7F
-pp7u33RKs'rr<?/muHg`;rZ]>Gc0OCN&=E+7m(jppm]-E5MI8h]?kFPm6=7NZLr^$
-rrB>p^e]Qs(HsDJD"pld4a4\J1AKt6lQ.\RX.so`ia9YT08+d,n`P_dn<LbF^*[*4
-!$3t8JGO3'IhYE2Ih+Jq4tC<=%J8P6^*K:5?KYS`4oN]`]M1#`oSjSdr"ERb#:/#.
-!'No-nR!_p_*1%/pcUiMJ(XWfrnl2MVr9;^Qf)5&Hq@eR7e\qcM``*N_nuBnnOJ@W
-8<o+dCDm\lVr$[,V1le,EG9]8/5jKaCZo]@r!*0$KR<\10DIrL*.PgSrr<Agr%1_>
-7XsA/nFui*hsduP!9%Sj!5e.'!/6L4MuB:HS,WHpkPQr^pq+<1Qi3EQ&g-mOrrDRr
-Iq\i^_H6a;'5I)6%Xu]QY_RkF0AM$'Se:pi5@r^Zr-Z0/]N*sl^Q'?Tp_E;-6hnE=
-idVt7XBTr,`-3:9oZmnKps+;7`\uZsfBrK9X@oZRU#HnHc!i82ipo6-ok31OQbhS3
-hnU?'W5%9op_Wfjpac=]rrE$3n+]`:n;2N:pj:u7pekJg[D(,i!"2<r'c6R&LTJ8L
->CXN3qebNo-f=EJrr?O.!5`7>]:\jh^U/CaGFoh'%fXKJ!49fE,<t\Frr<-#!,'(#
-"9&k8mB?:PJ)PSK,5?NT>Q,3fpdm]UJ)MUO!/,"a'>G&nhq10Jhq0t3p=K">fful/
-Z#lVIH2dltep^BgKmXF.06e;OrZ(ICJj'uu)Xqs0r#P9n8,*8H*uB0'iQm.(4lUqu
-r!DldTl7!q*sI$PYNZrgSu\R_-.)<h4&&L@pi30:gA!a'e1GP+Cp[k.@#@tZ42=)M
-9^gWO^q[?0+7N)cnHPnpr,C&+muIAsn6MTo_r'-siBN&Z/`M96+m-0%kD8ej:\Jr0
-Sj!P[;>B%P>BjXSnJ?j@3NR\YIhM`?C)U]VipRV,P31e$pku4Jj(807nXmf#!!%7f
-_YWE(Y'?j:d^4EQ9tJ*hodf?qX_b'iD.73sDXOZ=FH.1\M-<IkfDqT@f?8ZK[[F(-
-^TaX&>GQ#bG<0oHVLHc3Z=SccVqsc6pNALHT+?Ai_0'I7"G(*<ined%Ar5#"E[*(7
-5o'(s@aG&S,8QRE!+9)^rr>^)2d96Y72/U+)B\`%a6[e!_EZaui'mCUr<ld'8c*%G
-=87dFch<Cg=,=9Q)>KOopk/*XiiMtkkDXe6Dfr8YP>]qY&$E@AiI;=&hA;O;jo5=6
-i:q`[D$NW%5K!7Y1#a3;f2IT]pkA_J"LS,^IOj\)1"?1Hr#aO<>BB<jiCAM!%/aIn
-<VYD?rUg*iNh-gWD;h%$_I!apO4jh1LZ4OZ=3'cerr<N#X`Ad'LOU@o1>2H_j-P=E
-9r7V``kE/^M55C>_*/@\Zn:/8rrBkm^LEgi*Y\>Ii,8^F(]M>A\*ZWR0B$:)ea_*]
-rr@b4nRkf#!/0OnVnkTLQ_1Un_]K'\[oi1WTr@a!rXkcTRYBXOrrD"&n9s2Lr)p,s
-hsc_PK3m*@;]JupI9l?WiNIi^%"'l+GOTt<Y)E;[#iEOlKcUEeO2G<)G^'$T<n9L>
-4;6XY"&JF$Klg\hI=D1r<S)A#m&^XfYd+2Tf!RY2<ke,ge#?^2?;!/oT,N)Grr@XS
-I`"AbFT2?p2aQu+_>SOq#6*2bmAGlWBO?M.*VeI\rrBjL#lZ%Co%V+?%6S,Z`643p
-*X2>8iP1*g*Vch>GamY&J@0;0Hrf`tKY0P>(WH"1g:Vk`nNO3pir8ur6a,qX!5l4Z
-@\<K@rrDY=+7Sinq'b,9J)p:;kd5i\p\t5\kPe%3rCE3-IK'9M[/G_soaO]'ZhQbf
-pfGI=VsP`!L\A2!'##FbDYX53nB^+VM=L'.K(.$oK>'8=ZbbN8rZ6GbnAiKI!!6h@
-'RV]FVJ/4NphAZi(?chJFgs8f)G@gK^!;V6c"Zip_=)u*%_`'jB)BI&%WpNM)f94n
-](&:I]L1^T*I.28YJacepmUAAdkjAM08NsMr[R]4`h*qD,&=VN):3agi6<3Bn]-R#
-6)\H<"7Vq8]EP$7C&SS2LPBn6/)sE\J+-$jfRMjM_`^BFT7B$Kn^Bbu+fb;RifCu]
-rr@WM!:\^W[aqMK;L\iIB@&bHiP14Q0Dm:?C\ES6IN6?,!!ssDNkAAkIqZaYR.Y;<
-`L=".-X$]QQ/c'h2oHJY^*<RWJl_ldIP91;oUcoucC,Q,1ojF)e&)+bn5&@E1W3TQ
-plhiEp><0"Jc&6<Gh9c=%W1S*58i826a$2O`a0b6Hs>QZMm:::)LOd/D%fIl[%E.t
-R]`,mG7O#dr"F/F5Lk8B"1[l&J:)M0(L?fMn^HGUm2t9$)uNk;TmpbEMr,1)YDU'r
-5N+/CK9oY('YYsm>4HOLD/[5)%IZE-j8E?%Ig:,r!#01?#B[(ta8S3k'KuWuh=7D"
-[2i>&e%ah'J+-5s,?FSTX6JNJkLmW/8c3\7rM0>rBLCdo`q__1n/LAhQ]8DVM"BGM
-#P`^#`2Pj,n5$j6+S"$mr[@<?_;Bs\*UoE3h]M.;++eAmDr<hkJ&8kf)Ye5oqu-n9
-q[DcdL8TI'r#aO<;f-UFUZ2m#cOBSa`ZH/65PW"/Ig<\"r-RqX[t4N.p^d(9piGG5
-MH[K>Iq?;$`*NJN[J5#Y([U2@^P0#h;rQ4TnG`L)e+eF/\^:m&[Jp40Oo9lSN@+Z*
-5dgA_j0&XM>5nT<^P9M0=,o+EK`;%Z\*ZiX@nHI!n5J9F!.o>HL;+2q(\,78pdt"R
-_,c%+5N*CQF/rYm!nYA?(h)sLM_@1+,[M58p$:uPda#]?=44kAT-(>YLZ&-0/GqNt
-5=4kZQ2>-?..A%gce9I,n@lTr57MjM`W#oDrYKr,eNO+`4n'PKHnh=>P>C]B_Q=3_
-IgJ!'6buqo?O4$b!`';tp@iJfR]V9trO215:Y:<n?ML`$,\d8YYcj,e)#jSSrlWqr
-JUSF526cj[rr<A'`'#Wln5$lYh[&L3%<PtP:%Vd.C#9N!rr@^io>&'TS,5Zn(Wi^n
-+5't,^ON9&IAnOTn&0_/$heK5\aa`-q!%;biD,*dIu4"L_N0L;!Nu+]X3Gh::\!&P
-hhj*EIPpmVnV=tbB!#Y&hi;%N0CEAC=joPTr+5Bt!06t#iGTB8hfu?ARQcSfC\u@[
-J!<n2#h/eR"QM1\,!A<O-G/7fT8)514t1j`n.r@j+-6F%[',J%:#Sm!^DQq^l9>@J
-BCKP'nR%3g0^F07[.mL4nAAK#*eWtViS&%e_B0#j%i4rh`P2\cIfoJh`dTB,#-Zib
-rrBkf^LI3C&*b'FXl(9(r)`YRWp/CJ4qE#S][Zr]BE%tc\+[3-Si%#pr&XeKr%iKR
-YCelS`7rUhh].(eh#(@-INA2AmS=.6HcKJ,jRIGT+n3]V=q(BWT1[S>qb(e`LnF02
-DqLuITD!`+ipVKrHjaTe!"-L<6f=#YINs5CpiH<gps8pR\,7F(HnYL"KqnMsHoplU
-Kn!`"MkBKokl1VnINA2R:]CEKU[Yn7rdTG^*;hnnGGoqr^qKp?O,()\\gX;1.&+F;
-rL#cfiNEZ;E;dNK/$3S&>'GcUrr?e0#l*9&8%Fm0e8DoFW;afoZ=elmHpn4>0Uc8g
-kJU[=nLf_7r+O[E;pdHA1E`.Bd![45=SrBmQ]:tfHqs17KYAFNBAu_+YP:Nc!9%^@
-61FmSKR>kVGiRe%r#f02rZCVgr%&p*C"e!D^#Mo`6SoaON>'0Yn<.N)Qi&)>7E!nt
-O7kXaA;.a3pgN.k/&hMg[ib!KY5!J:*E,SYrr?]HfZV+"L%V4Bf%,:!d_6k'gR]Y>
-ZjV_PZ:1eGk[#n2^9)NebU9m)fCZW878(-`g\nBAjMsK$J,;0Cg6;O::nNPDr_MB2
-rrA2%`8C8,e3ET!lhdRZ!/"aqjI6(pJ+bJnci4"AJ,Q,-qJNRPI3n?hrBeP$:qDCT
-I;*n8Vs51sXlZ^bW*Wi/cXCHJ>?oo>m;6o]E2Z&nkCr&QAS'6fhm*1]Sf65['7M/*
-!9IK.g\*l'_cm'?_JdA"r2ZUiI`MG4CL?j2pl#.PQ#qLof`(rt%;YtD$,7(%nue&@
-q]GXmXaf:gi\1:2dJ^girr>/=YP]aF7K3A1\j*[jJ*2Qorr@`0Lqiae8+unBr:&:P
-n=/qarr=P4rnk!\!1k+\rY'`)rrD.d+5?KRo>=c3!5`Zm?i6t"qgQTbG\^[]:&'YH
-!0qYUDqP'icOF[i!"$CPJ+Bb'mJA"$iN7Ug2rZLi<RLc[A,cNk26Zp)r'gVcb.9gH
-m!n2Q[Jp5[hh]&C=%Du_O8SLu^[R`_(]OIbkl0JErrAW/fDZG4,6%Z)>p%hp5P)cr
-rrBoS`*`GCU\fM\rci3cpeCOArrA=+IrF!>!7)*irr<A?&V'ASO6ufdq;JH*iA]aL
-r`.AE^LR9D4>j>?-N$=4!6Vl;\*SV-L:.$]K\qU#q,^)[rK$mGf"^^DnJD3*.d6lh
-Z2Xfq)V=s%INndlj]rt_p-8/d>5nT>Do?#\X/#Q@a8U=!?hd@jMuNdBF<,\CJdoH$
-5o:a>CW&UPH@eAe\H]cnnTX?=q],N"nIDDTmiVPN?aJpUr*-8Jf364PHtiI/p^b>m
-,h9&"P4q#7]rufDe2:MuiQ3D.]=XM$,aMn229l.$_\`<g+7s'8ZCh+>^V[bbFgQY9
-(]M5moOFN!TDg"K_S?(m["#t0rkT]KA"U'!rZT%n^]&A_rrDh(0A%fSN,SDdrrBtn
-peUnicDls#@kZIbretdh;#^O61\acG!7%U*pgYu0/,kKGp/(bh`&%0arrC?EXm,ic
-Z5;j`UhUZk[ZgS'I`pGGWM`uiGGj_0DsVuC_SZ/hmbPgC?!6";HnU5$CRAW?,ZDT)
-9,jn:3j8a8-)t^Dlh;0\f%-:KZ:h.\p\2/+g3*C[CM@X^hq?mF%J?"$T0:$"93Y%^
-8D#>&Q<&SC#sBSUqQ&CSl8iOWQBU0/5m@7YHFAYUpQiq#:Sp\ulumA<o%h1lQ3'.H
-i6B2[c7U?!A;4(tIrF!>!7)*irr<A?&V'ASO6ufdq;JH*iA]aLr`.AE^LR9D4>j>?
--N$=4!6Vl;\*SV-L:.$]K\qU#q,^)[rK$mGf"^^DnJD3*.d6lhZ2Xfq)V=s%INndl
-j]rt_p-8/d>5nT>Do?#\X/#Q@a8U=!?hd@jMuNdBFFS5]rrC@SC]=A@^CbtdY)huI
-+8OltJ)N?G0E+u!rP)kB!'E-Br$M>1rrC3Q5I^!/kD$DE!/06c^\Lr$pAL'MnCGAD
-S+.<p!%R43hm*1]Sf65['7M/*!9IK.g\*l'_cm'?_JdA"r2ZUiI`MG4CL?j2pl#.P
-Q#qLof`(rt%;YtD$,7(%nue&@q]GXmXaf:gi\1:2dJ^girr>/=YP]aF7K3A1\j*[j
-J*2Qorr@`0Lqiae8+unBr:&:Pn=/qarr=P4rnk!\!1k+\rY'`)rrD.d+5?KRo>=c3
-!5`Zm?i6t"qgQTbG\^[]:&'YH!0qYUDqP'icOF[i!"$CPJ+Bb'mJA"$iN7Ug2rZLi
-<RLc[A,cNk26Zp)r'gVcb.9gHm!n2Q[Jp5[hh]&C=%Du_O8SLu^[R`_(]OIbkl0JE
-rrAW/fDZG4,6%Z)>p%hp5P)crrrBoS`*`GCU\fM\rci3cpeCOArrA=+IrF!>!7)*i
-rr<A?&V'ASO6ufdq;JH*iA]aLr`.R4r(6ZFq`4Re\C5?p140)s>Od%.7YXQQ,4FNh
-^`<O:2:e%0/@&&'^703(0*LT>fYJi]b:CJG,Z1qS8Kh!W`;,bt0o,*/Jj84Krr?U]
-*e37qIMHMbDtm>%LJEB[YGn^Mn3;]B)#PfOWd$>Y=2R65r&*tlXju"%DrBN-?O?,4
-"6%_.gr11:h8Q)_A&C>KN&;!MJf(;qQ5JIE*+EX4'.`',[QV=K^[*cR?EN9[Df\/0
-c21(>95]oL`Ofkl%Qna0$Ze)',d2*p9+8!@o%HKQ)a&IQ^WGZYrrDULGaJEI2u`mS
-;"ae9rrBm??h-p@BKuA0rr?^3!<#.]d<5C];+20r72/Tf'N%:5;+20r72/Tf'N%:5
-;+20r72/Tf'N%:5;+20r72/Tf'N%:5;+20r72/Tf'N`JM[hnt1=7(S=!+re=5_&'s
-nSNc>+-$:#jDaWBrJ#7j!;)uNqksGoK4;UVRf:Z`p+?9irrDnFrM&WSI/#MeB>K'/
-]GGqS^D5W'8&!RC^*EPgZ'oGMN;ikpZjS;KZk&+%47Ms'B4muaHcLG5Ml5:nqC\&2
-fN[+_C%foT2TX+%.nLu\f>^HJ!rOp-o2Ms`rrA,Cde#1-BY#Og%]B1hIaF6`lIL9@
-cE1l,qH_@L`J\DObM,TFR2lIeY,)Q-+p*\GO.n`An:TX``,?+;Gb;lTh\0mDY@<Kf
-L]/2&j0RQUpC@m1elVB1nNKaTh+!Psju4EiD]GgBFXN-u4qr5Ob>Zo,U:9[Y7;70o
-CE#k8j7\3_1j8U+7"re]=[arC!Fi"->9k\Y"X!M??3gK1T3iUgiV3;F5Pa]orr<DL
-_#FE+lf52H55tVi8,iQP\j,.VGTZp5I!,GhLYqf]rrD5k8,Okj"9/AIYE$Bequ4tb
-r:]@S!/5"BJ,/d-fDZkAg*?UtT%tLXXLo)D!'\+XrrBt*qa>r*gS=`_Q\#/:kL[a]
-pjN/BBTN.>FFV05n3?jIq!7q[&&7KDrrCA_O8)a^#QFdr?QFXTp\ggNq<cT0!"-ob
-rrDZVj0/AErrBDrrr>3n5N,ai+9$\9FoMGshtDm+!9^gtXl6J:j5Ga!U02546fM?l
-h#4-s61OR,qSYLc\_pbO-cGgcAKk%*Og;r^^`c29r%g"CTC7/)rrBt8nalb\Sm<H-
-beFL7^%"Vm!"\hEci/33J&=&>.K9(\+8e@\+$]S_dJj1TbODG,h\:S0rr@ForrD5K
-8,P.r_Op:E;?$X6rUKLZ!1mI<nBAWSJ%bABrr<T(a3Xa1FFV1`r$hX>`?5"Bh]G)Y
-jjF).%*S.<qqi*;nG`K9I/a30QUgs00>a@MHr9nD_u9,srrAWr+7RLh$@fbZ8,iQ"
-pW(VZH$"PR1AiU#pVe6P5MmPIq;p$(!"@'?Vu,?cJ+3I<I!kqokEe^:1G?V;msJ"4
-!5nd*oD\f^>p&R[^C#J(nONTZ&,4,jrcrU8__V-=rqFARr'0'\5PaEgrr<JNn>H0@
-'S#WP!.91o!9]\=r%g"CTC7/)rrBt8nalb\Sm<H-beFL7^%"Vm!"\hEci/33J&=&>
-.K9(\+8e@\+$]S_dJj1TbODG,h\:S0rr@ForrD5K8,P.r_Op:E;?$X6rUKLZ!1mJA
-=2o024q%.4i4CWWpepkG4c[!]nK6].N&+ggBDBHLfh#bYr*o.CLUEU5bo=Sb44SFY
-6J#&]F^7>Ninj\8:Uu1Q\TUqT<]Lh6MC>3V.&)SIU5C@nMC>3V.&)SIU5C@nMC>3V
-/*5+3MuHDNp;$\.ZX!I%5P7tM[_KqF`r?&03-^eh_`.SqqG?k`e,KEaZ![&rIqV(D
-(B4AIrrE!^rm>le6MMeF>+`^ifltEl1X[j!^;'1;!5q*^pQ8ZTE>(atZtI;bHb!DP
-0l:P[pE1QBR"0+>Re_$a\&Wn)a.EDiP@o$6^Q#An7%1lLFMSmO>^1]LAq(lDUh[@^
-e21kqkuTfenk-Mo@rOV.F3B$Mh[oHV'ms_H4=fELI;?_=StE)hGdm$@0jWI=Iq<<B
-g"FW+:R)+MHGB/m/eM6\Nd-@)meuP4&,?`OJ+a].^\"sLaKOP1p71YCL3/LO-Qi7+
-!W*gNhBL=R^Y8SFQi%WFa8RL^-i5B.3kh4tqagWnnB]&!g/mu'nOLKH&UZ2*)fp!8
-`;]gn3Z#^V%)jTM]Fh4>9>^P>TAmNk2q@O>Mu>dWi-cjM!"?L:>Po62O8f1h2t/K[
-YP]_sZ-Vfurr<5Lq\SY5q`]9$ilV3#iD'5Dpf[Us"kinUKK%iPm1\sn6$8rJ+7P]u
-!5bi4A+595VMPl8Fo.6e><R%0den=JfK:[bIa'8<'=[rJ8aprt7K3@?B(%U,!W7!-
-/H5^X:Va_rJ$c)LV0job2i><aGh:t__VZ;[=8f?%+FGp=/b(@2*sVX9Y/ts!i*?HE
-2o^?#hC.mtrr@s>4*dXJiB:AminHol9Y/6'iVdukO5e`EnQ5E'rr@XrrrBl7^YkMe
-(k)g:leil_-6KOSr"D$_htV'XhcfOd_;C&P9tu\#47U)Z8c=u?D4c[:r]^+"nPA/!
-Yoils&)&hWH=r$t)Ybr^`"uTPMr:37l;uQN'DP)rTkWJFHb00Ko`"oGE-S;?=,-W7
-ipYPj<W/2Xrr@Z7J&*?/!4+jFHnkD?TP,G:8%[+7?eEQ]\pRrd!/+/AB<h6,i_P=j
-GPiSlEG6*cg]%7drN.qapfdM7pO_cp;?$V'@P'(`pK7B>p]L&ap-JYF5N&ji#lIE#
-IaXkX:Tjlu#JC':JgP`G_Yso;YODer'o2.bq]'jI`7gRU'YE?/\Td#iKROuTps\ah
-_7EsaQT@Wp:Q"e(-fV=e2%=WHINA37id!-JR2])P1gbt9+)(ZS"(oopi8LeN?MKBW
-!!N/IIQUe_dQd5,$\&>-2u&7!B>PSEr"MfB*Z8nL]Ad;UlMghb^,B;FH1:h6N4^>'
-U)Rm?(<`e(G=hQ1j,H7c9@5pZ>KPl_8Gl>ah"X8'^\B+ir$t#,BYX<f#Q-ZIrX`H'
-n+_(oS,WI!UAk4JIK%%^!/5(ZhtU%E#Q-@Or%rWk8,QRephK9mC#A\j?=3D5r+3Y:
-#Q,rVn=P3LSGq*ClcP+]/&7eJ.VW8`rVlkq/'@1VU5C@nMC>3V.&)SIU5CJ:5A@=s
-,qJuqAOkYhriaY&Q,?I(p\)<!bh&Uae#fFOZ'jui^XVo_[)f/WJ`Mj]/L*tFrT/XV
-<:V?HQcP$O"OY"2=B\W6p<KH5!'InKrr@aHrrDuC;>mi"rrC@u%"I575Q:^>e:2<"
-5P*(9+8Ag]rrC:9,AVMe$T`N8<-;gC<6>D?#"e=Z"!iHj32jUN,.[^IKYR#ZPQ(WI
-'S!tgF8bP6J)OZ\rr=Gqrr@_0kPO*KrrBpI:]=0jW:`kgAdK3]L?3L(,OmY7Z0HR6
-nED<N:BRl'%he[;!)2lpfY?B!f)?_8;u95T5M=r`P5+n26Ml8br/\8aMu-FB[JO%Y
-Iar6-T-MSN519b+\'C%Y/cPeYj5IcO'Yf6lpij(er^!=Y(WXFCqC-mt5Oe,T5Q$.(
-r%F+crrD[hrX+/6hU$cJ#*8Od*tA5Mkb\1krrBsMT`5#_%3P)R4raM%d7a6`rr@h$
-62prG)F*2.HoM'*U6k@Jrr<Q&KDtqm1k3C;pi$0475*SsrZ1A2rrA-orr@cCnDF5&
-?boP945(5F!$K\h!"7iG^\nk]JtMg^Zlf95U])(M_ghM3Ig&(+mq=r`K1GhmO,!Z7
-oMYYqJ)T82J,';0pg5*PrrD8Zr"T/2_nD`C!:gR@n@h(*rrCG>paQ4CLO2>e!9>%_
-iI$#3rrAd[n5K>e%ebPT!6@!H_YEnErr>J@i2?Ppm0EXkOD+XoL%4Zireb(!:]*<.
-&,uVPdJj1Sj5IcO'Yf6lpij(er^!=Y(WXFCqC-mt5Oe,T5Q$.(r%F+crrD[hrX+/6
-hU$cJ#*8Od*tA5Mkb\1krrBsMT`5#_%3P)R4raM%d7a6`rr@h$62prG)X;]-j8CdR
-Ir52cKKi]9H/cU*hm7fGrrBnnj6M,;llU'8rlOlkm(F>'m([<4/_A[grr=^uq_\:Q
-mj:c>pO<p*0k#9I@=R:oKsk(6<tebD=l'!Ke*X=*0(#HJDCr#.k0fE+/g-Q'.A<">
-8>J^F<Fm:Srr@bhi8=AOrY#52iR-)gq--Ae/e80d!7:3(Qi@$qNg9VEb1a=5nOLKC
-XnA!HV>.+ML8Cm7=*E.5G+E(3,/WpIrqc1r\$WHH[("JZ\@T;`\<8g'Xe:\GVj^#2
-,\L[egKA9811*\Ol8Bj+nR4A"blmK^@s_md)!6th[^EJRRaubZMWWW>GbdVV'1?Gi
-;T\O6mD])*-<9qNJ(^uRcl`+`r**Oha5_[F*'?mo!+DAs!<"<lrosF_i7P7/-GQo0
-rJQ03rrE%jrr?`Drg`mJnB4c*a87:[]A^2Ziq^4lW-FZgGK*U7`=V9.XpYrl^M2RD
-lZY7r3^e;&KdNLklSc=jg)d/-(9sc1-Cq,A#d0ncBs3^_EUZ-**8GpR^6dl@Ji):V
-is13a&+Fe^3i7Q,3GK4P?bdI9Oa,&EK>c>E4l>W1D6(W6V/*8LE'1^\WMr(NGASYJ
-P$"M^/`lq^5N%iWnAcUa+6*9^qbhZsii\L)%h@n`=.U1[^q+044>3h[YJ%@!3m<ak
-pp7oAn#'EdnnH8Wa&j[Cg2!*FZTS6f9)Ni1KR=U55^;DgF5m3")16kZ[0WiQ7^KGr
-7JgbIfcRQ8LKdE4=Om)&H1`fnrm0I>IN%u7;t0rcXPH<jidF<b^%!E1N&kR7GHBTa
-=sf/A@H1_al5tZY!;'1h!,WhU>#5&1oD\fbT"`D;^VL<H#^C""^(Sk:3Ni"X$g:ba
-LNL_S'R7O8?9%I4cC^hFpA/?ka,%BDj'.QUGg")&m+0b8afG33`ObcPiboBC%<8Fa
-g:jD`h;-p^]Dhj<b?k2KT=lKL!!4g'q#ZWP<a,7qrTPF!&UXNXa:s-@ZIckSmn!HY
-^l.+L5bn;nQG*:u5C,j!"CD*.nc^-)XL7NmqpI^u,5;*;O=:,/Kk7H;ceafa!.bs$
-r..sV./4s6ir8uepl!!m[\l![Q/[c2=7GXUGN"#gGg!o%-FVCr]ftIM]X[J"NI2I\
-iVrlqGXGbkg?(s`Ntch3?I:l0iVc&Zokaq8drekf9?;Q=rr@gNr#bq=U6kajrrD',
-J)I5sr=nqirr<;=@"/FZ%Il=MMgQ9"5EB")X/P5`?6-P_pquuBrn1Yc5DE[sme%#F
-;jQF`_-\;`1&O`7DO7N&cB2f][u*#e#1LNA>(!oQP@pr4V/(D%Sc8]FrYj6<1i3lK
-9tGR[T%iWoh?J.Zq:B]5],F6"F+ffGAi7I1"!@e0Zr'7+;+20r72/Tf'N%:6i#f>X
-r0!?F!4&Bh#QFd*kJKpNW3;?`!,JbTG`1PLlrX'dGl,>rPkm=s4:gpSp5&6gL,Fm$
-.s%P3LVm:#NA[gS;R^3eb<:l\ASlJr!Xd$^OEdsKdm)c^5O_I<%6DYSqt;Q=Qb6OL
-CMabEIOF[S^i+q`3q9)^EejkP[u(#kih$QmSfmP=[='Cdn$PkjroWM.B4bc`'c-QA
-47iFXhu<[G(&Jhti[t'>rrD1"O8*q^r"HjEN%=TUrrBuAp`]Y;bV^L3n'CbVJ,L3c
-ls]noLpuk@rrAF$niqaKZfh5ug\-]t^&J(m5A-&1g\qMYn`R_l<kie99iK%2!!YV!
-rla15HnVAlU;p$W[<pd?htVi>rZB`KRlu5H8_5dn;X6i_]8ogue$Y/bp02(9e1Du9
-"6'!jYP9@2`D;M$Zo@@+i'5m"p+Y*I2#bXin>X1]IX![J(u+$KQi@$k+8dcV#[[;t
-iFi'f>0k'&42QFprr@_I_Kp@eX8`/6B"R%Ulq]"q4sL!Ie>.uHc[amW^Yk0f[,:d6
-Dtm3PZ4H;1j)=^*c]<Pf5@u!qrrDSDh[fWDrr<=ca"N,G!8.;On=TJ#r[RAig'@?O
-!;6Zkrfd?^'eb;+[_*c`rNH2G])JJc>kp@O(VU!#cel($a3WDE<W/H%$%+<!$[qP$
-j+"uXKte4/pc77S$N)[-]Q<"@q^?pA?PVt8T,$Sh%+96'4'nCKn`Rc="RB5LTrHf%
-hJ$h<Gm0_C_gQL+p)elNjPi9:rr?S:j$3O@+1(ooM-^5B5E;B*O8dZ/!!`H'Arl^U
-^=WAb$ZG`grM@4hJ&6""\+Y=H8,iSJSc0i4akd$t!/+SU&^Tg#^U8RM0`M--T`3OA
-g]$'YJ)MLL!/)H\+5%Rir$:09nG`L(*s048X+0WJ^MS)kPI9k0^[QdK92Y]hL%4+$
-!"OBkrr@bJrr<@,p?0J7Kcd_[r"LC6(P9@2rrBpGZM8R>C3jOj/MD]_n4c.$?hTfc
-!/6,Vi\^.KJj83/rr@a3X'KI(/_<)cXSDDErrCuJ?ai8t2rDI-DrT+@.e!.3rrC^O
-!:\;VnK@i3K\QJ>^U4"@_Ya:brr?SJgKXYD^[R'S2p)("KN%jgU])"+r.AS[h>[J.
-'E/Xuplk^X_GC13#cEHl5bJ#`+ln*rrr=*iBMD.XQc&h'!ri8;&b,ts9(<G-BRVL]
-dN@t0r%.Wdq[*8Y5I;em^&n;U?anA"^Pi_O(\&mN1Io@_!/PmpZ/a.JHlqmFJNQg"
-Mr<3B4qR!PnLqfV+8dF6)S;Wfr($be"hXcSrr@a3VZ-X(I_[!@rr@bDrr<K[rr<ku
-j!Xa=_u:BPlmLi.ph-f*AEj*oitK1C?he.r(4X4srr?te_c?^:_AhK!ppAocrrD!\
-pr3+nIa[*_5N8XA!/4q_!!t9_pAY,KIr>i4GT6?urr@Y4r+,?L_-[`,ptPcS_r:Uq
-'O:FRiVrn2r[qqL,k/"U^D1uHp&b!oqe^S57e"aBD.DNXKCsX3_rk+reTpYR7e&C9
-nBu_T:t*'+D=JPA_KnYsLunDYiU6d9^\eeTj6soN&,[Zbpd+DirX$F<60eIM*^=B/
-q_.k-eph<cpaSLf4u7R)dem,(hq<MQL]+5:,sT@UMZ+Fl!.oTfT*+k@_d3ZE-fM*J
-%JVSCn1Th[*tuuj3l=qKn%8h"BbhLK.fCIfT)Ld#_WoPHH)>h=_Vajdr\/^3pjh6,
-IQr3=K3S?UKYL%H2oRbh$/eU9p@c34pjip;T\4]\pj_<WL0kVn*.1ZZFlNYP]J&8+
-cN8@g_n(?9mt\Xa4tp]C&AA_N$fC0BMC>3V.&)Uon&GA-no5^.rrB>Xn72Iu;ifW6
-^-;Ld4qE#TnYG'M[u5\Yr"/W`nMA+LrrBKGNBB4:XaEV5CZ.JqlB[ka?OD5rC2dm1
-\rO=u?!kEV"o[!=g_NcBXe]#7pX>o>CT4+FT<qA*rr<2crKLm?/3Z4E'`F%S(#g;N
-/<Y6V_"N6Y4<*=!M-_X?M<'\Dh[TK;pj_7p'`:;L[/5,XOt3(n8at!\NO6i;T&Ma9
-;LZqQp\Y\sp8Y^UoY5r!"b1$C)0hXfOMc5#T)rAI"Rp>\r[%>Sb2K*gD+DMd%"9=D
-B>VCpFBpNa8Y_0p<7JQ<D5UX_iYX:YQRQ7gTmS?b/`C&r*sQj@!rN?!*UrMu\(3Z7
-E?;UI+,'V"n><iDrr@_$D*McN\lOk%Y65;GWTk8Jg=kE"D0H`LXlNP)?+Ga*TDh;3
-/,m>qrrE%bG](6=rOBW'b.ha'q_c^R"9/@$5Ds=TR/Cn&!$d8UJ*\t@rrAl+?emsE
-)\rAQ,hMaBrrB<Bp4*)Be,KF8(LP]/_B0\1?OoA6c"k=&fU9+['B3ZFBl8X9(R0i]
-g*bkpKKE-8J`kk.]s'gn\]DXVq;:n!f6eIqT7NG<NborN\/mNtUmHuB2[8,A,h)40
-@m,OAkf8+a?@6h2=TYqiHBX5]q]PfRnM0S,O2>ViReO\Q]tNgQQOL>Z?,)'I9$ep!
-ROE&k=f6[+k%b-N6H9\p?EC._/=HFUrr@\/rrCuVh\UcOl`]!^p2^+urr?dUL]7@[
-cc4k!T+Cr%COb&>`a9H<fKKW>6Imu#!e/@CZ]E%C)>klW,H,u5pqrb?>%PJH2NPl4
-4!0/`$[s@trf=-`q![20Vr>AokW]_<47-t'QN$rchm5QF'\hQ$m2,8-p-&2?@H!i;
-''fJs[F`7p!/-sVo]ok:IfR5t?eT;Rf>DMAHq0a?2r]=A5!JqEILQ,`f00?442`3H
-IO+0l-h%qk#5FJCO,"X7J1'j:m_/-0_u9hf,tF$l_>aLe97Oc_rr?q4*r)f8$$kR7
-gIq7-nHHD<^Y9jgrrDs2e&@ptr+#V$GVAbNpj_c@`K5PgRZ+htL#R%(#K/j4a+=.G
-nQXs:LcuLI>JjY$WV]'K5IZp@JGp!mSdX"2,@>gO\^p[L4rqf':jDU2%Xb\ZAao$Z
-L%.rprr?PIpdmS6n@/*Vp_!C@Hm*tCHqaL6]HQdNj0-9`N1[LB_gg?gir79DT=($P
-&c4#):"$bpHgtmf?9doaN-kZq,NC/g08a'UD\;5WIhOq'iXZLSfZiIV!:WqUpak%8
-0*?IJiO?]8Ms943fVcaHn5%C*/GK&Tk>2&`Hq!opI!bXVnT3X?`4stIp5/PJnY>f1
-eF]Ho]as'\^jh7!&UZerKtIlS>@3;\"Z>1g2``:Z5DK(gg'-*H9:]@qmgjn@hlsTW
-/*"D!&,(#4BC.M7c[nCNTfaXkUWrRbn.WZbT>[9Bi\unq8c(LBT%:qbpbD;'ig%!-
-1`J(SHntJJnMe<d[b`ag4qRL%`ZGsJHip//\e^j<r(+QlCq_.`c\9*JU5C@nMC>3V
-.&)SIU5C@nMC>3V/&4A`YPBIprr?V#i",gjc\@_&;-soah;@daYM4:#c*R,@rrCP)
-a7]:6fB7/LLZX"KQ17S`K`;&1U<DMD@aa`=WVq^PnYH$UL@-l-Ic'i(pucGOI5Ab6
-\poU3nU?P#GX>d4.4s\_Y%ubRX*NW]h[T@DbJsN&e,1_opj9t`AuFTp(u4o,8CdVG
-i8:pQKCo0D&U:)0oq%B:6fQG1TD0ggT>FA1f]dmn?gPJbT+laq^)?E`SStJ%Jh&EO
-iXbEDj)%T357[,]!+p-[HuY`BM#Jq'K=kXP?e`?6Zg%5`+8CWN&(m6BT[<ToGCOah
-qfd;Jp=K'crr<1Rq#,Eqr<pZ<ZtJd8-bsNDL70=cb`R.Mhr9#I3;C+ff_d2IINnP7
-;YXbkpINoK<TDteg(02$pmL,;*rJ1r6h!H6plj\ZLALoMNr19oS+^1Xc\ZcD!!<'Q
-rbq]tq_8$M_-m9Ci10fI#J]2nT<^EBg[K,edl^@p=8iNbq\OWjpbhRtp+#SS`(ptm
-+RkH2DqW9OKV,PWm;$;&hXAHK!WEXTFt_TKp:C#bU3oB-Uc_RonEr8cBFB+`3T,Y]
-<ibahifsETnSa3WY<EkReUA,/W^#F7T+etMhhRin;Vqn3a57]JD_Ll0.JV*V$cF)"
-rr@Y$B]$3f`:)?2^`O&8/pMm>[3#pl?1G6s\,QG[K6Y`A&C64M4q#b#=oSI/5>fqE
-0)0MHbjakc+5$Q!97I%me:5:9rYtXEiD7?%paF58rZ1o]piYOkM#RJE<mTLkijZab
-ph9[-#lJZ2Qc/n(*W-K=LPNSRJ&8elO/ei+2bqj$1\dX<UJ947qfdu_+WKkdl[C"^
-f0A4Fe8BY8D6@^Pqt@2'1OO6C!.oQs3QLMij5\aO5@EC'=FGPJd=)B$!0`6.=8e82
-N;inSS:8fW_LKI6IaMNpM;R(f!<3$/2uF<3rrAp!?@Sr!HhNj*V7nDR2thdsHgmrm
-#ODuk\)9Kgrr@n*#CJU[qeLRArLX#hBto@o'RggHdN0Y.:#fT;[^l]o5@ZqQ-nIP6
-d_6iK5K1CCrrBmgFKZO+_rA.Z4?9<aF2YdCd;==Rr(#976PkRX'_!"_r">4j'>e+`
-PS*h>h=3GarrBt:!/9/#NT9dt(O8&+_>aMi-fK::`VXBL!5V1<1]'dh8&2Su&T=B5
-(W67Q#QE=^[GID4mtY8VT9"@gi_(4D!dkjSn&)>eIhVf>fm(9NR^L2.r!<<&Jm3]R
-rrBBL^gE$"!4+>q:YVr/rr@cP)15ijTDTMp^?<MiBC)bj(I\4s^)m2Npj`;D"PEJY
-qZ-Cej$1E<MuFUm['VIspeUc+`#l=hJA+22rYLdWI])0g3pPa2n/e(h1<T;r)r`c3
-GglWtS+,a\\)%bIrr?PIN?8]rB92gU4s0dMh?pXZLW1tgIanAt[U6nr8,aA:p<!9!
-Iqt\02Tk@$?PgImD(GJciVrnnDtm3P)L`Is5JS?O2;\N9!,$Otp8Rh@W-Eg1IN/:2
-\C*K>kS>90:LDhJ_I"=brr?hALVL7#m/I'_Ia_UTrr@e,rr@c;WHcV[1\cmfhgmsC
-rr@c-i:#;/iMMb;!",@W5)K/Tp_Vop_LM>JINSRi_)jgj_5Vq$@I`O@Du:oq1%B2#
-^Co9#!5^%Vl@'N<DhO/lJ&+9tC4D$\)#_-s)s]_rYO)8hD=GaJ$753A!6.'<`k)[9
-p+uK%&!$Q@nP@0^n5$fQ5Hu91j"H,#0tR=mmsI?oHp>+1#JpE?%/aG\rYg$fiVrn;
-]LN`uIBNK%\bNFRHZQ+_9[c*'!/P!f^[:^a7dK!)MnE3i?iJ+YHqjR0^M"!NNh6V8
-Nt20)Ii:/i!]ThFm,Rt<rltF*n@->C"DV<5;@Rig*\@<DnG`LU'lDq`#jZpWpl"YA
-!<*Q>A&2*[XQ^ceZLL>&pi"M9q[\LtZ.=u8l?W^%n,#A!g`I@tB^^`qn&@$7;rU<_
->E@HIiJ*AA.I$g7pfm7*8\0]9rrDF2qc<V0ZLBfjq`fgA!q7SShh1n=n4(%[A&N\+
-JNaZLC*+G0+aEJ9#.<GdMr,9\phZ#F/,kYmqg\VGiPtltJm!Tqb:E&X.&)SIU5CA&
-Nr3hq!%/B=?i)&I!!Y[\3;oL#kPkP8;uT$h[GUqT7udNKohBfXYKS*AB>M?icBIbp
-_]SAOYCcp^rLs3BrmB<r44\msce4XdO&*I@]Mn;M:&(REpcJf?T@o-&]XBl)K"`IY
-ce])Z1sH*BiOkVT^)d!N%Zbt6gdc5@q"/hbrk\QDIOfdOpso6PkeHUdn(F1;dWI4"
-^U!-<^DHk\Hr&063_,+Z_aa/sQ)=I]rLLYFg\F]^O_I!?nE'D$4s'LViLbo-*BV3+
-elmj]U=FA?4,3X$0DR-5#X@Z#ia;XAgJs[A!9@V;^[)?3rrD;-L?n#@gPc&)X7j@/
-!4,r/TKi*JppRrZO2h2"ni1l\rkg\p!;]ObrR:cH_6IA<9n-h@q\K23BE%u15Q9&Q
-r@:O8Gk].KZ'WB\#N;#)+RsB02.)0S)6C3k&'q1gH<J"iS+`NFP3^-=qchQlN?Sg(
-cbmNO\,&noNi-B$/uNK!%+d58K\+<fnBV%6*pfuB35ZiR:PuaHLUE1t?4(%l4qlHF
-,Q%q%;:.QSfKo$7hcH.ANXq'VT\8%'??hf4e7YB1=n8cSN[9EoDBkJ(%lXFfJmj,Q
-J+-9aK"i5mF\g_$^fheMnCI?OSgR0Z@fHGf-\FN_if+IJ]Um^;8COZ7n?/spa`Rd*
-/G=CBh)e,F/Zc-oFX=Y(H,$*)g-=p5H2Dok`g]aFr#30H!.o_[^ru3"/Tg;sNj-k"
-3PGpdSh.JJq5Ja#?\.`ln[,':VsDnmhEAU)8&OrYHVG:$kZho.pg2fm7.t!@F7rl6
-'DiSn$1Kn?dJGbF)u^SU_(UPXn<8@=(#Z:j8\AQn+7*A09RL@0+!:9=r[L,SpkQgp
-/_#9WHs>U4HWL.HM71*Ip-6%bK#?rdAZ_5_^W)lMrrCu;hsa=3ft74plYd#WcaJ&3
-+7L)arrA#X!"45oGRNPu`h/9`ZqnQbLE6TsTtI?'5NlG^rXs\-rr<ct."!fFHiF'R
-QHAR%Di/k5JikESlQ/"Sk.Tbm%/?/ce3#tTmh4lr\!gY'!5T0F!8s%Z^P=pCiBIqP
-*:Zg`r'02%g&D&g?a?g%TB#qOgFN!6pjrC+q`+L4po!$\NICm&0Arn7)ZJ,fp$]f5
-L].bXS++>3?7,1(J`$p.%9i!<fpB9-R#Al]+RpM<X8DnsNdouV+7N'5M-h:96i0OO
-fASoUXaG!U=7$%c/q2;rpPj[]Du<Va^>JJ8p+GiYM7`ld1jJ3_&^;]_4bn]mJ)OT+
-9?'.?dXU3nZI!Id*TJ7/+1M%F!5mYCeElNTD17$6S,WJ$^Y,ga7.;P.n@/+3cub>'
-*t5Q,L`SMMQYl6X9_$/[21G[P5K&$`22OFailsF@DhNL4idGa_rr<<'+5ZdEir9!a
-e,C$Y.b";7n?^$D`ilQ1IN.coOaF9I1Z*QZ!;n)\&,c_)O8KkuJ+;egi?6KskVo;e
-i6'7C!0:"W!!rj^rr>?u,Q@`J<aYcNO8)7&+8QH2+8@UsrrD*/J&4LErrCDa8H/\+
-Q'_LN*i&]I%0ulbH:RrCXM=Q'+7PA*5P,oC5O`5qrrC*<rr@_)62pqXhN@g<K.AVS
-4\,Dq)@ucNoT/nf=b#u,\SJ-G?[88P^9bKC[e[[L\VB.fhn*NhjLad9Z1dV*mB)?7
-34D<j;+20r72/Tf'N%;D#OODK!$nCjm&9g_rrCUFnC"g]/&XV%Hn2Jsl0oYP+2M5]
-<1cP,4t_(EinqXJ7p<=0>J$FQa2\SID[g";<n=B($Zg;tDlH<L$k5$D1m'>+/7FHt
--aqVki1lSL7qFo9Iq(,G959@epkhl$8)oqfT3<t/^Y2KB.">_;*CJfM/q=SVV+'DT
-&OgC"dDr7l+BGKA!9#@+!.p./!7<4nMuNeI/j;@HoE%ni!!u0n'OUir8*jU_!/Y^c
-g]%8H&sRX5rX(2O&&Osk\9jk%j5[iYjnf(Bq$M?D,erhG?hu(@Z"O%^a2bC_J/UZ2
--3!ssMZ3\(/H(JknLd!gJ+N`grr<?Yr"N63M.c0Xrr@mqna$2TTE_`E?\Y2[n&55+
-MuNb^rZH[:am^Oj^(pDRi\)'p61DXDrXaHJpl4f^?1Eu9r($7Oi\/-K)"jFq`h*>3
-#&4&PnEu:pO,CY&eE0ssIhQ1(]!OLl5\]r]bjt^fi/d[nNs1$d(\l>V!3+$*rr?Db
-^Th_T'Hb77/H)_/+,e5_mD&0Q_&r/CY7LW`]$J5hL0cn8'DkUR55h&l;>l_:]<-GZ
-$-V9lfIOo_[&8Sk')p1J"n;iboD\dno^L2HDq^!,Q-Y<d0K4]5Hgu$j)A]l^pm^1^
-Zq]I1;ZlaKpnR^bpnQk^m:GhN8FV]-!W+m%J+ctD!.nU+%K3*1D[^m&p?24/nC,F-
-ZCcsFc\oR-;_-+&j(F-sA$=QM`nq[6!+CrCrrD$_^#=HkSe1Ff*s98kmuIASpfZYU
-+2D4n^(>Zan]-Et5NAr'QMq'\rrCderX-R?:]A\OhoB)[h[@.5G^n^Cm($ojrrCfG
-iNL&SM;BfY:#Z*P"o).mrMTYq@IMkkp8Ri;nHVVT2iTA<DEe_\EVR<-r?pWdls'"T
-i5W+^$3(!6hq;Y[qOX6@c\st"qaYml6h#SW[9qVqTDboWC*20%i@""]q^MFipoE@<
-L]7@^B>tJ8kOsGq#ONhr4\PKepf[,'i'rderr<OXd6I+qhtSf/_b4nNCEEkjT8DI6
-(W>#,!9$g^rlcE.pm:#j)#P`1^+=Y1nb7Ss@4-\V#l_t2&:Q<X-c8+WptbiGn=RXK
-n<j,)phAaVpeUl2r)`muKWF)3!/#Yhrr<F"iB<h,GJ_[_?e_.ldrdnM:];8HrrDPW
-r(?hk_uB]RrN#o10*^,0!5c_FpXspSW9LO9_JA/5TA-jSJOL8M72/Tf'N%:5=3#bK
-rrA7=nZVnRItJj>S:8g"oD\gWWW)r@0A>moc_JM[!;`S,&Qb'-qB,)^qZHW6i[p5X
-Xmjr[^U:Q;Q16NJIOY&ciVrn.kMd8Fn8I>?m-E](L`4gaM1-R\h[Xed+';bF1%E#p
-c%!]6qT"K#T*jl;pO[PV#&9V#ULg@ZlWS<VTCW!^K)Yg\%uENXTC#M8IuQZ-4rdAq
-#_'r]&2jIf"FNT8Tg*'N)rfG&nS[gh\+nA?cc$Z+0^qTN%j1$8!"X0%^P6)'XG4'Y
-BTi9[IgC;B`-U%SW4Y?/CZ;Bf>Dq7,EBdVNrrA4on:U_W4sg4/dp9@aTDh;3/,m>q
-rrE%bG](6=rOBW'b.ha'q_c^R"9/@$5Ds=TR/Cn&!$d8UJ*\t@rrAl+?emsE)\rAQ
-,hMaBrrB<Bp4*)Be,KF8(LPaSm*#D/,c/9BW;M,E!7go80"q7Arr=t7$q[I5J+-[7
-gKVY2*:Xi%Hm@XS"THf`[na]sY7^P">efdr\#/F/O2m:mGV8fceF_F%]1?i;3TAk=
-:Ul6-7@#I@*0g\3qTJi%5AC,tM;C;lMuF@FBg3]AFe=OT*q7LrD\d_'^:q5+INj/5
-L>tYrVrE&ALY=\E%uBZHWI-S#l96+&#0?*K%(`=8@A[_dBY&nhS#0p9g:,S(*Ihc$
-CZ03u;=N32O7=QR+-$1drr<Ej([J[0:O`n,HlHLrHq42:Kls*S^CboBppSpJf5:L$
-HjBFjIH%7*-2`,bTl8nN'>s<di0T1GHgq_%#l'uU$*T,l+.7R!rndVcQf0<E^*`b`
-](f.*h#(%$Ht^8$FJ&=Uf8RF(J&+d"rr@j="7QHi2M:$CLcSM-"Fk!d$i'P)0*D"H
-;L\^p7b;b^!/<PD_lnjP-Ik:%pj9r/&ad5BnJagaP[2mu5N&2!Z?M!FnJ8)O`,0_;
-Sdk15_Mqp_B8h9iHn"hZnYbDC^u#BE3mkYRgjFF;;XntOYCmu.4E9k#_YW\sn6pF2
-M1-<20"p;Y5KB?Mn:uue)=&=VnBSFYnQ4\MGcu>O8+"(g07M5R2R`C#nU'8>r$&j9
-e3Dns_k[!5*sMR0nM[N/4^6qNPP[^^rr<B'/)a]^$$]6Prr@_Ua'TL0iKaC%BO1].
-#DUu4n[FH>D;h#fiV/-"%7A0C'##1WGK,+kBclhDYCfk?'YZ\S'B2cJY5!4W^B-S5
-Hq=%MiZF,/&%iAK7!r;8Ff"kGi9/.qgV;\8`Hr\_qW<Y346X7W_G,6ig/mW*XD82\
-ipBQVrr<_FH/ag-iMXIC:ZDVfK/>e5Hq=*(ia;(ei1C#Kd=26_Am5X=pdmXoHroji
-L@buk=S_g%O8f1ehn_K;p^d7<r*f("O8dZgL@6rP(k9D$Y5Z>2'"e>H!!o`sYNacL
-M<Fm=_H!^4B4i!2VKfSm2/i7<f>4Wor+5ZHn42I[LH[6CGg#'d`I2[`pOdR+KAQdG
-BTLks`8;.h1Z8kthtB)*l/St'pYHV_T"YU15h1<(k["qQIr*Gdrr<Q^Qc+Vq55S/^
-1K:X2A@_45hB1*`^M#:q.*'3."P\;]dJa>chse.';t17UVsHY+"S$,VrY9fippp8d
-Bg)k%W]t/=JA)ZGB(7hI(\"oOf=q>K!TU:Xi$ZM=4t(e4cocUD@meeSCMt&;*:[iO
-(%G@Z^*NIu:[to:GQ.XH.K,-GSHHeO0_%*AO8)"g$_W!d+*eC8?\puWIOtCQph/W*
-$2EiGB7[c.kT:O'&H#,irr@U42rJ&'*s1Kmf>S8T(7lfHrU=mH*]j'Fi10u0B>^nm
-ps[:;#D%8FiEm44hQPmfg>Cg9MtN\PphraoB"Md:D\RS#dQRkLSf$uf_bZ.r#Os[\
-`Q`>p=L\7:D#=Ot0+Rd/_1!KW]HOGqq__X!nH2jN`O7fQ*ZrlIj5K.65+D(+ddP#6
-pg0$]!!P+UPJ/2Sp2YNspna[35h0(ErK;$jM`j_NIi<\fVtaoB5IO(=^Lh7WK%dtr
-[6%0:Sgh5>[_)'&_8!B*JMlnJIN@s5PMs2>idZflh]6r6pVe0Yd_61id2k1?.HMWY
-^Yl5d!rR!+;tbA/kMr`Vq!6m.L%3(=?&ur&8&<p*_=-*i>POV#j)&;FT<YT;h&!nW
-"hYX[q_241Ia]>AeG^\Ag#!<f#GlfXphr85:Q77/mgVqZVo(_2oIJ7E>0k%b!2OKs
-Dnjtk*t7BT+bO%pYH2KM^:WAX%\JFR)?#s&!,:m:rmEtPe3"tRpg7+m291`lAT&"T
-*S%o=?\^ZXKqeAB!9&[CWHb2Yh[2J)iL=Zlit&shDG=AM?Q-Wn?222&hq;r-=+YlW
-r%mi_`ZKrHfDHnd%Xor'(ZG,,Y5ig*q`@j+rrBP+'B?1ppnP^;fCh\K@ARbN=8&eN
-Wn:[.B5:[_SZ>lgrr?Z\X=WfaRbg9*W1o.tU5C@nMC>3V.'EXLVSD2VYPj_.J3WnF
-4rRK37<q+W^*<?%i=Ee4M#RGi]NI)"rY>3FU\m[Qf84AfL[>c0pj^/IRf9k!gd,gg
-KNq4USRljn:jLF`dNZZma1HTTFN"1ZJr&a(FdB@Dq`'&Hq@/aiD&)`@NT8pMpYs2J
-j%VGcjTMgApn(%F\*RD\^CTR4e8_dPm6=55LPW'L-J\agG79F!n*Fuf.,Xt7J(TPV
-!#&#c^]+:!'d))cn56ss+TDGH&,moBa++)=.Rqh#i1m(gT)q5cokqa`D%D[9#<_*<
-ljAF9OnXS@4Q?W!lsKN:+8lbsfPgci'//Ctrr>;i+5"?t;Et"$T<R5P-==fsrd_RE
-Z%(]-J+Q)m@DD_6^Q2b#!Hjq<`.-JgiVrnrT8"BhrM2Uir#tQ@LW4aL`*O,PGN-Ah
-rr=!c?h&bCS&ZQgn5"mi,i*]H`E']2p_WEQ;"4,2O+BD,j%Xkje9&l@'A;2#L9Bkq
-rrBCfT&&;frr<1Oai&ESrlDjoJ,N,,BDUROARF.qp(RD&["!],*W;RW3VG*:r&+8!
-TR9l?Q8C69rlO%7^Lk/#e)=lQJHs'J0B-@*NM_)Kpc%]>bJc[Vr%7E]ijP9ElW<VC
-m.gjpiQhQ"'B;$)4<ri+91&.J!6,NVC&TRQrr@n)55tV7@!kHBZ?4nIitoNRL]0C6
-X*t+t5kn.ET1JpR^*WcrSj2a0LHZ+D;q<LI)tBia?c,Ssp>tg?^mjeE?OhN-C:^%W
-O,(=(_LDdDr,g?a7t'o'il?\!/`?Rc?]':od53FVl44YZ`*]d!O+&F#S)[S1^LU-n
-K>sN$4DEdQB>T*PppK,-J6rY28+ACSSe^c;_qUf:INe4,M7e,8GY[kL3qnF&hh="U
-T+#k5)cY@*[-^fNmFBO7n#`MWh"'^2Gct$?"UFF7n;"fn+o"XfrEo8Nn^#&O!/dBe
-r!W%0j1nt/e28<XGZXTBf)-ETNq6&9a-Y3b)eg?9e*Xp.TY<//rZ9eWp31h*YD%EO
-r-ko;<UfX01=\5=)LMJaL3tB-?No]G3^8801ZA?6$0`7t+Rs*&0/UEPkh:34Vd4PJ
-a1a%SI!+JQ'3s2SG1O+Npk-SX2XqlFHt20\AltO"nK3Xrh.OYe`QdPKWaB(.cr!4G
-;+20r72/Tf(%L1@rrD->4DXrsA7+98rhgjF"aT!X4ph!g_GU*qT_OB64pUk@nO(6E
-(3SpP+Z)><8[S"0LpWcbG^/!-kmZHf\?rNf4=QuWUq3\ijH<lQXf5IBV*V/rQ#"tN
-!5cA;ci"PBMnf$@e,KFD/s#d/IMr.cU5/8_rr<6AJ,]KpeusjV)rVe>`7c;j+2o<6
-27q*7k$*a*I;Q@7gL9f3>2J3<2iB4nCeQV38>!PT-?YG\fP/\3!$`8Err?G4J,]LA
-]Jj1ZIb\<$ARDkNrL2p:!WN/"T>e5;9R\r<nV;rkVR:k;nmUk]VuHaL@_^umrm6/g
-/cO)r!;_3DU?h['rL&/rPdgUV+-5=U^HNsq^X6ENmpg-SUjp3iIrES5<O\SodcU>n
-qeF([V5Qa-Q%ZI!rmQ@1[>m>lQ&=Ei/oBR9HZWBu9ajqC(hAVnI]7h5.ssqI:CQK[
-[=ikW^Z"VlNCVrNKl<kZWbT+_PV;3[%ikk+a_p:Nqc'QX6julsFn9)H8!pjdNqG%9
-r*(8K2o&c1Ho(9tKROd9>."&^nB4VV[?$5q%"(e>/&OOh^XKh[i'm/VO,?+=kT:Ie
-$2Bug]R;9e=OF8<@JGi@H1X7CimUoBO&`[;m^t]_ITChirr@XGJ&:!mfAeg.mhC5n
-58lb"c#^p4'7=6KPP[`H`..9g5@fWN!9%Pf1]<Sf&Dc1?2uT.,62O+'GjF>g!04E.
-!rg/G!pm9Y*:"]Ra2AK4pV\/\"3][!1k1A]&((:fqRg2):2N?hn7Td+g%3*G)>#L>
-p.bLb4qpf^j5]<SV>)"gSL<H]l4*V1GRsKr[b#s4HqX6GifAgYZerS^$JXOC_@M?,
-,D4tErJnO1iLMX@p3o,V_^j^'"F-]Y*Y%mVG\?^bpuSXWeij?;Y!,)LdGG9nFlP+V
-CVL--1sZU.*rVN)?gq^G2guY>8+9a^$8(bIcUbc62>sKQ5&.4&lWULi'I-cN:"P3'
-n"A.s2#dQ1)J=f!n@[@:.D,+.M;<X,^TfGK^LnXJ4sg!)i6R?C(9aQ^=P&!WgjF)1
-[u()!l5*WY\`'.qrmj<BGO9D>Db0Y%ia"(oQB,nPdp;`mj"K.sa1`GdRGok9G\?%H
-TCIEK4qmFBn@+,N#jS0f^=<'6p3Zf>Jpd?_^q[2dm-uHVDDX$"ch<Y!H1>67rMT9`
-%f"LCe36+p3quS3CTlEX`':N9Jc>^_5DWK5L;#87)Z/PIL&3WS`1A4C\*UT!HqWrF
-`P7.rLW+`aHkGjlm4%'Ur'@H0X5Z'lr,qG""@$@&'7;n?Uh'G)rZV2Jd(FSmDoK:(
-m0.Fu?H9m3$M=pah[['_'7=E=^L2PHrZ9Vh*r'YYpndLR`81L@]G9qRrX&T)nG`J^
-f"=*(:E=gYe3%I*cQ%2M`g/e:n5"h5d68URr8$l*rX!</1Z9Fn5D9%:!rN<#:3[KN
-*72?@rr<2npp9Lfe&C4NNk_ap9_a>31\Lms5@b90kuU(Wr,\W^dJamM\&&(E!rPg_
-\*Qo[ROpnDIOt8(n],#+Y.q.;7+Ns&H*6Dcc\B(si;>6\^[O^"!W3h_]JJN-#jVEi
-ZZh$YYD/M7m'R(KHs?*,p*TQWnB9jYNr0.Z1k*sS!4/lr,91'uLW:f*ET.KHI!>@h
-j(iSdX2<^2eGOUM+o=KO3h++f2>Dmq=2o^l4s9-inAE0D!";&Rps8s?"QJoH`D;>_
-ZnKE>+3#DlKmZAbX5I=h?Ml2@(]5NS[tt%aiC8:G4qH9E%eubOg11"(lc2&0L%.+h
-Rd]Tarr<2m^Ae1e1ZD+b:AB*Qrr<IWp1?su5M?5"ID:Wb%Y);S]G'3FL42;\4n.(C
-+7P#43S/aqn(:/(M!tY)J)ML"]LDi#$K&ZaYdT,["o)HA^BX]<[IsP"*8YJF0`M-+
-VaC?;/1c;0@I%*e3jsnF!"0&!3gPW^ld#m^ET5k([f6>Z??hmFDqR4h3k+JcTj@FP
-p+"G%"n9.^SZ\OQ:JfMf9rWLLpe1K_rrBkp5A9M?rZCp3YMB%ge[2LpHrl(qrr@Y"
-al"fkr(caJKt\UQ6cBt!`ROFLKCEfpp>6D8_;7.85Q8kk*rZOpAb^iRAcBii?21Dh
-j5P!rIi6'EJ?Ae^r%7\riL^@&,P\\D49!15%(q!(YMnr,rrBM=loApclaD6trr@Xr
-r$U+o46+R1j*eT:/t_Ye`?#E!p_i*og(0%s$iNKn!.o3<*q;2UnbXJYc<gQ6COMmk
-Shg'[q_ruM?O+5JWVBf_:qcADUZ-3HIggFK"`)`H*PBq0bnF*hd'!%I'(4dN\^^7g
-,>b".P29Ef1;`/6[#=A+.&)SIU5C@nMC>3V/&4A`YPBIprr?V#i",gjc\@_&;-soa
-h;@daYM4:#c*R,@rrCP)a7]:nFX@6P27WB&iEnBgB)Sho1[q$Tp)a^U2rH?Ih]MhW
-lM:snMR:-M?NN>=VX*(e\+%)nUT.GLGa$2)54Q[L4s0\'p_0=dZ1qhLPP>MfrLs3G
-HmI2?05;R<^*%YRi75ld08SI&]C9TDl(>Cs_`n0:rr<IV&H:7Q)#jSH^Y/)LZ1sg^
-&*tCkgJ%RG4?_]k?c:jkQ$D=on6a)Jpf90J9CQ<(08Vn+5N+N5d\>1V50*/28+V+I
-]'"[P5PRe2d+;CL]AJ3)[GU>kqb2LV:]CD'iVQ4E#lUEGi<oS'rr@_qrY1F5%u7n7
-^Yoh*!/-R5>Q,5lpdtJci<8Z\^&<T^^&<Sdrr?O.!,DIrqc!A.<r3E"rLJ5prr>7_
-!3r0o(5MV.nSddo!<3$%`r31B!,B1Lp1NnC^b>I3+71ebrl&a45M>YeVo:lTh\^eC
-r-.Za`G^S4!"HXHGh?fH&cOtA>OZ">ItW7p\bJ,D-2=gESN#KiN4p?!ia3+0ILg@S
-P%_G1L,FF8i]m>\Qhr--Ab[qU8U+b=;Xn,4%gm\ue:2"ipa?rsn(B5NNk&rp'?(kS
-M`c(X,5`eXrrA!$f.[+9k^O;\-[]V&2uTeTGY_02Z1,e-rN^ochh%:]`8:[l?W%Zn
-I\E`Gfm$_$rMfaGIP?$8j'V-rq\/m=pn?[OnMeD$Mgr$&m,.=pi[9RIZZLU3rXp:m
-q"N_0K03/nh/iH8_qKR'TP6XEgA\.O?iL+<BR4!SUY(!im(-f$B4VbmdI=oYh;_af
-DZ9]gHQdQ?5AL2u*juBraSg_j!,[f-3b3.nRBLo*8,SlIK"pZ1r+H$0eDp7PYK1)G
--Kj_?qb25N^n7s*KQUW0rn%/MYcijH%fX6^5O@Y)PN%qIrrA,[!41SMA)k6uj0@0"
-A=ZK<qt:`Qr[<.mrr@Y+r%e$Lq`hu0n0?t#LOLt*414j+q`B$a`k"Bprr?\Wo`"oE
-?8:sT_9W,I^U'7m2saQA6ehUm?Q(Rn_S=fSa*PLZ5AgE#fLt7kKYM<[Lqg;e_F+2A
-pp]25m.'R$rX&DZmuA=d!63@;_nl?Q*]uOBST"4onTE1EiUPqopg)pn-iOFu4T5?U
-kH+RhpmLX+`r?#BFH;2`"SeDSCZGl<pa3cCC%3#":8]b+5@n15%h8GQnHZl`(4X.d
-1egW\?gp`R"9-:>!44u0^C>\/<'T<2?Q]2mibsLA&GQPjLOX#Vg(3-@OmlSjJ%$MU
-Hj?bQ!5V8!IiNpan9c\T/=m?^\K;\Q2LJQpkDoP6nJD*:(ZVk$eil%!pf$\"iVrnq
-YLq%6^[Tcsrr<9&!RIil42G:0GJqg]T+q8DJ&)fr9mcaapq,M*_Y:e7f>8W_rrDbR
-q"=MIrnF"ipkrkUpV7m?N_f0m9^rpYIqUKg5I>@Ehi/[@rLJFQYNU>MHHr;F5770u
-`&bqlr'B6m?XE7$NNDE:"n?0MKl9(Ri4VW[e#fgW]I2]ScN<m2`h!LJnHXh%B9u->
-DL<Jb*u9*%I7DNE?OqCN?.'Y;<4_9AU5C@nMC>3V.&)Uon&GA-no5^.rrB>Xn72Iu
-;ifW6Y#.V&Ma.,u>$(ZRFoMI?0(@\EmJCmQad%>-+80KBZj6T1IhpZ313i!]7irCo
-fP==`!7HY+m[O1bMZ3[>C\pEt!8+dX5Q:`JrrDbNYNn^PAcDan;W%1IIQr>Ir:lUb
-rr>K;!h'Yep\T8N+7NEog-\W^^M1H=3qn.g#l`5$[R4a.!!PP3ps7q@^$msXn<\oX
-F5q1kSeLUarrBrd%J\,`H?I5si<q:RB_q1PmCq$Y[>r#\D')uN42"86-'S2&rLElf
-DZ9]n*tpkL?\CWa]N=UG_j^T*Nr4.:*VDW0f_@g6\F;/&F>"/P*Vd2)YD;Z(>;(eT
-%j-%aokdW#dr]B4dpX/sXj,@%+hF"=d?-8&-W'9HC!YNYi/b['fe^M&[V+t8i]018
-Hl.LP*X2)+MfkGp?PN:t?O<XL>Q4[(BO2\-A^^JYiSB"%]$u`!NuD\X$f'tF*k4UR
-PGqj,AYqh;F)B0O_b0h@rr@e@rr@d:rr@`$r\?;/'OUbpYP]ocpd[GLrr=<CrY,;3
-pf7=on="jD?2]EU!!k7UO'hE%rr@^nrXs_U90_PdrIb'0rr<]>pIb";JDV2k1]'Q;
-%JVaLrrBl93pr?mhi;%N4rsQ0n<TL%MetZ$`7fEiIO9;,8+Ea7A)]"%-WAUgX%dcd
-9%NA]om:O3=k30>2$iUoZdeI2Oup3uFT2>t?4#/2-@!/\onKm;r'p0/JUSX;9(>u<
-J$ZOr^TtKcnR#YuUZ$\&CL>fe=@]&lIrFYf#!O>8rr?\G\t.ucV16?@p75s9::&M.
-$]S5Ap`'*&r"T+*^Ys/3!5b&lVu.lkn=]bAHpR_"^+B9a`Aur(%fZOG.IjV#BD+jn
--_:_G!/e*Kd(d&>YeRYhYP>'o2>sl?4\tHPnKukq%jL2YpIb";LOU.g1\!9?rr=*f
-'qj4F[[ODdnaTsVpc[YANF(@8K2:#[9s+=&pbVI>degoPg$3eU2nB]P%J]&D/Mc>K
-<j^73"S"C@i[["\a`ORX1Ki9*Y7u5>:[j-oHq!&N>2NVtd_%6,CAoF,m6!&\IhR(e
-`7I&!M5T-DGF&4Kn5k4KNt?QZ`VSrPf$['aG[J<k%_(G9&8DYmV!'j/V5iA*=j=Qb
-bOG*rdk>fIWGcnE)nB$LSi)\rdb`tPN*9@<5k;q]&2Up%#A@^Y#$C'$rr@_%62pqX
--B\<.K%hsX1Iq?fq@EN*1lqPMfmiO\\SJ+q=S\RtZ*Ue.G58ma[YE\`ft1mbjJ$SG
-^%Um>h9Cmr3O_Ek;+20r72/Tf'N%;D#OODK!$nCjm&9g_rrCUFnC"g]/)pR/gN--)
-ec,VWYM295dd8YE%8Tq$Sc8\(h*4]>[#*tW]tV/KQ]E`cD(VH?1X0oZ4H[Sk8.3Na
-Wi.1o?Xr;l)#bQNUI`kH6fIJLkh=UCXBIo>V<ZcGgc)fnTk/1oiOQ>,J_hiMO\S7g
-*#u!Z^k(Nq)h&NNbeLMLr$+.m'f7F86cFKWrn@APKlQWQ_HnSZDo1Ckrr<E+!9#=)
-ac".<!:Zr$4T$_]r"nmqiA^Z^3c9ePG^%3cn?+ltiK*b04<g+U%InrAf7c'k7n1)Y
-4rJ+d^'!joM;^Z6Hu8D7`k?^krmL[n`8?E[*t1!0*-dt?g:dK^C]1_Nn8%"/_I&&k
-rrC^&GF&4Mdsp<rpjM-$!&mHsX<uL_[<:^k9lEqu5N-*s;uVDMTD-_4!#kc[rKdH`
-i0.NR5O?@eIa"AqS)`u)(]-Mr+oRA-mi6TDp0dY+q`oC]i3o]UKAfVFrr=)7T2>&p
-a2\kPmtJLYIM;"]&j@ml4&te]N90h3idZnjrrBu>4qLNMT+bu>!"AMG$[@O#NFtf=
-pjN/B"OHibn>Gu)n`T7WnE]ebrMk5sq\]+g^ji_p_^g5iFrA&+NF0LC$Lg:I4_sRM
-GcO7%T>Zd&rl\Ksm3=jn+^342D/[AM&%+&.r,V=VY6M2+G^e8a\,J>UjBBQSXT""Q
-!mj+Hrm#upIL?)#IL,I5VlFtpi((XkLE?`5,H:I<mnUUe5,7(tL)piP]FgfDpl>)?
-dkj3;o3T&WZo^p?@d?_8FH&KE:m0gB/MBo.Gc`.YO4khu=pKq7B`A(b)oJ*kVf/PM
->&Wd7nMeI3\o"dTQ^6JDdm%<6g<[Z<qY^'N`^mJ;:Cqc[_\tB+cDq"]3qetT?d?6>
-)sa[1J'#WR/,mW)`ddq^5A0ii&rJ*3MC>3V.&)SIU5C@n^,tl"r1$9:J*`*k)#jTc
-j7\#(PYjkYci3ti(7"n"?sS9^!)'s`?TW_l?h.c8[Klc"kNr<M!32[1[Jijk3WB)A
-a2Hm/)Uq"DU$MTQrr@[\^Z:j_d!ta@rm1TEqLAI<lh]$-R=F:^\,DR6O5KfK4segq
-d9l%pT`5#7Aj>4H5PA@^!,^WlC)F#F>Q+q!iia-_4pV%`]G[bpZc(SDK_ueYc?nFR
-phNs_2%;o<n<M=YY5E@CGd[H$UKgRJB89F(]$*aICN*t<[T<6bX1qNBMG)'&RSVQ8
-!887JYDp7Hrk\U7Z$1p"!M]SoDsOu9O2'V@58(0dJ$a<g/'.3U_2m<Bp.+nqnLIf?
-::5SL=j-gF#iEOl!r/h7?eNf]8ZQVKfjEDN"bs(\heBZ5kN8\"rrCuH57r>H:Sd2]
-ZX8?l08U_Z^&=G8D*N`(&EMFo]E`pLa26_kIht?-RQh3E(&S4(Dh*9uGd#*D%_Q6?
-?bjGG9eY0a;#QtL%!\-!-&/,_'B3*4c[ie:pkATS)"#$gr'd6rr%ICirr<2spn-Nk
-g./qB-MYLJ5N9G3rr?[2!.qfNm;q8?J=[#@gTQ(I4r^-0>)/+p0DHgMM#J1El<aS,
-@':2FI`jWQ'V?Ir#6*01)S?I:IgUE$]JJN=Mk1OMcg;h6r?Fi2Ubse1HplJsU;Qs:
-_u!GI5I',4TC=5Krr<N+Fn%d--c!L&a,.QFH_6)i\*S>!DiK(pK`25Ub.]7u0;j98
-^*<>nqd$[fIq"Iq^'49@qa13Nn?9ksJ5]1;a7*!e_L;gdj7,'8e$Pb%^VbL1rLpuD
-:NZA;q],NUrL('/c]-ccrK9D(I/J?>Ipmg=Hp.Fer(6F^?i?4:D<#Qf:ZARqNuNSb
-5^kA2/)a:C57i'Oj7[-T\&'3gr*Jm%m4n)hp3"`r)ud_.GDUbYr%$3C'B1Zs(EPWc
-IKFmPpiZ,Ea1O%&rr<2<rN5u2VYi.C$0$A/i*Yl,q`3q+!ri8YR/[/m\&:gS^'7_f
-*<+(TBE%r7fDbi&Jc<uE5Oa]"j37\cL[@V%Mb!QCrr<F.p2g#JqdF`9im!dWi=.S.
-e\C'<GYc3Q*f6e1*\Gk=/)tO5j1jq0nKM0jMZ3YZoRGP8rXp=*Eng;je:&]k(AK!K
-4a]-e!.o9:bJg%V[VshDp.b&6Kf-&d^Bf=-br]&+Oa\!l$bZ8^5OI.'HtUp8D[cD>
-p4:_B2>GA2SiZ?eL!P95-%'Fs#DkR<iG\)Iqd]O6pj_e>`SN6;DS,D9rX&u%]AgTA
-n(H1*hE16sU#=7X*[^F&TCIF1#m:&;r&"AS]NaAI;crR&Mgc^SlbBd``kU/m`BUfV
-YGc^>nN9P9o2,C=mQL_t1W>I>J$iRrZ/Z;Ng5#Y6^#S^`IaK5Irr?Upfl-j&D[Ser
-0C`uSF808*YM*V_rL*S)rr<D`_Kp_0'D'-aZ]Do*Jc>`>:(Q%c?]=Q)f"V@f!9#'q
-K<AnAJ&b=frma1Ee344a_u"*,kJ[r=HqF*Aih$m"&q85XFFMB)Z_*<X*WFiD[#`1o
-rWiH'AG?t\hse-nF`5tUp5SQ;m*D_]f)@c$B8sVYG^!E^Dh.fmrm2ankJWu,q!5m`
-YePn)$fPm5D[Ce<rN,o%i1H!Y#ctD*JY!PEhhsU6i*@ZoLAq7[n*Y\C0DPV(rrC\X
-j8T*MX=M\3U5C@nMC>3V.&)SIU5CJ:5A@=s,qJuqAOkYhriaY&Q,?I$\d/.XcbMNk
-r'ipo&Wu'9:kCt9*"WW)^4+Ts@UIcg>h!\7NGnMKrK=RZ?W+G#o24%\J(^aXSu8RQ
-(NZj,Y-5%tHjr6ph9=/;90L5A9-Y(pjIFa2pgF]c>Q0SBp,W-Q`*<!MrrC7P+7R,h
-YdaQK+7+(K!/S,R-iX16)H$A;rkdUSI`-`@a5d%KHjCtf4olf*,+\`6$n;&^J'jC-
-`o$QKrr<(Lq;9U"!":=R%"HZeI`C:?MZ3YWJ,/!Lrr<HVq[@u%Oab=-pko(O!Isq&
-f;JO$p]^-ti0DlqJ+-\#5J[k_\q[n/1u3(Ipf$[;iSVPD7p"0*B^Q%YV17F\%Ht9f
-[R,4JS*[U?8I(_'5F8oH*gtrIq)FE=J(YY5ci4!Ea6`g+?Xcl$'N%:5;+20r72/Tf
-'N`>(2u`lAM".\IOai!*qOE#]'lo0[XBGQ'jC6QPljL#s!9n]^lfW3@MuHDNp;$\.
-ZX!I%5P7tM[_KqJa$9,Spm_9#>)3*A4b%S2n8)2(P@*#Srl)Y*rrE'!:]CF%?%6$B
-ZS26>QN$rjU[e6]!*A@%]&>h.IaQm4_cSQL9+MPIZfucPMR6Y&;hn:eM(\I:4\"U8
-[Cgo?k197[*A[?:9dW@rGAF0F.`d.7o&Jqp!Vl-$^Ce+;@H)bG?:T'JHPC<J5&;lp
-VqaC+1Ke)('U!m9l84Y_0t@I_Gi`2*WB[!+TC>>=pa7Z^`W#po59A_?(9_TFDrRCF
-r+Y0:*dGRrq!n5OB_1Q$pV]905E'u$Fu5a;ioQJWV*hA0Oj9j#G)N22g1?I!G1pf(
-SWluU-`28Frr@Xarl/:L/\F_jnB9dOML6i`N%F#<r(J\k3r[K-Z>13ea)`5$GB<&a
-'^t3CZ)-R=a<Qj-eZNP(U#gG^?<h^__iLVW)@_\!d.CZRC!c)_(6tUaBjmq(\m;GG
-V4EpEBkT)/L>L4qd`UG#cJIA$M?kF=WpE^nS,WHqb<c..T=nV3!!4^dq#\5/!5qrg
-"2#f;^P?/(Hs,uD_VQ+(S+2.1'(>TpT+8M&j0&`%Sic_Brr<E+!(V[[?9S;gKlu>p
-8ZfWkj)=]ZHp;[hY5#X.&Y2-brr@^j8%=1MepbSL/9A:nJ&8M<J*69%rrBim0E+53
-rY:`Orr>90^]"@=J+<abn>ru=q>8_B!:V2UrrA-/rr@aaT`5#<hQQqZJJMVjJOfVg
-/I29(omclFZMspc$:!KPBKu+_X8`1X7@4#S+Ar.=$Hka8!2$r3rr<*O^\IrB]aI06
-nGT/K<`32G'Xo`;c#iJ<Jk(\8L^#89:k<%A!CGP!'#Y=ceJ(kL'N%:5;+20r72/Tf
-GR*Unrr==@J*a-3!WN/Mq=)hBC+C)crrA)trrDCCi_TMD[9D:YMC>3V/!#*s=R]\:
-?O6Ghe%kr1n[=WonGD3@K_5_&$/TnZhbgW-HqE<^Kc7sp1sl$H`VpCVR`]Da#O<fa
-Q</9O_)g=%QHL9-<V8$?B\W"P+Fb:on3>i,rr>7Z5N/AU^Z^7HB`A(Jrr@U7r;5^X
-!/?KIrrAbunY?*a"9&H'!;#ZSrYd]lreMZ9O8KO`'E8'Y^5r&&g[Ft]Ii:Q@5N#?;
-!'^6DiM1>+k^iYFrrBk7!.dB4qrn%[L5iqI!29_gU]1;rrWN6$oC&IR)E.KlL`aWt
-r"&Q9rrCBZO8*DCn+n/V)F*^Ui(s@Q55IM&UMmp2Jc'3]!5SU7JNs)0kl1X;NP>Dm
-U'L4`rr<0#"TJJnn"]k#2Z*K0+3'B>&,6h<!7/B?ph8FNqB18+5O^nq:]CDYqENr6
-DnkLer+Q*1_#FCc5Q(EBrr@e5^Ae2-#P"Sh!!E3'rrDZZU])/iqu2Bn`fL$.p_3Z-
-cb>J8B\W"P+Fb:on3>i,rr>7Z5N/AU^Z^7HB`A(Jrr@U7r;5^X!/?KIrrAbunY?*a
-"9&H'!;#ZSrYd]lreMZ9O8KO`'E8'Y^5r&&g[Ft]Ii:Q@5N#?;!'^8MeCO;R)LPQT
-GE-S=&)r'Akr54F^)M;m:Ufk*kCW+Z)uW:EIO"WkXD63O%ta^disTO:TsjKGN025/
-GA022[E?O+dD0=2_MTbC=oSK_@ab8VljL"Hl$%mJkAT+5r_0Bd_#FD@>lC<[oi(Xo
-^WD\[5Opf/S,U</L]3N$IrsT;CfgOu?eQ%i`P:++!<3$prrBE3Io*ibnWp*Bp\%n_
-GDu0P8?]5p5Of9E^#W5CS4(a`m2>EqhX4H-N*BH04idli-6O8h-GEa[Xmt:8n`R]I
-,h_!f0B6ht&LO^A*ABsl<urHA=eEa?Bc=+pFU]6_qGker]TTGJ=POFO*:i!kpV]3n
-`EsNk:C?lkhcfNhVl/hs*\I7(bZAshT@mC)p3(Ld'BMN,*j>O4$\VPoURiY8qnLG.
-r#@eqr%-?Ii2OJuDu;1?)1KXJ%f6M/)h[[-;YYD7!"F5Ce&.dj^Yp[;Vec/uHu/f_
-KL`knZNpCR?PYg>J&2<b?gF3S&,9&;'(djP=^E?BYM":rrL*/I`]nC6q`FLup4`$L
-m@eh*!!HBuiMCebi"q1H3UgqPrWpF30'C5<4T1t'CVPb`2#Y)Z0,7:_!!M`@[4`*T
-h]+fmlQ<AJJ@mJnc\rcL`FcdP?c9\mC7cEW(T?Z'#.<t^qnde%nKl]"#jhQkSfd_T
-J*eDSrktBJpsJt.r!LjO!9&1tJ)T;_)h\#;ptOenchnF!_&`aSGMqqDrrBEKrrC#$
-:W#5BRJUcE:K*>JW;'rahqS/2iMDlsHqX!2a$6sj`OcWjh0_B\'CbJaM=DsL5@Ydk
-Sfa;)dBqf(1r&f9rrDs242i9X[?'!V_`tUX_uB]QG^^1u/,oVI&i]Mhd_BOHg#HH<
-P.tb6@oN.9qg!Q&rLbgX2>A--h]+KQ!8+X9O6kugn+]:5BCM*Sf)-uVCN%kS_O`LW
-J)e$.Vo.s=G_b9kL\+ePQfnAKg&q<]$3'u/"P!GOD*Q\m`ngjnIK'9Vh>:7Q!5Uhu
-!,ql;pc/`U7fAo8D,3Oga+O;6n[H<+"b1,;JX8P:nUJM2%/_?t4s0PmiWmC4L].q]
-JZnC.LOd)Cp`&0eZ15:npiiEZ2Xj1uV>O9^Gk#CDrP&9HIh;7%Ma+JUm.^#t6N+#N
-iOUSQBCPoH?(^hlrr@^6^n2)9!9%h](O+Ko`*.ro.kcZa)=WE:rYL($2rY"jr"K)1
-$F`jYe&QqIJ)M=G!/)<NQD`^QM7NqM]KrQGImk&K72/Tf'N%:5;+20r72/Tf'N]g6
-dpMZ<=8p@'^`WM^T+*<*U9L+R8FEX`[/EKkdZ*k"f66j4:O?6IJ7X)R,6%X=^0#8c
-;QFjb\V+4Tj-!u!K1O>fbJ*uVTp&[[!5BQqrrD-a+5(kqoJ12hpZ'0+r1Kh^0)PX&
-9l'b+G^'/fPSAUYhga"pXaf5h%fZP"Jrf91n+mnZYP[kKhu6GLrKhs4!(/*@rr@L1
-49#<'$9tib^Z]4Z^[K3uJ,)B#p0IFk%%>fHq!dbP!%98pbJ*uVTp&[[!5BQqrrD-a
-+5(kqoJ12hpZ'0+r1Kh^0)PX&9l'b+G^'/fPSAUYhga"pXaf5h%fZP"Jrf91n+mnZ
-YP[kKhu6GLrKhs4!(/*@rr@L149#<'$9tib^Z]4Z^[K3uJ,)B#p0IFk%%>fHq!dbP
-!%98pbJ*uVTp&[[!5BQqrrD-a+5(kqoJ12hpZ'0+r1Kh^0)PX&9l'b+G^'/fPSAUY
-hga"pXaf5h%fZP"Jrf91n+mnZYP[kKhu6GLrKhs4!(/*@rr@L149#<'$9tib^Z]4Z
-^[K3uJ,)B#p0IFk%%>fHq!dbP!%98pbJ*uVTp&[[!5BQqrrD-a+5(kqoJ12hpZ'0+
-r1Kh^0)PX&9l'b+G^'/fPSAUYhga"pXaf5h%fZP"Jrf91n+mnZYP[kKhu6GLrKhs4
-!(/*@rr@L149#<'$9tib^Z]4Z^[K3uJ,)B#p0IFk%%>fHq!dbP!%98pbJ*uVTp&[[
-!5BQqrrD-a+5(kqoJ12hpZ'0+r1Kh^0)PX&9l'b+G^'/fPSGL)OU[l+`UoK5>)&_k
-M$r3J)g7Z3=R]5:h(<L2D69qQ^h8cP[uAWp)/^?n=NZ$Qqf.,-Q%%@-p1p;-#QC`Q
-(>&@;Gj#&r*ts.VCJb$2dYG$oS,NkSrrA3tqa(5^fXL`BrrD<`!;;>Sl-I8^%(/<Y
-J$P,n^)Lbb0:Tb'LP^I-Ht>i2;%AiEi3?!,p7:`V[rZ>+UdqJ!;JI,!ZYQG_U$?g+
-CDq<#C"ej!MWuWKRe\b[*s:9Vc,[h>l$bVe,>H\%0R,Olrr<:O;lXLqZ^.:DL&:sm
-Bbu`8kWDRNUYYpr<nb2bC0%q>VZY,?lC*q$[s$2)R3d_ZK&0ke'E/;Nrr<IInM1"r
-ko[;\LqYA'4s9@_ZXnF@BKQ["GZ2KUgq*C;?,Nbc-,5@#9()Oub"j@SYj?LaBPjWW
-PZoriq\M[8;+20r72/Tf'N%:5;+20r72/Tf'N%;D#OODK!$nCjm&9g_rrCUFnC"g]
-.&)SIU5C@nMC>3V.&)SIU5C@nMC>3V.&)SIYEqIk0DRB,gB7H"F7t.a!7am)gA_."
-:E9B7aQ)8uq[I9^qG?k`dso3=?h-p@BKuA0rr?^3!<#.]d<5CbHm/$WQ14D=I+GrA
-XbiN?d68n)G*_>rTm92?rM"`a=@9J]3$*M'>MB9+H^p$DYFY[nBME]eSgjFPV>03$
-)lnPM?Q)L\YX<AHjcW>%pVo#A>#($#gVr?r4=-(>4u]H#W^!d"`nqFO+'AFfSf+_Z
-/Z[X_ghC`NF#D_I9sh#(C[%RJk2i%Udr&d%=9L0p*TcS/UGBr`b]!89YPnm"nTX[Z
-])A.KB.qqfp7_82q^hY^pmLXO!;<o#V0lkE;dG%6T>W<k7IV\ka87jo7e*+fItB_:
-_B4^t#.:=4rrBrMr,&dFpf6gmi_!SAqSf(erZ:?R)t70dnM=+Xf)-t8li%e%!.t/o
-=2p\OcEZ<rJ6j>fAs$a+!!FJ8BD`O&o2P5*m1#t/g3'TV]ER;sB>D5BrJg5`[(h<]
-<mZ)D_1"<3kD4L+im3L&b.<Xh4B8(j4s&9=%9_um?1j^/!W*U]_.<QGC&\0k?QO^T
-VS=2O-?qViqR>f5q_eAk+7N)+!8DhkiI.nhHp;Q>QhG:cYK%a[-Jl*+?[1nPrr<3R
-oY5pJ+1D-Ir'BAH)qeJ0HEO%5^Z0ORm5r-\BtAbsi<>[f<ke'XS)aMK[Vu'`62O/s
-'D=!PgT:0_p3HF_q`Ol,?82BZJma&M?gpsCfmh"**Vcs`qbVMN8,+J/=8p[`%0$<>
-CZY>LVg-\KTBu7N!!p@,!V"//(8d)NcNs;PgVZ5o^(G-!`&$3DZWbn$?OoARr-/#;
-!;fK>d!lXWi0U#<pe.Q1S)Xb@!W.BE:&VB4C]=CfS+\<0T=cEG6gB0,a2'tAGRrf+
-`dM@9O?p)FVrBAr^&&iJ5Oeu4rZB>BrA.U+r)]oRr%7^<i]/lW%!XEln=PCs3G#C=
-]>RSE5B$Q%#6arunINRaL#95/__:d4?\gm"rmZBOrMTYqi2<3PQ\rKkp`&q&pj8_0
-=&8Vgrr<2^pj:q[Lgk:Wh\A=-p^?%uOlNWtrr<cjO,4no\CWicj4t7(Vi<kYC"dKb
-VU0c+HsYD]NsbZ#a$,(5TD1%RMQXZKgus2ArK03,Tmk=Grr<4onRqb30$iO,L4<nh
-8&_)<BDD@:#.!(hpoec.-WL&8r"n:\?\A>&\V%fHpp*H*BZn^?GV0G(=h)lW/`YM@
-.iVh-rr>F9;+20r72/Tf'N%:5;+20r72/U*!W,T@aXLTo.R*o_omV9FXr<2["ob]M
-pX_=OC"d0cBlcFr11+0hC,]4Xfj)d9HZA0$l?4UlDD%\Ber_n`F$Gu^]#(bl'n!-`
-rn_"ep4]I%kka3(YPTU/qS&G=/Y8`6C;1KG#H-iF(N?WNX`&#nrZjjPCN1!hZGAY#
-b8UMaT^buGiSa_9Ytt<?:[E6(!/H3cfDbh5g-=QSrrB<"r?"i%FoMGsKAkG^!'Jt)
-rr@Y(rl$>p+5<^e4!9#siqL@24IgAinL^.$k5aF\GQcN'nF5o!S,SJDp-AWX_m/,Q
-rco3-_o'5uDu)YYf`V6S%`a+7q;bEQ!"TS<M8/9N5@b<&4!"J'!9]JNZgbHtPkZ]t
-a&1>CT7[(CZtI0mMgD7aCq%!YTCCINg(02s1qP-(4*8*aD>Z9OSP!**=1FPE'&r.b
-Kr1.aK:*uRDb/Km=*<KX7nh=umdG9M>?J2][4OU9n=RRiLgE'jACInGoS[!YrbF.j
-bHK^S=]o"qqDGpP=0YuFe*8j<a!8[E7Xt=`)Q3N6^*eEi07M9?r6E^i!"$ZErr>;;
-M;S)dhm=d2!&M!3_JuT*cjSiWrZ_+($3("Lm2thfC7k,"pmqEbLqW[PJ+G`lr$ND\
-r;aPZJ)W,1d%C6]dJj1Q`i8t<5VIuOpl"%:-iX0&["#r4WdiA'ickAGp[&:e!6jgP
-n=46coE+fYrr@kgqa,f(4%K2r)Q3N6^*eEi07M9?r6E^i!"$ZErr>;;M;S)dhm=d2
-!&M!3_JuT*cjSiWrZ_+($3("Lm2thfC7k,"pmqEbLqW[PJ+G`lr$ND\r;aPZJ)W,1
-d%C6]dJj1Q`i8t<5VIuOpl"%:-iX0&["#r4WdiA'ickAGp[&:e!6jgPn=46coE+fY
-rr@kgqa,f(4%K2r)Q3N6^*eEi07M9?r6E^i!"$ZErr>;;M;S)dhm=d2!&M!3_JuT*
-cjSiWrZ_+($3("Lm2thfC7k,"pmqEbLqW[PJ+G`lr$ND\r;aPZJ)W,1d%C6]eqSh:
-]<;f]3i7sPGC-4Pg-(acWG3>YM`qjQ6L[16*hBH0X4lesnC`'7>ls0^b4b!`ensHY
-ZARWFT2)qO8J4H!Hoo;3[P,E<"SdmXn<]&^4a]9Zrr@n'4fDV">1S\4kWU0!^!lH;
->bo_B)et$G&0<iAB81Y73T-&kA<'-prr@f@rKmNakiBGmrrCuL`#noaU])4Ap0[h"
-UQYCRrr@Y#&:a9!]&*R<eis:d-htGBn.3FoNP5JaLQ&lAH8PR._n$Y>4@st#C)8'C
-DItW@*iFgrXR..?^XR1>)CmBu::7^`FUO+C)dA5V^5K>1e=tHb9@X[+<gM<0lO3S,
-hV&j@[sM41/ab1Q]"=C=RsD0pGiVHYK'!Aj"rUiohrg'TMuHDNp;$\.ZX!I%5P7tM
-[_KqJa$9,Spm_9#>)3*A4b%S2n8)2(P@*#Srl)Y*rrE'!:]CF%?%5Jpkajs--gYF7
-$UOQ!iQ+,cj%WV70?.cZ1W/hL)IA_Jm3_e14Cl%n[D(5b*@"+-;R>l]p9"=XrM-@E
-g.SF!g-[aACEYS+8,P0Xa1EiTN\JNC'B61*iU(.6Q\(R^c\1sUM#RGVi7)jEM7*tC
-6FYM,e74-k!pDOcQIh]Se+FUA\(5r-p`kW(RTkU0[tDr?i0[lX?i1T[i31/4h,F$7
-n.peWHo8V,kD@XE=MOWfi6N/5UI3Qb-agM52!ZR&/$%s@>sWH<4eA>@:=7h>CFe/q
-8T*,9DsQ<Y1?ZHFphG<RD/]28^Z-ZUiLg,MiKldfAcDbI:#d>k+[>J$J)P3n_@?MF
-#]KVd5OblV!9Bf&`;]i:&o[P65N+?s!16jc,X9qrnL^r"j8T+2+TDGX1$nlWp^?$r
-JbqQSK>Ck#piZ(Uins+qU;uc`p5JsL4rO-r?2+Tne)D.>nR(:J_!d-;&O%:aC@Kin
-:Q5;R#Q.Bf'3j(9<5/l+0DMTg4q#_[*Il!0_ce[RD6E0TpR]4ZYP9EalmM;c`--SS
-n41:?pd[R/+8c0:/pP"F<Z`!(0n7'ApsJRYiFg$R&c<79Fl72l?f9H6!"`c;9D_\<
-_Ai!2`HoRT1`mB[dN/bjVrJ^<%Y&$Ba5S39V`[$:=.f83rWpdK!!LsDrr@U6,5a@1
-rL<feiF$n'ieQn#!9#$Q='rE2g[TpVfBiU?G^oF,pj]A@ibnmG(\gkec]2?HIN`sF
-i+Kt-!![\Uo`"n1GZR0*.B\%_[IF1rNr1]kD]J".e&B'4r"6%*J'^(1pa.rdM;nO8
-!bree]RQaVclWu"5B62qiGZ\r&*b5R5Abo)?fMBOrYKr\pb/^`HLJb4M15PT.==nh
-TmU#52thChJY?E93i!R@1ADI@mtY3onKs<D2hucZWG?r)/#FcbbPhffq[*0Bn__.>
-MI$;X)?#ij2thChJbr%:=SQ\%(K:*unVbAX41P'`qd4%1^)d0I^*W\TnTToj+R@l,
-q"O:\icg1E1qa8nnX%:E6fLmtoM$Dsd'V+,C0D@<LSR4Io*=Wmrr<0trLQ1YHtE*9
-n_<('!/Q"gqal%eiZJ(4J)d1!'PlYCLZ3/linoJS%=AKWL%/mgZhRPf^Loq(UW%_h
-kJSI$*sn^l4A+HDrM=YoL)P!Kb?=L4)XBXa$JbD,_R!t6Zd_i@'N%:5;+20r72/Tf
-'N%:5;-j;#9n186?i)<;!.XZjHo.uEMYP6cg!qr3&,$M3ZF.@ep?,-"oRGQcp6jHQ
-X[^T*L@2rVe%@-iX32I:=dS9.in!6/VhS1pUQH;@L&fiikCr9p%g;ZO7IZ@kFA4j7
-Sf.%[SSP$7H5;W[%@3K[l*aG?2V+1[d/]<L)CWp5G:b)!niJS_rnWe9Q2^h&i4n5r
-Ho(d&Kq\MH$:Fe.7tAA5FT2?X"oeQ1=8ipFr$FTIrr@bHrr<D@rXp=J7"=0+J&26b
-V>gN%?i2$Rn<O"R`A.Am$&A4Mr$1+gOT,=!Qhs;M9Dod@hsK)]a^=SAOoGDk+8@6[
-m'H]l"UFg0YC(!]OFAX._VFp%iL_1VT+!U'&q@b1nJAu*@e%a%iU7/!Y>WaI!3uMN
-pd`/(rQj0(%iT\)rrDpkcUt^pk5Ng+/\[o1m@L"gBRCj!]"T'[D>gKLCld6S_O:^j
-[/U,_?a0k61XGtNI<3=fB88'$%H8K)BjZW6Vo8T8!ri8;][ZT2'l)J%Xo4HVBf@r!
-/cPg(PJ]QtqZa:o>Nl(egX](GTc*_RIbe?>rr?l=ph?Aq<Z24(Zlf'S:YOjh2sb&E
-&,m6u1W,Ygp<U\gJ\U]6rrBo?YBVl&&apHZU\dQs3fj1b)LqZ0\u*%<!!r%LDZ$!M
-m4Si]*aBe#o0:t>HYIpmJ&+=VBWUU[euh5Nrr@m^&\6HPN>GI%n=HKR(&lcJ/CZd@
-4j*cp>orIQrX&(C^FbY8M!CQPdk8EKgSmBii/d[nNs1$d(\l>V!3+$*rr?D8=3M^:
-pt+N-$hhsB"oC=5l2Dcg_*8Z!Ae3Vaj'RUb9:K3Ur)IChYCJhP^LAhtpcD:!YG0QU
-dOkA]WG*H]ViIoB9l#0Nl8jpeUSRZ[D(eo:XfQZ'4aZc&i",`#"68j0^MWpRi?-$W
-#^d`A^LbS1&:@CN.<X\.$YUS<e%B\Z&!+<2r"OY[$>KAdI`koMO8Mr9:P]g:%eL9a
-rr<YF*WH,U4>$OFlBbC_WT-bjrnCd%^'&ZkiSKhHL[e5(3T-O-rrCuA^UCVj5MMsk
-08R=kHs=r]+8C&u)Fs]\\(Rk^*GJh)dPQ1J!/9J5!!LsQL-KK](4#WQ-LkH$Y?Ulc
-ic"3Cj4t*\^0[KLffTS:GXkHW^U<u*@BB6r?hf61rX-:79&>$>^DT3gh<7'.oH,#s
-Qc(!8:&b4I+8/XHnE7UUNW/tt2!k\M$0hHi"],)tZsS?5Zaoken3=]1'_MD*MVf2!
-D>sTkhA5UY`gq>5cb_p"qo#rB!S=t`IMHN<#WtuEMk+Wie#`BD:]:]`qc_eMn)8K-
-9fp:#&,\M9J,]KXBE%r<?cAR#rWu*p!!Nl-pZ'"-J&78orrCuLSgNr>p7M6rPMolh
-I5CT.rJ:C(Ir+QjphO18!/?p3#Dtb)2UVL@r%7^0i;WfD+,4.12o6LaT==`4qe#bS
-ph0IUrrBl?rZcZB++sPDpoXPr"QT"O!0/YD$``FI"nALDINJDUnQ17Ui0aNEZTmi0
-H*$eI^t7HYr+"_\2oGLT`_VNL0sJ+UcB%KE2'!dtS/rR;]Y5rJ4B&*ASj1j)K#@;Z
-rOb6YA,A@Oh@]P9q`im2KD(T/YO4Ver?'".(r,!krrBO;m$I_P$K"AC8*k*i<rUVJ
-2qBUq"+JZ?[\&/#-N%$H!/.ZPi9/"]$2?a)rZ1MfJp[m`Y<V"][.8T3nHH:g?\:R5
-rr?XaNIEAPV$G#$LYi`Orr<SGnWWZQpq[3N5E#C$JZX&85N/5p]N'+DCZ,3ma1i(2
-6MPDnC\k3Aih$VRJ&Yh&IQDj:f!WhZhC-pe8#Z>9pk<_JDhXK!&H4J1Do$`9`p\a+
-:XMTF;+20r72>@MNW0">i]M#V!+]Hpa8VtYZit]0m";?R)E*lX?X7BT+(h*?gPa*+
-48D]IR%*%&_<DgqcQ&l=nO@^+$o[#t"bF;Uj7_ccIL1Bl56Nf)08[HNB?03mHQNl8
-hZJ@?DhbCa5KCJOnCFN;!$L/1q#9u6D[uOMiO5)P#)VuMpk.U6$s`)ecYmm$>@-&X
-P8ATTrOMQmN8G6*pa+o?45u=fj72./!(alp%Y=+Rp6tbgrr<ITBB)buBi0_0?#S]Y
-WGcY55DS,/D)@'eP3Yqh#KH`ge9"?./hXPi)]M=YS9mEnM=p7GihsWY/Or^1HSsA:
-7<S;m=KUt^jt.StL>l;eUP:5\Jh)bHmH'`W96flBOqs$pB+ecOrr=8ZQ2^hl?%;kS
-9>!2j4+>slnmu1:#Q:+Sm/d4eWh78<r_/nDrrA2%`8C8,e3ET!lhdRZ!/"aqjI6(p
-J+bJnci4"AJ,Q,-qU,80J)lj'rKSIchtk)O-.foZ72/Tf'N%:5;+20r72/Tf'N%:5
-;+20r72=`&[+G5=Q2^iiU[SNg!*A@$9&Z_PLqdirq+''(]DhkCg&"]tl5AXYr?uIA
-\GXD<pA3C[2ZEc`2oeHO0<Ah"rrBl-5AaWL=&[_`2lp/,hW)D$n4pC]7u+JM%o;^q
-QD`\I*n&O2#IX&+q@AO&Hpa]ErZo#*r#r4fU=W62083m)LP\,DV-\E(9_"/Kqb[2I
-plY)r_Z'TH^LisbJ3"5.#BSkk#JtpC[f*O^C*+)`#K!&LpegQ/8^k=<i#$o%Hp,mW
-!,&Xs?]U!9eF5#XRf$1TS\Mu/"b+I_!BP\;iX9+JT=.P^n`)]J(J2+,?e`3NQgK9@
-rr<1Rq#1(Crm&ubg=,binZT`Dc[`TSrr<ZhM_>Qi_I)9jMn7`*_r$?7l2Dh#O7>]_
-;RZT*Klulp`Vq`5KmM(bDiHspr[6TQ_B%SCmu<qRIqZ$Bf3U0$B>e`)^PLe:7Xt1_
-+2Q8*J&+XiAq/Lo`uYBY]AP?rfDZ)Oq\"9?dXFAnQDsa8CDs+iJ(Q,Lpi60qpi#k+
-Yg>!eB[;Qb,D^_hrJWirnJXWKhCe>0QBgrPiYRUR+DJP!e\"KCUVKO^XZ#hADu:6[
-p9*p%`t-o0ia9P%!;Iq_rLa)iA1rc=!4S<m&]`qFhs;[P;>V8V6%<SJ!83;(9CS"]
-D$0L0pb[F4Hm\XOid]X";&YM6mhC"JitqVD^Ps<Ir"nksiW6=a!/-d5H_6+_FhWHW
-C&\1kM#RI\n&:@@1Z=,Vc_Gk\rL\SuQa@9_TC>bIg2$D>p_!"/C4?GkLP1.iT8=U1
-pebhr^I\@Hp^?,cLjolH*W:P#iOf*i$NC+C(SZ/7CL7U%_E[a22E<T1dI6OQ`;Q_h
-%,W')!8sIWS<<\Kq"_Pb+7R+][]o#\alhts7sH9X:*[S^p-ns:rrD>(q`i[=rr<EG
-rX,.p!(Lo(!.X"O5A78"PjNPd5667JrrCb'`EG4=YDoi4J+a`Sambq?r[.+n_G?*i
-!3m(%+6!5"g4R@JrrBr$Mu&Kfp&>#Oh[R5<iNLuHrX%E>O+fb9nG]oVT7\3d4Ai"l
-RRb8f)>lgn;=J'tBRVl7FlBlYA"e9G1r&f3rrBhd-c(9RHms!nrr@ueX8^LR#Q-%?
-n&JcIgL'GT*tYetM4PCUqtj=keb4L#T>QX\a5QuoL[a3pT-(H_m<S4Xp4Ml7!/g[t
-iS?0Gn%uhrRKp_N8)T0?%u(umJ@*!-qu]Fg!.n$p%/;jP^VuhNc&_7uqbQu?i(r`I
-n:'-c:Y%aCrF]I8O(-SP/o!Qirr@XnG\?_,McT>>M*+0&/5>Z3j5U?5q_\;sH=+Z"
-SKGY^&ZpF1^+/nfibofCHol8$d!3UIpHANV`)$.Q#OF%GG_8NVO20Y-Sfdoer,&/&
-InA%hr*B1:r$VH4^(BQgRZE0;C(Ju^p:0TFM`aY0C7bSjBAmbIpk-@('u+8ILXC?=
-gW$rKnIL=ir%$eLMOH^&L35#=("het%mYX&R'nmo44$/JpcnK!rNH,$qaSR)!"5S$
-(/O<.iS+mqgJdY"`uk(^g-=r)iD"Cm(,(:;F8I'S_r*.urr<>NJU_-ifsAKn&cVib
-/b!i?-^CJ)5G(sG5PufK1\#sS]Mmf7`8C&X>9=^7rmZB9nK7.lqd8VQ&,uWH+,Bh=
-n8I\InE9-[Z*g3Z4sbH7`F#mZJ\PZ2HfE*>`J<f0C[hMCh[hI?+8e"c=-*@]Z[;f6
-?OH]^[J6YorNaW*V8'qH7ooD/IOFJ^WdK$[GJUJ=Y^aJb^MEiLMZ3\GMYoa/QgHI'
-2uJ!kk+2MP"QS!]YWoT\"T3045:3Mj$blgn_H*98I"1Yc!92>A?eR`_;r6F,]>?`q
-o09Ro(#gm%>5*_oCD1rRfIhUlr-eO5]ITaj?a=%UYCliTZnI7uCZ5j<Gj"dVpo"!i
-IafDqp_WHVi]"g!h)iK"9s;L-&8PV[^LNni%nQ6RLce,%B`l7?6a4p$&:?Y9.Id)I
-h[I41HkGjCL%'#trX8LLnDBl<!/6F4!!Q*s!2DLOJ3WR8T<q]"!(qFKrrB3O7e(,F
-Hq1.1ZUaNZM7c'UlM^kT"h00_Ff"<UcCLtM4q$m\kCn:>j/YBQpp.oZk'N^1G_57t
-4uDbQN,>q=@OjT2IgYtW_`f6$fsH`c9>%k".&)SIU5CJ]^Dm1Qai&GUrlDjjO8Vg<
-BF=S8!;9Cl!0A#aGQ.YUdGo`T;dTg2o2kWCrL3^Bpl"iNpgO1&"Z?7A]L;;hh`a-Q
-r\A`Ap7D&)j)5Od_sm!c]8gfhT+G5Frr<)6,XZQ6RWj<FC%08L3P6=#9?4VdV1A%]
-`f14Y4@*m=L%PhQ[%F%AD'.Jqi<SaYrr<2Ipm(_QHo8@^r#bJ+p.FkqJc'HFcNX*T
-_!%C0IqLFgbJ522Ho#2Fn?^(p,IDc_PHO\U;80R8Dgc5L9cqEi'_,bO=FY#:C2fF9
-%ZC<Yn%oV4#l'bd!)7XeAq0Un['0?.li-t]?/`Bjg\0Y,!0\o2YWqL+5A1T+<;nJQ
-nmh4)r/MgErrB:JrrE%_4b%SR!:Xf+r0(LA&,sP_g&D'P!)NUpZsA/b5I3$@P*Z+J
-ZD6serr?-``4G^>.&)SIU5C@nMC>3V.&)SIU5C@nMC>3V.&+?Vp6u!]P#B'g<.4iI
-!:'LWBj<M1jW6;SET+Zk?O;0,r$ClrhEQ[B-YU7-quPfAe)sA>p[IX0mX.BpCIr)Y
-,Z@3OG5?@[b1f\\b`L%H7Z'I-%tn/7,5o!XfH[WLrr?m(K:7LRU+O'Tmu0J@0,X"]
-.D!!ED2)nW<q,#6Xl,0D;UlWbqd&WTi?&S6>fmJ[l'C(]eGfO<X?UU+qE-Faj8T)j
-J)Xi8!)*HTpf8KG=8a0Vm.()ULd1D_rrAns8j4)@h)XZl_Yp&kmRQV,nLU<RrrBl#
-8+RG`pf7=o[l=7,-g^U-!/NT(/,oUH#tOnCrrCfCrf7`dHiF)a)u,]u!7M(GrY9qM
-c2Rc6M>KI9!9+Ic9)enUJlSEKIa9)O[3(8J&,mr*d%;EX1\"<>,/*LoM#J=f8)^qm
-X]+/lLM,Y.'DNNc?OZ@M<T:XJ'7>*#l)JuZ[*JjLn&BZSOelc4G\5ASST4,eT)J%n
-j%l`R&cVhY&`Bki,6%W\rrD^OrL`EFS+[`pg[W#8p7V2/qdX>IZ*2.X"l0+X_-jo?
-qbg\<nS@.q`1P_`6MP3j8pIDSSfdJ]m6CUN"CKQhASLX\j&bUQnNZ_pnG`L*+8@14
-_N0[`#C\4KS&'T\Q*-l@`%Ma:R_Qf0$2f2@Zka]CdsQZE$9.tb'CXZT!9<O)rr?a$
-pg=Vd5IK('rr<2;rL1,IJ\M<e!9E'&C]=BjT+pYl!,)o<.Jrlb_8#J1O4p5HJ+1])
-'7LAhfDZr,e,C9?pc%2>KKitMO$4fXDs[Sbhh'IK8&B`r:%7a>Z1ssT+1I%''gMDZ
-pbVH8p6potfBib2rrBoB?c2mDpa?Atr&OX,r(Hh$q`X_8p6bUei]l*hp'(Dr^,C3d
-p6sH[@f%h2gV[A6]FFB1!9-5^YM!j2?P@l%Hr0Uoqdt<*?OK%HIa<Kar#=WCp^*UC
-_X6grO2/M;rN&,&qdFk#rNe_#ce5eC58&?0qdb(BpeUF4i7I?4n8lPjZpoi?1W*Q2
-VX[aT$i^20rr2tMp3\af^Of18^i'ATa^58MF5d-!"o*$0?-mt;n;lPcMC/*IW;JsV
-RGqQfHp@Cqqcs%Hpik`b"6)8TrrA]VDdOL`bTF93llg*?.;D'[HpRX!koM&D_>aK<
-J+3I<a8:?(k^FZLBCQAKIgl<7rrBl84qrIkINr3WOSD2Z56`^R)15i^#E?G!rm6)q
-pq?1;_O_bB>O`*ZDoBs*pohQk,5?0IMc[431cTqLnU?Jp6iP6c[<@W.<IWE2/F`t'
-IqoQ2J&+*/DNEJI4u$^dh[)Ib_;Lr<?NYdmYP9EAm/?Edp6P6_Tr3-JitoM'KV&MB
-08Vn,r]5PF;nb8:qo)nFr[,tg,lASZU:b^>]AbJoIQ)L5p/:D#Kf+>Z!;6Ek[/U,B
-0A<>tT_Na#(?>,,pcmeGL#3;d62P6Kr'U7]n0>jn"$^Pq5A9Kmr!W#o!;mGdir9"0
-oPH8TP43,NoD:9?.>,PWDi0$]Iu=7+"oNl0DhihJ[t1pP%tdO7T7sQF:1)^F6L^?/
-O5XH54puhm+170G:\Z97r"IDlC%5iprrDE9iX[,[ci4!L[Xk1JO5`B`IN*YHp_3.d
-p)WX`lp\#NShJfu_`tR/!6&m0VtR.[A02@H-@X@An431jrM#(e?eNoHh@fT.iua2/
-!<3%2%gdV"n:uf`3I]<S!:Wggg<8[jK"n]PM#In^D"7N*mC2t%rmT^l3[ah="2eG&
-nE5D;"]+WnpV<Ej;Jueha1iF?i3%MnnNH?X:D/&%rL?)b^D[$urr<To&H9sVhZl>+
-pk-We!3ug"q_3C(n_UP@K>V%7oZn"OrlDhirX;q2ci3tKr+5b2rl2NUVu&^RLZ(Jb
-!W*6%D>h#[iSFM6*.B8_?FnY$@ZQG^n?@C[c\UKJ;;^&.p.bPeK#R`;?Os:2Iu/Z_
-?\H'2rr<G%_I'`)m(!qKhZNYCiD56C%esQ5&UtX5?3^0PnAeJVoa=P4I=M,[rn2e.
-#Js+UN$#B,Vu'hN_R8n=_*?ZR!)rZ2iSWCfp6,3iq]L@-h@B(*JMb-og\*`-UF5h(
-n[%7WMne2BJ$fgRjY-!%j"D;Lg"Pf-"25V"/cCb0'5JXQp_3N\puB=SLVsR-&:>\s
-MfnR%a?O2WgO&XdZhSV3=8)XB]FX!$!/[$!Zk(.efui(/kNpgZ4\*Ei!"8]TYC=t#
-!4G]$&TdpWoAU;6.p;Af`/bk@O*kHr57d%O[=\0`p+4V(1@j`P+4,,ugKrY.K)!UM
-a?1.52/?BTiVRNle).Nn_;-X8]D\=M.XotJ+8r%KD=G1:$,Q0*)#OX.%m^)I]QrI?
-h/D8]r"DT>T+Sd]I")(qK!>6nT,%>8Gf/R&^i'b]@JJl,2Q-%Rj5?QJ?Q9!cr\N$9
-A,ALg$M_[2pV8^O.CYN7UAZ24OT,;pYDBq,5B!aZJ)KdU5!AoG_WCdtKHL10<S!f#
-rrC`9a.KZX`P:'[i"q$Y,OqPH?OqT$r&siHFeO19nB^L0q`Ff7qNlr=2-[7$r#PRQ
-nI+>H^n2]UBV-BZ@IRL@'E8'L'rh*OrLElf?`9]V.&+F;n\>!l7u`#bMu4Fl!7^'&
-J?PUF!+et%!IiXMp3du@rrCS,n;=m-?2-)M7K1TI'RhBV9E,!DIe_s^FC#7Jh;[fl
-i]"gEfjj`BdX4u3n@$6oVhcB3HsQ8,i=EkfL=[?YN'83G?8oEGF\`kL55tW"4u;\o
-XfpMp)WmT/Tj:uhMoIjsq[7YXj'V2!Ujh$)[ibMsbnJ%p)RT!kg\_BVPV%92(W/Io
-r[.D]WuZECLVs_W2oXYc2,+;Hiua(@(M_0\T+A"BiQ$Zqd-&mMFhZAuXYW^H,%&a-
-^Z;Qq+TDGGO,8AYf54Q$rrA1>9)emq0#.DdV;</pS\K%qq(f/."9-Pdp43/CePG2Y
-rr=B1)ufoZiSn5A%,_'bksO(s:]CD!`IGuerLj/jls'F\rrD]k!;f4:oqVC>rrC.i
-Du2"K+2@JtHqUYmU5C@nMC>3V.&)SIU5C@nMC>3V.&)SIU5CJ:5A@=s,qJuqAOkYh
-riaY&Q,?I*+7W^tNK:mdJDV3X1MW4W)O?`ZT>FqN4sXlhFebaVGPZN8O,5thIqNOB
-Oj+ki2ccAhd+cYf1<1B[Nq#Z?;!7)8!e5.U=&-'N[6NAdp/1<[Tmpnoe_c$]p-8>C
-nGmfSH-f+Y4*]I$gIo=9Gb.P@hF+rn*Y%W"(Qp#b%[dGg2dZLaL3ig25NqW%AO$)X
-rr@q+r@f-SiL[f&&,JCafh_VJ&3o0Hrr>^sOhYP$gVn^Gp;[&r&>.rhfK\AP,Fn;=
-pAY,(kFp%i%i@8M0DK0egX#k[1\OuO!5oBBQi@'5ogep9YO1NQ!(WIS/H5_0#CK2E
-!9j9SrYa>]oD\fcbl*iWnH6KOrrD\><un8GIaXhi^+4RAn<_/@M8'5n0mH@OkDQuO
-nD?R^rYU"unTVeiGJW,qnFsf7Ld)b.jOQ0V'7=oslYkdD%dRF4pfHKK-Fg@onAX7J
-Xeq+!FUNQ,'gA2X8,SlIK"pZ1r+H$0eDp7PWI>BWg><9%21Es1*ku<j%-ScE1li2q
-%f7XI=2\GZl!>@6pdP'IIq2hPiSTWEnB@IVe,3:IhY^RW!/=DHRsUoX&cJcEc(O;C
-n=on?G`0Js%D5j*G_9)*Jc,NJp4`MHJqSA1p2g#,nK[#]Lctq?clP.8Qb\[8rrBia
-[3+cZn^G8[n0UqbT<n"%T,r6<j1^?lNdPW<Gi.PbJc7S&e,BrM1\P\\\)Ru2ph/Md
-_;C1-0lIP8(3[D1nFqb:>HVZ=(;0JG;uNeIAW7ADIh]U4lT_bcm/I']HqjAVnG`Jb
-pp'@miRXpsPMt&INrBRe/CHA'$cH5P`4q19&\@KP?6K#mnG`J^nG`KG4>X/**]!7t
-T;6^Pb=D(<KrNkm;-@Z1I.n[H#OV'N$cb<cm(F5%l1$"VrrDFJi1J^Vp7Ll!m(]QJ
-8,+P'S&'P<n?9`*'mN7B8,]*1CA[2D2(o$GN&6N,_uiR*/"u`albRc`a+j7-5>M!;
-V0L!qkq/tfoPY<<#K4C2?f>Y8T7K%Am13j1J&9S-J)]A\<;(eKBD>8PiQi;>!5dsi
-+70*h*sVX(rLa!JnC,<Rle5FXqsX;c*tUU\GQYh>%IpWXr+Y,^KpFsmQKc+6nZS#O
--1Lo_>4Hd$kPkPOg)gd<+8d\i!/7oZ@d/C3mb\Q1r':8^Kls(nIbNZs^LZd9rrBo5
-XA.["pdqj7oFD^b/cDFC0RPXcrnF`anN;,!LMo;%A)k+Li<f$\V/bH5D\(Q9qTc#&
-*ta!<+5(/^rrA);pfm9,p6PZLrYKrV\bL[608gV'%_a.bAGC<*T,l^7/F\CTipRJ(
-Zf542&b.f9oZn(AnG`L*rZCobj5"pt?8@R;D[pHL5D"8gWTmZP[?lX@RI%E\Hi$/-
-!r,iql<6EjrrA'D#Q>]XqDX2inRf&&q"NcTK)?^hkroiK_S6laFVfnB.j#>g>'8)N
-LZIr#^`STn0ooJKMCgjd/+?X"hhY=okoUBt@sOhs_5)Rs9n-[Ypt=]bJ3H0l[IF1r
-i4m2@!dm6&J&N^pikNJtg&D%BdJRY8:PV.NIqt[0T+eWi");-apq>[:m>q$A?gu'B
-'L![fD::.ToW;W]B7Vq$$H)Ct:[faM$Qk3(!r.-7#K/:L?f>Y8IuD&ErWVSu\+[ST
-hi9o4/Na'/G[&(prZ&](4;n+$n5&bKq!$b0)Z3%O/p6J%&9rEXrrA!?5PlXPC[efd
-Hq.tJCB";'OEg63Zfmj+PdXacM`#tnGlIc$J)I)oZ%'YU)LPfZ0?8"b)rU_rm+8<9
-,P]''$;5C97f6Hb;t+j'pl".4It1n4a6abGC**e[nW/\]/pps`rr<N'-ha,+@AWa^
-l)aO57n<)Lc2EXQPe'9>*nN:L!'gFlIqjJd+5j?@0A0^Mh\5ohn:/DA[2t\3:]ATt
-?aHB?/SF+hM=C,s.F`i^^PS;LYWfVfYJPbu+k7t1:W-TNp_2U^m18aA=Llk_]H+/"
-=':0m^*\\Z%h*6B"i$%E+8#koIqp.ZA&\;b`*X#L:\L+QTDVRG%tjl^&3M3,TAn^]
-iSTTd%^iu[iHN7*L`SXMiGX7\)LP!&1uAo#hY8JX#E?GEgKaY;n;i3L9a7$F58&5/
-hL>gpg26;7,*Pf.rr<B)d(]RnHO#:C]F48Mi;We:/\GfW%3*05%_2##`4lKNNXlnM
-X2KJlXhSPq%sVa)1MHX8jEgQV2;d*Xo$?@)NMC3)Ff=St#-P)B-eR0Li0iTV)h>^%
-ZG1"Ke%@Vfi89N$#Q?++pp\0`$FFXP8+7V?hguX_NiAq(>Obe]jl,S7`L:VW-2<\_
-SKh8+rJm$;>(4cR3g/5deMSupGdG9%)1E3$r%IQcO8NkbMr=nn]R08M!5\[8paZmA
-/b,=gf>@"1%n6Gi4qIEii8;I;KDLABNt_<Sa8Z,]5A'?mC#8sa*A2ip^;j+G4n7CR
-r\NBqrXJY=Uh]o0[4fDC%euqidWFpkpfG7;.b-Aj$@G/0Q\BfYnIOR'Qgm0$%;5Cj
-rJUS6n8#mjZtG2ECVSPT6N*N=Hf>F*$2>=s[^5MuiD,a/CW;qqZ_,1e\"4K,T>^Wq
-(.$lN&bpt/kJ;U%\%0nnI<+pVJq"+%RMft.9a=X%?[qR;M``NMh[9-ka'Jr>2i%<F
-i1Cp4In&s@K=k^Q4_IO[+,,)FiEm2]f%S0"]M7@W&ErjIRRY!LrHCfFZdgmLB1onK
-e$Vn2lIu*Sk'Lh%Q+@;NYE&O!rr=DYj'V[-rr<6fof2oC.u_ih%X]DGrrD"'R!;\>
-^:j&lN:l(a*[J;,n[>I%?[/oq<n^<@WG4?&A2`\MBi4m1AEY'Vd@l1g[Y2c#k^%=8
-'5AGQ]@="X5N,jp,Q@b;,>nI@_S]@Q!9@lZiEUaTrrA`;;?$X5_c6X9jD*B;pP&Sc
-pfgqNr'@(P55s/5dj?m):Au`W\3tM"iGe;A=ih>X`?^SMA0_C2KcDVGI/a3;0kk"g
-"kWbSoXi"`o=+,+rr=BGqd=p,Y("_>qPjBs?f]8fJ,('H9E,!#S,WKe.!kmWrrD!0
-YPBN[Zlf7)J$].Trh'2jBY+2MIqE'`,q],sAOkeTriaY)Fmns"72/Tf'N%:5;+20r
-72/Tf'N%:5;+20r7<f()2?*Y%V17j1quQftebS^_\8!PR0AF,<;>'g(rrC`\Iam9O
-L3W^4:g6`rOgtDkhadT[iih&Tp;tg5(OTTb?i)YW/bjO`Hp[e+IPp=Q,4R%uD(FVT
-`X`LWcG'VQ[/U+26%,j0Rbgg^CRSmqr[E4af;q(hTQlr(e9ieD/,mlP[*OUn)U?&#
-eN[`L+5g5<08b2^pn+STBqMbTpVK(#iK(f.g)j2^n&4[T^,5]lg3t2ocG-TEm=T3O
-45>>&>N:]a_u:DMfC<4'/\c#GL>N2bZ0\T/D7jT_!"2<jN??g(f$\q;nJD*HIL#Ba
-Ns2/&n432Epj;m'rrBo3rr<<OJar%lrr@^Fq\T-2rYKeFZhmPtbl7ZYrndY*q[`TL
-+7R\X!!n#frrBoOjF:XqIr0\P)u[JM!!qJQV#LG37K&SO]qKphrr=_P!3m(4'Y!f/
-d/O)VJ+t87mFCaUp71XXm5_"m_*\/%D+hXr0B8tsrrD)OL#95g_p8_c6W!QQn[mft
-_iKKn*e"E?n)08ChhN71n@l[,ZJ4;^T>nSIpl@YYcO9YSe%B\(=D:hY$8lZZ_u:q1
-]C-A^_0J3qIb8#4a6bbD^OuOdZ'Xi6n<;fA`?3a5rX)ffT7Obbrr@V*m0*/J"T23q
-4+&USYAs'X`1Iu2GB<X@HnP0tnAAW.M'%=,bKg?-+1#>AC\pkA57bI^Bj)%b58%47
-rZ]'nCJ"Kerr@Xdq!5m?3WB)2FFM#s2=\_D]KtR2)Yh5D.fGY1;r\B)podlN]LCh@
-(&4]F*s4V3X*B98Sg<h1YB+uiCRY75X'OQHR`;V4?/96VStgFLH[B`qbjrp/hmL/L
-TCKhu$1,2M+16<R:JuLf_4S0OmXNroJ+,u+S4A1Gm#1dSrrCR/p4'9k?eOcE#snGU
-r$g-FA5=7o62e6@0RQO`^6dgY!8>3*5ITI%`kCl*iTJ,5rB'`Pn?7a63.BMh5I-oA
-rW<)B*s2HBBYOcHK>er%:q[\'DoL%W?7`hc[G[)\Hnb>.iEm.1^'`G=0lnT]'%OPm
-!8:ZV#r1H^)Z4FAY-7>YiLfK:!9:g)pqQMfpeCWFHli6g5AIse)rnEH^Y=\?#5G+T
-08mTR8&RQ/p72)Or+#8,i:$%@nMfG<`"*12rmMninaF@4jSc62BE%rDf_Dr6O+dES
-VYi^K%u9e,#5F\)?@ViirrBkd^MSJSX2Vgd/Q]ra&,\q/XoAC=GY@"6N5#sSD9pr(
-b=A2BT<uZ*48W[ibPqPD4qtj5!!MZ:rXjCIp-na<rr<BUDq\.KO2KieIaB/H4CP7;
-;tud=:P8X!pr25%(?=Cma'Tq`/cMFAZi:$`Qi8K5Yl=]>/I1:MLjWRgr=@g[rZD*0
-Hp?X1%4bf8D13g'#JqR6TC>u*LHZkc?OQ0A&,]`&VoN*ceU1<q!!NW&)^_9Ja5Ypi
-N.)4`@JG3.c]*Dar]GQfnYa9A8md=f(&ku!oM=4/`4l`[/9jD=O2?D!KB(Lj^[Q`h
-^&c]s)=)`,poX&OiLe,>'l(Jp^+f=Lp4L'RZ#SbVKAX$uIK]F1nJCnHTA[JBHlMQm
-%g%-!e9j"@$X!2An3=qM'L!jg-HEuq)tgti$a9=O5K>oC;=HfhIg:3Ci;We.mX-hM
-&)&s<n;lohq`=`55IMBp-i6#Tc<h*3BFbIL`B%V/V0j0ZWP;tnJmJfZM;fTfc1)J@
-0_#[oIi&"sQhFGS=n'bW?P`YAC]=BjhCmG4Vt%74XY\"I)h!?(rr@XeHu/9W^gGfr
-p(d'QIa@`&ZS1^2q`g-q^*`X(VKelqmtNrKq`&@,+7N!cK)Yi?:TYR&pfmVJGdBj6
-e,KCUPMuM3rr<Jli1GgOI])]`p?_9mNpSZQLcY!Vp!#kD)V;l2DhpUn9@)7#p8@k`
-5Anf#hmLet:[kje5k'8V^))/^rKFla#K#@%Hu/S9qb)@@rY^4Dn,*p$9^qM3m'R@[
-^Tp)>%5U]QJY;pXrOmXbpqOT[Br"K'!!ppK.\@>up;b1aGDgRH#j>HYTRP/CYW'Nc
-K&7EZ3,3n,nG`LTrrDSqi0Wh\rr<KMi31i:_B(/r%uC5cifNq<i\0&mrX**2>l6%V
-dQ@]8HlqlSKYM1Bpfj=&rr@Y%=o9lHl/3'jlb<[P3UjZ[&.NPSnE5W-!,)ft`K=jQ
-:QPM$hm&Ngg&;2)b9+,mQT'^a+F_m*&GX*"ce9=*n:0iCj0'AG-fTo;rW.7np-&3<
-q\/tST<m_J$h9,3iCCjOM*D3Y0R+\t:[J12qb_gjhB'#uBCUVjG@0i:?Q4IGOn]_d
-n:uY15L&4a"oJ<"m-FNdI!tM)mBs"ogKtcZpcm`>?fIu=rr?fGT8;A2^)M=_`h*l#
-mt[Japp&b,pa#%=^P9<YJpnqhUZ"_[CS-J*+1Uf9r"FRu^CWMKib`nun%sKC_S.Mp
-V4mfIco`]9XWt_brr<]):QRaHJ&*s+D%D0s!!'_CI`n0BJ$TB>r"H&W@/g4Y7=9LX
-mI=CYpsnn=_;6[:FlKV"-a/.%!8sB^%mDB=4nqV<Y1NA[nV31rVo/KjdQcZ^EHm\_
-?P%TpnRLJuUFr>3H;>#qLZ.BND=I@K8`QF-n.5F/'?:kq$@Wlj&GV+@hh1nen@-3j
-&,sY"""_)ZnSe-3rO0IUh)k=ap]^/*p<`bo^,p^]o06jUO-/7Ic/5d%L]/fO0)^d)
-\(&0(c\3DOq#0-c'R6[t^&n(BDt204QboAIRZ6dTrrBPm3<&up3rUT'X5g\V-2TuU
-,5A/;!!qbGF\hcurr?b_flKL34E9@D+2QZTmId,s45caJh[o)1)DobKp`e`sZi-Nh
-YC^,dGO4S`!c.f9LO.IB)DrUf5IHjU'a*Dpp:Uui^,u*/:[kQ[r%S-NJk:I/M"k-C
-CZ03KS"GK,rr?qcfDbj?87*J6"6(tm-K">h?i?9Ti0`@@rr@XeG]q9H?PpF]iQm84
-5PD"n#_1fsIqT:8iV/*a>s<1^;>?43]rn7JmsooH3q99m*:s&Wpa/Mu:O1nPpa<8_
-X]JR%TBn[)rr<2rpj_dWp3P-!;lBO^pku0<*u_j/Hj'DX^Yk-eZp0:o/a@d!\bIPI
-fmG@GJ`Hb1L0sFG^Q!2J^BSP&?1C"oSc\H>M#J1bG>J"kj8T)ileX2_Vh)DiO.QdY
-3W@#?[9(>NpaC'5]HuP:!01,F'L"3u<U`M3IL>;q)Z?nQ9rPu!pZ'llU]1;s^$o@+
-j1c@E^Tp)jA,Bs;7.A6Q4;75urX";<*A6)3Qf+/'_`n_-=5sgGFe*%&Q\%>:V.lP1
-Hu&RCrr<2qpfldnJ`![bloji:ig,;u!!p?Xhh1q/Z3TaFn@.C1L4?T&I;f)sh];VZ
-pb1R/$2D,!rn6f/Tr[s<=8p;2#*GiurrCc!(9=Fup\t5+qc9,`?J.sTbeIN47=9=>
-J,)'b)ZKfj(\f`b!3+$+!EU\DMT)4e7P-.i^q0OGrg.kI^39Ib^Z<PPC_-D#ce8L$
-!*)7AC]'RtDuTe^LP^NI1OoE)V%6qh5PuH8rr==rp4NAFZ#B>crrCOJ!::S0erT1@
-rr==@^[.osIfBDuq=-)Nre`+uMC>3V.&)SIU5C@nMC>3V.&)SIU5CA&!<&e0jHQkH
-PokN@qS,34<t.TGNVd#V6c>T.Iq#&(e%gDBdVeaX!#Kn3i-4Q+iD0jFH@/LOrj1T+
-&GUIhg.mX(=[7P0CV<)4]=,)UM%m=\8r0.'"Z?nd.M(konOD6!m7Zq5_`-Znm@GEi
-O2WaSpcl_Y28C&u:=oCsia$V!f<d,1e\R.3:"=@_>J#/[XH<u!i]\^gh-]YEIuSm^
-f)?P7Abbrq(]7M4D;oL#htTc,*rJb-NUSUA^'F05p,9*_iXI",Do-rQf!Scg<W:.m
-[&kucdsg1_EV:D[9sE-LI&l!`H)!P@Ibt))n4mnT^'N+M+*^l\deHV<kWU*fdea4J
-!6!dL-81@-34St<eaN1CYO0)]^DVJOq"*K8M7fn69&^jMrXqF2C;8ET7!9UndJh%V
-kuqD_BAS-UcbEk+qE,kQYQ"S5\&-JjC9-sHp2/3,i.E,W=,Hnnpq,I&`SZ4b0!"J/
-626T$c[jZ=2uU;b@I^,1*s8nM!/rsmVPirfj5?heIPq%QpkReRKNe,gCR[[-NBC51
-lTjskM>TlAl5K)QWp:H^=,?PH/P+6qchJZ5KmYQ6:PYMUrLuC^iD5+j5L=j:pfGC@
-!'De3!!OeGcf)(\TmSTl6g=S0ds`lnF2OWV5)9#2fR*ej:4oajnJfIag.%.]^P=up
-e,0TWC3KS&n--R\r'd@D>,I_]Qbq)'a8QC;n5J;$_iKFW%)6Oqfrr:X%DEI"&&KCs
-^)qT<rYd#sHI)L6rWhp/LU?LWpeO<WfC9*+F^9>orlWT0Ws]I*/T4V<[<qAKrMri2
-]Y'PGM)i<^rmIDC5AKZ@48(b`IqO7eh@B>+rr<Bi0mlCaZ1/o4pgrH%(WUhdJc$(O
-Z>]+\nA='`nQ)pRHehUpcq^FtIu4.6d.E5j:?pR%<4LGRCFEeTf&>Zf$LgR`S4A1G
-m#1dSrrCR/p4'9N.&)SIU5C@nMC>3V.&)SLj1cQ5!6N0(fD`k+_2nOi5A1D772/cR
-rrDUEBj^Q;fDbjC]>Jd_\*_07!%(_C@"6k4IaB25WVft-jN$;1q&DLirr?JsrrE!G
-HN*1/!8uM5q'Nk`+8q+IZi:%)TDnn)])K'dAmb?[/cPf^8)s@CYKr&Jn+9IG'N%:5
-;+20r72/Tf'N%:5;+20r72/TfGR*Unrr==@J*a-3!WN/Mq=)hBC+C5g,[!l.+H:<X
-KFu$'G`,P;#I,#m%80Pp!oMk5*<<[@!V?Fe;Z?`2l<j/q^Ae2K]8uqO8+rONrr>>(
-n,*R'rrD)DUK,g[aOG.E*=0<f#P/R,^U?"<q?gt%p`";S!68dPf[[b#.B*7Hi,-g?
-!$.j3@oiU0TVeLa!.hUDr-"csrr-GAV7jL,2TFtA\XCjL5oYrVWPJRnK?+;*A9]?u
-:*[S^p-ns:rrD>(q`i]bPYjj`;+20r72/Tf'N%:6n_]?+!9E-%C]=BF?f9!(V]W8L
->b[*+(4Z,s['0?.li-t]?/`Bjg\0Y,!0\o2YWqL+5A1T+<;nJQnmq::r/NrfrrB:S
-U&P+h%q"-Or#6CN!$p1iKDtqVDt\\\!7UrJm2'-\O6k'i!$nDUm&9i2rrCUFnLhNS
-MC>3V.&)SIU5C@nMC>3V.&)SIU5C@nMC>Y.rMI?jPct%N++QTP^HNQ;%7O]MH:Zo<
-m8;9b*I#GAb,WV/'Sg#EAdKR_P]IPD8elkd*0I`M>tNkHMC>3V/!7B3`kEGfM;aL;
-GX"L`[u%l*r"nD>#\lCrM0rU0GWTjA-(=#7NG?p>ZG4ic&`\q[I@'pEH`LqO8aPfM
-p@otljnu)%4jX$YYDlo]8A5miiUcSPrr>FZ+7QkU21O!tpg*n"LX3r3r=@D-_WppH
-rr>HFiHP8C58Jb@5>hF\$`i;hr=Uc;htVTs=oSKKrC?c<YDlo]8A5miiUcSPrr>FZ
-+7QkU21O!tpg*n"LX3r3r=@D-_WppHrr>HFiHP8C58Jb@5>hF\$`i;hr=Uc;htVTs
-=oSKKrC?c<YDlo]8A5miiUcSPrr>FZ+7QkU21O!tpg*n"LX3r3r=@D-_WppHrr>HF
-iHP8C58Jb@5>hF\$`i;hr=Uc;htVTs=oSKKrC?c<YDlo]8A5miiUcSPrr>FZ+7QkU
-21O!tpg*n"LX3r3r=@D-_WppHrr>HFiHP8C58Jb@5>hF\$`i;hr=Uc;htVTs=oSKK
-rC?c<YDlo]8A5miiUcSPrr>FZ+7QkU21O!tpg*n"LX3r3r=@D-_WppHrr>HFiHP8C
-58Jb@5>hF\$`i;hr=Uc;htVTs=oSKKrC?c<YDlo]8A5miiUcSPrr>FZE7WK_f>N.N
-4AY#+(hc)KnB^g+K)>l4%6I/Nf8I%T)".D(KMPkJO0)^Q2n/X]JijS;?aYC#EGKE.
-Ba('q5/BA0go$V]6a!/@.gfu84sn`f%Yds0[CI>4b%+')e3#q"4!o/$8C5SZ`!(=A
-5bsWP5'd+:^Z<PPC_-D#ce8L$!*)7AC]'S_F8l4bO,:X<25l#h6eD',rr<8BJ&sSH
-T`5#Y>Q(2o!;-9kqaK-/Ynt;`$J"STS$%-6d3-0R22u@!5Ju@s4tubQ7nlcdeSd=i
-B'.E-d(FM!ko,'FL9IO_C,Z^gp/]c,lKWXq,r.>Prr<<.O8TPQ)F*a7^,pi9`hWME
-$Qo3bIPcQ66%!kU!9]>3r#cb>oJlb^rrBuhq!J(]cPhl>5V.EKEVRr]!/UmLg]%8F
-2';=<=T8BJj7/oE!"o\"\,QFjC-UYWZ2Xfta5]\h,T"L>rclqB_?"0H!(2geO8MO%
-No0d)W;cjN!lt:q+,qB;OC'$Cq;Y?P!!iahr=2%15Ofl14+HkAU](f4+8Qt+1k4LN
-I!5MikD`"0+;R363;dIi!5sKamJd14)NXYY/:Zl'psK*AM$<G(rrAWJ+7Oe_rrCF+
-nY?*a&e!a/rr>/r5N)UIrrAb5j%'(o(WUInGgq5[!Fu-06]]6Jr(&K$hu*#Crr@]R
-a8Ui9N?@qW?QHoWj&,gV#R-:f%R1jrnK>P-J+L[TrX]GZqAar@J)WbAG5hR*NCWmh
-(-hFNr+Q*1`.IdOrrC@`O8(skJ*:nIdJj3'"nC@I!1l%in:4X@!79crU]1<,$fe_r
-!'G!\i;g._!27Hn8,abMa)Cs%e:5=9A,cNrO2d7Y82$"\r:-`c!/(EoreDST+8Cq)
-*P_F1;?$V%"crTl58lcV+MKpeo>[R)&.9TV*.B_oi^%s8rrD5A8,OJF5P-r5B`A(N
-K)"a5!7)REpcpB[k]-CFrr@lZn_='DSi%VZJ6;gOd,XYkrr<Z>j1#$g4DI+>!3uP(
-TuZ1`rZi<#DuP"2J&24rrr>EI`fL$g094rfnYlHfKEB3nLEDKtplJi'^\Qnerr<<.
-O8TPQ)F*a7^,pi9`hWME$Qo3bIPcQ66%!kU!9]>3r#cb>oJlb^rrBuhq!J(]cPhl>
-5V.EKEVRr]!/UmLg]%8F2+'%7>mfi_cD@[k:=e@.eMM\h%6qcq)EokMO%4Uo5h0]D
-bo5a97+Zg/W+d0*p3s3Cf]kBal5!GZip,)$=sbu+H3G%IEM;XK(K0+q>sWUPON2>u
-Nhr^hX`>NoYa^cQh:e^DOX%5I/B[N7HX[NIU+44^JRe][4nZ#V.6L'!!6[u!YUk:e
-^:!t@KdV\kq.W@m"crTUf"^^MnJD3*/L^V6Z2XfqqUb]\Sg+17jeX'O(-hEJ>5nT>
-PJgi+[%mL"a8UGO?hdNDMuNdCP^d(CrrCAnC]=AA:D&*IdZ<`&+8PB-J)NuY0E,-P
-rIJJY!'U"Yr$a`srrC575Hl\gkJ"A(!/2eV^\MS6p'$NTpX[+KV"#9$!%fVu^p3n>
-T).(<'V6NK!9L%!fG6^Chcg$[_NVoFr3W6r!lt:elX0EbG`2S%QBZl,=T8BII;Ai_
-$;V7`o$WTc$Qo35Xaf;$i\1:7;>l&Urr>4TYP]h37K3A28jBO2J*4PRrr@a#Lqib"
-8+m+Ir:edWn>,Rjrr=W!rkPf=!1s&=rY1qJrrD/W+4q>noA<aO!5ar<?i7:+qZ=h;
-Hg>&6;L"-"!1&k!?s*F/c[BU/!")L6J+D$KljFp2n#_)u8`DE&>#G6LA,cNlorn9B
-4@T8Mb=Y"'/:Zis[Jp5\-]#P5Bh.k#O8Sb'^[S&h(]OIe./q#errAYefDZJU,6%Z)
-V'">*5P*c9rrBp"`*`GLU\b,5rd3s<pel?prrA@LIpcCY!7-(/rr<C%&V'B"O6d5r
-q<tG8iCW#^r`W1tJRe][4nZ#V.6L'!!6[u!YUk:e^:!t@KdV\kq.W@m"crTUf"^^M
-nJD3*/Lo;2QY!'P_qN'PQL3^ZRu<2oS(jpd;2CnYh;1kGEq.$agC-e*N\/Od75?lA
-Rm1dDq(f/."9-Pdp43/CePG2Yrr=BA*<-#[j5P"S%;I!];"ae9J&/BsnkFUI5Pl5r
-!,)<3rBL;/Fo-UWPP3o'Qbm)FGalQN?O],;nJ:0$1;dbb?"ZOpGJJ]`?5W1OXY5:6
-T8A`p(Hs2ETme_D(XR<LIn]WMTjR^fnK*hNh+,E8Se:HB=a6^\Z06L6rLLm`?[MeQ
-"Wt,#Ic(+!q_EOsYl;fEfDa:sDs[l2!!MSprltHCKR`t:&,,bPr;QcOE^-i/!+LGp
-V"h"hYP+#1q`"KhQc'uSGsCeQG`V_Y^&J(aO4n<_DuS/_R6E'%Iq=+Frr?e^\+YLT
-!.o>srr?[2!5^u#!"0&/HgUf^mC==krrB;giDP&'rn%$;Qi3ER!"-p/&)04=pd7/6
-rL.'m!5V1m1uGeB!,2AUT+n@kZG3gI!4>#Fqa,eK3j!n<J)MLL!/6((^%VI+5PEln
-m!mZ[n>ST$rr?j5UW`Y]rr@aanH\HQ:])B-,Q>q@J)I*qRW$s\!475f:Pr0pfjEJ5
-!8=&^rLlI6SQ<MY^[R<a!5cSOhYVepqeept5O;2@<1anT[JnS8rr?[2!5c&:KD*V=
-rXdBfrr?Yt^[P+t9fMJ>!89ZD-cISHm'#f+m8(1id%Bf&X'b5Npdb>aiF)ZcDgfCH
-rO4$K+8.)[.Skr:gA_.do)A]rJ)OOX62P;Yrr<=;M#RI]9AfLmrMH(XrrDF.fotE\
-L\=gC^\4S[IqVXQ-WRADDu:j[!:[4B\%^b_rnES6O8BUi'dpt-m=2KgJ(_U+XM,hU
-ZcW4IKJUPrfqn08'RnM*qg\=#m)eci_ttt]?i*dh^U,Bd'<9[]2uXEh!;KY\gYZr@
-rr?oWrl=torr<Ciiii'jg-!.:htU5Z&:W<nrrBnRi]leXp\kLaBr:jDqa^?jpn_Et
-Q2RobWV56''E/<gC]0b&!!rT)r%&rWn$i,m!4Ls<A,aFH!/4#7=8Q@l*aeVZr$sFV
-5A]n?i=,5up1\mR!!OIOdsg3QU\cfo;R$/Crn%/!qetj.rr<2e[JnGN!/,k$((^-5
-g\h'OgN#N`rr?MX_PHt-rNGpU0Dd^-'pli\[Wt+,L3SdV1qinhJreW"^Mj,!rL#hu
-=FXn3C]=BLICJp'rr@Xn>5nS7rrBo#rr<E3qg7`0J*jcgf`(rV5N,Lf<W:VI8!j1D
-rr<DLiXad+TD1c98,\l_rrBl*m53_0rr?a3bb#TN5I/&3rrBGjg\X<e_)e]JZ[^pU
-rr@b*rOqq)!'g24O6hAKTCAgD.fTKarM.R8c2RctAap#mSko8-Sg46Z07VoTp6opS
-rrBEUAl":b+5(#TrrCcFD>g.mi13o`ft[$;rrBpPrndO%TDNLrp-7n>pf*k#J$o:'
-jo5<mrrBpApk/:d-iO\'&cViCQbW#eqb9$:rrCb;ZR<^B&+$LeJ*g%?rm7;,:9.ag
-htT_A!9%>c!,m;#ci(<tq]GMZr$kL"^Y8\fB_)0'Z[^q:HpRXBPQ(UgB8HQfZV03N
-./g$4pAY-[+5)k;Q&#'7p:p=!gOEm4pa9(Fp2BjRrrDPmJ%*/LkPj4urK$ghrY6g"
-?gW?MH%4M^n>s>HrNjWG!/*/HJ(^[er"OV/:&BG6O6k!Y9#LNVqd95!mD$"Ur"H*^
-q`"KdrrDgr5MP(6oD\f-aSs6YM>mP_PN&e>^Y1fbm,.S=?P%\>jSo4s)<*mIdeE_J
-5A@"n^\^OpAGE!0rK[>brMfMJg(XGleSG,Qrr<?)!;nAimI.O[rrBLgIq/Jrrr@aE
-nQ5Tpm2fX.Du;+=Ld,_HJ)Lh++80Dqrr<3E[*sK]rM06FHr@3Jb5U#leGF1O$3'u.
-lF$W9rr@_%rY?%<pY5WG!8DNYZ2Xf5J&8#VX8T6qO"^AhrY:d<+1?GZn:l1Kq_Z"d
-!.p9cBtnTcdJ]Is.9M(2Ir#&aC43SbK`;%(F^"eFB)_kJ5Q:]k#Q&l8rdX=G+5$Sn
-Ys72FHr^0tqa["OS,WHqbMj&e4J2C94@f@>%Ia3/Kf%\rrr?a3bPqPU/3gGT[Jp67
-525s(J&+3`J$XX`+9)=pKDiLWrr>:We;rsGfUqZ44t?R4C]1$OrltHCKk9cZm@I,O
-+eBqXbqFS)Ua`2>^\^Op?hg$trK[>brMfMJg,&^7gM?bWrr<?)!;nAimI.O[rrBL'
-Iq/Jrrr@aEnQ5Tpm2fX.Du;+=Ld,_HJ)Lh++80Dqrr<3G9fMJ>!89ZCrrC!\&+$Le
-J*g%?rm@A-:>9.BhtT_A!9%>c!,m;#ci(6rq]GMZr$kL"^Y8\fB_)0'Z[^q:HpRXB
-PQ(UgB8HQfZV03N.10e(DuS/_Qi8=6Iq=+Frr?e^\+Yd\!.oCJrr?[2!5^u#!"0&/
-HgUf^mAV2[rrB;giDP&'rn%$;Qi3ER!"-p/&)04=pd7/6rL.'m!5V3):&BG6O6jXO
-1;iu>qd95!mD$#@r"HNjq`"KdrrDgr5MP(6oD\f-8H-[.M>mP_PN&e>^Y1fbm,.S=
-?P%\>jSo4s)<*mIdeE_J6CMiIrrBEUAcDaeQ64degA_0,T5FP%5N&*@^Y-BkO8f3s
-_>`<gJ"QUQ8+o16:\[n]'n<XjdH1B.B)_kJZM9(GcR8]'cOp0WAs^:%;A@T/hu0>I
-0DnMJrlY5lrm^g`m2>p("RWVrc2RcsJ,U2op@m>>rrCeO5I(4g@Xl7jpoF@sp5^m(
-2uXPY`#lF55OaDPO8CcIrr@Y4VOR;Z!::l]J)Y$pp/gt&p8?YpB[?H$D6NYOr$24A
-n?@DO^>J,Qg6)>pq\/rD-cKH[J$aKNft[$X^**B\ao;?o1W4drV=4<rKf%\rrr?a3
-bPqPU/3gGT[Jp67525s(J&+3`J$XX`+9)=pKDiLWrr>:We;rsGfUqZ44t?R4C]1$O
-rltHCKk9cZm@I,O+eBqXbqFS)Ua`2>^\^Op?hg$trK[>brMfMJg,&^7gM?bWrr<?)
-!;nAimI.O[rrBL'Iq/Jrrr@aEnQ5Tpm2fX.Du;+=Ld,_HJ)Lh++80Dqrr<3G9fMJ>
-!89ZCrrC!\&+$LeJ*g%?rm@A-:>9.BhtT_A!9%>c!,m;#ci(6rq]GMZr$kL"^Y8\f
-B_)0'Z[^q:HpRXBPQ(UgB8HQfZV03N.10e(DuS/_Qi8=6Iq=+Frr?e^\+Yd\!.oCJ
-rr?[2!5^u#!"0&/HgUf^mAV2[rrB;giDP&'rn%$;Qi3ER!"-p/&)04=pd7/6rL.'m
-!5V3):&BG6O6jXO1;iu>qd95!mD$#@r"HNjq`"KdrrDgr5MP(6oD\f-8H-[.M>mP_
-PN&e>^Y1fbm,.S=?P%\>jSo4s)<*mIdeE_J6CMiIrrBEUAcDaeQ64degA_0,T5FP%
-5N&*@^Y-BkO8f3s_>`<gJ"QUQ8+o16:\[n]'n<XjdH1B.B)_kJZM9(GcR8]'cOp0W
-As^:%;A@T/hu0>I0DnMJrlY5lrm^g`m2>p("RWVrc2RcsJ,U2op@m>>rrCeO5I(4g
-@Xl7jpoF@sp5^m(2uXPY`#lF55OaDPO8CcIrr@Y4VOR;Z!::l]J)Y$pp/gt&p8?Yp
-B[?H$D6NYOr$24An?@DO^>J,Qg6)>pq\/rD-cKH[J$aKNft[$X^**B\ao;?o1W4dr
-V=4<rKf%\rrr?a3bPqPU/3gGT[Jp67525s(J&+3`J$XX`+9)=pKDiLWrr>:We;rsG
-fUqZ44t?R4C]1$OrltHCKk9cZm@I,O+eBqXbqFS)Ua`2>^\^Op?hg$trK[>brMfMJ
-g,&^7gM?bWrr<?)!;nAimI.O[rrBL'Iq/Jrrr@aEnQ5Tpm2fX.Du;+=Ld,_HJ)Lh+
-+80WRHmJ["]IiY4ibk%NT3M)!j1g:s/+EW0$sjuN'_oH$+--!l='"gmkDH?`h[WG\
-HiWrbnWqqHrZek]pj_f\4"Vi#;Ku5jEc6[3!#+_+&+*(]iTH-#[%Fe*U5C@nMC>3V
-.&)SIU5C@nMC>3V.&)SIU5C@n^0LWH^Z<PPC_-D#ce8L$!*)7AC]'S_EW6"`O,:X<
-21PW+V%6qh2uFU0rr==rp4NAFZ#B>crrCOJ!::S0Y+N!>m19+/VtSQ$/H^Ef`;VV]
-W;cj.M2eG,QgEi6!!L2JAc9+<!"/U#D*.V_ktQ,=U%)@'K3C<<]PiS_'2F.n,kst(
-2uF?tp@FdI+n.G+4[V^6C]=ABF5g9g7Jg<e#Q9V\%/<IonYc:8DZ`N"5NBJ_W^3KI
-h\5u4gA"V+0#-?5!9b=+LAXWBl5HRS4rAZ<nI=?[%Ypb4GZcT*C]=AGkWB[#0DI"E
-_U$l<8+96fr"T/2`a8arA02lj<W<&QdB3<pd68TK:&*-57<fck4pLcoi,9"ue&PXF
-rr<Y=0A1.!BD*.&A,cO^LhQc0pgJC*99!<!qRtL6r&=,W;t9%3HrusHd_"uCH?\^G
-rr<GIrYb&$(Qn^tK_PH^fDID5pAY-j.pn4ln>!bWVuHbU&H;``hu4M2rYfkW&23fj
-chLjSf\bn"n>H9diGAMo_SZ<QKYRL<p\Z8Nn=KX[`ALm2m2c3,"_dk)rr?^1+8195
-/mlZ6n@a8\r!!&"^,Pfti<R?JKDtonrr?Zu+81RVZ6+Ydr+kgY_]Jro1AkPT2ktaX
-pp]rY4*qA4X_Zk?V=@LNrWg3-ic^Zapk-BYA`fr$56sL3Z(J?=NrK)l&(sJ5O2NH\
-/po;AYO,tqBQ*D7p4'LKSUYC(Lu0%3;r].u/)gL.NZSl"ILQ-<nB\m04t6KXT*YE6
-pg[Wi[85LhiFg%k;rBj;!3j%e``AEe`J0c:p#8dB.9GkKiEt6Ohu3s%WVh(hDSK\>
-XTQGS,`C\aLAX9rD]*9TVg-D)\j+)L,2V@s?4cVW\a]mM?aKN[Y$$!"`Ej:kn<=tB
-n0a)9ehg/Akl)XQ4?]n&l'rNCrr<4Irr@Y!po8f^`SjVH>=%dj\&84Gfq7;;m>^*g
-CVmdppmpDO$b,KKq`F^`n]/F`MglMT2r`X(_,pUQn\0XKHrB`ZiuJ4lZLCnuiZ3Bd
-H?P]nir9"6qF?Ej(Th@W+k694rr@Z/J&+%8;8'>$ZnB*'Q(dD+ZT!cSBB/<]g#Mds
-ZhQcS^V^!N[Prp<)riU)X2LVJ^,Fep)Md8V_+b0oT8.fBiHsB6=ST5_Ig0W`4SP3=
-?]$Hm4^12A%??_>J+-C/gWja4-R\7Bn[nM=?\Z>b\PL&Vpf=p"D>sSBVu/'kpdkDb
-iF2Xjn.3C>q&DWX'_0NC5P@>>-Qh+#ngeIIg)o!tfmi3mD>qqin6_%0n61=p9AlG\
-I;_pVc/To@<.>1d1]&G3^U8!:28>"*$9rA,!!.Pr4s0:nZhm_drrB?*O#FKE0R0Yl
-4jn7*T)i]a&p8%E:"+J]J+5_[ie@'VV5NX&^B18,7sT%CG#%o*rX1=T!GNYFOak5H
-nV>0A!<3%P'?@fqpi#\<rYC:U_>@;]/H5^("6(DZ5Oa7(!5c+mIqbPM=MG!O1&h4^
-a5AV-^[SNk1&h4\fAa"$"9/?.gYmY#/Y4Hl!/*GR)W1H8*^0N'KPS:$!/IJ$`..9h
-J)R!6iHZO?:Oh>OJ&<ddDuTgS[J7H8!"(ge)Lq_u&,8m!!9'G4iMSp!!ri7TD#XKh
-p&0mLL&V,[J,U50r%'Mr9E,"Ohg`L)rr<Aor)6V/qb7"i_+?k%YLs<&$/gl)IhT6g
-1WGRT,k75Am;'Q\%fQt9DYWb]Ns0n:pj]6pkoMGOfC:LZp^?TWia/bV\)A[!X'Z;j
-IO';1[.(h_[2hb5f;u?]B):].?6P5"i4NS"!!RWI!.oXo'>jbL[(hUnhqD:#\aWtm
-K:r4g?7PaKir8ucpc%2VO*iV>?OQkc3dupdrlq#[nD:q<?Nk\88bf?Zr)D*l8"o3o
-5-aU?n&JU\RA]=NpV%l^dB/>L]FXBcrr<41pc%,,KcdcYrLS/FJ)]A+0A-Th+71qb
-C0,_*m.^BJGk^oDn?9lnJ02,k^%&]*iCCk:g-<Cp#.+(.U$LDN=m2;UNk>a>n^#*:
-1=J,J8Nn-;-B7O6o$^$6&)]DE(=VtMeph1Trr?_>g,J%5KA[gir!31g^L47(hmVs>
-iD5/W)t1Emn7T^)[thiH!VkR2AVZ#AXSa[19j>TJ#E(HX)8gBfgA!=*plVNM7o#6(
-0-9DIIEfIeg%V\+TC>hkfo*aEIad"XJc&fWr'KpDm&-M(C2]!D,La@7rm^eRm*4H!
-+8cQB5C;pia$1(5/,n+l$3(!<IuHSt49_p5=2V7G>'T@!ddK;:nL)3-p$-cGbMf@U
-IOWC9r&`F'/LUN*8c&hHpg<"RVst_dY(P^#>JqThrr?V[MZ3Yi26R+,+81HaOmjIN
-5+h^\C"c;%_"[WWqa3<XNsPM6i$O$F%d-m#]C8jtqbgPqcTWc,4<&dDGi-JH"n5!F
-Y1l;cHf;a7/!oTKiie:W*s8mrNEZ:aN@fWoNtm,`EpJ0"p_EZnGW4RXIb"E,K35Y6
-rr?\iJ(b^Xrr<D55Cb\b(@NKpmoRB?$FKSr5.0F]kL&[E&SpAFT+L2uC45Qj&,7ST
-lt>eqp5e\jm#U[lj48k@5M@XIL4Sj?`1IN')=&=cn[%L%3Rb\rr+`S:T0=<#pfCV&
-nC?]Up!%tkpn`63A^?'PrGmB%G^mU,=,B*epm4LurY]rZ`832rIRs8*rr<50rK?ek
-f\R.m(\VnEa.W5)`kNQZAoHGUj#?<nV>.7Q?cMsb$iFW,:[B1mZcAXrpnqQ[>:\#-
-GV<+eQ@\!X>JZM-lP@2kf)?WR4tb<Z\;S.+VP/'NB6Ff;TC?&\fe2=C5O@dsO4m[q
-*eWBXN#jbQRD33\N8M!`GT5UK`r?#Mr!31jHrKoTpc$)/LVp_7NLq&p*t*>n!9%k_
-ae3n-`>[OP_,e=X8&_)-l7huklU(,2Z)UUYh,dDB/u?2[!!Ni1^OA+jc_%U@r"FGN
-489V-i#N3EJ%)nJIQltaLW3,GIg8.hIaS!V_`]+"Do8+R`&='3*s+V7Gk^/EMY5<j
-9mg+(T*rQr%uL.T`D7!=)rR'6Zk!rIj2\`BmtE":4A4VHK>=,K>]9Ba+2nbFf:Nel
-*.HI"%uu#lB<Q\)n9Set(&2qAQX'<LWqcSoj6r'.-@@]G4n-5(Ig3:[!/GXn?h%LB
-^E.WXi:k/Q7n<>IiL^3eh\&l')BH<+MuNbb=o9i@#DTm&XDc;^!!S\eJA:*pg$-6g
-I!t"H(&VS3n&MVcIL#XPi'5nIp9+1En]1VEJ*arKNA&?@LE88H$fGrT?6T*knA!#Y
-$oHiQkaj!g(PD]7GRqXi+o_Oq6WCD^StDoepek,CCVBKbrr<3trJ:IRB\seW./8/Y
-KB&*a*l%72^fpKNO+A4(X74a#pOW5Qn\`9$%amI"Y'`L`^((!8nb7RH0C[TQQ]HS2
-fm'7:+,g.!$G6])c%"`._AuuSnZR`I-?qblRf<B*Y93#C)XfQ0g["QRd=5hfrrC_I
-f>W2%n[HPG&,uXHZ2XfWn%sP[rW<"Ipt;G?,Q@atbB9dMnB_(MYJ`)Hrr<ITEU_T<
-0Dm,>>"/GkM/@b$F*PI8^LQaqE;VuO5/H0(b<HPCHr]^?rX3H;-/8>&rM"[:q_`b2
-d!U!+K>G=/2smsAS+^i?*;h>^hr4$SrrBEMMLT+H#5Ffepk`GK:ZE5(iGS^D/cDR=
-%gDa'7"k?dfCjF`Zf8)VD[+q]hC-eE83Au1C*"\M:P,5.>>Np)j5</gmGa2\=5t?S
-i*VEa1B!WU@Xj?oZu^I2iEsV)!"f&5rLA76qe,[__]"<J]+9mn(pk@mGlId&DsYT=
-GgjVMgrI63^U-MMT*jj;pbqG)nOBd`:Z:,2:[p'6l[Kkgi2n*-T>Q]qIb7_o$m3O)
-++/M6)u'[3K%@XYl$`a05OnaAi,tC*&)$.(G-1;\`Ld8qBDZ'2J)K4Brr?ZWLE8Ue
-dB%Hi!"Sd^8_3fbH/]nOGe[Cfn7JNUMiSpd4q>-o5D6f@>!IXh&p,5j-iX1(4Afsg
-HiqfHD'+F\(]GiXU=8gk5I?3^bt$aR56LocAo@d#d_?E5IMV^6a+(C<L[]rVLVcgi
-pj:"kplG-(nOLR%J=d)>IgbKWhC84mi\-2c[@Y"g]a)9$paugL'5GkP[uS0RlbBeZ
-^YmEAr&sgHn>G=?ZR<[eg#Mdsphf#MF5TR.rr=/*h[;UbHu&LknGC8`#.utd#NHoC
-:D3Rkf!IXL\&=>\Sepq+K=!d/?I2K(opm;]>gfO_qVV!lrO'??rm\N7`>o'=pPeeB
-Y8Vd$fDI_h^PgtX^*A"Ypoj0?is3J-8&ejOZ14`DmQ>.OF5s0MIN3`5cnl7PpgX1Z
-Ig#PI;"0,Z(\*.o>23F&ehp*m%r9O+^J',m9E+uTJ'[:b1ONg5Xun`A5Brp>hr;D$
-^+OYWi<@e`CT6TK[.^!J4ZgYj!W3J1c`$,cHf=u)MYB:?nJ@#\.Jt45Ho9lB(K's[
-j0+NY'ttH.2tg&BHf3O$PK,np#D]r\F_TgVrU7V<&3Mu5Y7(,D`r686:4qR["o-8,
-dJR#'%i>"B=O[18iI;Se?c5!R^9=2SPJ__GO`brFl^A<oUu#9iH9SU2?/95kStC.D
-HY%1[[.-cGP2EZR\T)in!!OnOMtDiZ?<A?%ZqX"/"0&r<gIjKl[Jp416+3BP1h6%X
-;NA`b<Z>^_eJI1WK3qV_#d#2hrr<\`7?>@$$,8lAU5C@nMC>3V.&)SIU5C@nMC>3V
-.&)SIU5C@n^0LWH^Z<PPC_-D#ce8L$!*)7AC]'RtDuTe^LP^NI1OoE)V%6qh5PuH8
-rr==rp4NAFZ#B>crrCOJ!::S0UL++P,kr&3Du:<=p=\%]-$Zc5*WaV?HpOpifm'./
-qQ?%@SM@;-rKr(B?P$Q.QC]>PoH^`&=7H4iKR?)F)pL*"FeMBJV"dS`ethf=Mep$\
-J$+"ueUQMMrY,6urr?mH"FLZ_Zi.9q#CINdOo$R+f"VCg!,Silr[cX58`4NC4p\Ul
-TDL]br]QW^?PWP^7I_V]cFr4u!T*$$:W8k`?IM"onMfF1Lif1p_RJ7OnNaGM:PjH`
-WHg.R4rnlhic"4(q[!2QrrBEMr"Nr?1tR+hqZL]l[QVPM(\gMik25+kL-0b?O4lPN
-P^a#&dIi.P^Y9RbQEB*dHf9FSn>G9$MRAKWV>d`tpm4e([9j>,KmXn^i%GZ:T2kB!
-L7b]:m!\@Np9+28qa>[Mp5K"OJmJ0G9DGF^C&"Isdag9?g5GZ.phTDdp9+0dif=[e
-;#%BV:P-:jIatkK[3rjrDhcsVL&>ZSUZ/J84qQuq?NbMr8)WgCCZ:mX?69aO?O1n;
-;Ug.fd/O+(N'FT@RIMN<HJcX_paI$GiNN#4^cE#('UQY-47URV_uB^k^)6gZIqTo4
-Ic"H3rLlCrprcn?X?UNLDt\_OI[0Gein(uj-X?G!08$t_lT_`<O/Kko"nD9"X5L$_
-A$)V`mli`2!.oUr%IsGu_QW_^YCsVErnfs0:QLCi1]IH,@d"jnpf6gdcf58siSe\q
-Ia&rHIK\rnZi6H`931QVm1]@WGc18X^"%L9nS>u;YO)8hJ+4aRpn?ZmN?/)hGDGk[
-!ViN"T7[b]pg.fM7f$?_U]$[sAoHBZrX!*)"9&V3GPb]q_V_\unON:KgO*H,2Z,/r
-2o7e2*X;WEKHKoF]D2&urrBn^q_?4i7I,TD5A`Ul4Dgqiccu7.EV?"@BcdsO+P_C/
-ll*?eFR1+(ch:Z>)uEG/G5.X*6@:Qg!.p%+c6!-NC%6]P$/b9frX#:g[nQR`UNg#'
-B8.A`8&R%tpp\9>O,H1Dfm&#?L\M%Qr'0tai9aU`T,2A;*I#K6f>Oit?0V>-]8D(=
-kk@7BnNGa6nRep'!!J5YR?-^RqfdM7(OtpRDh6Iap;6S6rr<22pa(:I.ut'_)F+!s
-J+2c"LY<i$2(oVKG^<`N-85-dJ)P8E!5aN][]=nPc)u:erY8f6-]2_X2/aK7!5]n[
-?6@Po!8E"s1]IH,;#]$1!'b6@K_f&6^LKL]X5]K54.tjsrr<WqBn(gt5O@X.Hs`Ma
-qB*[lIu`,!a2Cac>GdD>08MXun&=aGQQ@RM[GfAO`;3f6iu!.Gj&#_)n@shP8+D(`
-r[n)]5N&(S%6ncl')Yu/M=JL_$D72EGXLId`:)>?_Z'V@-]B^m*IK<`Zk!:Q_r5h,
-m2,/`(W=Q[_EKUNZ2A+8C&\0Gd(Tg2Mr?mVHl8r/o)A^3ebh#ZT8?5#]fsb0^A)WB
-pRek^r"J,aB)STViU<CSrr@Y4Hk,psrr<Qsrr@chqfgaF4:U9\ph0'j@';Nd9C6&(
-a$1&`_T2ZVK_PH\09*^'kC:@[rr@b&rr<>VMLNtQ!!u0n,5Sd6^$sME')dm*"THs/
-)8BjG%Xuftn4UM;l$jEI!,Xq7IbIuFVu'>?b?k^-1B,h]$2dZ[/SZ@CHqEg/_9^iD
-_tKo$CMiRq61DXK4qrBEnRo]Z6L3Qi\Z#EHeua<uWGBE2*in61&aEP\H2DH-aM5"S
-m6CJWpf$n65IAK/'B<3bVhG'MArV02?h%L?^Y<P^YJX`%-f@Sc^5;AQ`?,ie:P_1K
-n3?h-(VhV(iVrnsY6SgV*;J:Ic$REUQ\rF]Vqq,/ho-L&Vhb1#F5^IAl8lu1+1*^!
-'-$XWq![`;=8ek@8cJbo'`F91*.H=C#!<.f&9p/-"S'OM:PQRfn1V[$pa:Rh0kZ;b
-mi;6qZg\L@3.GXFHjB1K^jd#FH/RS<R_OWj$1Z.8=8r7-"2jt1Zf'"K&GX^DpiS<H
-hH0DNphSep#_0Z`^'FR!rr@Y8rlSOfrL:R[UOGB)[(\0j:[luS56:!)0_jPp^Z'b1
-Aai(*rr<N+IrjRuN&i'JA+8BkF*J52*^'4CidVs4SeCQ(^_sdO^(Kj9NIDo6?9W4=
-8^opMkhd/':&b3F62V2A4p:l3T<mF*J)IBBZ\O*Z(].,0bocFM^O\VVcDU17iLbh:
-IH#bO8cJeKR!oN/#k2bn^(4Q6^U9EFh(.GbKB"O6i-qA>nI*-=5LFp:l5E-ci9uKM
-l!?TY[^)LR_]H5UBDr3[q]br*rMfesCTlHP&)5;$;Z351rrCbKi&C&6n4Ub^-g]lg
-lG!aEHuK#b%6<qD`P2hVnMfiBVYIdsd.i[kgZ(Nr.N:SUpugX\M6pWDrr<GAAcDc*
->2Q\GJi/UKT+H-YFmfOl=BY-B,l[jr7K1NZr%Ro^n/;i4.Q>01)rSd(2t.dc$*!De
-p;aMi]Ii&Whhg(Mr&XGed!.KCnMfh/j0\cZFFOXF!WN.RMr@H_]%gUBd=*Nl0)_Z^
-i=,5eKfjdb>O'q.S"s?bHUIOsO8(*Cm*08<YI4B1_+6`p>5aBY$cRVq!!TdDqaH9k
-U&-"]rrD",rmUh6m_$l+C\E8En+]2]D>*u0N7.&NTC@V\VsPQ5A,cO^IocFohDZJh
-rL*%;i2:d+n58MdgJd$QWNuJTYQ"T39AbAG*[L535@b[>m02LANnU,DbHH_BHq7VN
-rr?\]_@>OD$X`Za?N[4Z5N*+B::YB(\GlQf+4[`V:WI`Fi/iEjFKY[l$2>4Ln5\B!
-_TUjZm!\AerX,FiCZ%[AWI-MkZ[?-/HnYL""WdAVnb9h*0#.2;nMl!K<aH4)p:]rb
-k3Ks3e2L\DpbD8R:[p7`$[cril?ZflU_im2K_s(%J&*R`A+,)B0td%jQhsp8_(P^F
-lFNn[dJFs^$2B9oqgEq757N*Wh*8gV-iJl#"RA:Yh8bSj#t8e0>l5GLpa`$88FU!'
-98ua,=+I^%^PSD5[u()"pkJJ>IjUH>a3f8pqO.4KGYe$Gps]+YrkO#l<T!2Cn2nIa
-p&tBqL;*Ot_jc]"GT0Z_!/6L6!"Bb6O&5UQWVrm:o))&+^Yo1m!/5@k!"-K\g?nn?
-S)Ji4Ir0\P0B/NTj8KY:pdTCC7Lt-a,Q@`Hq#-Vp)ufoS3e(T\fUC"_$:4/@Hq=8;
-Jp2[p^*!<Z^(Ym7euUtB4;"]C:\\kucf<p%TqQj8p`10k3urZFn/\Zai\-3R&D+;8
-%=E<f:P`H0qu_B,n`#HG57;_&_=O9#J)Hq@ZT#\Gg7S(frN?&err<3Fp`8@DM*D;2
-CL?icVsTc>a$d>>n2Gt^&b-[sJ,Bu_iRE>c]MYAM4O\5_3V]X]p`\Q[K,P99]h7X*
-ShKUea$1.1P?77/`(BVD'R465:UmXug&!4J_*1(qDqRAS*A-ugpaHH`mhgPlW5%<L
-he`0YLOm)arr<G-rYmZm(2roEg:YalHM@=eTD2A-f\SO`J"-H<$3(#',sUmMpo!L$
-n;%#D@qsoS^$!H)fVA./ps]6C"YKL@rr<3<]D]'#AM8Xa/GL=IcNSR-pK.,6g:+tL
-g-ajiLV=Jt&)n+S2*ZeE)nn5Pqd!sO#(0k;583<G*V$RpnOHHCp.!JZ-gP+>^)cKG
-Zb=DtI65<;&_4:V5%s^]rr<1urK"^+mt!\:^Lk4ermkHG9=OD&\+#UTc1j0Tn(J`#
-?a:3[>Mo3(2hQK2qaG`kp5nclV>gORIqt$&p:9\TQ/\?]iBEI/pohR6-G$JW,N)il
-`h*\='mRp\lrmc6b@K,1NshNlrr@XKrl<n&4C`ZsI4t<"rr@XVr,'u,:YDN:489KZ
-%c@!VrK)IHrmeT0L\ssF&c;sdIqQBS+++]YhtFVU0luhc626T#^P%plT>[o6CR9Ma
-2%+=9r%7FJlhLHR/&RFBpiGb.$3&,_"+D7Vrr<31pbc^a!!Nu5S-SD'rr<37pp^-+
-HtE*MnF'Q.]IZ9]DZtB\p8n$TYP^NX]j^EZp5b.*LU$V[iQVVE?75Mjiu]%]<nG?`
-Z<rU!%0o2gLPpO#idFbD>)%U.Gh0pOr(6ng"Ru1*nMe9kY`H\?g,o9@Du2M0^'jmk
-5A#u2+8.jKIM)?6_VYU2:ZKcP5I>@q@it&Y4PIfaj1j;lj-Gth+,aJ6oUgh%'KgN>
-GhkJ<XEZhF\qZ3Ek\ot"_:IHEnID=opc$/Vp`prshi*$gr+5B\iue16GP5u_)<i74
-:B(=IPPtl^n?^,`"ScWgDZk;p^n1ZmAO"m-8,]0i?P\#fn/mO;CG1KIYJcK[?7".:
-B8cci%:8A7*;G6WF2?]Ce,1`d*r>'8HL9"K1d2lWM"hM>5M;[e#OT;+!!Nr4ZECrZ
-:P%6qrO>)NQbM5Dk2XCO#4V*Z.NeFrc\-cZrY=^JC@Q\D&iF%k9L%J_rr@^r`nKh[
-!1i(u#CjT2rr<<`MKHIkmD&!^>>`lDJ)NeF_%cO&$i#Xr+7Q%Ti0SasK(Vib9(>u@
-4<a_)$H)R:ZLGT'ifAjuJ&OPq6h)O[Zk)LO[&^le^m\-qgSS[g`hdArU#Ctnr)9o.
-\?WJ+/W.%:+o$iNp9Zq6n@ue([su3n!83k8;",9OoZmeLr#Yg.2(s[`!"6Lg:M\n'
-pe?-!WVeufpus/dFaH?*T)msHD;a:cpg!T4i"*\CK:fM0_g`5F1;345_Z'ViVr?-3
-&CnEN&%m9NpqutFr"8E^Sabs\^Df?AG[J=Z'E8&cL3YB>^,5V/=OlgsH`^Yq4s][e
-M`bk9Y7u5j<UjFT4F,q9(&3"4LQ)3\Hp[AC[B=c7`ni](IO+^Ca5.ri]N2a!ef3Qi
-NF*<G,OllT$=WfI8`2fNG^m`e2Nt?0[eb^0KmZmuGah=SFcAKVDuTfhNp+'^V8O9J
-MtLk602o4,/EG7P8LEqfLTVu:Z<]*G`-s/Fd@Wnt8*_00;+20r72/Tf'N%:5;+20r
-72/Tf'N%:5;+21#bFc6[r0^XRJc>^^\beXAlDO/hJ!1t6rrD,!nLsiqDuTh0U$MTR
-rr@[\^Z:j_d!ta@rm1TEqLAI<lh@%30C1Rn.f=ed=Rk:f084K4IPcBjD)1k)4q[RT
-nUKLU\#e67R=;tji]I/?KHCbQ"ZM:):._7::4EhG:0S*8[apU/D]EaEP(1BL^L9q7
--%?OlnL_Lln,A,X5N1."Yc%F4^PO'-QJ],prr>GE+7SR!fMhd+?c8$'95iQHrrAc3
-O8*j!lm_r77'GT?r[#&@Sc8];%7g=WX7d8-!2<Qb,Q@`Vg\/qm!9f04rZ,#9$@gGR
-plYRVM/E-&J+Q**rr<P/rImK"Q2F2Q!5u>EZbQ>[W;cjQ<IVfWoLf*.J)X[]g#)`>
-e:5B9^L9q7-%?OlnL_Lln,A,X5N1."Yc%F4^PO'-QJ],prr>GE+7SR!fMhd+?c8$'
-95iQHrrAc3O8*j!lm_r77'GT?r[#&@Sc8];%7g=WX7d8-!2<Qb,Q@`Vg\/qm!9f04
-rZ,#9$@gGRplYRVM/E-&J+Q**rr<P/rImK"Q2F2Q!5u>EZbQ>[W;cjQ<IVfWoLf*.
-J)X[]g#)`>e:5B9^L9q7-%?OlnL_Lln,A,X5N1."Yc%F4^PO'-QJ],prr>GE5Q2[+
-q[%c"-hrW"!/YXkBn,bD;?$V+XSmgek`bp5rrC!HrNs?9,,kMALK8l@?h?qh,6%Z&
->Q3>`r=N"Y_lH"10DZso!"j_N/cPff0E-d-5N1.bYa>;$Iu(l7QN$rnQi@%R<?L_q
-ce(niM*Jpcr(DOo9E,!d.Za@IBC$rE!(<I=0E*94mA9g_d1o1L3j\MmrrAchnJD3*
-'&WE2rrD8?U])9:q[%c"-hrW"!/YXkBn,bD;?$V+XSmgek`bp5rrC!HrNs?9,,kMA
-LK8l@?h?qh,6%Z&>Q3>`r=N"Y_lH"10DZso!"j_N/cPff0E-d-5N1.bYa>;$Iu(l7
-QN$rnQi@%R<?L_qce(niM*Jpcr(DOo9E,!d.Za@IBC$rE!(<I=0E*94mA9g_d1o1L
-3j\MmrrAchnJD3*'&WE2rrD8?U])9:q[%c"-hrW"!/YXkBn,bD;?$V+XSmgek`bp5
-rrC!HrNs?9,-0?[$%BgBZIeI3ilQRnn>"rZ`gPjcV!9u]Q\p0!nN5ba`P#bKdrg@r
-4^np1:[s(s099W4[$nWCd+W6$INFD@][SKtXKJ]P[<IJAWM57uU5C@nMC>3V.&)SI
-U5C@nMC>3V.&)SIU5Jbfp>Z)PP:HO85O?udBFk&@r[k>EAF[_<N]nfi!3k#R!</3G
-Ir@R@D7@BS"+3u@?1I(7`juADXsT:imspIs*C@d"o\-_@^&(/)Y9_mJR"XJEgWeAP
-J!1r?ls,$3o)?\%!9>HPJFihHPEDX)_kH]6IoB0&luVY%%X\SVrYe7t5PC(+hm)(S
-/0FY\1en9m.o.0Kr/B0LrJuC.Ndp!kd6R)Y.`4K-0]O4eAtXY,"5k:dnfqi*L6nfh
-Ndp;K?c&LTfaH^d3<&u3+%I;ode*P>kMu_=rr@d?p^@*%6:R+;!.rB)r\I(B1)I`5
-q@YWGr"`CanX;]$OM1er!76k(J)IWMrrA#*rr<I]n/)(WN?eH'"dU8.Arl^t07^h0
-,\\@q/?o-Sj"u8'+aaIn!21W.rrBlHL]7>lU]),=i%P$8)Fsc7/3ipS+7R?Y!Is<(
-dQd5(@K->IB`A'e6MLrg!('/;rr@Yo&,n@Tr%])(?htBlO8KbqJ+8sliK1bTrrCE.
-Ujq=._uB^qdJj1TL%#oXKT.5V!!SZ1r+;#bA1rJJoH\,mpaiZL!95nc_]aC2rrA`;
-8H/\+AV^9c)5I0K$fE]:#oZ>5$S4O;bocGr?NGZ?8CB`l=^h=1`b>APL-kYCrr>AT
-OoGE5b7FS.8,P+Y^gHpN1lqPM=F]k05N.^<!ri8IOedKbZGZ\BN7%Y*%#+0ere-7U
-rr<4g+8f`3pgc%.^[rdc+8@CkrrD(9J&<FW"oeRr,=qh7_.AE%!#_R2)%5@Ur<XB4
-rX18AprsoMaBnstkXa,dn6'3"!6/^P!/<i8$i^2n7Zm]NK$+](1Iq?u(VjDS&i>[I
-(0H(VRQobm^&n<7d#k,Ri3L9#!0#>*!"=SN(]K)I,Q@`IQ66$:O8*6=JA:_%Bcm+$
-Yl=^`1k3CdHj0NMTd*,.!5W6%rr<q3rYZ+%0Du1q8,`lI5PWJFnAnr;J*9GO5O_fa
-rrC&Prr@d?p^@*%6:R+;!.rB)r\I(B1)I`5q@YWGr"`CanX;]$OM1er!76k(J)IWM
-rrA#*rr<I]n/)(WN?eH'"dU8.Arl^t07^h0,\\@q/?o-Sj"u8'+aaIn!21W.rrBlH
-L]7>lU]),=i%P$8)Fsc7/3ipS+7R?Y!Is<(dQd5(@K->IB`A'e6MLrg!('/;rr@Yo
-&,n@Tr%])(?htBlO8KbqJ+8sliK1bTrrCE.Ujq=._uB^qdJj1TL%#oXKT.5V!!SZ1
-r+;#bA1rJJoH\,mpaiZL!95nc_]aC2rrA`;8H/\+AV^9c)5I0K$fE]:#oZ>5$S4O;
-bocGr?NGZ?8CB`l=^h=1`b>APL-kYCrr>ATOoGE5b7FS.8,P+Y^gHpN1lqPM=F]k0
-5N.^<!ri8IOedKbZGZ\BN7%Y*%#+0ere-7Urr<4g+8f`3pgc%.^[rdc+8@CkrrD(9
-J&<FW"oeRr,=qh7_.AE%!#_R2)%5@Ur<XB4rX18AprsoMaBnstkXa,dn6'3"!6/^P
-!/<i8$i^2n7Zm]NK$+](1Iq?u(VjDS&i>[I(0H(VRQobm^&n<7d#k,Ri3L9#!0#>*
-!"=SN(]K)I,Q@`IQ66$:O8*6=JA:_%Bcm+$Yl=^`1k3CdHj0NMTd*,.!5W6%rr<q3
-rYZ+%0Du1q8,`lI5PWJFnAnr;J*9GO5O_farrC&Prr@d?p^@*%6:R+;!.rB)r\I(B
-1)I`5q@YWGr"`CanX;]$OM1er!76k(J)IWMrrA#*rr<I]n/)(WN?eH'"dU8.Arl^t
-07^h0,\\@q/?o-Sj"qk2$fE[V"DJbJdd03neMmIF#N.iF#oYc%$S6e'6G@gFY^^9"
-KDlVaOFM#YCIdlCNGGKW+1"JXHi6.j4YFi&\%B$B?/hoCH)$L3glb)_Bd,UsOd%V_
-^`*4Q/cPejF5mcDT3Z(/!<3$k*l#>Epbg`iIN&45H]Bo@^Y.on:]/95!,2B49)bha
-M7%eMREl,KqG^67&bh%chpD7BpZYM]Ol6/TSd/T!X#m1BnE]Q3<Ln\$cN&%cIh>]:
-L3&pdp[pBbp%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY09X?dSfQ
-KcAXqoKV;(p%A7opee_QIma2LDdQkurr@`lf@TXZiC<M5r=A[#]mYAtrY5U]je\6U
-`T?4*2O9Yj96GB"F!<ngD/B>2ZeSe].9N9u(m3mF=W(*o<d%lN8GMZIe^aquq^?pG
-&4,;/#K`[_q\FR$f(?X2hWF7p`S.`ekC>ZnD]YlmQL+HMn9EC;R<:H,2Jl73\$n-3
-.l:Vp)rlGD*'?mo!+DAs!<"<lrm<sghER(9$2t0W1\f,m!#,>Zr&=CiSgMfJ$U^XQ
-`#g%F>JVbi9qc?0*@B<FdU0r([[+Lh\n#"<P:iUNT:Ya2lC)ME#ZgrSbP`?Og[k,7
-mJB]Yc(-nF_YEn-qB,K*#O>2XqgX(:aoR"GMtUsUc9?0-574W!T'bP*U]])MaJaUI
-^]+:EU]1<Q9D^OfYK+tC"7jcr^Q>DKpAOrQZ&eZp?eM+8e)T?&F6ii+;fKe?RY:[t
-J$NG[*A?d10QY:Tc\2VnrrA1o+2a69e8>)2rlKg)5AEF9Zg%Ji$h*%>-_L8T^Wnmi
-J+2?&Z>][^([TiT!/L=-5Q:^@e:5AaI`]@sFC2@erZC$NrrDuK;?$V*p%p*9!7B2C
-c(Fc\IM;_]o3Fla2qRDcrr>PXq_ir_rV01g!6oX.nD@TYDuC[mm+MC=L\Kalrr=q+
-J&?\`ahRIi?aFDE+5_bO!;tGGrr<N$q^2=CdF!EfTD3nb'E8((>t=fOfBf",!(TKT
-2Lj]apeUnic#k,thd<[-r>c^@g&D&-pYe@:!&`8U_gR!U^[uVTZY07Zhh;"0r7=gG
-!"JVu-N=(nd=0?4pj[`+rrDXr8,P<tm$n"T7n*;5J)UA$:]CF>FW^,1?a=VK*>e(q
-rr@iKiBR>B2:R,nI=B;QoQ4HHBDs"1K`;&Mf2;PJ%JBTFrrCHoIa+M[Isr(2!:sJd
-r&<6oS,WIY7JeumiViOIrrC;d+7S/pZ>][^([TiT!/L=-5Q:^@e:5AaI`]@sFC2@e
-rZC$NrrDuK;?$V*p%p*9!7B2Cc(Fc\IM;_]o3Fla2qRDcrr>PXq_ir_rV01g!6oX.
-nD@TYDuC[mm+MC=L\Kalrr=q+J&?\`ahRIi?aFDE+5_bO!;tGGrr<N$q^2=CdF!Ef
-TD3nb'E8((>t=fOfBf",!(TKT2Lj]apeUnic#k,thd<[-r>c^@g&D&-pYe@:!&`8U
-_gR!U^[uVTZY07Zhh;"0r7=gG!"JVu-N=(nd=0?4pj[`+rrDXr8,P<tm$n"T7n*;5
-J)UA$:]CF>FW^,1?a=VK*>e(qrr@iKiBR>B2:R,nI=B;QoQ4HHBDs"1K`;&Mf2;PJ
-%JBTFrrCHoIa+M[Isr(2!:sJdr&<6oS,WIY7JeumiViOIrrC;d+7S/pZ>][^([TiT
-!/L=-5Q:^@e:5AaI`]@sFC2@erZC$NrrDuK;?$V*p%p*9!7B2Cc(Fc\IM;_]o3Fla
-2qRDcrr>PXq_ir_rV01g!6oX.nD@TYDuC[mm+MC=L\Kalrr=q+J&?\`ahRIi?aFDE
-+5_bO!;tGGrr<N$q^2=CdF!EfTD3nb'E8((>t=fOfBf",!(TKT2Lj]apeUnic#k,t
-hd<[-r>c^@g&D&-pYe@:!&`8U_gR!U^[uVTZY07Zhh;"0r7=gG!"JVu-N=(nd=0?4
-pj[`+rrDXr8,P<tm$n"T7n*;5J)UA$:]CF>FW^,1?a=VK*>e(qrr@iKiBR>B2:R,n
-I=B;QoQ4HHBDs"1K`;&Mf2;PJ%JBTFrrCHoIa+M[Isr(2!:sJdr&<6oS,WIY7Jeum
-iViOIrrC;d+7S/pZ>][^([TiT!/L=-5Q:^@e:5AaI`]@sFC2@erZC$NrrDuK;?$V*
-p%p*9!7B2Cc(Fc\IM;_]o3Fla2qRDcrr>PXq_ir_rV01g!6oX.nD@TYDuC[mm+MC=
-L\Kalrr=q+J&?\`ahRIi?aFDE+5_bO!;tGGrr<N$q^2=CdF!EfTD3nb'E8((>t=fO
-fBf",!(TKT2Lj]apeUnic#k,thd<[-r>c^@g&D&-pYe@:!&`8U_gR!U^[uVTZY07Z
-hh;"0r7=gG!"JVu-N=(nd=0?4pj[`+rrDXr8,P<tm$n"T7n*;5J)UA$:]CF>FW^,1
-?a=VK*>e(qrr@iKiBR>B2:R,nI=B;QoQ4HHBDs"1K`;&Mf2;PJ%JBTFrrCHoIa+M[
-Isr(2!:sJdr&<6oS,WIY7JeumiViOIrrC;d+7S/pZ>][^([TiT!/L=-5Q:^@e:5Aa
-I`]@sFC2@erZC$NrrDuK;?$V*p%p*9!7B2Cc(Fc\IM;_]o3Fla2qRDcrr>PXq_ir_
-rV01g!6oX.nD@TYDuC[mm+MC=L\Kalrr=q+J&?\`ahRIi?aFDE+5_bor7;k0^\t^X
-AdqAi`5mFD&(pqsJ+/?;Dl%-9cc492hqi/*-,.#MX_WB&r).Wmr%/,9o$+/9b`Uf<
-8/BY%.tkEpXh61X[f*I\ApnmsAc8\%9cNf%rJn;Q='PW`4F>uq)c,r^Nr0+\/+Hu(
-0)csMg-OYh"'Spo.<f@]rAs-93_kX<f]kN;V.HIACS]b-F;EL+bC"'Ir[mXZUFW,)
-pWSYn1:":R<L&+YQ%9&L80Ht5<6=1()-bk9@g@k`aD@u8(A<mU=%R6/qnK^rA.clQ
-J-f3YJ29ds!"%PArrD7rf0Ab7F8l6\.1_HOA:"$C><cC_jSo3?.6lcOnW3VWg=Q<4
-/jK-B5N+TlJa;<$B`A(erQ"p<(J4W,$,;E`k[i=pn32@$/s#d%r*fU*6S>_F!.jbA
-!:b/\_JeHFqAFFJr"#G"!/mWO'7UjKd*&Nj!8r8)!;p+En=03jre=]krr</arrD'B
-rr@`4`WN,qFcl\(Dtb@O>qc+'4u*';Tpo6c!5XB0rr<j*r$NO>4a]o)+8^PtrrD'C
-5N+QkL]%Xmci+0qrrC$crr<A?N'HN;epm0QJ,V']peCZprr>D=Zi:#VoD\g\FFV/G
-it(u(FeARBTDnnLU](pV(k9oUXT&:YI/a3E>p&R*pr!)c?"a0;"6][aiopCBK\sck
-oJ5_sp`Da#!#J0'-QXr^4A2c:qgZ-U!936miApFhr=%E3rX:DDppr]K3Ur1/%,0>4
-$nad>\j,.6nW3VWg=Q<4/jK-B5N+TlJa;<$B`A(erQ"p<(J4W,$,;E`k[i=pn32@$
-/s#d%r*fU*6S>_F!.jbA!:b/\_JeHFqAFFJr"#G"!/mWO'9<t?SgDrXrP.-;nT;P8
-SG:/(L2C`+!!X5]r*:E6S9VjBnLh1umJc/G!/mZQ!/07L+7q>S5PQ<brr<j*r$NO>
-*BZurO8FF:rrD'CJ)NEXO8TL@fDZ125PVfSiAg@Ylf)2`rrCgPa8Z,U8cJbs^PkD@
-A_)A#5(EPaO8)HI@K-<p0!kQXJb/mAnT98tDrVB))0MSL&"ik%Mkg7bIi*[^bH1^D
-i-bP)r*:E6S+so#L0\Hl!!DEa!935B!/07L+7q>S5PQ<brr<j*r$MCsrrAaZ=oSK;
-q>UHi\j,.4nV@&O]$L?\ci4!adJj1Q^PkD@A_)A#5(EPaO8)HI@K-<p0!kQXJb/mA
-nT98tDrVB))0MSL&"ik%Mkg7bIi*[^bH1^Di-bP)r*:E6S+so#L0\Hl!!DEa!935B
-!/0CP+7q>S5PQ=?rrC$drrBoWiue+8[BKKF>^u9cJ&63c&,I0OYP\p@rrD'C5N+Qk
-L]%Xmci+0qrrC$crr<A?N'HN;epm0QJ,V']peCZprr>D=Zi:#VoD\g\FFV/Git(u(
-FeARBTDnnLU](pV(k9oUXT&:YI/a3E>p&R*pr!)c?"a0;"6][aiopCBK\sckoJ5_s
-p`Da#!#J0'-N5_!!25`^rrBk1rrDi*5N+QkL]%Xmci+0qrrC$crr<A?N'HN;epm0Q
-J,V']peCZprr>D=Zi:#VoD\g\FFV/Git(u(FeARBTDnnLU](pV(k9oUXT&:YI/a3E
->p&R+Gf0N8?"a0;"7ADK\mP5-Ht30V6T2@P!.tZ?r[s9,:-;tb!(/ZPrr@WE+8fCl
-r$MCsrrAaZ=oSK;q>UHi\j,.4nV@&O]$L?\ci4!adJj1Q^PkD@A_)A#5(EPaO8)HI
-@K-<p0!kQXJb/mAnT98tDrVB))0MSL&"ik%Mkg7bIi*[^bH1^Di-bP)r*:E6S+so#
-L0\Hl!!DEa!935B!/07L+7q>S5PQ<brr<j*r$MCsrrAaZ=oSK;q>UHi\j,.4nV@&O
-]$L?\ci4!adJj1Q^PkD@A_)A#5(EPaOSI_Pj:H]1X:Ri,2q*jSl3K%p%rcbNc;-RS
-1J'aJN@`Mdkp1^\gAl,$`_"2u^JiC,s4I~>
-%%Trailer
-%%EOF
diff --git a/docs/figs/acm_overview.eps b/docs/figs/acm_overview.eps
deleted file mode 100644
index e52bcf3419..0000000000
--- a/docs/figs/acm_overview.eps
+++ /dev/null
@@ -1,1463 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0
-%%BoundingBox: 0 0 1106 631
-%
-% created by bmeps 1.2.6a (SCCS=1.78)
-%
-/pstr
- 1106 string
-def
-/inputf
- currentfile
- /ASCII85Decode filter
- /RunLengthDecode filter
-def
-gsave
-0 631 translate
-1106 631 scale
-1106 631 8 [1106 0 0 -631 0 0]
-{ inputf pstr readstring pop }
-image
-K)^H&K)^H&K)^H&VuHbSm(WPPK)^H&K)^H&K)^H&K)^H&_Z']3LFD?d!FYAJs-s#g
-mt/<E^B!_Ss+:9&s+:99rrL.gjT#<(hh(m!rrLFWJcM;@!=6Gls+:9&s+:9<rrMk=
-rW!!JGdm%S"J83b!'#T1Sc8\>JcM5>!.TV#K)^H&K)_5<"F'nH#`%UC")%Z7^OlKW
-rr[`N!2kF`T>(F-!.TV#K)^H&K)_8="NLKB.+dV]"7H3iO+RD'rr[`N!8iD.TDnrm
-!.TV#K)^H&K)_;>"SX;E#g_T3![%JFK)_GB"+L:Nhh(m#rrN0#ItI]Ps+:9&s-iri
-NrT08j8T3X!#YH^s.B;nIfKK+K)_JC!WW4MK)^H&K)^H&Rf<FK!#X_q"HNN_8FM01
-T`5+D!!(o.s.B;m!!%M#s+:9&s+:9>rrN0#B]8sk5lL``3/'U!BSY35rr[`N!8iD.
-TDnrm!.TV#K)^H&K)_>?"6TXaTAfeNmmr$1rVut,n"]mbIfKK+K)_JC!WW4MK)^H&
-K)^H&S,WTJ!!'LcrrK<QKKoMSrVus9\"s$+IfKK+K)_JC!WW4MK)^H&K)^H&S,WTJ
-!!'ccs5*bVcWL/H!-k@?"+L:Nhh(m#rrN0#ItI]Ps.TGnkD+Y=\UOX@n&YM2hZ*Yk
-K)aX+"Lf3J!5GE2"+L:Nhh(m#rrN0#ItI]Ps.TGm0S0;6!!$-Brr_-Y!5F-cg]%E>
-&-*jIVuHjK!!(o.s.B;m!!%Mbrrqk`Im?71JcM_L"UI@YBRe@Ks+16Z!!#:*rr_-Y
-!5F-cgA_8I!!$u9rr[`N!8iD.TDnrm!.Vod!N/bG!1X#j+E6MdrrN0#ItI^4rrPFc
-5fis-hZ*YkK)aO("#p8lpSe)oIfKK+K)_JC!WW4M`W#tJ0`:tR#XCY"Jq'\J!a%]1
-r;Zm)E:;$N!WW4MK)`I_!^H`NaSuA"!!'ccs4RDSQN.$+W;csL!!(oprrg)j@q1b,
-rrR9gA,H9+g&B4PrrRm:Z1@nr^P/rgrrN0#=SK'#ldGe6ha%/@!si#,pO`F=rrUf%
-./j2I&<G*9!WW4MK)`I_!^H`NaSuA"!!'ccs4RDShZ*YSW;csL!!(pFrrV>:PhZ3=
-bWPe'!0mE]!6hqP!3uM'"jI#HYrj?2!!4H/UZh^Yk1T_5!0mH_!87#E"Qh!1!5JC1
-!WW3npQbg@e,KWm(]XOIL\HE#S,WN85lL`aB_TjQ!WW4MK)`I_!^H`NaSuA"!!'cc
-s4RDSpAb2cW;csL!!(pKrr@cN,m"&HUYYqNfd6Lq!+Z$."MZ5_-/#j/!'L5\!nmV,
-pAb4kk3N$LKd?^]rr2tPrVurBo`"p8rVuqPqYpTs!)*'P!9M`1"fDV+!-%CYs-N`h
-^E<LV5k!)"!WW4MK)`I_!^H`NaSuA"!!'ccs4I>Q!!&Xirr[`N!8mMM!O3sH!!#mP
-rr>pp!!=Mn4PB`6!'L5\!+WV?!5JL5"&]*ubk;#;--Y`U!%%UE"/GnrL&M&Pbk1o8
-Pl:X_L&1fN!!#[dQ2p$srrfM*!!o3Ks-3Neml1:I3;:i#!WW4MK)`I_!^H`NaSuA"
-!!'ccs4I>Q!!&Xirr[`N!8mPN!2K8g!'K-<!87;N!JT\5rr>pq!!%,Prr?R.!!C"9
-s31HB"Asl,;'l/@!'KWJ!%%UE"2Fm9L&M&Pbk1o8L&M&PU\aul!!#[dQ2p$trrgXR
-!"cnss-!BbpK.Cq=OI-M!!%M#s1A:45QF'jrr_-Y!5HSS!d$Q0p\t<"4JVfR!d$Q"
-qu6bn,s9lYrr[?h4QaEY!WW4mW;csL!!(pOrrAhl!!4H/-2mlE4Pp)<Pl:X_A,6-,
-fhj%m\c2aX!!#.\rrC:B!!%`Orr@cO!!&e]rr]Mg-$9.d!/:CP!6k*8!/:CP!6k<>
-!WW3npQbg@fDc!:+92DNK)^r4"SY.]!/K#&!WW4MK)`I_!^H`NaSuA"!!'dTrrBh5
-!!%`KrrAhn!!(^Nrr[rT!%%OB"!mpI;>gFr,ldq!^]+?8!2$4i"+L:Nhtd9P^\n-<
--*dLMo-FA:;;V<QA,ZH.bc^sGL&M&PPlC[_bl.SBL&CrNL&M&P;<IlYL&M&Pbk1o8
-L&M&Pbkh>@!!#[dQ2p$urr[3?!0;a3NrK7N+92]1e,KIL!.TV#]Dhpt!'nX*"5a(Y
-^W?ETg&1mNU\k&kZ2O_'-2dcC-2mlEU](2mbl.SB-2dcF,ldq!^]+?8!2$4i"+L:N
-htm?Ro-OA9!@>tgrr]#B4PB6(!p533rVlo\g%bRL49,@-XoAJL!!">DrrC:B!!%`N
-rrC:B!!#.Drr@cP!!(7<rrhKHs8Psq!!(7>rrN0#9D=_Pjk0S8cN!rAK)^f0"4$rI
-:t,FG!!%M#s1A:45QEA1YlO+<rr_-Y!5HSS!2KMn!@?FtrrM7.rVur5rVllNr;Zh-
-rVlkOr;ZiArVlsG!!%_frrN0#T;_blIfKK+qYpP*rVusFbk(i<k*0@<A#&r$$7,ZP
-U]6#o,lf6FrVm8fb`jCR!$u_L4AiB^rr^"u4O!X$"jE3bKqmf/rr_CG-"HlQ"6M]l
-;?$S&Yu-bcs1`Y<,pe9BrrM8Hr]C6ZPih]>!2KMn!+Z!-!6kEB!/:@N!5JL5!'L8\
-"6M]lA,Q?/juaqerVlqQ4Al(W!/:CP!6k??!M_dU,m@..!!">-qYpTs!)*'P!9Ml5
-"&Jstc[u1TrrZ't!700p!WW4MK)`I_!^H`4pm(pAdf0F,!!'dRrrAhn!!#.[rr>1\
-!!&8]rrA;^!!#.[rr>1[!!&8^rrXPI!/82f!WW4mW;csL!!(pRrrBh4!!&ecrrI3f
-qu?a[bl7VBbl.SC4AktU"GQmUUF#U6!87AO"!mpI4T#-ZKdHWs!@<I!rr@0?!!(7A
-rr@cP!!gaJjs:!-PYq;X!2KMm!JMis!!+Bfp\t@Y!!">-rVllArVuqPrVlo\4T5<\
-PlC[_FT)7?bl.PAL&M&Sbl@^rrVuq?rr2tPrVurBr;QaZpAb1>q>UKr!)*'P!9Mo6
-"4mMQBS-8Arr_-a!*IbN!WW4MK)`I_!^H`4pm(pAdf0F,!!'dQrr?R.!!>@`s)e5?
-!+Yp+!+Ys-!%%UD!%%RD!/:CO"!mpIKtmWh!!&Xirr[`N!8m\R!)`^q!+YX#!'L&W
-"=<[>s310:"""!I4S8[Sg&D!R,ldokrVloB-27HB-/&;\rVurBrVljprW!#Ds310:
-!'L8\!+Ya'!/:7K!2KMn!+Ys,!6kEB"_5d#P[c$=!!">Drr>1\!!(7Arr>pq!!CIF
-s31HB!'L8\!/:CP!6kEA!'KrT!%%I@!WW3npQbg@g&D/(!!(>ss,$aX:]Ldqec,[N
-!.TV#]Dhpt!%.K,!9MZ/"5a(Y^Vp-P4T5<]A$Q"5!'L,X!'L/Z"53_S^\e'34T59^
-,ldq!^]+?8!2$4i"+L:Nhu*KSg&:sP-0Fk"!+Yp,!%%RD"(VB2bk_;?;*=gX!mL[u
-q>gL@!Bc)7rrXPI!'L8\!SJdt!!4H/4T,6]L&WIu!!(^Nrr>1\!!:CEbkhA@,s;/,
-"$HV`Z2FY),s4:9rVupEq>URD!!">-r;Qc@o`+usrVljDrVurOrVlj[rW!&Es8U=B
-!!%-?rr@cP!!(7Brr?R.!!FTXKnWD&!!">@rrN0#9D=_Pjk9Y8-ibBAs+p[WT)\kh
-ec,[N!.TV#]Dhpt!%.K,!9MZ/"5a(Y^Vp-Qo-OA9"=4$J--Z5c!%%OC"/GnrA,H<,
--2miG,ldq!^]+?8!2$4i"+L:Nhu*KSFT)7?A+]d$^\n-7A(gmHrW!$Hs8U=?!!8qq
-bl.SKU]:A/PftER!'L&V"!mpI4T>?\;>pOr4MUmq!0mH_"blt&!!">Crr>1\!!:CE
-bkqGIFQWTL!!#.]s#g8\!0mK_!0mH_!%%LA!/:CP!+Yp+!6k-:!@>MZrrXPI!%%RC
-!'L5\"3gfFbl.SBL&V)PL&M&Xbl@_*,ldokbl.PAPl:X_-2IQB!!#[dQ2p%#rr^jQ
-!-j+qM#RSG#QRuWrrN0#ItI^4rrPFc-MWl,jjO/2hZ*Yk_uBb]-2[`CPktC[bkhAH
-A,lQT!!";F!%%UD"!mpIbeO/Z!!&Xirr[`N!8m_S!'L5\!5J1+!+Z!.!)`^p!+Z!.
-!l+cZqu?hQs8U=B!!%`NrrXPI!'L)W!6kEB"$HV`^]"354T,3ZL&M&UL&WG!!%%RC
-!'L5\!mL\gr;Zhmrr3-J!!#mr^]"39A,lS(4T,6[A,H90o-FA:-1h$6!6k'8!2KPn
-"!mpI-2dcC4T5<_bl@]srVuqPrr2tPrW!&Es8S>_!!&ekrrXPI!'L)W!WW3npQbg@
-gA_8a!!(&ks+gUU:]NK*rrN0#ItI^4rrPFc-MWl,jjO/2hZ*Yk_Z'V#r;Zh-q>UbT
-!!"<-!!#.]^]"35L&M&Pbl7VE,ldqh^]+?8!2$4i"+L:Nhu*KV,ldokoD\e:rVurO
-rVll4rW!"Rs31EA!'L8\!5JL5!/:@N"!mpI4Sf!Wbl.SE4TGFkrVuqnr;Qb=rW!,:
-s!7XF-2dcI49,@-k5W[)!!$O-rro/D4PBaVrW!#)KdHWs!'L,X!+Z!.!/::L!6kEB
-!)``L!FmGS!!ah's8OAF!%%RC#<Vtd-0G7-L&M&PL&V)PL&M&Vbl@]?!!">ArrXPI
-!'L)W!WW3npQbg@gA_8I!!)K;rrJ@Ko`#!-L$"Qu!p53$qYpWgKp;E5"5.0]k0O&/
-BE01*rrN0#IuaO0ft[N?!L2:&rr^"u-)8lf!^H`4pm(pAdf0F,!!'dNrr>1[!!$O)
-rt.?n!'Gr8!%%YT!!">:,ldq0rr3'H!!(6XrrN0#T;_blIfKK+r;QjF!!">:rrXPI
-!%%RC!6kEB!epZur;Zh^rr2tPrVuqPr;QjF!!#.WrrC:B!!YRcs#^8]-2[]B4T5<a
-g&E>u!%%RC#!;kc-3+"hrVuqPq#:=VrVupEqu?a[U\aunjs:!--2IQ@bl.SBL&CrO
-^HDJq##YF#,ldokr;Qj]!!">Err@cP!!%`Prr@cP!!^[Is#^8]4So'[,ldp-q>UKr
-!)*'P!9Mr7!e11UeGfYK!!#.Dp\t>j!!"=ErrSrAFRoG3L&<4u!!&ekrrXPI!+Ym*
-"$?P`4O=$/IfKK!rrN0#J+EU>g&B1sKfjIRrr@cL!!,3Wm/I/M!!">BrrJ@Zg&D+=
-!%.K,!9MZ/"5a(Y^Vg'O;>U=nU\aun,ldpebl.SNUEom?A,eXk!+Z'/bl.SBbeO/Z
-!!&Xirr[`N!8m_S"!mpI-2@KCg!'Krbl.SB4T,3Zbl.SDL&[D:!!+D.rr2tPrVuqP
-r;QjF!!#.WrrC:B!!YRcs!7XF-2[]K,ldoks8OAF!%%RC#!;kc-3+"hrVuqPq#:=V
-q>^OYU\OihA,ZH.U\Xoibl.SBL&1fU,ldokk5Q_-!%%RC"$?P`-3!oEL&M&PL&V)P
-L&M&Vbl@]*!!#.XrrXPI!'L)W!WW3npQbg@gA_4f!$Kek!%%UE!@@@5rrAhm!!(6D
-rrgOl!!&eerrKANq#CClr;QbNrVupEqu6Ykr;Zi4d/O37!!)35rrN0#J+WaAUHJAQ
-!847L!%%C?!)`.`"$?P`-2dcF49,@DgA_4>!%.K,!9MZ/"5a(Y^Vp-PA,ZH34='t-
--0G.*!2KMn"i('`!!#.\!!p@>@fQKTs8U=B!!(6XrrN0#T;_blIfKK+r;QaCrVuqn
-qu7#p@fQL+s8OAF!'L2Z!5JL5!gN_=rVupErVlkOrVuqPr;QjF!!#.WrrC:B!!YRc
-s!7XF-2dcC^]"3;-3+!-!!">CrrtRc!%%[Fbl.SBL%tZJ4T,6],uMGOrrBh5!!#.V
-rrC:B!!%`Lrr>1\!!UUH49,@-r;Qj]!!">Err@cP!!%`Prr@cP!!^[Is#^8]-2RWD
-,ldp-q>UKr!)*'P!9Mr7!al!neGfMjr;Zg[qYpQ1r;Zg[WrE&]rVuq?pAY,fpAb1U
-r;QaCr;Zhmr;Qb,r;Zh>d/O3?!!(p-rrN0#J+`gA;>:+kL!K]#ffUR&h>[I$pAb1U
-mf*AO!!">DrrC:A!!(^,rrPFc-MWl,jjO/2hZ*Yk`W#pJrW!!Gk-=mc!'L2Z##P@#
--3+!Bqu@0Ps8S;`!%$e-bQ%Vhk.got!!&Xirr[`N!8m_S!-J2?!@>tgrrJl@rW!0L
-s8OAF!%$e+rr>pq!!:jRL&M&P4T59[^]"35A,Q?/,ldp-q>UH=rW!-bs8OAF!%%RC
-!)`^q"$HV`4T5<\bl.PG49,@-s8U=B!!%`Jrr>pq!!,sZqu6]Zbl.PA;>pOqU\Oih
-bl.SBL&CrOUJ_!j"""!I4T5<\bl.PD49,@-rr2tPrVuqPrr2tPrW!&Es8R3?!!$O,
-rrgOl!!">@rrN0#9D=_PjkB_9?iWI@rr?R-!!%-=rrM^;rVusFo;hlkA,QB-4SSjU
-U\k)n,s3LQ!!#.[rrM7.r;Zh>r;QaCr;Zg[d/O3?!!(p-rrN0#J+imB4SJgUL!K]$
-;#gSBk2-+C,ldp-bfmh!r;Zh>n,EJP!!">DrrhI1!!">!rrPFc-MWl,jjO/2hZ*Yk
-`r?%'rW!'Ibl@]brVuq?rVm'J!!#.]s-3E]"(VB2g&:sTPlJr-!%#AZ!WW4mW;csL
-!!(pSrrM7.rW!'I@teD=qu?g]s8QU.!!GFHs8QU.!!>@`s+UFP!'L5[!6kEB!'L2Z
-"!mpI4Sf!Wbl.SE4TGFkrVuqPrr2t.r;Zp^s8RfP!"5%ks5qNO!!">Fs31HB!/:4J
-!2KMn!@=N>rs.4e,liZ!s4RAO!'L#U!6kEB"a%tQF?ClI!!B"rs+UFP#aGAhk0,+O
-!%%XE!/:CP!/:FP!/:CP"O-oGjsC!,"_6]ps-+i/!!">@rrN0#9D=_PjkB_9?iWI?
-rr?R-!!&emrr>pq!!+CiX8`1)qu?^Cq#:?/r;[*LZ2ajq,ldpBrVll4qu?^ZrVlo\
--2dfD-.)YoT)\lKf)GdO!.XbC!'L2["!r&C4T5<\L!K\u4T5<\bhi@%,ldp-rVlkm
-rVupEn,EJP!!">Crr^#5;;'\'!^H`4pm(pAdf0F,!!'dSrrAhn!!+CirVlj[rW!>$
-s8V4-!!%-@s5kX+!!'e5rs0nN!)`c\!!">Crr^#G,uM__!WW4mW;csL!!(pRrrAhe
-!!#mqrrM7.rW)pDr;Zr)s8RfP!!#.ZrrXPI!%%RC"!mpI4Sf!Wbl.SE4TGGrr;Zm]
-@jV$Q"$HV`U\t2l-2dfG-0G6OrVuqPp\t4Ur;ZpG4?Oqg!!?a2s'u$.!2K;g!6k'8
-!2KPn!2KJmr[%LC"=<41s+UFP!/:FP!/:CP!6kHB!-J/>r[%IB!%%I@!WW3npQbg@
-gA_4^!'ns3!'L5\"=;:ls)e2>!2Jo\!p533rVlo\fua6po-O86!875K!V7W:!!+Ci
-rVltp,s9lZrr@cN!!">DrrAhl!!"=lrr\kn!8lB-!WW4Mq#:>(r;Zh-rr3,`,ldq?
-cMmlSrVuqPhu<]0rVup\r;Qb=rVurBnG`SQ!!"=mrrPFc-MWl,jjO/2hZ*YkaSu78
-r;Zhmr;Qc3rW!$Hbl>od!!&8_rr>1\!!">Drs_g*!%%Z!!!"=!Ki'-Br;ZhOaSu;A
-!2$4i"+L:Nhtm?QU\Ffi-'\?-!0m6Y!+Z$.!0mH_!/:@N"!mpI-2miHjs:!-4Sf!W
-bl.SB4T>?\FS5\7L&V)P-2%<?bl>od!!%`IrrL=ipAbFEg&L1\!!">=rrC::!!,3s
-r;QaCp&G3=s8RfP!!%`Prr@cP!!(7Arr>1S!!(^KrrN0#9D=_PjkB_9?iWI>rrLe!
-rW!!Gk-=jb!+Yg(!SMSo498requ7!L!!&eoKdA#F-&(Xa!d$PYjo5<jrVupErVuqn
-qYpP*rVusFbk1o84So*Yg&D!O;>U=nbgHFmT)\lKf)GdO!.XhE!0mE^!+Ys,!jPUe
-p\t9VbhW4#UP6I)rW!%BKnZ;]rrC:B!!%-=rr@cP!!(74rrY@`!%%.7!mJmAjo5BI
-!%.K,!9MZ/"5a(Y^W?ET-2mlEU\aujL&M&R4TEY)!!(7Brr@0?!!%`Orr@cP!!1;t
-o`+usaSu;A!2$4i"+L:Nhtd9R^JQ<V!!4GmL&(`LUF#g<!@;jdrrC:B!!%`NrrY@`
-!%%UD!6kEB!)`Ok"$?P`L&M#PKdHWs"Ci_X!/:FP!R)ka!!:CEbl.SBU\=]ho4'*D
-!!OZGk5YJ*rVuqPp&>"<q>^RC;5=!f!R)ka!!gaJs5kU-!5JO5"-`cc-2[]CF=$ea
-"!mpI-2IQB!!#[dQ2p%#rrQR.5g]N2Z2FY'4=0t,!'L&V!+Yj*!@=N?rrC:B!!,2Z
-qZ$VMm/I'\rVurOkPkOerVusFA,ZH.FSl(<^\n-4U\"Kc-2RZB^]+65-2RZB^X<&`
-T)\lKf)GdO!.XkF!Tk^-!!$O&rsRLB-):LT;'dLg-):D<!TnM&,m$2Nk4nrWUJ_":
-!BcVFrr?R&!!#.ZrrJllr?VJAU[\9`bl.SBL&CrNA,ZH.bl%JEPWU6<4GE\4"$?P`
--2miGo/n<]qYpSM-2mlG-"H*:rrR9g;>L4ojuar3qYpU^!%.K,!9MZ/"5a(Y^W?EW
-,ldq?q#:V0!!">Ff`2!urVlu^,lg(*rrqO2!!(6Xq#CLC-"F^1rrN0#T;_blIfKK+
-p\t6UrlbB)pAY0UFT+B'FQWK#!b3NRqu6c',pf>brrC:B!!%`IrrJA!qu6l_PYjPQ
-^Y/Sd!/:@N$):um4ER@',pcFfrrQ[V;=jemk+dW-4GBQmrVlu^,lf7`rs.[r4?S=O
-UWiE2$):um4ER@',pcFerrV>:g&1jOP_HmJrs>HB4Ca)[s--Bqq>UKr!)*'P!9Mr7
-!al!nci4!?q>^OBbk_8=4SJgX^]4>Xp&G(=m/I'>rVurBkPkNErVutQbl.SB4T#-Y
-;>pOqA+T^$jsBm)"*FSC^\Rp1L!fo&T)\lKf)GdO!.XkF!+Z!.!'KrS"Ao.!,uOO>
-!%%UD!M^t;!!+C@qu6]@4Sf$\-):M?-1q6<k5PA\;>C1l4RrFObl.SBL&M#OZ2O_'
--2miEYpK8I!@>tgrrY@`!%%UD!/:CP!2KJl!+Yj*"!s`BU](5nFSc";;>pOqg&(dN
-5QE/+Q2p$prr_-Y!5HVT!ni:4pAYAO4L+qdZ%^m/rrM9+qYq#04GEh8Yrj<p4AggI
-k/@9$!!&Xirr[`N!8klt"!mpnk3;mGU](5n^\%O+k2-+<bh)jpk1BV7!!#[dQ2p%#
-rrQR.5gKB0A,?6+U\XoiFSu4=49-],!!?a2s31<>!DtuY!!(71rr@cP!!(7,rr@0?
-!!YRcs!7XF-2dcCg&:sP-0Fh!!2KAj"$HV`A,ZH.4T5<\;:5CGT)\lKf)GdO!.XnG
-!Tk^-!!'e,rr>1T!!CIFs0;:u!@?n,rrJl@p](CBs8R37!!#.\rr>1U!!$O"rrC:B
-!!J#Us5o%6!!%`PrrB>!!!#.[rrY@`!%%UD!/:CP!/:CO!-Iu9![[l]r;Zi4r;Qc3
-rVusFk55/[5QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:NhoG`tbi\-h!)`^q!82u(
-q>UKr!)*'P!9Mr7!al!nc2Rbir;Zh-q>UW\,ldok^]+65A,ZH1;?-[?qZ$\ms31HB
-!2K)a"L2H!4=0t,rB((bmJd4?-2mlH^]4<[rVurBrVlk>rVuq.o)A]"rW!15,ldok
-s8ODE!!KPQ!!"=mrr\kn!8lB-!WW4Mqu6Y<rVupqo`"nRqu?dE;,R;m"3gfF-2mlE
-4T:$7-2mlEPlC[`fd6Ut#:3lTKd?^!-3!oHftW5<rVuq.rlkBA!/:CP"=7Q3Kk()^
-!%%49!/:CP"!p&U-2dfD4T>?]jsBs+!@9l,!!%`PrrY@`!%%UD!/:CP!6kHB!5JI4
-$&-U<@fQKTs8P4\!!#.Zrr>pq!!$O*rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL
-!!(oYrrAhn!!"<ss7lTq!!#[dQ2p%#rrQR.5gKB0A,H<,4Sf!WFT)7CPlKm"-2dfG
-U]:A<qu?hQs8U=B!!%`Crr=A<!!(^?rr>pq!!H1!bfi3K!!%`Orr>1\!!'e)rr=AE
-!!0>NrVuuC^]"3:-3#7k!%$%m".oPnhq%f/!!%NGrr=AE!!'e+rr>1[!!?a&s+UFP
-!mL[urVuq.rr3"o-2mlEU]18n;>pOu--ZDhbl.SBA,H9+L&M&PL&:lU,ldokbl@_*
-A,ZH.-1_'9L%bQJ4PB`6!+Z!."=:h_s.fPn!%%XE"$?P`-2miDFT)7?bl7VB;>pOq
-L&M#TZ%_??s1eL4!/:FP!5JI4!875K!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N
-!8k3a"/@.g4T:$7;>gIpKnB@"rrN0#9D=_PjkB_9?iWI<rr@0;!!%-;rrtRc!%#j!
--2[`CA,cK.bl%MA4T>?\^]"35L%50C-2%<>-0F[r!0mE^!@9&h!!#mprrXPI!%%49
-!87>O![[kVrVutQA,ZH0FT4K&!!'d^rr\kn!8lB-!WW4Mr;Qo^,ldokoD\eQrVuq.
-rr3G&!!">-s!7XF-1h/$4T,6[-3!oEg&:sP--ZAg!6kEB!/:=M!2KMn!/:@N!2KMn
-"GQlj@jV'R!/:"D!/:4K!@;jcrr=AE!!';&rsCjg!%$e-s#^8]-2miD4T5<_bl@^X
-rVup\pAY,&rVupErr2sqrVupqq>UL]!%.K,!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+
-[Jp4QpAb1UK)bTF!WW3npQbg@gA_4^!'np2!2KJm!%%RD!3uG$!%%C?!E$W1rrC:A
-!!&8_rr@cP!!%`CrrM89r]L/["E]?O;6fTi!)`@g!%%UD"!mpI-1_'9L&M&R4TD2U
-!!,2.rW!#Qs+UFP!-HZh".oPnhq%f/!!%NHrrC:B!!#.QrrbFa!%%78rsFHBZ2`r4
-!!#l<-2[`D4O!g)!/:CP!-J2>!6kEB!/:=M!6kEB!/:@N"_.N4-&#4o!!+Bfnc&TC
-rW)p[!E#*YrrC:B!!">Crr@cP!!^[Is#^8]-2miD4T5<_bl@]QrVur5pAY0U-2mlG
-L&\pd!!'e0rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL!!(oarr>1V!!#lJs7ZHo
-!!#[dQ2p%#rrQR.5gfT3U\t/o4TA:X!!+D;r;QaCqZ$[D;8<#.!0mH_!@?n-rr@cP
-!!%`?rr@cP!!(7/rr>1W!!+Alr;ZiNrr3'H!!">?rrLfsrVlj[rW!%Ss5kX)!!>@`
-s1eO5!'J^0".oPnhq%f/!!%NHrrC:B!!#.QrrY@`!%%F?!6k3<!Bd.Trr>1\!!(7A
-rrC:B!!%`MrrC:B!!%-=rr>1W!!4HVk4&BNFT)7?g%YLHU](5nA,Q?,L&M&Vbl@]*
-!!">Drr>1\!!^[Is!7XF-1q3;L&M&R-0A_:!!#mkrrPFc-MWl,jjO/2hZ*YkK)aL'
-!WW4mW;csL!!(o`rrJ?Hr?VM-A&!Wqp&>'n!)*'P!9Mr7!al!ndf0<^r;ZsHbl?fO
-rVupqr;QaCr;ZmFA*3Ue!/:CP!%%UD!/:CP!/9h?!/:CP!6jg0!Tk^-!!dV"^Wapa
-s&&aq!0mK_!%%UE!2KGk"S6+'!)`aq!%%UE"3gfF-2RZBPlC[b,ldokdf0EA!!(p-
-rrN0#J,K<Hbl.SB4Sf!Yk(T'!rrY@`!%%F?!6k9>!Bd.Rrr>1\!!(7ArrC:B!!%`M
-rrC:B!!#.Zrr>1Y!!4HVk3i6O49,@-pAY,HrVuqPr;QbNrW!/Hs8P1]!%%UD!'L5\
-#0d,I,ldp-oD\e:rVusr-2mlE^\Ig15QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:N
-hh(m#rrN0#9D=_PjkB_9?iWI@rrL=irVusFbl7VBZ2FY&L&M#O-2mlEL&1fPg"HE*
-L&M&P4T59[^]"35A*s9uPQ1\0li-rprVupEqYpPjrVupqrr2t?rVusFbl.PBUF#m>
-"""!I^]"35-3!oEFSl+>-0G4,!'L5\!2J$C".oPnhq%f/!!%NGrr=AE!!'e2rsFu:
-!!$O/s#^8]-2@K?bl%MC,uMGPrr>pq!!(7@rrXPI!/:=M!6kEB!'L2Z!'L2[!@<Hc
-rrY@`!%%@=!6kEB!+Ys,$=a&9-0G7-49,@-rVlj[rW!/Hs8OAF!'KlQ!2KAj!)`Lj
-!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N!8iD.TDnrm!)*'P!9Mr7!al!neGfQn
--2dfD^\n*3A,QB-Z2Xb'A,ZH/4MUjp#/<8#!5JPfrVup\rVllArVup\m/I-@4L+5P
-!%%UE!/:7K#UKHN-0G7-jsC!,"=7Q3@jV$Q"$HV`L&M&P4T>?\bkqG@4T59[A,ZH.
-A(1G[T)\lKf)GdO!.XnG!)`^q!@>M[rrKl3r;[$as8P1]!%%F?"m.*2!%$=qrrq)0
-Z2aiXrVuq?r;QjF!!#.YrrC:B!!#.Zrr?R.!!%-;rrJmKo)AeS!!">=rrqO2!!">:
-rr3,F,ldokrr3'_!!">Drr>1\!!gaJs#^8]-0G+)!R0^'rr>1Y!!'e.rrPFc-MWl,
-jjO/2hZ*YkK)aL'!WW4mW;csL!!(o.s.B;m!!#[dQ2p%5rrDf_rrQR.5h5l8fd6Rs
-!2KDj!'L5\"XVCms5kX+!!=N04=0q+!i,dLrVup\r;QjF!!"=prrA;_!!">?rr?R.
-!!&8_rrAhe!!#mqrr>pq!!#mprr=AD!!&8^rrAhn!!"=orr\kn!8m&@!;Gs^!WW4M
-qu6]M-2dfF4?Oqe!!]4us#^8]-27E>;>pP(4JV'=s1`%D!%$e-g&:sT-,9K[k&gS&
-!@?n+rrC:B!!#.ZrrBh4!"!/Zs8Uc:49,@koD\nT!!"><rr>pq!!GF!bbHK`!!%`P
-rrY@`!%%UD!'L5\"3gfFL&M&Q4L+nc"GJ-%-0G.*!2KGl!)`Ii!^H`4pm(pAir9#Q
-o)AgL!!'dtrrqQ/UP4EGmJd:N;*<(Mrs7ces3/63KqllarrRm:FP6Zq!!&Xirr[`N
-!8iD.TDnrm!)*'P!9NSI!a(NXo)Ac!!'o*7!)`[p!2KAi!5JI4!'L8\!M^t8!!>@`
-s-3K_!/:@N"!mpI-.Mqp;>pOqL%tZJ^]"354T59[U\Ffi-'\B.!'L5\!/:CO!+Z!.
-!@?n,rrM7.rVurOeGfWC!!(p@rrVpSYOVVo!!%NFrrAhf!!+CNrr3'_!!">>rrBh3
-!<+;C!!">Err>1[!<+;B!!%`NrrC:B!!#.Yrr>po!!+Alqu?_=oD\nT!!"><rrBh.
-!!#.[rrY@`!%%UD!'L5\!6kHB!%%RDr[%LC!6k??!)`[p!2K8f!^H`4pm(pAir9(P
-@,LVV"5a(Y^Zkb!jsBp*![V@JnG`TE!!#.[rrTrh^Y/VeL&NCq!!4HDZ2O\(UP7k0
-rrXPI!6j0s!WW4mW;csL!!(o0rrQ%DKqSGI!!#[dQ2p%5rreqo(m"F`rrQR.5h5l7
-4T5<\U\FcgU](5n-2miEfhqSG!@;jerrC:B!!%`NrrY@`!%$.p"0j-P4SJdWF8u<*
-r;Qi5;'l2A![T.Hqu6Y+rVur5rVll4rVuqPqu6XYrVurBeGfWC!!(p?rrZX/0X(*J
-!WW4Mq>UJj-2ITC-"HQFrrY@`!%%@=!M^t9!!+C@rr3#C-2%<=-2dcCbl.SB;>U:m
-;>1%j4S&LS@fQKTo`"oFq#CFAbl.PD49,@-rVljprVurBrr3#C-27H?4So'XFT)7?
-4SA^U5QE/+Q2p%+rri'%!+=^Xrr_-Y!5Idu!0m9Z!@>t[rr[rT!'L8\!87>O!5I7f
-!'KoS#*f/fPQ1\0rr3'H!!(6srrN0#T;_blIfKK+e,KJH-"HWJ!i%&=`W$$^!!">$
-rrTrhZ24J%fnH^,rrTH&FPQlt!!#[dQ2p%5rs%ot!!!jsp\+Ug?iWIBrr^J--&)$l
-"-b)XFSl(Bfp%1Q;2)d^rrQ[V;>^@qYpC]ke,KI2bk1o9UVHX)!9X:)!9X+W"6NH,
-L&:lOZ"'$prr^Ik!)_5F".oPnhrt(?\,H@.0X(0L!WW4Mq#:BWA,R\T4ET`_rrZ*u
-!'KrS!p3u=qu?dEA(ge[!SL?J!!O[&@fQKkr;QcMrVuqnq>UMk4=0q+![Tsnnc&^E
-,pd[)rrJl@qu?apg&1jPF8u;NrVlu7,lg(*rrV=[-2[`D4JV`P!%%UE!2K5e!^H`4
-pm(pAiVrm[rVut,ht[3RhZ*Ykl2LsA!!"<-4=0t,!@?n!rr[rT!'L8\!2KMn!0l4;
-!'L5\q^)4A"/GnrA,ZH4g&M'u!!(6srrN0#T;_blIfKK+eGfN5rVurBp\tBY,ldq!
-a8Z;),ldoko`"u7-):)3!Tmnj,m+,I-0G.*"MZ5_!2KGk"PG($!-I&s!WW3npQbg@
-li-rer;Zm9O8&GL!al!n`;]l#k(<X+rrCa#rr\kn!8lu>!#YY7!AL_OrrN0#J*Ht8
-k$qoSo)Aj:^P/H,p\tBLP_Fh+rr3&)L$&:4!jPUepAY<Yb`mh*k1fn9U],rIg%kXK
-bfoq`!872J"m2&';2*]urrAhn!!#.RrrPFc-MWl,jl-4>\,64,@,Lh\"5a(Y^Zkb#
-K`D*8rr2tPrVuq.o)AfG!!#.[rrQ%D4PB`;49,A'k5>5\fp&92rr^q:-"HrS"!mpI
-bhE'u!!&Xirr[`N!8l<+!/:CP!6k3;!0mH_!0kP(!/:CP!/:+G"JYqs-0Fn#!JMiq
-!!&8]rr>pq!!#.Yrr?R.!!">$rrN0#9D=_Pjm2pHYPS;$(m"FfrrQR.5_B#jrr\kn
-!8lu>!-%f8!AL_QrrN0#ItI^Frr>1\!!&8UrrPFc-MWl,jl$.=&GlG.@,Ln^"5a(Y
-^Zkb#K`D*8rVlta!!">9rr[rT!'J^0"$?P`L$nsC,ldqhgA_3S!2$4i"+L:NhphZ+
-L&M&PbkM,;4T5<\bfB_c,ldokp&>':-2mlE^\7[-A+os'L&M#PjsC!,!@?n+rr=AD
-!!'djrrN0#9D=_Pjm2pHfD,CJ(m"FhrrQR.5_B#jrr\kn!8lu>!13K]!AL_SrrN0#
-ItI^GrrBh5!!">:rrPFc-MWl,jl$.=3;EOT@,Lt`"5a(Y^Zkb#F8u;'rVluD!!">9
-rr[rT!'KlQ!SP]VrrY@`!/9k@"!mpIbhE'u!!&Xirr[`N!8l<+!/:CP!6k3;!'L5\
-!6iOa!5JL5!+Y^%!'L2[!/:1I!+Ys-"!p&l-2mlEL&M#OU\k)l^]"05jsBs+!/9;0
-!WW3npQbg@li-tZpAb73O8&YR!al!nK)^T*".oPnhrk">\+]k'0X(HT!WW4MK)a-r
-!+Z!.!+YX#!^H`4pm(pAi;WdZpAbD*huDR6!5Idu"$?P`FT)4AUAt9?rVm)a@lu&"
-A+T[!",-^T4T>?_fd.r>r;Qu+49,@-4JVoU!`:8=qYpUo-&)$l#Wr(eL&_1sbi\d%
-"/@.gg&D!R,ldqhr;QeO4T6W-;5<:R!WW4mW;csL!!(p+rr@cP!!(7;rraVJ!%$dK
-rr>pq!!(^Grr@0=!!#.Vrr@cO!!GF;s8Tk5!!&8^rr@0=!!%`OrrAhl!!#mQrrN0#
-'DEgR3U/j0"SMg"(m"Fk?iWHDs+^OUT)\jNk<K#(o`,1MYQ+V&!.TV#cMmkjrVurO
-oD\kW!"/KJ!'/t&!$(Y3"CT+I!5Idu"$?P`L&V)TbU!5hA,cK/KdHWs!@?Furr[rT
-!'L8\",-^T4T59[U\Xrp4TCWG!%$=rrr\Jc!%%=<!^$G_rZqRF!<+8EFT)4A49,A8
-rr3'H!!(7BrrLe8q>^M*kPkS`!2$4i"+L:NhphZ+L&M&PbkM,>,ldokmJd3OL#2h4
-js:!-4SJdT^\\!2-2IQ@^\n-44T,3\F<sf^rr>1Z!!#.[rr?R,!!#.<s3:TI(lqr&
-5_B#jrrA\A!!G!Z!!%M#s3L]F^]"354S&LP5f3R%^Zkb.49,A'beIX6!!"=us8S>Z
-!!#.\rr[rT!'L8\",-^T4T>?bfd-Uu,s3LQ!!1<srVup\r;QjF!!#.Srr>1T!!(^O
-rrY@`!/:FP"!mpIbl7VB4T5?[-2mlE^Zb\!!!&Xirr[`N!8lc8!p4Ser$;A+g&D!O
-L&M&PbkM,C,ldoks8UbLA,-'6Kfk(hs'l$/;?+Cb4Cb/]rrM8Hr]C6ZPih]>!+Z!.
-!2K8f!'L,Y!@?n)rr>1\!!#.Qrr=AC!!">Drr=AC!!">%s3(HE#lm5Bs+^ORT@!W=
-ItI^HrrAhn!!&8Srr>=%!!'durr>1V!",M$s5kU-!%!?CA,ZH4U]:@J!!#.\rrZa2
-!'L8\$p4Li--ZDhPU03,s'u$.!2KPn!/:CP!2K5e!'KuU!%%UD"!mpIL&V)V,ldqh
-s8RfP!!ebgs03jM!/9Y:!WW4mW;csL!!(p9rrJl@q#CClrr2t?rVurBp\tOG!!">F
-s!7XFA,?3*Z2O_)U]2Y>!!">C!!+Ciqu6\N-2RZC-$8q^"Qh!1!'KuT!-J2?!B`LD
-!!'e2rr@cP!!+D!o`"pEqZ$UBrr2uOqZ$UBhZ(h#"(5(.5_B#jrrA\A!!Ej_!!%M#
-s3CWGF<sfSrr>=%!!'durr=AA!!+CNrr2t?rVur5rr39e!!$O/s+LFQ4T>?b49,@D
-s8Skn!!'e0rrhp>!!">ErrXPI!'KoR"?ZYa-&)6?r;QjF!!%`Prs^7S!6kKC,ldq!
-s5mf;rVurOkl1\a!2$4i"+L:NhrF_:^\7^.4T>?`49,@-k55/cbeJjc,ldoks5kX,
-!!';$rr>1\!!8Db-2.B?-0G1+!+Ya'!/:7K!+Z!.!2K;g!SJdu!!0igrVuq?qu6XB
-rVuq_oD\fcq>^W4s8R3;!!(7#rrN0#'DEgR3U/j0#5%s"@,Lul!'l/9LAq@J!!#"A
-5QE_8!!X!an,E@fItI^4rrPFc$MYqJ3T*.&*q]L95c4S^^Zkb",ldrE,lpl<r;Qj]
-!!#mprs=AZ!'L;]K`D*8rr39e!!%-@s%rar;>:(jL&M&RL&[D:!!&edrrY@`!/:+G
-"!mpI^]+6@,ldqhs3(HC-*^;nrVusFUZ_XY!!&Xirr[`N!8li:!/:CP#<[^)b]Egb
-A,cK849,@-s4O0$4=)<M!!=PIs&&aq!%%RC!2KMn"""!I-2%<=A,cK.Z2FY),s4:9
-rVupEqYpQ1rVup\pAY+TrW!"0s1eO5!'L2Z!0mH_!'KiP!+Yj*",6dT-2mlE4T5<\
-Pi)KB!!#[dQ2p%3s7QEn@,Lt`!al!nK)^T*".oPnhrk">^\7^0&:a0JrrN0#ItI^4
-rrPFc-MWl,jl$.=@.sX*5em?V!!'durrXPI!6k6<"!mpIL&M#XK`D*8s8RcQ!'L8\
-#s81fL&_0!!!'e-rs1^e!%%5!!!#.QrrY@`!/:+G"!mpIbl7VG,ldqhs.fDj![V@=
-k5PJ_!2$4i"+L:NhrF_:;>pOqZ2O\(P[ikTrr>1\!!">;!!FVJs5kX,!!%->rr>1\
-!!@?Cs!@UD#>r7[YpBAM-3!oE4T5<\PlC[_Pl:X_-2RWA;>pOqU\FcgPl:Xf-1h0!
-,ldokr;QaZrVuqno)A\9rVuq.rW!!^s4RAO!@>#M!!$NdrrN0#9D=_Pjm2pHhtR0P
-@,Ln^!al!nK)^T*".oPnhrk">TD8Hg&:a0HrrN0#ItI^4rrPFc-MWl,jl$.=5ktB\
-5em<u"5a(Y^Zkb#,ldqhq#:FB!!%`Ors=AZ!'L;]K`D*8rr39e!!%`Qs!7Xkk4\fT
-U](5n4T5<\U\"Kf49,A8p&>+?!!(7Brrj\K!6kIsqu?dEFQVZa!WW4mW;csL!!(p:
-rrA;_!!4Hgk5##W4R`=N4T>?\L&M&T-0G7-U](5r-0G7--2mlEPl:U^A,ZH0^]2(J
-!!Hg3s._^T!!$O+rrBh5!!#mjrrM^;rW!(Cs3/\5rVurBrVlsG!!">9rrCaO!!ah'
-,ldoks)e5?!Fsg^!!#.=rrN0#9D=_Pjm2pH\,$(*@,Lh\!al!nK)bWG!i%l3r;Qhn
-4GDbo!L/;Nrr\kn!8lu>!-nA@!YBkMqYpTs!.TV#]Dhpt!%.K,!9N/=!#YS5!AM:d
-rr_-Y!5Idu"!mpIbkV2?,ldperVm1$!!$O/s+LFQ4T>?e49,A8s8OAF!6k-9!'L/Z
-!%%49"$?P`L%YHJ,ldqhrr3-J!!(7CU](5o4I"h)!WW4mW;csL!!(p9rr>1[!!4HV
-k55/Y4Sf$b,pcEBUWgq.!!#.[rr=AE!!?a2s#g8\!+Z$."$?P`-2dcCPl:XaL&Z8o
-!!9EZ-2[`C4So'X4T5<\^\@a.A,QB.,piEg!0mK_!6kEB!'KiP!0mH_!^-K/rVuuC
--2mlJ^],S[!%$P&!WW3npQbg@li-ruqu?b*ht[3Q?iWI(rrC9ZrrCaO!!&8_rrCaO
-!!&8DrrZa2!)^H0".oPnhrk">./a,I&:a0DrrN0#ItI^4rrPFc-MWl,jl-4>a8>o<
-0X(?Q"5a(Y^Zkb#,ldqhq#:S/!!"=hs8Skn!!^4<s+LFQ4T>?f49,A's8P1]!'KlP
-rrTr4A,Q?,^\e'3L%>6G49,A8p&>+?!!'e5rs9tO!6kK*,ldper;QhP,uNn+!WW4m
-W;csL!!(p8rr>1Z!!+C"r;QaZrW!$_FHk#GrrXPI!'L5[!2KJm!PcDK!!+D.rr2s\
-rVurOrVllArW!"Rs#g8\!%%OC!Bd.RrrAhn!!#mjrr=A;!!#mqrrC:B!!#.Prr>1\
-!!7lSA,ZH.;>pOt-3+!-rVur5i;WiY!)*'P!9NSI!V[0)!!-KbpAY2%!'n6t"S4_U
--)8BX!6kEB!/:FP!6kEB!/9J5"$?P`-,'<\T)\lKkl1Y'rW!!2J+*+2!WW4MK)`I_
-!^H`4pm(pAiVrmkrVusQYPA,"hZ*Ykl2Li3!!(7<rrBh5!!4H/4T5<\4T>?_K`D*8
-rr30b!!#.]s.fPn"!qH24T5<\Pl1O];>pOq-1V!;49,A8p&>+?!!%`PrrsbL!6kKC
-A,ZH.-2p"/,ldokkl1\a!2$4i"+L:Nhr+M8UHJGS!'L5["$?P`-2.?@,ldp-r;QaZ
-rVusr;>pOqA,ZE-4T5<\bl.PAbl.SDL&X:3!!,3Wq#:IZ!!">-p\t4>q#CFA-2mlE
--3!oEbl.SB4S\pWbh;sp!%%UE!mL\>q>^V-s8R3?!!%-!rrN0#9D=_Pjm<!MY5eQ1
-ht6pM?iWI*rr@cP!!">$rrQ[mZ0M>hbl.SBL&V)Pbl.SBL#`18,ldok^&J2,!!(p?
-rrd9@&:a0@rrN0#ItI^4rrPFc-MWl,jl6:CpD<laYP.tuhZ*Ykl2Li3!!(7;rr@cL
-!!+D!rr3(S!!#.\rrY@`!)`aq!+Yg)!@?FsrrAhn!!%`CrrY@`!/:+G"!mpIPlC[b
-,ldqhrr2s\p](;9kl1\a!2$4i"+L:NhqnA6^JXq0!+Z$."!mpI-2.?@,ldp-r;Qc3
-q>^OBk5G;[4T5<\bl.PAU](5pL&X:6!!4HD^\@a.L&M&PA,$!'U](5p-&%'PbQ@hE
--2mlMg&M*7,ldokk55/`ffT67L&_1frW!'Is8V4-qZ$`Os8Tk5!!#.>rrN0#9D=_P
-jm<!K:gi2OrrQR.5e[0tPl:X_4Pp)?@fQKTlMgk.rVuqPrr2uBrVuqPj8T3-!!"=Y
-rr\kn!8m&@"8=3nn+-J[!!%M#s1A:45QE/+Q2p%+rrTAXYOqhshZ*Ykl2Lfp,uO@8
-!L+o/!!,48rVlu)!!&8_rr]MP-*dFK!JMiu!!4HVk55/\;#gSBnG`SQ!!%`Grr[?h
--0G4,!^$H/r;QhP,piNj![Tt(kPkS`!2$4i"+L:Nhq\53U](5n-3!oH,ldp-pAY4@
-!!">Brr>pn!!$O,rr>1\!!(7Arr>pq!!8qq;>pOr;<IcU!TqW)rraVJ!%$e%rr>1\
-!!$O*rr?R.!!&8_rr>1\!!,4RrVlnP-2mlH4TGG'rVup\rr2s\qu?^CrVm!H!!">-
-iVrrZ!)*'P!9NSI!9`kO!al!n]`/(D,s9E.rr>1\!!(7/rrC:B!!%`PrrC:B!!%`5
-rrXPI!'Isp".oPnhs(.Ap[@VO!WW4MK)`I_!^H`4pm(pAir9#Ao)AgL!!'ddrr^#i
-L"Z>&!SQ/trr^#iKqnJD"Qh!1!/9qB",/$`k3`0Kbk_8=k5NTcrrN0#T;_blIfKK+
-j8T1cKtmTd"S3o>!%%XE"!mpI4SJdW,ldokqu6Z2qu?aDk5>5Z4T5<\U]18nL&M&S
--0G6&rVusFU](2tfjc<.L&_1;rVuq.p\t6.r;Zi4qYpQ1rVup\rr2u'r;ZsHFG3R<
-qu?h@s8P4\!!%-?rr@cN!!%->rr=AE!!&eQrrN0#9D=_PjkB_9?iWHWrr>pq!!&8L
-rrC:B!!%`PrrC:B!!%`5rrXPI!'Isp".oPnhq%f/!!%M#s1A:45QE/+Q2p$prr_-Y
-!5Gf="ChE3-0DB1!WW4mW;csL!!(p;rrCaO!!">E49-],!!#.\rrXPI!'KuT"!mpI
--2RWAA,QB-;>^@n4T,9Z-2dfDA,cK.4T,6^,s4:9r;[(4s8P1]!%$e%rr>pq!!#mk
-rr=AE!!(^Orr?R%!!%-?rr=AE!!&8_rrCaM!!(^Nrr?R.!!#mTrrN0#9D=_PjkB_9
-?iWI"rrTrh^]"05g#h]%"6Ri-L&M&SUWgsEmf*:2rVuqPrr2uBrVuqPkPkY.s8UdO
-!!#-prr\kn!8lB-!WW4MhZ!bS@lukNPi2QBP_Iom!JU.Arr\L>Ktm9[!5JMe!87&F
-!87@*!5I@i!^H`4pm(pAdf0F,!!'d=rrXPI!+W/2!WW4mW;csL!!(p;rrCaG!!BM+
-s31HB!'KuT"!mpI-2RWAbl%MA^\e$24SJgU4T59\bU)u`"!uY#U](5nA+op&-2mlE
-^\Ig/L&M&PL&M#OA,$$)4MUjp!%%UE!6kEA!%%UE!'L2Z!2KMn!%$V(!WW3npQbg@
-gA_4^!'n6t"6NHCU]19$^An6[k5Sp;!$sb4qu6\l;>VXEFT;Ap,lf5;rW!'I!!"<B
-qu6]ZPl<cGFP6Tl!6kEB!/:FP!6kEB!/::L!M`Nk49:/hq>U]^@jNE$,pd[4!!$NB
-rr\kn!8lB-!WW4Mhu<^>!<"2F!%#DCrrI4qrr3!]-/JS&@fXaNrs$[n!$rokA,$!)
-ffT96,ln!Up\t7k!<+8F!'K-<!^H`4pm(pAdf0F,!!'d>rrAhn!!'d9rrN0#T;_bl
-IfKK+j8T.6-2ITB-):G="!mpIL%bNK;#gSBqYpP*rVupqqYpOXp](:Vqu6`h@jV!P
-"XR%.s8RfP!!'e-rr[?C!+Ya&"$?Q0g&1jNUHJJT![Tt(qu6a\!!">Crr@cP!!'e3
-rrhI1!!">(rrN0#9D=_PjkB_9?iWI*rrZ*u!%%XE!/:CP!Fn7h!!'e4rr>1V!!:jR
--2%<>-0G1+!FmGQ!!,sMrr2uBrVuqPrr2uBrVuqPr;Qf&-2ITA;>^@oUF#X7!/8,d
-".oPnhq%f/!!%N,rsDU'A*3gkk(Nd]k3;mIbQ*@rrrJ@<hZ![f!!(7@rs'hr^]4=D
-!/:4J#Wr*@s8V4D!/:7K#]p&Vk5YHk!)_YR!^H`4pm(pAdf0F,!!'d>rrZ*u!%"`H
-!WW4mW;csL!!(p9rrM8HrB(*jU\k&mfnG[_rrRn.g%t^K-2mlE^\[s14T5<\;>rZY
-A&%g=#Nhe8;*9Q-k5G;^YpBBIo`"sFbk1o9PihfA!87@qq#:H24?TnGrrSEpZ24J&
-UEq4.iVrrZ!)*'P!9Mr7!al!n^&J'prW!&Es8RfH!!#mqrr>pj!!:CE;>'ti-3!oF
-bWPY#!%%XE!6kEB!/:FP!6kEB!/:CO!2K8g!)`^p!2K2e!/8,d".oPnhq%f/!!%N-
-rrV=/-2[]D@fV5IrrUCEL"lV2ffT6\!6kEA!gE\=rVlmE-2IQB^AqdBrrVd<-2IQA
-,piKh!^$J9i;WjD!%.K,!9MZ/"5a(Y^U!kA49,A'XT&>%!2$4i"+L:Nhn/mgL&M&P
-4Sf!W4T5<\bi\p+k01@8!TrP&rrN0#9D=_PjkB_9?iWI*rrY@`!%%XE!/::M"XRY)
-!!">Err=AE!"EFl^S<mk-0G7-P]T#6rVup\re1@*rr2s\r;ZmF@o<4*!%%XE!6kEB
-!/:FP!6kEB!/:FP!Tk^-!!">E4T5<a-0G7-jsC!,"?_BlF=$kc!/8,d".oPnhq%f/
-!!%N-rrUCE4T#-[ffWdCrrhJ<@s"LBrsuku;2)dbs-.U*;2)dbP_K&8"J^'9L"ZG)
-#JYumk(QZdg%YLNfd.quK`K?qrrP;/k5G;]F9')PrrSEIL&CrO4=0k(!nf\5r;Qh?
-!6jC$!^H`4pm(pAdf0F,!!'d>rrUD,;60]u!!&Xirr[`N!8kEg!%%UE!2KAi!'L5\
-!6g&pp\t9p!)*'P!9Mr7!al!n^&J0s!!">Err@cN!!ssqs+LFQ-0G6\rVup\rVlrP
-A!Hlj!/:CP!/:=M!+Ys-"-iicbl.SB;?$Rqbl.SBL&V)Pbl.SBL&V)PA,ZH.A,cK/
-^ErjZ"53_SA,ZH.A,ZE.o0!!P!2I7-".oPnhq%f/!!%N,rrOJm^\7[-U\uJ?!'JL(
-rrHU0rZqpPA,fCP!$rqFs#_V,rrUD,!<+8F!-J5?!ehqbrZqUG!2K>h#0^T>s+LHs
-rVlmE-2dcEUB$#=rrFDlo)AbR!86<1!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N
-!8kHh!5JL5!%%F?!'L5\!6g&pp\t9p!)*'P!9Mr7!al!n^&J0\!!">Err@cN!!C"9
-s+UFP"3gfF-2mlF4L+V[!0mH_!/:@N!Tk^-!!&enrrC:B!!%`PrrC:B!!%`PrrC:B
-!!%`Prs'hM!'L;]^JXq0!'L8\"!mpI4T#-YL&M&Pbe=#YT)\lKf)GdO!.Wr,"bcpV
--$6ours5k04PBc7PQ3iFrsWuLA+T`l;#lj\bQ*@rrrG5.rr3Wo!/:IQju`Wts8RcQ
-!0mN`PQ3$%rrRlSbl.PB,s;,*!mCXSoD\lG!+YX#!l"^thu<aC!%.K,!9MZ/"5a(Y
-^OlL<rrN0#T;_blIfKK+]`.t/rVuq?q#:=VrVurBK)bTF!WW3npQbg@gA_4^!'n6t
-"!mpI-3!oEL&CuOA,cK.FT)7Bbl@^<qu?a[U\Oihbl.SBL&CrNPl:X_A,ZE-bl.SB
-L&V)Pbl.SBL&V)Pbl.SEL&_1frW!"RUHJGS"=;:ls4RAO!/:=M!/:CP!6i.V".oPn
-hq%f/!!%N+rrJlWrW!!G4I#gE!^%d^rVm(U!2KSo,piNi#3I4/s3(Isrr30b-3+"?
-!+Z!-#P05fs8RcQFT)4@493UurrRlSbl.PB,s;,*!mCX,o`##g!%%7/rr^Ik!5IFk
-!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N!8kHh!%%UE!87/I!'L5\!6g&pp\t9p
-!)*'P!9Mr7!al!n^&J0\!!">Err@cO!!(^Orr>1\!!(7BrrJl@qu?a[g%t^Kbl.SB
-L&CrN;>pOq^]"04bl.SBL&V)Pbl.SBL&V)Pbl.SEL&_1,rVupEqu?aDL&M#Obl.SB
-^\e$2L&M&Pbe=#YT)\lKf)GdO!.Wi)$e^4r,ldp-k5YH-4T,3`bQ(N?bQ)/KrrUCE
-L&V)V4=1%-;#ni<rru=#bl<@sbl.PCF9'PXrrRlSbl.PB,s;,*!mCX,p&>,h!%#k]
-rr^Ik!2JEN!^H`4pm(pAdf0F,!!'dns8L5os8)`s!!&Xirr[`N!8kKi!87>O!'L#U
-!'L5\!82u(p\t9p!)*'P!9Mr7!al!n^&J0\!!">Err>pq!!">Drr>1\!!(7ArrV=m
--2dfE-):A;!6kEB!'L2Z!'L5\!6kEA!6kEB!/:FP!6kEB!/:FP!6kEB",6dTL&(cM
--&)6r!6kEB!6k??!/:CP!6i.V".oPnhq%f/!!%N%rs-;$!)`d?!!)mB"TU[bK`Hi&
-rrUCEL&V)U4=1%-4=0n)#)*&As+LHsrVlqQ!6k-9!egWurVlmE4T,3\bQ)/Hrr[rT
---Z#]"0j-PUYYqO5QE/+Q2p$prr_-Y!5IUp!FmGT!!4HDg#i;7U](2n,uNLu!Du_k
-rrLeMrZqPup&>#%rZqSBg#W/7!!&Xirr[`N!8kHh"(M<WZ1n8#YpBBIK)bQE!WW3n
-pQbg@gA_4^!'n6t"!mpI-3!oE4T5<\;>pLp4T5<\bkqDAk(P,\!!+D.r;Qc@rVup\
-r;QaZrVurBrVm#_,ldq!rr2uBrVuqPrr2uBrW!%Ss8RfN!!,3Wq>UH=rVuq?qu6YM
-rVurB^&J2,!!(p-rrN0#J)UD.^P2Oa#4j,es3(HhqLo':s+LH,q>UN?!/:FP"["+2
-s#_V)rs"/WPlHF;bl.PCK`K?irrRlSbl.PB,piKh!l"_hp\t>*!'Js,rr]"r-*c8*
-!^H`4pm(pAdf0F,!!'dqrrP:_4T:$:49-\Okl1Zn-2miE,uNP!!b23mr;R#T,pdYe
-;#k,#rs(Xd@tf"N-/%D[!WW4mW;csL!!(ogrrLg8p&>'Tb_#lfrrN0#9D=_PjkB_9
-?iWI*rrXPI!%%XE!'L5\!/:CO!-J2?!2KAi!V8GQ!!%`NrrC:B!!#.Zrr@cP!!&8]
-rrXPI!)`aq!6kEB!/:FP!6kEB",6dTPl:X`4MUam!6kHB"=4$J--Z;e!+Z!.!2I7-
-".oPnhq%f/!!%N-rrP:_^\[s6494's,s:u&!mCXdr;Qqqbl>leL&V)V4=1%-;#ni<
-rrus5bl<@sbl.PCK`K?irrRlSbl.PB4=0q*!egWLq#:CX!'KlQ"*=MhbhN.!5QE/+
-Q2p$prr_-Y!5I[r!gE[pr;Qh_!'KKF!B_[^rrhq'!!#.ZrrQ$t^]+67@fX:>rrRlS
-L&V)R^Aq-mrrN0#T;_blIfKK+K)_JC!WW3npQbg@gA_4^!'n6t"!mpI-3!oE4T5<\
-L&M#OL&M&UL&_1,PhH$8!-J2?!/:@N!6kEB!'L2Z!5JL5!BfuQrrfSQ!!">ErrC:B
-!!%`PrrC:B!!n;Ys5kU-!%!?trs.\?,lggBs'u$."XTrDs5m2W!!%_drr\kn!8lB-
-!WW4MiVrtD!'L/Y#Nd<Ys8OAkk5G;aUEt$^js;>Orrj\ps3(Isrr30b-3+"0!-J/=
-"skSqs+LHsrVlqQ!6k-9!egWurVlq@!2KMm!^%dkq>UM+!+YX#"/>iYo@j3G5QE/+
-Q2p$prr_-Y!5I[r!^$J,qu6^D-0G+)!87,H!TrPBrrG5.p&>$Fp&>$Fp&>3#,lhF$
-4T59]js<.grrUjR;>L4m;'l/?!@9&RrrN0#T;_blIfKK+K)_JC!WW3npQbg@gA_4^
-!'n6t"!mpI-3!oE4T5<\L&M#O^]"374TA:X!!">E4T,6[U\t,lbl.SB4T#-Y-2mlH
--"CF2qu?hos8U=B!!%`PrrC:B!!%`Prr?R-!!FT14=)<Q!!FVJs5kX+!<+;B!!%_d
-rr\kn!8lB-!WW4Mi;X`Y!'I%=s8SiV!/:IQPQ3i.s8U:h!5JR6@fU$<rsN<:L&]?s
-;?-7f4=1",![RiArr345!-J8@K`K?qrrRlSbk:u;K`K?qrs7a5--ZDh@fU$<rs/.L
-PlLcg!%%Kcrr34WL&_28,pfhnbhrF%5QE/+Q2p$prr_-Y!5I[r!`8rmqu6]Mbl.PG
-Yrj<4,uNh&rr@cO,n#G,bU!5h,piTk,uO[A#3KDA!$rqUrVm+";;"em!$ua]rrkMI
-Z2Z+4rVlqo!/:@N!@9&_rrFDljo5A^!2$4i"+L:Nhh(m#rrN0#9D=_PjkB_9?iWI*
-rrXPI!%%XE!)`^q!6kEA!6kEB!^-K[pAb1Uqu6Z?rVup\qu6Yko`,(Vs8U=B!!%`P
-rrC:B!!%`Orr>1T!!&enrrJl@p&G(i^&J2,!!(p-rrN0#J)C8-49,B\,m"&mFT)4E
-@fRf;4=(!&rVm'a!$s`R!+Z$."sj6qL&X7]rr35I,lf5R,lhHSrrRlSbl.PCK`K?i
-rrRlSbl%JFUEq3K,lg(+rrpUH4TGFYq#CC@rr3*I-3+"0p](<<i;WjD!%.K,!9MZ/
-"5a(Y^ZPP!YlH(lg%bRQUAuToKjt*/k5PB#;#i_4Kff?Fo7\J:Kn]R,,s;5-js:";
-KnVVhA,cK64=):NKleU@L%tZJ^]+66,s;/+!egWhr;Qd[-1h-<@fV5ErrN0#T;_bl
-IfKK+dJj70L&O18FMHc6!JQcorrKBhqYpQXre1@7p&>0WP_Fgdnc&WDo?[F<!!#[d
-Q2p%#rrQR.5e[1"@fQL+rr2tPrVurBr;QsI!!#.]juiG>!)`Um!6kEB!0m?[!M^t<
-!!c@`!!">Fs4RAO!5JO5!87>O!5JI3!JMir!!,3sr;QfA4So*],p`NkKt[KgT)\lK
-f)GdO!.Wl*!P`aU49:/uqu6i7F?D[-g&(dPUJX-NU](2sflU)ds-/68rreQK4Cc/)
-rrTrhoDS[j^P2:PrrTrhoDAOjfjd-,Pl1Obo7`G/s-3;4rr3+TL&_1fpk8_>i;WjD
-!%.K,!9MZ/"5a(Y^ZGJ#F<pne,uKohrVlu^,pi0^rs,;!;?-Zk!)`^p"["*ns#_V+
-rrsc3s8PprPl:Ue493.rs#^9krr3&D,pi3`!@9l,rrRlSbl%JB493V"rrh";,li&J
-rrN0#T;_blIfKK+df0BD,lmoj!WW41kPkVG;9]%>!@9kbrrUCj4T#-YU\lD<L%kTP
-F<po5,lf78o`"u&!6idh!WW3npQbg@gA_4^!'n3s!McFgrr_CG-$9%a"*>hObl7VC
-^LR4)!JT5%rrR9g;>:(tPYjP*FP6]oF?Hi-rrTHZU\t,nZ%\tKrs$5l@m"jtg%bRR
-fnE9cKp:`Q@thSq".oPnhq%f/!!%M#s1A:45QE/+Q2p$prr_-Y!5IUp%H_aY,ldok
-;=jhfPQ6sGrrtS3s8Pprbl.PF^P2^f4=0t+"XQ;2s!8uhrs-:=;?-YY-0G1+!@9&a
-rrFE.rVlqQ!6kB@!^$J,p\tDl4?Oo9UZMLW!!&Xirr[`N!8l9*"2=g^U]18q^H;L<
-kl1^<!6kHB!JQcqrr^Ik!'L2Z#ep@%k5XR+!5J@0#dF@l^]4=u!%%=<"(M<2bg6:j
-!!#[dQ2p%#rrQR.5_B#jrr\kn!8lB-!WW4MK)`I_!^H`4pm(pAdf0F,!!'dmrsIn`
-@jM+;s8PprFSpgr,ll0h,pi?d!B_\,rrj]2s3(I?qu6gG4TGFD-2dcD4=0Y"!@9l,
-rrRlSbl%JB493Utrr^Ik!5I[r!WW4mW;csL!!(p*rrQ[1U\t,njs;>;rrRlSbhN.#
-KdA#F4T,3\;#nB1rrV=/;>L4n4=0.grrR9BPkb7^ffT6\!6idh!WW3npQbg@gA_4^
-!%<I!LAq@J!!(p-rrN0#ItI^4rrPFc-MWl,jjO/2hZ*YkhZ!fO491WG4951'"3gck
--2@K@4=0t+"XQ;2bQ*@orrj\ps8P2-r;Qd[-1q3<,s;/+!egWur;Qd[-1_';UB"fd
-rrN0#T;_blIfKK+e,KJ3!6k??!b4@GrVm#8Ki*Q=qYpY^@q1c&rs4<U!-Eqds+Q^8
-rreQrA!H-Srs+dQs1`YQPih`?"]57^bU#CLrrFDlr;Qd[-2IQA;'l/?!mCXuq>UZP
-,pe8!!6idh!WW3npQbg@gA_4n!"ab^LAq=9!!(RL!WW4MK)`I_!^H`4pm(pAdf0F,
-!!'dsrrUk"A,?30^Aq.2493V#rrFDlq#:@W-2miI,s;4O!)`Xn"XQ;2s#_V*rrG5.
-o`"q<4T59]PQ6F8rrFDlq#:?Ir;QiB!'KED!WW4mW;csL!!(p*rrR9BA+fj&@fZKS
-!<?!qrt2L^!$rok--ZB8,lf5;bl8tOrr34u,lf5;!%"E>rs1_L@fRf$!%$=nrrlo-
-s8OB-rVlrC!)`[o!b25SoD\l6!0m<Z#0^T>s+LHsci4%H!)*'P!9Mr7"-3E^pO`F#
-rrREF(tJWf!!%M#s1A:45QE/+Q2p$prr_-Y!5I^s"6LmUoDAOlYlJnGK`IA8rs"_&
-s8P1]g&:pSUEu]84=0t+"XQ;2s!8uhrs$4<;?-YY-2dcD4=0Y"!@9l,rrUjR;>pLr
-js<.crrFDlr;Qhn!+Y0k!WW4mW;csL!!(p*rs&'@!$tL,g%t^cF9#hBs8QR/A,lSk
-,pfhrs03jrs8RcQbl7VZ,s;5-fd.rLs8Th[!5JR649-\Bs8QR/;=skh,s;/+!mCXu
-r;QhP!2K2d"7mfbk4S`UK`K?CrrN0#9D=_PjkB_:VZ6_KK)^W+!al!^ec,[N!.TV#
-]Dhpt!%.K,!9MZ/"5a(Y^ZPOu;#i`@rVm,b493.rf`4/5rs-ao-3+"?!+Z!-"]59Q
-s#_V+rrsc3s8PprU](2s;#mBks#_V*rrG5.o`"q<4T,3\4=/5NrrQ[1U\Xok;#ljZ
-rrP:_^ZPOt!!&Xirr[`N!8l6)!p3u=rW!!GA&&!B!@9&irru=Hk5TN'Pl:Ud@jTh.
-K`K?rrrsc3s8QR/U](2t^Aq.2s#^:drVlmE-1q3<,s;/+!mCXur;QhP!/:(F!^$I:
-o`"uH!6idh!WW3npQbg@gA_8q!!&@;s+gUU(][+WrrN0#ItI^4rrPFc-MWl,jjO/2
-hZ*Ykjo5WL!$sa]Ki',rA,cK6F9"Fub`jCRU]19549/m+^LI7Rs8Ppr;0;j<,s;5-
-fd-W?beI!T;?$Rr4=0q*!B_\#rrFE.r;R#,!%"Da@fSXirs_gObl@^r,liYCUHANd
-jo5A^!2$4i"+L:Nhp;<1ULPSr!!%`Qs1\PUr;QtT!0mLG-0G%'!egWurr3-J4TGF-
--2[]G,piTk4=0q*!B_\#rrFE.rVlrC!/:@N!egW.p&>(U!+YX#!egWuci4%H!)*'P
-!9Mr7"8<?,5_B#lrr^"9!/K,)!WW4MK)`I_!^H`4pm(pAdf0F,!!'dprrHUUrW!!G
-4JViS!JMj!!!+C@r;Qq1,ldokFT2:Ffd-VEk5Q`)rr32U;'c2B-&)<t!Dt0@rrGtC
-o`"q<;>^@sYpBAM,uOU?!`:8frr32H4='t--&(F[!WW4mW;csL!!(p#rs.\?!!'e6
-K`Lrq"9=/U,pi?d!egWurr3-J4TGF-4T#-^494(74=0q*!B_\#rrFE.rVlrC!/:@N
-!egWLp\t?K49/m^rrRlSbg6:j!!#[dQ2p%"rrZX/!9\t6M>mZk!!(p,rrN0#ItI^4
-rrPFc-MWl,jjO/2hZ*Ykir9,6bfo5ErrUltg%bRJbfoq`!87,H!p7_Ng]%?!bi\Ns
-!p7_Nir9&[!2$4i"+L:Nhp_T+Pe[(p#)*&!s+LGMqLo$ds!8udrrRlSbl7VG,s;5-
-,s;))"Zue<s#_V*rrG5.o`"q<4T59]bQ)/NrrR9BbkV2?bU!7Cnc&ZE!6idh!WW3n
-pQbg@g&D/`!!&(3s,-gYpD<lieGfRM!.TV#]Dhpt!%.K,!9MZ/"5a(Y^OlL<rrN0#
-T;_blIfKK+eGfTo!'L,X#0['Es.]R9q#:@W-2dcIk+hPJK`K?rrrj]2s8OAkqu6gG
--3+!--2dcD4=0Y"!@9l+rrFE.r;Qg\-0G%'"0j-uU[\9bK`K?CrrN0#9D=_Pjk9Y:
-pFlRapO`F'rr\;^!2n?H!WW4MK)`I_!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N
-!8l9*![RiAqu6kB!0mNG,piKh#%Jsas'l&(rVm(D!2KRJ!6kHB"slD3s%rd$rVm):
-!'L;]4=0q*!B_\#rrFE.r;Qg\-0G4,!qR^#q>UQM,pge(rrRlSbg6:j!!#[dQ2p%!
-rr]G)!0;a3N;j"S(]Z8=rrN0#ItI^4rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL
-!!(p*rsGM$!+X7Qs4Ll^-3!oG@fU$<rt;(,-3+#-,pge8s3)c8s8RcQFT2:P,s;5-
-^AoS(s8V4D!3uS(4=0q*!B_\#rrFE.r;R%t!'KlQo/m#Jrr34fL%G?E490L#bQ[V<
-s7:r/qYpVN!6idh!WW3npQbg@fDbq,!"db6s,I$\BE/%9e,KIL!.TV#]Dhpt!%.K,
-!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+df0WK,ldok,ldp-bl.PH49-Zi,lf78rr3S*
-,pbZ9,pge8s1\O6--ZB84T>?cUEq3K4=);-rr3!]-2dcD4=0Y"!@9l*rrus5,s3IR
-A,ZE1493V*g%YONL&_1s!'L,X!egWuci4%H!)*'P!9Mi4"Le@2+Qn@VO8f<;!!#:4
-rrN0#ItI^4rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL!!(p(rs%VM;*6sNU\auo
-ULQDKPihoD"m0nh4ET`ars#`<A&&%tPl:Uck&`^JFQWQ%!L/<9rrJ@<o`"rGPktC_
-Yu*V\U\t,pP_J`/oD""C^]4?*Kp;H6!l'H\ci4%H!)*'P!9Mf3"HNN_3;8%)OoGQf
-!!"/1df0@K!.TV#]Dhpt!%.K,!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+K)_JC!WW3n
-pQbg@ec,bc!!"_1K)_&7"HNN_&D,>0!WW4MK)`I_!^H`4pm(pAdf0F,!!'ccs4I>Q
-!!&Xirr[`N!8iD.TDnrm!)*'P!9Mc2"ntOf!#X%6s-<TeBE/#<\'Y-V!!%M#s1A:4
-5QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:Nhh(m#rrN0#9D=_PjjX50E;fh<@,HS9
-RK!G_+92Bacd2Um!!%M#s1A:45QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:Nhh(m#
-rrN0#9D=_PjjO//Qi6sd#\^Dns.95lhiBJj!!,(BcMmqG!$HkY]0HE/!%.K,!9MZ/
-"5a(Y^OlL<rrN0#T;_blIfKK+K)_JC!WW3npQbg@dJj7);#L@q&7C9F^SJUGQ[^^f
-!!*q'bl7YKJcN7[!%.K,!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+K)_JC!WW3npQbg@
-ci4$l:kA\9!!4!upWNR:QhE[r-Gh)0BD@bmjjO/2hZ*YkK)aL'!WW4mW;csL!!(o.
-s.B;m!!#[dQ2p$krrVAM5_9!/!!4!N^V'SuQFN4\jjO/2hZ*YkK)aL'!WW4mW;csL
-!!(o.s.B;m!!#[dQ2p$frrCZ&^SS[FpUL6TQFN4\jjO/2k5YLSK)aO("5a(YT;_bl
-IfKK+K)_JC!WW3npQbg@K)^H&T`9V0\<[-VdJj7J!.TV#g&D0+!!'L,rr[`N!8iD.
-TDnrm!)*'P!9Jh4K)_MDJsNp4!9MW.![%IkK)aO("+L:Nc`$jGIfKK+K)_JC!WW3n
-pQbg@K)^H&T`9V0\<[-VdJj;n!!'ccs4dPUpD<lQVuHjK!!(o.s.B;m!!#[dQ2p#u
-s+:9Ds+6QHQ2p$orrgpZ!$L`^s4mVVBE/%)VuHjK!!(o.s.B;m!!#[dQ2p#us+:9D
-s+6QHQ2p$nrr\Sf!*FjQh>[Sd!!#Qerr[`N!2kF`T>(F-!)*'P!9Jh4K)_MDJsNp4
-!9MQ,"@)qe37ic^iVs)UGQ7^TkGJ7ZIt@Zh!!#[dQ2p#us+:9Ds+6QHQ2p$mrs%@/
-!!!:<f7O%ars%YI+92BQ\#'*)^OcHS!!$L&Q2p#us+:9&s+:9FrrMk=JcOU,!D)CK
-rrC[E^AtZnE2[^UHM3X)jb!Mas+:9&s.KAma%1d^i;`lqT9]EVnq*0tQ2p#us+:9&
-s+:9BrrM;t]70fVr;Zh9Z@;nYa-6N'nq*0tQ2p#us+:9&s+:9&s4.,LTD\`ihh(mE
-rrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.s2"^8nq*0tQ2p#us+:9&s+:9&s4.,L
-TD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.s2"^8nq*0tQ2p#us+:9&
-s+:9&s4.,LTD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.s2"^8nq*0t
-Q2p#us+:9&s+:9&s4.,LTD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.
-s2"^8nq*0tQ2p#us+:9&s+:9&s4.,LTD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$
-rrA\i!!(o.s2"^8nq*0tQ2p#us+:9&s+:9&s4.,LTD\`ihh(mErrDtKjdbE4pk&Nt
-s+:9&s+::$rrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&
-s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9Q
-rrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i
-!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.
-s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&
-s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&
-s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&
-s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9Q
-rrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i
-!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.
-s+:9&s+:9&s+:9&s+:9XrrC+:rrA\i!!(pSrrMT?K)^H&K)^H&K)^H&K)^H&]Dhto
-(hhP#rrA\i!!(pUrr]H,#g\,&K)^H&K)^H&K)^H&K)`I_#PT&8!%;N1?Msj.G(3U2
-!!#iIs+:9&s+:9&s+:9&s+:9]rrA,M!!(>ss+:9&s+:9&s+:9&s+:9]rrMj2o)Jbe
-K)^H&K)^H&K)^H&K)^H&\,QGho)Jd:K)^H&K)^H&K)^H&K)^H&\,QL')"dk/:kJ_!
-s+:9&s+:9&s+:9&s0_k,O7`JQc[u1Ks+:9&s+:9&s+:9&s0_k-pDEW)!)S:IK)^H&
-K)^H&K)^H&K)`1W!0?jS!7-8sK)^H&K)^H&K)^H&K)`1W!V[H,!!#iIs+:9&s+:9&
-s+:9&s+:9UrrA,U!!(>ss+:9&s+:9&s+:9&s+:9UrrMj2qZ$UmK)^H&K)^H&K)^H&
-K)^H&YQ"T`qZ$WBK)^H&K)^H&K)^H&K)^H&YQ"Xt)#XF7:kJ_!s+:9&s+:9&s+:9&
-s/l;$O8T%Yc[u1Ks+:9&s+:9&s+:9&s/l;(pD<l1:kJ_!s+:9&s+:9&s+:9&s/Z/%
-NrT1+K)^H&K)^H&K)^H&K)^H&X8`7q(f5haK)^H&K)^H&K)^H&K)_hM!KYQYs+:9&
-s+:9&s+:9&s+:9&s+:9&s+:9&s+:9&s+:9ds+8"U^AuT3s+:9&s+:9&s+:93rr>$1
-!1NrgBS-89s+:9&s+:9&s,m<]hgtis!!"-ns+:9&s+:9&s+:95rr_-Y!-j+1T>(Fu
-!$HmnK)^H&K)^H&K)^u5"5a(YT7[*8rrQR.+G0WFs+:9&s+:9&s,m<`hZ*YKK)_JC
-!al!NK)^H&K)^H&K)^H&OoGO@!!&XCs.B;m?iV=$s+:9&s+:9&s+:95rr_-Y!2"lC
-TDnt#!$HmnK)^H&K)^H&K)^u5"5a(YT7[*8rrQR.+G0WFs+:9&s+:9&s,m<`hZ*YK
-K)_JC!al!NK)^H&K)^H&K)^H&OoGO@!!&XCs.B;m?iV=$s+:9&s+:9&s+:95rr_-Y
-!2"lCTDnt#!$HmnK)^H&K)^H&K)^u5"5a(YT7[*8rrQR.+G0WFs+:9&s+:9&s,m<`
-hZ*YKK)_JC!al!NK)^H&K)^H&K)^H&OoGO@!!&XCs.B;m?iUu:YlN%#s+:9&s+:9&
-s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm
-^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XC
-s.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&
-K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfn
-K)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lC
-TDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&
-s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXN
-s+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8
-rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YK[Jp8lUTjb!UQiUp!al!ApQbfnK)^H&
-K)^H&K)^H&SGr]K!!&YVrr[s;L$$e_"$?P`FOC*hYrqq1!Frn1rrZa2!'J-u!al!A
-pQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrr@cP!!4HVk0s>4,ldp-dJj1mq#CFmk3`0N
-49,@-r;QkQ,pf>0rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKli-rIqu?dE;5;\A
-"!mpI4OX60bkD)<--YfW"$?P`-2miDg&:sO--Q;i?iUl7Q2nXNs+:9&s+:9&s+:9@
-rr_-Y!2&TW!'L&W!@<HOrrXPI!'J^0!6kEB"!p&l-2dfE-1gU*"$?P`-2miDbl.SC
--0EGO!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrr>1U!!,3sg&D.#!!#.0rrC:B
-!!%`PrrJl@rVuq.n,EJP!!">CrrZ*u!+X4P!al!ApQbfnK)^H&K)^H&K)^H&SGr]K
-!!&YWrrtRc!%"mI-2RZBL"cP/,ldp-df0<^rVuqPrVm#E,ldokn,EJP!!">BrrLg+
-b5VNN!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlL_49,@-s8V4k-2[`CA*X'pbh;Xg
-"!mpI4OX60L&M&PPl1O`49,@-n,EJP!!"=^rrQR.'DIdm^4QB:s+:9&s+:9&s.')k
-hZ*YKli.&L!!">CrrI3fr;Zh>q#:?/re1BJk55/a;#gU$s5q(M^\[s4,ldp-q>UQ@
-P_HmLrrV>:^\Ig1UP7k%rr@cP!!(7@rrY@`!%%LA"3cIQbkh>A49,@-r;QhnKsCLS
-"m0nh4Cb/arrTrhk4nrWPa(J5!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrrY@`
-!%%OB!R*\)!!';$rrJ?1qu?dE;;(sK!87>O!^'=+rVusFFSu.@,ldp-qu6\N-2dfE
--&)?u"Qh!1!5JC1"-`cc-1h-:L&M&Pbl.PEfd-Uu-2miFo4'*F!!,3er;Qj]!!">D
-rrB>'!!(^MrrJl@qu@!KL&_1X!!">:qYpY-!!#m^rrQR.'DIdm^4QB:s+:9&s+:9&
-s.')khZ*YKli.&L!!">@rr>1\!!#.Zrr?R(!!FV1s8U=:!!$O-rrXPI!'L2Z!'L&W
-"*FSCPl:X_4So'X-2mlEbk1o8L&M&Pbl7VCbU*5g!/:FP!R)kc!!';&rrY@`!%%UD
-!/:CP!/:CO!2K;h!d+H>rVuq.qu6Z2rVupEli.#o!#,*m!5='bK)^H&K)^H&K)_A@
-"5a(YTBlLZ49,@-q>UKX-2mlEU]18nPl1U]-2dfGFT;Bbo`,!,rr3'H!!#.[rr?R'
-!!C"9jsC!,!-J/=!/:CP!'KlQ!+Z!."Ja2*;'l2A!%%UD!'L#V!%%UD"$?P`-2miD
-L&M&PU]18ofd6Ut![TrTrW!!^s.fMm!3uJ%!)`^q!+Y?p!al!ApQbfnK)^H&K)^H&
-K)^H&SGr]K!!&YWrrY@`!%%F?!/:CP!'L8\!%%UE!/:FP!-J2?"$HV`bkqGC4GAK!
-rVupqrr3'H!!#.\rrAhm!!?)n^HDJq"&]*uL&M&Q-/&7s!%%UE!2K/c!'KuU!@>M[
-rr?R-!!?`GUF#m>!0mK_"$?P`-2miDL&M&Pbl7VB;>pOqA,cK4YpC]ks8Psq!!#.[
-rrBh5!!+D.li.#o!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLZ49,@-q#:T],ldok
-s8S>_!!IEDs1_G0!!AJcs31EA!/:CO"!mpI-3!oH,ldp-rr2s\rVuq.rr3,m,ldok
-rr2s\rVupqrr2tPrVupEo)A\Pp](=Wbl.PA-2mlEPlC[_^]"354T>?_49,@-rVljp
-rW!&Es8Tk5!!#.UrrLe!rVuqPrr2sqrVupqlMgon!#,*m!5='bK)^H&K)^H&K)_A@
-"5a(YTBlLZ49,@-p\tXJ!!">Fs#^8]-1dloqu?^ZrVlsG!!#.Zrr>1\!"R6Qs!7XF
-4TGHD,ldokoDS[hA,ZH1bl@^<r;Zr7s8ODE!!%`Drr>1Y!!4H/Pl1O]U](5n4T,3]
-,ldokrr3'_!!">Drr>1\!!CIFs&&aq!5J7-!+Z!."""!I^\n-4^Zth#?iUl7Q2nXN
-s+:9&s+:9&s+:9@rr_-Y!2&TW"$?P`-27EH,ldoks8OAF!$rrh!!+C"r;QjF!!">C
-rr@cP!"$mLs!7XF4TGH*rVup\r;QbNrVurBrr2sqrW!!^s-3K_!%%18"$?P`-2u*g
-k5,)XL&M&PL&CrQ49,@-rr3'_!!">Drr>1\!!^[Is!7XF-2%9=o-OA9!d+H>rVupq
-l2Lfm!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLZ49,@-q#:T],ldoks8ODA!!+C"
-qYpXD!!">Crr@cP!"$mLs!7XF4TGG8rVuqPr;QbNrVurBrr2u5r;Zkn4T5<\L%50F
-,ldp-pAY+TrVurBr;Qj]!!">ErrY@`!%%UD!'L5\!mL\grVuq?o`"oFrW!!G^ErjZ
-!5Idu!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrrY@`!%%F?!/:CP"&]*u-2[`D
-4JV]O"!mpI-2dcCFT)7Hbl@\h!!#.]s.fPn!/:@N!/:CP!6kEA!+Z!.!%%UE!%%.7
-"!mpI4SJdTA,ZH.bl%JC49,@-rr3'_!!">Drr>1\!!:CEbl.SBL%G<E4T5<\-2mlE
-;<\#]?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2&TW"!mpI-2IQAbU*5g"/Gnr-2mlF
-;8;i)"!mpI-2dcC-2mlNg&M'u!!#.]s31HB!'L2Z"$?P`-2dcDjsBm)!/9qB"!mpI
-4SJdTL&M&PFT)4Bjs:!-4T>?_49,@-rVlj[rW!#Ds4RAO!+YX#!2KAj!5Iat!al!A
-pQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrrXPI!%%LA!R)kh!!#.\rr>pq!!%-<rs<cn
--0G7-,ldokrVlk^rVupErr3'H!!#.\rr=AE!!&enrr?R.!!#mnrr?R,!!">6rrXPI
-!'KuT!87>O"XVCms78AP!!&8_rrY@`!%%UD!'L5\#L*5J,ldok^]"07k$pNKqu6XY
-qu?^okPkTk!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLW-2mlFA&&#e!i'6Or;Zi4
-rr2u5r;[!I;2']d-2mlHPlLb0rW!$H4?Oqg!!%`PrrXPI!'L8\!/:@O!^&Rkr;Zi4
-qu6]Z-2dfDFRT53,ldp-p&>"hrW!$H4?Oqh!!">DrrY@`!%%UD!'L5\"3gfFL&CuV
-;2'^6,ldokqu6Z$qu?`3kPkTk!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLW-1_*:
-U\t,lA+fm*-0G7--2.B>4T59^,ldp-rVlj[p](;9q>UG:rVusFk3r<P,ldp-p&>'G
--27H?Z2O\)49,@-rVlj[rVurBrr2s\pAb1>qYpOXrVup\k5PKj!#,*m!5='bK)^H&
-K)^H&K)_A@"5a(YTBlLWFS,V7-):>:!L+o+!!,48rr2sEp](:Vr;QjF!!$O-rrM7E
-q>^M*q#:=krVuq.mf*Ad!!$O$rrKk\qZ$XCU\t,o49,@DrVm"S!!">-rVljpq#CFm
-g%t^K-2mlEUZVRX?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2&QV!l&4kq>^RC;;(^D
-#F&(J,pbZq^\n*3-2moC,lp,mqu6bn4Ak8<rr@cO,lplXq#:N[,ldokk3`0LKn]*t
-!Tmnj,lqN<qu6cB4?UCVrrRmOZ2=P%UJ^t9!Frn?rrAhn!!#.CrrQR.'DIdm^4QB:
-s+:9&s+:9&s.')khZ*YKkPkb$Ki'sdKtlgN"!mpI-/8G"A,ZH.A%2I<k4\fT4T5<\
-UZMLW?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%:2"!mpI-/8G"-2mlE^T@G8^]"35
--05(-?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%:2"!mpI-/AM#Pl:X_4KJJ^;>pOq
-FQEH'?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%:2"!mpI-/AM#4T5<\UTFJ!js:!-
--0F:g!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y2rrXPI!%$J$!87>O!%"]G!0mH_
-!'K<A!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y2rrXPI!%$J$!0mH_!+W)0!)`^q
-!2JTS!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y2rrZ*u!+Xjb"Qh!1!5GT7"0hh+
--0"q+?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%71!L/i'rrV>:^T%57^P1h0rrQR.
-'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K
-!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&
-K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!A
-pQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y
-!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&
-s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y;rr^rubiXNW
-ec,\Y!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT@*Z>KdH]u![Tt6k5PJE^]+66;'k&u
-!l$&*qu6YMrZqSBg%PFHUHJN%!E%PErrLeMrZqPSci4&S!#,*m!5='bK)^H&K)^H&
-K)_A@"5a(YT@3`G@fRfsKnWAM!0l^I!nelRrr3!r-/SY(bU!85r;R"3!)\Gl,ph7>
-rs4;Y-$4iN!%$=ors.4'-$4iN!'JX.!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y?
-rr^pS4S/OO"3`&;k3;mIbQ*@NrrfSQ!!(7ArrTq8;?$RsbU$-^rr_C04S/RP!i#`m
-q>ULn!5JO5!egW=dJj8U!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT@<fAK`Hi(rrQ[1
-U\k&kk4\fTbl%JBbQ*@irrCaGrrC:8rrlm4-"?r!rVlq/!5JL4!`8sNqYpV]!/:@N
-!@9&grrVd<4T59]bQ'cQrrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKe,KK6!+Yp+
-!qXY-rVlk-r?VH.r;R>];'c2g;;(tH,lf5;L&Y!rrVm(s4='tR;<IlX#DFJq@jM+$
-;>:(pbU$cjK`K?qrrFDlr;QhP!0m?[!qX1Ar;QdD-1h-<^Aq-YrrQR.'DIdm^4QB:
-s+:9&s+:9&s.')khZ*YKe,KR5,lhGip\tI\!+U_:490L&rt3!l-$4i_,ph6/F9#0l
-^]-DBrr3XR!%!>Q@fRh.s8Rd!4?S=O49/7Rrs&)Ws8RcQbl.PB,s;,*!mCXuoD\m,
-!'KoR"6M]G^X<&_?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%^>#GWRF!$sa]g&1jO
-@fV5]rs(Xdg&M(7!5JO5#,;0.s3(Isrr33c-3+"u!'KlPrs,;!;?-ZM!'L5[![T/T
-p&>)I!6kEA!@9l+rrUCE4S/RS492Y[rreQK,pf>5rrQR.'DIdm^4QB:s+:9&s+:9&
-s.')khZ*YKd/O034=0t,!BeU*rrFDlr;Qu9!-J7o!'L2Z"bj5]bQ*@rrrtS3s8R0@
-U\t,r494(7K`InHrrQ$tbk:u;K`K?qrrFE.r;QiB!'KoR!^$Hmp&>2*4?NU+bgHFl
-?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%O9$,:R.!%$=uf`3>rKa)W!4TD/VL&(`M
-bQ*@rrrtS3s8P1]g&1jSF9')UK`K?qrrRlSbk:u;K`K?qrrFE.r;QiB!'KuT"7nVT
-A+BR#UAuUfrrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKb5VZU!)`d?!!)jA"B#2Q
-!/:7K!mCXurr3-a-3+!--2[]HK`Hi,K`K?qrrRlSbk:u;K`K?qrrFE.r;QiB!/:1I
-"3`%kA+0F!@fW:PrrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKe,KG24Sf!\,piT8
-!'L&V!i#aLq>UN?!/:FP#!=43s#^;7r;QtT!5JPf!6kEA!egWup&>)I!6kEA!@9&i
-rrSDbL%tZMYpBCFo`"p_r;QhP!/8l$!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y?
-rrOJH^\e$8o-HO!s!8uhrs%VMg&K7r;>gFt4Al.&!/:FP#!=43s)\79r;Qs`!87C+
-!6kEA!egWup&>)I!6kEA!`8sNrVlq/!6k9="3`&;Z1\+ubU$-arrQ[1UXK/D?iUl7
-Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%a?",-_$^\n*:@fV5_s%rc\rVm+4!/:IQ4=/5N
-rs$4<;?+i?FT2:E4=1%-^ApCprs-:=4TGG8!6kEA!egWup&>)I!6kEA!i#a*rr3&D
-,s;#'"7mfbbk(i9,pge7rrUCj-.2_o?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%^>
-$"Er84EQ9e,lg(,rs7a5!+X6f@fSXjrt2L9-'ZW<,ph7Ef`3=?Z2Zp4rr3F;!'I%#
-KdA%[s8RcQbl.PCK`K?irrRlSbl%JG49/m8UEooFrr35I,uO^BF9!Wa49/7XrrFDl
-rr38!!%"DaPU-=)dJj8U!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT@*Z?KdA&E!!+C"
-r;QuS;'c2B,uOU?!O4cd!!,4+rr314,lhHT;'l2@#)+?'!$tLqrr3%R--Z>f!ehrE
-p&>)I--Z8d"_/hY!%"E=rrpUm;?-Ynpa,q>!@9&jrrJl@rVus]Z-`LP?iUl7Q2nXN
-s+:9&s+:9&s+:9@rr_-Y!2%U;"6RhOg%YLIbfok^!nkfNqYpQKp\t<=bi[^\!p7_N
-iVru4bh:;A!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&
-s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.
-'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K
-!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&
-K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!A
-pQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y
-!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&
-s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7
-Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(Y
-T7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&
-K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m
-!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YK
-K)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&
-s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm
-^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XC
-s.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&
-K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfn
-K)^H&K)^H&K)^H&SGr]K!!%7q^Rr7B8,s=tQ2nXNs+:9&s+:9&s+:9@rrCr.!1Elf
-'DIdm^4QB:s+:9&s+:9&s-s#g."VGg!!"\HQ2nXNs+:9&s+:9&s+:9?rrDfd^Aru%
-E!0#@!"rnaDua@LDub%SQ2nXNs+:9&s+:9&s+:92rrB=<Q2hp(!!#g:Q32(9!%O_/
-!5='bK)^H&K)^H&K)^l2!3s8(r;Zgjad)oHrVuq2UQtnoK)^H&K)^H&K)^H&NrK*a
-^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&
-K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"
-r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&
-NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtno
-K)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK+F^?,:n
-!-63Cr;Zh<UZDLDK)^H&K)^H&K)^H&K)`smr;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&
-K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&
-K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&
-K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#
-K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>
-!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhI
-aoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8
-r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&
-K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&
-K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&
-K)^H&K)^H&W;cn9Xi8'R!!%Mjs8;otItI]Ps+:9&s+:9&s+:9Mrr=dg!!%5bs8;ot
-?cBb[Y(H\*s+:9&s+:9&s+::6rrBsN!!#C.s1\O7"Ik#CK)^H&K)^H&K)^H&l2LaF
-^&S.0aoB'T!#^CgK)^H&K)^H&K)^H&l2LaU^An9Kn&bS0$,6H?$A/;0s+:9&s+:9&
-s+::8rrA\i!!&q9^AuEsrrI?F^]4?NK)^H&K)^H&K)^H&K)b*8!2'2i!8iY5!Ul`$
-^Aph(!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&
-s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-n
-s+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`i
-hh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&
-s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+
-!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`
-TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&
-s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mN
-rr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9Z
-rrC[9^B"#RrrA\i!!(oAs6@?!a3Xbc@/^-++G0WFs+:9&s+:9&s1/.1Va0DF!D)D#
-rrA\i!!(oErrVqM.-LX4#^H*lrr?I+!!"-ns+:9&s+:9&s+:9_rrM:Rj8]3'n'V.8
-TD\`ihjXQGa!g!K!*I\L!+>d+!$HmnK)^H&K)^H&K)`L`#,`"4!"`PAlG!F/!!$uc
-rrA\i!!(oGrr@<C!!+L/lG!J*-ia7Ve,KDUrVup@K)^H&NW0&i;<EK1K)^H&[JpEV
-#QOj4n)s]P5QDqSrrA\i!!(oHrreYg!!nACrr_Ei!-$Ee!+>d+!$HmnK)aX+!b4@-
-p&>)g4L)m*"(M<2;?$Rqbk(i8g#dndK)^H&b5VV=0E;Bfjo5F<!!)K9rrA\i!!(oI
-rrh3b!%?I\rrP.[8CRS=@/^-++G0WFs5!\W@fQKTpAY9K,ldqua8Z.SrW!-bs5kU-
---Z)_"(M<WZ%E"-s+:9orr[`N!/KY8"1J71T@3`>TD\`ihjscL5QCf)jSo<q!!qK3
-rr?I+!!"-ns+::,rrY@`!%%@=!+Z!.!6iL`!+Z!.!i,dLrVusFZ2">!A,ZH.4G*Tb
-s+:9prr_]q!''$="SW`5!-$D:!)NOn!,oDt!f+P2l2Ljp!!%9(rr]_1!#X48!&4BP
-!"cSg!gg[RK)_qP"$?P`-2.?@,ldok`r?5h!!">Fs1eL4!@?Fqrr@0>!!%_)s+:9&
-s31KFT)\khir9"fJcPcM!Z5nFm/I/q!!)3Arr?_a!<)s!.%c+kY5\Sd!!">=rrXPI
-!%#\c!0mH_!/:FP!2KJm!'L/Y!3uJ&!+UW\K)^H&bPqZh!!r>XrrL/2JcPcM!>rlE
-rrP.[5iDYCT.kisrVusikCW`<rrY@`!%%C>!6kEB!%#\c"$?P`-2dcCU\t/mA,ZE.
-jsC!,!'Gl5K)^H&b5VNF!&0$)hu<bmO!su-!-mr3!Z1oVK)ad/#OfEW(]XOI[t=Xb
-rrY@`!%%C>!6kEB!'KZK!R06RrrBh5!!$O+rr?R-!!%`Prr>1\!!+D.m/I+>fn06U
-s+::0rrPFc5_B$krre)_!!&ASrrN0#ItI^Vrrqk!!!!;^K)`Rb!Mac7491*6rrY@`
-!%%C>!6kEB"[)hbk(USFrsb`Wk5YHY!!';(k.cVbpAY--re1BJk4S`S;>pOq^\[s1
-4T,6]U]4j&!!';!rrCaOK`RFkqu7"F!!%`Qk&`^34JRN.K)^H&l2LfM!'l/9g]%E.
-+92])nG`Oi!.TV#g]%AZ!!#99s1nX8UF#^9!2KPn"$?P`-27E>bl.SH4TFOi!!'e1
-rrnVe!%%ZurW!!^;'l2A!@;jarrJ?1qu?dE;;(aE!5JL5!)`Rl!V7W:!!+C"r;Zh-
-q>UK14So*Z4L+kb"XO-K-)2da!!%+ms+:9&s6BUc5QF'$s4[JT^An7!nG`Oi!.TV#
-gA_8"!!&@;s2+d9Z1e4uL&V)S,ldokq>UNYbbP.;!^-LIrVup\qYpOArVuuCbk;#:
-A,Q?,A,$$)-0G%'!)`^q!5J=/!R)kd!!#.WrrAhg!!';'rr=A>!!+D.K)^H&K)b0:
-!^H`NK)aO(")%Z7fCAkB!!%M#s4[JTpF$"aK)`^f!'L5\#:2KBF<pnePlC[h,ldp-
-s8UceKfo>\qu?g]s5kX,!!%-=rr@cP!!5:_bk1r9^]+65Pl1U]-2dfDFSc";Z2O_'
-;>1"iZ24M%-/&.p!SJdu!<"5C!!#.\rr=AB!!+AlrVuq_K)^H&K)b0:!^H`NK)aO(
-"5a(YJ+<O?!!%M#s4RDSLB%=pK)`ag"=4$J-1h-9!p2U-rVm$I!!"<--1q6?;?-ZM
-rVusFg&:pN-2mlGU]8R9!!>?;Kk()^!)`aq!%%UE!/:FP!-J2?!'L,X!'L5\!5J4,
-!/:=N!3uA"!)`^q#\3#ss03jM!%%XE!%%OC#!DMK,ldpeK)^H&K)b0:!^H`NK)aL'
-!\aU>nc&Xj!.TV#g&D0C!!&@;s24j:4T5<];;(aE!%%+7!/:FP!'L5\!)`aq!/:CP
-"""!Ibl%MAL&M#U,ldoks8S>_!!IEDs1_G0!!&8\rrAhn!!$O$rr>1[!!+CiqYpQK
-rW!*as8V4k-2mlE;?$Rq-2dfD4T>?_,ldp-K)^H&K)b0:!^H`NK)aL'!al!Vnc&Xj
-!.TV#f`)!a!.TV#_uB_Ar;ZmF;8;u-!%%F@"XPHWFG4i9!!%`PrrAhm!!C"9s!@XE
-!/:FP"!mpI4T,3Z4T5<dbl9d*!%%634T#0Z4So'\,ldokk4S`S4So*Y4So'XL&M&S
-Z+j-^r;ZjEg&D!O-2dfD^]+68,ldp-K)^H&K)b0:!^H`NK)aL'!al!Nnc&Xj!.TV#
-f`)!q!.TV#_Z'V2qZ$Xok5>5Z-2mlI,s5\%bl%J@bl.SBL&M#O;>pOs4TCZF!!">D
-rrXPI!%%RC!/:CP#0d)n!!";kqu?aDL&1fLL&M&PA+fj%A,-*)A,H9+4T5<\-2[`E
--"H*9rr=AE!!#.\rrC:B!!#-5s+:9&s6K[d5QF'$s4I>Q?iV>>rrN0#J'7iqg!#/(
-UY1q4![%JmK)`[e!P_M0!!+C@rVlsG!!#.UrrC:B!!%`OrrBh4!!/iWrVuqPrVlsG
-!!">Crr@cP!!:CE-2ITB-&)0p"nO#?!%%71rr?R-!!-Sor;Zi&r;QaZq>^RCA*3^h
-!Tk^-!!&8_rrC:B!!#-5s+:9&s6K[d5QF'crrR:)U\k&nUEr%UVZ-^*!$Lh3!WW4M
-c2Rgt4So*Z4L+b_!l'H(U&P0:!.TV#^]+AM@jV'R#J^<=js:!-4SSjUbl.SBL&CrN
-A,ZH.-2mlE-2dcF,ldokr;Qb=rW!#Ds!@RC!Bd.Orr?R.!!%`Hrr@0>!!>@`s&&aq
-!@?n,rr>1Z!!4I#k5,)Xbl%MAbl7VBbl.SB4G*Tbs+:::rrPFc5f3O'K`D*!qu6aE
-!!#lnrrQR.+S#I5!!%Mnrr@cJ!!$O,rrCaO!!'d.rrO;CItI^6rrM7ErW!$ts8U=B
-!!$O'rrC:B!!#.ZrrM7.qZ$VMr;QjF!!">Crr=AE!!:jR-2mlF;8;i)"Qh!1!%%@=
-!2KJm!'L8\!V7W:!!#.[rr>1\!!,3Wp\t6;rVupErVm#_,ldp-K)^H&K)b0:!^H`N
-_Z'T^rVuqnrVllArVupEVZ-^*!$Lh3!WW4Mc2RctrW)pDr;Zh>rVlkmrVuq_UAk9;
-!.TV#_uBbjbl%J@bl.SE4TGH*rVuqPp\t6;rVup\qu6Y+qu?^Cqu6aE!!">DrrA;_
-!!=PIs&&aq!-J,<#';.;k5YHkrVuqPp\t5gr;Zg[r;Qc%r;Zh-rr2t_rVusrk5>5_
-PU.W\s31HB!%%RC"!mpI-%c/Ks+:::rrPFc5f<U%g&1mNA,ZE-L&CuObbtIB?iV>>
-rrN0#J'IuqK`D*8rr3"o-2mlEg&:pP;'e>urrO;CItI^=rrfS,!$tMAK`F77!!?*u
-s31HB!/:1I!6kEB!'L/Y!Tk^,!!%-<rr=AE!!=N04=0q+",6dT^\n-9,uKAM4=0t,
-#*f/f,ldokp\t5gr;ZjEbkqD?A,QB-U]18n-2mlJ,s6m8;'l2A!`B!ArVupEr;QaC
-rVurOK)^H&K)b3;!^H`N_uB_$r;Zg[rVlj[r;Zh^VuHg+!$Lh3!WW4Mc2Rm"!!#.[
-rrgOl!!%_ArrO;CItI^=rr@cH!!C"9s+UFP!/:1I!6kEB!'L,X!-J2?!@?n*rr=A>
-!!#.[rr?R&!!=P0s+UFP!/:4J!Tk^-!!+Ciq>UFWr;Zr7s8Ske!!9G*bl.SB4T,3Z
-4T5<\b_#kHs+::;rrPFc5f<U%A,QB--2miD-2dfDL%#$Cfho#errQR.+S#I5!!%Mn
-rr[rT!'L2Z"$?P`L%kTPUP7D$s5qPLXT&>E!.TV#`;]l04S\sX-):J>!2KMn!2K8f
-"!mpI4So'X;>pOqA,?3*-27H?4T#-ZPU6,*#X$f?s#^8]-0G"&!6kEB!@>tbrrL=i
-rVuqPrr3#64S\sX-*dIL"!mpI4T,3ZFT)7?b_#kHs+::;rrPFc5f<U%4T#0]g&M)e
-qu?^ZqYpT2A,[bT;5=*i#UKHs^N;Ra4GCZP!al!Nnc&Xj!.W8n",-^T4T59_o-FA:
-L&V)`fd.r>s8Th6!'Kj_,ldokbkqD@^LR6h!E#Wjrrc1]^]0#d,m;Hl;'i"6rrQ%D
-L"H>++96nCs2+d:PW\mj!^(Ser;Qh?4Ce'a"/@t@bkqDDjs:!--0G((!%%UEr?VJ,
-Pkb7`PYjOh,s6:arVlss!!$O&rrY@`-,90R"MZ5_-,9BX#GYck,pbZ`U\t,o;#ho;
-r;Ql6,lg&Zs+:9&s6K[d5QF'err=AC!!B"rs'ts,!%%OB!+Yj*"$HV`bl.SB-2[`C
-4N%1#?iV>>rrN0#J'IuqK`D*8rr3#64T5<\g&D!UK`D*8s8RfP!!">C!!#.Zrr?R*
-!!bXds-*K`,piHh"[&"L!%$=rrr\Jc!%$7s![%JmK)_>?!+Z!.!+Yj)"!mpI-0>.-
-Pa(h?!6k'7!p54!mJd42k5,)Yk0/GWK)^H&lMgoN!'nL&!6k<?$"O#8,ldok!!">C
-rr>1[!!+AlrW!#Ds313;!-H0Z!al!Nnc&Xj!.W8n!/:CP![TrTr;Zh>rVm(U!!#.]
-s31??!%%UE!6kHB!'L2[!@9&k!!:CEL&1iQ,ldokg&:sO4T,3],ldp-fDbmp!.TV#
-S,WI7rVur5q>UOC!!"<ss+:9&s,R*\5QF'frs=AZ!$s`-!'L:rrVuqPrVurBrr2tP
-rW!6e^]1P=!%%[Fbl%MG-$4i'!!"=`rrQR.+S#I5!!%Mnrr@cJ!!+D.rVm(3!!#.]
-s31B@#aG?O!!%`Qs+UFP#s?!&YlFbMs8RfO!!bX$bQ%Vhs'u$.!2KPn!/:CP!2J0G
-![%JmK)_A@!0mH_!'L&V"!mpI-%c/Ks+:92rrPFc5fE[749,@DK`D*!s'l$/-1`D_
-!0mK_"!mpI4T>?_K`D*!rr3'H!!$O.rrhp>!!(6^rrQR.+S#I5!!%Mnrr@cI!!+Ci
-rr30b!!#.]s1eL4%!;OL49,A8s8OAF!'L8\#)*$W-3+"!rW!@:s8U:C!%%[:,ldok
-rr3'H!!#.4rrO;CItI]jrr>1\!!&ehrrXPI!%!6sK)^H&NrK/G!'nL&"=4$JFNj^a
-&>LNO!+Z$k!!$O/s.]Po-0G4,",-^T4T>?_,ldqhrVlsG!!%_lrrQR.+S#I5!!%Mn
-rr[rT!%%Vu!H]Xe!"(%Ds8P1]!-J8@L&M&P-3!oN49,A8s.]Po-0G4,$&&?Z4TGG8
-!!">DrrlmpU]:@JrW!"Rs-3K_!2J-F![%JmK)_DA!87>O!%%C>"!mpI-%c/Ks+:92
-rrPFc5fNa'U](5s^],S[!'L5\$bu^O!!">Fs+LFQ-2miGK`D*8rr3'H!!%`OrrY@`
-!/8Dl!al!Nnc&Xj!.W8n",-^T4T,3ZPl:XhFT;A'!!%`Qs+UFP!-J5?#Wr(eL&Zi,
-!%%UD$&&?Z4TGG8!!#.Urs1^e!%%5!!!#.3rrO;CItI]krrA;_!!$O'rrXPI!%!6s
-K)^H&NrK/G!'nO'##P@#-3+!Bqu@-Os8S;`!%$e-K`D*8rVlu7!!#.\rrXPI!/:CO
-"$?P`KuO&n?iV>>rrN0#J'IuqK`D*8qu7(7!!#.]s#^8]L&_1,rVurBrr36d!!%`Q
-K`D*8rVm2=!!#.]s+LFQ4SSjUU](5n4T5<\UXfAG+96nCs.0/mjs:!-^\@a1;#gT+
-K)^H&K)^l2!^H`N`W$,g!!#.]s-3E]"(VB2g&:sTPlHF;!%%UD"3^`F-3!oH,ldq!
-rVlsG!!&8&rrQR.+S#I5!!%Mnrr[rT!'L2Z&\gF.!)`dr49,A8s8QR/!%$e,rs1^e
-!+Z%_!!">Drs?mL!%%[FK`D*8pAY+Tqu?^CeGfRm!.TV#SGrZQKtm<\!L/h#s+:9&
-s,I$[5QF'hrs7a5!!%-@s5kX+!!'e5rrj\K!)`d2rVur5rr3>1!!">-s8OAF!/:FP
-!+Z!.!85?k!al!Nnc&Xj!.W8n#_`6Y4TEX#@jV'R%);iB49,A's8P1]!%%UD"]57"
-4TE1q!!'e5rs>q1!%$e-K`D*8pAY--qu?_NeGfRm!.TV#K)^H&K)^H&QN%"O!'nR(
-!6kEB!0mK_!'L5\!%%UD%8d**-3*uk!!"<eKi'/q!"!08s!7XF,pbZ"rVupq`;]mH
-!$Lh3!WW4Mc2RctrVupEq>^Mjrr39e!!#.]s'l$/-2miQK`D*!s8OAF!$u`@;'l2A
-"_7Rd!!#.Srr>pq!!"=orrO;CItI]Ps+:9&s+:9:rrPFc5fWg(bl.SBbl7VBFT)7?
-L&M#OL&M&Rbl=I4!!=PIs!@I@!@?mHrrQR.+S#I5!!%Mnrr@cJ!!,3srVm0d!!#mr
-s+LFQ-2miJPQ1\0s8Skg!!O\KK`D*8p&>#erVuqPe,KIl!.TV#K)^H&K)^H&QN%"O
-!'nR("5*YS-2miGjs:!ir;R&b,ldqhs8T>Mr;['bF?BOLs8ODA!!,sM_uBdG!$Lh3
-!WW4Mc2Rgt-2dfG,pd'9qu6u-,pfhrs-*K`;>pLsf`2!urr3#(-2dfM4EN[c-3'_?
-!)`Fh"&T$u-.;ep+96nCs8;ltPb[jM!L0A,rrL@+K)^H&K)^H&hu<aC!'nO'!jRI4
-r;Qf[bkh>@Yrma<rr^K0PhH'9$^BfRs!7XFFHhKDftm[i?iV>>rrN0#J'@omk5ENn
-rrSF=k5>5\P_Ifgrr^K0PhH'9"dJ0Ls-/61rrhI1!!%`$rrO;CJ%GX\g!&a]!R/dG
-rrY@`!-Io6"$?P`FOU6l,lf7Ro)A`q4T$K+A&!WqK)^H&K)bWG!^H`NU&P3@!!%_d
-rrQR.+S#I5!!%M.rrcg3!%$dUrrO;CJ%P^_K`D*8q#:DL,uOI;"(M<2;;qNW,ldp-
-p&>+?!!#.2rrC:B!!%`Drr=A@!!,sZU]1F+,s9DmrrIgqg]%B<;'f(ks+:9grrPFc
-5b\2[,ldq!^&J.A!$Lh3!WW4MNW0),!!$NVrrO;CJ%P^\4T5<\PktC[Z2O_'A,?3*
-^]"35-/nk+,ldp-p&>+?!!#.2rrAhn!!%`ErrC:;!!+Cih>[Q=Kqm9"!p533q>UGZ
-rVup\ao;I-!!#mZrrTrh^\Rm0;>pOqFFsOEs2=p=5QF'CrrXPI!/8,d!al!Nnc&Xj
-!.U%/!2KMn!5Hq]![%Jm]DhkQrVup\qYpOXrVupEqYpP*rVup\iVs!+!!"><rrXPI
-!'Jd2!/:CP!0m*T!6kEB"!p&l-2dfE-1g!n"!mpIPh?!<,ldq0qYpPLrVupEb5VIV
-rVupEkl1XtrVurOqYpOXrVuq.K)^H&`;]m(!'m7X"!mpIKt[Kf?iV>>rrN0#IuaO2
-;#gSBd/O.i!.VW\!87;N!87;M!2KGl!878L!%%UE!2JNQ"!mpI-2%9?,ldp-eGfN&
-rVurBoD\g7rVuqPrr3"o-2mlEA)I:dbl.SB4PB`7bl.SB4So'\ju`ViUW`Z<o-O>8
-!6j^-!/:CP!/::L"L06Q-/!nMK)`dh!^H`NU&P3@!!&e-rrQR.+S#I5!!%M/rrY@`
-!-HTf![%Jm])MaVrVuq_r;QaZqu?`3r;Qo^,ldoki;Wm*!!"><rrXPI!'Jd2!/:CP
-!6k'7!5JL5!/:CO"O&.l!%$P&!6kEB!%$=u!6kEB!%%F?!R0]Krr?R,!!&8Jrr@cP
-!!$O(rrC8ps+:9frrPFc5b\2ZUHE&!rrQR.+S#I5!!%M/rrUD,;:#7D+96o&rr@cP
-!!#.[rrM7.qu?_Nr;Qb]rVupqi;Wm*!!">BrrQ\-g&D!R,ldp-eGfMYrVurBoD\fE
-rVuq_r;Qj]!!">%rrXPI!%$:t"!mpI-0"q*g"G?a!3uD$!+Y9n!6kEB!+UW\K)`@\
-!^H`NK)aL'!al!Nnc&Xj!.TV#f`)!q!.VT["Qh!1!%%UD!0m?\!-J/=!'L5\!2KAi
-"3cIQbkh>H^Qdm\s5p(u4ET`brrXPI!%%RC"$?P`-3!oH,ldp-q>UQ@P_HmFrrBh5
-K`Kg$rs.\.4=):9PW\pF!86uD!/:CP!6kB@"$?P`-3!oFUSIhg"PK#L4I#[A"3d!`
-^\e$5@jNE`rW)mC!E&"VrrAhnK`Jm^rrqP,4?R,Kr;Qk/,pb\Q!<"2E;<IlX!gJDl
-q>UTNUP5K*qu7"F!!%`Qk&`^34JV3A!V7W7!!#.Urrp/I4?R`#rVm#_;'dMNrW)mC
-!+Z$.!p52jrVlq/;;(gG!el?jqu6Ykre1?eK)^H&hZ!XB!'l/9f`)"\!$Lh3!WW4M
-K)aL'![%Jm\c2XlrVur5rr2s\qZ$UYrVllNrVupEqu6`h@jV'R!BdXcrs$4<!%$<.
--2dfD-3!oH,ldokrVlj[rVupErr3'H!!#.YrrIg"r;ZjEL&(`LKdHWs!Bd.SrrI3f
-p](:?o)A]DrVurBrVm;Z,ldoks8RcQ!)^L.qu?^or;QeO-2dfE-&)?u!5J1,!-J2>
-!H]Xc!!+BUqYpSk-2[`G-&)C!^\%R2FT;A_!!">BrrKAer;ZjEA,Q?1,ldokUF#g<
-!-IQ,!+Z!."ApHF!%%F?!+Ym+"?`shs)do6%);iB49,@Ys8Ppr!'L/Y"&T$u4T59\
-F=$hb!@;6-s+::/rrPFc5_B$grrQR.+S#I5!!%M#s4I>Q+96o%rr@cP!!IEDs5kX)
-!!">Drr?R.!!$O,rrL=iq#CE"rr2tPrVupEq>^kes8OAF!'L;]ff]35!/:FP"!mpI
-4T,3Z4S\sWFSu.>ff]$0!-J2>!+Y^&!%%49!/:CP!6kHB!R)kh!!@rTs#fuT!87AO
-!'L&W"*FSC^\%R,FT2:?4SSmV4T,3ZU\FfjFT9,K!!@?Cs#g8\!6kEA!+Yg)!'L5[
-!%%@>!@?mqrrBh5!!4J/4T5<\bkh>>A,$$*Z2\q=!"$F?s!7XF-3*ukrVur5rVm#_
-,ldokrr2s\p](:VK)^H&iVrsE!'l/9f`)"\!$Lh3!WW4MK)aL'![%Jm\c2Z_rW!$_
-s8S>_!!FT1!!">DrraVJ!%$e*rr>1V!!">Err@cL!!">E!""AZs!7XF4TEVOr;Zh-
-rVlsG!!#.[rr?R'!!'e5rrM^;r;ZmF4=0t,!'L8\!/:@O"!p&l-2dfD-1_'9A,ZH2
-UWes"-2mlE-3!oE4Sf$X-2mlHbl@]QpAbE4s8Rd8,piKir]C0Xrr2t.r;cgCr;Zi4
-rr3#P-2mlG,s3LQ!!YRcs+NQ]-2diC49/7XrrbFa!%$e,rrA;X!!%`Prr=AB!!+Al
-rVuq_mJd/KrW!"Rs'u$.!/:=M!0mE^!^&RkrW!.Vs8QRk,piKir]C1&rr30K!!">F
-s+UFP!)`^p!-J2?"(VB2A,QE,-2dfD^OlK;s5O%[5QF'$s4I>Q?iV>>rrN0#ItI^Q
-rrO;CJ%5L_,ldoks8P4\!!-S>rW!&Es8Skn!!#morr?R-!!?`GUF#m>"-iicL&:oP
-A&$7e!!n;Ys!7XF4MN3@!!$O,rrXPI!'L8\!2KJm"&Yi.4T5<\;?$Rq;>gIsL&_1,
-rVuqPrr2sErVuq_rVlk-rVupEo)A\PpAb4?^]+654T,6^-$7gorW!#Ds.fMm"&Yi.
-4T5<\;>^@q,ldokqu6Z2rVusFU]18n4T5<\L&V)P;>pOqA,cK1YpC]kqu6aE!!">A
-rrY@`!%%XE!Tk^-!!>?Jb[^VP!%%XE!%%OC#!DMK,ldpemf*9@rW!$_s8S>_!!#mn
-rr=AE!!&enrr[s$4PBZ4!6kEB!'L,X$RGcQ4TGHD,ldokk5PA\-2mlGg&Jhd!!+C@
-rr2s\rVuqPK)^H&ir9'F!'l/9f`)"\!$Lh3!WW4MK)aL'![%Jm\GlPNrW!#7jsC!,
-!Palu!!@rTs&&aq!5JI3!%%UE!0mK_!5JL5"$HV`L&CuRU]:A<rW!.Vs8OAF!%%OC
-!-J,<"!mpI4T>?\4T5<\A,cK5o-FA:-3+"[r;Zhmrr2tPrW!&Es8Skn!!%`MrrXPI
-!'KiP!'L#V!BeU)rr>1\!!FUls8RfP!!:CE4T5<\A,cK2o-FA:-2[]E,ldokqu6Xn
-rW!)+s8SiVr;ZrQs8Tk5!!#.QrrXPI!%%LA"!mpI-3!oEFT)7?4T59[;>pOtbl@\h
-r;Zg[rr3'H!!#.MrrM7.rW!%qs8U=B!!">Crr@cP!!$O$rrC:B!!#.YrrCaO!!#.\
-rr>pq!!@rTs.fPn"&]*u;>pOuZ2aj!4T,6[fn06Us5O%[5QF'$s4I>Q?iV>>rrN0#
-ItI^QrrO;CJ%5LY^]"36FG9\o!^-M,rW!."s5kU-!'L2Z!2KMn!'L2Z"sj6L-3+"!
-rVuq?rVm'a!%$e-s!@LA!)`Um$RGcQ4TGHD,ldokoDS[hA,ZH0bl;2P!!%->rr@cP
-!!^[Is'l$/-2RWD,ldp-o)A\PqZ$[D4I#aC!'L5\!3uP'$K`W74TFOi!!">:rVlk-
-rVurBr;Qj]!!">BrrsbL!'L:8-2[`CA,cK.;>pOq^[qI-49,@-qYpXD!!">Err=AE
-!!';&rrAhn!!@rTs!@UD!5JO5"!mpI4R`:M;>gIp4T6Z+!!+D.rVm!H!!">:oD\n=
-!!#.YrrC:B!!#.\rrBh5!!=PIs&&aq$)@P#,ldp-s+Mcs!!$M\s+::0rrPFc5_B$g
-rrQR.+S#I5!!%M#s4I>Q+96o$rrqO2!!#,-rW!4gs8OAF!%%YerVuq_r;QbNrVuqP
-r;Qs`!!">Fs+UFP!6kB@!6kEA!%%F@!0mB\"sj6L4TGH*rVup\r;QbNrW!/Hs!7XF
--0G1+!/:CP#0d,I49,@-qYpXD!!#.PrrY@`!%%Wg!9X+W"$?P`-2[]Ebl@^erVup\
-r;QbNrVurBr;Qj]!!">CrrC:B!!+Alqu?a[U](2p,ldoko)AeS!!">ArrXPI!%%XE
-"!mpI-2dcCbl.SEL&_0!rVup\rr2uBrVup\nc&XP4S/URU]18nbl.SBA+KX%,ldp-
-qu6Z?rVup\rVlj[rW!5=js:!--3+"hrVusF-2[`D4JRN.K)ad/!^H`NK)aL'!al!N
-nc&Xj!.TV#f`)!q!.VKX!%%LB!%%XE#UKHN-.sRE!%%OB!'L5\!6kB@#!;kc-3+"!
-rVurBq#:?<qu?^CrVusFbl%JF,ldp-s8RfP!!%`Nrr@cP!!UUH,ldokr;QbNrW!/H
-s8P1]!'L,X"!mpI4S&LS,ldp-p&>+V!!">?rr@cP!!%`Nrr@cP!!(7@rr>1\!!(^N
-rrC:=!!,3Wr;Qc@rVuq?o)A\PrVurOqu6jH!!">Fs31HB!'L2Z!6kEB",6d;-2mlE
-PlC[_bl.SB4RrFObjtf7A,cK.L&M&P^[hC,,ldokqu6Z?rVup\rVlk^rVut/A,ZH1
-L&_1sq#CFXUOrMts5*bW5QF'$s4I>Q?iV>>rrN0#ItI^QrrO;CJ%,FXA,?6+FT2:?
-;>pOq;>pOqFSl(<A,ZH.bl%JF49,@-s8RfP!!(7<rrC:A!!7964T5<]-1h*8"sj6L
-4TGGVrVuqPr;QbNrW!,Gs!7XF-2dcCPl:Xebl@]*!!">ArrXPI!'KiP"!mpI4SA^V
-49,@-q#:>hrVuqPr;QbNrVurBr;QaZrVurBrVllAqZ$Xo^\[s1bl.SBL%>6D4T5<\
-bkqDI,ldoks8V4-!!#.ZrrC:B!!7lSbl%MAbl7VBbl.SB4RrFOL&M&R,s5'(K`TDm
-rVupErr2tPrVurBo)Ae<!!">BrrC:B!!#.ZrrXPI!%%UE!%%XE!6k<?!E$U`s+::+
-rrPFc5j&(Jg!&.9rrV>:Pg'./k02'?rrSsLg"HB,?iV>>rrN0#J*-b4bfo59rrTrh
-Z-<4Lg!%\2rrJ@<f`)!q!.VKX!2KGl!@?n-rr@cM!!+D.qu6YMrVuq?rVm,b,ldp-
-s8RfP!!(7<rrC:B!!H1!s4J^t!!#mprrsbL!'L;]bl.SB4T,3d49,@-s8P1]!%$e+
-rrC:B!!B"rs'u$.!0mE]"S3o>!'KiP"!mpI4SA^V49,@-q#:?<rVup\r;Qj]!!">B
-rr>1\!!(7ArrC:A!!-T_q#:?IrVuq.o)A\PrVurBqu6aE!!">ErrXPI!%%RC!+Z!.
-!mL\grVupErVm#_,ldp-nc&S8rVuqPqYpdH!!">-s8S>_!!&ebrrXPI!%%OB!6kEB
-!'L2Z!+Ym+!/:FP!6kBA!Fsf7s+::)rrPFc5jA:Mfd.sD!!4HD^[M1);#gT\rVlo\
-bh2psKdAk\,m=8K,pcE`r;QfNg&D!Rf`2!ug&D+]!$Lh3!WW4Ml2M$a,p`Nk,pd'`
-n,EJ9!!(^NrrLg+f`)(a,s3J"rW!$H-"F^frrL@+rr3(b!!#mLrrO;CJ%,FXg&(gM
-;>pLpbkhA?;>U:mg&:sT--ZDho0!!P"-iicL&M&PbkV2<^]"35L&V)PU\t/mPlC[b
-,ldp-rr2sErVuqnrr2t.rW!$ts8QU.!!%`OrrAhn!!?a2s1eL4!0mK_!SKU7!!">9
-rrXPI!'KrS"$?P`-27E>-2mlEU]18nA,ZH.;>^@n4T5<\bl%JD,ldokPl1Ogk#!Ee
-s8OAF!%#DYrr_Cn4JVfR!'L5\!6k??"!mpI-3!oE;>pOqA,cK.U](5q-3+"hrVupE
-r;QjF!!">9rrA;_!!+D.qYpP*rW!%Ss8UdO!!,4ErVlu7;*<)"rrXPI!%%OB!6kEB
-!'L2Z!878M!@?n,rraVJ!%!m-rr_C\,s6eZK)aj1!^H`Nl2L`nq#CD:nG`SQ!!%`P
-rr]MP!'Js7!%%==%6WeQs)\5@FT;Bb!!"=urrQR.+S#I5!!%N5rr=AA!!+C@nG`S:
-!!(7Brr[?C!-Hrp!6k*9!)`aq#s826Z2aiX!!#.7rrO;CJ%#@W-2dfDU\t,l-2[`C
-^\Rm0;>pOt,s4:9rVupErr2tPrVurBq#:>JrVuqPrVlk>rW!0Lk5YH-!!#.\rr@cO
-!!58F-2dfG^]4>Kr;Zq0^Q_Uo!!">Err>pp!!=N04=0q+!%%49"!mpI4SA^V49,@-
-p\t5Ir;Zm]4=0q+!5JF2!'L5\!6kB@!/:@O"XRZ4F?ClK!!:jRL&CuV;2'^6,ldok
-qu6XYrVurBqu6aE!!">ErrBh4!!4H/4T,6^L&_1srVupEr;QaCrVurOoD\eQrVuq.
-q>UH0rVupErr2sqrW!'I@tfV6rVup\qu6aE!!">BrrC:B!!#.Yrr>1[!!$O,rr@cO
-!!OZYKlfF'rVurOK)^H&j8T0G!'ofK!^$G_r[%LC!+YR!"$?P`L&V)PA,ZH.bhE's
--1q6Hg&M'u!!">Fs3(HC-/&;"?iV>>rrN0#J*Ht7,ldrE-2dfDU[e?d,ldqhrr3'H
-!!">!rrC:9!!=PIs5s:\##YF#K`D*8g&D*r!.VHW!)`^q!@@@8rr>1[!!">?rrLe!
-p](<!rr2tPrVurBq#:>JrVuqPr;QaZrW!.Es8OAF!'L5[!'L#V!-J2>!'KoS"GQmU
-jsB^$!@?n"rrXPI!'KrS"$?P`-2.?=4SSmVFSc";4T5<\bkqD?4SAaT4T>?\4SJgU
--2[]B4T5<\bkqDB,ldokrVlk-p](:Vrr2uBrVup\r;QaZrVurBo`"pErVusFk4nrV
-4T5<`g&M**-2.B>;>^@q,ldokqu6Z?rVup\qu6YkrVusFk55/Y4SAaT4G*Tbs5O%[
-5QF(6rs(Xd!/:IQUHJMU!5J+)"$?P`L&V)SYpBB4g&D1$!!%,Ur6,4r4GEe7$$6.I
-FT;Bb!!"=urrQR.+S#I5!!%N5rsC%P!6kKCKd?^!-1V!;,ldqhrr3(B!!%,prrgOG
-!%!?sbQGV%4L+nc#s81fZ2aiX!!#.7rrO;CJ%#@WPl1R^g&1jMPl1R^L%kTJ^EraW
-!@=N>rr@cP!!(^IrrCaO!!&8]rrBh5!!\/Ws!7XFA,ZE.juiJ?!+Yp+!'L)X!%%UE
-!'L8\!TlN@!!FSJ!%$e!rrZ*u!+Y^%"$?P`-2.?>juiJ?!+Yj)"$?P`-2IQAF=$b`
-!@;7Rrr>pl!!,sMqu6a\!!">ArrZ*u!'L2Z!+Yj*!'L2Z"!mpI4T,3ZFT)7?bk(i:
-,ldpep\tB2!!">-rr3#C4Sf$Y-"HfO"!mpI4So'[,ldpTqYpXD!!#mlrrI3fq>^OB
-@tO`4s5EtZ5QF(6rrY@`!/:CO"$?P`A+KX%49,A8rVlo\bh2pt,ldqho`"sFbl7VE
-bQ%Vhg&D+]!$Lh3!WW4Ml2Li3!!(7BrrgOl!!&ebrrXPI!6kEA!SP]Mrr^IF!%%7:
-!R06rrr[rT!'Js7![%Jm[Jp>+,pd[1rrhI1!!#.SrrM7lr?VJSk5>5]^EikBpAY2J
-4GEY3!i%kfrr3(q4Ak8<rr@cO,lplXq>UJj4T6W2;5=/r,pfhorsHMN4=):9FP0M;
-L%50DKn]1!",/$IFS,S5L&E:u;8;o+"/@.gFSPkAk(Po[,pb[-k5,)YUJ^t9!Frn?
-rr]#B-$9"`"6O*'g&(dMUHJN%!Bd.SrrZ*u-):D<"2?,^4S&LRk(T&mrrTH&^\e$3
-PW\mj!HdK"rrZaW-*d=H!l%TSq>UQ@4Ajf,rs7b@4?Oo94GDpLs+::/rrPFc5jA:N
-49,A8rVltR!!#.PrrY@`!/8l$"!mpIbjYQ6bQ%Vhg&D+]!$Lh3!WW4Ml2Li3!!(7A
-rrY@`!/:"D"!mpIbgZRobQ%Vhmf*BC!!#.7rrO;CJ#`MNfnG.Bk5PG7OT,@Dk2H=?
-k2ZIAk4JZRk2H=@bi\d%!TqVWrrD3RrrD25s+:9ZrrPFc5jA:N,ldq?rVltA!!#.Z
-rreR.4GCQJrrY@`!/:FP!mEc(qu6i7;'dMNPl:U_FCY.H!b5a&p&>+?!!(79rrSrX
-FT2:BbQ%Vhqu6l8F?DZ_Pih-.!al!Nnc&Xj!.X;6"O$iG-0G1+"$?P`L&M#Tk(R;B
-L$&=5"!mpIbl7VDUHEYqrro/[,pcE`rr3&Q@tjdZ!ngG)p&>-<!!">;rrR:)U]18q
-K`D*8qu6hp@luk`UZMLW+96nCs+:9&s+:9&s-EZd5QF(6rrXPI!6kHB"O&.l!0mK_
-!L+o.!!%->rrY@`!/:FP"$?P`L&M#OU\b#q-):KM!!#mnrr[rT!)`Fh"=4$J@m'`:
-"$A\Cg&:pW,ldqhs8U:C!%%RC!+Ym+!@=N(rrQR.+S#I5!!%N6rr^IF!%%UD!2KMn
-!87AO!H]Xd!!+C@rVlsG!!(7BrrXPI!6kEA!+Ym+#!CT=49,A8qu6aq!!&8WrrpUH
-!$u_LrZqV.4Ce?i"3^`F-3!oHK`D*8rVloO4So*Z--YQP![%JmK)^H&K)^H&K)_/:
-!^H`Nl2M5>!!(7Ck(P)]!%$e-s+U7K!0mK_"$?P`L&V)S49,A8rr2u5r;ZgDrW!!G
-s)e5?!0mH^"Qh!1!)`Fh!%%@>!'L5[#pfQObl@^e!!">Drr?R(!!(^9rrQR.+S#I5
-!!%N6rs-aJ!%%[Ffjk!]!'L8\!)`Rm!@?FurrXPI!6kHB"!mpIbl7VBL&M&Q,piNj
-##YC_!!"=urVlkmrVuq_pAY-:p&G)&rr3)E!!">Err[rT!'L5[!'L&W!%$h.![%Jm
-K)^H&K)^H&K)_/:!^H`Nl2Lf2!!*!Er;[;%s8Uau!!"<TF<pne-3!oH49,A8rr3'_
-!!%`Prsq3l!%#D[^H;Kns77N:!%%UD!+Z!.!5J4,!%%@>!'L5[#pfQObl@^e!!">E
-rrAhn!!d#Xb`jCR!/9Y:!al!Nnc&Xj!.X;6!6kEB!@9&j!!FV$s8S>_!!4HgA,ZH.
-;?$Rt,ldqhrr3TW!!(7Cs4J[u!'KE+UEonos1eO5!)`^p"$?P`-2%9<bk;#:FT2:B
-^An6[rr3(S!!#.\rr?R.!!e5%b]G-2!6j[,![%JmK)^H&K)^H&K)_/:!^H`NlMgnI
--2ITB-):J>&Q&N.--ZDhbU!5h^]4<r!!%`PrsC%P!/:IQK`D*!bl.PAbl7VBPl:Xf
-FT;C',ldpBo`#%?!!"<Bqh5%4rr2uBrW!/Hs8U:C!%%XE#<VtdA,lS(4T5<\^Zb\!
-?iV>>rrN0#J*R%6U\Olj4O!g)$7,ZP4S/UQPQ1\0rr30K!!(7Cs31HB#0d,I;#gSY
-r;QcMrr2t.rW!&*s8Skn!!%`GrrC:B!!+BUr.P-8rVltR!!">Ert0qb!'L;]js:!-
-PlLc;,ldokkPkT+!.TV#K)^H&K)^H&QN%"O!'oiL!6k?@"!o78k5G;^,ldpTrVm0d
-!!%`Qs#^8]L&V)Y,ldq?s8OAF!+Yd'#!;kc-0G5;rVur5o`#">!!(7:rtETV!%$e-
-s3(HC-3+"u!!"=hKdHZt!+Y3l!al!Nnc&Xj!.X;6!/:=N![TsnrVllArVuqnrVmWZ
-!!(7Cs!7XFbl@^e!!">-s5kU-!2K>h$K`W7!'L;]49,@-o`#$;!!"><rr[rT!%%XE
-%#"Z]4TGGG!!#.D@jV'R!2J`W![%JmK)^H&K)^H&K)_/:!^H`NlMh%3!!"=hbkh>>
-bl.SBbl.PJ49,A8s8P1]!/:FP#pfQObl?>r!%$e%rrB>'!!Qm4,ldpBoD\n=!!(7:
-rr^IF!%%XE$HrJM-3+"[!!";kr;Zj\UZVRX?iV>>rrN0#J*R%;K`D*8bfoq`",-^T
--2dcX,ldqhs8OAF!6kKCbQ%Vhs8S;`!%%@=!-J2?!MdF/!!%`Frr^IF!%%=<",-^T
-4T>?fK`D*8s8R0@!$rri!!,s3k5PK*!.TV#K)^H&K)^H&QN%"O!'oiL"3^`F-2@K?
-bl.SBbl.PJ49,A8s8P1]!/:FP#UKHNbl>le!%%=<"Ao.!-"HoS!5J.*"!mpIbkD&=
-bQ%Vhrr32H!!">Fs+U=M!Bd.<rrQR.+S#I5!!%N6rr[rT!'L&V",-^T-2dcX,ldqh
-s8OAF!6kKCbQ%Vhs8RcQ!)`Fh#:0?M4Ac(Y-1h-=bQ%Vhp&>,J!!#.\rs"/W!'L;]
-4T#0\,uMG<rrO;CItI]Ps+:9&s+:9:rrPFc5jJ@ObQ%Vhq#:?IrVurBrVm0M!!&8`
-s#^8]L&V)X,ldqhs3(HC-2%9<^\\!24S&LS,ldqhpAY6=!!">Ers$[I!%%[FPl:Xa
-,uMG:rrQR.+S#I5!!%N6rr[rT!'L&V"-`cc-2miZjs:!-g&M'u!!(7Cs3(HC-3+"!
-!!#mhrr@cM!!$O#rr^IF!%%=<",-^T4T>?bK`D*8s8Psq!!4HVk2QCB+96nCs+:9&
-s+:9&s-EZd5QF(7rr^IF!%%C>"!mpIA,cK8UAt9?k5YHD!!%`Prs9tO!6kK*,ldq?
-rVlr]KtmQc!+Yp,!2K,b"!mpIbkD&=bQ%Vhrr3>L!!">Fs4IAP-'\?-!l&6!kl1]l
-!$Lh3!WW4MlMgs?!!#.VrrCaO!!&8_rrZa2!%%XE&1%;Vbl@^e!!">Fs.]Po--Z>f
-!l'HOr;QaZr;ZjEk4ATTbQ%Vhp&>,J!!#.\rsFG[!'L;]PQ1\0^\n*5UJ\;[rrO;C
-ItI]Ps+:9&s+:9:rrPFc5jJ@ObQ%Vhp\t5'rW!!sKk()^!)`aq"$?P`L&V)V,ldq!
-s8Psq!!d#K^LJPi-0G1+!Tk^-!!#.OrrXPI!6k0:!6kEB#0d,IbQ%Vhrr2s\rVupq
-re1G:!!">/rrQR.+S#I5!!%N6rr[rT!'L#U!'L5\!b6p]rVuqPrr30K!!(7Cs31HB
-%F"kP,ldokFNgLW!!#.ZrrAhm!!$O"rr^IF!%%=<",-^T-3!oWK`D*8s8V4-!!"<T
-KnXUp!!#.FrrO;CItI]Ps+:9&s+:9:rrPFc5jJ@ObQ%VhpAY+Tq>^OBk5PA_49,A8
-rr33L!!%`Qs4J^o!!+D.r;Qb,rVuqnnc&\;!!(7:rrC:B!!^[Is3(HC-3!oFfd6Cn
-!)_t[!al!Nnc&Xj!.X;6",-^T4SSjVbU*)c!'L5["sj6Lbl@^erW!&Es8Skh!!#.Y
-rraVJ!%$durr^IF!%%=<",-^T-3!oHK`D*8rr2tnpAb2Ikl1],!.TV#K)^H&K)^H&
-QN%"O!'oiL"6Lm0;>1"jff]04!BeU)rrZ*u!5JO5"&T$ug&D!PbWPb&!E%PIrrY@`
-!'KcN"!mpIbk:u;,lf7jrr^pS!'L5[!p3?+qu?aDA*<jn?iV>>rrN0#J*R%9YlFcX
-pAY/u-2[`C;>gFq,lf7irrOJH-2miEUF#g<!@;7QrrhI1!!$O!rr^IF!%%=<"2=g9
-;?$RtPQ1]*rVlo54So*Z-&(O^![%JmK)^H&K)^H&K)_/:!^H`Nl2LeHbk(i;ULQD`
-U\aukKqnSG!R06orro0-4?R`=qYpQ1rVuqnnG`PP!%%:;!p7_hrVlr(L$&:4!Tp0V
-K`JmLrrQR.+S#I5!!%N5rrLg+oD\rX;*8@'qu6`NKtmTd!p7_hqu6ha;*6t*k5,)\
-K`D*!k4/HRjs:")o`"sFbl%JAPa)%E!SN_:K`K?YrrO;CItI]Ps+:9&s+:9:rrPFc
-5dC=k;#gSBmf*:2_>aRE!$Lh3!WW4MZ2XnP!!#mbrrM9+_>aQZ!.TV#K)^H&K)^H&
-QN%"O!'mji"Qh!1!/7QT!al!Nnc&Xj!.V<S!2KMn!5GZ9![%JmK)^H&K)^H&K)_/:
-!^H`NZMt&L!!">-XoAH1!$Lh3!WW4MZMt"h!!"=HrrO;CItI]Ps+:9&s+:9:rrPFc
-5dLCl,ldpBXT&?0!$Lh3!WW4MZi:0j,ldq!XT&>E!.TV#K)^H&K)^H&QN%"O!'mji
-"!mpIUTFIs?iV>>rrN0#J$].XbQ%Vhk,eRa+96nCs+:9&s+:9&s-EZd5QF'TrrQ[V
-4KJJ`?iV>>rrN0#J$T(U4=+L<rrO;CItI]Ps+:9&s+:9:rrPFc5_B$grrQR.+S#I5
-!!%M#s4I>Q+96nCs+:9&s+:9&s-EZd5QF'$s4I>Q?iV>>rrN0#ItI^QrrO;CItI]P
-s+:9&s+:9:rrPFc5_B$grrQR.+S#I5!!%M#s4I>Q+96nCs+:9&s+:9&s-EZd5QF'$
-s4I>Q?iV>>rrN0#ItI^QrrO;CItI^crr>R2!!"*ms+:9&s+::6rrPFc5_B$grrQR.
-+S#I5!!%M#s4I>Q+96nCs6BUb*>6OK!>kfgs+:9&s+::6rrPFc5_B$grrQR.+S#I5
-!!%M#s4I>Q+96nCs6BUb*@/g8!A=G)s+:9&s+::6rrQ!s5_B$grrQR.+S#I5&-.33
-s4I>Q#QT@+s6BUb*@/g8!A=G)s+:9&s+::6rrQj6+G0XGrrP^k5k4jU-idY,s4I>Q
-!!%e+s6BUb*@/g8!A=G)s+:9&s+::6rr[`N!9\t6gA_9L&--,.rrPFc."_KPrr]_1
-!2kGKlMgl*,g0Nq0*$V(K)^H&K)b$6"2=g9LP#Q[rr]G)!2oAe"+L:Na+F?FrrZ@'
-#k*BFlMgl*,g0Nq0*$V(K)^H&K)b!5""4-Tf7O%Xrrhd-!#YJ#rrh3b!%@Sns4mVV
-^An71K)b*8!?EH/?NDe[K)^H&K)^H&k5PP0#QQi9s4mVV?iU2!n,EKV!!%7qs5!\X
-pE0GIkCW`urrF,cb?k9'!.t6&s+:9&s5j7`IfKI>kCW`lrrhdu!!#RWrrbRe!-n6i
-s5<n[a!^ofT7[+,rrF,cb?k9'!0[?^LWMd]T7[)ps,d6bpG`-Q&=;R3s5a1apSSi.
-!$LIlrrq9k!!"FNK)am2!T//$!!#iIs6'C_*@/g8!A=G9rrE*,b7am]*J4<Cs,[0\
-mpQ(o!'#QqjZieOrVusikNi-Kf/Wa0!"a`IjZif"rVus)LP#QgrrF,cb?k9'!0[?_
-!%,l`!?E24s+:91rrKSGJcO^/!>qHlrrIl\JcO^/!BA\_s5j7]*@/g8!A=G9rrE*H
-b=r!X*J4<Cs,6mXYAgO-r;Zg?^d%s7TC:nA!r&TpY<W(!rVup0]KcLBc[u2WrrF,c
-b?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_
-!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24
-s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'
-!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB
-5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+
-rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'
-!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`
-!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&
-s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#
-s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``
-5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,c
-b?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_
-!%,l`!?E24s+:9&s0D\'!!$BF^Aum*rrC*Y^Aote!!#99s.')i*@/g8!A=GrrrM:)
-aT);fb=r!X*J4<Cs+:9Vs1\O7%&h>K!J:Nj!!#'3s.')i*@/g8!A=GrrrTq8;p0%Z
-!%,l`!?E24s+:9&s0D[=!!!nZrr<A?!!"-ns.')i*@/g8!A=GrrrTq8VT[cr!%,l`
-!?E24s+:9&s0DY)$,6H?#L!,IfY.=c.Y@\jrrF,cb?k9'!6bBD^At.Sh#RL&b=r!X
-*J4<Cs+:9Vrr@\d!!!bWrrCrk!!*,!K)_A@!?EH/?NDe[bPqXY!2drq!<=Ii9`Z7T
-K)^H&K)`+U!RZtI^Aph(!!".brrCsT!!%5_^B1s,mt1S/rrF,cb?k9'!6bBD^At.S
-h#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT*@/g8!A=GrrrTq8
-VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+rrF,cb?k9'!6bBD
-^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT*@/g8!A=Gr
-rrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+rrF,cb?k9'
-!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT*@/g8
-!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+rrF,c
-b?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT
-*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+
-rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)p
-s4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XC
-s+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NT
-T7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT
-!!&XCs+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscb
-hu*NTT7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".b
-rrCsT!!&XCs+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-+
-+Nscbhu*NTT7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+
-!!".brrCsT!!&XCs+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i
-@/^-++Nscbhu*NTT7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::H
-rrDNbrr?I+!!"/<rrDNArrD6ZrrCsT!!&YgrrDM>s+::2rrF,cb?k9'!6bBD^At.S
-h#RL&b=r!X*J4<Cs+:9&s7uZr:fsq"rr?I+!!"/?rr^kl+QqJY"0X,.hu<WUhu*NT
-TDnimpRauqK)^H&j8T-#,g0Nq0*'2q!l"`4bM<1!-Hf*a*?Bb3K)^H&K)bZH#L<AM
-(hf8N;>pP#*P\M%0E;)lf`).0!!#96\#90)#CO:A?jH`<kCW_cs5X+[*@/g8!A=Gr
-rrTq8VT[cr!%,l`!?E24s+:9&s+::Grr>md!!*Agf`(rTnGiQ.K)^H&ir9$",g0Nq
-0*'2q!l"`4bM<1!-Hf*a*?Bb3K)^H&K)bWG!7139!-$Nh!&4!E!=7k?s+::1rrF,c
-b?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s7cNn;"O_g#j9e=!3bto!-!PiK)ag0
-!?EH/?NDGQb<Q+_!1_6g!<=Ii9`Z7TK)^H&K)^H&p\t6>oDel1eGfM&o`,!ukCW_c
-s5EtY*@/g8!>baZ0ENL"I*:=H!%,l`!?E2KrrBfcJ"1ug[t=Y#rr>mh!!*AgeGfNP
-o`+u2K)^H&i;Wfu,g0Nq(BDXo!g!D0bM<1!-Hf*a*?CUK!3^tSRK*>kK)`pl!71?=
-!-$Bd!&4-I!=7k?s+::/rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*Ld!.It@Zh!!%M#
-s2Y->;"t"k#j9Y9!3c+s!-!PiK)aa.!?EH/?NCrCbJ41@!.;uG!<=Ii9`Z7TRf<G=
-!!%WNT)Sil!.TV#a8Z.cp](;5d/O)"q#CF$kCW_cs53hW*@/g8!>ba\^]r$0X?`?=
-j3?B\!%,l`!?E2LrrRZM!.t6BrrN0#ItI^?rr>ml!!*Agd/O*Lq#CD6K)^H&hZ!Ts
-,g0Nq(BDt#"O>ren+l\W"T7uamc;mR!<=Ii9`Z7TRf<G=!!%WNT)Sil!.TV#`r?%b
-q>^M7cMmkuqZ$X&kCW_cs5*bV*@/g8!>bag^]VO-l20iI"9%iVhq6`c!%,l`!?E2L
-rrRZM!.t6BrrN0#ItI^>rr>mn!!*AgcMmmJqZ$V8K)^H&h>[Kr,g0Nq(BE4*!lEOQ
-jo5D]oB=oa!<=Ii9`Z7TRf<G=!!%WNT)Sil!.TV#`W#qaqu?_9bl7Ysr;Zj(kCW_c
-s5!\U*@/g8!>bal^]MC0qr%JTr9E(n!<=Ii9`Z7TRf<G=!!%WNT)Sil!.TV#`;]g6
-rVus)kKNr+YPeG$E.\+As4mVT*@/g8!>bam^]E$\pAY9I[srm8r'1BmIt+rZpAY0h
-k2+np!%,l`!?E2LrrRZM!.t6BrrN0#ItI^=rrCCE!!$u\rrb"U!!qb>s+::+rrF,c
-b?k8d!8tWn`pNR$!lodMn,NMTLX5bq!V5.+h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M#
-s24j=:]Ldab5VRI!!$tis+::*rrF,cb?k8d!9(]of_bOF!nV)kl2Ul&Gh;fl!W;->
-h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M#s24j<cN%q*rrOk[kCW_cs4dPS*@/g8!>baq
-^]<QorrKSgj8]3?\,-+)mc*%'!%,l`!?E2LrrRZM!.t6BrrN0#ItI^;rrH6baSu:E
-E.\+As4[JR*@/g8!>bar^]<QprrL_BhuEdKhu!ESo%rH`!<=Ii9`Z7TRf<G=!!%WN
-T)Sil!.Tq,\\A-T`kMM[Y.ju"K)`%S!?EH/?NCrCjhLo6lhg\^GkV1B)eEf*TqT-u
-f*8m]TlOpM'_hY/#`&<W!VP=2h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M2rr^l&5VRci
-U]:N'5Y.7!K)`7Y!?EH/?NCrCk.h#9mJQtbh`1E3!ZPIKnCI`8<ttH1!BA^/rrMfL
-k1p%<-Hf*a*?CUK!e11Mdf0B`L"YMd"6NH,FRK/0biX`]!WW4MPlCgZLF@`SRfEIC
-YCce`rrF,cb?k8d!9_,u_Xm^*!RD>S!!3@2Y3OU>Ti(Xd!>*TTrrD`Sh#RL&b=r!X
-*Ld!0IfKK?rr^q#-"H':"2=g94QHGAL&M&PbjbW849-[)^UjFHUQjojrrN0#J!L$7
-T-4(4"!D9,LP!:>^BD#qIom9\!!+dgK)`C]!?EH/?NCrCkJ.)\r;Qf4&GlG.0=Bro
-!N74>!!*YWr;QcbkM6.=-Hf*a*?CUK!e11MoD\efrVurOk5PO;!!">*rr@cP!!(75
-rrA;]!!,s3^&J4F!!">-ec,[N!.U@8!T,=)!!49^c[u1hrrTZC)#aL98FM01]DhmP
-,g0Nq(BE[7!8.5L!P\p<!!*:Ej4==YAbuH.+Q*+s!9WM$!<=Ii9`Z7TRf<G=!!)Wj
-!'L5\!6jU*"$?P`4QHGAL&M&Pbjk]5L&(cN-$8:brr=AE!!&86rrN0#J!g6>^CUAF
-(nZE[Rf<TdIh2S[.+a(N]`/!Q,g0Nq(BE^8!QtB>rrL^_qu?aT[G]X;W$;->!?gk0
-rrN&Ul.l@?-Hf*a*?CUK!e11MoD\eQrVurBk5PNG!!#.Arr@cP!!(75rr@cJ!!+Bf
-_>aKtrVurOec,[N!.UF:!13Zb!Isiqs-N`hmoTPi&@[8k^&J*R,g0Nq(BE^8!:Tmd
-!Uh0/!!,4/p"'8fTn`J\!f`o#p"'5e./X&G3;<CO!:oC1!<=Ii9`Z7TRf<G=!!)Wj
-!'L5\!6jU*"$?P`4QHGAL&M&Pbjk]5L&M&Q4=0k)!BeTDrr_Cn4L*E9!WW4MRf<Mo
-!!!;&K)_&7"GZsW#g\,&^Ae3S,g0Nq(BEa9!8.5L!+>^)!Bea(f)s0?6Oi_h!uk*l
-d.l2nasd/f!.XqH!9WS&!<=Ii9`Z7TRf<G=!!)Wj!'L5\!6jU*"$?P`4QHGAL&M&P
-bjk]5L&M&SbiXU*qu?aDUQb]Z!!%M<rrg@J!"dJ.s,m<aY5ePFkCW`KrrF,cb?k8d
-!:.E$_YO01!2'/h!Bea)f)j*+%Ia?!%;!]Xf)a#Br;Zj(ci*kDq<Hc:!%,l`!?E2L
-rrRZM!;$3j4T5<\bi\p349,@Ds8TifL!8f]!/:CP!6k!5!/:CP!6kHB!M_dT!!&e]
-rr^q:4O!g)!R/dBrr^qO;;(sK!l'H5p](08!9WhO!WW4MSGr`T(]XiVK)^o3"HNN_
-3;8%)_#FEU,g0Nq(BEd:!8RPQ!V[H0!!+%cq:>Y:'^Pf#)lWSa!Q,BF!!#RfrrD9K
-h#RL&b=r!X*Ld!0IfKK?rr>1\!!(76rrKlEr?VJdk5G;`49,@D@jV'R!@=!*rrJ?H
-r?VJS^\n*3L&M&Pbjk]5L&M&Pbl%J@L&CuP--Z5c!M`Nk,lqN<r;R1&!!#.]YpBAM
--):Kor?VGtq#:AZ4T6W-;5=$g"&U?jg&D!U49,@Ys)]Rd!!,4+r;Qhn4=0n*!@>#A
-rrN0#J"6N@Du]m)K)^i1")%Z7O+RDIrrF,cb?k8d!:7K%_YO01!0@$X!0m<2!++jh
-!-n=k!-nDA!3cA$!;Ys:!<=Ii9`Z7TRf<G=!!)Wj!'L5\!6k*8!V91b!!+Bfrr2s\
-p&G)&qu6]@4S\sWA,ZE-L&M&Pbjk]5L&M&PbkqD@^ErjZ!'L2Z!SKU4!!+C@rVm!H
-!!"=0qu?aD4So*YL&:lNUF#a:!BeU*rrC:B!!$O.rraVJ!$sc)!!#.[rr?R(!!#.P
-rrN0#J"?TAhZs3YK)^f0"SW`5)#&X^_>aNV,g0Nq(BEg;!8.8M!V[H0!!#C_f)a5c
-q>^U/:k,,8^B:*X:^Hmt!*B!J!%@dG!&4?N!9WY(!<=Ii9`Z7TRf<G=!!)Wj"$?P`
--1q3<fd6@m"3gfF4S8[SL&M#PjsBa%!2KPn!/:CP!6k!5!/:CP!6k<>!R)kh!!&8_
-rrM7.q#CFAg&D!R,ldoko)Jb:r;Qb,pAb1Urr2uBrVup\rr2sEp&G30s8Skk!!">E
-!!#.PrrN0#J"?TA:]LLAK)^c/"0V\)O+RDJrrF,cb?k8d!:7K$n,<7dO8T%Z#/'ib
-!RNt+!!,'Wp&>*fT-4"2!)`UE!3#eq!5JL4!:oL4!<=Ii9`Z7TRf<G=!!)Wj"!mpI
--1q3;4T,6e;3[h%!!">-s8P4[!!GEZbfjSr!!+D.rr2sqrW!'IFG5EGrVupqrr2tP
-rVurBnc&TCrVurBq>UGKrVup\rr2s\r;ZmF4=0t,!)`aq!%%LB!'L/Z![V>&rVurB
-rr2tnr;ZpGFKo?T!!$O.rrC:B!!%`Prr=AB!!.2+rW!%Ss8R3?!!d#Xg&J<'!/:"D
-!WW4MT)SoM!!#iIs,$aW0E;rAs2"^9*@/g8!>bb'^];IRrr=bO!!$@%f)T.T!!+4W
-nG`N]&GuM.Er+Af6i?ub;#UCprnd%u!<=Ii9`Z7TRf<G=!!)Wj"!mpI-2%9<L&CuO
-U]18q,ldokrr3*`!!"=0r;Qb,rW!%Bs8Tk5!!PLVs8ThrrVuq.rr2tPrVurBnc&TC
-rVurBq#:OE!!">-s.fMm$^C\kbU!5h-0G7--2[`DL!9Jq"&\4\FT)7?PlC[_-2mlI
-4S/UQL&M&PU]18n^]"35L&V)P-2[`LU]:??!!#mrs'u$.!0mH^!SO7<rrN0#J"HZB
-LB%=hK)^]-",?jV^OlL&rrF,cb?k8d!:@Q%hYmHS^\e'3[JSPUY5A8#+Q)Ve!RD>U
-!!*;,qpth;r;Zj(kPbD\l0[:-!%,l`!?E2LrrRZM!;$3m,ldokp&>"<rVuq_rVlsG
-!!#.\rrY@`!'L,X"sj6L4TGFkrW!&8s.`Hh!!'e5rr@cP!!(75rr@cP!!(7<rr>1\
-!!:CE;>pOqFT)4>FT)7BU]:??r;Zn`s31HB!'L8\!6kEB",6dTPl:X_4T59[L&M&P
-bl7VBL&M&PL&V)P-2dfDFT2:E,ldp-s8Skm!!,3WmJd4f!.UU?!^H_sK)^Z,"5a(Y
-BS-9$rrF,cb?k8d!:@Q%n,<7d@/U'*0Da9#0DtkO&D-dY#5R`J^Y\\_qYpT2#lO`'
-./MNq'`A"3L].5Qo'P66!%,l`!?E2LrrRZM!;$3m,ldokpAY-:rVup\r;QjF!!#.\
-rrY@`!'L,X$TnCh-3*uk!!"=!4T#0[-):G=!/:CP!6k!5!/:CP!6k6<!'L5\#0d)n
-!!">-rVllArW!%Ss8ODE!!?a2s4RAO!'L8\!87>O"$HV`4T5<\Z2O\&L&M&Pbl7VB
-L&M&PL&V)P-2mlE-3!oIjs:!-4T>?\A,H<-4JVBF!WW4MTDo#^!!$DYs+gUU2uk@Y
-s2+d:*@/g8!>bb(^];=Nrr<W/!!%cNf)VuO!!'5#rs\_YaM>TQ!.<VYipZjDrrA,X
-!!'2!f)TUb!!"_OrrE#bh#RL&b=r!X*Ld!0IfKK?rrXPI!%%@=!/:CP!/:@N"!mpI
-4T>?_49,@DqYpa^!!">Fs!@I@!@<Hsrr@cP!!(75rr@cP!!(7<rr>1\!!UU/,ldok
-r;Qc@rW!.Vs8OAF!%%UD"!mpI4T59d,ldp-s8OAF!%%RC!/:CP!6kHB!/:CP!/:FP
-!%%UE!+Z$.!6kEB!'L5[!H]Xc!!,sZnc&Xj!.UX@"4$rIYCce0rrRZM!.t6frrF,c
-b?k8d!:IW&eG]CI^\n-5#138!!(6\b!*K1!!U%>u^]KStI/Vk%i:[$J!&4?O!(6Y8
-!5/40!8mbT!93G&!<=Ii9`Z7TRf<G=!!)Wj"!mpI4SJdTL&M&PL&CrQ,ldp-rr3'_
-!!#.XrrtRc!%%[F-2RZC-&)0p!/:CP!6k!5!/:CP!6k6<"XO-K-3)3g!!#.ZrrC:B
-!!\/Ws!7XF-2miG,ldp-rVm0M!!">Fs!7XF-2dcCL&M&Pbl7VBL&M&SL&_1sr;Zi4
-rr2uBrVup\r;Qi\@jV'R!@?FirrN0#J"Q`C[f?ESeGfS[4L+SZ!jOkAW;ck[n,NC2
-"2@\qg&(dOk#"7UqYpZN4=,^-rr\kn!9\t6_uB`X,g0Nq(BEm=!9!hU!/LLQ!&+6$
-!Q,-?!!(@DrrMZ,r4iAq!.=_#!T*\OrrB8#!!'G(f)QN`!!&qqrrD<Oh#RL&b=r!X
-*Ld!0IfKK@rrC:B!!#.TrrA;_!!%`NrrY@`!'L8\"$?P`4T#-`fd-Uu4TGF-r;Zj\
-U\FcgL&M&Pbjk]5A,ZH.bk_8=L&M&V4TGF-!!">CrrAhn!!]4us!7XF-2miG,ldok
-rVm0d!!">-s!7XF-2dcC^]"35bl7VBL&M&SL&_1srVusFk5PA\bl.SB4Sf!XKdH]u
-!)`=e!WW4MTDo"c!!)34rr?R.!!%`IrrAhn!!&dorrR9B4S/RSk$o_7!!#mnrrY@`
-!%%LA!'L5\!5Hn\"1J71c[u27rrF,cb?k8d!:IW&li$h`=T&4"?Mi=SGl7UB;#L=n
-bko0WO8s\*h#Q[:rr=bO!!%9@f)S2:!!%9BrrDQVh#RL&b=r!X*Ld!0IfKK@rrC:B
-!!#.Xrrh#/U]8R;!!#.ZrrY@`!%%XE"$?P`4T,3[o0!!P#F,8g,ldokU\k&mk*2,0
-rr@cP!!(75rr>1\!!(7>rrAhm!!B"rs!@XE!5JL4$9S:g-0G7-,ldokrVls^!!">D
-rr>1\!!:CE4T5<\^]"04bl.SBL&V)PL&M&SL&_1srVupEr;QjF!!">?rrgOl!!">9
-rrN0#J"Q`BIfKJurr>pp!!&8ZrrAhm!!&7arrAhn!!&8VrrJl@q#CC@r;Qblr;Zhm
-r;QcMr;Zh-d/O3g!!'ccs24j;*@/g8!>bb(^]=!)rr=bO!!&#Uf)Rr3!!'5$rrDB]
-^]KStI/;Y!q>L<nO8T%Y;>\rFEr>t<;#UCoo^:N9!%,l`!?E2LrrRZM!;-9kbl.SB
-FT2:Bb`ksNrW!"Rs!@XE!0mK_!L+o0!!B"rs#g8\"XS9*b]G01!!#.\rr@cP!"C6.
-g&M)rF<pneU]:@JrVurBnc&SOrVuqnqu6YMr;Zg[rr2tPrW!'IUWgJ8rVupqrr3'H
-!!">Drr>1\!!(7Brr@0?!!8qqPl:Xd4Qc\Dfhq_K!'L8\!/:CP",6dTbl.SB-2dcL
-,ldoks8R1'FMIhT"MZ5_!%%49!WW4MTDntB!$Kek!SJdt!!'e2rrL=irVup\X8`4R
--2mlEA+op&U\=`g-2dcC;>gIp;>gFoPl1R^-.)YohZ*YkK)`ag!?EH/?NCrCm_Ai"
-rVlj'r;Zi*r7:tr#5nN%hu3QTde^`\O8s\)h#Qd>rrBh4!!"5?f)V<=!!"GGrrDl_
-h#RL&b=r!X*Ld!0IfKK@rrBh5!!=N0,piBf!^-Kmr;ZmF4=0n*"&]*u4S8[S^]"04
--2[`D,piHh"2Fm9L&M&Pbjk]54T,6[-2fq+-2dfE-/&7s!%%C?!@?FurrXPI!%%UD
-!-J2?!6kHB!/:CP",6d;-2mlG,s3LN!!C"9s+UFP",6dTbl.SB-2dcC4T5<]bfp"c
-r[%LC!)`=e!WW4MTDntB!$Kbj!R)kh!!+D;r;QaZrVusFk,\L^4T,6[4SSjUU\k)n
-;2',k!!">Crr=AD!!">Crr>pp!!"=lrr_-Y!5F-c_uB`X,g0Nq(BEp>!65!;!8%,K
-!7:Yq!3#hr!#YY6!6"`L!g!D0qV;/1rVlllqu?`Dr7:qVqu?`krr2usmbImD-Hf*a
-*?CUK!e11Mo`"odo)Jlts8P4S!!:jR4SJgV-*dCJ!R*\#!!$O.rr@cP!!(75rr?R$
-!!+Cir;Qf4-2@N@U](2p49,@-rVlkOrVuqnrr2u5rW!%1s8Ske!!?*us-3K_#DN3X
-js:!-4T,3Z;>pOsbiU5H!!+D!o)Aak!.UX@!e11mdf0<^r;Zg[rVlk-rVusFbcCaD
-L&:oN-2@K@bU*5g!@>M[rrZa2!'L5[!Tk^,!!">Crr=AC!!(6jrr_-Y!5F-c_uB`X
-,g0Nq(BEp>!6G-=!5JI4!#5=^!0-pW!(d(g!;60'!g!D0q:u&JrVljGr;Zi#r7:qq
-qu?`SrVu<A!<=Ii9`Z7TRf<G=!!)Zk!Tk^'!!=MnA(gh\!FmGS!":/`PU-;Uk5V\4
-,s3LP!!4HVk5##XKdHWs![U^KrVlu)!!#.MrrGtCpAb4Vg%t^LbWPe'!BdXbrr[rT
-!)`^p!/:CP!/:FP!87>O!)`aq!O4cb!!PK[49,@krr3'_!%$e,rrXPI!)`[o!0mH_
-"53^h4So*[,uN@crrN0#J"Q`BIfLV=rrA;^!!?a2s+UCO!0ljM"5-OKg&D!Q^P0nS
-rrLe!qZ$W?q>UFWrVusFbl%JBFCX#&rrBh2!!(7BrrCaL!!'d]rr_-Y!5F-c_uB`X
-,g0Nq(BEp>!7(QC!5JI4!%@`r!-8#<!-nJB!9a0n!g!D0q:u&ErVlj_r;ZhkqptfW
-r;ZiTrVu<A!<=Ii9`Z7TRf<G=!!)Wj!O4cc,m6>-KtldGrrhJZKnZ<$rrUl-^]"06
-k5YJ[bk1o<g!#/7bk_8>g!&g_"I)"p,lmoj!Frn<rrBh5K`Jm`rrLfsr;Qc3rVurO
-rVltA,s9lYrrC:BK`Kg*rrJ@Kr;Qc@r;Qi54Ce6f!b4?trVllNrIk9Ik3r<O!!%M@
-rrRZM+OL,gA,QB.KtmQd!)`Ok!L,_F,lqMjr;Qs`!!#mrF=$nd!BeTlrrP;/;<@fX
-4T5<\-2mlEPktC[FT)7@--Z#]!/::M!/:FP!/::M!/8i#"5a(Y^OlL'rrF,cb?k8d
-!:R]'d/EtE^\n-42>bu*C]+55J,TBIi;(.iO8s\(h#R0Irr>=_!!&_if)Qcg!!(pT
-s6e\D!%,l`!?E2LrrRZM!1*Wck02W\!l'H([/U1-!.UX@!e11mci3u-r;ZgDrVusF
-oD8IfbWP\$!+Z!-"=4$J,s;&)!'KWJ!0mH_!6jX+!/:CP!Bc)8!!$O+rrM7.rVuq_
-oD\eQqZ$V+rr2s\qZ$V+dJj=+!!'ccs24j;*@/g8!>bb)^];a[rrBh4!!"nRf)TUb
-!!%NIrrD!Q^]KStI/2RupAP!k5lCZ_U&3FA)uTa:hu3TCh#RL&b=r!X*Ld!0IfKJ#
-s.95l!!%M@rrRZM+O9ue4Sf$X^\[s2jsBa%!2KPn!%%==!5Iq$!/:CP!6j[,!Tk^-
-!!0@KrVupEqu6Y+rVupqo)A\9qZ$aFs8V4-qZ$UYdJj=+!!'ccs24j;*@/g8!>bb)
-^];a[rrBh4!!"nRf)TUb!!%NIrrD!Q^]KStI/2RupAP!k5lCZ_U&3FA)uTa:hu3TC
-h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+O9ufbU*/e!0m<Z!)`^q"=8/DKi.gL
-!)`aq!%%LB!HaS*!!%`?rr@cP!!(7,rr>pq!!Z=#s!7XF-2[]B-2mlE^[qI*g%k[N
--3+"0rW!'`,ldokdJj=+!!'ccs24j;*@/g8!>bb,^]W$Cn+6MX!5JI4!&aZ*!,MN5
-!.XtI!;H<X!oq&Pq=XgerVlj_r;Zhkqptfer;ZiTrVlunoBYE,h#RL&b=r!X*Ld!0
-IfKJ#s.95l!!%M@rrRZM+O0od;>gIp4Sf!W^]"3:4S/UQ^HDJq!+Z$.!%%OC#,D4u
-,ldpBnc&T2r?_FCr?VGcmJd0krW!'Ik5YHDrVur5rVlkmrVup\o)A]SrVus]4T5<^
-^]-Fq!!/<HrVurOdf0F,!!'ccs24j;*@/g8!>bb.^]DaRq>UH0r;ZgTqptg`r;ZhI
-jSo3Fr;Zhkqptfer;ZiTq>UKfj7M..!%,l`!?E2LrrRZM!.t6BrrN0#J"Q`BIfLV:
-rr?R+!!';#rr?R.!!C"9UJ^ph!5JO5!%%RD!-J5?"!mpI4S&LQjsB[#!6jm2!'L5\
-"B!BsKdH]u!/:CO!+Z!.!0m'S!'L5\!L.^*!!dW.,ldoks'u$.!2J!B"5a(Y^OlL'
-rrF,cb?k8d!;=2/_WU[n!5JI4!&aZ*!,MN5!.X)0!'pJ_!29;A!#tk:!8mPN!:BI8
-!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@!e11mci4!!q>^OBoDAOk,ldokKfo85!@=N>
-rr=AE!!">ErrhI1!!#.Orr>1T!!">6rrM7lo`+tSrVlj[rVurBo)A\9rVuuP^]"36
-4I#gF!`Au^rVuq.df0F,!!'ccs24j;*@/g8!>bb0^]<]orrBh4!!"nRf)TUb!!%N0
-rr>=_!!&_if)Qcg!!(pMrrM`JpY>iM-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$KYg
-!2KJm!B_\-!!#mnrr=A@!!+C"qu6XBrVuq.rr2uBrVup\nG`U7KnX%9!!K(@b_>3J
-rr>1R!!">Drr>1\!!(77rrBh5!!ahMs!7XF,piNj!i,e>rVupEdf0F,!!'ccs24j;
-*@/g8!>bb1^]<*]rrBh4!!"nRf)TUb!!%N0rr>=_!!&_if)Qcg!!(pLrrDZbh#RL&
-b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+OU2hU\t/o-1eD?!!&8]rr=AB!!+C"qYpQ>
-r;Zi4rr2uBrVup\mJd0?rVurBli-rIquH[A!B_\-!!(7Brr>1\!!'e0rrSsL^]+65
-A,ZH1;?-YYqZ$UBrr3*I!!">-e,KO-!!'ccs24j;*@/g8!>bb2^]DIRr;QeQ+LV7O
-5aV6CrrD-Th#RL&b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+O^8jbU*5g"=;:ls'u$.
-!@>tgrr=AD!!,3Wq#:?<rVusFk5PA\bl.SB4RN.KL&M&Pg$J_=^\n-5UWiZ9!+Z!.
-!/:FP!-J2?!)`Xn#j+ta!%$e-s!@XE"-iicFSc%<A,cK.4T5<\UXT5FhZ*YkK)`ag
-!?EH/?NCrCpqQmirVlom33iMb0^nu?!;6-C!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@
-!e11me,KHm-2mlF--Z>f!'L5\!'L5["=4$J-):A;"m2&6s8U=B!!">CrrXPI!%%%4
-"0hh+-0tR2;>pOq4So'X^]"354T>?\g&1mNA,ZE.KdHZt"3gf--2mlHbl@^rqZ$W2
-rr2tPrVupqe,KO-!!'ccs24j;*@/g8!>bb2^]=91rr?H2!!#:_rrN,Vq:u&O-Hf*a
-*?FVK!8"@Q!e11MK)_GB!WW4MnG`L?Z2XlT!$Kek!R)kg!!';%rrBh4!!#mqrr@cP
-!":0-g&M)rF<pneU]8R;!!">CrrXPI!%%"3!l'HOm/I+K-2mlEU\Xoi-2mlEg&D!O
-A,QB0,s4:9qu?g]s8U=B!!">Drr=AD!!">DrrBh5!!"=orr_-Y!5F-c_uB`X,g0Nq
-(BF9H!6kEA!8"@R!8mbT!9a16!<=Ii9`Z7Tnc&Z_+LeKQ!e11MK)_GB!WW4Mo)Acp
-0UK'E!e11mec,[4-2dfDU\aujL&CuOA,cK.-2[`D,piHh!l+cZrVupEr;QaZrVurB
-ec,VkrVup\q#:>9rVuq?rVlj[p&G)&rr2tPrVupErVlk-r;Zh-r;QaCrVurBeGfX.
-!!'ccs24j;*@/g8!>bb3^]<$crr@<B!!#!gIfL>a!!'5$rrD?[h#RL&b=r!X*V9:5
-T-++NXT&?O!!("<!-J2d"$A\f^OlLFrrN0#J+WaDY:oq^n$2loIfLVArr@cO!!&eh
-rr>1[!!M!Ts3*V"!!d$6s5kU-!'L2Z!)`^q!6j!n!)`^q!2K>h"Qh!1!'L2Z!'L&W
-!BdXcrr@cP!!#.[rrBh4!!'e3rr>1\!!%`&rr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M
-!+>a*!2$e$!+>a*!2'5i!:'C9!<=Ii9`Z7Tp&>&b+T;?@E30'@IfKJgrrAhi!!+C1
-K)ap3!WW4MpAY/s0`D%P:pBs$IfLVArrA;_!!&efrr>1\!!(^NrrIg"qu?dE;6g*"
-"!mpI;>gFoPl:X_g"$*)ffUQjpAY5i,pg>'rrJlWr?VJAU\k&k^]"35U\t,o49,A'
-qu6YMrVuq_eGfX.!!'ccs24j;*@/g8!>bb3^]<$crr?I*!!&YjrrMB.]u9tDr;Zhi
-rVll_q:u&O-Hf*a*?FnS!M:M4!!(?HrrRZM!65$=L%bQJ4P>>dk5PJ_!.XeD!O"3T
-!!'4,rrRZM+OpDmKfl.'rr_ji-&)3q"PM"QPg'"(!l$j-qYpV,4L)j)!9WSH!i&Vf
-qYpSkbk_8?F<tGGrr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M!+>a*"/#Vn`Oh'/2#RCS
-TDecilM96:!%,l`!?E3VrrJ`7qZ$U5X8`6N!!(%=!/:CP!@9&h!!+C@K)b$6!WW4M
-qYpT"0_tbLpTXZ!IfLUCs+^OUhZ*YkK)`ag!?EH/?NCrCq7m!_rVlk*r;Zqls7_Sd
-MuY^5!!&YirrD?[h#RL&b=r!X*W,j;T-3q0!'mUb!e11M`r?$mrW!)Fs3-]iqu?`3
-K)b'7!WW4Mr;Qf$0_k\K+KteHIfLUCs+^OUhZ*YkK)`ag!?EH/?NCrCq7m!_rVlk*
-r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7TrVlnj+SPj9@&s;/IfKJgrr@cP!!(7A
-rrJ?1rVupEK)b'7!WW4Mrr3#&0_YPI5d11hIfLUCs+^OUhZ*YkK)`ag!?EH/?NCrC
-q7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9a)OXs8S]6RfLJ.!/:CP!6kB@
-!R)kh!!&8Js8:(@k3`0Lbi\d%!R0^"rrLg+q#:EKbfo2Kr6,0'ir9/^!.Y$P0Ve[O
-0W0C#+G0WJrr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M!+>a*!h]M^\r6VGr;ZhirVll_
-q:u&O-Hf*c*?CapR/l+D!^%c+m/I'>rVurBqu6Y\rVup\qu6]3A,R\S4I#^B!i%k(
-qu?aDZ2=P%UJ_":!Ft9irrXPI-/&4r&L@E'Z2aj!,s9l\UHBh&!'Js4rrKAerW!!G
-;8;u-!P`.C,lp,mqYpVl4=0n*!@>#2rrW6$="p9I!cn>aK)^T*"5a(Y^OlL'rrF,c
-b?k8d!;XD1f_tgM@/U',TE"DlMuY^5!!&YirrD?[h#RL&b=r$Y&eLE1hu<\@rVurB
-mJd/`rVurBqYpXD!!#.Zrr@0:!!+CirVlk-p](:VrVloO4So*Z-):J>!2KMn!/:CO
-!6kEB#DN3X,ldpB4So*Y;>pLpU\OliA,Q?,FSPn;--Z>f!+Yd(!'K<A!WW3/T)\pk
-!$HmnLAqA5!!'ccs24j;*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:
-!%,l`"<ANOIh8%Khu<\1rVurBmJd/KrVurBqu6Y+rVup\rVlk>pAb1Urr2tnqZ$UB
-rVup\rr3#]-2@ND-/&=uL&M&PL&M#OL&M&SL&_0!pAb1>rr2u'pAb3;rr2t?pAb1U
-rr2tnqZ$UBrVup\j8T5^!.0bDU&Y9,HN51?s+^OUhZ*YkK)`ag!?EH/?NCrCq7m!_
-rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9a2UYs8VP;&G?)(33.N156(]@rr@cP
-!!(71rr>1\!!(7ArrM7lr;Zh>rr2u5r;ZstKnXUprW!&Rs8R3?!!d#Xg&J<'!/:FP
-!'L2[![TrTrW!$ts8Psq!!&emrr@cP!!@rTs!@RC"XRY)!!">Err=AE!"*5[b]G-2
-!87DP^\n-8;2'^G-2mlHg&M(orW!15bh<$$,liYZrrrH'J,f8()"mq0.'\7)Qfihu
-+G0WJrr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M!+>a*!h]M^\r6VGr;ZhirVll_q:u&O
--Hf*a*?G+Y!q1UMp](:rX8`6N!!)'Z!-J/crW)mC!-Ic2!'L5\"a#HP@lu(9!!+D;
-rr2sqrVuq_rr2tPrW!'Ik5YHkrVuq_rVloOU]18nU\t0"PlLd-,ldokk5RRC!!(7A
-rr@cP!!@rTs!@UD$&/EZ49,@-s8RfP!!#mprrUl-^]+65;>pOqPlC[_L&M&T-0G7-
-A,ZH.Pl:U_fq[R,!WW4Mrr3&oNu7Wl!'%1^!e11mK)^T*"5a(Y^OlL'rrF,cb?k8d
-!;XD1f_tgM@/U',TE"DlMuY^5!!&YirrD?[h#RL&b=r!X*W,j<msboF!!#!ZrrRZM
-!9F.\jsB[#!6k$6!'KoS!@>thrs7a5!!#mrk&_pJ!!#mqrrAhm!!,3WqYpOmrVuq?
-rVlk>rW!"ps#g8\!6kEA!/:CP",6dT-2mlEPlC[i@fQKks8OAF!%$e&rs7a5!!#mr
-k&_pJ!!#mqrrAhm!!,3WhZ!WW!.XqH!r%`mq>^L4YQ"ZR!$HmnLAqA5!!'ccs24j;
-*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E3VrrVY=&GuM/
-&GN:+!e11Mj8T*Ap&G(=nc&SOpAb7@A*3ai!2KMn!d%ouqu?^or;Qb,qu?a[U\t,p
-,ldokk5G;[bl.SDL&X:7!!(7Arr@cP!!^4<s!7XF4T,3^@o:qZU](5nFSGe8U](5p
-FCQWp!!#morr?R,!!,3Wi;WiY!.XkF!r%`mqZ$WZYl=cS!$HmnLAqA5!!'ccs24j;
-*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E3TrrVY=&H)S/
-YH7a*IfKK.rr^K!Kk()^"Ja2bL$%q*!'L#V!@>#Jrr@cJ!!,s3qYpS<-2[`K;<IoY
-js:!--2dcCbl.SDL&X:7!!(7Arr@cP!!^[Is!7XF4S\pVA,ZH.g%YLHL%kWK;8;u-
-!H]Xc!!,sZir9&[!.XeD!r%`mr;ZhYYl=cS!$K\h!R.><K`Rt2lMgs?,s9D's4I>R
-hZ*YkK)`ag!?EH/?NCrCq7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7T
-p&>3aIh2S[:osZuIfKK+rr@cP!!(71rr>1\!!">B!!+Bfr;QbNqZ$[D;8;l*!p3u=
-r;ZpGg&K:q!!#.ZrrC:B!!7lSFT)7?bl.PAL&M&Vbl@\h!!#.VrrY@`!%%@=!/::M
-![U^Yp\t<W@jV'R!@?FZrrN0#J+imGpQ$-k!&1YW!e11mdf0;EqZ$[D;8;Jt"!mpI
-4T,3\k(UR7rrTrhg!Tg%hZ*YkK)`ag!?EH/?NCrCq7m!_rVlkBr;Zmq^U1Rc!$D.>
-!2oeq!:'C9!<=Ii9`Z7ToD\s^Ih2nSXoAHP!!(pV!/:CP!86c>!'L5\"52@;-2[`D
-4PB`6!/:@O![V@=o)A`E-2mlK;?-YB!!">CrrAhn!!8qqL&M&P^]"04L&M&Vbl@\h
-!!#.VrrY@`!%%@=!/:@O![V@=o)A`E-2mlE;<.ZX!!%N@rri(W(]`0mrrRZM+Og>k
-jsBd&!-IW."!mpI4T59_fd-UuFI)q,Pl:X_Z-rXShZ*YkK)`ag!?EH/?NCrCq7m!Y
-rVllDXoJIJrVllYq:u&O-Hf*a*?F\M!q1W:XoAHP!!(pV"0hh+-1(X34T5<abl@_*
-@jV'R"=:>Qs.fPn!'L,X!l'HBq#:TC,ldoks8ODE!!'e4rrtRc!%$e-Pl:X_L&M#O
-L&M&Vbl@\h!!#.Vrr@0?!!&ekrrgR!s8Skn!!#.XrrTrhg%bRMbU!5h-0,",!!%N>
-rrVqUO0S]dIfLV?rrC::!!$NsrrXPI!'L5[!/:CP!%!s2!'L5\!)_2E"5a(Y^OlL'
-rrF,cb?k8d!;XD2_YsH5!'mag!$M4>!9!\/!<=Ii9`Z7TRf<G=!!(mU!l'HOm/I&J
-rVurBrVloO4T#0]^]4<[rW!I+^]4>rUJV!k4TGG'4ES@;rs-:b!!">Fs+UFP"=9he
-^HDJq"&]*ubl.SG4MT+TKfo>7#0d,I,ldp-q#:?/rVusFPlC[fUHAMVZ2ahMrW!I+
-^]4>rUJV!k4TGG'4ES@;rrg(_!!">*rrN0#J"Q`BIfLV?rrC:B!!IDfbbI<!!!':m
-rrXPI!'L5[!2KMn!)]'^!+Z!.!0kq3"5a(Y^OlL'rrF,cb?k8d!;O>0j8JuYh[$Lf
-!>+/errD]dh#RL&b=r!X*Ld!0IfKJgrr>1\!!(7?rr?R-!!>@`s+U@Nr[%LC!^-M,
-r;cgCr;Zgprr2sEp](=@g&D!O-2%<CPlLb0!!#.Urr>pp!<+;C!!@rTs+U@Nr[%LC
-!^-M,r;cgCr;Zgpj8T/\!.UX@!e11me,KElrVuqPrVlk-rVup\n,EJ9!!#.ZrrSrX
-A!HupKfk(:rr_-Y!5F-c_uB`X,g0Nq(BF6G!6kB@!S9<=!!3F.fDPXKj7qF2!%,l`
-!?E2LrrRZM!65$=4T5<\bkh>>U](5n4T>?\FS>b<--ZDO-27H@-/&:t!P]rV!!&em
-rr@07!!\/Ws!7XF4SJdT4SSmW-/&:t!-Ir8"=;:ljsBd&!@?FZrrN0#J"Q`BIfLV?
-rrA;_!!%`NrrY@`!%%+6"!mpI4G*Ucrr_-Y!5F-c_uB`X,g0Nq(BF3F!9O+X!T-HH
-!!@G[^UM1U!+c$.!I+#0rrDQ_h#RL&b=r!X*Ld!0IfKJgrr]MP!'L&V"0jsNbl.PC
-^JQ<T!!4HgoD\aj^HDAn![U^sr;QfA4T#0[4L+e`!H]Xc!!">E!!\\fs!7XFFS5Y7
-F=$hb!@<HsrrTr4-2[`E-$8bXrrKksqZ$[D;;'t/!WW4MTDntB!$Kbj!/:CP!5JI3
-"$?P`-1Cj9,ldp-nG`R6bi[LV!TqW(rrLfsqYpTLbl.PCKfk(grr^r=UZVLS!jOjt
-rr3)_UQjI'rrQ[mZ2Xb)b_<ggrr_-Y!5F-c_uB`X,g0Nq(BF3F!Q+O,rr?I*!!Akn
-s7F:^!/CFP!2'/g!;-!@!<=Ii9`Z7TRf<G=!!("<!TqVmrrgQ@Ktl=:rrCaNK`Rt2
-q#:?/re1?ep\tN6KnZ;Ts)]Psrr3&7;0;C/"J^ZJKtm?]"O*Wp^Y/G_!87=)!Mef8
-rrN0#J"Q`BIfLVWrrZaW4Qc&2!/:CP!6kB@"!mpI-2dcIk&`^3,s7t"rrXPI!'L5[
-"2?-.A,?30@jM*T,pe9DrrQ%DFSYq=YpC]koD]EU4=-d&^JQ:'!%"E?s+LFQA,Q?2
-K`D*8s8Skn!!9pZ4T5<]-$9.d#Nd<4!/:#A-2mlE;>gFrKdA%?rr314!!">FUF#m>
-!@=N:rrJm:r]C48k3r<PhZ*YkK)`ag!?EH/?NCrCp:p^Op&+gi@/U'-TE"r``Rb*E
-r;Zhir;Qcdp"]WK-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$LY.!87>O!/9h?!/:CP
-!6kEA!-J2?!)`^p!JMis!!#.ZrrXPI!'L5["?ZYa-0G.*!'L)X"!u1kA,ZH.Z24J&
-,ldokoD\qj!!"<BqZ$gHs8OAF!%%RC#!;kc-3+"!rVus]-2RZEU]:A<rVusF-2RZB
-A,ZE0,ldokrr2s\rVup\qZ$XCk5>5[KdHTr!@<Hhrr_-Y!5F-c_uB`X,g0Nq(BF*C
-!:0U`!+>a*"/#VnoYoD^LA_)PTDecimI]38!%,l`!?E2LrrRZM!.t6BrrN0#J"Q`B
-IfLVXrrC:B!!%`?rr@cP!!LOGs4Lo\!!'e5rr@09!!$O-rrXPI!'L5[!'L5\!6kEA
-!'L#V!^-L)rVusFoDJUgL&M&P4S/RQ4SAaYbl8sh!%%RC"sj6L-3+"!p&G1Ws8U=:
-!!">DrrXPI!%%XE!'KrT!-J2>!'KuU!'KfO"5a(Y^OlL'rrF,cb?k8d!;+&,kPbD\
-@/U'-TE"r``Rb*Er;ZhirVll_o\BNJ-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$LY.
-!6kEB!/9h?!'L5\!^&Rkqu?_,rr2u'r;ZmF4=0q+!5JO5"!mpI4T59^49,@-rVlkO
-rW!9OUWfJq!!#mrjsC!,!+Ys,!%%UE!2K/c!'L/Z![U]@rVuuCg&:sO-2dcI,ldok
-s8RfM!!k]^49,@-s8U=?!!4I2A,ZH.bl7VE,ldp-rr2s\qZ$e0UEom?4T>?\4T,6^
-4GAJdrVupEnc&^K!!'ccs24j;*@/g8!>bb.^]<Qrrr?I*!!@G[^UM1U!+l*/!2'5i
-!:'44!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@!e11mnG`Na4T6Z+!<"2D;=XYd4SJgU
-A,ZE-4T5<`4Qc\DA,ZH.A,cK1,ldp-rVls^!!">Drr=AE!!'e4rrJ@Krr2tPr;Zi4
-rr2tPrVupEo)A\Pr;Zq0oDaOD!!1<frVup\r;QsI!!">Fs+U@N"$HV`L&M&Rg&K:o
-!!=Oks31HB!0mK_"!mpI4T>?\4T#0cA,lQk!!">Fs-3K_!@>MZrrXPI!%%18"5a(Y
-^OlL'rrF,cb?k8d!;+&,kPbD\@(61:TDecilL`m5!%,l`!?E2LrrRZM!.t6BrrN0#
-J"Q`BIfLV\rr=A<!!%`Drr>1W!!+C1rVllNrVusFk5G;^,ldokrr3'H!!#.[rrXPI
-!%%XE!/:CP!-Ir7!'L5\!)`aq!%%UE!/:"D!'L5\!+Z$."eu%t-0EGN!!#.ZrrsbL
-!%%[FL&CuS-0G7-L&M&Rbl>ob!!BM+s31HB",6dTbl.SB4T>?\4T,6[4T>?b49,@-
-s8ODE!!'e3rrXPI!%%18"5a(Y^OlL'rrF,cb?k8d!;+&,kPbD\@(61:TDecilL`m5
-!%,l`!?E2LrrRZM!.t6BrrN0#J"Q`BIfLV\rr@06!!'e)rr>1\!<,(]A#&r$!/:CP
-!+Ys,"$?P`-3!oH,ldp-rVlsG!!">ErrXPI!%%=<!3uJ&!l+bhrVupEnc&_S!!">:
-rVm"S4L+q1rVup\r;QsI!!#.]s+UCO!/:FP!+Z!.!mL\gr;Zgprr2tnrW!%Ss8U=B
-!!#.\rr>1[!!'e5rrj\K!%%ZurVup\r;Qo^,ldp-nc&^K!!'ccs24j;*@/g8!>bb.
-^]<Qrrr?I*!!Akns7F:^!/CFP!2'5i!:'44!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@
-!e11mn,ELCP_Fhj!!IDfb`om4rrY@`!%%@=!+Z!.!2KJl"$?P`-3!oH,ldp-rVm3N
-!!">Fs5kU-!)`Cg!)`^q!^-K/rVuqPnc&\R!!">?rrC:B!!#.ZrrsbL!'L;]L&M&Q
--0G4,!'L5\!mL\gr;Zhmrr2tPrW!%Ss8U=B!!#.\rr>1\!!">Drrj\K!%%Z?rVuqP
-r;Qc@rVuq.nc&^K!!'ccs24j;*@/g8!>bb.^]<Qrrr?I*!!Akns7F:^!/CFP!2'5i
-!:'44!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@!e11mm/I(0rVuqPmJd87!!#.Trr>1\
-!!(7@rrY@`!%%XE"!mpI4T59a,ldoks8U=B!!%`FrrBh4!!#mq!!">7rrY@`!%%C>
-"!mpI4T,3`,ldp-s8P4\!!#.[rr>1\!!:CEL&M&P-2miDL&M&SL&_1srVup\rr2sE
-rVuq?rVm$I!!">FL&M&PL&CrNL&M&PL%50FhZ*YkK)`ag!?EH/?NCrCoY:IirVlk*
-r;Zqls8V`1f)UR(!!&YirrD?Vh#RL&b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+RK+.
-bl.SBPjSJQ,ldp-pAY,HrVuqnr;QjF!!">ErrXPI!'L5["sj6L-3+"hrVuqPoD\f#
-q>^MLnG`SQ!!">>rrXPI!'L2Z"sj6L4TGFDrVuq.rVlj[rW!#Ds+UFP!%%UD!/:CP
-",6dTbl.SB4T>?\-2mlEU](2r,ldoks+UFP!/:@N!'L5\!2K)a"5a(Y^OlL'rrF,c
-b?k8d!;+&,kPbD\@/U'-TE"r``Rb*Er;ZhirVll_o\BNJ-Hf*a*?CUK!e11MK)_GB
-!WW4MTDntB!$LY."Qh!1!86c>"!mpI4SJdTU](5n;>pLpPl:X_A,cK1,ldp-rVlsG
-!!">ErrXPI!'L/Y!TqW'rrM7.qu?^Cn,EJP!!">>rrXPI!%%RC"sj6L4TGFDrVuqP
-rVlkOrW!"as+UFP!'L5[!6kEB"&]*ubl.SB4T>?\-2mlEbl.PA4T5<]ft[Ld!+Z!-
-!0mE^!6k!5"5a(Y^OlL'rrF,cb?k8d!;+&,kPbD\@/U'-TE"r``Rb*Er;ZhirVll_
-o\BNJ-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$LV-!p53Om/I/6!!#.Srr=AE!!?`T
-b_>uq!5JO5"!mpI4T59^,ldokrr2sqrW!4$g&M*7@jM+;qu6Y+qu?_Nn,EJP!!">>
-rr>1\!!J#"b`m5K!!>@`s#g8\!/:CO!/:CP!d+HrrVup\rVllArW!$_s8U=B!!#.\
-rr=AE!!(7Arr>1\!"$F?,ldok^]4=uqu?`@nc&^K!!'ccs24j;*@/g8!>bb.^]<Qr
-rr?I*!!Akns7F:^!/CFP!2'5i!:'44!<=Ii9`Z7TRf<G=!!(^P!P_M1,lqN<jo5>P
-rr3"/;;M6Rjuh>orrg)64?S>jrrM8(r]C1Fo)Acr4I#aC"MZ89s7?)@!5I7f!WW4M
-TDntB!$Kbj"!mpI4SA^SL%bQIA,ZE0,ldp-rVlsG!!">ErrBh3!<+;D!!">BrrM^;
-rVusFk3r<P49,@-p\t58p&G1@s8P4\!!&8^rrC:B!!5:_L&M&P;>gFu,ldoks8U=B
-!!#.\rr=AE!!(^Nrr@cP!!7lSFSu1?,piEg!86oB"5a(Y^OlL'rrF,cb?k8d!;+&,
-kPbD\@/U'-:Odk?`G5H@r;ZhirVll_o\BNJ-Hf*a*?CUK!e11MgA_5L!!*!\"!mpn
-^Zb\!o/qa+rrG5.h>[O=!6kB@#GV8F4?NU+oD&=jYpBB44='tio`#$b,liYrrrdEi
-s8U=>!!%`,rrN0#J"Q`BIfLV?rrXPI!'KoR!)`Ol!'L2Z"!mpI4T59^,ldokrVlkm
-pAb2'qYpOXrVuq.mf*AO!!">>rrM7.pAb:As8QU.!!(7ArrCaO!!5:_U](5nL&CrT
-,ldoks8UdO!!#.\rrXPI!%%RC!0mH_",6dT4Sf$[,ldoknG`UJ!!'ccs24j;*@/g8
-!>bb.^]<Qrrr?H:!!&YirrD?Vh#RL&b=r!X*Ld!0IfKK'rr_C0-,9EY!gE[2kl1_.
-!/:FP!SP]SrrhIH!!(7Ars7a54S/UQUB"g!rrOJm^]+67@fU$3rrZ*u!/:=M"smdZ
-s+LHJr6,04gA_3S!.UX@!e11me,KNF,pfhfrrI3fr;ZjEA,H9.49,AVrVltR,pd[2
-rrKksqu?dE;8;u-!87>O!@?mrrrZ*u!'KuT!R*\(!!aer!!">Fs-3K_!87;M"XO-K
-;?,>K!!&8]rrZ*u!%%XE"&T%EZ2Xb*;#gSBr;QcMrVuq_rr3"@-2dfH;02d<-1Lp:
-hZ*YkK)`ag!?EH/?NCrCoY:IirVlk*\,ZN$rVll_o\BNJ-Hf*a*?CUK!e11Mg]%>>
-!-J,<!`8s4l2Lh/!/92-"dC;5493V(rrR9BU](2o4=0.drrSqqFSu.>,pi9b"I&mK
-!/:@N#Nd>-s8PqBk1'D4!!%M@rrRZM+Me!\k*1RRPihfA!R06orrM9Eq>UWOKlggh
-k4nrVA,ZH.A*s9uk$qoSo`#6NP_Fh8s3*Sf^]+67F?Hi*rrTGfA,cK0PWXZsrr^qO
-;;(pJ!87;M"6NHXg&(dNKfk(drs6AnL"ZJg!!">7rr_-Y!5F-c_uB`X,g0Nq(BF*C
-!9a=\!+>a*"/#VnoYoD^LA_)PTDecilL`m5!%,l`!?E2LrrRZM!8IMTK`H5lrrTrh
-^]"09UHBhbA(ge[&E[Ib,s7t&s'n.k,s7Fl@o<4)"m0;W,s7Fjrs+ccs._\&4I#U?
-#0['0^P)[3rVlm\-2dcEK`InErrTrWPl1O^4=0b%"kb23K`Hi)rrJ?1rr3!F-.Dkq
-!!%M@rrRZM+Hla*jsC!,!83M7"!mpI4Ri@QhZ*YkK)`ag!?EH/?NCrCoY:IirVlk*
-r;Zqls8V`1f)UR(!!&YirrD?Vh#RL&b=r!X*Ld!0IfKK'rr^pS-):26#@d`[4?Oo9
-U]19*YpBB44='u;s'n.k,s7Fl4=1",#GWRF4?Oni4T>?dKdC4T4?OniFSPk?fq\TI
-K`K?qrrFDlr;Qi5!/:%E!p1dTp\tCZ4TC*8L&CrO;*=jX"slCH@m"89f`)!Q!.UX@
-!dF\NP5bN9rVupqOoGEVrVuq.nG`U:!!'ccs24j;*@/g8!>bb/^]DaTrVlk*r;Zql
-s8V`1f)UR(!!&YirrMiOp"]WK-Hf*a*?CUK!e11MgA_A!!!"<-L!9Go!egVarr38J
-,ph^Rs!8u+rr31"!5JQX!/:FP#<X=4s5kUR^]+6B@fU$=s+LG!bl@^e,pi3`!egWu
-rVlmE4T,3\bQ(N3rrQ[1L%tZPF9')UK`Hi)rsU3-s8U:C,lf5;!!%,orrN0#J"Q`C
-QN.$KPQ(V/rVuqnR/[01r;Qf4-2mlE^[V7*[f?ESK)`ag!?EH/?NCrCp:p[\qu6Y(
-r;Zqls8V`1f)UR(!!&YhrrN&[p>#`L-Hf*a*?CUK!e11Mg&D,g;'l2A!@;7SrrOJm
-oDS[nUB$PYUB#E7rs$5#Z2`#JL&V)V4=1%-PQ6F8rrsbqk5U,8Pl:U`493UurrRlS
-bl.PB,s;,*!mCX,o`"u&!'L&V#JU7ms8RcQL&M#]bQ->rs-*LG^]4>K,lj^orrN0#
-J"Q`C[f?ESPlC`urVupERK!EC,lf5;r]L,Z!'K`M".oPnkCW`OrrF,cb?k8d!;F80
-b5M5;!+>a*"/#VnoYoD^LA_)PTDSWhrSdM,!<=Ii9`Z7TRf<G=!!(UM$GU[F,lg(!
-s5kUir6,A?!'L:'!5J@0!mCXurr30b-3+!-!6kB@#%IYWs+LHsrVlqQ!6k-9!egWu
-rVlmE4T,3\bQ'currQ[14SSjV4?WWC!egW.rVln?-3!oFo?@.4!l"^tgA_3S!.UX@
-"4$rIYE]%eFT)7?A"!>sL%bQJ--YiX!dF\FK)`^f!?EH/?NCrCpV6e%r;QiULEZTr
-""6E"4iK8Y,5hKC18!b-rrMuQptYrN-Hf*a*?CUK!e11Me,KU649/mkbkM/@4T@MD
-bk_8?bQ*@rrrkM2s8P2-qu6kS!/:H,!6kEA!egWup&>)I!6kEA!@9l+rrUCEFS>_9
-;#i`QrrQ[Vbl7VDK`Hi*rrG5ZpAY.>-//A#!!%M@rr_]i!+;&k!+Z!.!83e?!SJdp
-!!,48mf*>:!%<I!_Z'WW,g0Nq(BF6G!7^rH!M9q1!!*@\r;Qc`ptYrN-Hf*a*?CUK
-!e11Mg]%:aA,?30js;>RbQ'd%bQQW!;#ni9rrUCEL&V)V4=1%-4=0.frs"/WU]6#J
-bl.PCK`K?irrRlSbl.PB,piKh!i#aLq#:HY49/mbrrFDGr$;RJ,pe9Fjs?errrFDl
-gA_3S!.UU?"$chtpQY[Z;'g=MrrJm:r]C6ZL"Ykn"5a(YG_5t4rrF,cb?k8d!;O>0
-oDS[hVm$.$TDeciqY8kI!%,l`!?E2LrrRZM!8IMT,ph^Mrrj\ps8OAkqu6iQs8RcQ
-U\t,q;3_+)!/:FP#!=43s'l&Dr;Qsu!6kIs!6kEA!egWup&>)I!6kEA!^%dkrVlq@
-!5J@0"7mf=FS5Y6;>`N^,lf5RPlIL)k5PA^@m&oOrrFDlgA_3S!.UU?".&uf[t=X:
-rr\#V!5F-c_Z'WW,g0Nq(BF9H!6G-=!V[G8!!*AorVllWq:u&O-Hf*a*?CUK!e11M
-g]%@c!'KlNrs+5XA,lQk!5JL4#)*%es1\P2rVm(s!-J7b!/:FP#!=43s.]R(rVm,b
-,piTkK`K?qrrRlSbk:u;K`K?qrrSDbL&M#P,pi?d!^$IXmf*?B!/:FP!Fn7jrrQ[1
-L&M#QPQ54IrrN0#J"HZBk5YKYK)^`."8=JL(kVe(rrF,cb?k8d!;XD1f)>UKVlg""
-\,H=,kP<p7!%,l`!?E2LrrRZM!8@H&49-[L^W`HM!%$e-s1\O[U]:@Y!%$e-s%rc+
-k5V\4-0G6O!%#D5s#_V,rs_'jA*3g+491WGs+LHsrVlqQ!6k-9!egWur;R!J!0mNG
-491*7rs+cNPlLcJ!%%Jqrr3!r;>L4nK`Hi+rrFEfrVm2d,lj20s-*L0k1]h:!!%M>
-rr[3?!7-8sMuNm?!!&(3s2"^9*@/g8!>bb3^]<$crr?I*!!8Men@FPY2#RCSTDeci
-lM96:!%,l`!?E2LrrRZM!87AQ;'l,?!E%PKrs,;F!$rok--Z>f##P@H,lf78rr30b
-!!%-@4=0t+##P@H,lf6Urr3%R!6kEA!egWup&>)I!6kB@#0]10,p`P$rVm%T!/:IQ
-4S\sW-3!oF,piBe#DE/3s8UaPbl%JG^Eik+,lg'Og&D*R!.UR>"6Tpi:kJ_+rri'5
-!#YH^s2"^9*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E2L
-rrRZM!8.;Tk+dWaPhGm4"2BPD^\[s4fnG-Tqu6i7PhH)ibl%JCfnG-Tr;Qfhbl%JA
-o??k,!V=P2rr]$ML"ZD("nTt0s8UdIbl7VCbfon_#4p(1s8Tifq>UQ3Kn[:nrrN0#
-J"6N@Du]m!K)^i1"(2*/YCceirrF,cb?k8d!;XD1f_tgM@/U',TE"DlMuY^5!!&Yi
-rrD?[h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M=rrhL-!!'K[s,[0^NrT/FK)`Uc!?EH/
-?NCrCq7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WNT)Sil
-!.UL<"O@>R&C5t.OoGQf!!"/1K)`Uc!?EH/?NCrCq7m!_rVlk*r;Znks7!UY!&XWS
-!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UI;"Kqe*#cE:SPQ(c@!!!;VK)`Rb
-!?EH/?NCrCq7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WN
-T)Sil!.UF:!13Zb!Isiqs-N`hmoTPi&@[8k^&J*R,g0Nq(BF9H!8.8M!+>a*!h]M^
-\r6VGr;ZhirVll_q:u&O-Hf*a*?CUK!e11MK)_GB!WW4MR/[?)&-)\IT7[*3rs&4I
-&-)\Yf7O%8rrF,cb?k8d!;XD1f_tgM@/U',TE"DlMuY^5!!&YirrD?[h#RL&b=r!X
-*Ld!0IfKJ#s.95l!!%M8rrM"*rW!!BE6j.9TDnu%BGg^K!D)[2s1A:3*@/g8!>bb3
-^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E2LrrRZM!.t6BrrN0#J!L$7
-T-4(4"!D!$ItGG6^BBUIIo$^T!!+dgK)`C]!?EH/?NCrCq7m!_rVlk*r;Znks7!UY
-!&XWS!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WNT)Sil!.U75!r%HuJcM8?!AL^/s0r"/
-*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E2LrrRZM!.t6B
-rrN0#J!'a5f7-%FJcMSH":.7`Qf!Dp[Jp7J,g0Nq(BF9H!8.8M!+>a*!h]M^\r6VG
-r;ZhirVll_q:u&O-Hf*a*?CUK!e11MK)_GB!WW4MK)^H&K)^H&h>[Kr,g0Nq(BF9H
-!8.8M!+>a*"/#VnV7VZd2#RCSTDecilM96:!%,l`!?E2LrrRZM!.t6BrrN0#ItI]P
-s+:9&s5!\U*@/g8!>bb3^]<$crr?I*!!Jqos81$QW;o0]!!&YirrD?[h#RL&b=r!X
-*Ld!0IfKJ#s.95l!!%M#s+:9&s+::,rrF,cb?k8d!;XD1f_tgM@/U'*T=Fn$@/U'*
-TDecilM96:!%,l`!?E2LrrRZM!.t6BrrN0#ItI]Ps+:9&s5!\U*@/g8!>bb3^]<$c
-rr?I*!!&(irr?I*!!&YirrD?[h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M#s+:9&s+::,
-rrF,cb?k8d!;XD1f)>UKVlg""\,H=,l1s-9!%,l`!?E2LrrRZM!.o]lIf]TMItI]P
-s+:9&s5!\U*@/g8!>bb3^];ISrrMj2YQ+\0n,<7djS@U4!%,l`!?E2Lrr@h+!1Elf
-ItI]Ps+:9&s5!\U*@/g8!>bb2^]=!)rrA[q!!&YirrDulh#RL&b=r!X*Ld!/f,0)>
-S,`R,c[u1Ks+:9&s5!\U*@/g8!>bb2^];m^rrJ/dZiC+4L]%/PnG(f?!%,l`!?E24
-s+:9&s+:9&s+:90rrF,cb?k8d!;F8/p&+gkhg\2,5QXKKkPY>\r87;*!<=Ii9`Z7T
-K)^H&K)^H&K)^H&N;io!,g0Nq(BF3F!QtA@rrN,^pY>iM-Hf*a*?Bb3K)^H&K)^H&
-K)^f0!?EH/?NCrCp:p[\X8`5"kP!^4!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d
-!;4,.deBpE!Vk[Ih#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>bb.^]MC0pTjf"
-p?;,(!<=Ii9`Z7TK)^H&K)^H&K)^H&N;io!,g0Nq(BF!@!QrpJhu^uM^>A8Zl/pjm
-h#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&
-s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8
-!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&
-b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&
-s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ
-^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X
-*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90
-rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KSt
-I*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<C
-s+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,c
-b?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H
-!%,l`!?E24s+:9&s+:9&s+:90rr=Bt!1s5k*eOEDs+:9&s+:9&s,?sXYKD=qDbnQ+
-!ddFabC9OkB?G](YCce+s+:9&s+:9Grr
-~>
-grestore
-currentdict /inputf undef
-currentdict /pstr undef
diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1
index a4525457cb..631408b436 100644
--- a/docs/man/xm.pod.1
+++ b/docs/man/xm.pod.1
@@ -1007,384 +1007,6 @@ Delete a vnet.
=back
-=head1 ACCESS CONTROL SUBCOMMANDS
-
-Access Control in Xen consists of two components: (i) The Access
-Control Policy (ACP) defines security labels and access rules based on
-these labels. (ii) The Access Control Module (ACM) makes access control
-decisions by interpreting the policy when domains require to
-communicate or to access resources. The Xen access control has
-sufficient mechanisms in place to enforce the access decisions even
-against maliciously acting user domains (mandatory access control).
-
-Access rights for domains in Xen are determined by the domain security
-label only and not based on the domain Name or ID. The ACP specifies
-security labels that can then be assigned to domains and
-resources. Every domain must be assigned exactly one security label,
-otherwise access control decisions could become indeterministic. ACPs
-are distinguished by their name, which is a parameter to most of the
-subcommands described below. Currently, the ACP specifies two ways to
-interpret labels:
-
-(1) Simple Type Enforcement: Labels are interpreted to decide access
-of domains to communication means and virtual or physical
-resources. Communication between domains as well as access to
-resources are forbidden by default and can only take place if they are
-explicitly allowed by the security policy. The proper assignment of
-labels to domains controls the sharing of information (directly
-through communication or indirectly through shared resources) between
-domains. This interpretation allows to control the overt (intended)
-communication channels in Xen.
-
-(2) Chinese Wall: Labels are interpreted to decide which domains can
-co-exist (be run simultaneously) on the same system. This
-interpretation allows to prevent direct covert (unintended) channels
-and mitigates risks caused by imperfect core domain isolation
-(trade-off between security and other system requirements). For a
-short introduction to covert channels, please refer to
-http://www.multicians.org/timing-chn.html.
-
-The following subcommands help you to manage security policies in Xen
-and to assign security labels to domains. To enable access control
-security in Xen, you must compile Xen with ACM support enabled as
-described under "Configuring Security" below. There, you will find
-also examples of each subcommand described here.
-
-=over 4
-
-=item B<setpolicy> ACM I<policy>
-
-Makes the given ACM policy available to xend as a I<xend-managed policy>.
-The policy is compiled and a mapping (.map) as well as a binary (.bin)
-version of the policy is created. The policy is loaded and the system's
-bootloader is prepared to boot the system with this policy the next time
-it is started.
-
-=back
-
-=over 4
-
-I<policy> is a dot-separated list of names. The last part is the file
-name pre-fix for the policy XML file. The preceding name parts are
-translated into the local path pointing to the policy XML file
-relative to the global policy root directory
-(/etc/xen/acm-security/policies). For example,
-example.chwall_ste.client_v1 denotes the policy file
-example/chwall_ste/client_v1-security_policy.xml relative to the
-global policy root directory.
-
-=back
-
-=over 4
-
-=item B<resetpolicy>
-
-Reset the system's policy to the default state where the DEFAULT policy
-is loaded and enforced. This operation may fail if for example guest VMs are
-running and and one of them uses a different label than what Domain-0
-does. It is best to make sure that no guests are running before issuing
-this command.
-
-=item B<getpolicy> [--dumpxml]
-
-Displays information about the current xend-managed policy, such as
-name and type of the policy, the uuid xend has assigned to it on the
-local system, the version of the XML representation and the status
-of the policy, such as whether it is currently loaded into Xen or
-whether the policy is automatically loaded during system boot. With
-the I<--dumpxml> option, the XML representation of the policy is
-displayed.
-
-=item B<dumppolicy>
-
-Prints the current security policy state information of Xen.
-
-=item B<labels> [I<policy>] [B<type=dom>|B<res>|B<any>]
-
-Lists all labels of a I<type> (domain, resource, or both) that are
-defined in the I<policy>. Unless specified, the default I<policy> is
-the currently enforced access control policy. The default for I<type>
-is 'dom'. The labels are arranged in alphabetical order.
-
-=item B<addlabel> I<label> B<dom> I<configfile> [I<policy>]
-
-=item B<addlabel> I<label> B<mgt> I<domain name> [I<policy type>:I<policy>]
-
-=item B<addlabel> I<label> B<res> I<resource> [I<policy>]
-
-=item B<addlabel> I<label> B<vif-idx> I<domain name> [I<policy type>:I<policy>]
-
-
-Adds the security label with name I<label> to a domain
-I<configfile> (dom), a Xend-managed domain (mgt), to the global resource label
-file for the given I<resource> (res), or to a managed domain's virtual network
-interface (vif) that is specified by its index. Unless specified,
-the default I<policy> is the currently enforced access control policy.
-This subcommand also verifies that the I<policy> definition supports the
-specified I<label> name.
-
-The only I<policy type> that is currently supported is I<ACM>.
-
-=item B<rmlabel> B<dom> I<configfile>
-
-=item B<rmlabel> B<mgt> I<domain name>
-
-=item B<rmlabel> B<res> I<resource>
-
-=item B<rmlabel> B<vif-idx> I<domain name>
-
-Works the same as the B<addlabel> command (above), except that this
-command will remove the label from the domain I<configfile> (dom),
-a Xend-managed domain (mgt), the global resource label file (res),
-or a managed domain's network interface (vif).
-
-=item B<getlabel> B<dom> I<configfile>
-
-=item B<getlabel> B<mgt> I<domain name>
-
-=item B<getlabel> B<res> I<resource>
-
-=item B<getlabel> B<vif-idx> I<domain name>
-
-Shows the label for a domain's configuration in the given I<configfile>,
-a xend-managed domain (mgt), a resource, or a managed domain's network
-interface (vif).
-
-=item B<resources>
-
-Lists all resources in the global resource label file. Each resource
-is listed with its associated label and policy name.
-
-=item B<dry-run> I<configfile>
-
-Determines if the specified I<configfile> describes a domain with a valid
-security configuration for type enforcement. The test shows the policy
-decision made for each resource label against the domain label as well as
-the overall decision.
-
-B<CONFIGURING SECURITY>
-
-=over 4
-
-In xen_source_dir/Config.mk set the following parameter:
-
- XSM_ENABLE ?= y
- ACM_SECURITY ?= y
-
-Then recompile and install xen and the security tools and then reboot:
-
- cd xen_source_dir; make clean; make install
- reboot into Xen
-
-=back
-
-B<RESETTING THE SYSTEM'S SECURITY>
-
-=over 4
-
-To set the system's security policy enforcement into its default state,
-the follow command can be issued. Make sure that no guests are running
-while doing this.
-
- xm resetpolicy
-
-After this command has successfully completed, the system's DEFAULT policy
-is enforced.
-
-=back
-
-B<SETTING A SECURITY POLICY>
-
-=over 4
-
-This step sets the system's policy and automatically loads it into Xen
-for enforcement.
-
- xm setpolicy ACM example.client_v1
-
-=back
-
-B<LISTING SECURITY LABELS>
-
-=over 4
-
-This subcommand shows all labels that are defined and which can be
-attached to domains.
-
- xm labels example.client_v1 type=dom
-
-will print for our example policy:
-
- dom_BoincClient
- dom_Fun
- dom_HomeBanking
- dom_NetworkDomain
- dom_StorageDomain
- dom_SystemManagement
-
-=back
-
-B<ATTACHING A SECURITY LABEL TO A DOMAIN>
-
-=over 4
-
-The B<addlabel> subcommand can attach a security label to a domain
-configuration file, here a HomeBanking label. The example policy
-ensures that this domain does not share information with other
-non-homebanking user domains (i.e., domains labeled as dom_Fun or
-dom_Boinc) and that it will not run simultaneously with domains
-labeled as dom_Fun.
-
-We assume that the specified myconfig.xm configuration file actually
-instantiates a domain that runs workloads related to home-banking,
-probably just a browser environment for online-banking.
-
- xm addlabel dom_HomeBanking dom myconfig.xm
-
-The very simple configuration file might now look as printed
-below. The B<addlabel> subcommand added the B<access_control> entry at
-the end of the file, consisting of a label name and the policy that
-specifies this label name:
-
- kernel = "/boot/vmlinuz-2.6.16-xen"
- ramdisk="/boot/U1_home_banking_ramdisk.img"
- memory = 164
- name = "homebanking"
- vif = [ '' ]
- dhcp = "dhcp"
- access_control = ['policy=example.chwall_ste.client_v1,
- label=dom_HomeBanking']
-
-Security labels must be assigned to domain configurations because
-these labels are essential for making access control decisions as
-early as during the configuration phase of a newly instantiated
-domain. Consequently, a security-enabled Xen hypervisor will only
-start domains that have a security label configured and whose security
-label is consistent with the currently enforced policy. Otherwise,
-starting the domain will fail with the error condition "operation not
-permitted".
-
-=back
-
-B<ATTACHING A SECURITY LABEL TO A XEND-MANAGED DOMAIN>
-
-=over 4
-
-The addlabel subcommand supports labeling of domains that are managed
-by xend. This includes domains that are currently running, such as for
-example Domain-0, or those that are in a dormant state.
-Depending on the state of the system, it is possible that the new label
-is rejected. An example for a reason for the rejection of the relabeling
-of a domain would be if a domain is currently allowed to
-access its labeled resources but due to the new label would be prevented
-from accessing one or more of them.
-
- xm addlabel dom_Fun mgt Domain-0
-
-This changes the label of Domain-0 to dom_Fun under the condition that
-this new label of Domain-0 would not prevent any other domain from
-accessing its resources that are provided through Domain-0, such as for
-example network or block device access.
-
-=back
-
-B<ATTACHING A SECURITY LABEL TO A RESOURCE>
-
-=over 4
-
-The B<addlabel> subcommand can also be used to attach a security
-label to a resource. Following the home banking example from above,
-we can label a disk resource (e.g., a physical partition or a file)
-to make it accessible to the home banking domain. The example policy
-provides a resource label, res_LogicalDiskPartition1(hda1), that is
-compatible with the HomeBanking domain label.
-
- xm addlabel "res_LogicalDiskPartition1(hda1)" res phy:hda6
-
-After labeling this disk resource, it can be attached to the domain
-by adding a line to the domain configuration file. The line below
-attaches this disk to the domain at boot time.
-
- disk = [ 'phy:hda6,sda2,w' ]
-
-Alternatively, the resource can be attached after booting the domain
-by using the B<block-attach> subcommand.
-
- xm block-attach homebanking phy:hda6 sda2 w
-
-Note that labeled resources cannot be used when security is turned
-off. Any attempt to use labeled resources with security turned off
-will result in a failure with a corresponding error message. The
-solution is to enable security or, if security is no longer desired,
-to remove the resource label using the B<rmlabel> subcommand.
-
-=back
-
-B<STARTING AND LISTING LABELED DOMAINS>
-
-=over 4
-
- xm create myconfig.xm
-
- xm list --label
-
- Name ID ... Time(s) Label
- homebanking 23 ... 4.4 dom_HomeBanking
- Domain-0 0 ... 2658.8 dom_SystemManagement
-
-=back
-
-B<LISTING LABELED RESOURCES>
-
-=over 4
-
- xm resources
-
- phy:hda6
- type: ACM
- policy: example.chwall_ste.client_v1
- label: res_LogicalDiskPartition1(hda1)
- file:/xen/disk_image/disk.img
- type: ACM
- policy: example.chwall_ste.client_v1
- label: res_LogicalDiskPartition2(hda2)
-
-=back
-
-B<POLICY REPRESENTATIONS>
-
-=over 4
-
-We distinguish three representations of the Xen access control policy:
-the source XML version, its binary counterpart, and a mapping
-representation that enables the tools to deterministically translate
-back and forth between label names of the XML policy and label
-identifiers of the binary policy. All three versions must be kept
-consistent to achieve predictable security guarantees.
-
-The XML version is the version that users are supposed to create or
-change, either by manually editing the XML file or by using the Xen
-policy generation tool (B<xensec_gen>). After changing the XML file,
-run the B<setpolicy> subcommand to ensure that the new policy is
-available to xend. Use, for example, the subcommand
-B<activatepolicy> to activate the changes during the next system
-reboot.
-
-The binary version of the policy is derived from the XML policy by
-tokenizing the specified labels and is used inside Xen only. It is
-created with the B<setpolicy> subcommand. Essentially, the binary
-version is much more compact than the XML version and is easier to
-evaluate during access control decisions.
-
-The mapping version of the policy is created during the XML-to-binary
-policy translation (B<setpolicy>) and is used by xend and the management
-tools to translate between label names used as input to the tools and
-their binary identifiers (ssidrefs) used inside Xen.
-
-=back
-
-=back
-
=head1 SEE ALSO
B<xmdomain.cfg>(5), B<xentop>(1)
diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt
index 976e7c085d..750bb28463 100644
--- a/docs/misc/xsm-flask.txt
+++ b/docs/misc/xsm-flask.txt
@@ -11,7 +11,6 @@ Xen XSM:FLASK configuration
XSM_ENABLE ?= y
FLASK_ENABLE ?= y
- ACM_SECURITY ?= n
NB: Only one security module can be selected at a time. If no module is
selected, then the default DUMMY module will be enforced. The DUMMY module
diff --git a/docs/src/interface.tex b/docs/src/interface.tex
index e596b63535..6f81ead684 100644
--- a/docs/src/interface.tex
+++ b/docs/src/interface.tex
@@ -2177,47 +2177,6 @@ Most of the above are best understood by looking at the code
implementing them (in {\tt xen/common/dom0\_ops.c}) and in
the user-space tools that use them (mostly in {\tt tools/libxc}).
-\section{Access Control Module Hypercalls}
-\label{s:acmops}
-
-Hypercalls relating to the management of the Access Control Module are
-also restricted to domain 0 access for now. For more details on any or
-all of these, please see {\tt xen/include/public/acm\_ops.h}. A
-complete list is given below:
-
-\begin{quote}
-
-\hypercall{acm\_op(int cmd, void *args)}
-
-This hypercall can be used to configure the state of the ACM, query
-that state, request access control decisions and dump additional
-information.
-
-\begin{description}
-
-\item [ACMOP\_SETPOLICY:] set the access control policy
-
-\item [ACMOP\_GETPOLICY:] get the current access control policy and
- status
-
-\item [ACMOP\_DUMPSTATS:] get current access control hook invocation
- statistics
-
-\item [ACMOP\_GETSSID:] get security access control information for a
- domain
-
-\item [ACMOP\_GETDECISION:] get access decision based on the currently
- enforced access control policy
-
-\end{description}
-\end{quote}
-
-Most of the above are best understood by looking at the code
-implementing them (in {\tt xen/common/acm\_ops.c}) and in the
-user-space tools that use them (mostly in {\tt tools/security} and
-{\tt tools/python/xen/lowlevel/acm}).
-
-
\section{Debugging Hypercalls}
A few additional hypercalls are mainly useful for debugging:
diff --git a/docs/src/user.tex b/docs/src/user.tex
index 69971cdd66..a35bb86b88 100644
--- a/docs/src/user.tex
+++ b/docs/src/user.tex
@@ -2081,1927 +2081,6 @@ iptables:
iptables -A INPUT -p tcp -{}-destination-port 8002 -j REJECT
\end{verbatim}
-%% Chapter Xen Mandatory Access Control Framework
-\chapter{sHype/Xen Access Control}
-The Xen mandatory access control framework is an implementation of the
-sHype Hypervisor Security Architecture
-(www.research.ibm.com/ssd\_shype). It permits or denies communication
-and resource access of domains based on a security policy. The
-mandatory access controls are enforced in addition to the Xen core
-controls, such as memory protection. They are designed to remain
-transparent during normal operation of domains (policy-conform
-behavior) but to intervene when domains move outside their intended
-sharing behavior. This chapter will describe how the sHype access
-controls in Xen can be configured to prevent viruses from spilling
-over from one into another workload type and secrets from leaking from
-one workload type to another. sHype/Xen depends on the correct
-behavior of Domain-0 (cf previous chapter).
-
-Benefits of configuring sHype/ACM in Xen include:
-\begin{itemize}
-\item robust workload and resource protection effective against rogue
- user domains
-\item simple, platform- and operating system-independent security
- policies (ideal for heterogeneous distributed environments)
-\item safety net with minimal performance overhead in case operating
- system security is missing, does not scale, or fails
-\end{itemize}
-
-These benefits are very valuable because today's operating systems
-become increasingly complex and often have no or insufficient
-mandatory access controls. (Discretionary access controls, supported
-by most operating systems, are not effective against viruses or
-misbehaving programs.) Where mandatory access control exists (e.g.,
-SELinux), they usually deploy platform-specific, complex, and difficult
-to understand security policies. Multi-tier applications in business
-environments typically require different operating systems
-(e.g., AIX, Windows, Linux) in different tiers. Related distributed
-transactions and workloads cannot be easily protected on the OS level.
-The Xen access control framework steps in to offer a coarse-grained
-but very robust and consistent security layer and safety net across
-different platforms and operating systems.
-
-To control sharing between domains, Xen mediates all inter-domain
-communication (shared memory, events) as well as the access of domains
-to resources such as storage disks. Thus, Xen can confine distributed
-workloads (domain payloads) by permitting sharing among domains
-running the same type of workload and denying sharing between pairs of
-domains that run different workload types. We assume that--from a Xen
-perspective--only one workload type is running per user domain. To
-enable Xen to associate domains and resources with workload types,
-security labels including the workload types are attached to domains
-and resources. These labels and the hypervisor sHype controls cannot
-be manipulated or bypassed by user domains and are effective even
-against compromised or rogue domains.
-
-\section{Overview}
-This section gives an overview of how workloads can be protected using
-the sHype mandatory access control framework in Xen.
-Figure~\ref{fig:acmoverview} shows the necessary steps in activating
-the Xen workload protection. These steps are described in detail in
-Section~\ref{section:acmexample}.
-
-\begin{figure}
-\centering
-\includegraphics[width=13cm]{figs/acm_overview.eps}
-\caption{Overview of activating sHype workload protection in Xen.
- Section numbers point to representative examples.}
-\label{fig:acmoverview}
-\end{figure}
-
-First, the sHype/ACM access control must be enabled in the Xen
-distribution and the distribution must be built and installed (cf
-Subsection~\ref{subsection:acmexampleconfigure}). Before we can
-enforce security, a Xen security policy must be created (cf
-Subsection~\ref{subsection:acmexamplecreate}) and deployed (cf
-Subsection~\ref{subsection:acmexampleinstall}). This policy defines
-the workload types differentiated during access control. It also
-defines the rules that compare workload types of domains and resources
-to decide about access requests. Workload types are represented by
-security labels that can be securely associated to domains and resources (cf
-Subsections~\ref{subsection:acmexamplelabeldomains}
-and~\ref{subsection:acmexamplelabelresources}). The functioning of
-the active sHype/Xen workload protection is demonstrated using simple
-resource assignment, and domain creation tests in
-Subsection~\ref{subsection:acmexampletest}.
-Section~\ref{section:acmpolicy} describes the syntax and semantics of
-the sHype/Xen security policy in detail and introduces briefly the
-tools that are available to help you create your own sHype security policies.
-
-The next section describes all the necessary steps to create, deploy,
-and test a simple workload protection policy. It is meant to enable
-Xen users and developers to quickly try out the sHype/Xen workload
-protection. Those readers who are interested in learning more about
-how the sHype access control in Xen works and how it is configured
-using the XML security policy should read Section~\ref{section:acmpolicy}
-as well. Section~\ref{section:acmlimitations} concludes this chapter with
-current limitations of the sHype implementation for Xen.
-
-\section{Xen Workload Protection Step-by-Step}
-\label{section:acmexample}
-
-You are about to configure and deploy the Xen sHype workload protection
-by following 5 simple steps:
-\begin{itemize}
-\item configure and install sHype/Xen
-\item create a simple workload protection security policy
-\item deploy the sHype/Xen security policy
-\item associate domains and resources with workload labels,
-\item test the workload protection
-\end{itemize}
-The essential commands to create and deploy an sHype/Xen security
-policy are numbered throughout the following sections. If you want a
-quick-guide or return at a later time to go quickly through this
-demonstration, simply look for the numbered commands and apply them in
-order.
-
-\subsection{Configuring/Building sHype Support into Xen}
-\label{subsection:acmexampleconfigure}
-First, we need to configure the access control module in Xen and
-install the ACM-enabled Xen hypervisor. This step installs security
-tools and compiles sHype/ACM controls into the Xen hypervisor.
-
-To enable sHype/ACM in Xen, please edit the Config.mk file in the top
-Xen directory.
-
-\begin{verbatim}
- (1) In Config.mk
- Change: XSM_ENABLE ?= n
- To: XSM_ENABLE ?= y
-
- Change: ACM_SECURITY ?= n
- To: ACM_SECURITY ?= y
-\end{verbatim}
-
-Then install the security-enabled Xen environment as follows:
-
-\begin{verbatim}
- (2) # make world
- # make install
-\end{verbatim}
-
-Reboot into the security-enabled Xen hypervisor.
-
-\begin{verbatim}
- (3) # reboot
-\end{verbatim}
-
-Xen will boot into the default security policy. After reboot,
-you can explore the simple DEFAULT policy.
-\begin{scriptsize}
-\begin{verbatim}
-# xm getpolicy
-Supported security subsystems : ACM
-Policy name : DEFAULT
-Policy type : ACM
-Version of XML policy : 1.0
-Policy configuration : loaded
-
-# xm labels
-SystemManagement
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 941 1 r----- 38.1 ACM:DEFAULT:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-In this state, no domains can be started.
-Now, a policy can be created and loaded into the hypervisor.
-
-\subsection{Creating A WLP Policy in 3 Simple Steps with ezPolicy}
-\label{subsection:acmexamplecreate}
-
-We will use the ezPolicy tool to quickly create a policy that protects
-workloads. You will need both the Python and wxPython packages to run
-this tool. To run the tool in Domain-0, you can download the wxPython
-package from www.wxpython.org or use the command \verb|yum install wxPython|
-in Redhat/Fedora. To run the tool on MS Windows, you also need to download
-the Python package from www.python.org. After these packages are installed,
-start the ezPolicy tool with the following command:
-
-\begin{verbatim}
- (4) # xensec_ezpolicy
-\end{verbatim}
-
-Figure~\ref{fig:acmezpolicy} shows a screen-shot of the tool. The
-following steps illustrate how you can create the workload definition
-shown in Figure~\ref{fig:acmezpolicy}. You can use \verb|<CTRL>-h| to
-pop up a help window at any time. The indicators (a), (b), and (c) in
-Figure~\ref{fig:acmezpolicy} show the buttons that are used during the
-3 steps of creating a policy:
-\begin{enumerate}
-\item defining workloads
-\item defining run-time conflicts
-\item translating the workload definition into an sHype/Xen access
- control policy
-\end{enumerate}
-
-\paragraph{Defining workloads.} Workloads are defined for each
-organization and department that you enter in the left panel.
-
-To ease the transition from an unlabeled to a fully labeled workload-protection
-environment, we have added support to sHype/Xen to run unlabeled domains accessing
-unlabeled resources in addition to labeled domains accessing labeled resources.
-
-Support for running unlabeled domains on sHype/Xen is enabled by adding the
-predefined workload type and label \verb|__UNLABELED__| to the security
-policy. (This is a double underscore
-followed by the string ''\verb|UNLABELED|'' followed by a double underscore.)
-The ezPolicy tool automatically adds this organization-level workload type
-to a new workload definition (cf Figure~\ref{fig:acmezpolicy}). It can simply be
-deleted from the workload definition if no such support is desired. If unlabeled domains
-are supported in the policy, then any domain or resource that has no label will implicitly
-inherit this label when access control decisions are made. In effect, unlabeled
-domains and resources define a new workload type \verb|__UNLABELED__|, which is
-confined from any other labeled workload.
-
-Please use now the ``New Org'' button to add the organization workload types
-``A-Bank'', ``B-Bank'', and ``AutoCorp''.
-
-You can refine an organization to differentiate between multiple
-department workloads by right-clicking the organization and selecting
-\verb|Add Department| (or selecting an organization and pressing
-\verb|<CRTL>-a|). Create department workloads ``SecurityUnderwriting'',
-and ``MarketAnalysis'' for the ``A-Bank''. The resulting layout of the
-tool should be similar to the left panel shown in
-Figure~\ref{fig:acmezpolicy}.
-
-\begin{figure}[htb]
-\centering
-\includegraphics[width=13cm]{figs/acm_ezpolicy_gui.eps}
-\caption{Final layout including workload definition and Run-time Exclusion rules.}
-\label{fig:acmezpolicy}
-\end{figure}
-
-\paragraph{Defining run-time conflicts.} Workloads that shall be
-prohibited from running concurrently on the same hypervisor platform
-are grouped into ``Run-time Exclusion rules'' on the right panel of
-the window. Cautious users should include the \verb|__UNLABELED__|
-workload type in all run-time exclusion rules because any workload
-could run inside unlabeled domains.
-
-To prevent A-Bank and B-Bank workloads (including their
-departmental workloads) from running simultaneously on the same
-hypervisor system, select the organization ``A-Bank'' and, while
-pressing the \verb|<CTRL>|-key, select the organization ``B-Bank''.
-Being cautious, we also prevent unlabeled workloads from running with
-any of those workloads by pressing the \verb|<CTRL>|-key and selecting
-``\_\_UNLABELED\_\_''. Now press the button named ``Create run-time exclusion
-rule from selection''. A popup window will ask for the name for this run-time
-exclusion rule (enter a name or just hit \verb|<ENTER>|). A rule will
-appear on the right panel. The name is used as reference only and does
-not affect access control decisions.
-
-Please repeat this process to create another run-time exclusion rule
-for the department workloads ``A-Bank.SecurityUnderwriting'',
-``A-Bank.MarketAnalysis''. Also add the ``\_\_UNLABELED\_\_''
-workload type to this conflict set.
-
-The resulting layout of your window should be similar to
-Figure~\ref{fig:acmezpolicy}. Save this workload definition by
-selecting ``Save Workload Definition as ...'' in the ``File'' menu.
-This workload definition can be later refined if required.
-
-\paragraph{Translating the workload definition into an sHype/Xen access
- control policy.} To translate the workload definition into a access
-control policy understood by Xen, please select the ``Save as Xen ACM
-Security Policy'' in the ``File'' menu. Enter the following policy
-name in the popup window: \verb|mytest|. If you are running ezPolicy in
-Domain-0, the resulting policy file mytest\_security-policy.xml will
-automatically be placed into the right directory (/etc/xen/acm-security/policies/).
-If you run the tool on another system, then you need to copy the
-resulting policy file into Domain-0 before continuing. See
-Section~\ref{subsection:acmnaming} for naming conventions of security
-policies.
-
-\begin{scriptsize}
-\textbf{Note:} The support for \verb|__UNLABELED__| domains and
-resources is meant to help transitioning from an uncontrolled
-environment to a workload-protected environment by starting with
-unlabeled domains and resources and then step-by-step labeling domains
-and resources. Once all workloads are labeled, the \verb|__UNLABELED__|
-type can simply be removed from the Domain-0 label or from the policy
-through a policy update. Section~\ref{subsection:acmpolicymanagement} will
-show how unlabeled domains can be disabled by updating the
-\verb|mytest| policy at run-time.
-\end{scriptsize}
-
-\subsection{Deploying a WLP Policy}
-\label{subsection:acmexampleinstall}
-To deploy the workload protection policy we created in
-Section~\ref{subsection:acmexamplecreate}, we create a policy
-representation (mytest.bin), load it into the Xen
-hypervisor, and configure Xen to also load this policy during
-reboot.
-
-The following command translates the source policy representation
-into a format that can be loaded into Xen with sHype/ACM support,
-activates the policy, and configures this policy for future boot
-cycles into the boot sequence. Please refer to the \verb|xm|
-man page for further details:
-
-\begin{verbatim}
- (5) # xm setpolicy ACM mytest
- Successfully set the new policy.
- Supported security subsystems : ACM
- Policy name : mytest
- Policy type : ACM
- Version of XML policy : 1.0
- Policy configuration : loaded, activated for boot
-\end{verbatim}
-
-Alternatively, if installing the policy fails (e.g., because it cannot
-identify the Xen boot entry), you can manually install the policy in 3
-steps a-c.
-
-(\textit{Alternatively to 5 - step a}) Manually copy the policy binary
-file into the boot directory:
-
-\begin{scriptsize}
-\begin{verbatim}
-# cp /etc/xen/acm-security/policies/mytest.bin /boot/mytest.bin
-\end{verbatim}
-\end{scriptsize}
-
-(\textit{Alternatively to 5 - step b}) Manually add a module line to your
-Xen boot entry so that grub loads this policy file during startup:
-
-\begin{scriptsize}
-\begin{verbatim}
-title XEN Devel with 2.6.18.8
- kernel /xen.gz
- module /vmlinuz-2.6.18.8-xen root=/dev/sda3 ro console=tty0
- module /initrd-2.6.18.8-xen.img
- module /mytest.bin
-\end{verbatim}
-\end{scriptsize}
-
-(\textit{Alternatively to 5 - step c}) Reboot. Xen will choose the
-bootstrap label defined in the policy as Domain-0 label during reboot.
-After reboot, you can re-label Domain-0 at run-time,
-cf Section~\ref{subsection:acmlabeldom0}.
-
-Assuming that command (5) succeeded or you followed the alternative
-instructions above, you should see the new policy and label appear
-when listing domains:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 941 1 r----- 81.5 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-If the security label at the end of the line says ``INACTIVE'' then the
-security is not enabled. Verify the previous steps. Note: Domain-0 is
-assigned a default label (see \verb|bootstrap| policy attribute
-explained in Section~\ref{section:acmpolicy}). All other domains must
-be explicitly labeled, which we describe in detail below.
-
-\subsection{Labeling Unmanaged User Domains}
-\label{subsection:acmexamplelabeldomains}
-
-Unmanaged domains are started in Xen by using a configuration
-file. Please refer to Section~\ref{subsection:acmlabelmanageddomains}
-if you are using managed domains.
-
-The following configuration file defines \verb|domain1|:
-
-\begin{scriptsize}
-\begin{verbatim}
-# cat domain1.xm
-kernel= "/boot/vmlinuz-2.6.18.8-xen"
-memory = 128
-name = "domain1"
-vif = ['']
-dhcp = "dhcp"
-disk = ['file:/home/xen/dom_fc5/fedora.fc5.img,sda1,w', \
- 'file:/home/xen/dom_fc5/fedora.fc5.swap,sda2,w']
-root = "/dev/sda1 ro xencons=tty"
-\end{verbatim}
-\end{scriptsize}
-
-Every domain must be associated with a security label before it can start
-on sHype/Xen. Otherwise, sHype/Xen would not be able to enforce the policy
-consistently. Our \verb|mytest| policy is configured so that Xen
-assigns a default label \verb|__UNLABELED__| to domains and resources that
-have no label and supports them in a controlled manner. Since neither the domain,
-nor the resources are (yet) labeled, this domain can start under the \verb|mytest|
-policy:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm create domain1.xm
-Using config file "./domain1.xm".
-Started domain domain1
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 1 128 1 -b---- 0.7 ACM:mytest:__UNLABELED__
-Domain-0 0 875 1 r----- 84.6 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-Please shutdown domain1 so that we can move it into the protection
-domain of workload \verb|A-Bank|.
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm shutdown domain1
-(wait some seconds until the domain has shut down)
-
-#xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 875 1 r----- 86.4 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-We assume that the processing in domain1 contributes to the \verb|A-Bank| workload.
-We explore now how to transition this domain into the ``A-Bank'' workload-protection.
-The following command prints all domain labels available in the active policy:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm labels
-A-Bank
-A-Bank.MarketAnalysis
-A-Bank.SecurityUnderwriting
-AutoCorp
-B-Bank
-SystemManagement
-__UNLABELED__
-\end{verbatim}
-\end{scriptsize}
-
-Now label \verb|domain1| with the A-Bank label and another \verb|domain2|
-with the B-Bank label. Please refer to the xm man page for
-further information.
-
-\begin{verbatim}
- (6) # xm addlabel A-Bank dom domain1.xm
- # xm addlabel B-Bank dom domain2.xm
-\end{verbatim}
-
-Let us try to start the domain again:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm create domain1.xm
-Using config file "./domain1.xm".
-Error: VM's access to block device 'file:/home/xen/dom_fc5/fedora.fc5.img' denied
-\end{verbatim}
-\end{scriptsize}
-
-This error indicates that \verb|domain1|, if started, would not be able to
-access its image and swap files because they are not labeled. This
-makes sense because to confine workloads, access of domains to
-resources must be controlled. Otherwise, domains that are not allowed
-to communicate or run simultaneously could share data through storage
-resources.
-
-\subsection{Labeling Resources}
-\label{subsection:acmexamplelabelresources}
-You can use the \verb|xm labels type=res| command to list available
-resource labels. Let us assign the A-Bank resource label to the
-\verb|domain1| image file representing \verb|/dev/sda1| and to its swap file:
-
-\begin{verbatim}
- (7) # xm addlabel A-Bank res \
- file:/home/xen/dom_fc5/fedora.fc5.img
-
- # xm addlabel A-Bank res \
- file:/home/xen/dom_fc5/fedora.fc5.swap
-\end{verbatim}
-
-The following command lists all labeled resources on the system, e.g.,
-to lookup or verify the labeling:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm resources
-file:/home/xen/dom_fc5/fedora.fc5.swap
- type: ACM
- policy: mytest
- label: A-Bank
-file:/home/xen/dom_fc5/fedora.fc5.img
- type: ACM
- policy: mytest
- label: A-Bank
-\end{verbatim}
-\end{scriptsize}
-
-Starting \verb|domain1| will now succeed:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm create domain1.xm
-Using config file "./domain1.xm".
-Started domain domain1
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 3 128 1 -b---- 0.8 ACM:mytest:A-Bank
-Domain-0 0 875 1 r----- 90.9 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-Currently, if a labeled resource is moved to another location, the
-label must first be manually removed, and after the move re-attached
-using the xm commands \verb|rmlabel| and \verb|addlabel|
-respectively. Please see Section~\ref{section:acmlimitations} for
-further details.
-
-\begin{verbatim}
- (8) Label the resources of domain2 as B-Bank
- but please do not start this domain yet.
-\end{verbatim}
-
-\subsection{Testing The Xen Workload Protection}
-\label{subsection:acmexampletest}
-
-We are about to demonstrate the sHype/Xen workload protection by verifying
-\begin{itemize}
-\item that user domains with conflicting workloads cannot run
- simultaneously
-\item that user domains cannot access resources of workloads other than the
- one they are associated with
-\item that user domains cannot exchange network packets if they are not
- associated with the same workload type (not yet supported in Xen)
-\end{itemize}
-
-\paragraph{Test 1: Run-time exclusion rules.} We assume that \verb|domain1|
-with the A-Bank label is still running. While \verb|domain1| is running,
-the run-time exclusion set of our policy implies that \verb|domain2| cannot
-start because the label of \verb|domain1| includes the CHWALL type A-Bank
-and the label of \verb|domain2| includes the CHWALL type B-Bank. The
-run-time exclusion rule of our policy enforces that A-Bank and
-B-Bank cannot run at the same time on the same hypervisor platform.
-Once domain1 is stopped, saved, or migrated to another platform,
-\verb|domain2| can start. Once \verb|domain2| is started, however,
-\verb|domain1| can no longer start or resume on this system. When creating the
-Chinese Wall types for the workload labels, the ezPolicy tool policy
-translation component ensures that department workloads inherit all the
-organization types (and with it any organization exclusions).
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 3 128 1 -b---- 0.8 ACM:mytest:A-Bank
-Domain-0 0 875 1 r----- 90.9 ACM:mytest:SystemManagement
-
-# xm create domain2.xm
-Using config file "./domain2.xm".
-Error: 'Domain in conflict set with running domains'
-
-# xm shutdown domain1
-(wait some seconds until domain 1 is shut down)
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 873 1 r----- 95.3 ACM:mytest:SystemManagement
-
-# xm create domain2.xm
-Using config file "./domain2.xm".
-Started domain domain2
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain2 5 164 1 -b---- 0.3 ACM:mytest:B-Bank
-Domain-0 0 839 1 r----- 96.4 ACM:mytest:SystemManagement
-
-# xm create domain1.xm
-Using config file "domain1.xm".
-Error: 'Domain in conflict with running domains'
-
-# xm shutdown domain2
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 839 1 r----- 97.8 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-You can verify that domains with AutoCorp label can run together with
-domains labeled A-Bank or B-Bank.
-
-\paragraph{Test2: Resource access.} In this test, we will re-label the
-swap file for \verb|domain1| with the \verb|B-Bank| resource label. In a
-real environment, the swap file must be sanitized (scrubbed/zeroed) before
-it is reassigned to prevent data leaks from the A-Bank to the B-Bank workload
-through the swap file.
-
-We expect that \verb|domain1| will no longer start because it cannot access
-this resource. This test checks the sharing abilities of domains, which are
-defined by the Simple Type Enforcement Policy component.
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm rmlabel res file:/home/xen/dom_fc5/fedora.fc5.swap
-
-# xm addlabel B-Bank res file:/home/xen/dom_fc5/fedora.fc5.swap
-
-# xm resources
-file:/home/xen/dom_fc5/fedora.fc5.swap
- type: ACM
- policy: mytest
- label: B-Bank
-file:/home/xen/dom_fc5/fedora.fc5.img
- type: ACM
- policy: mytest
- label: A-Bank
-
-# xm create domain1.xm
-Using config file "./domain1.xm".
-Error:
-VM's access to block device 'file:/home/xen/dom_fc5/fedora.fc5.swap' denied
-\end{verbatim}
-\end{scriptsize}
-
-The resource authorization checks are performed before the domain is actually started
-so that failures during the startup are prevented. A domain is only started if all
-the resources specified in its configuration are accessible.
-
-\paragraph{Test 3: Communication.} In this test we would verify that
-two domains with labels A-Bank and B-Bank cannot exchange network packets
-by using the 'ping' connectivity test. It is also related to the STE
-policy. {\bf Note:} sHype/Xen does control direct communication between
-domains. However, domains associated with different workloads can
-currently still communicate through the Domain-0 virtual network. We
-are working on the sHype/ACM controls for local and remote network
-traffic through Domain-0. Please monitor the xen-devel mailing list
-for updated information.
-
-
-\subsection{Labeling Domain-0 --or-- Restricting System Authorization}
-\label{subsection:acmlabeldom0}
-The major use case for explicitly labeling or relabeling Domain-0 is to restrict
-or extend which workload types can run on a virtualized Xen system. This enables
-flexible partitioning of the physical infrastructure as well as the workloads
-running on it in a multi-platform environment.
-
-In case no Domain-0 label is explicitly stated, we automatically assigned Domain-0
-the \verb|SystemManagement| label, which includes all STE (workload) types that
-are known to the policy. In effect, the Domain-0 label authorizes the Xen system
-to run only those workload types, whose STE types are included in the Domain-0
-label. Hence, choosing the \verb|SystemManagement| label for Domain-0 permits any
-labeled domain to run. Resetting the label for Domain-0 at boot or run-time to
-a label with a subset of the known STE workload types restricts which user domains
-can run on this system. If Domain-0 is relabeled at run-time, then the new label
-must at least include all STE types of those domains that are currently running.
-The operation fails otherwise. This requirement ensures that the system remains
-in a valid security configuration after re-labelling.
-
-Restricting the Domain-0 authorization through the label creates a flexible
-policy-driven way to strongly partition the physical infrastructure and the
-workloads running on it. This partitioning will be automatically enforced during
-migration, start, or resume of domains and simplifies the security management
-considerably. Strongly competing workloads can be forced to run on separate physical
-infrastructure and become less depend on the domain isolation capabilities
-of the hypervisor.
-
-First, we relabel the swap image back to A-Bank and then start up domain1:
-\begin{scriptsize}
-\begin{verbatim}
-# xm rmlabel res file:/home/xen/dom_fc5/fedora.fc5.swap
-
-# xm addlabel A-Bank res file:/home/xen/dom_fc5/fedora.fc5.swap
-
-# xm create domain1.xm
-Using config file "./domain1.xm".
-Started domain domain1
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 7 128 1 -b---- 0.7 ACM:mytest:A-Bank
-Domain-0 0 839 1 r----- 103.1 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-The following command will restrict the Xen system to only run STE types
-included in the A-Bank label.
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm addlabel A-Bank mgt Domain-0
-Successfully set the label of domain 'Domain-0' to 'A-Bank'.
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 839 1 r----- 103.7 ACM:mytest:A-Bank
-domain1 7 128 1 -b---- 0.7 ACM:mytest:A-Bank
-
-\end{verbatim}
-\end{scriptsize}
-
-In our example policy in Figure~\ref{fig:acmxmlfileb}, this means that
-only \verb|A-Bank| domains and workloads (types) can run after the
-successful completion of this command because the \verb|A-Bank| label
-includes only a single STE type, namely \verb|A-Bank|. This command
-fails if any running domain has an STE type in its label that is not
-included in the A-Bank label.
-
-If we now label a domain3 with AutoCorp, it cannot start because Domain-0 is
-no longer authorized to run the workload type \verb|AutoCorp|.
-\begin{scriptsize}
-\begin{verbatim}
-# xm addlabel AutoCorp dom domain3.xm
- (remember to label its resources, too)
-
-# xm create domain3.xm
-Using config file "./domain3.xm".
-Error: VM is not authorized to run.
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 839 1 r----- 104.7 ACM:mytest:A-Bank
-domain1 7 128 1 -b---- 0.7 ACM:mytest:A-Bank
-\end{verbatim}
-\end{scriptsize}
-
-At this point, unlabeled domains cannot start either. Let domain4.xm
-describe an unlabeled domain, then trying to start domain4
-will fail:
-\begin{scriptsize}
-\begin{verbatim}
-# xm getlabel dom domain4.xm
-Error: 'Domain not labeled'
-
-# xm create domain4.xm
-Using config file "./domain4.xm".
-Error: VM is not authorized to run.
-\end{verbatim}
-\end{scriptsize}
-
-Relabeling Domain-0 with the SystemManagement label will enable domain3 to start.
-\begin{scriptsize}
-\begin{verbatim}
-# xm addlabel SystemManagement mgt Domain-0
-Successfully set the label of domain 'Domain-0' to 'SystemManagement'.
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 7 128 1 -b---- 0.8 ACM:mytest:A-Bank
-Domain-0 0 839 1 r----- 106.6 ACM:mytest:SystemManagement
-
-# xm create domain3.xm
-Using config file "./domain3.xm".
-Started domain domain3
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 7 128 1 -b---- 0.8 ACM:mytest:A-Bank
-domain3 8 164 1 -b---- 0.3 ACM:mytest:AutoCorp
-Domain-0 0 711 1 r----- 107.6 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-
-\subsection{Labeling Managed User Domains}
-\label{subsection:acmlabelmanageddomains}
-
-Xend has been extended with functionality to manage domains along with their
-configuration information. Such domains are configured and started via Xen-API
-calls. Since managed domains do not have an associated xm configuration file,
-the existing \verb|addlabel| command, which adds the security label into a
-domain's configuration file, will not work for such managed domains.
-
-Therefore, we have extended the \verb|xm addlabel| and \verb|xm rmlabel|
-subcommands to enable adding security labels to and removing security
-labels from managed domain configurations. The following example shows how
-the \verb|A-Bank| label can be assigned to the xend-managed
-domain configuration of \verb|domain1|. Removing labels from managed user
-domain configurations works similarly.
-
-Below, we show a dormant configuration of the managed domain1
-with ID \verb|"-1"| and state \verb|"-----"| before labeling:
-\begin{scriptsize}
-\begin{verbatim}
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 -1 128 1 ------ 0.0 ACM:mytest:__UNLABELED__
-Domain-0 0 711 1 r----- 128.4 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-Now we label the managed domain:
-\begin{scriptsize}
-\begin{verbatim}
-# xm addlabel A-Bank mgt domain1
-Successfully set the label of the dormant domain 'domain1' to 'A-Bank'.
-\end{verbatim}
-\end{scriptsize}
-
-After labeling, you can see that the security label is part of the
-domain configuration:
-\begin{scriptsize}
-\begin{verbatim}
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 -1 128 1 ------ 0.0 ACM:mytest:A-Bank
-Domain-0 0 711 1 r----- 129.7 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-This command extension does not support relabeling of individual running user domains
-for several reasons. For one, because of the difficulty to revoke resources
-in cases where a running domain's new label does not permit access to resources
-that were accessible under the old label. Another reason is that changing the
-label of a single domain of a workload is rarely a good choice and will affect
-the workload isolation properties of the overall workload.
-
-However, the name and contents of the label associated with running domains can
-be indirectly changed through a global policy change, which will update the whole
-workload consistently (domains and resources), cf.
-Section~\ref{subsection:acmpolicymanagement}.
-
-\section{Xen Access Control Policy}
-\label{section:acmpolicy}
-
-This section describes the sHype/Xen access control policy in detail.
-It gives enough information to enable the reader to write custom
-access control policies and to use the available Xen policy tools. The
-policy language is expressive enough to specify most symmetric access
-relationships between domains and resources efficiently.
-
-The Xen access control policy consists of two policy components. The
-first component, called Simple Type Enforcement (STE) policy, controls
-the sharing between running domains, i.e., communication or access to
-shared resources. The second component, called Chinese Wall (CHWALL)
-policy, controls which domains can run simultaneously on the same
-virtualized platform. The CHWALL and STE policy components complement
-each other. The XML policy file includes all information
-needed by Xen to enforce those policies.
-
-Figures~\ref{fig:acmxmlfilea} and \ref{fig:acmxmlfileb} show the fully
-functional but very simple example Xen security policy that is created
-by ezPolicy as shown in Figure~\ref{fig:acmezpolicy}. The policy can
-distinguish the 6 workload types shown in lines 11-17 in
-Fig.~\ref{fig:acmxmlfilea}. The whole XML Security Policy consists of
-four parts:
-\begin{enumerate}
-\item Policy header including the policy name
-\item Simple Type Enforcement block
-\item Chinese Wall Policy block
-\item Label definition block
-\end{enumerate}
-
-\begin{figure}
-\begin{scriptsize}
-\begin{verbatim}
-01 <?xml version="1.0" ?>
-02 <!-- Auto-generated by ezPolicy -->
-03 <SecurityPolicyDefinition ...">
-04 <PolicyHeader>
-05 <PolicyName>mytest</PolicyName>
-06 <Date>Mon Nov 19 22:51:56 2007</Date>
-07 <Version>1.0</Version>
-08 </PolicyHeader>
-09 <SimpleTypeEnforcement>
-10 <SimpleTypeEnforcementTypes>
-11 <Type>SystemManagement</Type>
-12 <Type>__UNLABELED__</Type>
-13 <Type>A-Bank</Type>
-14 <Type>A-Bank.SecurityUnderwriting</Type>
-15 <Type>A-Bank.MarketAnalysis</Type>
-16 <Type>B-Bank</Type>
-17 <Type>AutoCorp</Type>
-18 </SimpleTypeEnforcementTypes>
-19 </SimpleTypeEnforcement>
-20 <ChineseWall priority="PrimaryPolicyComponent">
-21 <ChineseWallTypes>
-22 <Type>SystemManagement</Type>
-23 <Type>__UNLABELED__</Type>
-24 <Type>A-Bank</Type>
-25 <Type>A-Bank.SecurityUnderwriting</Type>
-26 <Type>A-Bank.MarketAnalysis</Type>
-27 <Type>B-Bank</Type>
-28 <Type>AutoCorp</Type>
-29 </ChineseWallTypes>
-30 <ConflictSets>
-31 <Conflict name="RER">
-32 <Type>A-Bank</Type>
-33 <Type>B-Bank</Type>
-34 <Type>__UNLABELED__</Type>
-35 </Conflict>
-36 <Conflict name="RER">
-37 <Type>A-Bank.MarketAnalysis</Type>
-38 <Type>A-Bank.SecurityUnderwriting</Type>
-39 <Type>__UNLABELED__</Type>
-40 </Conflict>
-41 </ConflictSets>
-42 </ChineseWall>
-\end{verbatim}
-\end{scriptsize}
-\caption{Example XML security policy file -- Part I: Types and Rules Definition.}
-\label{fig:acmxmlfilea}
-\end{figure}
-
-\subsection{Policy Header and Policy Name}
-\label{subsection:acmnaming}
-Lines 1-2 (cf Figure~\ref{fig:acmxmlfilea}) include the usual XML
-header. The security policy definition starts in Line 3 and refers to
-the policy schema. The XML-Schema definition for the Xen policy can be
-found in the file
-\textit{/etc/xen/acm-security/policies/security-policy.xsd}. Examples
-for security policies can be found in the example subdirectory. The
-acm-security directory is only installed if ACM security is configured
-during installation (cf Section~\ref{subsection:acmexampleconfigure}).
-
-The \verb|Policy Header| spans lines 4-8. It includes a date field and
-defines the policy name \verb|mytest| as well
-as the version of the XML. It can also include optional fields that are
-not shown and are for future use (see schema definition).
-
-The policy name serves two purposes: First, it provides a unique name
-for the security policy. This name is also exported by the Xen
-hypervisor to the Xen management tools in order to ensure that both
-the Xen hypervisor and Domain-0 enforce the same policy.
-We plan to extend the policy name with a
-digital fingerprint of the policy contents to better protect this
-correlation. Second, it implicitly points the xm tools to the
-location where the XML policy file is stored on the Xen system.
-Replacing the colons in the policy name by slashes yields the local
-path to the policy file starting from the global policy directory
-\verb|/etc/xen/acm-security/policies|. The last part of the policy
-name is the prefix for the XML policy file name, completed by
-\verb|-security_policy.xml|. Our example policy with the name
-\verb|mytest| can be found in the XML policy file named
-\verb|mytest-security_policy.xml| that is stored under the global
-policy directory. Another, preinstalled example policy named
-\verb|example.test| can be found in the \verb|test-security_policy.xml|
-under \verb|/etc/xen/acm-security/policies/example|.
-
-\subsection{Simple Type Enforcement Policy Component}
-
-The Simple Type Enforcement (STE) policy controls which domains can
-communicate or share resources. This way, Xen can enforce confinement
-of workload types by confining the domains running those workload
-types and their resources. The mandatory access control framework
-enforces its policy when
-domains access intended communication or cooperation means (shared
-memory, events, shared resources such as block devices). It builds on
-top of the core hypervisor isolation, which restricts the ways of
-inter-communication to those intended means. STE does not protect or
-intend to protect from covert channels in the hypervisor or hardware;
-this is an orthogonal problem that can be mitigated by using the
-Run-time Exclusion rules described above or by fixing the problem leading
-to those covert channels in the core hypervisor or hardware platform.
-
-Xen controls sharing between domains on the resource and domain level
-because this is the abstraction the hypervisor and its management
-understand naturally. While this is coarse-grained, it is also very
-reliable and robust and it requires minimal changes to implement
-mandatory access controls in the hypervisor. It enables platform- and
-operating system-independent policies as part of a layered security
-approach.
-
-Lines 11-17 (cf Figure~\ref{fig:acmxmlfilea}) define the Simple Type
-Enforcement policy component. Essentially, they define the workload
-type names \verb|SystemManagement|, \verb|A-Bank|,
-\verb|AutoCorp| etc. that are available in the STE policy component. The
-policy rules are implicit: Xen permits two domains to communicate with
-each other if and only if their security labels have at least one STE type in
-common. Similarly, Xen permits a user domain to access a
-resource if and only if the labels of the domain and the resource
-have at least one STE workload type in common.
-
-\subsection{Chinese Wall Policy Component}
-
-The Chinese Wall security policy interpretation of sHype enables users
-to prevent certain workloads from running simultaneously on the same
-hypervisor platform. Run-time Exclusion rules (RER), also called
-Conflict Sets or Anti-Collocation rules, define a set of workload types
-that are not permitted to run simultaneously on the same virtualized
-platform. Of all the workloads specified in a Run-time
-Exclusion rule, at most one type can run on the same hypervisor
-platform at a time. Run-time Exclusion Rules implement a less
-rigorous variant of the original Chinese Wall security component. They
-do not implement the *-property of the policy, which would require to
-restrict also types that are not part of an exclusion rule once they
-are running together with a type in an exclusion rule
-(http://www.gammassl.co.uk/topics/chinesewall.html provides more information
-on the original Chinese Wall policy).
-
-Xen considers the \verb|ChineseWallTypes| part of the label for the
-enforcement of the Run-time Exclusion rules. It is illegal to define
-labels including conflicting Chinese Wall types.
-
-Lines 20-41 (cf Figure~\ref{fig:acmxmlfilea}) define the Chinese Wall
-policy component. Lines 22-28 define the known Chinese Wall types,
-which coincide here with the STE types defined above. This usually
-holds if the criteria for sharing among domains and sharing of the
-hardware platform are the same. Lines 30-41 define one Run-time
-Exclusion rules, the first of which is depicted below:
-
-\begin{scriptsize}
-\begin{verbatim}
-31 <Conflict name="RER">
-32 <Type>A-Bank</Type>
-33 <Type>B-Bank</Type>
-34 <Type>__UNLABELED__</Type>
-35 </Conflict>
-\end{verbatim}
-\end{scriptsize}
-
-Based on this rule, Xen enforces that only one of the types
-\verb|A-Bank|, \verb|B-Bank|, or \verb|__UNLABELED__| will run
-on a single hypervisor platform at a time. For example, once a domain assigned a
-\verb|A-Bank| workload type is started, domains with the
-\verb|B-Bank| type or unlabeled domains will be denied to start.
-When the former domain stops and no other domains with the \verb|A-Bank|
-type are running, then domains with the \verb|B-Bank| type or unlabeled domains
-can start.
-
-Xen maintains reference counts on each running workload type to keep
-track of which workload types are running. Every time a domain starts
-or resumes, the reference count on those Chinese Wall types that are
-referenced in the domain's label are incremented. Every time a domain
-is destroyed or saved, the reference counts of its Chinese Wall types
-are decremented. sHype in Xen fully supports migration and live-migration,
-which is subject to access control the same way as saving a domain on
-the source platform and resuming it on the destination platform.
-
-Here are some reasons why users might want to restrict workloads or domains
-from sharing the system hardware simultaneously:
-
-\begin{itemize}
-\item Imperfect resource management or control might enable a compromised
- user domain to starve other domains and the workload running in them.
-\item Redundant user domains might run the same workload to increase
- availability; such domains should not run on the same hardware to
- avoid single points of failure.
-\item Imperfect Xen core domain isolation might enable two rogue
- domains running different workload types to use unintended and
- unknown ways (covert channels) to exchange some bits of information.
- This way, they bypass the policed Xen access control mechanisms. Such
- imperfections cannot be completely eliminated and are a result of
- trade-offs between security and other design requirements. For a
- simple example of a covert channel see
- http://www.multicians.org/timing-chn.html. Such covert channels
- exist also between workloads running on different platforms if they
- are connected through networks. The Xen Chinese Wall policy provides
- an approximated ``air-gap'' between selected workload types.
-\end{itemize}
-
-\subsection{Security Labels}
-
-To enable Xen to associate domains with workload types running in
-them, each domain is assigned a security label that includes the
-workload types of the domain.
-
-\begin{figure}[htb]
- \begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}l|l}
- \begin{minipage}{0.475\textwidth}
- \begin{tiny}
- \begin{verbatim}
-<SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>__UNLABELED__</Type>
- <Type>A-Bank</Type>
- <Type>A-Bank.SecurityUnderwriting</Type>
- <Type>A-Bank.MarketAnalysis</Type>
- <Type>B-Bank</Type>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>__UNLABELED__</Name>
- <SimpleTypeEnforcementTypes>
- <Type>__UNLABELED__</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>__UNLABELED__</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>A-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>A-Bank</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>A-Bank.SecurityUnderwriting</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.SecurityUnderwriting</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>A-Bank</Type>
- <Type>A-Bank.SecurityUnderwriting</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>A-Bank.MarketAnalysis</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.MarketAnalysis</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>A-Bank</Type>
- <Type>A-Bank.MarketAnalysis</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>B-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>B-Bank</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>B-Bank</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-\end{verbatim}
-\end{tiny}
-\end{minipage} &
-\begin{minipage}{0.475\textwidth}
-\begin{tiny}
-\begin{verbatim}
- <VirtualMachineLabel>
- <Name>AutoCorp</Name>
- <SimpleTypeEnforcementTypes>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>AutoCorp</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- </SubjectLabels>
- <ObjectLabels>
- <ResourceLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>__UNLABELED__</Name>
- <SimpleTypeEnforcementTypes>
- <Type>__UNLABELED__</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>A-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>A-Bank.SecurityUnderwriting</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.SecurityUnderwriting</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>A-Bank.MarketAnalysis</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.MarketAnalysis</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>B-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>B-Bank</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>AutoCorp</Name>
- <SimpleTypeEnforcementTypes>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- </ObjectLabels>
-</SecurityLabelTemplate>
-</SecurityPolicyDefinition>
-
-
-
-
-
-
-
-
-\end{verbatim}
-\end{tiny}
-\end{minipage}
-\end{tabular*}
-\caption{Example XML security policy file -- Part II: Label Definition.}
-\label{fig:acmxmlfileb}
-\end{figure}
-% DO NOT MODIFY WHITESPACE ABOVE, it balances the columns
-The \verb|SecurityLabelTemplate| (cf Figure~\ref{fig:acmxmlfileb}) defines
-the security labels that can be associated with domains and resources when
-this policy is active (use the \verb|xm labels type=any| command described in
-Section~\ref{subsection:acmexamplelabeldomains} to list all available labels).
-
-The domain labels include
-Chinese Wall types while resource labels do not include Chinese Wall types.
-The \verb|SubjectLabels| policy section defines the labels that can be
-assigned to domains. The VM label
-\verb|A-Bank.SecurityUnderwriting| in Figure~\ref{fig:acmxmlfileb})
-associates the domain that carries it with the workload STE type
-\verb|A-Bank.SecurityUnderwriting| and with the CHWALL types \verb|A-Bank|
-and \verb|A-Bank.SecurityUnderwriting|. The ezPolicy tool
-assumes that any department workload will inherit any conflict set that
-is specified for its organization, i.e., if \verb|B-Bank| is running, not
-only \verb|A-Bank| but also all its departmental workloads are prevented
-from running by this first run-time exclusion set. The separation of STE
-and CHWALL types in the label definition ensures that
-all departmental workloads are isolated from each other and from their generic
-organization workloads, while they are sharing CHWALL types to
-simplify the formulation of run-time exclusion sets.
-
-The \verb|bootstrap| attribute of the \verb|<SubjectLabels>| XML node
-in our example policy shown in Figure~\ref{fig:acmxmlfileb} names
-the label \verb|SystemManagement| as the label that Xen will assign
-to Domain-0 at boot time (if this policy is installed as boot policy). The
-label of Domain-0 can be persistently changed at run-time with the
-\verb|addlabel| command, which adds an overriding option to the grub.conf
-boot entry (cf Section~\ref{subsection:acmlabeldom0}).
-All user domains are assigned labels according to their domain configuration
-(see Section~\ref{subsection:acmexamplelabeldomains} for examples of
-how to label domains).
-
-The \verb|ObjectLabels| depicted in Figure~\ref{fig:acmxmlfileb} can be
-assigned to resources when this policy is active.
-
-In general, user domains should be assigned labels that have only a
-single SimpleTypeEnforcement workload type. This way, workloads remain
-confined even if user domains become rogue. Any domain that is
-assigned a label with multiple STE types must be trusted to keep
-information belonging to the different STE types separate (confined).
-For example, Domain-0 is assigned the bootstrap label
-\verb|SystemManagement|, which includes all existing STE types.
-Therefore, Domain-0 must take care not to enable unauthorized
-information flow (eg. through block devices or virtual networking)
-between domains or resources that are assigned different STE types.
-
-Security administrators simply use the name of a label (specified in
-the \verb|<Name>| field) to associate a label with a domain (cf.
-Section~\ref{subsection:acmexamplelabeldomains}). The types inside the
-label are used by the Xen access control enforcement. While the name
-can be arbitrarily chosen (as long as it is unique), it is advisable
-to choose the label name in accordance to the security types included.
-Similarly, the STE and CHWALL types should be named according to the
-workloads they represent. While the XML representation of the label
-in the above example seems unnecessary flexible, labels in general
-must be able to include multiple types.
-
-We assume in the following example, that \verb|A-Bank.SecurityUnderwriting| and
-\verb|A-Bank.MarketAnalysis| workloads use virtual disks that are provided
-by a virtual I/O domain hosting a physical storage device and carrying
-the following label:
-
-\begin{scriptsize}
-\begin{verbatim}
- <VirtualMachineLabel>
- <Name>VIOServer</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank</Type>
- <Type>A-Bank.SecurityUnderwriting</Type>
- <Type>A-Bank.MarketAnalysis</Type>
- <Type>VIOServer</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>VIOServer</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-\end{verbatim}
-\end{scriptsize}
-
-This Virtual I/O domain (VIO) exports its virtualized disks by
-communicating to all domains labeled with the
-\verb|A-Bank.SecurityUnderwriting|, the \verb|A-Bank|, or the
-\verb|A-Bank.MarketAnalysis| label. This requires the
-VIO domain to carry those STE types. In addition, this label includes a
-new \verb|VIOServer| type that can be used to restrict direct access to the
-physical storage resource to the VIODomain.
-
-In this example, the confinement of these A-Bank workloads depends on the
-VIO domain that must keep the data of those different workloads separate.
-The virtual disks are labeled as well to keep track of their assignments
-to workload types (see Section~\ref{subsection:acmexamplelabelresources}
-for labeling resources) and enforcement functions inside the VIO
-domain must ensure that the labels of the domain mounting a virtual
-disk and the virtual disk label share a common STE type. The VIO label
-carrying its own VIOServer CHWALL type introduces the flexibility to
-permit the trusted VIO server to run together with \verb|A-Bank.SecurityUnderwriting|
-or \verb|A-Bank.MarketAnalysis| workloads.
-
-Alternatively, a system that has two hard-drives does not need a VIO
-domain but can directly assign one hardware storage device to each of
-the workloads if the platform offers an IO-MMU, cf
-Section~\ref{s:ddsecurity}. Sharing hardware through virtualized devices
-is a trade-off between the amount of trusted code (size of the trusted
-computing base) and the amount of acceptable over-provisioning. This
-holds both for peripherals and for system platforms.
-
-
-\subsection{Managing sHype/Xen Security Policies at Run-time}
-\label{subsection:acmpolicymanagement}
-
-\subsubsection{Removing the sHype/Xen Security Policy}
-When resetting the policy, no labeled domains can be running.
-Please stop or shutdown all running labeled domains. Then you can reset
-the policy to the default policy using the \verb|resetpolicy| command:
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm getpolicy
-Supported security subsystems : ACM
-Policy name : mytest
-Policy type : ACM
-Version of XML policy : 1.0
-Policy configuration : loaded, activated for boot
-
-# xm resetpolicy
-Successfully reset the system's policy.
-
-# xm getpolicy
-Supported security subsystems : ACM
-Policy name : DEFAULT
-Policy type : ACM
-Version of XML policy : 1.0
-Policy configuration : loaded
-
-# xm resources
-file:/home/xen/dom_fc5/fedora.fc5.swap
- type: INV_ACM
- policy: mytest
- label: A-Bank
-file:/home/xen/dom_fc5/fedora.fc5.img
- type: INV_ACM
- policy: mytest
- label: A-Bank
-\end{verbatim}
-\end{scriptsize}
-
-As the \verb|xm resources| output shows, all resource labels have
-invalidated type information but their semantics remain associated
-with the resources so that they can later on either be relabeled
-with semantically equivalent labels or sanitized and reused
-(storage resources).
-
-At this point, the system is in the same initial state as after
-configuring XSM and sHype/ACM and rebooting the system without
-a specific policy. No user domains can run.
-
-\subsubsection{Changing to a Different sHype/Xen Security Policy}
-The easiest way to change to a different, unrelated policy is to reset the system
-policy and then set the new policy. Please consider that the existing
-domain and resource labels become invalid at this point. Please refer
-to the next section for an example of how to seamlessly update an
-active policy at run-time without invalidating labels.
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm resetpolicy
-Successfully reset the system's policy.
-
-# xm setpolicy ACM example.test
-Successfully set the new policy.
-Supported security subsystems : ACM
-Policy name : example.test
-Policy type : ACM
-Version of XML policy : 1.0
-Policy configuration : loaded, activated for boot
-
-# xm labels
-CocaCola
-PepsiCo
-SystemManagement
-VIO
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 873 1 r----- 56.3 ACM:example.test:SystemManagement
-
-# xm resetpolicy
-Successfully reset the system's policy.
-
-# xm getpolicy
-Supported security subsystems : ACM
-Policy name : DEFAULT
-Policy type : ACM
-Version of XML policy : 1.0
-Policy configuration : loaded
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 873 1 r----- 57.2 ACM:DEFAULT:SystemManagement
-
-# xm setpolicy ACM mytest
-Successfully set the new policy.
-Supported security subsystems : ACM
-Policy name : mytest
-Policy type : ACM
-Version of XML policy : 1.0
-Policy configuration : loaded, activated for boot
-
-# xm labels
-A-Bank
-A-Bank.MarketAnalysis
-A-Bank.SecurityUnderwriting
-AutoCorp
-B-Bank
-SystemManagement
-__UNLABELED__
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-Domain-0 0 873 1 r----- 58.0 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-The described way of changing policies by resetting the existing
-policy is useful for testing different policies. For real deployment
-environments, a policy update as described in the following section
-is more appropriate and can be applied seamlessly at run-time while
-user domains are running.
-
-\subsubsection{Update an sHype/Xen Security Policy at Run-time}
-
-Once an ACM security policy is activated (loaded into the Xen
-hypervisor), the policy may be updated at run-time without the
-need to re-boot the system. The XML update-policy contains several
-additional information fields that are required to safely link the
-new policy contents to the old policy and ensure a consistent
-transformation of the system security state from the old to the
-new policy. Those additional fields are required for policies that
-are updating an existing policy at run-time.
-
-The major benefit of policy updates is the ability to add, delete,
-or rename workload types, labels, and conflict sets (run-time
-exclusion rules) to accommodate changes in the managed virtual
-environment without the need to reboot the Xen system. When a
-new policy renames labels of the current policy, the labels
-attached to resources and domains are automatically updated
-during a successful policy update.
-
-We have manually crafted an update policy for the \verb|mytest|
-security policy and stored it in the file mytest\_update-security\_policy.xml
-in the policies directory. We will discuss this policy in detail before
-using it to update a running sHype/Xen system. The following figures contain
-the whole contents of the update policy file.
-
-Figure~\ref{fig:acmupdateheader} shows the policy
-header of an update-policy and the new \verb|FromPolicy| XML
-node. For the policy update to succeed, the policy name and the
-policy version fields of the \verb|FromPolicy| XML node must
-exactly match those of the currently enforced policy. This
-ensures a controlled update path of the policy.
-
-\begin{figure}[htb]
-\begin{scriptsize}
-\begin{verbatim}
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Auto-generated by ezPolicy -->
-<SecurityPolicyDefinition xmlns="http://www.ibm.com"
-xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
- <PolicyHeader>
- <PolicyName>mytest</PolicyName>
- <Date>Tue Nov 27 21:53:45 2007</Date>
- <Version>1.1</Version>
- <FromPolicy>
- <PolicyName>mytest</PolicyName>
- <Version>1.0</Version>
- </FromPolicy>
- </PolicyHeader>
-\end{verbatim}
-\end{scriptsize}
-\caption{XML security policy update -- Part I: Updated Policy Header.}
-\label{fig:acmupdateheader}
-\end{figure}
-
-The version number of the new policy, which is shown in the
-node following the \verb|Date| node, must be a logical increment
-to the current policy's version. Therefore at least the minor
-number of the policy version must be incremented. This ensures
-that a policy update is applied only to exactly the policy for
-which this update was created and minimizes unforseen side-effects
- of policy updates.
-
-\paragraph{Types and Conflic Sets}
-The type names and the assignment of types to labels or conflict
-sets (run-time exclusion rules) can
-simply be changed consistently throughout the policy. Types,
-as opposed to labels, are not directly associated or referenced
-outside the policy so they do not need to carry their history
-in a ``From'' field. The figure below shows the update for the
-types and conflict sets. The \verb|__UNLABELED__| type is removed
-to disable support for running unlabeled domains. Additionally,
-we have renamed the two \verb|A-Bank| department types with
-abbreviated names \verb|A-Bank.SU| and \verb|A-Bank.MA|. You
-can also see how those type names are
-consistently changed within the conflict set definition.
-
-\begin{figure}[htb]
-\begin{scriptsize}
-\begin{verbatim}
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>A-Bank</Type>
- <Type>A-Bank.SU</Type>
- <Type>A-Bank.MA</Type>
- <Type>B-Bank</Type>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
-
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- <Type>A-Bank</Type>
- <Type>A-Bank.SU</Type>
- <Type>A-Bank.MA</Type>
- <Type>B-Bank</Type>
- <Type>AutoCorp</Type>
- </ChineseWallTypes>
-
- <ConflictSets>
- <Conflict name="RER">
- <Type>A-Bank</Type>
- <Type>B-Bank</Type>
- </Conflict>
- <Conflict name="RER">
- <Type>A-Bank.MA</Type>
- <Type>A-Bank.SU</Type>
- </Conflict>
- </ConflictSets>
- </ChineseWall>
-\end{verbatim}
-\end{scriptsize}
-\caption{XML security policy update -- Part II: Updated Types and Conflict Sets.}
-\label{fig:acmupdatetypesnrules}
-\end{figure}
-
-In the same way, new types can be introduced and new conflict sets
-can be defined by simply adding the types or conflict sets to the
-update policy.
-
-\paragraph{Labels} Virtual machine and resource labels of an existing policy can be
-deleted through a policy update simply by omitting them in the
-update-policy. However, if a currently running virtual machine
-or a currently used resource is labeled with a label not stated
-in the update-policy, then the policy update is rejected. This
-ensures that a policy update leaves the system in a consistent
-security state.
-
-A policy update also enables the renaming of virtual machine and
-resource labels. Linking the old label name with the new label
-name is achieved through the \verb|from| attribute in the
-\verb|VirtualMachineLabel| or \verb|ResourceLabel| nodes in the
-update-policy. Figure~\ref{fig:acmupdatelabels} shown how subject
-and resource labels
-are updated from their old name \verb|A-Bank.SecurityUnterwriting|
-to their new name \verb|A-Bank.SU| using the \verb|from| attribute.
-
-\begin{figure}[htb]
-\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}l|l}
-\begin{minipage}{0.475\textwidth}
-\begin{tiny}
-\begin{verbatim}
-<SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>A-Bank</Type>
- <Type>A-Bank.SU</Type>
- <Type>A-Bank.MA</Type>
- <Type>B-Bank</Type>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>A-Bank-WL</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>A-Bank</Type>
- <Type>A-Bank.SU</Type>
- <Type>A-Bank.MA</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>A-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>A-Bank</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name from="A-Bank.SecurityUnderwriting">
- A-Bank.SU</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.SU</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>A-Bank</Type>
- <Type>A-Bank.SU</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name from="A-Bank.MarketAnalysis">
- A-Bank.MA</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.MA</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>A-Bank</Type>
- <Type>A-Bank.MA</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-\end{verbatim}
-\end{tiny}
-\end{minipage} &
-\begin{minipage}{0.475\textwidth}
-\begin{tiny}
-\begin{verbatim}
- <VirtualMachineLabel>
- <Name>B-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>B-Bank</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>B-Bank</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- <VirtualMachineLabel>
- <Name>AutoCorp</Name>
- <SimpleTypeEnforcementTypes>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>AutoCorp</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-</SubjectLabels>
-
-<ObjectLabels>
- <ResourceLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>A-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name from="A-Bank.SecurityUnderwriting">
- A-Bank.SU</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.SU</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name from="A-Bank.MarketAnalysis">
- A-Bank.MA</Name>
- <SimpleTypeEnforcementTypes>
- <Type>A-Bank.MA</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>B-Bank</Name>
- <SimpleTypeEnforcementTypes>
- <Type>B-Bank</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- <ResourceLabel>
- <Name>AutoCorp</Name>
- <SimpleTypeEnforcementTypes>
- <Type>AutoCorp</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- </ObjectLabels>
-</SecurityLabelTemplate>
-</SecurityPolicyDefinition>
-\end{verbatim}
-\end{tiny}
-\end{minipage}
-\end{tabular*}
-\caption{XML security policy update -- Part III: Updated Label Definition.}
-\label{fig:acmupdatelabels}
-\end{figure}
-% DO NOT MODIFY WHITESPACE ABOVE, it balances the columns
-
-The updated label definition also includes a new label \verb|A-Bank-WL|
-that includes all STE types related to A-Bank. Its CHWALL type
-is \verb|SystemManagement|. This indicates that this label is designed
-as Domain-0 label. A Xen system can be restricted to only run A-Bank
-related workloads by relabeling Domain-0 with the \verb|A-Bank-WL| label.
-
-We assume that the update-policy shown in
-Figures~\ref{fig:acmupdateheader}, \ref{fig:acmupdatetypesnrules}
-and \ref{fig:acmupdatelabels}
-is stored in the XML file mytest\_update-security\_policy.xml located
-in the ACM policy directory. See Section~\ref{subsection:acmnaming}
-for information about policy names and locations.
-
-The following \verb|xm setpolicy| command updates the active ACM
-security policy at run-time.
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 2 128 1 -b---- 0.6 ACM:mytest:A-Bank
-domain4 3 164 1 -b---- 0.3 ACM:mytest:A-Bank.SecurityUnderwriting
-Domain-0 0 711 1 r----- 71.8 ACM:mytest:SystemManagement
-
-# xm resources
-file:/home/xen/dom_fc5/fedora.fc5.swap
- type: ACM
- policy: mytest
- label: A-Bank
-file:/home/xen/dom_fc5/fedora.fc5.img
- type: ACM
- policy: mytest
- label: A-Bank
-
-# xm setpolicy ACM mytest_update
-Successfully set the new policy.
-Supported security subsystems : ACM
-Policy name : mytest
-Policy type : ACM
-Version of XML policy : 1.1
-Policy configuration : loaded, activated for boot
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 2 128 1 -b---- 0.7 ACM:mytest:A-Bank
-domain4 3 164 1 -b---- 0.3 ACM:mytest:A-Bank.SU
-Domain-0 0 711 1 r----- 72.8 ACM:mytest:SystemManagement
-
-# xm labels
-A-Bank
-A-Bank-WL
-A-Bank.MA
-A-Bank.SU
-AutoCorp
-B-Bank
-
-# xm resources
-file:/home/xen/dom_fc5/fedora.fc5.swap
- type: ACM
- policy: mytest
- label: A-Bank
-file:/home/xen/dom_fc5/fedora.fc5.img
- type: ACM
- policy: mytest
- label: A-Bank
- \end{verbatim}
-\end{scriptsize}
-
-After successful completion of this command, \verb|xm list --label|
-shows that the labels of running domains changed to their new names.
-\verb|xm labels| shows that new labels \verb|A-Bank.SU| and \verb|A-Bank.AM|
-are now available in the policy. The resource labels remain valid after
-the successful update as \verb|xm resources| confirms.
-
-The \verb|setpolicy| command fails if the new policy is inconsistent
-with the current one or the policy is inconsistent internally (e.g., types
-are renamed in the type definition but not in the label definition part of
-the policy). In this case, the old policy remains active.
-
-After relabeling Domain-0 with the new \verb|A-Bank-WL| label, we can no
-longer run domains labeled \verb|B-Bank| or \verb|AutoCorp| since their
-STE types are not a subset of the new Domain-0 label.
-
-\begin{scriptsize}
-\begin{verbatim}
-# xm addlabel A-Bank-WL mgt Domain-0
-Successfully set the label of domain 'Domain-0' to 'A-Bank-WL'.
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 2 128 1 -b---- 0.8 ACM:mytest:A-Bank
-Domain-0 0 711 1 r----- 74.5 ACM:mytest:A-Bank-WL
-domain4 3 164 1 -b---- 0.3 ACM:mytest:A-Bank.SU
-
-# xm getlabel dom domain3.xm
-policytype=ACM,policy=mytest,label=AutoCorp
-
-# xm create domain3.xm
-Using config file "./domain3.xm".
-Error: VM is not authorized to run.
-
-# xm addlabel SystemManagement mgt Domain-0
-Successfully set the label of domain 'Domain-0' to 'SystemManagement'.
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 2 128 1 -b---- 0.8 ACM:mytest:A-Bank
-domain4 3 164 1 -b---- 0.3 ACM:mytest:A-Bank.SU
-Domain-0 0 709 1 r----- 76.4 ACM:mytest:SystemManagement
-
-# xm create domain3.xm
-Using config file "./domain3.xm".
-Started domain domain3
-
-# xm list --label
-Name ID Mem VCPUs State Time(s) Label
-domain1 2 128 1 -b---- 0.8 ACM:mytest:A-Bank
-domain4 3 164 1 -b---- 0.3 ACM:mytest:A-Bank.SU
-domain3 4 164 1 -b---- 0.3 ACM:mytest:AutoCorp
-Domain-0 0 547 1 r----- 77.5 ACM:mytest:SystemManagement
-\end{verbatim}
-\end{scriptsize}
-
-In the same manner, you can add new labels to support new workloads and
-add, delete, or rename workload types (STE and/or CHWALL types) simply
-by changing the composition of labels. Another use case is to add new
-workload types to the current Domain-0 label to enable them to run.
-Conflict sets (run-time exclusion rules) can be simply omitted or added.
-The policy and label changes become active at once and new workloads
-can be run in protected mode without rebooting the Xen system.
-
-In all these cases, if any running user domain would--under the new policy--not
-be allowed to run or would not be allowed to access any of the resources
-it currently uses, then the policy update is rejected. In this case, you
-can stop domains that conflict with the new policy and update the policy
-afterwards. The old policy remains active until a policy update succeeds
-or Xen is re-booted into a new policy.
-
-\subsection{Tools For Creating sHype/Xen Security Policies}
-To create a security policy for Xen, you can use one of the following
-tools:
-\begin{itemize}
-\item \verb|ezPolicy| GUI tool -- start writing policies
-\item \verb|xensec_gen| tool -- refine policies created with \verb|ezPolicy|
-\item text or XML editor
-\end{itemize}
-
-We use the \verb|ezPolicy| tool in
-Section~\ref{subsection:acmexamplecreate} to quickly create a workload
-protection policy. If desired, the resulting XML policy file can be
-loaded into the \verb|xensec_gen| tool to refine it. It can also be
-directly edited using an XML editor. Any XML policy file is verified
-against the security policy schema when it is translated (see
-Subsection~\ref{subsection:acmexampleinstall}).
-
-\section{Current Limitations}
-\label{section:acmlimitations}
-
-The sHype/ACM configuration for Xen is work in progress. There is
-ongoing work for protecting virtualized resources and planned and
-ongoing work for protecting access to remote resources and domains.
-The following sections describe limitations of some of the areas into
-which access control is being extended.
-
-\subsection{Network Traffic}
-Local and remote network traffic is currently not controlled.
-Solutions to add sHype/ACM policy enforcement to the virtual network
-exist but need to be discussed before they can become part of Xen.
-Subjecting external network traffic to the ACM security policy is work
-in progress. Manually setting up filters in domain 0 is required for
-now but does not scale well.
-
-\subsection{Resource Access and Usage Control}
-
-Enforcing the security policy across multiple hypervisor systems and
-on access to remote shared resources is work in progress. Extending
-access control to new types of resources is ongoing work (e.g. network
-storage).
-
-On a single Xen system, information about the association of resources
-and security labels is stored in
-\verb|/var/lib/xend/security/policies/resource_labels|. This file relates
-a full resource path with a security label. This association is weak
-and will break if resources are moved or renamed without adapting the
-label file. Improving the protection of label-resource relationships
-is ongoing work.
-
-Controlling resource usage and enforcing resource limits in general is
-ongoing work in the Xen community.
-
-\subsection{Domain Migration}
-
-Labels on domains are enforced during domain migration and the
-destination hypervisor will ensure that the domain label is valid and
-the domain is permitted to run (considering the Chinese Wall policy
-rules) before it accepts the migration. However, the network between
-the source and destination hypervisor as well as both hypervisors must
-be trusted. Architectures and prototypes exist that both protect the
-network connection and ensure that the hypervisors enforce access
-control consistently but patches are not yet available for the main
-stream.
-
-\subsection{Covert Channels}
-
-The sHype access control aims at system independent security policies.
-It builds on top of the core hypervisor isolation. Any covert channels
-that exist in the core hypervisor or in the hardware (e.g., shared
-processor cache) will be inherited. If those covert channels are not
-the result of trade-offs between security and other system properties,
-then they are most effectively minimized or eliminated where they are
-caused. sHype offers however some means to mitigate their impact, e.g.,
-run-time exclusion rules (cf Section~\ref{subsection:acmexamplecreate})
-or limiting the system authorization (cf Section~\ref{subsection:acmlabeldom0}).
-
-
\part{Reference}
%% Chapter Build and Boot Options
diff --git a/tools/Makefile b/tools/Makefile
index 3ac76e6b43..df6270c352 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -13,7 +13,6 @@ SUBDIRS-y += hotplug
SUBDIRS-y += xentrace
SUBDIRS-$(CONFIG_XCUTILS) += xcutils
SUBDIRS-$(CONFIG_X86) += firmware
-SUBDIRS-$(ACM_SECURITY) += security
SUBDIRS-y += console
SUBDIRS-y += xenmon
SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
diff --git a/tools/check/Makefile b/tools/check/Makefile
index f24816601b..b2ee0d6b38 100644
--- a/tools/check/Makefile
+++ b/tools/check/Makefile
@@ -7,12 +7,12 @@ all install: check-build
# Check this machine is OK for building on.
.PHONY: check-build
check-build:
- PYTHON=$(PYTHON) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY) ./chk build
+ PYTHON=$(PYTHON) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ./chk build
# Check this machine is OK for installing on.
.PHONY: check-install
check-install:
- PYTHON=$(PYTHON) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY) ./chk install
+ PYTHON=$(PYTHON) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ./chk install
.PHONY: clean
clean:
diff --git a/tools/check/check_xml2 b/tools/check/check_xml2
index caa762c4e3..89fe5a4769 100755
--- a/tools/check/check_xml2
+++ b/tools/check/check_xml2
@@ -3,7 +3,7 @@
. ./funcs.sh
-if [ ! "$LIBXENAPI_BINDINGS" = "y" -a ! "$ACM_SECURITY" = "y" ]
+if [ ! "$LIBXENAPI_BINDINGS" = "y" ]
then
echo -n "unused, "
exit 0
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 232d9a3760..6464818187 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -13,7 +13,6 @@ CTRL_SRCS-y += xc_domain.c
CTRL_SRCS-y += xc_evtchn.c
CTRL_SRCS-y += xc_gnttab.c
CTRL_SRCS-y += xc_misc.c
-CTRL_SRCS-y += xc_acm.c
CTRL_SRCS-y += xc_flask.c
CTRL_SRCS-y += xc_physdev.c
CTRL_SRCS-y += xc_private.c
diff --git a/tools/libxc/xc_acm.c b/tools/libxc/xc_acm.c
deleted file mode 100644
index 9ab7a68b4d..0000000000
--- a/tools/libxc/xc_acm.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/******************************************************************************
- * xc_acm.c
- *
- * Copyright (C) 2005, 2006 IBM Corporation, R Sailer
- *
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "xc_private.h"
-
-int xc_acm_op(xc_interface *xch, int cmd, void *arg, unsigned long arg_size)
-{
- int ret;
- DECLARE_HYPERCALL;
- DECLARE_HYPERCALL_BUFFER(struct xen_acmctl, acmctl);
-
- acmctl = xc_hypercall_buffer_alloc(xch, acmctl, sizeof(*acmctl));
- if ( acmctl == NULL )
- {
- PERROR("Could not allocate memory for ACM OP hypercall");
- return -EFAULT;
- }
-
- switch (cmd) {
- case ACMOP_setpolicy: {
- struct acm_setpolicy *setpolicy = (struct acm_setpolicy *)arg;
- memcpy(&acmctl->u.setpolicy,
- setpolicy,
- sizeof(struct acm_setpolicy));
- }
- break;
-
- case ACMOP_getpolicy: {
- struct acm_getpolicy *getpolicy = (struct acm_getpolicy *)arg;
- memcpy(&acmctl->u.getpolicy,
- getpolicy,
- sizeof(struct acm_getpolicy));
- }
- break;
-
- case ACMOP_dumpstats: {
- struct acm_dumpstats *dumpstats = (struct acm_dumpstats *)arg;
- memcpy(&acmctl->u.dumpstats,
- dumpstats,
- sizeof(struct acm_dumpstats));
- }
- break;
-
- case ACMOP_getssid: {
- struct acm_getssid *getssid = (struct acm_getssid *)arg;
- memcpy(&acmctl->u.getssid,
- getssid,
- sizeof(struct acm_getssid));
- }
- break;
-
- case ACMOP_getdecision: {
- struct acm_getdecision *getdecision = (struct acm_getdecision *)arg;
- memcpy(&acmctl->u.getdecision,
- getdecision,
- sizeof(struct acm_getdecision));
- }
- break;
-
- case ACMOP_chgpolicy: {
- struct acm_change_policy *change_policy = (struct acm_change_policy *)arg;
- memcpy(&acmctl->u.change_policy,
- change_policy,
- sizeof(struct acm_change_policy));
- }
- break;
-
- case ACMOP_relabeldoms: {
- struct acm_relabel_doms *relabel_doms = (struct acm_relabel_doms *)arg;
- memcpy(&acmctl->u.relabel_doms,
- relabel_doms,
- sizeof(struct acm_relabel_doms));
- }
- break;
- }
-
- acmctl->cmd = cmd;
- acmctl->interface_version = ACM_INTERFACE_VERSION;
-
- hypercall.op = __HYPERVISOR_xsm_op;
- hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(acmctl);
- if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0)
- {
- if ( errno == EACCES )
- DPRINTF("acmctl operation failed -- need to"
- " rebuild the user-space tool set?\n");
- }
-
- switch (cmd) {
- case ACMOP_getdecision: {
- struct acm_getdecision *getdecision = (struct acm_getdecision *)arg;
- memcpy(getdecision,
- &acmctl->u.getdecision,
- sizeof(struct acm_getdecision));
- break;
- }
- }
-
- xc_hypercall_buffer_free(xch, acmctl);
-
- return ret;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 971daf02bc..9a4355f79c 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -44,8 +44,6 @@
#include <xen/memory.h>
#include <xen/grant_table.h>
#include <xen/hvm/params.h>
-#include <xen/xsm/acm.h>
-#include <xen/xsm/acm_ops.h>
#include <xen/xsm/flask_op.h>
#include <xen/tmem.h>
@@ -1250,8 +1248,6 @@ int xc_sysctl(xc_interface *xch, struct xen_sysctl *sysctl);
int xc_version(xc_interface *xch, int cmd, void *arg);
-int xc_acm_op(xc_interface *xch, int cmd, void *arg, unsigned long arg_size);
-
int xc_flask_op(xc_interface *xch, flask_op_t *op);
/*
diff --git a/tools/libxen/include/xen/api/xen_acmpolicy.h b/tools/libxen/include/xen/api/xen_acmpolicy.h
deleted file mode 100644
index 43aac5810d..0000000000
--- a/tools/libxen/include/xen/api/xen_acmpolicy.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2007, IBM Corp.
- * Copyright (c) 2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef XEN_ACMPOLICY_H
-#define XEN_ACMPOLICY_H
-
-#include "xen_common.h"
-#include "xen_string_string_map.h"
-#include "xen_xspolicy_decl.h"
-#include "xen_vm_decl.h"
-
-/*
- * Data structures.
- */
-
-typedef struct xen_acmpolicy_record
-{
- xen_xspolicy handle;
- char *uuid;
- char *repr;
- xs_instantiationflags flags;
- xs_type type;
-} xen_acmpolicy_record;
-
-/**
- * Allocate a xen_acmpolicy_record.
- */
-extern xen_acmpolicy_record *
-xen_acmpolicy_record_alloc(void);
-
-/**
- * Free the given xen_xspolicy_record, and all referenced values. The
- * given record must have been allocated by this library.
- */
-extern void
-xen_acmpolicy_record_free(xen_acmpolicy_record *record);
-
-
-/**
- * Data structures for the policy's header
- */
-typedef struct xen_acm_header
-{
- char *policyname;
- char *policyurl;
- char *date;
- char *reference;
- char *namespaceurl;
- char *version;
-} xen_acm_header;
-
-extern xen_acm_header *
-xen_acm_header_alloc(void);
-
-extern void
-xen_acm_header_free(xen_acm_header *hdr);
-
-/**
- * Get the referenced policy's record.
- */
-extern bool
-xen_acmpolicy_get_record(xen_session *session, xen_acmpolicy_record **result,
- xen_xspolicy xspolicy);
-
-/**
- * Get the header of a policy.
- */
-extern bool
-xen_acmpolicy_get_header(xen_session *session, xen_acm_header **hdr,
- xen_xspolicy xspolicy);
-
-
-/**
- * Get the XML representation of the policy.
- */
-extern bool
-xen_acmpolicy_get_xml(xen_session *session, char **xml,
- xen_xspolicy xspolicy);
-
-/**
- * Get the mapping file of the policy.
- */
-extern bool
-xen_acmpolicy_get_map(xen_session *session, char **map,
- xen_xspolicy xspolicy);
-
-/**
- * Get the binary representation (base64-encoded) of the policy.
- */
-extern bool
-xen_acmpolicy_get_binary(xen_session *session, char **binary,
- xen_xspolicy xspolicy);
-
-/**
- * Get the binary representation (base64-encoded) of the currently
- * enforced policy.
- */
-extern bool
-xen_acmpolicy_get_enforced_binary(xen_session *session, char **binary,
- xen_xspolicy xspolicy);
-
-/**
- * Get the ACM ssidref of the given VM.
- */
-extern bool
-xen_acmpolicy_get_VM_ssidref(xen_session *session, int64_t *result,
- xen_vm vm);
-
-/**
- * Get the UUID field of the given policy.
- */
-extern bool
-xen_acmpolicy_get_uuid(xen_session *session, char **result,
- xen_xspolicy xspolicy);
-
-#endif
diff --git a/tools/libxen/src/xen_acmpolicy.c b/tools/libxen/src/xen_acmpolicy.c
deleted file mode 100644
index f8d69195a4..0000000000
--- a/tools/libxen/src/xen_acmpolicy.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (c) 2007, IBM Corp.
- * Copyright (c) 2007, XenSource Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "xen_internal.h"
-#include "xen/api/xen_common.h"
-#include "xen/api/xen_xspolicy.h"
-#include "xen/api/xen_acmpolicy.h"
-
-
-static const struct_member xen_acmpolicy_record_struct_members[] =
- {
- { .key = "uuid",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acmpolicy_record, uuid) },
- { .key = "flags",
- .type = &abstract_type_int,
- .offset = offsetof(xen_acmpolicy_record, flags) },
- { .key = "repr",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acmpolicy_record, repr) },
- { .key = "type",
- .type = &abstract_type_int,
- .offset = offsetof(xen_acmpolicy_record, type) },
- };
-
-const abstract_type xen_acmpolicy_record_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_acmpolicy_record),
- .member_count =
- sizeof(xen_acmpolicy_record_struct_members) / sizeof(struct_member),
- .members = xen_acmpolicy_record_struct_members
- };
-
-
-static const struct_member xen_acm_header_struct_members[] =
- {
- { .key = "policyname",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acm_header, policyname) },
- { .key = "policyurl",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acm_header, policyurl) },
- { .key = "date",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acm_header, date) },
- { .key = "reference",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acm_header, reference) },
- { .key = "namespaceurl",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acm_header, namespaceurl) },
- { .key = "version",
- .type = &abstract_type_string,
- .offset = offsetof(xen_acm_header, version) },
- };
-
-const abstract_type xen_acm_header_abstract_type_ =
- {
- .typename = STRUCT,
- .struct_size = sizeof(xen_acm_header),
- .member_count =
- sizeof(xen_acm_header_struct_members) /
- sizeof(struct_member),
- .members = xen_acm_header_struct_members,
- };
-
-void
-xen_acm_header_free(xen_acm_header *shdr)
-{
- if (shdr == NULL)
- {
- return;
- }
- free(shdr->policyname);
- free(shdr->policyurl);
- free(shdr->date);
- free(shdr->reference);
- free(shdr->namespaceurl);
- free(shdr->version);
- free(shdr);
-}
-
-
-void
-xen_acmpolicy_record_free(xen_acmpolicy_record *record)
-{
- if (record == NULL)
- {
- return;
- }
- free(record->handle);
- free(record->uuid);
- free(record->repr);
- free(record);
-}
-
-
-
-bool
-xen_acmpolicy_get_record(xen_session *session, xen_acmpolicy_record **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy }
- };
-
- abstract_type result_type = xen_acmpolicy_record_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_record");
-
- if (session->ok)
- {
- (*result)->handle = xen_strdup_((*result)->uuid);
- }
-
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_header(xen_session *session,
- xen_acm_header **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy },
- };
-
- abstract_type result_type = xen_acm_header_abstract_type_;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_header");
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_xml(xen_session *session,
- char **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_xml");
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_map(xen_session *session,
- char **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_map");
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_binary(xen_session *session, char **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_binary");
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_enforced_binary(xen_session *session, char **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy },
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_enforced_binary");
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_VM_ssidref(xen_session *session,
- int64_t *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("ACMPolicy.get_VM_ssidref");
- return session->ok;
-}
-
-
-bool
-xen_acmpolicy_get_uuid(xen_session *session, char **result,
- xen_xspolicy xspolicy)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = xspolicy }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("ACMPolicy.get_uuid");
- return session->ok;
-}
diff --git a/tools/python/setup.py b/tools/python/setup.py
index f803632d3b..0f0c5f860d 100644
--- a/tools/python/setup.py
+++ b/tools/python/setup.py
@@ -43,14 +43,6 @@ process = Extension("process",
depends = [ ],
sources = [ "xen/lowlevel/process/process.c" ])
-acm = Extension("acm",
- extra_compile_args = extra_compile_args,
- include_dirs = [ PATH_XEN, PATH_LIBXC, "xen/lowlevel/acm" ],
- library_dirs = [ PATH_LIBXC ],
- libraries = [ "xenctrl" ],
- depends = [ PATH_LIBXC + "/libxenctrl.so" ],
- sources = [ "xen/lowlevel/acm/acm.c" ])
-
flask = Extension("flask",
extra_compile_args = extra_compile_args,
include_dirs = [ PATH_XEN, PATH_LIBXC, "xen/lowlevel/flask",
@@ -98,7 +90,7 @@ xl = Extension("xl",
sources = [ "xen/lowlevel/xl/xl.c", "xen/lowlevel/xl/_pyxl_types.c" ])
plat = os.uname()[0]
-modules = [ xc, xs, ptsname, acm, flask, xl ]
+modules = [ xc, xs, ptsname, flask, xl ]
if plat == 'SunOS':
modules.extend([ scf, process ])
if plat == 'Linux':
@@ -113,7 +105,6 @@ setup(name = 'xen',
'xen.util.xsm',
'xen.util.xsm.dummy',
'xen.util.xsm.flask',
- 'xen.util.xsm.acm',
'xen.xend',
'xen.xend.server',
'xen.xend.xenstore',
diff --git a/tools/python/xen/lowlevel/acm/acm.c b/tools/python/xen/lowlevel/acm/acm.c
deleted file mode 100644
index 832458de74..0000000000
--- a/tools/python/xen/lowlevel/acm/acm.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/****************************************************************
- * acm.c
- *
- * Copyright (C) 2006,2007 IBM Corporation
- *
- * Authors:
- * Reiner Sailer <sailer@watson.ibm.com>
- * Stefan Berger <stefanb@us.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * ACM low-level code that allows Python control code to leverage
- * the ACM hypercall interface to retrieve real-time information
- * from the Xen hypervisor security module.
- *
- * indent -i4 -kr -nut
- */
-
-#include <Python.h>
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <xenctrl.h>
-#include <xen/xsm/acm.h>
-#include <xen/xsm/acm_ops.h>
-
-#define PERROR(_m, _a...) \
-fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
- errno, strerror(errno))
-
-static PyObject *acm_error_obj;
-
-/* generic shared function */
-static void *__getssid(xc_interface *xc_handle, int domid, uint32_t *buflen, xc_hypercall_buffer_t *buffer)
-{
- struct acm_getssid getssid;
- #define SSID_BUFFER_SIZE 4096
- void *buf;
- DECLARE_HYPERCALL_BUFFER_ARGUMENT(buffer);
-
- if ((buf = xc_hypercall_buffer_alloc(xc_handle, buffer, SSID_BUFFER_SIZE)) == NULL) {
- PERROR("acm.policytype: Could not allocate ssid buffer!\n");
- return NULL;
- }
-
- memset(buf, 0, SSID_BUFFER_SIZE);
- set_xen_guest_handle(getssid.ssidbuf, buffer);
- getssid.ssidbuf_size = SSID_BUFFER_SIZE;
- getssid.get_ssid_by = ACM_GETBY_domainid;
- getssid.id.domainid = domid;
-
- if (xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid)) < 0) {
- if (errno == EACCES)
- PERROR("ACM operation failed.");
- buf = NULL;
- } else {
- *buflen = SSID_BUFFER_SIZE;
- }
- return buf;
-}
-
-
-/* retrieve the policytype indirectly by retrieving the
- * ssidref for domain 0 (always exists) */
-static PyObject *policy(PyObject * self, PyObject * args)
-{
- xc_interface *xc_handle;
- char *policyreference;
- PyObject *ret;
- uint32_t buf_len;
- DECLARE_HYPERCALL_BUFFER(void, ssid_buffer);
-
- if (!PyArg_ParseTuple(args, "", NULL)) {
- return NULL;
- }
- if ((xc_handle = xc_interface_open(0,0,0)) == 0)
- return PyErr_SetFromErrno(acm_error_obj);
-
- ssid_buffer = __getssid(xc_handle, 0, &buf_len, HYPERCALL_BUFFER(ssid_buffer));
- if (ssid_buffer == NULL || buf_len < sizeof(struct acm_ssid_buffer))
- ret = PyErr_SetFromErrno(acm_error_obj);
- else {
- struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)ssid_buffer;
- policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
- + sizeof (struct acm_policy_reference_buffer));
- ret = Py_BuildValue("s", policyreference);
- }
-
- xc_hypercall_buffer_free(xc_handle, ssid_buffer);
- xc_interface_close(xc_handle);
- return ret;
-}
-
-
-/* retrieve ssid info for a domain domid*/
-static PyObject *getssid(PyObject * self, PyObject * args)
-{
- xc_interface *xc_handle;
-
- /* in */
- uint32_t domid;
- /* out */
- char *policytype, *policyreference;
- uint32_t ssidref;
- PyObject *ret;
-
- DECLARE_HYPERCALL_BUFFER(void, ssid_buffer);
- uint32_t buf_len;
-
- if (!PyArg_ParseTuple(args, "i", &domid)) {
- return NULL;
- }
- if ((xc_handle = xc_interface_open(0,0,0)) == 0)
- return PyErr_SetFromErrno(acm_error_obj);
-
- ssid_buffer = __getssid(xc_handle, domid, &buf_len, HYPERCALL_BUFFER(ssid_buffer));
- if (ssid_buffer == NULL) {
- ret = NULL;
- } else if (buf_len < sizeof(struct acm_ssid_buffer)) {
- ret = NULL;
- } else {
- struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *) ssid_buffer;
- policytype = ACM_POLICY_NAME(ssid->secondary_policy_code << 4 |
- ssid->primary_policy_code);
- ssidref = ssid->ssidref;
- policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
- + sizeof (struct acm_policy_reference_buffer));
- ret = Py_BuildValue("{s:s,s:s,s:i}",
- "policyreference", policyreference,
- "policytype", policytype,
- "ssidref", ssidref);
- }
- xc_hypercall_buffer_free(xc_handle, ssid_buffer);
- xc_interface_close(xc_handle);
- return ret;
-}
-
-
-/* retrieve access decision based on domain ids or ssidrefs */
-static PyObject *getdecision(PyObject * self, PyObject * args)
-{
- char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL;
- struct acm_getdecision getdecision;
- xc_interface *xc_handle;
- int rc;
- uint32_t hooktype;
-
- if (!PyArg_ParseTuple(args, "ssssi", &arg1_name,
- &arg1, &arg2_name, &arg2, &hooktype)) {
- return NULL;
- }
-
- if ((xc_handle = xc_interface_open(0,0,0)) == 0) {
- perror("Could not open xen privcmd device!\n");
- return NULL;
- }
-
- if ((strcmp(arg1_name, "domid") && strcmp(arg1_name, "ssidref")) ||
- (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
- return NULL;
-
- getdecision.hook = hooktype;
- if (!strcmp(arg1_name, "domid")) {
- getdecision.get_decision_by1 = ACM_GETBY_domainid;
- getdecision.id1.domainid = atoi(arg1);
- } else {
- getdecision.get_decision_by1 = ACM_GETBY_ssidref;
- getdecision.id1.ssidref = atol(arg1);
- }
- if (!strcmp(arg2_name, "domid")) {
- getdecision.get_decision_by2 = ACM_GETBY_domainid;
- getdecision.id2.domainid = atoi(arg2);
- } else {
- getdecision.get_decision_by2 = ACM_GETBY_ssidref;
- getdecision.id2.ssidref = atol(arg2);
- }
-
- rc = xc_acm_op(xc_handle, ACMOP_getdecision,
- &getdecision, sizeof(getdecision));
-
- xc_interface_close(xc_handle);
-
- if (rc < 0) {
- if (errno == EACCES)
- PERROR("ACM operation failed.");
- return NULL;
- }
-
- if (getdecision.acm_decision == ACM_ACCESS_PERMITTED)
- decision = "PERMITTED";
- else if (getdecision.acm_decision == ACM_ACCESS_DENIED)
- decision = "DENIED";
-
- return Py_BuildValue("s", decision);
-}
-
-/* error messages for exceptions */
-const char bad_arg[] = "Bad function argument.";
-const char ctrlif_op[] = "Could not open control interface.";
-const char hv_op_err[] = "Error from hypervisor operation.";
-
-static PyObject *chgpolicy(PyObject *self, PyObject *args)
-{
- struct acm_change_policy chgpolicy;
- xc_interface *xc_handle;
- int rc;
- char *bin_pol = NULL, *del_arr = NULL, *chg_arr = NULL;
- int bin_pol_len = 0, del_arr_len = 0, chg_arr_len = 0;
- uint errarray_mbrs = 20 * 2;
- PyObject *result = NULL;
- uint len;
- DECLARE_HYPERCALL_BUFFER(char, bin_pol_buf);
- DECLARE_HYPERCALL_BUFFER(char, del_arr_buf);
- DECLARE_HYPERCALL_BUFFER(char, chg_arr_buf);
- DECLARE_HYPERCALL_BUFFER(uint32_t, error_array);
-
- memset(&chgpolicy, 0x0, sizeof(chgpolicy));
-
- if (!PyArg_ParseTuple(args, "s#s#s#" ,&bin_pol, &bin_pol_len,
- &del_arr, &del_arr_len,
- &chg_arr, &chg_arr_len)) {
- PyErr_SetString(PyExc_TypeError, bad_arg);
- return NULL;
- }
-
- if ((xc_handle = xc_interface_open(0,0,0)) == 0) {
- PyErr_SetString(PyExc_IOError, ctrlif_op);
- return NULL;
- }
-
- if ( (bin_pol_buf = xc_hypercall_buffer_alloc(xc_handle, bin_pol_buf, bin_pol_len)) == NULL )
- goto out;
- if ( (del_arr_buf = xc_hypercall_buffer_alloc(xc_handle, del_arr_buf, del_arr_len)) == NULL )
- goto out;
- if ( (chg_arr_buf = xc_hypercall_buffer_alloc(xc_handle, chg_arr_buf, chg_arr_len)) == NULL )
- goto out;
- if ( (error_array = xc_hypercall_buffer_alloc(xc_handle, error_array, sizeof(*error_array)*errarray_mbrs)) == NULL )
- goto out;
-
- memcpy(bin_pol_buf, bin_pol, bin_pol_len);
- memcpy(del_arr_buf, del_arr, del_arr_len);
- memcpy(chg_arr_buf, chg_arr, chg_arr_len);
-
- chgpolicy.policy_pushcache_size = bin_pol_len;
- chgpolicy.delarray_size = del_arr_len;
- chgpolicy.chgarray_size = chg_arr_len;
- chgpolicy.errarray_size = sizeof(*error_array)*errarray_mbrs;
- set_xen_guest_handle(chgpolicy.policy_pushcache, bin_pol_buf);
- set_xen_guest_handle(chgpolicy.del_array, del_arr_buf);
- set_xen_guest_handle(chgpolicy.chg_array, chg_arr_buf);
- set_xen_guest_handle(chgpolicy.err_array, error_array);
-
- rc = xc_acm_op(xc_handle, ACMOP_chgpolicy, &chgpolicy, sizeof(chgpolicy));
-
- /* only pass the filled error codes */
- for (len = 0; (len + 1) < errarray_mbrs; len += 2) {
- if (error_array[len] == 0) {
- len *= sizeof(error_array[0]);
- break;
- }
- }
-
- result = Py_BuildValue("is#", rc, error_array, len);
-
-out:
- xc_hypercall_buffer_free(xc_handle, bin_pol_buf);
- xc_hypercall_buffer_free(xc_handle, del_arr_buf);
- xc_hypercall_buffer_free(xc_handle, chg_arr_buf);
- xc_hypercall_buffer_free(xc_handle, error_array);
- xc_interface_close(xc_handle);
- return result;
-}
-
-
-static PyObject *getpolicy(PyObject *self, PyObject *args)
-{
- struct acm_getpolicy getpolicy;
- xc_interface *xc_handle;
- int rc;
- PyObject *result = NULL;
- uint32_t len = 8192;
- DECLARE_HYPERCALL_BUFFER(uint8_t, pull_buffer);
-
- if ((xc_handle = xc_interface_open(0,0,0)) == 0) {
- PyErr_SetString(PyExc_IOError, ctrlif_op);
- return NULL;
- }
-
- if ((pull_buffer = xc_hypercall_buffer_alloc(xc_handle, pull_buffer, len)) == NULL)
- goto out;
-
- memset(&getpolicy, 0x0, sizeof(getpolicy));
- set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
- getpolicy.pullcache_size = sizeof(pull_buffer);
-
- rc = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
-
- if (rc == 0) {
- struct acm_policy_buffer *header =
- (struct acm_policy_buffer *)pull_buffer;
- if (ntohl(header->len) < 8192)
- len = ntohl(header->len);
- } else {
- len = 0;
- }
-
- result = Py_BuildValue("is#", rc, pull_buffer, len);
-out:
- xc_hypercall_buffer_free(xc_handle, pull_buffer);
- xc_interface_close(xc_handle);
- return result;
-}
-
-
-static PyObject *relabel_domains(PyObject *self, PyObject *args)
-{
- struct acm_relabel_doms reldoms;
- xc_interface *xc_handle;
- int rc;
- char *relabel_rules = NULL;
- int rel_rules_len = 0;
- uint errarray_mbrs = 20 * 2;
- DECLARE_HYPERCALL_BUFFER(uint32_t, error_array);
- DECLARE_HYPERCALL_BUFFER(char, relabel_rules_buf);
- PyObject *result = NULL;
- uint len;
-
- memset(&reldoms, 0x0, sizeof(reldoms));
-
- if (!PyArg_ParseTuple(args, "s#" ,&relabel_rules, &rel_rules_len)) {
- PyErr_SetString(PyExc_TypeError, bad_arg);
- return NULL;
- }
-
- if ((xc_handle = xc_interface_open(0,0,0)) == 0) {
- PyErr_SetString(PyExc_IOError, ctrlif_op);
- return NULL;
- }
-
- if ((relabel_rules_buf = xc_hypercall_buffer_alloc(xc_handle, relabel_rules_buf, rel_rules_len)) == NULL)
- goto out;
- if ((error_array = xc_hypercall_buffer_alloc(xc_handle, error_array, sizeof(*error_array)*errarray_mbrs)) == NULL)
- goto out;
-
- memcpy(relabel_rules_buf, relabel_rules, rel_rules_len);
-
- reldoms.relabel_map_size = rel_rules_len;
- reldoms.errarray_size = sizeof(error_array);
-
- set_xen_guest_handle(reldoms.relabel_map, relabel_rules_buf);
- set_xen_guest_handle(reldoms.err_array, error_array);
-
- rc = xc_acm_op(xc_handle, ACMOP_relabeldoms, &reldoms, sizeof(reldoms));
-
- /* only pass the filled error codes */
- for (len = 0; (len + 1) < errarray_mbrs; len += 2) {
- if (error_array[len] == 0) {
- len *= sizeof(error_array[0]);
- break;
- }
- }
-
- result = Py_BuildValue("is#", rc, error_array, len);
-out:
- xc_hypercall_buffer_free(xc_handle, relabel_rules_buf);
- xc_hypercall_buffer_free(xc_handle, error_array);
- xc_interface_close(xc_handle);
-
- return result;
-}
-
-
-/*=================General Python Extension Declarations=================*/
-
-/* methods */
-static PyMethodDef acmMethods[] = {
- {"policy", policy, METH_VARARGS, "Retrieve Active ACM Policy Reference Name"},
- {"getssid", getssid, METH_VARARGS, "Retrieve label information and ssidref for a domain"},
- {"getdecision", getdecision, METH_VARARGS, "Retrieve ACM access control decision"},
- {"chgpolicy", chgpolicy, METH_VARARGS, "Change the policy in one step"},
- {"getpolicy", getpolicy, METH_NOARGS , "Get the binary policy from the hypervisor"},
- {"relabel_domains", relabel_domains, METH_VARARGS, "Relabel domains"},
- /* end of list (extend list above this line) */
- {NULL, NULL, 0, NULL}
-};
-
-/* inits */
-PyMODINIT_FUNC initacm(void)
-{
- PyObject *m = Py_InitModule("acm", acmMethods);
- acm_error_obj = PyErr_NewException("acm.Error", PyExc_RuntimeError, NULL);
- Py_INCREF(acm_error_obj);
- PyModule_AddObject(m, "Error", acm_error_obj);
-}
diff --git a/tools/python/xen/xm/messages/xen-xm.pot b/tools/python/xen/xm/messages/xen-xm.pot
index a600a69f0d..25c7556c30 100644
--- a/tools/python/xen/xm/messages/xen-xm.pot
+++ b/tools/python/xen/xm/messages/xen-xm.pot
@@ -8,10 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-31 17:40+0100\n"
+"POT-Creation-Date: 2011-03-25 21:46+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
diff --git a/tools/security/Makefile b/tools/security/Makefile
deleted file mode 100644
index f550ce2e56..0000000000
--- a/tools/security/Makefile
+++ /dev/null
@@ -1,94 +0,0 @@
-XEN_ROOT = $(CURDIR)/../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-CFLAGS += -Werror
-CFLAGS += -fno-strict-aliasing
-CFLAGS += $(CFLAGS_libxenctrl)
-
-CPPFLAGS += -MMD -MF .$*.d
-PROG_DEPS = .*.d
-
-XML2VERSION = $(shell xml2-config --version )
-CFLAGS += $(shell xml2-config --cflags )
-CFLAGS += $(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi )
-LDFLAGS += $(shell xml2-config --libs ) # if this does not work, try -L/usr/lib -lxml2 -lz -lpthread -lm
-
-SRCS_TOOL = secpol_tool.c
-OBJS_TOOL := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_TOOL)))
-
-ACM_INST_TOOLS = xensec_tool xensec_gen
-ACM_EZPOLICY = xensec_ezpolicy
-ACM_OBJS = $(OBJS_TOOL) $(OBJS_GETD)
-ACM_SCRIPTS = python/xensec_tools/acm_getlabel
-
-ACM_CONFIG_DIR = $(XEN_CONFIG_DIR)/acm-security
-ACM_POLICY_DIR = $(ACM_CONFIG_DIR)/policies
-ACM_SCRIPT_DIR = $(ACM_CONFIG_DIR)/scripts
-
-ACM_INST_HTML = python/xensec_gen/index.html
-ACM_INST_CGI = python/xensec_gen/cgi-bin/policy.cgi
-ACM_SECGEN_HTMLDIR= /var/lib/xensec_gen
-ACM_SECGEN_CGIDIR = $(ACM_SECGEN_HTMLDIR)/cgi-bin
-
-ACM_SCHEMA = security_policy.xsd
-ACM_EXAMPLES = client_v1 test
-ACM_DEF_POLICIES =
-ACM_POLICY_SUFFIX = security_policy.xml
-
-ifeq ($(ACM_SECURITY),y)
-.PHONY: all
-all: build
-
-.PHONY: install
-install: all $(ACM_CONFIG_FILE)
- $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
- $(INSTALL_PROG) $(ACM_INST_TOOLS) $(DESTDIR)$(SBINDIR)
- $(INSTALL_PROG) $(ACM_EZPOLICY) $(DESTDIR)$(SBINDIR)
- $(INSTALL_DIR) $(DESTDIR)$(ACM_CONFIG_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(ACM_POLICY_DIR)
- $(INSTALL_DATA) policies/$(ACM_SCHEMA) $(DESTDIR)$(ACM_POLICY_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(ACM_POLICY_DIR)/example
- set -e; for i in $(ACM_EXAMPLES); do \
- $(INSTALL_DATA) policies/example/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR)/example/; \
- done
- set -e; for i in $(ACM_DEF_POLICIES); do \
- $(INSTALL_DATA) policies/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR); \
- done
- $(INSTALL_DIR) $(DESTDIR)$(ACM_SCRIPT_DIR)
- $(INSTALL_PROG) $(ACM_SCRIPTS) $(DESTDIR)$(ACM_SCRIPT_DIR)
- $(INSTALL_DIR) $(DESTDIR)$(ACM_SECGEN_HTMLDIR)
- $(INSTALL_DATA) $(ACM_INST_HTML) $(DESTDIR)$(ACM_SECGEN_HTMLDIR)
- $(INSTALL_DIR) $(DESTDIR)$(ACM_SECGEN_CGIDIR)
- $(INSTALL_PROG) $(ACM_INST_CGI) $(DESTDIR)$(ACM_SECGEN_CGIDIR)
- $(PYTHON) python/setup.py install $(PYTHON_PREFIX_ARG) \
- --root="$(DESTDIR)" --force
-else
-.PHONY: all
-all:
-
-.PHONY: install
-install:
-endif
-
-.PHONY: build
-build: $(ACM_INST_TOOLS) $(ACM_NOINST_TOOLS)
- $(PYTHON) python/setup.py build
- chmod 700 $(ACM_SCRIPTS)
-
-xensec_tool: $(OBJS_TOOL)
- $(CC) -g $(CFLAGS) $(LDFLAGS) -O0 -o $@ $^ $(LDLIBS_libxenctrl)
-
-xensec_gen: xensec_gen.py
- cp -f $^ $@
-
-.PHONY: clean
-clean:
- $(RM) $(ACM_INST_TOOLS) $(ACM_NOINST_TOOLS)
- $(RM) $(ACM_OBJS)
- $(RM) $(PROG_DEPS)
- $(RM) -r build
-
-.PHONY: mrproper
-mrproper: clean
-
--include $(PROG_DEPS)
diff --git a/tools/security/policies/example/client_v1-security_policy.xml b/tools/security/policies/example/client_v1-security_policy.xml
deleted file mode 100644
index 2b3a6f098a..0000000000
--- a/tools/security/policies/example/client_v1-security_policy.xml
+++ /dev/null
@@ -1,195 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com -->
-<!-- This file defines the security policies, which -->
-<!-- can be enforced by the Xen Access Control Module. -->
-<!-- Currently: Chinese Wall and Simple Type Enforcement-->
-<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
- <PolicyHeader>
- <PolicyName>example.client_v1</PolicyName>
- <PolicyUrl>www.ibm.com/example/client_v1</PolicyUrl>
- <Date>2006-03-31</Date>
- <Version>1.0</Version>
- </PolicyHeader>
- <!-- -->
- <!-- example of a simple type enforcement policy definition -->
- <!-- -->
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>ste_SystemManagement</Type><!-- machine/security management -->
- <Type>ste_PersonalFinances</Type><!-- personal finances -->
- <Type>ste_InternetInsecure</Type><!-- games, active X, etc. -->
- <Type>ste_DonatedCycles</Type><!-- donation to BOINC/seti@home -->
- <Type>ste_PersistentStorageA</Type><!-- domain managing the harddrive A-->
- <Type>ste_NetworkAdapter0</Type><!-- type of the domain managing ethernet adapter 0-->
- </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
- <!-- -->
- <!-- example of a chinese wall type definition -->
- <!-- along with its conflict sets -->
- <!-- (typse in a confict set are exclusive, i.e. -->
- <!-- once a Domain with one type of a set is -->
- <!-- running, no other Domain with another type -->
- <!-- of the same conflict set can start.) -->
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>cw_SystemManagement</Type>
- <Type>cw_Sensitive</Type>
- <Type>cw_Isolated</Type>
- <Type>cw_Distrusted</Type>
- </ChineseWallTypes>
-
- <ConflictSets>
- <Conflict name="Protection1">
- <Type>cw_Sensitive</Type>
- <Type>cw_Distrusted</Type>
- </Conflict>
- </ConflictSets>
- </ChineseWall>
- <SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <!-- single ste typed domains -->
- <!-- ACM enforces that only domains with -->
- <!-- the same type can share information -->
- <!-- -->
- <!-- Bootstrap label is assigned to Dom0 -->
- <VirtualMachineLabel>
- <Name>dom_HomeBanking</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_PersonalFinances</Type>
- </SimpleTypeEnforcementTypes>
-
- <ChineseWallTypes>
- <Type>cw_Sensitive</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>dom_Fun</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_InternetInsecure</Type>
- </SimpleTypeEnforcementTypes>
-
- <ChineseWallTypes>
- <Type>cw_Distrusted</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <!-- donating some cycles to seti@home -->
- <Name>dom_BoincClient</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_DonatedCycles</Type>
- </SimpleTypeEnforcementTypes>
-
- <ChineseWallTypes>
- <Type>cw_Isolated</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <!-- Domains with multiple ste types services; such domains -->
- <!-- must keep the types inside their domain safely confined. -->
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <!-- since dom0 needs access to every domain and -->
- <!-- resource right now ... -->
- <Type>ste_SystemManagement</Type>
- <Type>ste_PersonalFinances</Type>
- <Type>ste_InternetInsecure</Type>
- <Type>ste_DonatedCycles</Type>
- <Type>ste_PersistentStorageA</Type>
- <Type>ste_NetworkAdapter0</Type>
- </SimpleTypeEnforcementTypes>
-
- <ChineseWallTypes>
- <Type>cw_SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <!-- serves persistent storage to other domains -->
- <Name>dom_StorageDomain</Name>
- <SimpleTypeEnforcementTypes>
- <!-- access right to the resource (hard drive a) -->
- <Type>ste_PersistentStorageA</Type>
- <!-- can serve following types -->
- <Type>ste_PersonalFinances</Type>
- <Type>ste_InternetInsecure</Type>
- </SimpleTypeEnforcementTypes>
-
- <ChineseWallTypes>
- <Type>cw_SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <!-- serves network access to other domains -->
- <Name>dom_NetworkDomain</Name>
- <SimpleTypeEnforcementTypes>
- <!-- access right to the resource (ethernet card) -->
- <Type>ste_NetworkAdapter0</Type>
- <!-- can serve following types -->
- <Type>ste_PersonalFinances</Type>
- <Type>ste_InternetInsecure</Type>
- <Type>ste_DonatedCycles</Type>
- </SimpleTypeEnforcementTypes>
-
- <ChineseWallTypes>
- <Type>cw_SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- </SubjectLabels>
-
- <ObjectLabels>
- <ResourceLabel>
- <Name>res_ManagementResource</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>res_HardDrive(hda)</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_PersistentStorageA</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>res_LogicalDiskPartition1(hda1)</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_PersonalFinances</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>res_LogicalDiskPartition2(hda2)</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_InternetInsecure</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>res_EthernetCard</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_NetworkAdapter0</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>res_SecurityToken</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_PersonalFinances</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>res_GraphicsAdapter</Name>
- <SimpleTypeEnforcementTypes>
- <Type>ste_SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- </ObjectLabels>
- </SecurityLabelTemplate>
-</SecurityPolicyDefinition>
-
diff --git a/tools/security/policies/example/test-security_policy.xml b/tools/security/policies/example/test-security_policy.xml
deleted file mode 100644
index 0f338a2c0b..0000000000
--- a/tools/security/policies/example/test-security_policy.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Auto-generated by ezPolicy -->
-<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
- <PolicyHeader>
- <PolicyName>example.test</PolicyName>
- <Date>Mon Apr 16 13:13:59 2007</Date>
- <Version>1.0</Version>
- </PolicyHeader>
-
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>PepsiCo</Type>
- <Type>CocaCola</Type>
- </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
-
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- <Type>PepsiCo</Type>
- <Type>CocaCola</Type>
- <Type>VIOServer</Type>
- </ChineseWallTypes>
-
- </ChineseWall>
-
- <SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>PepsiCo</Type>
- <Type>CocaCola</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>PepsiCo</Name>
- <SimpleTypeEnforcementTypes>
- <Type>PepsiCo</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>PepsiCo</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>CocaCola</Name>
- <SimpleTypeEnforcementTypes>
- <Type>CocaCola</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>CocaCola</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>VIO</Name>
- <SimpleTypeEnforcementTypes>
- <Type>CocaCola</Type>
- <Type>PepsiCo</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>VIOServer</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- </SubjectLabels>
-
- <ObjectLabels>
- <ResourceLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>PepsiCo</Name>
- <SimpleTypeEnforcementTypes>
- <Type>PepsiCo</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>CocaCola</Name>
- <SimpleTypeEnforcementTypes>
- <Type>CocaCola</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- </ObjectLabels>
- </SecurityLabelTemplate>
-</SecurityPolicyDefinition>
diff --git a/tools/security/policies/security_policy.xsd b/tools/security/policies/security_policy.xsd
deleted file mode 100644
index 4391a77253..0000000000
--- a/tools/security/policies/security_policy.xsd
+++ /dev/null
@@ -1,146 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Author: Ray Valdez, Reiner Sailer {rvaldez,sailer}@us.ibm.com -->
-<!-- This file defines the schema, which is used to define -->
-<!-- the security policy and the security labels in Xen. -->
-
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ibm.com" xmlns="http://www.ibm.com" elementFormDefault="qualified">
- <xsd:element name="SecurityPolicyDefinition">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="PolicyHeader" minOccurs="1" maxOccurs="1"></xsd:element>
- <xsd:element ref="SimpleTypeEnforcement" minOccurs="0" maxOccurs="1"></xsd:element>
- <xsd:element ref="ChineseWall" minOccurs="0" maxOccurs="1"></xsd:element>
- <xsd:element ref="SecurityLabelTemplate" minOccurs="1" maxOccurs="1"></xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="PolicyHeader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="PolicyName" minOccurs="1" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="PolicyUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="Reference" type="xsd:string" minOccurs="0" maxOccurs="1" />
- <xsd:element name="Date" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="NameSpaceUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/>
- <xsd:element ref="FromPolicy" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ChineseWall">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="ChineseWallTypes" minOccurs="1" maxOccurs="1" />
- <xsd:element ref="ConflictSets" minOccurs="0" maxOccurs="1" />
- </xsd:sequence>
- <xsd:attribute name="priority" type="PolicyOrder" use="optional"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SimpleTypeEnforcement">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="SimpleTypeEnforcementTypes" />
- </xsd:sequence>
- <xsd:attribute name="priority" type="PolicyOrder" use="optional"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SecurityLabelTemplate">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="SubjectLabels" minOccurs="0" maxOccurs="1">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="VirtualMachineLabel" minOccurs="1" maxOccurs="unbounded"></xsd:element>
- </xsd:sequence>
- <xsd:attribute name="bootstrap" type="xsd:string" use="required"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ObjectLabels" minOccurs="0" maxOccurs="1">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="ResourceLabel" minOccurs="1" maxOccurs="unbounded"></xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ChineseWallTypes">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ConflictSets">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Conflict" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SimpleTypeEnforcementTypes">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Conflict">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required"></xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="VirtualMachineLabel">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="Name" type="NameWithFrom"></xsd:element>
- <xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" />
- <xsd:element ref="ChineseWallTypes" minOccurs="0" maxOccurs="unbounded" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ResourceLabel">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="Name" type="NameWithFrom"></xsd:element>
- <xsd:element name="SimpleTypeEnforcementTypes" type="SingleSimpleTypeEnforcementType" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Name" type="xsd:string" />
- <xsd:element name="Type" type="xsd:string" />
- <xsd:simpleType name="PolicyOrder">
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="PrimaryPolicyComponent"></xsd:enumeration>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:element name="FromPolicy">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="PolicyName" minOccurs="1" maxOccurs="1" type="xsd:string"/>
- <xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:simpleType name="VersionFormat">
- <xsd:restriction base="xsd:string">
- <xsd:pattern value="[0-9]{1,8}.[0-9]{1,8}"></xsd:pattern>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:complexType name="NameWithFrom">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="from" type="xsd:string" use="optional"></xsd:attribute>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- <xsd:complexType name="SingleSimpleTypeEnforcementType">
- <xsd:sequence>
- <xsd:element maxOccurs="1" minOccurs="1" ref="Type" />
- </xsd:sequence>
- </xsd:complexType>
-</xsd:schema>
diff --git a/tools/security/policy.txt b/tools/security/policy.txt
deleted file mode 100644
index 493d1f2e55..0000000000
--- a/tools/security/policy.txt
+++ /dev/null
@@ -1,296 +0,0 @@
-##
-# policy.txt <description to the sHype/Xen access control architecture>
-#
-# Author:
-# Reiner Sailer 08/30/2006 <sailer@watson.ibm.com>
-#
-#
-# This file gives an overview of the example security policies.
-##
-
-Example of a Chinese Wall Policy Instantiation
-----------------------------------------------
-
-The file client_v1-security_policy.xml defines the Chinese Wall types
-as well as the conflict sets for our example policy (you find it in
-the directory "policy_root"/example/chwall).
-
-It defines four Chinese Wall types (prefixed with cw_) with the
-following meaning:
-
-* cw_SystemsManagement is a type identifying workloads for systems
-management, e.g., domain management, device management, or hypervisor
-management.
-
-* cw_Sensitive is identifying workloads that are critical to the user
-for one reason or another.
-
-* cw_Distrusted is identifying workloads a user does not have much
-confidence in. E.g. a domain used for surfing in the internet without
-protection( i.e., active-X, java, java-script, executing web content)
-or for (Internet) Games should be typed this way.
-
-* cw_Isolated is identifying workloads that are supposedly isolated by
-use of the type enforcement policy (described below). For example, if
-a user wants to donate cycles to seti@home, she can setup a separate
-domain for a Boinc (http://boinc.ssl.berkeley.edu/) client, disable
-this domain from accessing the hard drive and from communicating to
-other local domains, and type it as cw_Isolated. We will look at a
-specific example later.
-
-The example policy uses the defined types to define one conflict set:
-Protection1 = {cw_Sensitive, cw_Distrusted}. This conflict set tells
-the hypervisor that once a domain typed as cw_Sensitive is running, a
-domain typed as cw_Distrusted cannot run concurrently (and the other
-way round). With this policy, a domain typed as cw_Isolated is allowed
-to run simultaneously with domains tagged as cw_Sensitive.
-
-Consequently, the access control module in the Xen hypervisor
-distinguishes in this example policy 4 different workload types in
-this example policy. It is the user's responsibility to type the
-domains in a way that reflects the workloads of these domains and, in
-the case of cw_Isolated, its properties, e.g. by configuring the
-sharing capabilities of the domain accordingly by using the simple
-type enforcement policy.
-
-Users can define their own or change the existing example policy
-according to their working environment and security requirements. To
-do so, replace the file chwall-security_policy.xml with the new
-policy.
-
-
-SIMPLE TYPE ENFORCEMENT
-=======================
-
-The file client_v1-security_policy.xml defines the simple type
-enforcement types for our example policy (you find it in the directory
-"policy_root"/example/ste). The Simple Type Enforcement policy defines
-which domains can share information with which other domains. To this
-end, it controls
-
-i) inter-domain communication channels (e.g., network traffic, events,
-and shared memory).
-
-ii) access of domains to physical resources (e.g., hard drive, network
-cards, graphics adapter, keyboard).
-
-In order to enable the hypervisor to distinguish different domains and
-the user to express access rules, the simple type enforcement defines
-a set of types (ste_types).
-
-The policy defines that communication between domains is allowed if
-the domains share a common STE type. As with the chwall types, STE
-types should enable the differentiation of workloads. The simple type
-enforcement access control implementation in the hypervisor enforces
-that domains can only communicate (setup event channels, grant tables)
-if they share a common type, i.e., both domains have assigned at least
-on type in common. A domain can access a resource, if the domain and
-the resource share a common type. Hence, assigning STE types to
-domains and resources allows users to define constraints on sharing
-between domains and to keep sensitive data confined from distrusted
-domains.
-
-Domain <--> Domain Sharing
-''''''''''''''''''''''''''
-(implemented but its effective use requires factorization of Dom0)
-
-a) Domains with a single STE type (general user domains): Sharing
-between such domains is enforced entirely by the hypervisor access
-control. It is independent of the domains and does not require their
-co-operation.
-
-b) Domains with multiple STE types: One example is a domain that
-virtualizes a physical resource (e.g., hard drive) and serves it as
-multiple virtual resources (virtual block drives) to other domains of
-different types. The idea is that only a specific device domain has
-assigned the type required to access the physical hard-drive. Logical
-drives are then assigned the types of domains that have access to this
-logical drive. Since the Xen hypervisor cannot distinguish between the
-logical drives, the access control (type enforcement) is delegated to
-the device domain, which has access to the types of domains requesting
-to mount a logical drive as well as the types assigned to the
-different available logical drives.
-
-Currently in Xen, Dom0 controls all hardware, needs to communicate
-with all domains during their setup, and intercepts all communication
-between domains. Consequently, Dom0 needs to be assigned all types
-used and must be completely trusted to maintain the separation of
-information coming from domains with different STE types. Thus a
-refactoring of Dom0 is recommended for stronger confinement
-guarantees.
-
-Domain --> RESOURCES Access
-'''''''''''''''''''''''''''
-
-We define for each resource that we want to distinguish a separate STE
-type. Each STE type is assigned to the respective resource and to
-those domains that are allowed to access this resource. Type
-enforcement will guarantee that other domains cannot access this
-resource since they don't share the resource's STE type.
-
-Since in the current implementation of Xen, Dom0 controls access to
-all hardware (e.g., disk drives, network), Domain-->Resource access
-control enforcement must be implemented in Dom0. This is possible
-since Dom0 has access to both the domain configuration (including the
-domain STE types) and the resource configuration (including the
-resource STE types).
-
-For purposes of gaining higher assurance in the resulting system, it
-may be desirable to reduce the size of dom0 by adding one or more
-"device domains" (DDs). These DDs, e.g. providing storage or network
-access, can support one or more physical devices, and manage
-enforcement of MAC policy relevant for said devices. Security benefits
-come from the smaller size of these DDs, as they can be more easily
-audited than monolithic device driver domains. DDs can help to obtain
-maximum security benefit from sHype.
-
-
-Example of a Simple Type Enforcement Policy Instantiation
----------------------------------------------------------
-The example policies define the following types:
-
-* ste_SystemManagement identifies workloads (and domains that runs
-them) that must share information to accomplish the management of the
-system
-
-* ste_PersonalFinances identifies workloads that are related to
-sensitive programs such as HomeBanking applications or safely
-configured web browsers for InternetBanking
-
-* ste_InternetInsecure identifies workloads that are very
-function-rich and unrestricted to offer for example an environment
-where internet games can run efficiently
-
-* ste_DonatedCycles identifies workloads that run on behalf of others,
-e.g. a Boinc client
-
-* ste_PersistentStorage identifies workloads that have direct access
-to persistent storage (e.g., hard drive)
-
-* ste_NetworkAccess identifies workload that have direct access to
-network cards and related networks
-
-
-
-SECURITY LABEL TEMPLATES
-========================
-
-We introduce security label templates because it is difficult for
-users to ensure tagging of domains consistently and since there are
---as we have seen in the case of isolation-- useful dependencies
-between the policies. Security Label Templates define type sets that
-can be addressed by more user-friendly label names,
-e.g. dom_Homebanking describes a typical typeset tagged to domains
-used for sensitive Homebanking work-loads. Labels are defined in the
-file
-
-Using Security Label Templates has multiple advantages:
-a) easy reference of typical sets of type assignments
-b) consistent interpretation of type combinations
-c) meaningful application-level label names
-
-The definition of label templates depends on the combination of
-policies that are used. We will describe some of the labels defined
-for the Chinese Wall and Simple Type Enforcement combination.
-
-In the BoincClient example, the label_template file specifies that
-this Label is assigned the Chinese Wall type cw_Isolated. We do this
-assuming that this BoincClient is isolated against the rest of the
-system infrastructure (no persistent memory, no sharing with local
-domains). Since cw_Isolated is not included in any conflict set, it
-can run at any time concurrently with any other domain. The
-ste_DonatedCycles type assigned to the BoincClient reflect the
-isolation assumption: it is only assigned to the dom_NetworkDomain
-giving the BoincClient domain access to the network to communicate
-with its BoincServer.
-
-The strategy for combining types into Labels is the following: First
-we define a label for each type of general user domain
-(workload-oriented). Then we define a new label for each physical
-resource that shall be shared using a DD domain (e.g., disk) and for
-each logical resource offered through this physical resource (logical
-disk partition). We define then device domain labels (here:
-dom_SystemManagement, dom_StorageDomain, dom_NetworkDomain) which
-include the types of the physical resources (e.g. hda) their domains
-need to connect to. Such physical resources can only be accessed
-directly by device domains types with the respective device's STE
-type. Additionally we assign to such a device domain Label the STE
-types of those user domains that are allowed to access one of the
-logical resources (e.g., hda1, hda2) built on top of this physical
-resource through the device domain.
-
-
-Label Construction Example:
----------------------------
-
-We define here a storage domain label for a domain that owns a real
-disk drive and creates the logical disk partitions hda1 and hda2 which
-it serves to domains labeled dom_HomeBanking and dom_Fun
-respectively. The labels we refer to are defined in the label template
-file policies/chwall_ste/chwall_ste-security-label-template.xml.
-
-step1: To distinguish different shared disk drives, we create a
-separate Label and STE type for each of them. Here: we create a type
-ste_PersistentStorageA for disk drive hda. If you have another disk
-drive, you may define another persistent storage type
-ste_PersistentStorageB in the chwall_ste-security_policy.xml.
-
-step2: To distinguish different domains, we create multiple domain
-labels including different types. Here: label dom_HomeBanking includes
-STE type ste_PersonalFinances, label dom_Fun includes STE type
-ste_InternetInsecure.
-
-step3: The storage domain in charge of the hard drive A needs access
-to this hard drive. Therefore the storage domain label
-dom_StorageDomain must include the type assigned to the hard drive
-(ste_PersistentStorageA).
-
-step4: In order to serve dom hda1 to domains labeled dom_HomeBanking
-and hda2 to domains labeled dom_Fun, the storage domain label must
-include the types of those domains as well (ste_PersonalFinance,
-ste_InternetInsecure).
-
-step5: In order to keep the data for different types safely apart, the
-different logical disk partitions must be assigned unique labels and
-types, which are used inside the storage domain to extend the ACM
-access enforcement to logical resources served from inside the storage
-domain. We define labels "res_LogicalDiskPartition1 (hda1)" and assign
-it to hda1 and "res_LogicalDiskPartition2 (hda2)" and assign it to
-hda2. These labels must include the STE types of those domains that
-are allowed to use them (e.g., ste_PersonalFinances for hda1).
-
-The overall mandatory access control is then enforced in 3 different
-Xen components and these components use a single consistent policy to
-co-operatively enforce the policy. In the storage domain example, we
-have three components that co-operate:
-
-1. The ACM module inside the hypervisor enforces: communication
-between user domains and the storage domain (only domains including
-types ste_PersonalFinances or ste_InternetInsecure can communicate
-with the storage domain and request access to logical resource). This
-confines the sharing to the types assigned to the storage domain.
-
-2. The domain management enforces: assignment of real resources (hda)
-to domains (storage domain) that share a type with the resource.
-
-3. If the storage domain serves multiple STE types (as in our
-example), it enforces: that domains can access (mount) logical
-resources only if they share an STE type with the respective
-resource. In our example, domains with the STE type
-ste_PersonalFinances can request access (mount) to logical resource
-hda1 from the storage domain.
-
-If you look at the virtual machine label dom_StorageDomain, you will
-see the minimal set of types assigned to our domain manageing disk
-drive hda for serving logical disk partitions exclusively to
-dom_HomeBanking and dom_Fun.
-
-Similary, network domains can confine access to the network or network
-communication between user domains.
-
-As a result, device domains (e.g., storage domain, network domain)
-must be simple and small to ensure their correct co-operation in the
-type enforcement model. If such trust is not possible, then hardware
-should be assigned exclusively to a single type (or to a single
-partition) in which case the hypervisor ACM enforcement enforces the
-types independently.
diff --git a/tools/security/policytools.txt b/tools/security/policytools.txt
deleted file mode 100644
index fb863f4722..0000000000
--- a/tools/security/policytools.txt
+++ /dev/null
@@ -1,148 +0,0 @@
-##
-# policytools.txt
-# <description to the sHype/Xen policy management tools>
-#
-# Author:
-# Reiner Sailer 08/31/2006 <sailer@watson.ibm.com>
-#
-#
-##
-
-This file describes the Xen-tools to create and maintain security
-policies for the sHype/Xen access control module.
-
-A security policy (e.g. "example.chwall_ste.test") is defined in
-XML. Read in the user manual about the naming of policies. The policy
-name is used by the Xen management tools to identify existing
-policies. Creating the security policy means creating a policy
-description in XML:
-/etc/xen/acm-security/policies/example/chwall_ste/test-security_policy.xml.
-
-The policy XML description must follow the XML schema definition in
-/etc/xen/acm-security/policies/security_policy.xsd. The policy tools
-are written against this schema; they will create and refine policies
-that conform to this scheme.
-
-Two tools are provided to help creating security policies:
-
-
-1. xensec_ezpolicy: The starting point for writing security policies.
-===================
-
-This wxPython-based GUI tool is meant to create very quickly a
-starting point for a workload protection security policy. Please start
-the tool (xensec_ezpolicy) and press <CTRL-h> for usage explanations.
-The Xen User guide explains its usage at an example in chapter
-"sHype/Xen Access Control".
-
-The output of the tool is a security policy that is fully operable. It
-is sufficient to create policies that demonstrate how sHype/ACM works.
-
-However, it defines only a basic set of security labels assuming that
-Domain0 hosts and virtualizes all hardware (storage etc.). Use
-xensec_gen to refine this policy and tailor it to your requirements.
-
-
-2. xensec_gen: The tool to refine a basic security policy:
-==============
-
-The xensec_gen utility starts a web-server that can be used to
-generate the XML policy files needed to create or maintain a
-policy. It can be pre-loaded with a policy file created by
-xensec_ezpolicy.
-
-By default, xensec_gen runs as a daemon and listens on port 7777 for
-HTTP requests. The xensec_gen command supports command line options
-to change the listen port, run in the foreground, and a few others.
-Type 'xensec_gen -h' to see the full list of options available.
-
-Once the xensec_gen utility is running, point a browser at the host
-and port on which the utility is running (e.g. http://localhost:7777).
-You will be presented with a web page that allows you to create or
-modify the XML policy file:
-
- - The Security Policy types section allows you to create or modify
-the policy types and conflict set definitions
-
- - The Security Policy Labeling section allows you to create or
-modify label definitions
-
-The policy generation tool allows you to modify an existing policy
-definition or create a new policy definition file. To modify an
-existing policy definition, enter the full path to the existing file
-(the "Browse" button can be used to aid in this) in the Policy File
-entry field. To create a new policy definition file leave the Policy
-File entry field blank. At this point click the "Create" button to
-begin modifying or creating your policy definition.
-
- Security Policy Types Section
- -----------------------------
-
-You will then be presented with a web page. The upper part of it will
-allow you to create either Simple Type Enforcement types or Chinese
-Wall types or both, as well as Chinese Wall conflict sets.
-
-As an example, to add a Simple Type Enforcement type:
-
-- Enter the name of a new type under the Simple Type Enforcement Types
-section in the entry field above the "New" button.
-
-- Click the "New" button and the type will be added to the list of
-defined Simple Type Enforcement types.
-
-To remove a Simple Type Enforcement type:
-
-- Click on the type to be removed in the list of defined Simple Type
-Enforcement types.
-
-- Click the "Delete" button to remove the type.
-
-Follow the same process to add Chinese Wall types. The Chinese Wall
-Conflict Set allows you to add Chinese Wall types from the list of
-defined Chinese Wall types.
-
-
- Security Policy Labels:
- -------------------------
-
-The security policy label section of the web page allows you to create
-labels for classes of virtual machines and resources. The input
-policy type definitions on the upper part of the web page will provide
-the available types (Simple Type Enforcement and/or Chinese Wall) that
-can be assigned to a virtual machine class. Resource classes only
-include simple type enforcement types; the Chinese Wall policy does
-apply only to virtual machines.
-
-As an example, to add a Virtual Machine class (the name entered will
-become the label that will be used to identify the class):
-
-- Enter the name of a new class under the Virtual Machine Classes
-section in the entry field above the "New" button.
-
-- Click the "New" button and the class will be added to the table of
-defined Virtual Machine classes.
-
-To remove a Virtual Machine class:
-
-- Click the "Delete" link associated with the class in the table of
-Virtual Machine classes.
-
-Once you have defined one or more Virtual Machine classes, you will
-be able to add any of the defined Simple Type Enforcement types or
-Chinese Wall types to a particular Virtual Machine.
-
-If you create a new policy, you must also define which Virtual Machine
-class is to be associated with the bootstrap domain (or Dom0 domain).
-By default, the first Virtual Machine class created will be associated
-as the bootstrap domain.
-
-To save your policy definition file, click on the "Generate XML"
-button on the top of the page. This will present you with a dialog
-box to save the generated XML file on your system. The default name
-will be security_policy.xml which you should change to follow the
-policy file naming conventions based on the policy name that you
-choose to use.
-
-To get a feel for the tool, you could use one of the example policy
-definitions files from /etc/xen/acm-security/policies/example as
-input or a policy created by the xensec_ezpolicy tool.
diff --git a/tools/security/python/setup.py b/tools/security/python/setup.py
deleted file mode 100644
index 26c88b33c0..0000000000
--- a/tools/security/python/setup.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License,
-# or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-from distutils.core import setup
-import os
-
-# This setup script is invoked from the parent directory, so base
-# everything as if executing from there.
-XEN_ROOT = "../.."
-
-setup(name = 'xensec_gen',
- version = '3.0',
- description = 'Xen XML Security Policy Generator',
- package_dir = { 'xen' : 'python' },
- packages = ['xen.xensec_gen'],
- )
diff --git a/tools/security/python/xensec_gen/__init__.py b/tools/security/python/xensec_gen/__init__.py
deleted file mode 100644
index 8b13789179..0000000000
--- a/tools/security/python/xensec_gen/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/security/python/xensec_gen/cgi-bin/policy.cgi b/tools/security/python/xensec_gen/cgi-bin/policy.cgi
deleted file mode 100644
index d429c57cb1..0000000000
--- a/tools/security/python/xensec_gen/cgi-bin/policy.cgi
+++ /dev/null
@@ -1,2376 +0,0 @@
-#!/usr/bin/python
-#
-# The Initial Developer of the Original Code is International
-# Business Machines Corporation. Portions created by IBM
-# Corporation are Copyright (C) 2005, 2006 International Business
-# Machines Corporation. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License,
-# or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-import os
-import cgi
-import cgitb; cgitb.enable( )
-import time
-import xml.dom.minidom
-import xml.sax
-import xml.sax.handler
-from StringIO import StringIO
-from sets import Set
-
-def getSavedData( ):
- global formData, policyXml
- global formVariables, formCSNames, formVmNames, formResNames
- global allCSMTypes, allVmChWs, allVmStes, allResStes
-
- # Process the XML upload policy file
- if formData.has_key( 'i_policy' ):
- dataList = formData.getlist( 'i_policy' )
- if len( dataList ) > 0:
- policyXml = dataList[0]
-
- # Process all the hidden input variables (if present)
- for formVar in formVariables:
- if formVar[2] == '':
- continue
-
- if formData.has_key( formVar[2] ):
- dataList = formData.getlist( formVar[2] )
- if len( dataList ) > 0:
- if isinstance( formVar[1], list ):
- exec 'formVar[1] = ' + dataList[0]
- else:
- formVar[1] = dataList[0]
-
- # The form can contain any number of "Conflict Sets"
- # so update the list of form variables to include
- # each conflict set (hidden input variable)
- for csName in formCSNames[1]:
- newCS( csName )
- if formData.has_key( allCSMTypes[csName][2] ):
- dataList = formData.getlist( allCSMTypes[csName][2] )
- if len( dataList ) > 0:
- exec 'allCSMTypes[csName][1] = ' + dataList[0]
-
- # The form can contain any number of "Virtual Machines"
- # so update the list of form variables to include
- # each virtual machine (hidden input variable)
- for vmName in formVmNames[1]:
- newVm( vmName )
-
- vmFormVar = allVmChWs[vmName]
- if (vmFormVar[2] != '') and formData.has_key( vmFormVar[2] ):
- dataList = formData.getlist( vmFormVar[2] )
- if len( dataList ) > 0:
- if isinstance( vmFormVar[1], list ):
- exec 'vmFormVar[1] = ' + dataList[0]
- else:
- vmFormVar[1] = dataList[0]
-
- vmFormVar = allVmStes[vmName]
- if (vmFormVar[2] != '') and formData.has_key( vmFormVar[2] ):
- dataList = formData.getlist( vmFormVar[2] )
- if len( dataList ) > 0:
- if isinstance( vmFormVar[1], list ):
- exec 'vmFormVar[1] = ' + dataList[0]
- else:
- vmFormVar[1] = dataList[0]
-
- # The form can contain any number of "Resources"
- # so update the list of form variables to include
- # each resource (hidden input variable)
- for resName in formResNames[1]:
- newRes( resName )
-
- resFormVar = allResStes[resName]
- if (resFormVar[2] != '') and formData.has_key( resFormVar[2] ):
- dataList = formData.getlist( resFormVar[2] )
- if len( dataList ) > 0:
- if isinstance( resFormVar[1], list ):
- exec 'resFormVar[1] = ' + dataList[0]
- else:
- resFormVar[1] = dataList[0]
-
-
-def getCurrentTime( ):
- return time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime( ) )
-
-def getName( domNode ):
- nameNodes = domNode.getElementsByTagName( 'Name' )
- if len( nameNodes ) == 0:
- formatXmlError( '"<Name>" tag is missing' )
- return None
-
- name = ''
- for childNode in nameNodes[0].childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- name = name + childNode.data
- return name
-
-def getPolicyName( domNode ):
- nameNodes = domNode.getElementsByTagName( 'PolicyName' )
- if len( nameNodes ) == 0:
- formatXmlError( '"<PolicyName>" tag is missing' )
- return None
-
- name = ''
- for childNode in nameNodes[0].childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- name = name + childNode.data
-
- return name
-
-def getUrl( domNode ):
- urlNodes = domNode.getElementsByTagName( 'PolicyUrl' )
- if len( urlNodes ) == 0:
- return ''
-
- url = ''
- for childNode in urlNodes[0].childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- url = url + childNode.data
-
- return url
-
-def getRef( domNode ):
- refNodes = domNode.getElementsByTagName( 'Reference' )
- if len( refNodes ) == 0:
- return ''
-
- ref = ''
- for childNode in refNodes[0].childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- ref = ref + childNode.data
-
- return ref
-
-def getDate( domNode ):
- dateNodes = domNode.getElementsByTagName( 'Date' )
- if len( dateNodes ) == 0:
- return ''
-
- date = ''
- for childNode in dateNodes[0].childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- date = date + childNode.data
-
- return date
-
-def getNSUrl( domNode ):
- urlNodes = domNode.getElementsByTagName( 'NameSpaceUrl' )
- if len( urlNodes ) == 0:
- return ''
-
- url = ''
- for childNode in urlNodes[0].childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- url = url + childNode.data
-
- return url
-
-def getSteTypes( domNode, missingIsError = 0 ):
- steNodes = domNode.getElementsByTagName( 'SimpleTypeEnforcementTypes' )
- if len( steNodes ) == 0:
- if missingIsError == 1:
- formatXmlError( '"<SimpleTypeEnforcementTypes>" tag is missing' )
- return None
- else:
- return []
-
- return getTypes( steNodes[0] )
-
-def getChWTypes( domNode, missingIsError = 0 ):
- chwNodes = domNode.getElementsByTagName( 'ChineseWallTypes' )
- if len( chwNodes ) == 0:
- if missingIsError == 1:
- formatXmlError( '"<ChineseWallTypes>" tag is missing' )
- return None
- else:
- return []
-
- return getTypes( chwNodes[0] )
-
-def getTypes( domNode ):
- types = []
-
- domNodes = domNode.getElementsByTagName( 'Type' )
- if len( domNodes ) == 0:
- formatXmlError( '"<Type>" tag is missing' )
- return None
-
- for domNode in domNodes:
- typeText = ''
- for childNode in domNode.childNodes:
- if childNode.nodeType == xml.dom.Node.TEXT_NODE:
- typeText = typeText + childNode.data
-
- if typeText == '':
- formatXmlError( 'No text associated with the "<Type>" tag' )
- return None
-
- types.append( typeText )
-
- return types
-
-def formatXmlError( msg, xml = '', lineNum = -1, colNum = -1 ):
- global xmlMessages, xmlError
-
- xmlError = 1
- addMsg = cgi.escape( msg )
-
- if lineNum != -1:
- sio = StringIO( xml )
- for xmlLine in sio:
- lineNum = lineNum - 1
- if lineNum == 0:
- break;
-
- addMsg += '<BR><PRE>' + cgi.escape( xmlLine.rstrip( ) )
-
- if colNum != -1:
- errLine = ''
- for i in range( colNum ):
- errLine = errLine + '-'
-
- addMsg += '\n' + errLine + '^'
-
- addMsg += '</PRE>'
-
- xmlMessages.append( addMsg )
-
-def formatXmlGenError( msg ):
- global xmlMessages, xmlIncomplete
-
- xmlIncomplete = 1
- xmlMessages.append( cgi.escape( msg ) )
-
-def parseXml( xmlInput ):
- xmlParser = xml.sax.make_parser( )
- try:
- domDoc = xml.dom.minidom.parseString( xmlInput, xmlParser )
-
- except xml.sax.SAXParseException, xmlErr:
- msg = ''
- msg = msg + 'XML parsing error occurred at line '
- msg = msg + `xmlErr.getLineNumber( )`
- msg = msg + ', column '
- msg = msg + `xmlErr.getColumnNumber( )`
- msg = msg + ': reason = "'
- msg = msg + xmlErr.getMessage( )
- msg = msg + '"'
- formatXmlError( msg, xmlInput, xmlErr.getLineNumber( ), xmlErr.getColumnNumber( ) )
- return None
-
- except xml.sax.SAXException, xmlErr:
- msg = ''
- msg = msg + 'XML Parsing error: ' + `xmlErr`
- formatXmlError( msg, xmlInput, xmlErr.getLineNumber( ), xmlErr.getColumnNumber( ) )
- return None
-
- return domDoc
-
-def parsePolicyXml( ):
- global policyXml
- global formPolicyName, formPolicyUrl, formPolicyRef, formPolicyDate, formPolicyNSUrl
- global formPolicyOrder
- global formSteTypes, formChWallTypes, formVmNames, formVmNameDom0
- global allCSMTypes, allVmStes, allVmChWs
-
- domDoc = parseXml( policyXml )
- if domDoc == None:
- return
-
- # Process the PolicyHeader
- domRoot = domDoc.documentElement
- domHeaders = domRoot.getElementsByTagName( 'PolicyHeader' )
- if len( domHeaders ) == 0:
- msg = ''
- msg = msg + '"<PolicyHeader>" tag is missing.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- pName = getPolicyName( domHeaders[0] )
- if pName == None:
- msg = ''
- msg = msg + 'Error processing the Policy header information.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- formPolicyName[1] = pName
- formPolicyUrl[1] = getUrl( domHeaders[0] )
- formPolicyRef[1] = getRef( domHeaders[0] )
- formPolicyDate[1] = getDate( domHeaders[0] )
- formPolicyNSUrl[1] = getNSUrl( domHeaders[0] )
-
- # Process the STEs
- pOrder = ''
- domStes = domRoot.getElementsByTagName( 'SimpleTypeEnforcement' )
- if len( domStes ) > 0:
- if domStes[0].hasAttribute( 'priority' ):
- if domStes[0].getAttribute( 'priority' ) != 'PrimaryPolicyComponent':
- msg = ''
- msg = msg + 'Error processing the "<SimpleTypeEnforcement>" tag.\n'
- msg = msg + 'The "priority" attribute value is not valid.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- pOrder = 'v_Ste'
-
- steTypes = getSteTypes( domStes[0], 1 )
- if steTypes == None:
- msg = ''
- msg = msg + 'Error processing the SimpleTypeEnforcement types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- formSteTypes[1] = steTypes
-
- # Process the ChineseWalls and Conflict Sets
- domChWalls = domRoot.getElementsByTagName( 'ChineseWall' )
- if len( domChWalls ) > 0:
- if domChWalls[0].hasAttribute( 'priority' ):
- if domChWalls[0].getAttribute( 'priority' ) != 'PrimaryPolicyComponent':
- msg = ''
- msg = msg + 'Error processing the "<ChineseWall>" tag.\n'
- msg = msg + 'The "priority" attribute value is not valid.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- if pOrder != '':
- msg = ''
- msg = msg + 'Error processing the "<ChineseWall>" tag.\n'
- msg = msg + 'The "priority" attribute has been previously specified.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- pOrder = 'v_ChWall'
-
- chwTypes = getChWTypes( domChWalls[0], 1 )
- if chwTypes == None:
- msg = ''
- msg = msg + 'Error processing the ChineseWall types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- formChWallTypes[1] = chwTypes
-
- csNodes = domChWalls[0].getElementsByTagName( 'ConflictSets' )
- if csNodes and (len( csNodes ) > 0):
- cNodes = csNodes[0].getElementsByTagName( 'Conflict' )
- if not cNodes or len( cNodes ) == 0:
- msg = ''
- msg = msg + 'Required "<Conflict>" tag missing.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- for cNode in cNodes:
- csName = cNode.getAttribute( 'name' )
- newCS( csName, 1 )
-
- csMemberList = getTypes( cNode )
- if csMemberList == None:
- msg = ''
- msg = msg + 'Error processing the Conflict Set members.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- # Verify the conflict set members are valid types
- ctSet = Set( formChWallTypes[1] )
- csSet = Set( csMemberList )
- if not csSet.issubset( ctSet ):
- msg = ''
- msg = msg + 'Error processing Conflict Set "' + csName + '".\n'
- msg = msg + 'Members of the conflict set are not valid '
- msg = msg + 'Chinese Wall types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
-
- allCSMTypes[csName][1] = csMemberList
-
- if pOrder != '':
- formPolicyOrder[1] = pOrder
- else:
- if (len( domStes ) > 0) or (len( domChWalls ) > 0):
- msg = ''
- msg = msg + 'The "priority" attribute has not been specified.\n'
- msg = msg + 'It must be specified on one of the access control types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- # Process the Labels
- domLabels = domRoot.getElementsByTagName( 'SecurityLabelTemplate' )
- if not domLabels or (len( domLabels ) == 0):
- msg = ''
- msg = msg + '<SecurityLabelTemplate> tag is missing.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
-
- # Process the VMs
- domSubjects = domLabels[0].getElementsByTagName( 'SubjectLabels' )
- if len( domSubjects ) > 0:
- formVmNameDom0[1] = domSubjects[0].getAttribute( 'bootstrap' )
- domNodes = domSubjects[0].getElementsByTagName( 'VirtualMachineLabel' )
- for domNode in domNodes:
- vmName = getName( domNode )
- if vmName == None:
- msg = ''
- msg = msg + 'Error processing the VirtualMachineLabel name.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- continue
-
- steTypes = getSteTypes( domNode )
- if steTypes == None:
- msg = ''
- msg = msg + 'Error processing the SimpleTypeEnforcement types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- chwTypes = getChWTypes( domNode )
- if chwTypes == None:
- msg = ''
- msg = msg + 'Error processing the ChineseWall types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- newVm( vmName, 1 )
- allVmStes[vmName][1] = steTypes
- allVmChWs[vmName][1] = chwTypes
-
- # Process the Resources
- domObjects = domLabels[0].getElementsByTagName( 'ObjectLabels' )
- if len( domObjects ) > 0:
- domNodes = domObjects[0].getElementsByTagName( 'ResourceLabel' )
- for domNode in domNodes:
- resName = getName( domNode )
- if resName == None:
- msg = ''
- msg = msg + 'Error processing the ResourceLabel name.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- continue
-
- steTypes = getSteTypes( domNode )
- if steTypes == None:
- msg = ''
- msg = msg + 'Error processing the SimpleTypeEnforcement types.\n'
- msg = msg + 'Please validate the Policy file used.'
- formatXmlError( msg )
- return
-
- newRes( resName, 1 )
- allResStes[resName][1] = steTypes
-
-def modFormTemplate( formTemplate, suffix ):
- formVar = [x for x in formTemplate]
-
- if formVar[2] != '':
- formVar[2] = formVar[2] + suffix
- if formVar[3] != '':
- formVar[3] = formVar[3] + suffix
- if (formVar[0] != 'button') and (formVar[4] != ''):
- formVar[4] = formVar[4] + suffix
-
- return formVar;
-
-def removeDups( curList ):
- newList = []
- curSet = Set( curList )
- for x in curSet:
- newList.append( x )
- newList.sort( )
-
- return newList
-
-def newCS( csName, addToList = 0 ):
- global formCSNames
- global templateCSDel, allCSDel
- global templateCSMTypes, templateCSMDel, templateCSMType, templateCSMAdd
- global allCSMTypes, allCSMDel, allCSMType, allCSMAdd
-
- csSuffix = '_' + csName
-
- # Make sure we have an actual name and check one of the 'all'
- # variables to be sure it hasn't been previously defined
- if (len( csName ) > 0) and (not allCSMTypes.has_key( csName )):
- allCSDel[csName] = modFormTemplate( templateCSDel, csSuffix )
- allCSMTypes[csName] = modFormTemplate( templateCSMTypes, csSuffix )
- allCSMDel[csName] = modFormTemplate( templateCSMDel, csSuffix )
- allCSMType[csName] = modFormTemplate( templateCSMType, csSuffix )
- allCSMAdd[csName] = modFormTemplate( templateCSMAdd, csSuffix )
- if addToList == 1:
- formCSNames[1].append( csName )
- formCSNames[1] = removeDups( formCSNames[1] )
-
-def newVm( vmName, addToList = 0 ):
- global formVmNames
- global templateVmDel, allVmDel, templateVmDom0, allVmDom0
- global templateVmChWs, templateVmChWDel, templateVmChW, templateVmChWAdd
- global allVmChWs, allVmChWDel, allVmChWType, allVmChWAdd
- global templateVmStes, templateVmSteDel, templateVmSte, templateVmSteAdd
- global allVmStes, allVmSteDel, allVmSteType, allVmSteAdd
-
- # Make sure we have an actual name and check one of the 'all'
- # variables to be sure it hasn't been previously defined
- if (len( vmName ) > 0) and (not allVmDom0.has_key( vmName )):
- vmSuffix = '_' + vmName
- allVmDom0[vmName] = modFormTemplate( templateVmDom0, vmSuffix )
- allVmDel[vmName] = modFormTemplate( templateVmDel, vmSuffix )
- allVmChWs[vmName] = modFormTemplate( templateVmChWs, vmSuffix )
- allVmChWDel[vmName] = modFormTemplate( templateVmChWDel, vmSuffix )
- allVmChW[vmName] = modFormTemplate( templateVmChW, vmSuffix )
- allVmChWAdd[vmName] = modFormTemplate( templateVmChWAdd, vmSuffix )
- allVmStes[vmName] = modFormTemplate( templateVmStes, vmSuffix )
- allVmSteDel[vmName] = modFormTemplate( templateVmSteDel, vmSuffix )
- allVmSte[vmName] = modFormTemplate( templateVmSte, vmSuffix )
- allVmSteAdd[vmName] = modFormTemplate( templateVmSteAdd, vmSuffix )
- if addToList == 1:
- formVmNames[1].append( vmName )
- formVmNames[1] = removeDups( formVmNames[1] )
-
-def newRes( resName, addToList = 0 ):
- global formResNames
- global templateResDel, allResDel
- global templateResStes, templateResSteDel, templateResSte, templateResSteAdd
- global allResStes, allResSteDel, allResSteType, allResSteAdd
-
- # Make sure we have an actual name and check one of the 'all'
- # variables to be sure it hasn't been previously defined
- if (len( resName ) > 0) and (not allResDel.has_key( resName )):
- resSuffix = '_' + resName
- allResDel[resName] = modFormTemplate( templateResDel, resSuffix )
- allResStes[resName] = modFormTemplate( templateResStes, resSuffix )
- allResSteDel[resName] = modFormTemplate( templateResSteDel, resSuffix )
- allResSte[resName] = modFormTemplate( templateResSte, resSuffix )
- allResSteAdd[resName] = modFormTemplate( templateResSteAdd, resSuffix )
- if addToList == 1:
- formResNames[1].append( resName )
- formResNames[1] = removeDups( formResNames[1] )
-
-def updateInfo( ):
- global formData, formPolicyName, formPolicyUrl, formPolicyRef, formPolicyDate, formPolicyNSUrl
- global formPolicyOrder
-
- if formData.has_key( formPolicyName[3] ):
- formPolicyName[1] = formData[formPolicyName[3]].value
- elif formData.has_key( formPolicyUpdate[3] ):
- formPolicyName[1] = ''
-
- if formData.has_key( formPolicyUrl[3] ):
- formPolicyUrl[1] = formData[formPolicyUrl[3]].value
- elif formData.has_key( formPolicyUpdate[3] ):
- formPolicyUrl[1] = ''
-
- if formData.has_key( formPolicyRef[3] ):
- formPolicyRef[1] = formData[formPolicyRef[3]].value
- elif formData.has_key( formPolicyUpdate[3] ):
- formPolicyRef[1] = ''
-
- if formData.has_key( formPolicyDate[3] ):
- formPolicyDate[1] = formData[formPolicyDate[3]].value
- elif formData.has_key( formPolicyUpdate[3] ):
- formPolicyDate[1] = ''
-
- if formData.has_key( formPolicyNSUrl[3] ):
- formPolicyNSUrl[1] = formData[formPolicyNSUrl[3]].value
- elif formData.has_key( formPolicyUpdate[3] ):
- formPolicyNSUrl[1] = ''
-
- if formData.has_key( formPolicyOrder[3] ):
- formPolicyOrder[1] = formData[formPolicyOrder[3]].value
-
-def addSteType( ):
- global formData, formSteType, formSteTypes
-
- if (formData.has_key( formDefaultButton[3] )) or (formData.has_key( formSteAdd[3] )):
- if formData.has_key( formSteType[3] ):
- type = formData[formSteType[3]].value
- type = type.strip( )
- if len( type ) > 0:
- formSteTypes[1].append( type )
- formSteTypes[1] = removeDups( formSteTypes[1] )
-
-
-def delSteType( ):
- global formData, formSteTypes
-
- if formData.has_key( formSteTypes[3] ):
- typeList = formData.getlist( formSteTypes[3] )
- for type in typeList:
- type = type.strip( )
- formSteTypes[1].remove( type )
-
-def addChWallType( ):
- global formData, formChWallType, formChWallTypes
-
- if (formData.has_key( formDefaultButton[3] )) or (formData.has_key( formChWallAdd[3] )):
- if formData.has_key( formChWallType[3] ):
- type = formData[formChWallType[3]].value
- type = type.strip( )
- if len( type ) > 0:
- formChWallTypes[1].append( type )
- formChWallTypes[1] = removeDups( formChWallTypes[1] )
-
-def delChWallType( ):
- global formData, formChWallTypes
-
- if formData.has_key( formChWallTypes[3] ):
- typeList = formData.getlist( formChWallTypes[3] )
- for type in typeList:
- type = type.strip( )
- formChWallTypes[1].remove( type )
-
-def addCS( ):
- global formData, formCSNames
-
- if (formData.has_key( formDefaultButton[3] )) or (formData.has_key( formCSAdd[3] )):
- if formData.has_key( formCSName[3] ):
- csName = formData[formCSName[3]].value
- csName = csName.strip( )
- newCS( csName, 1 )
-
-def delCS( csName ):
- global formData, formCSNames, allCSDel
- global allCSMTypes, allCSMDel, allCSMType, allCSMAdd
-
- csName = csName.strip( )
- formCSNames[1].remove( csName )
- del allCSDel[csName]
- del allCSMTypes[csName]
- del allCSMDel[csName]
- del allCSMType[csName]
- del allCSMAdd[csName]
-
-def addCSMember( csName ):
- global formData, allCSMType, allCSMTypes
-
- formVar = allCSMType[csName]
- if formData.has_key( formVar[3] ):
- csmList = formData.getlist( formVar[3] )
- formVar = allCSMTypes[csName]
- for csm in csmList:
- csm = csm.strip( )
- formVar[1].append( csm )
- formVar[1] = removeDups( formVar[1] )
-
-def delCSMember( csName ):
- global formData, allCSMTypes
-
- formVar = allCSMTypes[csName]
- if formData.has_key( formVar[3] ):
- csmList = formData.getlist( formVar[3] )
- for csm in csmList:
- csm = csm.strip( )
- formVar[1].remove( csm )
-
-def addVm( ):
- global formData, fromVmName, formVmNames, formVmNameDom0
-
- if (formData.has_key( formDefaultButton[3] )) or (formData.has_key( formVmAdd[3] )):
- if formData.has_key( formVmName[3] ):
- vmName = formData[formVmName[3]].value
- vmName = vmName.strip( )
- newVm( vmName, 1 )
- if formVmNameDom0[1] == '':
- formVmNameDom0[1] = vmName
-
-def delVm( vmName ):
- global formVmNames, formVmNameDom0
- global allVmDel, allVmDom0
- global allVmChWs, allVmChWDel, allVmChWType, allVmChWAdd
- global allVmStes, allVmSteDel, allVmSteType, allVmSteAdd
-
- vmName = vmName.strip( )
- formVmNames[1].remove( vmName )
- del allVmDom0[vmName]
- del allVmDel[vmName]
- del allVmChWs[vmName]
- del allVmChWDel[vmName]
- del allVmChW[vmName]
- del allVmChWAdd[vmName]
- del allVmStes[vmName]
- del allVmSteDel[vmName]
- del allVmSte[vmName]
- del allVmSteAdd[vmName]
-
- if formVmNameDom0[1] == vmName:
- if len( formVmNames[1] ) > 0:
- formVmNameDom0[1] = formVmNames[1][0]
- else:
- formVmNameDom0[1] = ''
-
-def makeVmDom0( vmName ):
- global formVmNameDom0
-
- vmName = vmName.strip( )
- formVmNameDom0[1] = vmName
-
-def addVmChW( vmName ):
- global formData, allVmChW, allVmChWs
-
- formVar = allVmChW[vmName]
- if formData.has_key( formVar[3] ):
- chwList = formData.getlist( formVar[3] )
- formVar = allVmChWs[vmName]
- for chw in chwList:
- chw = chw.strip( )
- formVar[1].append( chw )
- formVar[1] = removeDups( formVar[1] )
-
-def delVmChW( vmName ):
- global formData, allVmChWs
-
- formVar = allVmChWs[vmName]
- if formData.has_key( formVar[3] ):
- chwList = formData.getlist( formVar[3] )
- for chw in chwList:
- chw = chw.strip( )
- formVar[1].remove( chw )
-
-def addVmSte( vmName ):
- global formData, allVmSte, allVmStes
-
- formVar = allVmSte[vmName]
- if formData.has_key( formVar[3] ):
- steList = formData.getlist( formVar[3] )
- formVar = allVmStes[vmName]
- for ste in steList:
- ste = ste.strip( )
- formVar[1].append( ste )
- formVar[1] = removeDups( formVar[1] )
-
-def delVmSte( vmName ):
- global formData, allVmStes
-
- formVar = allVmStes[vmName]
- if formData.has_key( formVar[3] ):
- steList = formData.getlist( formVar[3] )
- for ste in steList:
- ste = ste.strip( )
- formVar[1].remove( ste )
-
-def addRes( ):
- global formData, fromResName, formResNames
-
- if (formData.has_key( formDefaultButton[3] )) or (formData.has_key( formResAdd[3] )):
- if formData.has_key( formResName[3] ):
- resName = formData[formResName[3]].value
- resName = resName.strip( )
- newRes( resName, 1 )
-
-def delRes( resName ):
- global formResNames
- global allResDel
- global allResStes, allResSteDel, allResSteType, allResSteAdd
-
- resName = resName.strip( )
- formResNames[1].remove( resName )
- del allResDel[resName]
- del allResStes[resName]
- del allResSteDel[resName]
- del allResSte[resName]
- del allResSteAdd[resName]
-
-def addResSte( vmName ):
- global formData, allResSte, allResStes
-
- formVar = allResSte[vmName]
- if formData.has_key( formVar[3] ):
- steList = formData.getlist( formVar[3] )
- formVar = allResStes[vmName]
- for ste in steList:
- ste = ste.strip( )
- formVar[1].append( ste )
- formVar[1] = removeDups( formVar[1] )
-
-def delResSte( vmName ):
- global formData, allResStes
-
- formVar = allResStes[vmName]
- if formData.has_key( formVar[3] ):
- steList = formData.getlist( formVar[3] )
- for ste in steList:
- ste = ste.strip( )
- formVar[1].remove( ste )
-
-def processRequest( ):
- global policyXml
- global formData, formPolicyUpdate
- global formSteAdd, formSteDel
- global formChWallAdd, formChWallDel
- global formCSAdd, allCSDel
- global formCSNames, allCSMAdd, allCSMDel
- global formVmAdd
- global formVmNames, allVmDel, allVmDom0
- global allVmChWAdd, allVmChWDel, allVmSteAdd, allVmSteDel
- global formResAdd
- global formResNames, allResDel
- global allResSteAdd, allResSteDel
-
- if policyXml != '':
- parsePolicyXml( )
-
- # Allow the updating of the header information whenever
- # an action is performed
- updateInfo( )
-
- # Allow the adding of types/sets/vms if the user has hit the
- # enter key when attempting to add a type/set/vm
- addSteType( )
- addChWallType( )
- addCS( )
- addVm( )
- addRes( )
-
- if formData.has_key( formSteDel[3] ):
- delSteType( )
-
- elif formData.has_key( formChWallDel[3] ):
- delChWallType( )
-
- else:
- for csName in formCSNames[1]:
- if formData.has_key( allCSDel[csName][3] ):
- delCS( csName )
- continue
-
- if formData.has_key( allCSMAdd[csName][3] ):
- addCSMember( csName )
-
- elif formData.has_key( allCSMDel[csName][3] ):
- delCSMember( csName )
-
- for vmName in formVmNames[1]:
- if formData.has_key( allVmDel[vmName][3] ):
- delVm( vmName )
- continue
-
- if formData.has_key( allVmDom0[vmName][3] ):
- makeVmDom0( vmName )
-
- if formData.has_key( allVmChWAdd[vmName][3] ):
- addVmChW( vmName )
-
- elif formData.has_key( allVmChWDel[vmName][3] ):
- delVmChW( vmName )
-
- elif formData.has_key( allVmSteAdd[vmName][3] ):
- addVmSte( vmName )
-
- elif formData.has_key( allVmSteDel[vmName][3] ):
- delVmSte( vmName )
-
- for resName in formResNames[1]:
- if formData.has_key( allResDel[resName][3] ):
- delRes( resName )
- continue
-
- if formData.has_key( allResSteAdd[resName][3] ):
- addResSte( resName )
-
- elif formData.has_key( allResSteDel[resName][3] ):
- delResSte( resName )
-
-def makeName( name, suffix='' ):
- rName = name
- if suffix != '':
- rName = rName + '_' + suffix
-
- return rName
-
-def makeNameAttr( name, suffix='' ):
- return 'name="' + makeName( name, suffix ) + '"'
-
-def makeValue( value, suffix='' ):
- rValue = value
-
- if isinstance( value, list ):
- rValue = '['
- for val in value:
- rValue = rValue + '\'' + val
- if suffix != '':
- rValue = rValue + '_' + suffix
- rValue = rValue + '\','
- rValue = rValue + ']'
-
- else:
- if suffix != '':
- rValue = rValue + '_' + suffix
-
- return rValue
-
-def makeValueAttr( value, suffix='' ):
- return 'value="' + makeValue( value, suffix ) + '"'
-
-def sendHtmlFormVar( formVar, attrs='', rb_select=0 ):
- nameAttr = ''
- valueAttr = ''
- htmlText = ''
-
- if formVar[0] == 'text':
- if formVar[3] != '':
- nameAttr = makeNameAttr( formVar[3] )
- valueAttr = makeValueAttr( formVar[1] )
-
- print '<INPUT type="text"', nameAttr, valueAttr, attrs, '>'
-
- elif formVar[0] == 'list':
- if formVar[3] != '':
- nameAttr = makeNameAttr( formVar[3] )
-
- print '<SELECT', nameAttr, attrs, '>'
- for option in formVar[1]:
- print '<OPTION>' + option + '</OPTION>'
- print '</SELECT>'
-
- elif formVar[0] == 'button':
- if formVar[3] != '':
- nameAttr = makeNameAttr( formVar[3] )
- if formVar[4] != '':
- valueAttr = makeValueAttr( formVar[4] )
-
- print '<INPUT type="submit"', nameAttr, valueAttr, attrs, '>'
-
- elif formVar[0] == 'radiobutton':
- if formVar[3] != '':
- nameAttr = makeNameAttr( formVar[3] )
- valueAttr = makeValueAttr( formVar[4][rb_select] )
- htmlText = formVar[5][rb_select]
- if formVar[4][rb_select] == formVar[1]:
- checked = 'checked'
- else:
- checked = ''
-
- print '<INPUT type="radio"', nameAttr, valueAttr, attrs, checked, '>', htmlText
-
- elif formVar[0] == 'radiobutton-all':
- if formVar[3] != '':
- nameAttr = makeNameAttr( formVar[3] )
- buttonVals = formVar[4]
- buttonTexts = formVar[5]
- for i, buttonVal in enumerate( buttonVals ):
- htmlText = ''
- addAttrs = ''
- checked = ''
-
- valueAttr = makeValueAttr( buttonVal )
- if formVar[5] != '':
- htmlText = formVar[5][i]
- if attrs != '':
- addAttrs = attrs[i]
- if buttonVal == formVar[1]:
- checked = 'checked'
-
- print '<INPUT type="radio"', nameAttr, valueAttr, addAttrs, checked, '>', htmlText, '<BR>'
-
- if ( formVar[2] != '' ) and ( rb_select == 0 ):
- nameAttr = makeNameAttr( formVar[2] )
- valueAttr = makeValueAttr( formVar[1] )
- print '<INPUT type="hidden"', nameAttr, valueAttr, '>'
-
-def sendHtmlHeaders( ):
- # HTML headers
- print 'Content-Type: text/html'
- print
-
-def sendPolicyHtml( ):
- global xmlError, xmlIncomplete, xmlMessages
- global formDefaultButton, formXmlGen
- global formVmNameDom0
-
- print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"'
- print ' "http://www.w3.org/TR/html4/loose.dtd">'
-
- print '<HTML>'
-
- sendHtmlHead( )
-
- print '<BODY>'
-
- # An input XML file was specified that had errors, output the
- # error information
- if xmlError == 1:
- print '<P>'
- print 'An error has been encountered while processing the input '
- print 'XML file:'
- print '<UL>'
- for msg in xmlMessages:
- print '<LI>'
- print msg
- print '</UL>'
- print '</BODY>'
- print '</HTML>'
- return
-
- # When attempting to generate the XML output, all required data was not
- # present, output the error information
- if xmlIncomplete == 1:
- print '<P>'
- print 'An error has been encountered while validating the data'
- print 'required for the output XML file:'
- print '<UL>'
- for msg in xmlMessages:
- print '<LI>'
- print msg
- print '</UL>'
- print '</BODY>'
- print '</HTML>'
- return
-
- print '<CENTER>'
- print '<FORM action="' + os.environ['SCRIPT_NAME'] + '" method="post">'
- print '<TABLE class="container">'
- print ' <COLGROUP>'
- print ' <COL width="100%">'
- print ' </COLGROUP>'
-
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formDefaultButton, 'class="hidden"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formXmlGen )
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
-
- # Policy header
- print ' <TR>'
- print ' <TD>'
- sendPHeaderHtml( )
- print ' </TD>'
- print ' </TR>'
-
- # Separator
- print ' <TR><TD><HR></TD></TR>'
-
- # Policy (types)
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="49%">'
- print ' <COL width="2%">'
- print ' <COL width="49%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD>'
- sendPSteHtml( )
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' <TD>'
- sendPChWallHtml( )
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
-
- # Separator
- print ' <TR>'
- print ' <TD>'
- print ' <HR>'
- print ' </TD>'
- print ' </TR>'
-
- # Policy Labels (vms)
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="100%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD>'
- sendPLSubHtml( )
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
-
- # Separator
- print ' <TR>'
- print ' <TD>'
- print ' <HR>'
- print ' </TD>'
- print ' </TR>'
-
- # Policy Labels (resources)
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="100%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD>'
- sendPLObjHtml( )
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
-
- print '</TABLE>'
-
- # Send some data that needs to be available across sessions
- sendHtmlFormVar( formVmNameDom0 )
-
- print '</FORM>'
- print '</CENTER>'
-
- print '</BODY>'
-
- print '</HTML>'
-
-def sendHtmlHead( ):
- global headTitle
-
- print '<HEAD>'
- print '<STYLE type="text/css">'
- print '<!--'
- print 'BODY {background-color: #EEEEFF;}'
- print 'TABLE.container {width: 90%; border: 1px solid black; border-collapse: seperate;}'
- print 'TABLE.full {width: 100%; border: 0px solid black; border-collapse: collapse; border-spacing: 3px;}'
- print 'TABLE.fullbox {width: 100%; border: 0px solid black; border-collapse: collapse; border-spacing: 3px;}'
- print 'THEAD {font-weight: bold; font-size: larger;}'
- print 'TD {border: 0px solid black; vertical-align: top;}'
- print 'TD.heading {border: 0px solid black; vertical-align: top; font-weight: bold; font-size: larger;}'
- print 'TD.subheading {border: 0px solid black; vertical-align: top; font-size: smaller;}'
- print 'TD.fullbox {border: 1px solid black; vertical-align: top;}'
- print 'SELECT.full {width: 100%;}'
- print 'INPUT.full {width: 100%;}'
- print 'INPUT.link {cursor: pointer; background-color: #EEEEFF; border: 0px; text-decoration: underline; color: blue;}'
- print 'INPUT.hidden {visibility: hidden; width: 1px; height: 1px;}'
- print ':link {color: blue;}'
- print ':visited {color: red;}'
- print '-->'
- print '</STYLE>'
- print '<TITLE>', headTitle, '</TITLE>'
- print '</HEAD>'
-
-def sendPHeaderHtml( ):
- global formPolicyName, formPolicyUrl, formPolicyRef, formPolicyDate, formPolicyNSUrl
- global formPolicyOrder, formPolicyUpdate
-
- # Policy header definition
- print '<TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="20%">'
- print ' <COL width="80%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD align="center" colspan="2" class="heading">Policy Information</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="right">Name:</TD>'
- print ' <TD align="left">'
- sendHtmlFormVar( formPolicyName, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="right">Url:</TD>'
- print ' <TD align="left">'
- sendHtmlFormVar( formPolicyUrl, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="right">Reference:</TD>'
- print ' <TD align="left">'
- sendHtmlFormVar( formPolicyRef, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="right">Date:</TD>'
- print ' <TD align="left">'
- sendHtmlFormVar( formPolicyDate, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="right">NameSpace URL:</TD>'
- print ' <TD align="left">'
- sendHtmlFormVar( formPolicyNSUrl, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="right">Primary Policy:</TD>'
- print ' <TD align="left">'
- sendHtmlFormVar( formPolicyOrder )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="center" colspan="2">'
- sendHtmlFormVar( formPolicyUpdate )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="center" colspan="2" class="subheading">'
- print ' (The Policy Information is updated whenever an action is performed'
- print ' or it can be updated separately using the "Update" button)'
- print ' </TD>'
- print ' </TR>'
- print '</TABLE>'
-
-def sendPSteHtml( ):
- global formSteTypes, formSteDel, formSteType, formSteAdd
-
- # Simple Type Enforcement...
- print '<TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="20%">'
- print ' <COL width="80%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD align="center" colspan="2" class="heading">Simple Type Enforcement Types</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- sendHtmlFormVar( formSteTypes, 'class="full" size="4" multiple' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formSteDel, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Delete the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- sendHtmlFormVar( formSteType, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formSteAdd, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Create a new type with the above name'
- print ' </TD>'
- print ' </TR>'
- print '</TABLE>'
-
-def sendPChWallHtml( ):
- global formChWallTypes, formChWallDel, formChWallType, formChWallAdd
- global formCSNames, formCSName, formCSAdd, allCSDel
- global allCSMTypes, allCSMDel, allCSMType, allCSMAdd
-
- # Chinese Wall...
- print '<TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="20%">'
- print ' <COL width="80%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD align="center" colspan="2" class="heading">Chinese Wall Types</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- sendHtmlFormVar( formChWallTypes, 'class="full" size="4" multiple' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formChWallDel, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Delete the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- sendHtmlFormVar( formChWallType, 'class="full"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formChWallAdd, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Create a new type with the above name'
- print ' </TD>'
- print ' </TR>'
-
- # Chinese Wall Conflict Sets...
- print ' <TR>'
- print ' <TD colspan="2">'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="20%">'
- print ' <COL width="30%">'
- print ' <COL width="50%">'
- print ' </COLGROUP>'
- print ' <THEAD>'
- print ' <TR>'
- print ' <TD align="center" colspan="3"><HR></TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD align="center" colspan="3">Chinese Wall Conflict Sets</TD>'
- print ' </TR>'
- print ' </THEAD>'
- print ' <TR>'
- print ' <TD colspan="3">'
- sendHtmlFormVar( formCSName, 'class="full"' )
- sendHtmlFormVar( formCSNames )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formCSAdd, 'class="full"' )
- print ' </TD>'
- print ' <TD colspan="2">'
- print ' Create a new conflict set with the above name'
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
- if len( formCSNames[1] ) > 0:
- print ' <TR>'
- print ' <TD colspan="2">'
- print ' &nbsp;'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- print ' <TABLE class="fullbox">'
- print ' <COLGROUP>'
- print ' <COL width="50%">'
- print ' <COL width="50%">'
- print ' </COLGROUP>'
- print ' <THEAD>'
- print ' <TR>'
- print ' <TD class="fullbox">Name</TD>'
- print ' <TD class="fullbox">Actions</TD>'
- print ' </TR>'
- print ' </THEAD>'
- for i, csName in enumerate( formCSNames[1] ):
- print ' <TR>'
- print ' <TD class="fullbox">' + csName + '</TD>'
- print ' <TD class="fullbox">'
- print ' <A href="#' + csName + '">Edit</A>'
- formVar = allCSDel[csName]
- sendHtmlFormVar( formVar, 'class="link"' )
- print ' </TD>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
- for csName in formCSNames[1]:
- print ' <TR><TD colspan="2"><HR></TD></TR>'
- print ' <TR>'
- print ' <TD align="center" colspan="2" class="heading"><A name="' + csName + '">Conflict Set: ' + csName + '</A></TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- formVar = allCSMTypes[csName];
- sendHtmlFormVar( formVar, 'class="full" size="4" multiple"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- formVar = allCSMDel[csName]
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Delete the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- ctSet = Set( formChWallTypes[1] )
- csSet = Set( allCSMTypes[csName][1] )
- formVar = allCSMType[csName]
- formVar[1] = []
- for chwallType in ctSet.difference( csSet ):
- formVar[1].append( chwallType )
- formVar[1].sort( )
- sendHtmlFormVar( formVar, 'class="full" size="2" multiple' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- formVar = allCSMAdd[csName]
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Add the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
-
- print '</TABLE>'
-
-def sendPLSubHtml( ):
- global formVmNames, formVmDel, formVmName, formVmAdd
- global allVmDel, allVmDom0
- global allVmChWs, allVmChWDel, allVmChW, allVmChWAdd
- global allVmStes, allVmSteDel, allVmSte, allVmSteAdd
- global formSteTypes, formChWallTypes
-
- print '<TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="100%">'
- print ' </COLGROUP>'
-
- # Virtual Machines...
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="10%">'
- print ' <COL width="40%">'
- print ' <COL width="50%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD class="heading" align="center" colspan="3">Virtual Machine Classes</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- sendHtmlFormVar( formVmName, 'class="full"' )
- sendHtmlFormVar( formVmNames )
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formVmAdd, 'class="full"' )
- print ' </TD>'
- print ' <TD colspan="2">'
- print ' Create a new VM class with the above name'
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
- if len( formVmNames[1] ) > 0:
- print ' <TR>'
- print ' <TD colspan="1">'
- print ' &nbsp;'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="fullbox">'
- print ' <COLGROUP>'
- print ' <COL width="10%">'
- print ' <COL width="40%">'
- print ' <COL width="50%">'
- print ' </COLGROUP>'
- print ' <THEAD>'
- print ' <TR>'
- print ' <TD class="fullbox">Dom 0?</TD>'
- print ' <TD class="fullbox">Name</TD>'
- print ' <TD class="fullbox">Actions</TD>'
- print ' </TR>'
- print ' </THEAD>'
- for i, vmName in enumerate( formVmNames[1] ):
- print ' <TR>'
- print ' <TD class="fullbox">'
- if formVmNameDom0[1] == vmName:
- print 'Yes'
- else:
- print '&nbsp;'
- print ' </TD>'
- print ' <TD class="fullbox">' + vmName + '</TD>'
- print ' <TD class="fullbox">'
- print ' <A href="#' + vmName + '">Edit</A>'
- formVar = allVmDel[vmName]
- sendHtmlFormVar( formVar, 'class="link"' )
- formVar = allVmDom0[vmName]
- sendHtmlFormVar( formVar, 'class="link"' )
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
- for vmName in formVmNames[1]:
- print ' <TR>'
- print ' <TD>'
- print ' <HR>'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="10%">'
- print ' <COL width="39%">'
- print ' <COL width="2%">'
- print ' <COL width="10%">'
- print ' <COL width="39%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD colspan="5" align="center" class="heading">'
- print ' <A name="' + vmName + '">Virtual Machine Class: ' + vmName + '</A>'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2" align="center">Simple Type Enforcement Types</TD>'
- print ' <TD>&nbsp;</TD>'
- print ' <TD colspan="2" align="center">Chinese Wall Types</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- formVar = allVmStes[vmName];
- sendHtmlFormVar( formVar, 'class="full" size="4" multiple"' )
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' <TD colspan="2">'
- formVar = allVmChWs[vmName];
- sendHtmlFormVar( formVar, 'class="full" size="4" multiple"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- formVar = allVmSteDel[vmName];
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Delete the type(s) selected above'
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' <TD>'
- formVar = allVmChWDel[vmName];
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Delete the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- stSet = Set( formSteTypes[1] )
- vmSet = Set( allVmStes[vmName][1] )
- formVar = allVmSte[vmName]
- formVar[1] = []
- for steType in stSet.difference( vmSet ):
- formVar[1].append( steType )
- formVar[1].sort( )
- sendHtmlFormVar( formVar, 'class="full" size="2" multiple"' )
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' <TD colspan="2">'
- ctSet = Set( formChWallTypes[1] )
- vmSet = Set( allVmChWs[vmName][1] )
- formVar = allVmChW[vmName]
- formVar[1] = []
- for chwallType in ctSet.difference( vmSet ):
- formVar[1].append( chwallType )
- formVar[1].sort( )
- sendHtmlFormVar( formVar, 'class="full" size="2" multiple"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- formVar = allVmSteAdd[vmName];
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Add the type(s) selected above'
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' <TD>'
- formVar = allVmChWAdd[vmName];
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Add the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
-
- print '</TABLE>'
-
-def sendPLObjHtml( ):
- global formResNames, formResDel, formResName, formResAdd
- global allResDel
- global allResStes, allResSteDel, allResSte, allResSteAdd
- global formSteTypes, formChWallTypes
-
- print '<TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="100%">'
- print ' </COLGROUP>'
-
- # Resources...
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="10%">'
- print ' <COL width="40%">'
- print ' <COL width="50%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD class="heading" align="center" colspan="3">Resource Classes</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- sendHtmlFormVar( formResName, 'class="full"' )
- sendHtmlFormVar( formResNames )
- print ' </TD>'
- print ' <TD>&nbsp;</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- sendHtmlFormVar( formResAdd, 'class="full"' )
- print ' </TD>'
- print ' <TD colspan="2">'
- print ' Create a new Resource class with the above name'
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
- if len( formResNames[1] ) > 0:
- print ' <TR>'
- print ' <TD colspan="1">'
- print ' &nbsp;'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="fullbox">'
- print ' <COLGROUP>'
- print ' <COL width="50%">'
- print ' <COL width="50%">'
- print ' </COLGROUP>'
- print ' <THEAD>'
- print ' <TR>'
- print ' <TD class="fullbox">Name</TD>'
- print ' <TD class="fullbox">Actions</TD>'
- print ' </TR>'
- print ' </THEAD>'
- for i, resName in enumerate( formResNames[1] ):
- print ' <TR>'
- print ' <TD class="fullbox">' + resName + '</TD>'
- print ' <TD class="fullbox">'
- print ' <A href="#' + resName + '">Edit</A>'
- formVar = allResDel[resName]
- sendHtmlFormVar( formVar, 'class="link"' )
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
- for resName in formResNames[1]:
- print ' <TR>'
- print ' <TD>'
- print ' <HR>'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- print ' <TABLE class="full">'
- print ' <COLGROUP>'
- print ' <COL width="10%">'
- print ' <COL width="90%">'
- print ' </COLGROUP>'
- print ' <TR>'
- print ' <TD colspan="2" align="center" class="heading">'
- print ' <A name="' + resName + '">Resource Class: ' + resName + '</A>'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2" align="center">Simple Type Enforcement Types</TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- formVar = allResStes[resName];
- sendHtmlFormVar( formVar, 'class="full" size="4" multiple"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- formVar = allResSteDel[resName];
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Delete the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD colspan="2">'
- stSet = Set( formSteTypes[1] )
- resSet = Set( allResStes[resName][1] )
- formVar = allResSte[resName]
- formVar[1] = []
- for steType in stSet.difference( resSet ):
- formVar[1].append( steType )
- formVar[1].sort( )
- sendHtmlFormVar( formVar, 'class="full" size="2" multiple"' )
- print ' </TD>'
- print ' </TR>'
- print ' <TR>'
- print ' <TD>'
- formVar = allResSteAdd[resName];
- sendHtmlFormVar( formVar, 'class="full"' )
- print ' </TD>'
- print ' <TD>'
- print ' Add the type(s) selected above'
- print ' </TD>'
- print ' </TR>'
- print ' </TABLE>'
- print ' </TD>'
- print ' </TR>'
-
- print '</TABLE>'
-
-def checkXmlData( ):
- global xmlIncomplete
- global formPolicyName, formPolicyOrder
- global formChWallTypes, formSteTypes, formCSNames
-
- # Validate the Policy Header requirements
- if ( len( formPolicyName[1] ) == 0 ):
- msg = ''
- msg = msg + 'The XML policy schema requires that the Policy '
- msg = msg + 'Information Name field have a value.'
- formatXmlGenError( msg )
-
- if formPolicyOrder[1] == 'v_ChWall':
- if len( formChWallTypes[1] ) == 0:
- msg = ''
- msg = msg + 'You have specified the primary policy to be '
- msg = msg + 'Chinese Wall but have not created any Chinese '
- msg = msg + 'Wall types. Please create some Chinese Wall '
- msg = msg + 'types or change the primary policy.'
- formatXmlGenError( msg )
-
- if formPolicyOrder[1] == 'v_Ste':
- if len( formSteTypes[1] ) == 0:
- msg = ''
- msg = msg + 'You have specified the primary policy to be '
- msg = msg + 'Simple Type Enforcement but have not created '
- msg = msg + 'any Simple Type Enforcement types. Please create '
- msg = msg + 'some Simple Type Enforcement types or change the '
- msg = msg + 'primary policy.'
- formatXmlGenError( msg )
-
-def sendXmlHeaders( ):
- # HTML headers
- print 'Content-Type: text/xml'
- print 'Content-Disposition: attachment; filename=security_policy.xml'
- print
-
-def sendPolicyXml( ):
- print '<?xml version="1.0"?>'
-
- print '<SecurityPolicyDefinition xmlns="http://www.ibm.com"'
- print ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
- print ' xsi:schemaLocation="http://www.ibm.com security_policy.xsd">'
-
- # Policy header
- sendPHeaderXml( )
-
- # Policy (types)
- sendPSteXml( )
- sendPChWallXml( )
-
- # Policy Labels (subjects and objects)
- print '<SecurityLabelTemplate>'
- sendPLSubXml( )
- sendPLObjXml( )
- print '</SecurityLabelTemplate>'
- print '</SecurityPolicyDefinition>'
-
-def sendPHeaderXml( ):
- global formPolicyName, formPolicyUrl, formPolicyRef, formPolicyDate, formPolicyNSUrl
-
- # Policy header definition
- print '<PolicyHeader>'
- print ' <PolicyName>' + formPolicyName[1] + '</PolicyName>'
- print ' <Version>1.0</Version>'
- if len( formPolicyUrl[1] ) > 0:
- print ' <PolicyUrl>' + formPolicyUrl[1] + '</PolicyUrl>'
- if len( formPolicyRef[1] ) > 0:
- print ' <Reference>' + formPolicyRef[1] + '</Reference>'
- if len( formPolicyDate[1] ) > 0:
- print ' <Date>' + formPolicyDate[1] + '</Date>'
- if len( formPolicyNSUrl[1] ) > 0:
- print ' <NameSpaceUrl>' + formPolicyNSUrl[1] + '</NameSpaceUrl>'
- print '</PolicyHeader>'
-
-def sendPSteXml( ):
- global formPolicyOrder, formSteTypes
-
- # Simple Type Enforcement...
- if len( formSteTypes[1] ) == 0:
- return
-
- if formPolicyOrder[1] == 'v_Ste':
- print '<SimpleTypeEnforcement priority="PrimaryPolicyComponent">'
- else:
- print '<SimpleTypeEnforcement>'
-
- print ' <SimpleTypeEnforcementTypes>'
- for steType in formSteTypes[1]:
- print ' <Type>' + steType + '</Type>'
- print ' </SimpleTypeEnforcementTypes>'
-
- print '</SimpleTypeEnforcement>'
-
-def sendPChWallXml( ):
- global formPolicyOrder, formChWallTypes
- global formCSNames, allCSMTypes
-
- # Chinese Wall...
- if len( formChWallTypes[1] ) == 0:
- return
-
- if formPolicyOrder[1] == 'v_ChWall':
- print '<ChineseWall priority="PrimaryPolicyComponent">'
- else:
- print '<ChineseWall>'
-
- print ' <ChineseWallTypes>'
- for chWallType in formChWallTypes[1]:
- print ' <Type>' + chWallType + '</Type>'
- print ' </ChineseWallTypes>'
-
- # Chinese Wall Conflict Sets (if any) ...
- if len( formCSNames[1] ) > 0:
- print ' <ConflictSets>'
- for cs in formCSNames[1]:
- formVar = allCSMTypes[cs]
- if len( formVar[1] ) == 0:
- continue
- print ' <Conflict name="' + cs + '">'
- for csm in formVar[1]:
- print ' <Type>' + csm + '</Type>'
- print ' </Conflict>'
- print ' </ConflictSets>'
-
- print '</ChineseWall>'
-
-def sendPLSubXml( ):
- global formVmNames, allVmChWs, allVmStes
-
- # Virtual machines...
- if len( formVmNames[1] ) == 0:
- return
-
- print ' <SubjectLabels bootstrap="' + formVmNameDom0[1] + '">'
- for vmName in formVmNames[1]:
- print ' <VirtualMachineLabel>'
- print ' <Name>' + vmName + '</Name>'
- formVar = allVmStes[vmName]
- if len( formVar[1] ) > 0:
- print ' <SimpleTypeEnforcementTypes>'
- for ste in formVar[1]:
- print ' <Type>' + ste + '</Type>'
- print ' </SimpleTypeEnforcementTypes>'
-
- formVar = allVmChWs[vmName]
- if len( formVar[1] ) > 0:
- print ' <ChineseWallTypes>'
- for chw in formVar[1]:
- print ' <Type>' + chw + '</Type>'
- print ' </ChineseWallTypes>'
-
- print ' </VirtualMachineLabel>'
-
- print ' </SubjectLabels>'
-
-def sendPLObjXml( ):
- global formResNames, allResStes
-
- # Resources...
- if len( formResNames[1] ) == 0:
- return
-
- print ' <ObjectLabels>'
- for resName in formResNames[1]:
- print ' <ResourceLabel>'
- print ' <Name>' + resName + '</Name>'
- formVar = allResStes[resName]
- if len( formVar[1] ) > 0:
- print ' <SimpleTypeEnforcementTypes>'
- for ste in formVar[1]:
- print ' <Type>' + ste + '</Type>'
- print ' </SimpleTypeEnforcementTypes>'
-
- print ' </ResourceLabel>'
-
- print ' </ObjectLabels>'
-
-
-# Set up initial HTML variables
-headTitle = 'Xen Policy Generation'
-
-# Form variables
-# The format of these variables is as follows:
-# [ p0, p1, p2, p3, p4, p5 ]
-# p0 = input type
-# p1 = the current value of the variable
-# p2 = the hidden input name attribute
-# p3 = the name attribute
-# p4 = the value attribute
-# p5 = text to associate with the tag
-formPolicyName = [ 'text',
- '',
- 'h_policyName',
- 'i_policyName',
- '',
- '',
- ]
-formPolicyUrl = [ 'text',
- '',
- 'h_policyUrl',
- 'i_policyUrl',
- '',
- '',
- ]
-formPolicyRef = [ 'text',
- '',
- 'h_policyRef',
- 'i_policyRef',
- '',
- '',
- ]
-formPolicyDate = [ 'text',
- getCurrentTime( ),
- 'h_policyDate',
- 'i_policyDate',
- '',
- '',
- ]
-formPolicyNSUrl = [ 'text',
- '',
- 'h_policyNSUrl',
- 'i_policyNSUrl',
- '',
- '',
- ]
-formPolicyOrder = [ 'radiobutton-all',
- 'v_ChWall',
- 'h_policyOrder',
- 'i_policyOrder',
- [ 'v_Ste', 'v_ChWall' ],
- [ 'Simple Type Enforcement', 'Chinese Wall' ],
- ]
-formPolicyUpdate = [ 'button',
- '',
- '',
- 'i_PolicyUpdate',
- 'Update',
- '',
- ]
-
-formSteTypes = [ 'list',
- [],
- 'h_steTypes',
- 'i_steTypes',
- '',
- '',
- ]
-formSteDel = [ 'button',
- '',
- '',
- 'i_steDel',
- 'Delete',
- '',
- ]
-formSteType = [ 'text',
- '',
- '',
- 'i_steType',
- '',
- '',
- ]
-formSteAdd = [ 'button',
- '',
- '',
- 'i_steAdd',
- 'New',
- '',
- ]
-
-formChWallTypes = [ 'list',
- [],
- 'h_chwallTypes',
- 'i_chwallTypes',
- '',
- '',
- ]
-formChWallDel = [ 'button',
- '',
- '',
- 'i_chwallDel',
- 'Delete',
- '',
- ]
-formChWallType = [ 'text',
- '',
- '',
- 'i_chwallType',
- '',
- '',
- ]
-formChWallAdd = [ 'button',
- '',
- '',
- 'i_chwallAdd',
- 'New',
- '',
- ]
-
-formCSNames = [ '',
- [],
- 'h_csNames',
- '',
- '',
- '',
- ]
-formCSName = [ 'text',
- '',
- '',
- 'i_csName',
- '',
- '',
- ]
-formCSAdd = [ 'button',
- '',
- '',
- 'i_csAdd',
- 'New',
- '',
- ]
-
-formXmlGen = [ 'button',
- '',
- '',
- 'i_xmlGen',
- 'Generate XML',
- '',
- ]
-
-formDefaultButton = [ 'button',
- '',
- '',
- 'i_defaultButton',
- '.',
- '',
- ]
-
-# This is a set of templates used for each conflict set
-# Each conflict set is initially assigned these templates,
-# then each form attribute value is changed to append
-# "_conflict-set-name" for uniqueness
-templateCSDel = [ 'button',
- '',
- '',
- 'i_csDel',
- 'Delete',
- '',
- ]
-allCSDel = {};
-
-templateCSMTypes = [ 'list',
- [],
- 'h_csmTypes',
- 'i_csmTypes',
- '',
- '',
- ]
-templateCSMDel = [ 'button',
- '',
- '',
- 'i_csmDel',
- 'Delete',
- '',
- ]
-templateCSMType = [ 'list',
- [],
- '',
- 'i_csmType',
- '',
- '',
- ]
-templateCSMAdd = [ 'button',
- '',
- '',
- 'i_csmAdd',
- 'Add',
- '',
- ]
-allCSMTypes = {};
-allCSMDel = {};
-allCSMType = {};
-allCSMAdd = {};
-
-formVmNames = [ '',
- [],
- 'h_vmNames',
- '',
- '',
- '',
- ]
-formVmDel = [ 'button',
- '',
- '',
- 'i_vmDel',
- 'Delete',
- '',
- ]
-formVmName = [ 'text',
- '',
- '',
- 'i_vmName',
- '',
- '',
- ]
-formVmAdd = [ 'button',
- '',
- '',
- 'i_vmAdd',
- 'New',
- '',
- ]
-
-formVmNameDom0 = [ '',
- '',
- 'h_vmDom0',
- '',
- '',
- '',
- ]
-
-# This is a set of templates used for each virtual machine
-# Each virtual machine is initially assigned these templates,
-# then each form attribute value is changed to append
-# "_virtual-machine-name" for uniqueness.
-templateVmDel = [ 'button',
- '',
- '',
- 'i_vmDel',
- 'Delete',
- '',
- ]
-templateVmDom0 = [ 'button',
- '',
- '',
- 'i_vmDom0',
- 'SetDom0',
- '',
- ]
-allVmDel = {};
-allVmDom0 = {};
-
-templateVmChWs = [ 'list',
- [],
- 'h_vmChWs',
- 'i_vmChWs',
- '',
- '',
- ]
-templateVmChWDel = [ 'button',
- '',
- '',
- 'i_vmChWDel',
- 'Delete',
- '',
- ]
-templateVmChW = [ 'list',
- [],
- '',
- 'i_vmChW',
- '',
- '',
- ]
-templateVmChWAdd = [ 'button',
- '',
- '',
- 'i_vmChWAdd',
- 'Add',
- '',
- ]
-allVmChWs = {};
-allVmChWDel = {};
-allVmChW = {};
-allVmChWAdd = {};
-
-templateVmStes = [ 'list',
- [],
- 'h_vmStes',
- 'i_vmStes',
- '',
- '',
- ]
-templateVmSteDel = [ 'button',
- '',
- '',
- 'i_vmSteDel',
- 'Delete',
- '',
- ]
-templateVmSte = [ 'list',
- [],
- '',
- 'i_vmSte',
- '',
- '',
- ]
-templateVmSteAdd = [ 'button',
- '',
- '',
- 'i_vmSteAdd',
- 'Add',
- '',
- ]
-allVmStes = {};
-allVmSteDel = {};
-allVmSte = {};
-allVmSteAdd = {};
-
-formResNames = [ '',
- [],
- 'h_resNames',
- '',
- '',
- '',
- ]
-formResDel = [ 'button',
- '',
- '',
- 'i_resDel',
- 'Delete',
- '',
- ]
-formResName = [ 'text',
- '',
- '',
- 'i_resName',
- '',
- '',
- ]
-formResAdd = [ 'button',
- '',
- '',
- 'i_resAdd',
- 'New',
- '',
- ]
-
-# This is a set of templates used for each resource
-# Each resource is initially assigned these templates,
-# then each form attribute value is changed to append
-# "_resource-name" for uniqueness.
-templateResDel = [ 'button',
- '',
- '',
- 'i_resDel',
- 'Delete',
- '',
- ]
-allResDel = {};
-
-templateResStes = [ 'list',
- [],
- 'h_resStes',
- 'i_resStes',
- '',
- '',
- ]
-templateResSteDel = [ 'button',
- '',
- '',
- 'i_resSteDel',
- 'Delete',
- '',
- ]
-templateResSte = [ 'list',
- [],
- '',
- 'i_resSte',
- '',
- '',
- ]
-templateResSteAdd = [ 'button',
- '',
- '',
- 'i_resSteAdd',
- 'Add',
- '',
- ]
-allResStes = {};
-allResSteDel = {};
-allResSte = {};
-allResSteAdd = {};
-
-# A list of all form variables used for saving info across requests
-formVariables = [ formPolicyName,
- formPolicyUrl,
- formPolicyRef,
- formPolicyDate,
- formPolicyNSUrl,
- formPolicyOrder,
- formSteTypes,
- formChWallTypes,
- formCSNames,
- formVmNames,
- formVmNameDom0,
- formResNames,
- ]
-
-policyXml = ''
-xmlError = 0
-xmlIncomplete = 0
-xmlMessages = []
-
-
-# Extract any form data
-formData = cgi.FieldStorage( )
-
-# Process the form
-getSavedData( )
-processRequest( )
-
-if formData.has_key( formXmlGen[3] ):
- # Generate and send the XML file
- checkXmlData( )
-
- if xmlIncomplete == 0:
- sendXmlHeaders( )
- sendPolicyXml( )
-
-if (not formData.has_key( formXmlGen[3] )) or (xmlIncomplete == 1 ):
- # Send HTML to continue processing the form
- sendHtmlHeaders( )
- sendPolicyHtml( )
diff --git a/tools/security/python/xensec_gen/index.html b/tools/security/python/xensec_gen/index.html
deleted file mode 100644
index 8c541e1dd2..0000000000
--- a/tools/security/python/xensec_gen/index.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!--
- The Initial Developer of the Original Code is International
- Business Machines Corporation. Portions created by IBM
- Corporation are Copyright (C) 2005, 2006 International Business
- Machines Corporation. All Rights Reserved.
- -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<HTML>
- <HEAD>
- <META name="author" content="Tom Lendacky">
- <META name="copyright" content="Copyright (C) 2005, 2006 International Business Machines Corporation. All rights reserved">
-
- <STYLE type="text/css">
- <!--
- BODY {background-color: #EEEEFF;}
- TABLE.xen {width: 100%; border: 0px solid black;}
- TD {border: 0px solid black;}
- TD.heading {border: 0px solid black; font-weight: bold; font-size: larger;}
- -->
- </STYLE>
- <TITLE>Xen Security Policy Tool</TITLE>
- </HEAD>
-
- <BODY>
- <H1>Xen Security Policy Generation Tool</H1>
-
- <CENTER>
- <FORM action="/cgi-bin/policy.cgi" method="post" enctype="multipart/form-data">
- <TABLE class="xen">
- <COLGROUP>
- <COL width="25%">
- <COL width="20%">
- <COL width="55%">
- </COLGROUP>
-
- <TR>
- <TD valign="top" class="heading">
- Security Policy
- </TD>
- <TD valign="top" colspan="2">
- To generate a new Xen Security Policy leave the
- <B>"Policy File"</B> entry field
- empty and click the "Create" button.<BR>
- To modify an existing Xen Security Policy enter the
- file name containing the policy in the
- <B>"Policy File"</B> entry field
- and click the "Create" button.<HR>
- </TD>
- </TR>
- <TR>
- <TD></TD>
- <TD>
- Policy File:
- </TD>
- <TD>
- <INPUT type="file" size="50" name="i_policy">
- </TD>
- </TR>
- <TR>
- <TD></TD>
- <TD valign="top">
- <INPUT type="submit" name="i_policyCreate" value="Create">
- </TD>
- <TD></TD>
- </TR>
- </TABLE>
- </FORM>
- </CENTER>
- </BODY>
-</HTML>
diff --git a/tools/security/python/xensec_gen/main.py b/tools/security/python/xensec_gen/main.py
deleted file mode 100644
index a2c1229c84..0000000000
--- a/tools/security/python/xensec_gen/main.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/python
-#
-# The Initial Developer of the Original Code is International
-# Business Machines Corporation. Portions created by IBM
-# Corporation are Copyright (C) 2005 International Business
-# Machines Corporation. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License,
-# or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-"""Xen security policy generation aid
-"""
-
-import os
-import pwd
-import grp
-import sys
-import getopt
-import BaseHTTPServer
-import CGIHTTPServer
-
-
-gHttpPort = 7777
-gHttpDir = '/var/lib/xensec_gen'
-gLogFile = '/var/log/xen/xensec_gen.log'
-gUser = 'nobody'
-gGroup = 'nobody'
-
-def usage( ):
- print >>sys.stderr, 'Usage: ' + sys.argv[0] + ' [OPTIONS]'
- print >>sys.stderr, ' OPTIONS:'
- print >>sys.stderr, ' -p, --httpport'
- print >>sys.stderr, ' The port on which the http server is to listen'
- print >>sys.stderr, ' (default: ' + str( gHttpPort ) + ')'
- print >>sys.stderr, ' -d, --httpdir'
- print >>sys.stderr, ' The directory where the http server is to serve pages from'
- print >>sys.stderr, ' (default: ' + gHttpDir + ')'
- print >>sys.stderr, ' -l, --logfile'
- print >>sys.stderr, ' The file in which to log messages generated by this command'
- print >>sys.stderr, ' (default: ' + gLogFile + ')'
- print >>sys.stderr, ' -u, --user'
- print >>sys.stderr, ' The user under which this command is to run. This parameter'
- print >>sys.stderr, ' is only used when invoked under the "root" user'
- print >>sys.stderr, ' (default: ' + gUser + ')'
- print >>sys.stderr, ' -g, --group'
- print >>sys.stderr, ' The group under which this command is to run. This parameter'
- print >>sys.stderr, ' is only used when invoked under the "root" user'
- print >>sys.stderr, ' (default: ' + gGroup + ')'
- print >>sys.stderr, ' -f'
- print >>sys.stderr, ' Run the command in the foreground. The logfile option will be'
- print >>sys.stderr, ' ignored and all output will be directed to stdout and stderr.'
- print >>sys.stderr, ' -h, --help'
- print >>sys.stderr, ' Display the command usage information'
-
-def runServer( aServerPort,
- aServerClass = BaseHTTPServer.HTTPServer,
- aHandlerClass = CGIHTTPServer.CGIHTTPRequestHandler ):
- serverAddress = ( '', aServerPort )
- httpd = aServerClass( serverAddress, aHandlerClass )
- httpd.serve_forever( )
-
-def daemonize( aHttpDir, aLogFile, aUser, aGroup, aFork = 'true' ):
- # Do some pre-daemon activities
- os.umask( 027 )
- if os.getuid( ) == 0:
- # If we are running as root, we will change that
- uid = pwd.getpwnam( aUser )[2]
- gid = grp.getgrnam( aGroup )[2]
-
- if aFork == 'true':
- # Change the owner of the log file to the user/group
- # under which the daemon is to run
- flog = open( aLogFile, 'a' )
- flog.close( )
- os.chown( aLogFile, uid, gid )
-
- # Change the uid/gid of the process
- os.setgid( gid )
- os.setuid( uid )
-
- # Change to the HTTP directory
- os.chdir( aHttpDir )
-
- if aFork == 'true':
- # Do first fork
- try:
- pid = os.fork( )
- if pid:
- # Parent process
- return pid
-
- except OSError, e:
- raise Exception, e
-
- # First child process, create a new session
- os.setsid( )
-
- # Do second fork
- try:
- pid = os.fork( )
- if pid:
- # Parent process
- os._exit( 0 )
-
- except OSError, e:
- raise Exception, e
-
- # Reset stdin/stdout/stderr
- fin = open( '/dev/null', 'r' )
- flog = open( aLogFile, 'a' )
- os.dup2( fin.fileno( ), sys.stdin.fileno( ) )
- os.dup2( flog.fileno( ), sys.stdout.fileno( ) )
- os.dup2( flog.fileno( ), sys.stderr.fileno( ) )
-
-def main( ):
- httpPort = gHttpPort
- httpDir = gHttpDir
- logFile = gLogFile
- user = gUser
- group = gGroup
- doFork = 'true'
-
- shortOpts = 'd:p:l:u:g:fh'
- longOpts = [ 'httpdir=', 'httpport=', 'logfile=', 'user=', 'group=', 'help' ]
- try:
- opts, args = getopt.getopt( sys.argv[1:], shortOpts, longOpts )
-
- except getopt.GetoptError, e:
- print >>sys.stderr, e
- usage( )
- sys.exit( )
-
- if len( args ) != 0:
- print >>sys.stderr, 'Error: command arguments are not supported'
- usage( )
- sys.exit( )
-
- for opt, opt_value in opts:
- if opt in ( '-h', '--help' ):
- usage( )
- sys.exit( )
-
- if opt in ( '-d', '--httpdir' ):
- httpDir = opt_value
-
- if opt in ( '-p', '--httpport' ):
- try:
- httpPort = int( opt_value )
- except:
- print >>sys.stderr, 'Error: HTTP port is not valid'
- usage( )
- sys.exit( )
-
- if opt in ( '-l', '--logfile' ):
- logFile = opt_value
-
- if opt in ( '-u', '--user' ):
- user = opt_value
-
- if opt in ( '-g', '--group' ):
- group = opt_value
-
- if opt in ( '-f' ):
- doFork = 'false'
-
- pid = daemonize( httpDir, logFile, user, group, doFork )
- if pid > 0:
- sys.exit( )
-
- runServer( httpPort )
-
-if __name__ == '__main__':
- main( )
diff --git a/tools/security/python/xensec_tools/acm_getlabel b/tools/security/python/xensec_tools/acm_getlabel
deleted file mode 100644
index 8d5fe22461..0000000000
--- a/tools/security/python/xensec_tools/acm_getlabel
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; -*-
-import sys
-import traceback
-import getopt
-
-from xen.util.security import ACMError, err, get_ssid
-
-# getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
-# getopt.getopt if gnu_getopt is not available. This will mean that options
-# may only be specified before positional arguments.
-if not hasattr(getopt, 'gnu_getopt'):
- getopt.gnu_getopt = getopt.getopt
-
-def usage():
- print "Usage: acm_getlabel -i domainid"
- print " Test program illustrating the retrieval of"
- print " label information (for domains) from Xen."
- print " Argument is one paramter describing the domain"
- print " for which the label is retrieved."
- print "\t -i domain_id or --domid=domain_id"
- print " Return value:"
- print "\t none -- Error (e.g., unknown ssidref, label, or domain id)"
- print "\t (labelname, policyname, ssidref)"
- err("Usage")
-
-try:
- domid = None
- (options, params) = getopt.gnu_getopt(sys.argv[1:], ':i:', ['domid='])
- for (k, v) in options:
- if k in ['-i', '--domid']:
- if not domid:
- domid = v
- else:
- usage()
- if not domid:
- usage()
-
- print get_ssid(domid)
-
-except ACMError:
- pass
-except:
- traceback.print_exc(limit=1)
diff --git a/tools/security/readme.txt b/tools/security/readme.txt
deleted file mode 100644
index 991359a53a..0000000000
--- a/tools/security/readme.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-
-##
-# readme.txt <description to the sHype/Xen access control architecture>
-#
-# Author:
-# Reiner Sailer 08/30/2006 <sailer@watson.ibm.com>
-#
-#
-# This file is a toc for information regarding
-# the access control policy and tools in Xen.
-##
-
-1. Xen User Guide
-
- describes how to configure, install, and deploy the sHype Access
- Control Module in Xen. See chapter "sHype/Xen Access Control".
-
-2. 'xm' man page
-
- describes the commands related to Xen management, including the
- commands to manage security policies and labels. Read the access
- control subcommand section of the xm manual first.
-
-3. policy.txt
-
- describes examples for access control policies in Xen. First read
- the policy description in the Xen User Guide.
-
-
-4. policytools.txt
-
- describes the available tools for creating and managing security
- policies in Xen.
diff --git a/tools/security/secpol_tool.c b/tools/security/secpol_tool.c
deleted file mode 100644
index 792739e22d..0000000000
--- a/tools/security/secpol_tool.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/****************************************************************
- * secpol_tool.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Authors:
- * Reiner Sailer <sailer@watson.ibm.com>
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype policy management tool. This code runs in a domain and
- * manages the Xen security policy by interacting with the
- * Xen access control module via the privcmd device,
- * which is translated into a acm_op hypercall into Xen.
- *
- * indent -i4 -kr -nut
- */
-
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <stdint.h>
-#include <xen/xsm/acm.h>
-#include <xen/xsm/acm_ops.h>
-
-#include <xenctrl.h>
-
-#define PERROR(_m, _a...) \
-fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
- errno, strerror(errno))
-
-void usage(char *progname)
-{
- printf("Usage: %s ACTION\n"
- "ACTION is one of:\n"
- "\t getpolicy\n"
- "\t dumpstats\n"
- "\t loadpolicy <binary policy file>\n"
- "\t dumppolicy <binary policy file> [Dom-0 ssidref]\n",
- progname);
- exit(-1);
-}
-
-/*************************** DUMPS *******************************/
-
-void acm_dump_chinesewall_buffer(void *buf, int buflen, uint16_t chwall_ref)
-{
-
- struct acm_chwall_policy_buffer *cwbuf =
- (struct acm_chwall_policy_buffer *) buf;
- domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
- int i, j;
-
-
- if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) {
- printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
- return;
- }
- printf("\n\nChinese Wall policy:\n");
- printf("====================\n");
- printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
- printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
- printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
- printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
- printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
- printf("Conflicts Off = %x.\n",
- ntohl(cwbuf->chwall_conflict_sets_offset));
- printf("Runing T. Off = %x.\n",
- ntohl(cwbuf->chwall_running_types_offset));
- printf("C. Agg. Off = %x.\n",
- ntohl(cwbuf->chwall_conflict_aggregate_offset));
- printf("\nSSID To CHWALL-Type matrix:\n");
-
- ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
- for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++) {
- printf("\n ssidref%2x: ", i);
- for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
- printf("%02x ",
- ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
- if (i == chwall_ref)
- printf(" <-- Domain-0");
- }
- printf("\n\nConfict Sets:\n");
- conflicts =
- (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
- for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++) {
- printf("\n c-set%2x: ", i);
- for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
- printf("%02x ",
- ntohs(conflicts
- [i * ntohl(cwbuf->chwall_max_types) + j]));
- }
- printf("\n");
-
- printf("\nRunning\nTypes: ");
- if (ntohl(cwbuf->chwall_running_types_offset)) {
- running_types =
- (domaintype_t *) (buf +
- ntohl(cwbuf->chwall_running_types_offset));
- for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++) {
- printf("%02x ", ntohs(running_types[i]));
- }
- printf("\n");
- } else {
- printf("Not Reported!\n");
- }
- printf("\nConflict\nAggregate Set: ");
- if (ntohl(cwbuf->chwall_conflict_aggregate_offset)) {
- conflict_aggregate =
- (domaintype_t *) (buf +
- ntohl(cwbuf->
- chwall_conflict_aggregate_offset));
- for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++) {
- printf("%02x ", ntohs(conflict_aggregate[i]));
- }
- printf("\n\n");
- } else {
- printf("Not Reported!\n");
- }
-}
-
-void acm_dump_ste_buffer(void *buf, int buflen, uint16_t ste_ref)
-{
-
- struct acm_ste_policy_buffer *stebuf =
- (struct acm_ste_policy_buffer *) buf;
- domaintype_t *ssids;
- int i, j;
-
-
- if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
- printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
- return;
- }
- printf("\nSimple Type Enforcement policy:\n");
- printf("===============================\n");
- printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
- printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
- printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
- printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
- printf("\nSSID To STE-Type matrix:\n");
-
- ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
- for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++) {
- printf("\n ssidref%2x: ", i);
- for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
- printf("%02x ",
- ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
- if (i == ste_ref)
- printf(" <-- Domain-0");
- }
- printf("\n\n");
-}
-
-void acm_dump_policy_buffer(void *buf, int buflen,
- uint16_t chwall_ref, uint16_t ste_ref)
-{
- struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
- char *policy_reference_name =
- (buf + ntohl(pol->policy_reference_offset) +
- sizeof(struct acm_policy_reference_buffer));
- printf("\nPolicy dump:\n");
- printf("============\n");
- printf("POLICY REFERENCE = %s.\n", policy_reference_name);
- printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
- printf("XML Vers. = %d.%d\n",
- ntohl(pol->xml_pol_version.major),
- ntohl(pol->xml_pol_version.minor));
- printf("Magic = %x.\n", ntohl(pol->magic));
- printf("Len = %x.\n", ntohl(pol->len));
- printf("Primary = %s (c=%x, off=%x).\n",
- ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
- ntohl(pol->primary_policy_code),
- ntohl(pol->primary_buffer_offset));
- printf("Secondary = %s (c=%x, off=%x).\n",
- ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
- ntohl(pol->secondary_policy_code),
- ntohl(pol->secondary_buffer_offset));
- switch (ntohl(pol->primary_policy_code)) {
- case ACM_CHINESE_WALL_POLICY:
- acm_dump_chinesewall_buffer(buf + ntohl(pol->primary_buffer_offset),
- ntohl(pol->len) -
- ntohl(pol->primary_buffer_offset),
- chwall_ref);
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
- ntohl(pol->len) -
- ntohl(pol->primary_buffer_offset),
- ste_ref);
- break;
-
- case ACM_NULL_POLICY:
- printf("Primary policy is NULL Policy (n/a).\n");
- break;
-
- default:
- printf("UNKNOWN POLICY!\n");
- }
-
- switch (ntohl(pol->secondary_policy_code)) {
- case ACM_CHINESE_WALL_POLICY:
- acm_dump_chinesewall_buffer(buf + ntohl(pol->secondary_buffer_offset),
- ntohl(pol->len) -
- ntohl(pol->secondary_buffer_offset),
- chwall_ref);
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
- ntohl(pol->len) -
- ntohl(pol->secondary_buffer_offset),
- ste_ref);
- break;
-
- case ACM_NULL_POLICY:
- printf("Secondary policy is NULL Policy (n/a).\n");
- break;
-
- default:
- printf("UNKNOWN POLICY!\n");
- }
-}
-
-/************************** get dom0 ssidref *****************************/
-int acm_get_ssidref(xc_interface *xc_handle, int domid, uint16_t *chwall_ref,
- uint16_t *ste_ref)
-{
- int ret;
- DECLARE_HYPERCALL_BUFFER(struct acm_ssid_buffer, ssid);
- size_t ssid_buffer_size = 4096;
- struct acm_getssid getssid;
- ssid = xc_hypercall_buffer_alloc(xc_handle, ssid, ssid_buffer_size);
- if ( ssid == NULL )
- return 1;
- set_xen_guest_handle(getssid.ssidbuf, ssid);
- getssid.ssidbuf_size = ssid_buffer_size;
- getssid.get_ssid_by = ACM_GETBY_domainid;
- getssid.id.domainid = domid;
- ret = xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid));
- if (ret == 0) {
- *chwall_ref = ssid->ssidref & 0xffff;
- *ste_ref = ssid->ssidref >> 16;
- }
- xc_hypercall_buffer_free(xc_handle, ssid);
- return ret;
-}
-
-/******************************* get policy ******************************/
-
-int acm_domain_getpolicy(xc_interface *xc_handle)
-{
- DECLARE_HYPERCALL_BUFFER(uint8_t, pull_buffer);
- size_t pull_cache_size = 8192;
- struct acm_getpolicy getpolicy;
- int ret;
- uint16_t chwall_ref, ste_ref;
-
- pull_buffer = xc_hypercall_buffer_alloc(xc_handle, pull_buffer, pull_cache_size);
- if ( pull_buffer == NULL )
- return -1;
-
- memset(pull_buffer, 0x00, pull_cache_size);
- set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
- getpolicy.pullcache_size = pull_cache_size;
- ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
- if (ret >= 0) {
- ret = acm_get_ssidref(xc_handle, 0, &chwall_ref, &ste_ref);
- }
-
- if (ret < 0) {
- printf("ACM operation failed: errno=%d\n", errno);
- if (errno == EACCES)
- fprintf(stderr, "ACM operation failed -- need to"
- " rebuild the user-space tool set?\n");
- }
-
- /* dump policy */
- acm_dump_policy_buffer(pull_buffer, pull_cache_size,
- chwall_ref, ste_ref);
-
- xc_hypercall_buffer_free(xc_handle, pull_buffer);
-
- return ret;
-}
-
-/************************ dump binary policy ******************************/
-
-static int load_file(const char *filename,
- uint8_t **buffer, off_t *len,
- xc_interface *xc_handle,
- xc_hypercall_buffer_t *hcall)
-{
- struct stat mystat;
- int ret = 0;
- int fd;
- DECLARE_HYPERCALL_BUFFER_ARGUMENT(hcall);
-
- if ((ret = stat(filename, &mystat)) != 0) {
- printf("File %s not found.\n", filename);
- ret = errno;
- goto out;
- }
-
- *len = mystat.st_size;
-
- if ( hcall == NULL ) {
- if ((*buffer = malloc(*len)) == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- } else {
- if ((*buffer = xc_hypercall_buffer_alloc(xc_handle, hcall, *len)) == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- }
-
- if ((fd = open(filename, O_RDONLY)) <= 0) {
- ret = -ENOENT;
- printf("File %s not found.\n", filename);
- goto free_out;
- }
-
- if (*len == read(fd, *buffer, *len))
- return 0;
-
-free_out:
- if ( hcall == NULL )
- free(*buffer);
- else
- xc_hypercall_buffer_free(xc_handle, hcall);
- *buffer = NULL;
- *len = 0;
-out:
- return ret;
-}
-
-static int acm_domain_dumppolicy(const char *filename, uint32_t ssidref)
-{
- uint8_t *buffer = NULL;
- off_t len;
- int ret = 0;
- uint16_t chwall_ssidref, ste_ssidref;
-
- chwall_ssidref = (ssidref ) & 0xffff;
- ste_ssidref = (ssidref >> 16) & 0xffff;
-
- if ((ret = load_file(filename, &buffer, &len, NULL, NULL)) == 0) {
- acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
- free(buffer);
- }
-
- return ret;
-}
-
-/************************ load binary policy ******************************/
-
-int acm_domain_loadpolicy(xc_interface *xc_handle, const char *filename)
-{
- int ret;
- off_t len;
- DECLARE_HYPERCALL_BUFFER(uint8_t, buffer);
- uint16_t chwall_ssidref, ste_ssidref;
- struct acm_setpolicy setpolicy;
-
- ret = load_file(filename, &buffer, &len, xc_handle, HYPERCALL_BUFFER(buffer));
- if (ret != 0)
- goto out;
-
- ret = acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref);
- if (ret < 0)
- goto free_out;
-
- /* dump it and then push it down into xen/acm */
- acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
- set_xen_guest_handle(setpolicy.pushcache, buffer);
- setpolicy.pushcache_size = len;
- ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy));
-
- if (ret) {
- printf("ERROR setting policy.\n");
- } else {
- printf("Successfully changed policy.\n");
- }
-
- free_out:
- xc_hypercall_buffer_free(xc_handle, buffer);
- out:
- return ret;
-}
-
-/************************ dump hook statistics ******************************/
-void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
-{
- printf("STE-Policy Security Hook Statistics:\n");
- printf("ste: event_channel eval_count = %d\n",
- ntohl(ste_stats->ec_eval_count));
- printf("ste: event_channel denied_count = %d\n",
- ntohl(ste_stats->ec_denied_count));
- printf("ste: event_channel cache_hit_count = %d\n",
- ntohl(ste_stats->ec_cachehit_count));
- printf("ste:\n");
- printf("ste: grant_table eval_count = %d\n",
- ntohl(ste_stats->gt_eval_count));
- printf("ste: grant_table denied_count = %d\n",
- ntohl(ste_stats->gt_denied_count));
- printf("ste: grant_table cache_hit_count = %d\n",
- ntohl(ste_stats->gt_cachehit_count));
-}
-
-int acm_domain_dumpstats(xc_interface *xc_handle)
-{
- DECLARE_HYPERCALL_BUFFER(uint8_t, stats_buffer);
- size_t pull_stats_size = 8192;
- struct acm_dumpstats dumpstats;
- int ret;
- struct acm_stats_buffer *stats;
-
- stats_buffer = xc_hypercall_buffer_alloc(xc_handle, stats_buffer, pull_stats_size);
- if ( stats_buffer == NULL )
- return -1;
-
- memset(stats_buffer, 0x00, pull_stats_size);
- set_xen_guest_handle(dumpstats.pullcache, stats_buffer);
- dumpstats.pullcache_size = pull_stats_size;
- ret = xc_acm_op(xc_handle, ACMOP_dumpstats, &dumpstats, sizeof(dumpstats));
-
- if (ret < 0) {
- printf
- ("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
- xc_hypercall_buffer_free(xc_handle, stats_buffer);
- return ret;
- }
- stats = (struct acm_stats_buffer *) stats_buffer;
-
- printf("\nPolicy dump:\n");
- printf("============\n");
- printf("Magic = %x.\n", ntohl(stats->magic));
- printf("Len = %x.\n", ntohl(stats->len));
-
- switch (ntohl(stats->primary_policy_code)) {
- case ACM_NULL_POLICY:
- printf("NULL Policy: No statistics apply.\n");
- break;
-
- case ACM_CHINESE_WALL_POLICY:
- printf("Chinese Wall Policy: No statistics apply.\n");
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
- ntohl(stats->
- primary_stats_offset)));
- break;
-
- default:
- printf("UNKNOWN PRIMARY POLICY ERROR!\n");
- }
-
- switch (ntohl(stats->secondary_policy_code)) {
- case ACM_NULL_POLICY:
- printf("NULL Policy: No statistics apply.\n");
- break;
-
- case ACM_CHINESE_WALL_POLICY:
- printf("Chinese Wall Policy: No statistics apply.\n");
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
- ntohl(stats->
- secondary_stats_offset)));
- break;
-
- default:
- printf("UNKNOWN SECONDARY POLICY ERROR!\n");
- }
- xc_hypercall_buffer_free(xc_handle, stats_buffer);
- return ret;
-}
-
-/***************************** main **************************************/
-
-int main(int argc, char **argv)
-{
-
- xc_interface *xc_handle;
- int ret = 0;
-
- if (argc < 2)
- usage(argv[0]);
-
-
- if (!strcmp(argv[1], "getpolicy")) {
- if (argc != 2)
- usage(argv[0]);
-
- if ((xc_handle = xc_interface_open(0, 0, 0)) == 0) {
- printf("ERROR: Could not open xen privcmd device!\n");
- exit(-1);
- }
-
- ret = acm_domain_getpolicy(xc_handle);
-
- xc_interface_close(xc_handle);
- } else if (!strcmp(argv[1], "loadpolicy")) {
- if (argc != 3)
- usage(argv[0]);
-
- if ((xc_handle = xc_interface_open(0, 0, 0)) == 0) {
- printf("ERROR: Could not open xen privcmd device!\n");
- exit(-1);
- }
-
- ret = acm_domain_loadpolicy(xc_handle, argv[2]);
-
- xc_interface_close(xc_handle);
- } else if (!strcmp(argv[1], "dumpstats")) {
- if (argc != 2)
- usage(argv[0]);
-
- if ((xc_handle = xc_interface_open(0, 0, 0)) == 0) {
- printf("ERROR: Could not open xen privcmd device!\n");
- exit(-1);
- }
-
- ret = acm_domain_dumpstats(xc_handle);
-
- xc_interface_close(xc_handle);
- } else if (!strcmp(argv[1], "dumppolicy")) {
- uint32_t ssidref = 0xffffffff;
- if (argc < 3 || argc > 4)
- usage(argv[0]);
- if (argc == 4) {
- if (!sscanf(argv[3], "%i", &ssidref)) {
- printf("Error: Could not parse ssidref.\n");
- exit(-1);
- }
- }
- ret = acm_domain_dumppolicy(argv[2], ssidref);
- } else
- usage(argv[0]);
-
- return ret;
-}
diff --git a/tools/security/xensec_ezpolicy b/tools/security/xensec_ezpolicy
deleted file mode 100644
index 550196f774..0000000000
--- a/tools/security/xensec_ezpolicy
+++ /dev/null
@@ -1,1636 +0,0 @@
-#!/usr/bin/env python
-#===========================================================================
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2006 International Business Machines Corp.
-# Author: Reiner Sailer
-#============================================================================
-# use 'yum install wxPython' to get wx or download from www.wxpython.org
-import sys, time, string
-import wx
-import wx.lib.buttons as buttons
-"""
-This program creates a default policy based on names of organizations and departments.
-The resulting policy can be refined using the policy generation tool (xensec_gen).
-"""
-
-helpprovider = wx.SimpleHelpProvider()
-wx.HelpProvider_Set(helpprovider)
-
-ID_CS_START=1000
-
-realm_bmp = None
-workload_bmp = None
-conflict_bmp = None
-realm_icon = None
-workload_icon = None
-
-ACM_LABEL_UNLABELED = '__UNLABELED__'
-
-class orgTreeCtrl(wx.TreeCtrl):
-
- event = None
-
- def __init__(self, parent, id, pos, size, style, validator, name):
- wx.TreeCtrl.__init__(self, parent, id, pos, size, style,
- validator, name)
- self.parent = parent
- orgs_root = self.AddRoot(text="Organization / Department")
- self.SetItemBackgroundColour(orgs_root, wx.LIGHT_GREY)
-
-
- def LabelExists(self, label, item):
- for i in iterchildren(self.GetItemParent(item)):
- if (self.GetItemText(i) == label) and (i != item):
- return True
- return False
-
-
- def _OrgEdt(self, event):
- item = self.event.GetItem()
- self.OrgEdt(item)
-
-
- def OrgEdt(self, item):
- oldlabel= self.GetItemText(item)
- #get new name
- dlg = wx.TextEntryDialog(self, "Please enter org/dept name:",
- "Naming a Workload",
- style=wx.CANCEL | wx.OK | wx.CENTRE | wx.TE_NOHIDESEL)
- dlg.SetValue(oldlabel)
- ret = dlg.ShowModal()
- newlabel = dlg.GetValue()
- dlg.Destroy()
- if (ret == wx.ID_CANCEL) or (newlabel == ''):
- return False
-
- #now check if the new name is permissible
- if self.LabelExists(newlabel, item):
- dlg = wx.MessageDialog(self, 'Item with name ' + newlabel + ' already exists!',
- 'Rename', style=wx.OK)
- dlg.ShowModal()
- dlg.Destroy()
- return False
-
- #all checkspassed, change item and adapt runtime exclusion rules
- self.SetItemText(item, newlabel)
- app.win.LabelReplaceInConflictsets(item, oldlabel, newlabel)
- return True
-
-
- def _OrgRAdd(self, event):
- self.OrgRAdd()
-
-
- def OrgRAdd(self):
- new = self.AppendItem(self.GetRootItem(), text="")
- self.SetItemBold(new, True)
- self.SetItemImage(new, realm_icon, wx.TreeItemIcon_Normal)
- self.EnsureVisible(new)
- if not self.OrgEdt(new):
- self.Delete(new)
-
-
- def _OrgWAdd(self, event):
- item = self.event.GetItem()
- self.OrgWAdd(item)
-
-
- def OrgWAdd(self, item):
- new = self.AppendItem(item, text="")
- self.Expand(item)
- self.SetItemImage(new, workload_icon, wx.TreeItemIcon_Normal)
- self.EnsureVisible(new)
- if not self.OrgEdt(new):
- self.Delete(new)
-
-
-class OrgsPanel(wx.Panel):
- ID_CONSADDBTN = 145
- ID_REALMADDBTN = 144
-
- def __init__(self, parent, ID):
- global realm_icon, workload_icon
-
- wx.Panel.__init__(self, parent, -1)
-
- #create image list
- imagelist = wx.ImageList(16, 17, True)
- #define generic function and use it for all input
- realm_icon = imagelist.Add(realm_bmp)
- workload_icon = imagelist.Add(workload_bmp)
-
- #left tree control for organizations / workload definitions
- orgshdrbox = wx.StaticBox(self, -1, "")
- orgshdrboxsizer = wx.StaticBoxSizer(orgshdrbox, wx.HORIZONTAL)
- orgshdr = wx.StaticText(self, -1, "Organization / Department Definition",
- style=wx.ALIGN_CENTER)
- orgshdr.SetHelpText(RealmWorkloadPanelHelp)
- points = orgshdr.GetFont().GetPointSize() # get the current size
- hdrfont = wx.Font(points + 2, family=wx.DEFAULT,
- style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
- orgshdr.SetFont(hdrfont)
- orgshdr.SetForegroundColour('MEDIUMBLUE')
- orgshdr.SetBackgroundColour('SNOW')
- orgshdrboxsizer.Add(orgshdr, proportion=1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_LEFT, border=5)
- addorgsbutton = wx.Button(self, self.ID_REALMADDBTN, "New Org", style=wx.BU_EXACTFIT)
- addorgsbutton.SetToolTipString("Add A New Organization")
- addorgsbutton.SetHelpText(NewRealmButtonHelp)
- addorgsbutton.SetForegroundColour('MEDIUMBLUE')
- addfont = wx.Font(points, family=wx.DEFAULT,
- style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
- addorgsbutton.SetFont(addfont)
- orgshdrboxsizer.Add(addorgsbutton, proportion=0, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=0)
-
- self.orgs = orgTreeCtrl(self, -1,
- pos=wx.DefaultPosition,
- size=wx.DefaultSize,
- style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | wx.TR_NO_LINES
- | wx.TR_MULTIPLE,
- validator=wx.DefaultValidator,
- name="orgs")
- self.orgs.AssignImageList(imagelist)
- self.orgs.SetHelpText(RealmWorkloadPanelHelp)
-
- self.addconsbutton = wx.Button(self, self.ID_CONSADDBTN,
- "Create run-time exclusion rule from selection -->",
- style=wx.BU_EXACTFIT)
- self.addconsbutton.SetToolTipString("Create New Exclusion rule From Above Workload Selection")
- self.addconsbutton.SetHelpText(CreateRunTimeButtonHelp)
- self.addconsbutton.SetForegroundColour('MEDIUMBLUE')
- addfont = wx.Font(points, family=wx.DEFAULT,
- style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
- self.addconsbutton.SetFont(addfont)
- self.addconsbutton.Bind(wx.EVT_BUTTON, self._AddConflict, id=self.ID_CONSADDBTN)
-
- orgsvbox = wx.BoxSizer(wx.VERTICAL)
- orgsvbox.Add(orgshdrboxsizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- orgsvbox.Add(self.orgs, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- orgsvbox.Add(self.addconsbutton, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- self.SetSizer(orgsvbox)
- addorgsbutton.Bind(wx.EVT_BUTTON, self.orgs._OrgRAdd, id= self.ID_REALMADDBTN)
-
-
- def _AddConflict(self, event):
- app.win.conspanel._AddNewConflict(event)
-
-
-class ConsPanel(wx.Panel):
- ID_CONSSELECT = 151
- ID_CONSADD = 152
- ID_CONSRENAME = 153
- ID_CONSDEL = 154
- ID_CONSSELECTSUB= 155
-
- conflictMAX = ID_CS_START
-
- def __init__(self, parent, ID):
- self.conflictsets = []
- self.parent = parent
- wx.Panel.__init__(self, parent, -1)
- #header
- conshdrbox = wx.StaticBox(self, -1, "")
- conshdrboxsizer = wx.StaticBoxSizer(conshdrbox, wx.HORIZONTAL)
- conshdr = wx.StaticText(self, -1, "Run-time Exclusion Rules", style=wx.ALIGN_CENTER)
- conshdr.SetHelpText(RunTimeExclusionPanelHelp)
- points = conshdr.GetFont().GetPointSize() # get the current size
- hdrfont = wx.Font(points + 2, family=wx.DEFAULT,
- style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
- conshdr.SetFont(hdrfont)
- conshdr.SetForegroundColour('ORANGERED')
-
- #context help button
- ctxHelp = wx.ContextHelpButton(self)
- ctxHelp.SetHelpText("Context Help Button.")
- ctxHelp.SetToolTipString("Context Help: Press this button, then press any other button or panel to get help.")
-
-
- conshdrboxsizer.Add(conshdr, proportion=1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_LEFT, border=5)
- conshdrboxsizer.Add(ctxHelp, proportion=0, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=0)
- #scrolledwindow for all the run-time exclusion rules
- conflictspanel = wx.ScrolledWindow(self, -1, (0,0),
- style = wx.FULL_REPAINT_ON_RESIZE |
- wx.VSCROLL )
- conflictspanel.SetVirtualSize((1000, 1000))
- conflictspanel.SetScrollRate(5,5)
- self.conflictsboxsizer = wx.BoxSizer(wx.VERTICAL)
-
- #self.conflictsboxsizer.Fit(self)
- conflictspanel.SetSizer(self.conflictsboxsizer)
- consvbox = wx.BoxSizer(wx.VERTICAL)
- consvbox.Add(conshdrboxsizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- consvbox.Add(conflictspanel, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- self.SetSizer(consvbox)
- self.consvbox = consvbox
- self.conflictspanel=conflictspanel
-
- self.cmenu = wx.Menu()
- self.cmenu.Append(self.ID_CONSRENAME, "Rename Run-time Exclusion Rule", "Rename Run-time Exclusion Rule")
- self.cmenu.AppendSeparator()
- self.cmenu.Append(self.ID_CONSDEL, "Delete Run-time Exclusion Rule", "Delete Run-time Exclusion Rule")
- self.Bind(wx.EVT_MENU, self._CSRename, id=self.ID_CONSRENAME)
- self.Bind(wx.EVT_MENU, self._CSDelete, id=self.ID_CONSDEL)
-
-
- #Helper methods called from anywhere
- def New(self):
- #delete all run-time exclusion rules
- for i in self.conflictsets:
- i.Disable()
- i.Destroy()
- self.conflictsets = []
- self.conflictsboxsizer.Layout()
- size=self.GetSize()
- self.Fit()
- self.SetSize(size)
-
-
- def DelCSById(self, delid):
- #delete CS representation
- delpos, item = self.GetCSBox(delid)
- if item:
- self.DelCSByItem(item)
-
-
- def DelCSByItem(self, item):
- #delete CS representation
- self.conflictsets.remove(item)
- exists = self.conflictsboxsizer.Detach(item)
- if exists:
- item.Destroy()
- self.RefreshMe()
-
-
- def RefreshMe(self):
- size=self.parent.GetSize()
- self.parent.Fit()
- self.parent.SetSize(size + (1,1))
- self.parent.SetSize(size)
-
-
- def GetOrgSelection(self):
- (tree, selection) = GetOrgsSelection()
- if not len(selection):
- dlg = wx.MessageDialog(self, 'You must select first at least one Organization/Department workload!',
- 'Creating A New Run-time Rule', wx.OK | wx.ICON_ERROR)
- dlg.ShowModal()
- dlg.Destroy()
- return None,None
- # now rewrite selection (realm.workload extension, check consistency)
- alist = []
- for i in selection:
- if isRealm(i):
- alist.append(tree.GetItemText(i))
- else:
- alist.append(tree.GetItemText(tree.GetItemParent(i))
- + "." + tree.GetItemText(i))
-
- if isRealm(i):
- for j in selection:
- if tree.GetItemParent(j) == i:
- violation = ("[ " + tree.GetItemText(i) + ", " +
- tree.GetItemText(i) + "." + tree.GetItemText(j) + " ]")
- dlg = wx.MessageDialog(self,
- 'Invalid Selection ' + violation + '.\n\n' +
- 'You can only select EITHER an Organization OR specific Department!',
- 'Creating A New Run-time Exclusion Rule', wx.OK | wx.ICON_ERROR)
- dlg.ShowModal()
- dlg.Destroy()
- return None,None
- return (alist, selection)
-
-
- def AddConflict(self, name, types):
- csbox = myCSPanel(self, self.conflictMAX, name, types)
- self.conflictsboxsizer.Add(csbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- self.conflictsets.append(csbox)
- self.conflictMAX = self.conflictMAX+3
- self.RefreshMe()
- csbox.RefreshMe()
-
-
- def GetCSBox(self, id):
- pos = -1
- i = 0
- while self.conflictsboxsizer.GetItem(i):
- item = self.conflictsboxsizer.GetItem(i).GetWindow()
- if ((item.cbmp.GetId() == id) or
- (item.add_selection.GetId() == id) or
- (item.del_selection.GetId() == id)):
- pos = i
- box = item
- break
- i = i + 1
- if pos < 0:
- print "Run-time Exclusion Rule Not Found ERROR!"
- return (None, None)
- else:
- return (pos, box)
-
-
- #bind methods
- def _AddNewConflict(self, event):
- # first get the conflicting workload types with current selection
- types, items = self.GetOrgSelection()
- if not types:
- return
- #get name for conflict set
- dlg = wx.TextEntryDialog(
- self, 'Please enter a name for the Run-time Exclusion Rule:', 'Creating A New Run-time Exclusion Rule')
- dlg.SetValue("")
- ret = dlg.ShowModal()
- name = dlg.GetValue()
- dlg.Destroy()
- if ret != wx.ID_OK:
- return
- self.AddConflict(name, types)
-
-
- def _OnClick(self, event):
- self.event = event
- app.win.SetStatusText("")
- self.PopupMenu(self.cmenu)
-
-
- def _CSRename(self, event):
- delpos, item = self.GetCSBox(self.event.GetId())
- if not item:
- return
- #allow to name the conflict set
- dlg = wx.TextEntryDialog(
- self, 'Please enter a new name for the Conflict Set:', 'Renaming A Run-time Exclusion Rule')
- dlg.SetValue(item.box.GetLabel())
- ret = dlg.ShowModal()
- name = dlg.GetValue()
- dlg.Destroy()
- if ret != wx.ID_OK:
- return
- item.box.SetLabel(name)
- item.box.SetFont(wx.Font(item.GetFont().GetPointSize(), family=wx.DEFAULT,
- style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD))
-
-
- def _CSDelete(self, event):
- delid = self.event.GetId()
- self.DelCSById(delid)
-
-
- def _AddOrgSelection(self, event):
- addid = event.GetId()
- addpos, item = self.GetCSBox(addid)
- alist, items = self.GetOrgSelection()
- if not alist:
- return
- existing = []
- for i in range(0, item.clb.GetCount()):
- existing.append(item.clb.GetString(i))
-
- #now make sure that we don't get realm + workload into the same CS
- for i in items:
- if isRealm(i):
- #ensure no workload of this realm is already in CS
- realm = app.win.orgs.GetItemText(i)
- for j in iterchildren(i):
- workload = app.win.orgs.GetItemText(j)
- try:
- idx = existing.index (realm + "." + workload)
- except:
- #ok, does not exist
- continue
- #nok, exists already
- violation = ("[ " + realm + ", " +
- realm + "." + workload + " ]")
- dlg = wx.MessageDialog(self,
- 'Invalid Selection ' + violation + '.\n\n' +
- 'You can only have EITHER an Organization OR a specific Department workload\n' +
- 'in a single Run-time Exclusion Rule',
- 'Adding Orgs/Depts workloads to a Run-time Exclusion Rule',
- wx.OK | wx.ICON_ERROR)
- dlg.ShowModal()
- dlg.Destroy()
- return
-
- else:
- #ensure realm of this workload is not in CS
- realm = app.win.orgs.GetItemText(app.win.orgs.GetItemParent(i))
- try:
- idx = existing.index(realm)
- except:
- #ok, does not exist
- continue
- #nok, exists already
- violation = ("[ " + realm + "." + app.win.orgs.GetItemText(i) +
- ", " + realm + " ]")
- dlg = wx.MessageDialog(self,
- 'Invalid Selection ' + violation + '.\n\n' +
- 'You can only have EITHER an Organization OR a specific Department workload\n' +
- 'in a single Run-time Exclusion Rule',
- 'Adding Orgs/Depts workloads to a Run-time Exclusion Rule',
- wx.OK | wx.ICON_ERROR)
- dlg.ShowModal()
- dlg.Destroy()
- return
- #check if any of the selections are already in the conflict set
- overlap=[]
- for l in alist:
- for e in existing:
- if l == e:
- overlap.append(str(l))
- if len(overlap):
- if len(overlap) == 1:
- message = "Selected item " + str(overlap) +\
- " is already in the Run-time Exclusion rule and will be ignored.\n\n Continue?"
- else:
- message = "Selected items " + str(overlap) +\
- " are already in the Run-time Exclusion rule and will be ignored.\n\n Continue?"
- dlg = wx.MessageDialog(self,
- message, 'Adding Orgs/Depts workloads to a Run-time Exclusion rule',
- wx.YES | wx.NO | wx.ICON_EXCLAMATION)
- ret = dlg.ShowModal()
- dlg.Destroy()
- if ret != wx.ID_YES:
- return
-
- for s in alist:
- try:
- existing.index(s)
- except Exception:
- # s not yet in list box, add it
- item.AddTypes([s])
- self.RefreshMe()
-
-
- def _DelConSelection(self, event):
- eventid = event.GetId()
- pos, item = self.GetCSBox(eventid)
- idtuple = item.clb.GetSelections()
- idlist = []
- for i in idtuple:
- idlist.append(i)
- #delete reverse, otherwise item mubers get messed up while deleting
- idlist.reverse()
- for i in idlist:
- item.clb.Delete(i)
- item.RefreshMe()
- if item.clb.GetCount() < 2:
- dlg = wx.MessageDialog(self,
- """Run-time exclusion set has less than two types.\n\n
- Do you want to delete this rule?""",
- 'Deleting Orgs/Depts workloads from a Run-time Exclusion rule',
- wx.YES| wx.NO | wx.ICON_QUESTION)
- ret = dlg.ShowModal()
- dlg.Destroy()
- if ret == wx.ID_YES:
- self.DelCSById(eventid)
- return
- else:
- for i in item.clb.GetSelections():
- item.clb.Deselect(i)
- self.RefreshMe()
-
-
-class myCSPanel(wx.Panel):
- def __init__(self, parent, ID, title, list=[]):
- wx.Panel.__init__(self, parent.conflictspanel, -1)
- self.parent = parent
- cspansizer = wx.BoxSizer(wx.VERTICAL)
- self.box = wx.StaticBox(self, -1, title)
- csboxsizer = wx.StaticBoxSizer(self.box, wx.HORIZONTAL)
- #left: type add/del
- typesizer = wx.BoxSizer(wx.VERTICAL)
- self.add_selection = wx.Button(self, ID+1, "--> Add", style=wx.BU_EXACTFIT)
- self.add_selection.SetToolTipString("Add Workload Selection To Run-time Exclusion rule")
- self.add_selection.SetHelpText(AddToExclusionButtonHelp)
- self.add_selection.SetForegroundColour('MEDIUMBLUE')
- points = self.add_selection.GetFont().GetPointSize()
- addfont = wx.Font(points, family=wx.DEFAULT,
- style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
- self.add_selection.SetFont(addfont)
- self.box.SetFont(addfont)
- typesizer.Add(self.add_selection, proportion = 0, flag = wx.EXPAND | wx.ALL,border=0)
- typesizer.Add((5,5))
- self.del_selection = wx.Button(self, ID+2, "<-- Del", style=wx.BU_EXACTFIT)
- self.del_selection.SetToolTipString("Delete Workload Selection From Run-time Exclusion Rule")
- self.del_selection.SetHelpText(DelFromExclusionButtonHelp)
- self.del_selection.SetForegroundColour('ORANGERED')
- self.del_selection.SetFont(addfont)
- typesizer.Add(self.del_selection, proportion = 0, flag = wx.EXPAND | wx.ALL, border=0)
- csboxsizer.Add(typesizer, proportion = 0, border=0)
- csboxsizer.Add((5,5))
- #middle: types
- self.clb = wx.ListBox(self, id=-1, choices=list,
- style= wx.LB_MULTIPLE | wx.LB_SORT )
- self.clb.SetHelpText(ExclusionSetHelp)
- csboxsizer.Add(self.clb, proportion=1, flag=wx.EXPAND | wx.ALL, border=0)
- csboxsizer.Add((5,5))
- #right: Conflictset-global ops button
- bmpsizer = wx.BoxSizer(wx.VERTICAL)
- self.cbmp = buttons.GenBitmapButton(self, ID, conflict_bmp, style=wx.BU_EXACTFIT)
- self.cbmp.SetHelpText(ManageExclusionButtonHelp)
- self.cbmp.SetToolTipString("Rename/Delete\nAssociated Run-time Exclusion Rule")
- bmpsizer.Add(self.cbmp, proportion = 0, flag = wx.EXPAND | wx.ALL, border=0)
- csboxsizer.Add(bmpsizer, proportion=0, border=5)
- cspansizer.Add(csboxsizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=0)
- self.csboxsizer=csboxsizer
- self.cspansizer=cspansizer
- self.SetSizer(cspansizer)
- self.cbmp.Bind(wx.EVT_LEFT_DOWN, parent._OnClick, id=ID)
- self.add_selection.Bind(wx.EVT_BUTTON, parent._AddOrgSelection, id=ID + 1)
- self.del_selection.Bind(wx.EVT_BUTTON, parent._DelConSelection, id=ID + 2)
-
- # append and delete an item to get rid of
- # the ugly vertical scroll bar on the Listbox on Linux
- def RefreshMe(self):
- x = self.clb.Append(" ")
- app.win.conspanel.RefreshMe()
- self.clb.Delete(x)
- self.Layout()
- app.win.conspanel.Layout()
-
-
- def AddTypes(self, list):
- for i in list:
- self.clb.Append(i)
- self.RefreshMe()
-
-
- def GetTypes(self):
- alist = []
- for i in range(0, self.clb.GetCount()):
- alist.append(self.clb.GetString(i))
- return alist
-
-
- def GetBoxName(self):
- return self.box.GetLabel()
-
-
- def Replace(self, oldlabel, newlabel):
- index = self.clb.FindString(oldlabel)
- if index != wx.NOT_FOUND:
- self.clb.SetString(index, newlabel)
-
-
- def Delete(self, label):
- index = self.clb.FindString(label)
- if index != wx.NOT_FOUND:
- self.clb.Delete(index)
-
-
-class myHelpPanel(wx.Panel):
- def __init__(self, parent, ID):
- wx.Panel.__init__(self, parent, -1)
-
-
-class ezFrame(wx.Frame):
-
- ID_ABOUT = 101
- ID_NEW = 102
- ID_OPEN = 103
- ID_SAVE = 104
- ID_SAVEAS = 105
- ID_EXIT = 106
- ID_HELP = 107
-
- ID_ITRENAME = 111
- ID_ITADD = 112
- ID_ITDEL = 113
-
- ID_COLLAPSEALL = 121
- ID_EXPANDALL = 122
- ID_SORTALL = 123
-
- ID_TRANSLATE = 131
-
- ID_ORGEDT = 141
- ID_ORGADD = 142
- ID_ORGDEL = 143
-
- def __init__(self, parent, ID, title):
- global realm_bmp, workload_bmp, conflict_bmp
-
- wx.Frame.__init__(self, parent, ID, title,
- wx.DefaultPosition,
- wx.Size(700,450)
- )
-
- realm_bmp = GetIconBitmap('Organization')
- workload_bmp = GetIconBitmap('Department')
- conflict_bmp = GetIconBitmap('Conflict')
- self.SetHelpText(GetHelp)
- self.orgfilename = None
- self.CreateStatusBar()
- self.SetStatusText("")
- self.bkg = wx.Panel(self)
-
- self.orgswin = wx.SashLayoutWindow(
- self.bkg, -1, wx.DefaultPosition, (300, 150),wx.SW_3DSASH | wx.SW_BORDER)
-
- self.orgswin.SetDefaultSize((300,150))
- self.orgswin.SetOrientation(wx.LAYOUT_VERTICAL)
- self.orgswin.SetAlignment(wx.LAYOUT_LEFT)
- self.orgspanel = OrgsPanel(self.orgswin, -1)
- self.orgs = self.orgspanel.orgs
-
- self.realm_menu = wx.Menu()
- self.realm_menu.Append(self.ID_ORGADD, "Add Department\tctrl-a", "Add Department Workload")
- self.realm_menu.AppendSeparator()
- self.realm_menu.AppendSeparator()
- self.realm_menu.Append(self.ID_ORGEDT, "Rename Organization\tctrl-r", "Rename Organization Workload")
- self.realm_menu.Append(self.ID_ORGDEL, "Delete Organization\tctrl-d", "Delete Organization Workload")
- self.realm_menu.Bind(wx.EVT_MENU, self.orgs._OrgEdt, id= self.ID_ORGEDT)
- self.realm_menu.Bind(wx.EVT_MENU, self.orgs._OrgWAdd, id= self.ID_ORGADD)
- self.realm_menu.Bind(wx.EVT_MENU, self._ItemDel, id=self.ID_ORGDEL)
-
- self.workload_menu = wx.Menu()
- self.workload_menu.Append(self.ID_ORGEDT, "Rename Department\tctrl-r", "Rename Department Workload")
- self.workload_menu.Append(self.ID_ORGDEL, "Delete Department\tctrl-d", "Delete Department Workload")
- self.workload_menu.Bind(wx.EVT_MENU, self.orgs._OrgEdt, id= self.ID_ORGEDT)
- self.workload_menu.Bind(wx.EVT_MENU, self._ItemDel, id=self.ID_ORGDEL)
-
- self.orgs.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self._OrgRightClick)
- self.orgs.Bind(wx.EVT_TREE_SEL_CHANGED, self._OrgSelectionChanged)
-
- self.conswin = wx.SashLayoutWindow(
- self.bkg, -1, wx.DefaultPosition, (300, 150),
- #wx.NO_BORDER | wx.SW_3D
- wx.SW_3DSASH | wx.SW_BORDER
- )
- self.conswin.SetDefaultSize((300,150))
- self.conswin.SetOrientation(wx.LAYOUT_VERTICAL)
- self.conswin.SetAlignment(wx.LAYOUT_RIGHT)
- self.conswin.SetSashVisible(wx.SASH_LEFT, True)
- self.conswin.SetSashVisible(wx.SASH_RIGHT, False)
-
- #right tree control for non-concurrent workload execution
- self.conspanel = ConsPanel(self.conswin, -1)
- self.conspanel.RefreshMe()
- self.bkg.Bind(wx.EVT_SASH_DRAGGED_RANGE, self._OnSashDrag, id=self.conswin.GetId(),
- id2=self.conswin.GetId())
- self.bkg.Bind(wx.EVT_SIZE, self._OnSize)
-
- # Main Menu
- # -File
- fmenu = wx.Menu()
- fmenu.Append(self.ID_OPEN, "Open Workload Definition...\tctrl-o", "Open current workload definition")
- fmenu.Append(self.ID_SAVE, "Save Workload Definition\tctrl-s", "Save workload defintion")
- fmenu.Append(self.ID_SAVEAS, "Save Workload Defintion as...\talt-s", "Save into new file")
- fmenu.AppendSeparator()
- fmenu.Append(self.ID_TRANSLATE, "Save as Xen ACM Security Policy ...\talt-t", "Create Xen ACM security policy")
- fmenu.AppendSeparator()
- fmenu.Append(self.ID_NEW, "New\tctrl-n", "Create a new oganization definition")
- fmenu.AppendSeparator()
- fmenu.Append(self.ID_EXIT, "Exit\tctrl-x", "Terminate the program")
- self.fmenu = fmenu
-
- # -Edit
- emenu = wx.Menu()
- emenu.Append(self.ID_ITRENAME, "Rename\tctrl-r", "Rename Selected Organization/Department")
- emenu.Append(self.ID_ITADD, "Add\tctrl-a", "Add Child to Selected Organization/Department")
- emenu.Append(self.ID_ITDEL, "Delete\tctrl-d", "Delete Selected Organization/Department")
- self.emenu = emenu
- # -Help
- hmenu = wx.Menu()
- hmenu.Append(self.ID_HELP, "Step-By-Step Help\tctrl-h", "More information about this program")
- hmenu.Append(self.ID_ABOUT, "About", "More information about this program")
- self.hmenu = hmenu
-
- # -View
- vmenu = wx.Menu()
- vmenu.Append(self.ID_SORTALL, "Sort All", "Sort Entries In All Trees")
- vmenu.Append(self.ID_COLLAPSEALL, "Collapse All\tctrl-c", "Collapse All Trees")
- vmenu.Append(self.ID_EXPANDALL, "Expand All\tctrl-e", "Expand All Trees")
- self.vmenu = vmenu
-
- menuBar = wx.MenuBar()
- menuBar.Append(fmenu, "&File");
- menuBar.Append(emenu, "&Edit");
- menuBar.Append(vmenu, "&View");
- menuBar.Append(hmenu, "&Help");
-
- self.SetMenuBar(menuBar)
-
- self.Bind(wx.EVT_MENU, self._OpenSpec, id=self.ID_OPEN)
- self.Bind(wx.EVT_MENU, self._SaveSpec, id=self.ID_SAVE)
- self.Bind(wx.EVT_MENU, self._SaveAsSpec,id=self.ID_SAVEAS)
- self.Bind(wx.EVT_MENU, self._NewSpec, id=self.ID_NEW)
- self.Bind(wx.EVT_MENU, self._TimeToQuit,id=self.ID_EXIT)
- self.Bind(wx.EVT_MENU, self._TranslateSpec, id=self.ID_TRANSLATE)
-
- self.Bind(wx.EVT_MENU, self._ItemRename, id=self.ID_ITRENAME)
- self.Bind(wx.EVT_MENU, self._ItemAdd, id=self.ID_ITADD)
- self.Bind(wx.EVT_MENU, self._ItemDel, id=self.ID_ITDEL)
-
- self.Bind(wx.EVT_MENU, self._SortAll, id=self.ID_SORTALL)
- self.Bind(wx.EVT_MENU, self._CollapseAll,id=self.ID_COLLAPSEALL)
- self.Bind(wx.EVT_MENU, self._ExpandAll, id=self.ID_EXPANDALL)
-
- self.Bind(wx.EVT_MENU, self._Help, id=self.ID_HELP)
- self.Bind(wx.EVT_MENU, self._OnAbout, id=self.ID_ABOUT)
- self.Bind(wx.EVT_CLOSE, self._TimeToQuit)
-
-
- def RefreshMe(self):
- size=self.GetSize()
- self.Fit()
- self.SetSize(size)
-
- #helper methods
- def Load(self, file):
- self.orgfilename = file
- dictname = 'ezpolicy'
- d = {}
- # read in the config file
- globs = {}
- locs = {}
- execfile(file, globs, locs)
- for (k, v) in locs.items():
- if k == dictname:
- d = v
- break
- dict2org(d)
- self.orgspanel.orgs.UnselectAll()
- self.SetTitle("ezPolicy: " + self.orgfilename)
- self._ExpandAll(None)
-
-
- def Save(self, file):
- dictname = 'ezpolicy'
- d = org2dict()
- fd = open(file, "w")
- fd.write(dictname + " = ")
- fd.write(str(d))
- fd.close()
-
-
- def New(self):
- self.orgspanel.orgs.DeleteChildren(self.orgspanel.orgs.GetRootItem())
- self.conspanel.New()
-
-
- def LabelReplaceInConflictsets(self, item, oldlabel, newlabel):
- if isRealm(item):
- replace = [[ oldlabel, newlabel]]
- for i in iterchildren(item):
- replace.append([(oldlabel + "." + self.orgs.GetItemText(i)),
- (newlabel + "." + self.orgs.GetItemText(i))])
- else:
- parent = self.orgs.GetItemParent(item)
- replace = [
- [(self.orgs.GetItemText(parent) + "." + oldlabel),
- (self.orgs.GetItemText(parent) + "." + newlabel)]
- ]
- for r in replace:
- for i in self.conspanel.conflictsets:
- if r[0] in i.GetTypes():
- i.Replace(r[0], r[1])
-
-
- def OrgDelItem(self, item):
- label = self.orgs.GetItemText(item)
- if isRealm(item):
- delset = [label]
- for i in iterchildren(item):
- delset.append(label + "." + self.orgs.GetItemText(i))
- else:
- parent = self.orgs.GetItemParent(item)
- delset = [self.orgs.GetItemText(parent) + "." + label]
- for i in self.conspanel.conflictsets:
- for l in delset:
- i.Delete(l)
- #need to run in reverse order when deleting items
- rev = []
- for i in self.conspanel.conflictsets:
- rev.append(i)
- rev.reverse()
- for i in rev:
- if len(i.GetTypes()) < 1:
- self.conspanel.DelCSByItem(i)
- self.orgs.Delete(item)
-
-
- def _OnSashDrag(self, event):
- if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
- return
- w = event.GetEventObject()
- if w is self.conswin:
- self.conswin.SetDefaultSize((event.GetDragRect().width, 1000))
- wx.LayoutAlgorithm().LayoutWindow(self.bkg, self.orgswin)
- self.RefreshMe()
-
-
- def _OnSize(self, event):
- wx.LayoutAlgorithm().LayoutWindow(self.bkg, self.orgswin)
-
-
- def _OrgSelectionChanged(self, event):
- self.orgs.event = event
- item = self.orgs.event.GetItem()
- if not item.IsOk() or not self.orgs.IsSelected(item):
- self.emenu.Enable(self.ID_ITRENAME, False)
- self.emenu.Enable(self.ID_ITADD, False)
- self.emenu.Enable(self.ID_ITDEL, False)
- return
- self.SetStatusText("")
- #enable/disable edit menu functions
- if isRealm(item):
- self.emenu.Enable(self.ID_ITRENAME, True)
- self.emenu.Enable(self.ID_ITADD, True)
- self.emenu.Enable(self.ID_ITDEL, True)
- elif isWorkload(item):
- self.emenu.Enable(self.ID_ITRENAME, True)
- self.emenu.Enable(self.ID_ITADD, False)
- self.emenu.Enable(self.ID_ITDEL, True)
- if len(self.orgs.GetSelections()) > 1:
- self.emenu.Enable(self.ID_ITRENAME, False)
- self.emenu.Enable(self.ID_ITADD, False)
-
-
- def _OrgRightClick(self, event):
- self.SetStatusText("")
- self.orgs.event = event
- item = self.orgs.event.GetItem()
- #del not permitted on root items
- if isWorkload(item):
- self.workload_menu.Enable(self.ID_ORGDEL, True)
- self.workload_menu.Enable(self.ID_ORGEDT, True)
- if len(self.orgs.GetSelections()) > 1:
- self.workload_menu.Enable(self.ID_ORGEDT, False)
- self.PopupMenu(self.workload_menu)
- else:
- self.realm_menu.Enable(self.ID_ORGDEL, True)
- self.realm_menu.Enable(self.ID_ORGEDT, True)
- self.realm_menu.Enable(self.ID_ORGADD, True)
- if len(self.orgs.GetSelections()) > 1 or \
- ACM_LABEL_UNLABELED == self.orgs.GetItemText(item):
- self.realm_menu.Enable(self.ID_ORGEDT, False)
- self.realm_menu.Enable(self.ID_ORGADD, False)
- self.PopupMenu(self.realm_menu)
-
-
- def _OpenSpec(self, event):
- filediag = wx.FileDialog(self, defaultFile="myspec.wld",
- wildcard="*.wld", style=wx.OPEN,
- message="Select Workload Definition file name")
- ret = filediag.ShowModal()
- name = filediag.GetPath()
- filediag.Destroy()
- if ret not in [wx.ID_OK]:
- return
- self.orgfilename = name
- self.Load(self.orgfilename)
- self.SetTitle("ezPolicy: " + self.orgfilename)
-
-
- def _SaveSpec(self, event):
- if not self.orgfilename:
- filediag = wx.FileDialog(self, defaultFile="myspec.wld",
- wildcard="*.wld", style=wx.SAVE | wx.OVERWRITE_PROMPT,
- message="Select Workload Definition file name")
- ret = filediag.ShowModal()
- name = filediag.GetPath()
- filediag.Destroy()
- if ret not in [wx.ID_OK]:
- return
- self.orgfilename = name
- self.Save(self.orgfilename)
- self.SetTitle("ezPolicy: " + self.orgfilename)
-
-
- def _SaveAsSpec(self, event):
- if not self.orgfilename:
- self.orgfilename = "DEFAULT.wld"
- filediag = wx.FileDialog(self, defaultFile=self.orgfilename,
- wildcard="*.wld", style=wx.SAVE | wx.OVERWRITE_PROMPT,
- message="Select Workload Definition file name")
- ret = filediag.ShowModal()
- name = filediag.GetPath()
- filediag.Destroy()
- if ret not in [wx.ID_OK]:
- return
- self.orgfilename = name
- self.Save(self.orgfilename)
- self.SetTitle("ezPolicy: " + self.orgfilename)
-
-
- def _NewSpec(self, event):
- self.orgfilename = None
- #reset trees etc
- self.New()
- self.SetTitle("ezPolicy: *New File*")
-
-
- def _TranslateSpec(self, event):
- policyname = transInfo()
- if not policyname:
- return
- path="/etc/xen/acm-security/policies/"
- nameparts=string.split(policyname, ".")
- if len(nameparts) > 1:
- path = path + "/".join(nameparts[0:len(nameparts)-1])
- deffile = nameparts[len(nameparts) - 1] + "-security_policy.xml"
- filediag = wx.FileDialog(self, defaultDir=path, defaultFile=deffile,
- wildcard="*.xml", message="Select Policy File Name",
- style=wx.SAVE | wx.OVERWRITE_PROMPT)
- ret = filediag.ShowModal()
- filename = filediag.GetPath()
- filediag.Destroy()
- if ret not in [wx.ID_OK]:
- return
- #translate data into default policy
- timestamp = time.asctime()
- d = org2dict()
- types = []
- for i in d['orgs']:
- types.append(str(i[0]))
- for j in i[1]:
- types.append(str(i[0]) + "." + str(j))
- f = open(filename, "w")
- printPolicyHeader (f, policyname, timestamp)
- printPolicy(f, types, d['cons'])
- printLabels(f, d, types)#, d['cons'])
- printTrailer(f)
- f.close()
-
-
- def _ItemRename(self, event):
- #ensure only 1 item is selected
- sels = self.orgs.GetSelections()
- if len(sels) != 1:
- return
- self.orgs.OrgEdt(sels[0])
-
-
- def _ItemAdd(self, event):
- #ensure only 1 item is selected + add figure
- sels = self.orgs.GetSelections()
- if len(sels) != 1:
- return
- self.orgs.OrgWAdd(sels[0])
-
-
- def _ItemDel(self, event):
- sels = self.orgs.GetSelections()
- for i in sels:
- self.OrgDelItem(i)
-
-
- def _CollapseAll(self, event):
- for i in iterchildren(self.orgs.GetRootItem()):
- self.orgs.Collapse(i)
-
-
- def _ExpandAll(self, event):
- for i in iterchildren(self.orgs.GetRootItem()):
- self.orgs.Expand(i)
-
-
- def _SortAll(self, event):
- #would be nice to also sort the organizations
- for i in iterchildren(self.orgs.GetRootItem()):
- if self.orgs.GetChildrenCount(i) > 0:
- self.orgs.SortChildren(i)
-
-
- def _OnAbout(self, event):
- dlg = wx.MessageDialog(self,
- "This program helps you to define the structure\n"
- "of organizations and their departments.\n\n"
- "It translates this \'Workload Definition\' into\n"
- "a simple workload protection policy for the\n"
- "Xen Access Control Module.\n\n\n"
- "Copyright (c) 2006: IBM Corporation\n"
- "Author:\nReiner Sailer <sailer@us.ibm.com>",
- "About Me", wx.OK | wx.ICON_INFORMATION)
- dlg.ShowModal()
- dlg.Destroy()
-
-
- def _Help(self, event):
- hpopup = wx.Frame(self,-1, "HELP: Creating a Xen Security Policy in 3 Steps" )
- HelpHtmlWindow(hpopup, -1)
- hpopup.SetSize((650,650))
- hpopup.Show(True)
-
-
- def _TimeToQuit(self, event):
- self.Bind(wx.EVT_CLOSE, None)
- self.orgs.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, None)
- self.orgs.Bind(wx.EVT_TREE_SEL_CHANGED, None)
- self.Close(True)
-
-
-class ezApp(wx.App):
-
- def OnInit(self):
- self.win = ezFrame(None, -1, title="EZ Workload Protection Policy Tool")
- self.win.Show(True)
- self.SetTopWindow(self.win)
- return True
-
-
- def Load(self, file):
- self.win.Load(file)
-
-
- def New(self):
- self.win.New()
-
-
-def isRealm(it):
- if not it:
- return False
- return (app.win.orgspanel.orgs.GetItemParent(it) == app.win.orgspanel.orgs.GetRootItem())
-
-
-def isWorkload(it):
- if not it or not app.win.orgs.GetItemParent(it):
- return False
- return (app.win.orgspanel.orgs.GetItemParent(app.win.orgspanel.orgs.GetItemParent(it))
- == app.win.orgspanel.orgs.GetRootItem())
-
-
-def GetOrgsSelection():
- return (app.win.orgspanel.orgs, app.win.orgspanel.orgs.GetSelections())
-
-
-def transInfo():
- info = wx.TextEntryDialog(app.win, message="POLICYNAME",
- caption="Translate: Creating The Xen/ACM Policy")
- ret = info.ShowModal()
- name = info.GetValue()
- info.Destroy()
- if ret in [wx.ID_OK]:
- return name
- return None
-
-
-def iterchildren(node):
- cid, citem = app.win.orgspanel.orgs.GetFirstChild(node)
- while cid.IsOk():
- yield cid
- cid, citem = app.win.orgspanel.orgs.GetNextChild(node, citem)
-
-
-def dict2org(d):
- # release old structure
- app.New()
- # fill them with dict content
- for i in d['orgs']:
- orgnode = app.win.orgspanel.orgs.AppendItem(app.win.orgspanel.orgs.GetRootItem(), text=i[0])
- app.win.orgspanel.orgs.SetItemBold(orgnode, True)
- app.win.orgspanel.orgs.SetItemImage(orgnode, realm_icon, wx.TreeItemIcon_Normal)
- for j in i[1]:
- wlnode = app.win.orgspanel.orgs.AppendItem(orgnode, text=j)
- app.win.orgspanel.orgs.SetItemImage(wlnode, workload_icon, wx.TreeItemIcon_Normal)
- for i in d['cons']:
- app.win.conspanel.AddConflict(i[0], i[1])
-
-
-def org2dict():
- global app
- dic = {}
- o= []
- for i in iterchildren(app.win.orgs.GetRootItem()):
- d = []
- for j in iterchildren(i):
- d.append(
- str(app.win.orgspanel.orgs.GetItemText(j).encode("utf-8")))
- o.append([str(app.win.orgspanel.orgs.GetItemText(i).encode("utf-8")),
- d])
- dic['orgs'] = o
- c=[]
- for i in app.win.conspanel.conflictsets:
- c.append([i.GetBoxName() , i.GetTypes()])
- dic['cons'] = c
- return dic
-
-
-def dict_read(dictname, filename):
- """Loads <filename> and returns the dictionary named <dictname> from
- the file.
- """
- dic = {}
-
- # read in the config file
- globs = {}
- locs = {}
- execfile(filename, globs, locs)
-
- for (k, v) in locs.items():
- if k == dictname:
- dic = v
- break
- return dic
-
-#==================== Policy Generation/Translation functions
-
-def printPolicyHeader (fd, policyname, timestamp, version="1.0"):
- fd.write( """<?xml version=\"1.0\" encoding=\"UTF-8\"?>
-<!-- Auto-generated by ezPolicy -->
-<SecurityPolicyDefinition xmlns=\"http://www.ibm.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.ibm.com ../../security_policy.xsd \">
- <PolicyHeader>
- <PolicyName>%s</PolicyName>
- <Date>%s</Date>
- <Version>%s</Version>
- </PolicyHeader>
-""" % (policyname, timestamp, version))
-
-
-
-def printPolicy(fd, types, cons):
- fd.write("""
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>\n""")
-
- # add dynamically created type definitions org.dept
- for i in types:
- fd.write(""" <Type>%s</Type>\n""" % i)
-
- fd.write(""" </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
-
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>SystemManagement</Type>\n""")
-
- #add dinamically created cw types
- for i in types:
- fd.write(""" <Type>%s</Type>\n""" % i)
-
- fd.write(""" </ChineseWallTypes>\n\n""")
-
- if len(cons):
- fd.write(""" <ConflictSets>\n""")
- for i in cons:
- if len(i[1]) < 2:
- print "Ignoring Run-time exclusion set %s (less than 2 types}" % i[0]
- continue
- #name is optional but must be set
- if i[0]:
- rer_name = i[0]
- else:
- rer_name = "RER"
- fd.write(""" <Conflict name=\"""" +
- rer_name.encode("utf-8") + """\">\n""")
- for j in i[1]:
- typ = j.encode("utf-8")
- fd.write(""" <Type>%s</Type>\n""" % typ)
- fd.write(""" </Conflict>\n""")
- fd.write(""" </ConflictSets>\n""")
-
- fd.write(""" </ChineseWall>\n\n""")
-
-
-
-def printLabels(fd, d, types): #, cons):
- fd.write( """ <SecurityLabelTemplate>
- <SubjectLabels bootstrap=\"SystemManagement\">""")
-
- # create default boot label for dom0
- fd.write("""\n <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>\n""")
- # add dynamically created type definitions org.dept
- for i in types:
- fd.write(""" <Type>%s</Type>\n""" % i)
-
- fd.write(""" </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>\n""")
-
- # create one Udom label for each type ste type
- for i in d['orgs']:
- organization = i[0]
- fd.write("""\n <VirtualMachineLabel>
- <Name>%s</Name>
- <SimpleTypeEnforcementTypes>
- <Type>%s</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>%s</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>\n""" % (organization, organization, organization))
- for j in i[1]:
- workload = organization + "." + j
- fd.write("""\n <VirtualMachineLabel>
- <Name>%s</Name>
- <SimpleTypeEnforcementTypes>
- <Type>%s</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>%s</Type>
- <Type>%s</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>\n""" % (workload, workload, organization , workload))
-
- fd.write(""" </SubjectLabels>\n\n""")
-
- #create resource labels for each type
- fd.write(""" <ObjectLabels>""")
- for i in ['SystemManagement'] + types:
- fd.write("""\n <ResourceLabel>
- <Name>%s</Name>
- <SimpleTypeEnforcementTypes>
- <Type>%s</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>\n""" % (i, i))
- fd.write(""" </ObjectLabels>
- </SecurityLabelTemplate>\n""")
-
-def printTrailer(fd):
- fd.write( """</SecurityPolicyDefinition>\n""")
-
-#============== the icons/bitmaps ======================================
-# to ensure the program runs anywhere, we include the buttons right here
-# while this makes the file even bigger, it also makes it easier to use
-import cStringIO
-
-def GetIconBitmap(name):
- return wx.BitmapFromImage(GetIconImage(name))
-
-def GetIconImage(name):
- if name == 'Organization':
- iostream = cStringIO.StringIO(GetOrganizationIconData())
- elif name == 'Department':
- iostream = cStringIO.StringIO(GetDepartmentIconData())
- elif name == 'Conflict':
- iostream = cStringIO.StringIO(GetConflictIconData())
- else:
- sys.exit("UNKNOWN ICON NAME")
- return wx.ImageFromStream(iostream)
-
-def GetOrganizationIconData():
- return \
-'\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\
-\x00\x00\x00\x10\x00\x00\x00\x11\x08\x02\x00\x00\x00\x5b\xcd\xbb\
-\x93\x00\x00\x00\x03\x73\x42\x49\x54\x08\x08\x08\xdb\xe1\x4f\xe0\
-\x00\x00\x02\x7b\x49\x44\x41\x54\x28\x91\x5d\xd1\xcb\x4f\x13\x51\
-\x14\x06\xf0\x73\x1f\x74\x3a\x33\x9d\x96\x87\x0a\x14\x30\x3c\xd4\
-\x60\x34\xf1\xb1\x70\xa5\x26\x2e\xfc\x87\x4d\xdc\x18\x17\x26\x08\
-\x26\x44\x01\xc1\x07\x10\x52\x1e\x96\xb6\x94\x4a\x87\x0e\x33\x73\
-\xef\xdc\x7b\xcf\x71\x01\x31\x81\x6f\x73\x36\xe7\xb7\xf8\xf2\x31\
-\x22\x82\xab\x50\x51\x68\xa5\xd2\x6e\x77\xbf\xdd\xf8\x36\x52\x1b\
-\x5f\x78\xfc\xc6\x0f\x6b\x70\x3d\xf2\xea\x97\x28\x8e\xbb\xfd\x7e\
-\xd7\xb9\xb4\x3e\xe9\xe3\x99\x1d\x34\x3f\x34\xb9\xaa\x2f\xbe\x0d\
-\x2a\xa3\x8c\xb1\xff\x80\x5f\x1e\x63\x4c\x9a\x1e\x23\xaa\x24\xd1\
-\x8c\x91\xe0\xae\x04\xb1\xed\x7e\x6a\xff\x7e\x7f\x11\xb7\x01\xe8\
-\x26\x90\x52\x02\x98\x30\xac\xf8\x7e\x95\x88\x13\x5a\x0e\x4e\xe0\
-\xb9\xe9\x6f\xf5\xbb\x87\x5a\x17\x37\x01\xe7\x1c\x00\x38\x37\x9e\
-\x87\x9c\x91\xb3\xce\x21\x2f\xc8\x4b\xac\xec\xf5\xf6\x76\xd7\xdf\
-\xa9\x6c\x70\xad\x03\x00\x30\xc6\x6b\x35\x19\x86\x5c\x48\x42\x59\
-\x71\xd1\x3d\x88\x26\x82\x68\x8a\xf4\xa0\x68\x7f\x69\xed\xc0\x9d\
-\xb9\xd7\x41\xf5\xf6\x15\x50\x2a\x07\x60\xe5\xb2\x04\x00\x6b\x1d\
-\x56\x67\x71\x68\xbc\x67\x43\xe3\xa2\x49\x8c\xcb\x10\xe7\xad\xa5\
-\x53\x80\x5b\xb3\xaf\xa4\x52\x79\x9e\x0f\x8c\x4d\x01\xdc\x25\xb6\
-\x08\x27\x38\xaa\xb9\x3b\x4a\xb4\x13\x30\x02\x69\xc0\x1c\xc7\x9e\
-\xea\x2c\x1f\x1b\x23\x9b\xad\x46\xaa\xce\x53\x60\x7e\x09\xa7\x2e\
-\x81\xc3\xf6\x05\x58\xc7\x12\x2c\x45\x1e\x17\x45\xce\x19\x32\x42\
-\x61\xbb\x67\xad\x75\x79\xd0\x69\x9f\x23\x0e\xc0\x1f\x2e\xb3\x67\
-\x00\x00\x80\x04\x85\x25\x72\x56\x7a\xa1\xc7\x32\x61\x33\xb8\x1a\
-\x97\xca\xc1\xa8\x74\xa2\xd2\xd3\x8a\x0b\xc8\x0c\x68\xa5\x8c\xb1\
-\x8e\x0d\x21\x22\x3a\xc7\x3c\xe9\x51\x21\x51\x01\x21\x00\x38\xe4\
-\x95\xb1\xfb\x7c\xb8\x12\x0a\x00\xb2\x46\x19\x6c\xfd\x39\xdc\xda\
-\xda\x56\xca\x5c\x6e\x6f\xb4\x4e\xe2\x93\xbf\x49\xac\x8d\x23\x00\
-\xc7\x82\x70\x64\x5a\xd6\xc2\x00\x6d\x47\x08\x40\x12\x8d\x9d\x5f\
-\x5f\x77\xe2\xdb\x33\x73\x51\x89\x98\x60\x71\xaf\xf9\xf3\x70\xa5\
-\x99\x1c\x3c\x19\xe3\xf5\x9a\x57\x1d\x1e\xf5\x82\x31\x59\xe8\x84\
-\x9b\x6c\x38\x08\x98\xc7\xb2\x76\x7a\xd2\xcf\x38\xc0\xf3\x49\xe6\
-\x97\x82\xc1\xc9\xd2\x86\x5b\xdf\x3f\x75\x8d\x01\x3d\xb9\x55\x79\
-\x51\xf2\x26\x84\x2f\x3f\xaf\x7d\x0c\xfd\xe0\xe9\xdd\xa7\xbe\x70\
-\xdb\x1d\x1f\x31\x16\x9c\xcd\x4f\x8d\x29\xad\x3b\x71\x13\x88\x72\
-\x8d\x22\xa2\x8d\x63\xdd\xef\x37\xa2\xf9\x16\xdf\x6d\x6f\x4a\x91\
-\xf9\x43\xae\x1a\xf9\x82\x0b\x21\xf8\x45\x9a\x69\x5d\x74\xba\xa7\
-\x44\x90\xb7\x1c\x9d\x1b\x8c\x2d\xa5\xf4\xeb\xa8\xb9\x77\xb4\x2f\
-\x1f\xd5\x17\xbf\x6f\xad\x2d\xaf\xad\x3e\x9c\x78\x50\xaf\x08\xa5\
-\xcc\xee\xee\xfe\x4e\x63\x73\xe5\xc7\xea\x41\xe3\xf8\x0e\x8a\x97\
-\xf7\x66\x92\x3c\xa9\x4f\x4f\x64\xa5\xb9\x87\x0b\x8b\xff\x00\x63\
-\xce\x84\xe6\xf7\x5b\x7e\xce\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
-\x42\x60\x82'
-
-def GetDepartmentIconData():
- return \
-'\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\
-\x00\x00\x00\x10\x00\x00\x00\x11\x08\x06\x00\x00\x00\xd4\xaf\x2c\
-\xc4\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\
-\x88\x00\x00\x01\x52\x49\x44\x41\x54\x38\x8d\xd5\x92\x3d\x4b\x42\
-\x61\x18\x86\xaf\xf3\xfa\xfa\x81\xa9\x58\x48\x60\x08\x49\xd2\x26\
-\xb4\x37\x4a\x14\x6d\x6d\x42\x42\x7f\x20\x68\xae\x31\x28\xff\x85\
-\x83\xd0\x90\x05\x0d\x6d\x0d\xd2\x2a\x89\x24\x48\xb8\x85\x49\x1a\
-\x48\x87\xd4\xca\x93\xbe\xd4\x69\x38\x39\x1c\xa8\x34\x1a\xa2\x7b\
-\xbb\x79\xb8\xaf\x87\xe7\x43\x0b\x2f\x6c\xad\x05\x23\x4b\x39\x4d\
-\x38\x5d\xe6\xdb\x80\x9b\xab\xd3\x7a\xaf\x96\x99\x65\x4c\xc9\xfb\
-\x97\xd9\xdc\x43\xb3\xef\x82\x3e\xaf\xc6\x2d\x4a\x9b\x33\xc7\x0d\
-\x03\x48\x25\xa3\x4e\x25\x86\x0d\x0d\xbc\x8e\x8e\xff\x28\x95\x3a\
-\x70\x08\x21\x01\x0e\xcb\xe5\x5a\xb6\x52\xd9\xfe\x12\x60\x73\xa6\
-\x62\x7f\xae\x3a\x15\xf5\xf8\x52\x00\x8d\x6e\x97\xc5\x40\xe0\x32\
-\x0b\xdb\x00\x3e\x9f\xf0\xa4\xd3\x33\x9b\x5e\xaf\x70\x01\xe4\xf3\
-\x9d\xb6\x1d\xf0\xd6\x67\x3d\xe4\x60\xfa\xc3\xb6\x0d\x03\xb7\x10\
-\xc3\xaa\xd8\xd9\x99\x3c\x49\x24\x3c\xab\x00\xdd\xae\xc2\x30\x1e\
-\xaf\xed\x80\xef\xe5\x4e\x26\xf5\x95\x58\x4c\x07\xa0\x50\x80\x60\
-\x10\xc4\x88\xd0\x48\xfd\x1a\x30\x72\x84\x62\x24\x12\x9b\xdf\xdd\
-\x3d\x33\x95\x12\x26\x7b\xda\x8f\x00\xe7\x42\x70\x1c\x8f\x07\x34\
-\x29\x97\x91\x12\xd0\x00\xfb\x9b\x7c\x0b\xd0\xc3\x61\x5a\xa1\x90\
-\x65\x06\x03\xcc\x4f\x5e\xec\xef\x97\xf8\xcf\x01\x4f\x4f\xd4\x25\
-\xbd\xea\x05\x4a\xb7\xee\xdb\xab\x3e\x17\x5a\xad\x89\xa0\xdb\x0d\
-\x40\x43\x08\x0d\xbf\xdf\xda\xbd\x52\x14\x8b\x26\x77\x4d\x2b\x5c\
-\x2a\xa1\x67\x32\x6c\xbc\x03\x17\xdb\x6e\x97\x68\x69\xf7\x4f\x00\
-\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82'
-
-def GetConflictIconData():
- return \
-'\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\
-\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\x00\x00\x00\x90\x91\x68\
-\x36\x00\x00\x00\x03\x73\x42\x49\x54\x08\x08\x08\xdb\xe1\x4f\xe0\
-\x00\x00\x02\x45\x49\x44\x41\x54\x28\x91\x6d\x92\x4f\x48\x9a\x71\
-\x18\xc7\x7f\xbe\xef\xab\xcd\xed\x95\xcd\x8c\x25\x83\xc0\x24\xa9\
-\xc3\x4a\x17\xce\xea\x96\x3b\xe4\x0e\x5d\xba\xce\xa8\x88\xe8\x20\
-\x1a\x15\x1d\x3a\x78\x09\xf2\xed\xcf\xe8\x32\x68\x45\x56\x93\x66\
-\x94\x78\x99\x53\x68\x4e\x1b\xe1\x61\x30\xc2\x19\x5b\x16\xac\x9c\
-\x76\x19\x92\x2e\x35\xa6\x7b\xf7\xda\xfb\x3e\x3b\xd8\x9c\x9b\x7e\
-\x8e\xdf\xdf\xf3\x81\xdf\xf3\x87\x07\x00\xe8\x0f\x99\xb3\xb3\xd0\
-\xca\xca\x17\x97\x2b\x75\x7a\x8a\xf1\xf9\x77\xea\xeb\xe5\x3a\xdd\
-\x83\xe1\xe1\x6a\x85\xa2\x58\xc3\x2b\x08\x5c\x3e\x1f\x98\x9a\xfa\
-\xb0\xb0\x80\xf3\xf9\x72\x9d\xae\x56\xa5\xe2\x58\x36\x13\x8b\x9d\
-\xb8\xdd\x3f\x2f\x2e\x1e\x8e\x8c\x3c\x9a\x9d\xc5\xab\xaa\x10\x42\
-\x08\x00\x38\x96\x75\xf6\xf4\x58\x78\xbc\x37\x46\x23\x9d\x4e\x43\
-\x09\x57\x34\xfd\x7e\x6e\x6e\x4e\x28\xb4\x6b\xb5\x2c\xc3\x00\x00\
-\x02\x80\x77\x93\x93\xd3\x08\x51\x04\x71\xec\x74\x42\x25\xbe\xfa\
-\x7c\xf3\x24\xb9\x63\x30\x00\x00\x4a\x45\x22\x33\x02\x81\xd7\x64\
-\x5a\x69\x6e\x9e\xe1\xf3\x8f\x1c\x8e\x8a\xce\xc7\xe5\x65\x0b\x86\
-\x7d\xdb\xdf\x47\xfe\x89\x89\xa7\x22\xd1\xaf\xcb\xcb\x6c\x22\x61\
-\x55\x2a\x29\x82\x08\x6f\x6d\x95\x0b\x1c\xcb\x3e\x57\x28\x3c\x43\
-\x43\x68\x5d\xa3\x71\x74\x77\x17\xd2\x5c\x32\x69\x55\xa9\x28\x82\
-\x38\xdc\xdc\x2c\x77\xbc\x26\xd3\xb3\xba\x3a\xec\xfb\xf1\xb1\xb8\
-\xa1\xa1\x30\x32\xa1\x44\xa2\xdf\xdd\xbd\xdb\xd2\xf2\xba\xbf\xff\
-\xd0\x6e\x47\xff\x22\x69\x6a\xfa\x11\x8f\x63\x1c\xcb\xb2\x0c\x53\
-\x4c\x85\xd5\xd5\x7a\xbf\xbf\x56\xa9\x74\x0f\x0c\x7c\xde\xd8\x28\
-\x15\x80\xe3\x80\xe3\xb0\xdb\x32\x59\x26\x1a\x2d\x7d\xb8\x21\x16\
-\x3f\xf1\xf9\xa4\xad\xad\x9e\xc1\xc1\x4f\x36\x5b\x31\x4f\x47\xa3\
-\xa4\x54\x8a\x7c\xe3\xe3\xf3\x24\x99\x4b\x26\xff\xfb\x31\x9d\x4a\
-\xad\x6b\x34\x14\x8e\x1f\xac\xad\x15\x9a\x5e\x6a\x6c\x74\xf5\xf5\
-\xa1\x44\x38\x4c\xe1\xf8\xdb\xd1\xd1\xf2\x2e\xe9\x74\xfa\x45\x7b\
-\xbb\x05\xc3\x42\x56\x6b\x70\x69\xc9\xc2\xe3\x9d\x05\x02\x08\x00\
-\x76\x0c\x06\x8a\x20\xc2\xdb\xdb\x15\x9c\x4c\xc6\xd6\xd1\x61\xc1\
-\xb0\x79\x92\x7c\xa5\xd7\x5f\x6f\x9a\x65\x98\x97\x9d\x9d\x14\x8e\
-\xef\x99\xcd\x57\x34\x5d\x2a\xb0\x0c\xb3\x67\x36\x4f\x23\xb4\xae\
-\x56\xe7\x73\x39\x00\xb8\x3e\xbe\x7c\x2e\xe7\x1b\x1b\x3b\x58\x5d\
-\xbd\x59\x53\x23\xef\xea\x2a\x0c\x3a\x13\x8b\x45\xbc\xde\x6c\x3c\
-\x7e\xbf\xb7\xf7\xf1\xe2\xa2\x40\x24\xfa\x7b\xad\x05\xe2\xc1\x60\
-\xc8\x6a\x3d\xf1\x78\xb2\xe7\xe7\x88\xe3\x6e\x49\xa5\x32\xad\x56\
-\x6d\x34\xde\x6b\x6b\x2b\xd6\xfc\x06\xb3\xcb\xb3\xdb\x2f\x3f\x31\
-\xa9\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82'
-
-#=============== help texts
-
-NewRealmButtonHelp = \
- "Use this button to add a new top-level REALM type. \n\n\
-You can refine an existing realm by right-clicking it \
-and selecting \"Add workload\" from the pop-up menu.\n\n<Ctrl>-h for help"
-
-RealmWorkloadPanelHelp = \
- "\
-Use this panel to define names for types of workloads that \
-shall be confined against each other.\n\n<Ctrl>-h for help"
-
-RunTimeExclusionPanelHelp = \
- "\
-The run-time exclusion rules restrict which workload types \
-can run simultaneously on the same platform. At most one \
-type in an exclusion rule can run. If a domain starts, its \
-workload type is looked up and if it is in any exclusion rule \
-of which another type is already running, then it is denied \
-to start.\n\n<Ctrl>-h for help"
-
-CreateRunTimeButtonHelp = \
- "\
-This button creates a new run-time exclusion rule using the \
-selection from the left side workload definition panel.\n\n<Ctrl>-h for help"
-
-AddToExclusionButtonHelp = \
- "\
-This button adds the current selection in the left side \
-workload definition panel to the associated exclusion rule.\n\n<Ctrl>-h for help"
-
-DelFromExclusionButtonHelp = \
- "\
-This button deletes the current selection of the associated \
-exclusion rule from the associated exclusion rule.\n\n<Ctrl>-h for help"
-
-ManageExclusionButtonHelp = \
- "\
-This button allows to rename or delete the associated exclusion \
-rule. Left-click the button for the menu.\n\n<Ctrl>-h for help"
-
-ExclusionSetHelp = \
- "\
-Of the workload types specified in an exclusion rule, \
-only one can run at a time on the same platform.\n\n<Ctrl>-h for help"
-
-GetHelp = \
- "\
-Use <CTRL>-h to open the help window. Use the context help on buttons."
-
-#================ html help page =================
-# for ez use included in a single file, one could also
-# optionally try to fetch the page from a public location
-import wx.html as html
-
-class HelpHtmlWindow(html.HtmlWindow):
- def __init__(self, parent, id):
- html.HtmlWindow.__init__(self, parent, id, style=wx.NO_FULL_REPAINT_ON_RESIZE)
- if "gtk2" in wx.PlatformInfo:
- self.SetStandardFonts()
- self.SetPage(helptext)
-
-helptext = """
-<HTML>
-<HEAD>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-<META name="GENERATOR" content="IBM WebSphere Studio Homepage Builder V6.0.2 for Windows">
-<META http-equiv="Content-Style-Type" content="text/css">
-<TITLE>Overview</TITLE>
-</HEAD>
-<BODY bgcolor="#dfdfdf" text="#000000">
-<H3><FONT color="#000000" face="Palatino Linotype">Creating A Xen Workload-Protection Security Policy</FONT></H3>
-<FONT face="Palatino Linotype">The purpose of this tool is to create a Xen security policy that understands
-the workload types that you want to confine against each other. For this
-purpose you enter the names of workload types that you want to assign to
-domains and resources. You can also define groups of workload types that
-should not run on the same system simultaneously for any reason; such groups
-are called Runtime Exclusion Sets. Please refer to the Xen User Guide for
-more information.<BR>
-<BR>
-This tool will create a unique security label for each workload type. Every
-domain and resource must be labeled so that the hypervisor system can correctly
-identify the associated workload type and control the sharing among domains
-in a way that keeps different workload types confined from each other.
-This tool ensures two things:<BR>
-<BR>
-1. The created security policy includes a distinctive label for each workload
-type defined in step 1 below. These labels must later be assigned to Domains
-and Resources to enable Xen to enforce the confinement.<BR>
-<BR>
-2. The created security policy includes access control rules that are enforced
-by the Xen Hypervisor (independently of the guest Domains) and guarantee
-that:</FONT>
-<BLOCKQUOTE><FONT face="Palatino Linotype">(i) Domains that are assigned the same workload type label can
-share (communicate,
-use common resources) without restriction through the hypervisor. Their
-interoperation can still be constraint by the domains (domain-internal
-means).</FONT></BLOCKQUOTE>
-<BLOCKQUOTE><FONT face="Palatino Linotype">(ii) Domains that are assigned different workload type labels cannot share,
-i.e., cannot communicate or use common resources. Independently enforced
-by the hypervisor, the domains cannot overrule this decision.</FONT></BLOCKQUOTE>
-<BLOCKQUOTE><FONT face="Palatino Linotype">(iii) Once a Domain labeled with a workload type of a Runtime Exclusion
-Rule is running, no other domain labeled with another workload type of
-the same Runtime Exclusion Rule can start. This holds for all Runtime Exclusion
-Rules.</FONT></BLOCKQUOTE>
-<FONT face="Palatino Linotype">While all workloads share common hardware resources, the core hypervisor
-isolation and virtualization in combination with the Xen access control
-policy ensure that, e.g., viruses in one workload type cannot infect other
-workload types and that secrets used within one workload type cannot leak
-into another workload type. Currently the Xen access control enforcement
-covers domains, local storage resources, and the local virtual network
-interfaces. Protecting sharing through the open network is subject of ongoing
-work; such protection must currently be setup manually using IP filtering
-rules in Domain0.
-<BR>
-</FONT>
-<H2><FONT color="#000000" face="Palatino Linotype">Step 1</FONT></H2>
-<FONT face="Palatino Linotype">The first step of creating a workload protection policy is to determine
-names for the different workload types. The left panel offers the means
-to define and and manage workload type definitions.<BR>
-<BR>
-A workload can be an organization name (coarse-grained type), e.g. a corporate
-realm such as IBM or PepsiCo. An organization can be refined to describe
-independent functional groupings within the organization, such as IBM.Financing
-or Pepsi.Payroll. Use the<B><I> &lt;New Org&gt;</I></B> button on the left panel
-to create a new organization workload. To refine such a workload, right-click the
-organization and chose <B><I>&lt;Add Department&gt;</I></B>. You can add multiple
-departments to an organization but you do not have to add any.<BR>
-<BR>
-This tool will create a separate label name for each organization and for
-each department workload. The policy will be computed so that there is
-no sharing between organizations or departments by default. IBM, IBM.Financing,
-Pepsi, and Pepsi.Payroll will by default not be able to share in this simple
-policy example. You can introduce controlled sharing by refining the policy,
-which is beyond the scope of this help.<BR>
-<BR>
-As an example, define the four organizations PepsiCo, CocaCola, Avis, Hertz.
-Define department workloads Payroll, HumanResources and Financing for Avis
-and CocaCola, and PepsiCo.<BR>
-</FONT>
-<H2><FONT color="#000000" face="Palatino Linotype">Step 2</FONT></H2>
-<FONT face="Palatino Linotype">In this second step, we enter those workload types that should not run
-simultaneously on the same hardware platform. There might be multiple reasons
-for this, e.g., imperfect resource control.<BR>
-<BR>
-As an example, we will create a policy that guarantees that PepsiCo workloads
-and CocaCola workloads never run simultaneously on the same platform: <BR>
-<BR>
-1. Select the PepsiCo organization on the left panel by left-clicking it..<BR>
-<BR>
-2. Press the &lt;Ctrl&gt;-Key and then select CocaCola organization by
-left-clicking it while keeping the &lt;Ctrl&gt;-Key pressed..<BR>
-<BR>
-3. Click the <B><I>&lt;Create run-time exclusion rule from selection&gt;</I></B>
-button and enter a name for this Run-time Exclusion rule (e.g., RER1). The name is
-for your reference only. It has no impact on the policy. On the right panel, a run-time
-exclusion rule with the chosen name appears. <BR>
-<BR>
-The interpretation of the rule is as follows: If a domain labeled PepsiCo
-is running, then another domain labeled CocaCola cannot start on the same
-system and the other way round. This also holds for departments of PepsiCo
-and CocaCola (organizations dominate their departments). If PepsiCo or
-PepsiCo.Payroll etc. are running, then a domain with label CocaCola or
-CocaCola.Payroll etc. cannot start. If you want to restrict concurrency
-between specific subtypes, then you must create a Run-time Exclusion rule
-that specifies the department workload types. To exclude only CocaCola.Payroll
-and PepsiCo.Payroll from running simultaneously the Run-time Exclusion
-rule must be formed using Coca.Cola.Payroll and PepsiCo.Payroll, not their
-organizations. Consequently it does not make sense to add both an organization
-and any of its departments to the same Run-time Exclusion rule because
-any department is already covered by its organization (this tool will not
-allow it).<BR>
-<BR>
-You can create multiple Run-time Exclusion rules, all of which will be
-enforced simultaneously by the hypervisor. You do not need to define any
-Run-time Exclusion rule if you do not find it necessary. You can add or
-delete workload types from Run-time Exclusion rules using the <B><I>&lt;Add&gt;</I></B>
-and <I><B>&lt;Del&gt;</B></I> buttons associated with the rule. The <I><B>&lt;Add&gt;</B></I>
-button adds the workload types selected in the left panel to the Run-time
-Exclusion rule. The <I><B>&lt;Del&gt;</B></I> button deletes the workload types selected
-in the associated Run-time Exclusion rule from the rule. <BR>
-</FONT>
-<H2><FONT color="#000000" face="Palatino Linotype">Step 3</FONT></H2>
-<FONT face="Palatino Linotype">Now that we have defined the workloads and Run-time Exclusion rules, we
-can save the workload definition for later reference or refinement. Select
-the <I><B>File-&gt;Save Workload
-Definition as..</B></I> menu entry and choose a file name.<BR>
-<BR>
-Please use the <B><I>File-&gt;Save as Xen ACM Security Policy..</I></B> menu entry and choose a policy
-name to create a Xen Workload Protection
-security policy from the current workload definition. To simplify the succeeding
-steps, please use a name of the form &quot;example.chwall_ste.NAME&quot;
-where you merely replace &quot;NAME&quot; with a policy name of your choice.
-Save the policy under the name proposed by the tool in the proposed directory
-if you are using this tool in your Xen environment. Otherwise, you need
-to copy the resulting file into your Xen environment to the directory
-&quot;/etc/xen/acm-security/policies/example/chwall_ste/&quot;.<BR>
-<BR>
-This tool creates policies for the Xen Chinese Wall and Simple Type Enforcement
-policy. The Xen access control policy in general is more expressive and
-this tool only uses a small subset of the possible configurations. <B><BR>
-<BR>
-Where to go from here.</B> <BR>
-<BR>
-Before the new policy can be activated, we need to translate the policy into a representation that
-Xen and the Xen-tools can work with. To this end, in your Xen environment, please issue the command
-<B><I>xm makepolicy example.chwall_ste.NAME</I></B> where NAME must be replaced by the name you chose
-for your policy in step 3 above. Then, we need to make the policy available to the Xen hypervisor. In
-your Xen environment, please issue the command <B><I>xm cfgbootpolicy example.chwall_ste.NAME</I></B>
-to install the policy for the next reboot. If the command cannot find the correct boot title, then you
-can manually install it as described in the xm man page.<BR>
-<BR>
-Finally, reboot your security-enabled Xen environment. Please refer to the xm man page for how to enable
-Xen security. After reboot, you can use <I><B>xm labels type=any</B></I> to list all the created workload l
-abels. Use the <I><B>xm addlabel</B></I> command to assign workload type labels to the associated domains
-and resources.<BR>
-<BR>
-From here, please check the Xen user guide.<BR>
-</FONT></BODY>
-</HTML>
-"""
-
-#=============== main =====
-
-def main():
- global app
- app = ezApp(0)
- if len(sys.argv) in [2]:
- app.Load(sys.argv[1])
- else:
- dict2org({'orgs' : [[ACM_LABEL_UNLABELED,[]]], 'cons': []})
- app.MainLoop()
- print "Goodbye"
-
-if __name__ == '__main__':
- main()
-
-#==== end of file
diff --git a/tools/security/xensec_gen.py b/tools/security/xensec_gen.py
deleted file mode 100644
index d531777660..0000000000
--- a/tools/security/xensec_gen.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License,
-# or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-import sys
-
-from xen.xensec_gen import main
-
-main.main( )
diff --git a/tools/xm-test/README b/tools/xm-test/README
index 405532c7fb..88c00836ed 100644
--- a/tools/xm-test/README
+++ b/tools/xm-test/README
@@ -137,38 +137,6 @@ Xm-test will look for disk.img in the ramdisk directory when run by
default.
-BUILDING for ACM Security Testing
-=================================
-
-A number of tests have been added to test the access control module (ACM)
-in the Xen hypervisor and the tools for supporting ACM. Those tests are
-located in the security-acm directory. If ACM support is compiled into Xen
-(see the user guide for how to do this) those tests can be run with the
-following command from the xm-test directory
-
-./runtest.sh [...] -g security <report>
-
-Some of these tests will work even without support of ACM by Xen.
-
-The xm test suite has been extended to support labeling of resources
-as required by the existing tests. However, by default the test suite
-is not allowed to automatically label resources since this may affect
-existing labels. To enable this, the test suite must be configured with
-the following parameter passed to the configure scripts (in addition to
-any other desired parameters)
-
-./configure --enable-full-labeling
-
-To revoke the privilege at a later time run the configure scripts without
-this parameter:
-
-./configure
-
-If a 'make' has previously been run for building the test suite, it is not
-necessary to run 'make' again just for enabling or disabling the automatic
-labeling of resources.
-
-
Running
=======
diff --git a/tools/xm-test/configure.ac b/tools/xm-test/configure.ac
index 40d93c41d7..ad1eb78391 100644
--- a/tools/xm-test/configure.ac
+++ b/tools/xm-test/configure.ac
@@ -41,20 +41,6 @@ fi
AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue)
AC_SUBST(ENABLE_HVM)
-AC_ARG_ENABLE(full-labeling,
- [[ --enable-full-labeling allows the test suite to label all resources]],
- [
- ENABLE_LABELING=True
- ],[
- ENABLE_LABELING=False
- ])
-
-if test "x$ENABLE_LABELING" = "xTrue"; then
- echo "ACM_LABEL_RESOURCES = True" > lib/XmTestLib/acm_config.py
-else
- rm -f lib/XmTestLib/acm_config.py*
-fi
-
# Network needs to know ips to use: dhcp or a range of IPs in the form
# of: 192.0.2.1-192.0.2.100
# If not dhcp, a netmask and network address must be supplied. Defaults to
@@ -151,7 +137,6 @@ AC_CONFIG_FILES([
tests/restore/Makefile
tests/save/Makefile
tests/sched-credit/Makefile
- tests/security-acm/Makefile
tests/sedf/Makefile
tests/shutdown/Makefile
tests/sysrq/Makefile
diff --git a/tools/xm-test/grouptest/default b/tools/xm-test/grouptest/default
index 1db6a73398..f0516b2949 100644
--- a/tools/xm-test/grouptest/default
+++ b/tools/xm-test/grouptest/default
@@ -22,7 +22,6 @@ reboot
restore
save
sched-credit
-security-acm
shutdown
sysrq
unpause
diff --git a/tools/xm-test/grouptest/security b/tools/xm-test/grouptest/security
deleted file mode 100644
index 4d5c8b941d..0000000000
--- a/tools/xm-test/grouptest/security
+++ /dev/null
@@ -1 +0,0 @@
-security-acm
diff --git a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
index 3c5310f061..1ca2307c27 100644
--- a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
+++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
@@ -23,7 +23,6 @@ import os
import sys
from XmTestLib import *
from types import DictType
-from acm import *
class XenAPIConfig:
@@ -40,9 +39,6 @@ class XenAPIConfig:
'ramdisk': 'PV_ramdisk',
'root' : 'PV_args',
'extra' : 'PV_args' }
- if isACMEnabled():
- #A default so every VM can start with ACM enabled
- self.opts["security_label"] = "ACM:xm-test:red"
def setOpt(self, name, value):
"""Set an option in the config"""
diff --git a/tools/xm-test/lib/XmTestLib/XenDomain.py b/tools/xm-test/lib/XmTestLib/XenDomain.py
index f15b6a00a7..ae8c550c48 100644
--- a/tools/xm-test/lib/XmTestLib/XenDomain.py
+++ b/tools/xm-test/lib/XmTestLib/XenDomain.py
@@ -30,7 +30,6 @@ from config import *
from Console import *
from XenDevice import *
from DomainTracking import *
-from acm import *
DOM0_UUID = "00000000-0000-0000-0000-000000000000"
@@ -61,9 +60,6 @@ class XenConfig:
self.defaultOpts["disk"] = []
self.defaultOpts["vif"] = []
self.defaultOpts["vtpm"] = []
- if isACMEnabled():
- #A default so every VM can start with ACM enabled
- self.defaultOpts["access_control"] = ['policy=xm-test,label=red']
self.opts = self.defaultOpts
@@ -91,7 +87,6 @@ class XenConfig:
output = file(filename, "w")
output.write(self.toString())
output.close()
- ACMPrepareSystem(self.opts)
def __str__(self):
"""When used as a string, we represent ourself by a config
diff --git a/tools/xm-test/lib/XmTestLib/acm.py b/tools/xm-test/lib/XmTestLib/acm.py
deleted file mode 100644
index f8a62f4991..0000000000
--- a/tools/xm-test/lib/XmTestLib/acm.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2006
- Author: Stefan Berger <stefanb@us.ibm.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; under version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-from Test import *
-import xen.util.xsm.xsm as security
-from xen.xm.main import server
-from xen.util import xsconstants
-import re
-
-try:
- from acm_config import *
-except:
- ACM_LABEL_RESOURCES = False
-
-labeled_resources = {}
-acm_verbose = False
-policy='xm-test'
-
-
-def isACMEnabled():
- return security.on()
-
-def setCurrentPolicy(plcy):
- global policy
- policy = plcy
-
-def ACMSetPolicy():
- cmd='xm dumppolicy | grep -E "^POLICY REFERENCE = ' + policy + '.$"'
- s, o = traceCommand(cmd)
- if o != "":
- return
- s, o = traceCommand("xm setpolicy ACM %s" % (policy))
- if s != 0:
- FAIL("Could not load the required policy '%s'.\n"
- "Start the system without any policy.\n%s" % \
- (policy, o))
-
-def ACMPrepareSystem(resources):
- if isACMEnabled():
- ACMSetPolicy()
- ACMLabelResources(resources)
-
-def ACMLabelResources(resources):
- for k, v in resources.items():
- if k == "disk":
- for vv in v:
- res = vv.split(',')[0]
- ACMLabelResource(res)
-
-# Applications may label resources explicitly by calling this function
-def ACMLabelResource(resource, label='red'):
- if not isACMEnabled():
- return
- if acm_verbose:
- print "labeling resource %s with label %s" % (resource, label)
- if not ACM_LABEL_RESOURCES:
- SKIP("Skipping test since not allowed to label resources in "
- "test suite")
- if not isACMResourceLabeled(resource):
- ACMUnlabelResource(resource)
- s, o = traceCommand("xm addlabel %s res %s" % (label, resource))
- if s != 0:
- FAIL("Could not add label to resource")
- else:
- labeled_resources["%s" % resource] = 1
-
-
-# Application may remove a label from a resource. It has to call this
-# function and must do so once a resource for re-labeling a resource
-def ACMUnlabelResource(resource):
- s, o = traceCommand("xm rmlabel res %s" % (resource))
- labeled_resources["%s" % resource] = 0
-
-
-def isACMResourceLabeled(resource):
- """ Check whether a resource has been labeled using this API
- and while running the application """
- try:
- if labeled_resources["%s" % resource] == 1:
- if acm_verbose:
- print "resource %s already labeled!" % resource
- return True
- except:
- return False
- return False
diff --git a/tools/xm-test/lib/XmTestLib/block_utils.py b/tools/xm-test/lib/XmTestLib/block_utils.py
index 58124c832a..c302efeb15 100644
--- a/tools/xm-test/lib/XmTestLib/block_utils.py
+++ b/tools/xm-test/lib/XmTestLib/block_utils.py
@@ -6,7 +6,6 @@
import time
from XmTestLib import *
-from acm import *
import xen.util.blkif
@@ -27,7 +26,6 @@ def get_state(domain, devname):
def block_attach(domain, phy, virt):
- ACMLabelResource(phy)
status, output = traceCommand("xm block-attach %s %s %s w" %
(domain.getName(), phy, virt))
if status != 0:
diff --git a/tools/xm-test/runtest.sh b/tools/xm-test/runtest.sh
index aee67dfa06..73d1a5c69d 100755
--- a/tools/xm-test/runtest.sh
+++ b/tools/xm-test/runtest.sh
@@ -221,12 +221,6 @@ run=yes
unsafe=no
GROUPENTERED=default
-#Prepare for usage with ACM
-if [ -d /etc/xen/acm-security/policies ]; then
- cp -f tests/security-acm/xm-test-security_policy.xml \
- /etc/xen/acm-security/policies
-fi
-
unset XM_MANAGED_DOMAINS
# Resolve options
diff --git a/tools/xm-test/tests/Makefile.am b/tools/xm-test/tests/Makefile.am
index d5b64ef6cb..8d673ed525 100644
--- a/tools/xm-test/tests/Makefile.am
+++ b/tools/xm-test/tests/Makefile.am
@@ -19,7 +19,6 @@ SUBDIRS = \
pause \
reboot \
sched-credit \
- security-acm \
sedf \
shutdown \
sysrq \
diff --git a/tools/xm-test/tests/security-acm/01_security-acm_basic.py b/tools/xm-test/tests/security-acm/01_security-acm_basic.py
deleted file mode 100644
index 7876c51d1b..0000000000
--- a/tools/xm-test/tests/security-acm/01_security-acm_basic.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-#
-# A couple of simple tests that test ACM security extensions
-# for the xm tool. The following xm subcommands are tested:
-#
-# - labels
-# - rmlabel
-# - addlabel
-# - getlabel
-# - resources
-
-from XmTestLib import *
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants
-import commands
-import os
-import re
-
-testpolicy = "xm-test"
-testlabel = "blue"
-vmconfigfile = "/tmp/xm-test.conf"
-testresource = "phy:ram0"
-
-if not isACMEnabled():
- SKIP("Not running this test since ACM not enabled.")
-
-status, output = traceCommand("xm labels %s" % (testpolicy))
-if status != 0:
- FAIL("'xm labels' failed with status %d.\n" % status)
-
-#Need to get a vm config file - just have it written to a file
-domain = XmTestDomain()
-domain.config.write(vmconfigfile)
-
-#Whatever label it might have - remove it
-status, output = traceCommand("xm rmlabel dom %s" %
- (vmconfigfile))
-
-status, output = traceCommand("xm addlabel %s dom %s %s" %
- (testlabel, vmconfigfile, testpolicy))
-if status != 0:
- FAIL("(1) 'xm addlabel' failed with status %d.\n" % status)
-
-status, output = traceCommand("xm getlabel dom %s" %
- (vmconfigfile))
-
-if status != 0:
- FAIL("'xm getlabel' failed with status %d, output:\n%s" %
- (status, output))
-if output != "policytype=%s,policy=%s,label=%s" % \
- (xsconstants.ACM_POLICY_ID, testpolicy, testlabel):
- FAIL("(1) Received unexpected output from 'xm getlabel dom': \n%s" %
- (output))
-
-
-status, output = traceCommand("xm rmlabel dom %s" %
- (vmconfigfile))
-
-if status != 0:
- FAIL("'xm rmlabel' failed with status %d, output: \n%s" %
- (status,output))
-if output != "":
- FAIL("Received unexpected output from 'xm rmlabel': \n%s" %
- (output))
-
-status, output = traceCommand("xm getlabel dom %s" %
- (vmconfigfile))
-
-if output != "Error: 'Domain not labeled'":
- FAIL("(2) Received unexpected output from 'xm getlabel dom': \n%s" %
- (output))
-
-#Whatever label the resource might have, remove it
-status, output = traceCommand("xm rmlabel res %s" %
- (testresource))
-if status != 0:
- FAIL("'xm rmlabel' on resource failed with status %d.\n" % status)
-
-status, output = traceCommand("xm addlabel %s res %s %s" %
- (testlabel, testresource, testpolicy))
-if status != 0:
- FAIL("(2) 'xm addlabel' on resource failed with status %d.\n" % status)
-
-status, output = traceCommand("xm getlabel res %s" % (testresource))
-
-if status != 0:
- FAIL("'xm getlabel' on resource failed with status %d, output:\n%s" %
- (status, output))
-if output != "%s:%s:%s" % (xsconstants.ACM_POLICY_ID,\
- testpolicy,testlabel):
- FAIL("Received unexpected output from 'xm getlabel res': \n%s" %
- (output))
-
-status, output = traceCommand("xm resources")
-
-if status != 0:
- print "status = %s" % str(status)
- FAIL("'xm resources' did not run properly")
-if not re.search(security.unify_resname(testresource), output):
- FAIL("'xm resources' did not show the tested resource '%s'." %
- testresource)
-
-status, output = traceCommand("xm rmlabel res %s" %
- (testresource))
-
-if status != 0:
- FAIL("'xm rmlabel' on resource failed with status %d, output: \n%s" %
- (status,output))
-if output != "":
- FAIL("Received unexpected output from 'xm rmlabel': \n%s" %
- (output))
-
-status, output = traceCommand("xm getlabel res %s" %
- (testresource))
-
-if output != "Error: 'Resource not labeled'":
- FAIL("Received unexpected output from 'xm getlabel res': \n%s" %
- (output))
diff --git a/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py b/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py
deleted file mode 100644
index 4aac09d2fc..0000000000
--- a/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-#
-# Simple test that starts two labeled domains; both domains should start
-#
-# The following xm subcommands are tested:
-# - dumppolicy
-# - labels
-
-from XmTestLib import *
-from acm_utils import *
-import commands
-import os
-
-testlabel1 = "green"
-testlabel2 = "red"
-
-status, output = traceCommand("xm labels")
-
-labels = ["SystemManagement", "blue", "red", "green"]
-for l in labels:
- if not re.search(l, output):
- FAIL("Label '%s' not found in current policy!", l)
-
-status, output = traceCommand("xm dumppolicy")
-if status != 0:
- FAIL("'xm dumppolicy' returned an error code.")
-lines = ["ssidref 0: 00 00 00 00",
- "ssidref 1: 01 00 00 00",
- "ssidref 2: 00 01 00 00",
- "ssidref 3: 00 00 01 00",
- "ssidref 4: 00 00 00 01"]
-for l in lines:
- if not re.search(l, output):
- FAIL("Could not find '%s' in output of 'xm dumppolicy'" % l)
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
-verbose = True
-domain1 = XmTestDomain(name="domain-%s" % testlabel1,
- extraConfig=config)
-
-try:
- domain1.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start 1st labeled test domain.")
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2)}
-
-domain2 = XmTestDomain(name="domain-%s" % testlabel2,
- extraConfig=config)
-
-try:
- domain2.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start 2nd labeled test domain.")
-
-domain2.destroy()
-domain1.destroy()
diff --git a/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py b/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py
deleted file mode 100644
index 4aef380de5..0000000000
--- a/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-#
-# A test that exercises the conflict set of the chinese wall policy.
-# Start a first domain and then a second one. The second one is
-# expected NOT to be starteable.
-
-from XmTestLib import *
-from acm_utils import *
-import commands
-import os
-
-testlabel1 = "blue"
-testlabel2 = "red"
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
-
-domain1 = XmTestDomain(name="domain-%s" % testlabel1,
- extraConfig=config)
-
-try:
- domain1.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start 1st labeled test domain")
-
-# Verify with xm dry-run
-status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
- "grep -v \"Dry Run\"")
-if status != 0:
- FAIL("'xm dry-run' failed")
-if not re.search("PERMITTED", output):
- FAIL("'xm dry-run' did not succeed.")
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2)}
-
-domain2 = XmTestDomain(name="domain-%s" % testlabel2,
- extraConfig=config)
-
-try:
- domain2.start(noConsole=True)
- # Should never get here!
- FAIL("Could start a domain in a conflict set - "
- "this should not be possible")
-except DomainError, e:
- #This is exactly what we want in this case
- status = 0
-
-# Verify with xm dry-run
-status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
- "grep -v \"Dry Run\"")
-if status != 0:
- FAIL("'xm dry-run' failed.")
-if not re.search("PERMITTED", output):
- FAIL("'xm dry-run' did not show that operation was permitted.")
-
-domain1.destroy()
diff --git a/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py b/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py
deleted file mode 100644
index 367016339f..0000000000
--- a/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-#
-# Simple test that starts two labeled domains using labeled resources each
-#
-
-from XmTestLib import *
-from acm_utils import *
-import commands
-import os
-
-testlabel1 = "green"
-resource1 = "phy:ram0"
-testlabel2 = "red"
-resource2 = "phy:/dev/ram1"
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1),
- "disk" :"%s,hda1,w" % (resource1)}
-domain1 = XmTestDomain(name="domain-%s" % testlabel1,
- extraConfig=config)
-
-# Explicity label the resource
-ACMLabelResource(resource1, testlabel1)
-
-try:
- domain1.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start 1st labeled test domain.")
-
-# Verify with xm dry-run
-status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
- "grep -v \"Dry Run\"")
-
-if status != 0:
- FAIL("'xm dry-run' failed")
-if not re.search("%s: PERMITTED" % resource1, output):
- FAIL("'xm dry-run' did not succeed.")
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2),
- "disk" :"%s,hda1,w" % (resource2)}
-
-domain2 = XmTestDomain(name="domain-%s" % testlabel2,
- extraConfig=config)
-
-# Explicity label the resource
-ACMLabelResource(resource2, testlabel2)
-
-try:
- domain2.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start 2nd labeled test domain.")
-
-# Verify with xm dry-run
-status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
- "grep -v \"Dry Run\"")
-
-if status != 0:
- FAIL("'xm dry-run' failed")
-if not re.search("%s: PERMITTED" % resource2, output):
- FAIL("'xm dry-run' did not succeed.")
-
-domain2.destroy()
-domain1.destroy()
diff --git a/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py b/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py
deleted file mode 100644
index 89c6b5974c..0000000000
--- a/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-#
-# A test that tries to start a domain using a resource that it is
-# not supposed to be able to use due to its labeling
-
-from XmTestLib import *
-from acm_utils import *
-import commands
-import os
-
-testlabel1 = "blue"
-resource1 = "phy:ram0"
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1),
- "disk" :"%s,hda1,w" % (resource1)}
-
-domain1 = XmTestDomain(name="domain-%s" % testlabel1,
- extraConfig=config)
-
-ACMLabelResource(resource1,"red")
-
-try:
- domain1.start(noConsole=True)
- # Should never get here
- FAIL("Could start domain with resource that it is not supposed to access.")
-except DomainError, e:
- #That's exactly what we want to have in this case
- dummy = 0
-
-# Verify via dry-run
-status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
- "grep -v \"Dry Run\"")
-if not re.search("%s: DENIED" %resource1, output):
- FAIL("'xm dry-run' did not show expected result that operation was NOT "
- "permitted: \n%s" % output)
diff --git a/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py b/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py
deleted file mode 100644
index 92b09e9e01..0000000000
--- a/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2005
-# Author: Stefan Berger <stefanb@us.ibm.com>
-# Based on block-create/01_block_attach_device_pos.py
-#
-# Create a domain and attach 2 resources to it. The first resource
-# should be attacheable, the 2nd one should not be due to the label it has.
-
-import re
-from XmTestLib import *
-from XmTestLib import block_utils
-from acm_utils import *
-
-testlabel1 = "blue"
-resource1 = "phy:ram1"
-resourcelabel1 = "blue"
-resource2 = "phy:/dev/ram0"
-resourcelabel2 = "red"
-
-if ENABLE_HVM_SUPPORT:
- SKIP("Block-attach not supported for HVM domains")
-
-# Create a domain (default XmTestDomain, with our ramdisk)
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
-
-domain = XmTestDomain(extraConfig=config)
-
-try:
- console = domain.start()
-except DomainError, e:
- FAIL(str(e))
-
-# Attach a console to it
-try:
- console.setHistorySaveCmds(value=True)
- # Run 'ls'
- run = console.runCmd("ls")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL(str(e))
-
-
-# Explicitly label the 1st resource
-ACMLabelResource(resource1, resourcelabel1)
-block_utils.block_attach(domain, resource1, "xvda1")
-
-try:
- run1 = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-#Explicitly label the 2nd resource
-ACMLabelResource(resource2, resourcelabel2)
-#Cannot call block_attach here since we legally may fail the command
-status, output = traceCommand("xm block-attach %s %s %s w" %
- (domain.getName(), resource2, "xvda2" ))
-
-for i in range(10):
- if block_utils.get_state(domain, "xvda2") == 4:
- break
- time.sleep(1)
-
-try:
- run2 = console.runCmd("cat /proc/partitions")
-except ConsoleError, e:
- FAIL(str(e))
-
-# Close the console
-domain.closeConsole()
-
-# Stop the domain (nice shutdown)
-domain.stop()
-
-if not re.search("xvda1",run1["output"]):
- FAIL("Labeled device 'xvda1' is not actually connected to the domU")
-
-if not re.search("xvda1",run2["output"]):
- FAIL("Labeled device 'xbvda1' has disappeared?!")
-
-if re.search("xvda2",run2["output"]):
- FAIL("Labeled device 'xvda2' is connected to the domU but should not be")
diff --git a/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py b/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py
deleted file mode 100644
index a9e19a2153..0000000000
--- a/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py
+++ /dev/null
@@ -1,313 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-
-# Test to exercise the xspolicy class
-
-from XmTestLib import xapi
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-from XmTestLib import *
-from xen.xend import XendAPIConstants
-import xen.util.xsm.xsm as security
-from xen.util import acmpolicy, xsconstants
-from xen.util.acmpolicy import ACMPolicy
-from xen.xend.XendDomain import DOM0_UUID
-from XmTestLib.acm import *
-
-import commands
-import os
-import base64
-
-if not isACMEnabled():
- SKIP("Not running this test since ACM not enabled.")
-
-try:
- session = xapi.connect()
-except:
- SKIP("Skipping this test since xm is not using the Xen-API.")
-
-xm_test = {}
-xm_test['policyname'] = "xm-test"
-xm_test['date'] = "Fri Sep 29 14:44:38 2006"
-xm_test['url'] = None
-
-vm_label_red = "%s:xm-test:red" % xsconstants.ACM_POLICY_ID
-vm_label_green = "%s:xm-test:green" % xsconstants.ACM_POLICY_ID
-vm_label_blue = "%s:xm-test:blue" % xsconstants.ACM_POLICY_ID
-vm_label_sys = "%s:xm-test:SystemManagement" % xsconstants.ACM_POLICY_ID
-
-vm_label_black = "%s:xm-test:black"
-
-session = xapi.connect()
-
-oldlabel = session.xenapi.VM.get_security_label(DOM0_UUID)
-
-ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_sys,
- oldlabel)
-if int(ssidref) <= 0 or int(ssidref) != 0x00010001:
- FAIL("(0) Domain-0 label for '%s' has unexpected failure: %08x" %
- (vm_label_sys, int(ssidref)))
-print "ssidref for '%s' is 0x%08x" % (vm_label_sys, int(ssidref))
-
-
-xstype = session.xenapi.XSPolicy.get_xstype()
-if int(xstype) & xsconstants.XS_POLICY_ACM == 0:
- SKIP("ACM not enabled/compiled in Xen")
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-if not policystate.has_key('xs_ref'):
- FAIL("get_xspolicy must return member 'xs_ref'")
-
-xs_ref = policystate['xs_ref']
-if xs_ref != "":
- origpolicyxml = session.xenapi.ACMPolicy.get_xml(xs_ref)
-else:
- origpolicyxml = ""
-
-f = open("xm-test-security_policy.xml", 'r')
-if f:
- newpolicyxml = f.read()
- f.close()
-else:
- FAIL("Could not read 'xm-test' policy")
-
-try:
- os.unlink("/boot/xm-test.bin")
-except:
- pass
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-
-if int(policystate['type']) == 0:
- policystate = session.xenapi.XSPolicy.set_xspolicy(
- xsconstants.XS_POLICY_ACM,
- newpolicyxml,
- xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT,
- 1)
- if int(policystate['flags']) == -1:
- FAIL("Could not set the new policy.")
-
-print "state of policy = %s " % policystate
-
-rc = session.xenapi.XSPolicy.activate_xspolicy(
- policystate['xs_ref'],
- xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT)
-if int(rc) != xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT:
- FAIL("Could not activate the current policy: rc = %08x" % int(rc))
-
-if not os.path.exists("/boot/xm-test.bin"):
- FAIL("Binary policy was not installed. Check grub config file.")
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-
-if int(policystate['flags']) != xsconstants.XS_INST_BOOT | \
- xsconstants.XS_INST_LOAD:
- FAIL("Flags (%x) are not indicating the correct state of the policy.",
- int(policystate['flags']))
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-xs_ref = policystate['xs_ref']
-
-newpolicyxml = None
-f = open("xm-test-new-security_policy.xml", 'r')
-if f:
- newpolicyxml = f.read()
- f.close()
-else:
- FAIL("Could not read 'xm-test-new' policy")
-
-cur_acmpol = ACMPolicy(xml = policystate['repr'])
-new_acmpol = ACMPolicy(xml = newpolicyxml)
-
-new_acmpol.update_frompolicy(cur_acmpol)
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- new_acmpol.toxml(),
- xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT,
- 1)
-
-f = open("xm-test-security_policy.xml", 'r')
-if f:
- newpolicyxml = f.read()
- f.close()
-else:
- FAIL("Could not read 'xm-test-new' policy")
-
-cur_acmpol = new_acmpol
-new_acmpol = ACMPolicy(xml = newpolicyxml)
-
-new_acmpol.update_frompolicy(cur_acmpol)
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- new_acmpol.toxml(),
- xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT,
- 1)
-
-dom0_lab = session.xenapi.VM.get_security_label(DOM0_UUID)
-
-ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_sys, dom0_lab)
-if int(ssidref) <= 0 or int(ssidref) != 0x00010001:
- FAIL("(1) Domain-0 label for '%s' has unexpected failure: %08x" %
- (vm_label_sys, int(ssidref)))
-print "ssidref for '%s' is 0x%08x" % (vm_label_sys, int(ssidref))
-
-try:
- ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_black,
- vm_label_sys)
- FAIL("Could set label '%s', although it's not in the policy. "
- "ssidref=%s" % (vm_label_black, ssidref))
-except:
- pass
-
-ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_red,
- vm_label_sys)
-if int(ssidref) <= 0:
- FAIL("(2) Domain-0 label for '%s' has unexpected failure: %08x" %
- (vm_label_red, int(ssidref)))
-print "ssidref for '%s' is 0x%08x" % (vm_label_red, int(ssidref))
-
-label = session.xenapi.VM.get_security_label(DOM0_UUID)
-
-if label != vm_label_red:
- FAIL("Dom0 label '%s' not as expected '%s'" % (label, vm_label_red))
-
-
-ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_sys,
- vm_label_red)
-if int(ssidref) <= 0 or int(ssidref) != 0x00010001:
- FAIL("(3) Domain-0 label for '%s' has unexpected failure: %08x" %
- (vm_label_sys, int(ssidref)))
-
-label = session.xenapi.VM.get_security_label(DOM0_UUID)
-
-if label != vm_label_sys:
- FAIL("Dom0 label '%s' not as expected '%s'" % label, dom0_label)
-
-header = session.xenapi.ACMPolicy.get_header(xs_ref)
-
-if header['policyname'] != xm_test['policyname']:
- FAIL("Name in header is '%s', expected is '%s'." %
- (header['policyname'],xm_test['policyname']))
-if header['date'] != xm_test['date']:
- FAIL("Date in header is '%s', expected is '%s'." %
- (header['date'],xm_test['date']))
-if header.has_key("url") and header['url' ] != xm_test['url' ]:
- FAIL("URL in header is '%s', expected is '%s'." %
- (header['url' ],xm_test['url' ]))
-
-# Create another domain
-try:
- # XmTestAPIDomain tries to establish a connection to XenD
- domain = XmTestAPIDomain(extraConfig={ 'security_label' : vm_label_blue })
-except Exception, e:
- SKIP("Skipping test. Error: %s" % str(e))
-
-
-vm_uuid = domain.get_uuid()
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != vm_label_blue:
- FAIL("VM has security label '%s', expected is '%s'" %
- (res, vm_label_blue))
-
-try:
- domain.start(noConsole=True)
-except:
- FAIL("Could not create domain")
-
-
-# Attempt to relabel the running domain
-ssidref = session.xenapi.VM.set_security_label(vm_uuid,
- vm_label_red,
- vm_label_blue)
-if int(ssidref) <= 0:
- FAIL("Could not relabel running domain to '%s'." % vm_label_red)
-
-# user domain is 'red', dom0 is current 'SystemManagement'.
-# Try to move domain-0 to 'red' first, then to 'blue'.
-
-# Moving domain-0 to 'red' should work
-ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_red,
- vm_label_sys)
-if int(ssidref) <= 0:
- FAIL("Could not label domain-0 '%s'" % vm_label_red)
-
-# Moving the guest domain to 'blue' should not work due to conflict set
-try:
- ssidref = session.xenapi.VM.set_security_label(vm_uuid,
- vm_label_blue,
- vm_label_red)
- FAIL("Could label guest domain with '%s', although this is in a conflict "
- "set. ssidref=%x" % (vm_label_blue,int(ssidref)))
-except:
- pass
-
-label = session.xenapi.VM.get_security_label(vm_uuid)
-if label != vm_label_red:
- FAIL("User domain has wrong label '%s', expected '%s'." %
- (label, vm_label_red))
-
-label = session.xenapi.VM.get_security_label(DOM0_UUID)
-if label != vm_label_red:
- FAIL("Domain-0 has wrong label '%s'; expected '%s'." %
- (label, vm_label_red))
-
-ssidref = session.xenapi.VM.set_security_label(DOM0_UUID,
- vm_label_sys,
- vm_label_red)
-if int(ssidref) < 0:
- FAIL("Could not set the domain-0 security label to '%s'." %
- (vm_label_sys))
-
-# pause the domain and relabel it...
-session.xenapi.VM.pause(vm_uuid)
-
-label = session.xenapi.VM.get_security_label(vm_uuid)
-if label != vm_label_red:
- FAIL("User domain has wrong label '%s', expected '%s'." %
- (label, vm_label_red))
-
-ssidref = session.xenapi.VM.set_security_label(vm_uuid,
- vm_label_blue,
- vm_label_red)
-print "guest domain new label '%s'; ssidref is 0x%08x" % \
- (vm_label_blue, int(ssidref))
-if int(ssidref) <= 0:
- FAIL("Could not label guest domain with '%s'" % (vm_label_blue))
-
-label = session.xenapi.VM.get_security_label(vm_uuid)
-if label != vm_label_blue:
- FAIL("User domain has wrong label '%s', expected '%s'." %
- (label, vm_label_blue))
-
-session.xenapi.VM.unpause(vm_uuid)
-
-rc = session.xenapi.VM.suspend(vm_uuid)
-
-ssidref = session.xenapi.VM.set_security_label(vm_uuid,
- vm_label_green,
- vm_label_blue)
-print "guest domain new label '%s'; ssidref is 0x%08x" % \
- (vm_label_green, int(ssidref))
-if int(ssidref) < 0:
- FAIL("Could not label suspended guest domain with '%s'" % (vm_label_blue))
-
-label = session.xenapi.VM.get_security_label(vm_uuid)
-if label != vm_label_green:
- FAIL("User domain has wrong label '%s', expected '%s'." %
- (label, vm_label_green))
-
-
-rc = session.xenapi.VM.resume(vm_uuid, False)
-
-label = session.xenapi.VM.get_security_label(vm_uuid)
-if label != vm_label_green:
- FAIL("User domain has wrong label '%s', expected '%s'." %
- (label, vm_label_green))
diff --git a/tools/xm-test/tests/security-acm/08_security-acm_xapi.py b/tools/xm-test/tests/security-acm/08_security-acm_xapi.py
deleted file mode 100644
index 469bf35a91..0000000000
--- a/tools/xm-test/tests/security-acm/08_security-acm_xapi.py
+++ /dev/null
@@ -1,358 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2007
-# Author: Stefan Berger <stefanb@us.ibm.com>
-
-# VM creation test with labeled VM and labeled VDI
-
-from XmTestLib import xapi
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-from XmTestLib import *
-from xen.xend import XendAPIConstants
-import xen.util.xsm.xsm as security
-from xen.util import acmpolicy, xsconstants
-import commands
-import os
-
-vm_label_red = xsconstants.ACM_POLICY_ID + ":xm-test:red"
-vm_label_green = xsconstants.ACM_POLICY_ID + ":xm-test:green"
-vdi_label_red = xsconstants.ACM_POLICY_ID + ":xm-test:red"
-vdi_label_green = xsconstants.ACM_POLICY_ID + ":xm-test:green"
-
-vm_label_unlabeled = xsconstants.ACM_POLICY_ID + ":xm-test:" + \
- acmpolicy.ACM_LABEL_UNLABELED
-
-vdi_file = "/dev/ram0"
-vdi_path = "phy:" + vdi_file
-
-#Note:
-# If during the suspend/resume operations 'red' instead of 'green' is
-# used, the Chinese Wall policy goes into effect and disallows the
-# suspended VM from being resumed...
-
-try:
- # XmTestAPIDomain tries to establish a connection to XenD
- domain = XmTestAPIDomain(extraConfig={ 'security_label' : vm_label_red })
-except Exception, e:
- SKIP("Skipping test. Error: %s" % str(e))
-
-vm_uuid = domain.get_uuid()
-
-session = xapi.connect()
-xstype = session.xenapi.XSPolicy.get_xstype()
-if int(xstype) & xsconstants.XS_POLICY_ACM == 0:
- SKIP("ACM not enabled/compiled in Xen")
-
-f = open("xm-test-security_policy.xml", 'r')
-if f:
- newpolicyxml = f.read()
- f.close()
-else:
- FAIL("Could not read 'xm-test' policy")
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-if int(policystate['type']) == 0:
- policystate = session.xenapi.XSPolicy.set_xspolicy(
- xsconstants.XS_POLICY_ACM,
- newpolicyxml,
- xsconstants.XS_INST_BOOT | xsconstants.XS_INST_LOAD,
- True)
- if int(policystate['flags']) == -1:
- FAIL("Could not set the new policy.")
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-print "policystate = %s" % policystate
-acm_ref = policystate['xs_ref']
-
-
-#
-# Some tests with labeling of resources
-#
-labels = session.xenapi.XSPolicy.get_labeled_resources()
-print "labeled resources are:\n%s" % labels
-
-oldlabel = session.xenapi.XSPolicy.get_resource_label("phy:/dev/ram0")
-
-rc = session.xenapi.XSPolicy.set_resource_label("phy:/dev/ram0", "",
- oldlabel)
-
-rc = session.xenapi.XSPolicy.set_resource_label("phy:/dev/ram0",
- vdi_label_green,
- "")
-
-res = session.xenapi.XSPolicy.get_resource_label("phy:/dev/ram0")
-if res != vdi_label_green:
- FAIL("(1) get_resource_label returned unexpected result %s, wanted %s" %
- (res, vdi_label_green))
-
-
-#
-# Some test with labeling of VMs
-#
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-
-if res != vm_label_red:
- FAIL("VM.get_security_label returned wrong security label '%s'." % res)
-
-res = session.xenapi.VM.set_security_label(vm_uuid, vm_label_green,
- vm_label_red)
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != vm_label_green:
- FAIL("VM does not show expected label '%s' but '%s'." %
- (vm_label_green, res))
-
-res = session.xenapi.VM.set_security_label(vm_uuid, "", vm_label_green)
-if int(res) != 0:
- FAIL("Should be able to unlabel the domain while it's halted.")
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != vm_label_unlabeled:
- FAIL("Unexpected VM security label after removal: %s" % res)
-
-res = session.xenapi.VM.set_security_label(vm_uuid, vm_label_red, res)
-if int(res) != 0:
- FAIL("Could not label the VM to '%s'" % vm_label_red)
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != vm_label_red:
- FAIL("VM has wrong label '%s', expected '%s'." % (res, vm_label_red))
-
-sr_uuid = session.xenapi.SR.get_by_name_label("Local")
-if len(sr_uuid) == 0:
- FAIL("Could not get a handle on SR 'Local'")
-
-
-vdi_rec = { 'name_label' : "My disk",
- 'SR' : sr_uuid[0],
- 'virtual_size': 0,
- 'sector_size' : 512,
- 'parent' : '',
- 'SR_name' : 'Local',
- 'type' : 'system',
- 'shareable' : False,
- 'read-only' : False,
- 'other_config': {'location': vdi_path}
-}
-
-vdi_ref = session.xenapi.VDI.create(vdi_rec)
-
-res = session.xenapi.VDI.get_name_label(vdi_ref)
-if res != vdi_rec['name_label']:
- print "Destroying VDI now"
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VDI_get_name_label return wrong information")
-
-res = session.xenapi.VDI.get_record(vdi_ref)
-print "vdi_record : %s" % res
-
-oldlabel = session.xenapi.XSPolicy.get_resource_label(vdi_path)
-
-#Remove label from VDI device
-rc = session.xenapi.XSPolicy.set_resource_label(vdi_path,
- "",
- oldlabel)
-
-
-# Attach a VBD to the VM
-
-vbd_rec = { 'VM' : vm_uuid,
- 'VDI' : vdi_ref,
- 'device' : "xvda1",
- 'mode' : 1,
- 'bootable': 0,
-}
-
-vbd_ref = session.xenapi.VBD.create(vbd_rec)
-
-res = session.xenapi.VBD.get_record(vbd_ref)
-
-try:
- domain.start(noConsole=True)
- # Should not get here.
- print "Destroying VDI now"
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could start VM with a VBD that it is not allowed to access.")
-except:
- pass
- print "Could not create domain -- that's good"
-
-
-#
-# Label the VDI now
-#
-
-rc = session.xenapi.VDI.set_security_label(vdi_ref, vdi_label_red, "")
-if int(rc) != 0:
- FAIL("Could not set the VDI label to '%s'" % vdi_label_red)
-
-label = session.xenapi.VDI.get_security_label(vdi_ref)
-if label != vdi_label_red:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Unexpected label '%s' on VDI, wanted '%s'" %
- (label, vdi_label_red))
-
-rc = session.xenapi.VDI.set_security_label(vdi_ref, "", label)
-if int(rc) != 0:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Should be able to unlabel VDI.")
-
-rc = session.xenapi.VDI.set_security_label(vdi_ref, vdi_label_red, "")
-if int(rc) != 0:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Should be able to label VDI with label '%s'" % vid_label_red)
-
-res = session.xenapi.XSPolicy.get_resource_label(vdi_path)
-if res != vdi_label_red:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("(2) get_resource_label on %s returned unexpected result %s, wanted '%s'" %
- (vdi_path, res, vdi_label_red))
-
-res = session.xenapi.VDI.get_security_label(vdi_ref)
-if res != vdi_label_red:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("get_security_label returned unexpected result %s, wanted '%s'" %
- (res, vdi_label_red))
-
-domain.start(noConsole=True)
-
-console = domain.getConsole()
-
-domName = domain.getName()
-
-try:
- run = console.runCmd("cat /proc/interrupts")
-except ConsoleError, e:
- saveLog(console.getHistory())
- FAIL("Could not access proc-filesystem")
-
-# Try to relabel while VM is running
-try:
- res = session.xenapi.VM.set_security_label(vm_uuid, vm_label_green,
- vm_label_red)
-except:
- pass
-
-lab = session.xenapi.VM.get_security_label(vm_uuid)
-if lab == vm_label_green:
- FAIL("Should not be able to reset the security label while running."
- "tried to set to %s, got %s, old: %s" %(vm_label_green, lab,
- vm_label_red))
-
-
-#
-# Suspend the domain and relabel it
-#
-
-try:
- status, output = traceCommand("xm suspend %s" % domName,
- timeout=30)
-except TimeoutError, e:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Failure from suspending VM: %s." % str(e))
-
-# Try to relabel while VM is suspended -- this should work
-
-rc = session.xenapi.VM.set_security_label(vm_uuid, vm_label_green,
- vm_label_red)
-if int(rc) != 0:
- FAIL("VM security label could not be set to %s" % vm_label_green)
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != vm_label_green:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VM (suspended) has label '%s', expected '%s'." %
- (res, vm_label_green))
-
-status, output = traceCommand("xm list")
-
-#Try to resume now -- should fail due to denied access to block device
-try:
- status, output = traceCommand("xm resume %s" % domName,
- timeout=30)
- if status == 0:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could resume re-labeled VM: %s" % output)
-except Exception, e:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("1. Error resuming the VM: %s." % str(e))
-
-# Relabel VM so it would resume
-res = session.xenapi.VM.set_security_label(vm_uuid, vm_label_red,
- vm_label_green)
-if int(res) != 0:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could not relabel VM to have it resume.")
-
-res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != vm_label_red:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("VM (suspended) has label '%s', expected '%s'." %
- (res, vm_label_red))
-
-
-# Relabel the resource so VM should not resume
-try:
- session.xenapi.XSPolicy.set_resource_label(vdi_path,
- vdi_label_green,
- "")
-except Exception, e:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could not label the VDI to '%s': %x" %
- (vdi_label_green, int(rc)))
-
-#Try to resume now -- should fail due to denied access to block device
-try:
- status, output = traceCommand("xm resume %s" % domName,
- timeout=30)
- if status == 0:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could resume re-labeled VM: %s" % output)
-except Exception, e:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("2. Error resuming the VM: %s." % str(e))
-
-
-status, output = traceCommand("xm list")
-
-# Relabel the resource so VM can resume
-try:
- session.xenapi.XSPolicy.set_resource_label(vdi_path,
- vdi_label_red,
- vdi_label_green)
-except Exception, e:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could not label the resource to '%s'" % vid_label_red)
-
-res = session.xenapi.XSPolicy.get_resource_label(vdi_path)
-if res != vdi_label_red:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("'%s' has label '%s', expected '%s'." %
- (vdi_path, res, vdi_label_red))
-
-#Try to resume now -- should work
-try:
- status, output = traceCommand("xm resume %s" % domName,
- timeout=30)
- if status != 0:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could not resume re-labeled VM: %s" % output)
-except Exception, e:
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("3. Error resuming the VM: %s." % str(e))
-
-
-status, output = traceCommand("xm list")
-
-console = domain.getConsole()
-
-try:
- run = console.runCmd("cat /proc/interrupts")
-except ConsoleError, e:
- saveLog(console.getHistory())
- session.xenapi.VDI.destroy(vdi_ref)
- FAIL("Could not access proc-filesystem")
-
-domain.stop()
-domain.destroy()
diff --git a/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py b/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py
deleted file mode 100644
index cc53baf2b9..0000000000
--- a/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2007
-# Author: Stefan Berger <stefanb@us.ibm.com>
-
-# Test to exercise the xspolicy and acmpolicy classes
-
-from XmTestLib import xapi
-from XmTestLib.XenAPIDomain import XmTestAPIDomain
-from XmTestLib.acm import *
-from XmTestLib import *
-from xen.xend import XendAPIConstants
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants
-from xen.util.acmpolicy import ACMPolicy
-from xen.xend.XendDomain import DOM0_UUID
-import base64
-import struct
-import time
-
-if not isACMEnabled():
- SKIP("Not running this test since ACM not enabled.")
-
-try:
- session = xapi.connect()
-except:
- SKIP("Skipping this test since xm is not using the Xen-API.")
-
-def typestoxml(types):
- res = ""
- for t in types:
- res += "<Type>" + t + "</Type>\n"
- return res
-
-def cfstoxml(cfss):
- res = ""
- for cfs in cfss:
- res += "<Conflict name=\"" + cfs['name'] + "\">\n" + \
- typestoxml(cfs['chws']) + \
- "</Conflict>\n"
- return res
-
-def vmlabelstoxml(vmlabels, vmfrommap):
- res = ""
- for vmlabel in vmlabels:
- res += "<VirtualMachineLabel>\n"
- if vmlabel['name'] in vmfrommap:
- res += "<Name from=\""+ vmfrommap[vmlabel['name']] +"\">"
- else:
- res += "<Name>"
- res += vmlabel['name'] + "</Name>\n"
- res += "<SimpleTypeEnforcementTypes>\n" + \
- typestoxml(vmlabel['stes']) + \
- "</SimpleTypeEnforcementTypes>\n"
- if vmlabel.has_key('chws'):
- res += "<ChineseWallTypes>\n" + \
- typestoxml(vmlabel['chws']) + \
- "</ChineseWallTypes>\n"
- res += "</VirtualMachineLabel>\n"
- return res
-
-
-def reslabelstoxml(reslabels, resfrommap):
- res = ""
- for reslabel in reslabels:
- res += "<ResourceLabel>\n"
- if resfrommap.has_key(reslabel['name']):
- res += "<Name from=\""+ resfrommap[reslabel['name']] +"\">"
- else:
- res += "<Name>"
- res += reslabel['name'] + "</Name>\n"
- res += "<SimpleTypeEnforcementTypes>\n" + \
- typestoxml(reslabel['stes']) + \
- "</SimpleTypeEnforcementTypes>\n"
- res += "</ResourceLabel>\n"
- return res
-
-def create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss):
- hdr_xml ="<PolicyHeader>\n" + \
- " <PolicyName>" + hdr['name'] + "</PolicyName>\n" + \
- " <Version>" + hdr['version'] + "</Version>\n" + \
- " <FromPolicy>\n" + \
- " <PolicyName>" + hdr['oldname'] + "</PolicyName>\n" + \
- " <Version>" + hdr['oldversion'] + "</Version>\n" + \
- " </FromPolicy>\n" + \
- "</PolicyHeader>\n"
-
- stes_xml = "<SimpleTypeEnforcement>\n" + \
- " <SimpleTypeEnforcementTypes>\n" + \
- typestoxml(stes) + \
- " </SimpleTypeEnforcementTypes>\n" + \
- "</SimpleTypeEnforcement>\n"
-
- chws_xml = "<ChineseWall>\n" + \
- " <ChineseWallTypes>\n" + \
- typestoxml(chws) + \
- " </ChineseWallTypes>\n" + \
- " <ConflictSets>\n" + \
- cfstoxml(cfss) + \
- " </ConflictSets>\n" + \
- "</ChineseWall>\n"
-
- subjlabel_xml = "<SubjectLabels bootstrap=\""+ bootstrap +"\">\n" + \
- vmlabelstoxml(vmlabels, vmfrommap) + \
- "</SubjectLabels>\n"
- objlabel_xml = "<ObjectLabels>\n" + \
- reslabelstoxml(reslabels, resfrommap) + \
- "</ObjectLabels>\n"
-
- policyxml = "<?xml version=\"1.0\" ?>\n" + \
- "<SecurityPolicyDefinition xmlns=\"http://www.ibm.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.ibm.com ../../security_policy.xsd \">\n" + \
- hdr_xml + \
- stes_xml + \
- chws_xml + \
- "<SecurityLabelTemplate>\n" + \
- subjlabel_xml + \
- objlabel_xml + \
- "</SecurityLabelTemplate>\n" + \
- "</SecurityPolicyDefinition>\n"
- return policyxml
-
-
-def update_hdr(hdr):
- """ Update the version information in the header """
- hdr['oldversion'] = hdr['version']
- hdr['oldname'] = hdr['name']
- vers = hdr['version']
- tmp = vers.split('.')
- if len(tmp) == 1:
- rev = 1
- else:
- rev = int(tmp[1]) + 1
- hdr['version'] = "%s.%s" % (tmp[0],rev)
- return hdr
-
-session = xapi.connect()
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-
-if policystate['repr'] != "":
- print "%s" % policystate['repr']
- try:
- acmpol = ACMPolicy(xml=policystate['repr'])
- except Exception, e:
- FAIL("Failure from creating ACMPolicy object: %s" % str(e))
- oldname = acmpol.policy_dom_get_hdr_item("PolicyName")
- oldvers = acmpol.policy_dom_get_hdr_item("Version")
- tmp = oldvers.split(".")
- if len(tmp) == 1:
- rev = 1
- else:
- rev = int(tmp[1]) + 1
- newvers = "%s.%s" % (tmp[0], str(rev))
- print "old name/version = %s/%s" % (oldname, oldvers)
-else:
- oldname = None
- oldvers = None
- newvers = "1.0"
-
-# Initialize the header of the policy
-hdr = {}
-hdr['name'] = "xm-test"
-hdr['version'] = newvers
-
-if oldname:
- hdr['oldname'] = oldname
- if oldvers and oldvers != "":
- hdr['oldversion'] = oldvers
-
-stes = [ "SystemManagement", "red", "green", "blue" ]
-
-chws = [ "SystemManagement", "red", "green", "blue" ]
-
-bootstrap = "SystemManagement"
-
-vm_sysmgt = { 'name' : bootstrap,
- 'stes' : stes,
- 'chws' : [ "SystemManagement" ] }
-
-vm_red = { 'name' : "red" ,
- 'stes' : ["red"] ,
- 'chws' : ["red"] }
-
-vm_green = { 'name' : "green" ,
- 'stes' : ["green"] ,
- 'chws' : ["green"] }
-
-vm_blue = { 'name' : "blue" ,
- 'stes' : ["blue"] ,
- 'chws' : ["blue"] }
-
-res_red = { 'name' : "red" ,
- 'stes' : ["red"] }
-
-res_green = { 'name' : "green" ,
- 'stes' : ["green"] }
-
-res_blue = { 'name' : "blue" ,
- 'stes' : ["blue"] }
-
-cfs_1 = { 'name' : "CFS1",
- 'chws' : [ "red" , "blue" ] }
-
-vmlabels = [ vm_sysmgt, vm_red, vm_green, vm_blue ]
-vmfrommap = {}
-reslabels = [ res_red, res_green, res_blue ]
-resfrommap = {}
-cfss = [ cfs_1 ]
-
-vm_label_red = xsconstants.ACM_POLICY_ID + ":xm-test:red"
-vm_label_green = xsconstants.ACM_POLICY_ID + ":xm-test:green"
-vm_label_blue = xsconstants.ACM_POLICY_ID + ":xm-test:blue"
-
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-
-xml_good = xml
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-
-print "\n\npolicystate = %s" % policystate
-
-policystate = session.xenapi.XSPolicy.get_xspolicy()
-
-#
-# Create two non-conflicting domains and start them
-#
-try:
- # XmTestAPIDomain tries to establish a connection to XenD
- domain1 = XmTestAPIDomain(extraConfig={ 'security_label' : vm_label_red })
-except Exception, e:
- SKIP("Skipping test. Error: %s" % str(e))
-
-
-vm1_uuid = domain1.get_uuid()
-
-try:
- domain1.start(noConsole=True)
-except:
- FAIL("Could not start domain1")
-
-print "Domain 1 started"
-
-try:
- # XmTestAPIDomain tries to establish a connection to XenD
- domain2 = XmTestAPIDomain(extraConfig={'security_label': vm_label_green })
-except Exception, e:
- SKIP("Skipping test. Error: %s" % str(e))
-
-vm2_uuid = domain2.get_uuid()
-
-try:
- domain2.start(noConsole=True)
-except:
- FAIL("Could not start domain1")
-
-
-print "Domain 2 started"
-
-# Try a policy that would put the two domains into conflict
-cfs_2 = { 'name' : "CFS1",
- 'chws' : [ "red" , "green" ] }
-cfss = [ cfs_2 ]
-
-hdr = update_hdr(hdr)
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-
-print "policystate %s" % policystate
-
-if int(policystate['xserr']) == 0:
- FAIL("(1) Should not have been able to set this policy.")
-
-if len(policystate['errors']) == 0:
- FAIL("Hypervisor should have reported errros.")
-
-errors = base64.b64decode(policystate['errors'])
-
-print "Length of errors: %d" % len(errors)
-a,b = struct.unpack("!ii",errors)
-
-print "%08x , %08x" % (a,b)
-
-#
-# Create a faulty policy with 'red' STE missing
-#
-
-cfss = [ cfs_1 ]
-stes = [ "SystemManagement", "green", "blue" ]
-
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-
-print "Result from setting faulty(!) policy with STE 'red' missing:"
-print "policystate %s" % policystate
-
-if int(policystate['xserr']) == 0:
- FAIL("(2) Should not have been able to set this policy.")
-
-#
-# Create a policy with 'red' VMLabel missing -- should not work since it is
-# in use.
-#
-stes = [ "SystemManagement", "red", "green", "blue" ]
-
-vmlabels = [ vm_sysmgt, vm_green, vm_blue ]
-
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-print "Result from setting faulty(!) policy with VMlabel 'red' missing:"
-print "policystate %s" % policystate
-
-if int(policystate['xserr']) == 0:
- FAIL("(3) Should not have been able to set this policy.")
-
-#
-# Create a policy with 'blue' VMLabel missing -- should work since it is NOT
-# in use.
-#
-vmlabels = [ vm_sysmgt, vm_red, vm_green ]
-
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-
-print "Result from setting (good) policy with VMlabel 'blue' missing:"
-print "policystate %s" % policystate
-
-if int(policystate['xserr']) != 0:
- FAIL("(4) Should have been able to set this policy: %s" % xml)
-
-#
-# Move the green VMLabel towards blue which should put the running
-# domain with label blue into a conflict set
-#
-vmlabels = [ vm_sysmgt, vm_red, vm_blue ]
-
-vmfrommap = { "blue" : "green" } # new : old
-
-hdr = update_hdr(hdr) #Needed, since last update was successful
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-
-print "policystate %s" % policystate
-
-if int(policystate['xserr']) == 0:
- FAIL("(5) Should not have been able to set this policy.")
-
-#
-# Try to install a policy where a VM label has a faulty VM label name
-#
-vmfrommap = {}
-
-vm_blue_bad = { 'name' : "blue:x" , # ':' no allowed
- 'stes' : ["blue"],
- 'chws' : ["blue"] }
-
-vmlabels = [ vm_sysmgt, vm_red, vm_green, vm_blue_bad ]
-
-xml = create_xml_policy(hdr, stes, chws,
- vmlabels, vmfrommap, bootstrap,
- reslabels, resfrommap,
- cfss)
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- xml,
- xsconstants.XS_INST_LOAD,
- True)
-
-print "policystate %s" % policystate
-
-if int(policystate['xserr']) == 0:
- FAIL("(6) Should not have been able to set this policy.")
-
-#
-# End the test by installing the initial policy again
-#
-
-cur_version = hdr['version']
-(maj, min) = cur_version.split(".")
-cur_version = "%s.%s" % (maj, str(int(min)-1) )
-
-orig_acmpol = ACMPolicy(xml=xml_good)
-orig_acmpol.set_frompolicy_version(cur_version)
-orig_acmpol.set_policy_version(hdr['version'])
-
-policystate = session.xenapi.XSPolicy.set_xspolicy(xsconstants.XS_POLICY_ACM,
- orig_acmpol.toxml(),
- xsconstants.XS_INST_LOAD,
- True)
-
-if int(policystate['xserr']) != 0:
- FAIL("(END) Should have been able to set this policy.")
-
-domain1.stop()
-domain2.stop()
-domain1.destroy()
-domain2.destroy()
diff --git a/tools/xm-test/tests/security-acm/10_security-acm_pol_update.py b/tools/xm-test/tests/security-acm/10_security-acm_pol_update.py
deleted file mode 100644
index b60a62eae2..0000000000
--- a/tools/xm-test/tests/security-acm/10_security-acm_pol_update.py
+++ /dev/null
@@ -1,354 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-#
-
-import os
-import re
-import commands
-from XmTestLib import *
-import xen.util.xsm.xsm as security
-from xen.util import xsconstants
-
-def checkLabel(labeldata, expected, domname):
- if labeldata[0] != expected[0]:
- FAIL("Policy type of %s is bad: %s" % (domname, labeldata[0]))
- if labeldata[1] != expected[1]:
- FAIL("Unexpected policy indicated in %s label '%s', expected '%s'." %
- (domname, labeldata[1], expected[1]))
- if labeldata[2] != expected[2]:
- FAIL("%s does not have '%s' label but '%s'." %
- (domname, expected[2], labeldata[2]))
-
-if not isACMEnabled():
- SKIP("Not running this test since ACM not enabled.")
-
-testpolicy = "xm-test"
-testlabel1 = "blue"
-testlabel2 = "red"
-testlabel3 = "green"
-
-# reset the policy - must work
-s, o = traceCommand('xm resetpolicy')
-if s:
- FAIL("Could not reset the policy.")
-
-
-s, o = traceCommand('xm resources | grep -E "^[phy|file|vlan]" ')
-resnames = []
-if o:
- resnames = o.split('\n')
-
- for res in resnames:
- s, o = traceCommand('xm rmlabel res %s' % res)
-
-#Unlabeled domain must not start under xm-test policy
-domain_ul = XmTestDomain(name='domain-unlabeled',
- extraConfig=None)
-del domain_ul.config.opts['access_control']
-try:
- domain_ul.start(noConsole=True)
- FAIL("Could start unlabeled domain.")
-except DomainError, e:
- domain_ul.destroy() # delete if xend-managed domain
-
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
-
-domain_blue = XmTestDomain(name='domain-%s' % testlabel1,
- extraConfig=config)
-
-config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel3)}
-
-domain_green = XmTestDomain(name='domain-%s' % testlabel3,
- extraConfig=config)
-
-
-try:
- domain_blue.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start blue labeled test domain")
-
-s, o = traceCommand('xm list Domain-0 --label | grep -E "Domain-0"')
-if s:
- FAIL("Could not get the label of Domain-0")
-
-info = o.strip().split(' ')
-labeldata = info[-1].split(':')
-if len(labeldata) != 3:
- FAIL("Label of Domain-0 is bad: '%s'" % info[-1])
-checkLabel(labeldata,
- [xsconstants.ACM_POLICY_ID, "xm-test", "SystemManagement"],
- "Domain-0")
-
-# Should be able to set the Domain-0 label to blue
-s, o = traceCommand('xm addlabel blue mgt Domain-0')
-if s:
- FAIL("Could not set the label of Domain-0 to 'blue'.")
-s,o = traceCommand('xm list Domain-0 --label | grep -E "Domain-0"')
-if s:
- FAIL("Could not get the label of Domain-0")
-
-info = o.strip().split()
-labeldata = info[-1].split(':')
-if len(labeldata) != 3:
- FAIL("Label of Domain-0 is bad: '%s'" % info[-1])
-checkLabel(labeldata,
- [xsconstants.ACM_POLICY_ID, "xm-test", "blue"],
- "Domain-0")
-
-#Should not be able to set the label of Domain-0 to 'red'
-s, o = traceCommand('xm addlabel red mgt Domain-0')
-if not s:
- FAIL("Could set the label of Domain-0 to 'red'.")
-s,o = traceCommand('xm list Domain-0 --label | grep -E "Domain-0"')
-if s:
- FAIL("Could not get the label of Domain-0")
-
-info = o.strip().split()
-labeldata = info[-1].split(':')
-if len(labeldata) != 3:
- FAIL("Label of Domain-0 is bad: '%s'" % info[-1])
-checkLabel(labeldata,
- [xsconstants.ACM_POLICY_ID, "xm-test", "blue"],
- "Domain-0")
-
-# Should be able to set the label of Domain-0 to 'SystemManagement'
-s, o = traceCommand('xm addlabel SystemManagement mgt Domain-0')
-if s:
- FAIL("Could not set the label of Domain-0 to 'SystemManagement'.")
-s,o = traceCommand('xm list Domain-0 --label | grep -E "Domain-0"')
-if s:
- FAIL("Could not get the label of Domain-0")
-
-info = o.strip().split()
-labeldata = info[-1].split(':')
-if len(labeldata) != 3:
- FAIL("Label of Domain-0 is bad: '%s'" % info[-1])
-checkLabel(labeldata,
- [xsconstants.ACM_POLICY_ID, "xm-test", "SystemManagement"],
- "Domain-0")
-
-#Label some resource green
-#Label some resource red
-#Label some resource blue
-
-s, o = traceCommand('xm addlabel green res file:/tmp/green')
-if s:
- FAIL("Could not label resource 'green'.")
-s, o = traceCommand('xm addlabel red res file:/tmp/red')
-if s:
- FAIL("Could not label resource 'red'.")
-s, o = traceCommand('xm addlabel blue res file:/tmp/blue')
-if s:
- FAIL("Could not label resrouce 'blue'")
-
-# Start a green domain
-try:
- domain_green.start(noConsole=True)
-except DomainError, e:
- if verbose:
- print e.extra
- FAIL("Unable to start green labeled test domain")
-
-# Update the system's policy. Should not work, since blue Domain is running
-s, o = traceCommand('xm setpolicy ACM xm-test-update')
-if not s:
- FAIL("Could set the new policy even though blue domain is running.")
-
-s, o = traceCommand('xm getpolicy | grep "Policy name"')
-info = o.split(':')
-poldata = [i.strip() for i in info]
-
-if poldata[1] != 'xm-test':
- FAIL("Policy should be 'xm-test' but is now '%s'." % poldata[1])
-
-# Check that no labels have changed
-s, o = traceCommand('xm getlabel res file:/tmp/green')
-if s:
- FAIL("Could not get label for green resource.")
-label=o.strip()
-if label != 'ACM:xm-test:green':
- FAIL("Label for green resource has changed to '%s', but should not have,"
- % label)
-
-s, o = traceCommand('xm getlabel res file:/tmp/red')
-if s:
- FAIL("Could not get label for red resource.")
-label=o.strip()
-if label != 'ACM:xm-test:red':
- FAIL("Label for red resource has changed to '%s', but should not have,"
- % label)
-
-s, o = traceCommand('xm getlabel res file:/tmp/blue')
-if s:
- FAIL("Could not get label for blue resource.")
-label=o.strip()
-if label != 'ACM:xm-test:blue':
- FAIL("Label for blue resource has changed to '%s', but should not have,"
- % label)
-
-# Terminate blue domain
-domain_blue.destroy()
-
-# Update the system's policy. Should work and rename the green domain to GREEN
-s, o = traceCommand('xm setpolicy ACM xm-test-update')
-if s:
- FAIL("Could not set the new policy.")
-
-acm.setCurrentPolicy('xm-test-update')
-
-s, o = traceCommand('xm getpolicy | grep "Policy name"')
-info = o.split(':')
-poldata = [i.strip() for i in info]
-
-if poldata[1] != 'xm-test-update':
- FAIL("Policy should be 'xm-test-update' but is now '%s'." % poldata[1])
-
-# check previously labeled resources
-# - green should be GREEN now
-# - blue should have been invalidated
-# - red should be the same
-s, o = traceCommand('xm getlabel res file:/tmp/green')
-if s:
- FAIL("Could not get label for GREEN resource.")
-label=o.strip()
-if label != 'ACM:xm-test-update:GREEN':
- FAIL("Label for green resource has changed to '%s', but should not have,"
- % label)
-
-s, o = traceCommand('xm getlabel res file:/tmp/red')
-if s:
- FAIL("Could not get label for RED resource.")
-label=o.strip()
-if label != 'ACM:xm-test-update:RED':
- FAIL("Label for RED resource has changed to '%s', expected is '%s',"
- % (label,'ACM:xm-test-update:RED'))
-
-s, o = traceCommand('xm getlabel res file:/tmp/blue')
-if s:
- FAIL("Could not get label for blue resource.")
-label=o.strip()
-if label != 'INV_ACM:xm-test:blue':
- FAIL("Label for blue resource has changed to '%s', expected is '%s',"
- % (label,'INV_ACM:xm-test:blue'))
-
-config = {"access_control":"policy=%s,label=%s" % ('xm-test-update',testlabel2)}
-
-domain_red = XmTestDomain(name='domain-%s' % testlabel2,
- extraConfig=config)
-
-# Start the red domain - should not work due to conflict set
-try:
- domain_red.start(noConsole=True)
- FAIL("Could start 'red' domain.")
-except DomainError, e:
- domain_red.destroy() # delete if xend-managed domain
-
-# Terminate GREEN domain
-domain_green.destroy()
-
-# Start the red domain - should work now
-try:
- domain_red.start()
-except DomainError, e:
- FAIL("Could not start 'red' domain.")
-
-# Stop the red domain.
-domain_red.destroy()
-
-# Make Domain-0 GREEN
-s, o = traceCommand('xm addlabel GREEN mgt Domain-0')
-if s:
- FAIL("Could not set Domain-0's label to 'GREEN'.")
-s,o = traceCommand('xm list Domain-0 --label | grep -E "Domain-0"')
-if s:
- FAIL("Could not get the label of Domain-0")
-
-info = o.strip().split()
-labeldata = info[-1].split(':')
-if len(labeldata) != 3:
- FAIL("Label of Domain-0 is bad: '%s'" % info[-1])
-checkLabel(labeldata,
- [xsconstants.ACM_POLICY_ID, "xm-test-update", "GREEN"],
- "Domain-0")
-
-# Start the red domain - should not work due to conflict set
-try:
- domain_red.start()
- FAIL("Could start 'red' domain.")
-except DomainError, e:
- pass
-
-# Set Domain-0's domain to SystemManagement
-s, o = traceCommand('xm addlabel SystemManagement mgt Domain-0')
-if s:
- FAIL("Could not set Domain-0's label to SystemManagement.")
-
-# Start unlabeled domain - should work
-try:
- domain_ul.start(noConsole=True)
-except DomainError, e:
- FAIL("Could not start unlabeled domain.")
-
-# Stop red domain
-domain_red.destroy()
-
-# Stop unlabeled domain
-domain_ul.destroy()
-
-
-# Mark Domain-0 as red. This must not have any effect on the later reset
-s, o = traceCommand('xm addlabel red mgt Domain-0')
-if s:
- FAIL("Could not set Domain-0's label to 'red'.")
-s,o = traceCommand('xm list Domain-0 --label | grep -E "Domain-0"')
-if s:
- FAIL("Could not get the label of Domain-0")
-
-info = o.strip().split()
-labeldata = info[-1].split(':')
-if len(labeldata) != 3:
- FAIL("Label of Domain-0 is bad: '%s'" % info[-1])
-checkLabel(labeldata,
- [xsconstants.ACM_POLICY_ID, "xm-test-update", "red"],
- "Domain-0")
-
-# reset the policy - should work
-s, o = traceCommand('xm resetpolicy')
-if s:
- FAIL("Could not reset the policy.")
-
-# check previously labeled resources
-# - GREEN should be invalid
-# - red should be invalid
-# - blue should be invalid
-s, o = traceCommand('xm getlabel res file:/tmp/green')
-if s:
- FAIL("Could not get label for GREEN resource.")
-label=o.strip()
-exp='INV_ACM:xm-test-update:GREEN'
-if label != exp:
- FAIL("Label for green resource has changed to '%s', but should be '%s',"
- % (label, exp))
-
-s, o = traceCommand('xm getlabel res file:/tmp/red')
-if s:
- FAIL("Could not get label for RED resource.")
-label=o.strip()
-exp='INV_ACM:xm-test-update:RED'
-if label != exp:
- FAIL("Label for RED resource has changed to '%s', but should be '%s'.,"
- % (label, exp))
-
-s, o = traceCommand('xm getlabel res file:/tmp/blue')
-if s:
- FAIL("Could not get label for blue resource.")
-label=o.strip()
-exp='INV_ACM:xm-test:blue'
-if label != exp:
- FAIL("Label for blue resource has changed to '%s', but should be '%s',"
- % (label, exp))
diff --git a/tools/xm-test/tests/security-acm/Makefile.am b/tools/xm-test/tests/security-acm/Makefile.am
deleted file mode 100644
index 9bbb856a1b..0000000000
--- a/tools/xm-test/tests/security-acm/Makefile.am
+++ /dev/null
@@ -1,33 +0,0 @@
-SUBDIRS =
-
-TESTS = 01_security-acm_basic.test \
- 02_security-acm_dom_start.test \
- 03_security-acm_dom_conflict.test \
- 04_security-acm_dom_res.test \
- 05_security-acm_dom_res_conf.test \
- 06_security-acm_dom_block_attach.test \
- 07_security-acm_pol_update.test \
- 08_security-acm_xapi.test \
- 09_security-acm_pol_update.test \
- 10_security-acm_pol_update.test
-
-XFAIL_TESTS =
-
-EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) acm_utils.py
-TESTS_ENVIRONMENT=@TENV@
-
-%.test: %.py
- cp $< $@
- chmod +x $@
- @if [ -d /etc/xen/acm-security/policies ]; then \
- cp -f xm-test-security_policy.xml \
- xm-test-update-security_policy.xml\
- /etc/xen/acm-security/policies; \
- fi;
-
-clean-local: am_config_clean-local
-
-am_config_clean-local:
- rm -f *test
- rm -f *log
- rm -f *~
diff --git a/tools/xm-test/tests/security-acm/acm_utils.py b/tools/xm-test/tests/security-acm/acm_utils.py
deleted file mode 100644
index 457aa840b3..0000000000
--- a/tools/xm-test/tests/security-acm/acm_utils.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (C) International Business Machines Corp., 2006
-# Author: Stefan Berger <stefanb@us.ibm.com>
-
-from XmTestLib import *
-from XmTestLib.acm import *
-
-testpolicy = "xm-test"
-vmconfigfile = "/tmp/xm-test.conf"
-
-if not isACMEnabled():
- SKIP("Not running this test since ACM not enabled.")
-
-setCurrentPolicy(testpolicy)
-ACMSetPolicy()
diff --git a/tools/xm-test/tests/security-acm/xm-test-new-security_policy.xml b/tools/xm-test/tests/security-acm/xm-test-new-security_policy.xml
deleted file mode 100644
index abc49e1ef5..0000000000
--- a/tools/xm-test/tests/security-acm/xm-test-new-security_policy.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Auto-generated by ezPolicy -->
-<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
- <PolicyHeader>
- <PolicyName>xm-test</PolicyName>
- <Date>Fri Sep 29 14:44:38 2006</Date>
- <Version>1.1</Version>
- <FromPolicy>
- <PolicyName>xm-test</PolicyName>
- <Version>1.0</Version>
- </FromPolicy>
- </PolicyHeader>
-
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>green</Type>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
-
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- <Type>green</Type>
- <Type>red</Type>
- </ChineseWallTypes>
-
- <ConflictSets>
- <Conflict name="RER">
- <Type>green</Type>
- <Type>red</Type>
- </Conflict>
- </ConflictSets>
- </ChineseWall>
-
- <SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>green</Type>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>green</Name>
- <SimpleTypeEnforcementTypes>
- <Type>green</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>green</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>red</Name>
- <SimpleTypeEnforcementTypes>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>red</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- </SubjectLabels>
-
- <ObjectLabels>
- <ResourceLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>green</Name>
- <SimpleTypeEnforcementTypes>
- <Type>green</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>red</Name>
- <SimpleTypeEnforcementTypes>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- </ObjectLabels>
- </SecurityLabelTemplate>
-</SecurityPolicyDefinition>
diff --git a/tools/xm-test/tests/security-acm/xm-test-security_policy.xml b/tools/xm-test/tests/security-acm/xm-test-security_policy.xml
deleted file mode 100644
index 9c84a83626..0000000000
--- a/tools/xm-test/tests/security-acm/xm-test-security_policy.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Auto-generated by ezPolicy -->
-<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
- <PolicyHeader>
- <PolicyName>xm-test</PolicyName>
- <Date>Fri Sep 29 14:44:38 2006</Date>
- <Version>1.0</Version>
- </PolicyHeader>
-
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>green</Type>
- <Type>red</Type>
- <Type>blue</Type>
- </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
-
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- <Type>green</Type>
- <Type>red</Type>
- <Type>blue</Type>
- </ChineseWallTypes>
-
- <ConflictSets>
- <Conflict name="RER">
- <Type>blue</Type>
- <Type>red</Type>
- </Conflict>
- </ConflictSets>
- </ChineseWall>
-
- <SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>green</Type>
- <Type>red</Type>
- <Type>blue</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>green</Name>
- <SimpleTypeEnforcementTypes>
- <Type>green</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>green</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>red</Name>
- <SimpleTypeEnforcementTypes>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>red</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>blue</Name>
- <SimpleTypeEnforcementTypes>
- <Type>blue</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>blue</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
- </SubjectLabels>
-
- <ObjectLabels>
- <ResourceLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>green</Name>
- <SimpleTypeEnforcementTypes>
- <Type>green</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>red</Name>
- <SimpleTypeEnforcementTypes>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>blue</Name>
- <SimpleTypeEnforcementTypes>
- <Type>blue</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
- </ObjectLabels>
- </SecurityLabelTemplate>
-</SecurityPolicyDefinition>
diff --git a/tools/xm-test/tests/security-acm/xm-test-update-security_policy.xml b/tools/xm-test/tests/security-acm/xm-test-update-security_policy.xml
deleted file mode 100644
index 8c026c9da2..0000000000
--- a/tools/xm-test/tests/security-acm/xm-test-update-security_policy.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Auto-generated by ezPolicy -->
-<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
- <PolicyHeader>
- <PolicyName>xm-test-update</PolicyName>
- <Date>Fri Sep 29 14:44:38 2006</Date>
- <Version>1.1</Version>
- <FromPolicy>
- <PolicyName>xm-test</PolicyName>
- <Version>1.0</Version>
- </FromPolicy>
- </PolicyHeader>
-
- <SimpleTypeEnforcement>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>GREEN</Type>
- <Type>red</Type>
- <Type>__UNLABELED__</Type>
- </SimpleTypeEnforcementTypes>
- </SimpleTypeEnforcement>
-
- <ChineseWall priority="PrimaryPolicyComponent">
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- <Type>GREEN</Type>
- <Type>red</Type>
- <Type>__UNLABELED__</Type>
- </ChineseWallTypes>
-
- <ConflictSets>
- <Conflict name="RER">
- <Type>GREEN</Type>
- <Type>red</Type>
- </Conflict>
- </ConflictSets>
- </ChineseWall>
-
- <SecurityLabelTemplate>
- <SubjectLabels bootstrap="SystemManagement">
- <VirtualMachineLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- <Type>GREEN</Type>
- <Type>red</Type>
- <Type>__UNLABELED__</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>SystemManagement</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name from="green">GREEN</Name>
- <SimpleTypeEnforcementTypes>
- <Type>GREEN</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>GREEN</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>red</Name>
- <SimpleTypeEnforcementTypes>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>red</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- <VirtualMachineLabel>
- <Name>__UNLABELED__</Name>
- <SimpleTypeEnforcementTypes>
- <Type>__UNLABELED__</Type>
- </SimpleTypeEnforcementTypes>
- <ChineseWallTypes>
- <Type>__UNLABELED__</Type>
- </ChineseWallTypes>
- </VirtualMachineLabel>
-
- </SubjectLabels>
-
- <ObjectLabels>
- <ResourceLabel>
- <Name>SystemManagement</Name>
- <SimpleTypeEnforcementTypes>
- <Type>SystemManagement</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name from="green">GREEN</Name>
- <SimpleTypeEnforcementTypes>
- <Type>GREEN</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name from="red">RED</Name>
- <SimpleTypeEnforcementTypes>
- <Type>red</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- <ResourceLabel>
- <Name>__UNLABELED__</Name>
- <SimpleTypeEnforcementTypes>
- <Type>__UNLABELED__</Type>
- </SimpleTypeEnforcementTypes>
- </ResourceLabel>
-
- </ObjectLabels>
- </SecurityLabelTemplate>
-</SecurityPolicyDefinition>
diff --git a/xen/Rules.mk b/xen/Rules.mk
index e9d9c89850..f48ac56326 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -45,7 +45,6 @@ CFLAGS-y += -g -D__XEN__
CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE
CFLAGS-$(FLASK_ENABLE) += -DFLASK_ENABLE -DXSM_MAGIC=0xf97cff8c
CFLAGS-$(FLASK_ENABLE) += -DFLASK_DEVELOP -DFLASK_BOOTPARAM -DFLASK_AVC_STATS
-CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY -DXSM_MAGIC=0xbcde0100
CFLAGS-$(verbose) += -DVERBOSE
CFLAGS-$(crash_debug) += -DCRASH_DEBUG
CFLAGS-$(perfc) += -DPERF_COUNTERS
diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c
index be2550d22b..7b053a59a5 100644
--- a/xen/arch/ia64/xen/xensetup.c
+++ b/xen/arch/ia64/xen/xensetup.c
@@ -29,7 +29,6 @@
#include <asm/iosapic.h>
#include <xen/softirq.h>
#include <xen/rcupdate.h>
-#include <xsm/acm/acm_hooks.h>
#include <asm/sn/simulator.h>
#include <asm/sal.h>
#include <xen/cpu.h>
@@ -645,7 +644,7 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
expose_p2m_init();
/* Create initial domain 0. */
- dom0 = domain_create(0, 0, DOM0_SSIDREF);
+ dom0 = domain_create(0, 0, 0);
if (dom0 == NULL)
panic("Error creating domain 0\n");
domain_set_vhpt_size(dom0, dom0_vhpt_size_log2);
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 5734782d76..0478079dbc 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -36,7 +36,6 @@
#include <asm/desc.h>
#include <asm/paging.h>
#include <asm/e820.h>
-#include <xsm/acm/acm_hooks.h>
#include <xen/kexec.h>
#include <asm/edd.h>
#include <xsm/xsm.h>
@@ -1266,7 +1265,7 @@ void __init __start_xen(unsigned long mbi_p)
panic("Could not protect TXT memory regions\n");
/* Create initial domain 0. */
- dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
+ dom0 = domain_create(0, DOMCRF_s3_integrity, 0);
if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
panic("Error creating domain 0\n");
diff --git a/xen/common/domain.c b/xen/common/domain.c
index b8c48a7ab0..51aa0400df 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -212,7 +212,7 @@ static void __init parse_extra_guest_irqs(const char *s)
custom_param("extra_guest_irqs", parse_extra_guest_irqs);
struct domain *domain_create(
- domid_t domid, unsigned int domcr_flags, ssidref_t ssidref)
+ domid_t domid, unsigned int domcr_flags, uint32_t ssidref)
{
struct domain *d, **pd;
enum { INIT_xsm = 1u<<0, INIT_watchdog = 1u<<1, INIT_rangeset = 1u<<2,
diff --git a/xen/include/public/xsm/acm.h b/xen/include/public/xsm/acm.h
deleted file mode 100644
index b6ac8d5130..0000000000
--- a/xen/include/public/xsm/acm.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * acm.h: Xen access control module interface defintions
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Reiner Sailer <sailer@watson.ibm.com>
- * Copyright (c) 2005, International Business Machines Corporation.
- */
-
-#ifndef _XEN_PUBLIC_ACM_H
-#define _XEN_PUBLIC_ACM_H
-
-#include "../xen.h"
-
-/* default ssid reference value if not supplied */
-#define ACM_DEFAULT_SSID 0x0
-#define ACM_DEFAULT_LOCAL_SSID 0x0
-
-/* Internal ACM ERROR types */
-#define ACM_OK 0
-#define ACM_UNDEF -1
-#define ACM_INIT_SSID_ERROR -2
-#define ACM_INIT_SOID_ERROR -3
-#define ACM_ERROR -4
-
-/* External ACCESS DECISIONS */
-#define ACM_ACCESS_PERMITTED 0
-#define ACM_ACCESS_DENIED -111
-#define ACM_NULL_POINTER_ERROR -200
-
-/*
- Error codes reported in when trying to test for a new policy
- These error codes are reported in an array of tuples where
- each error code is followed by a parameter describing the error
- more closely, such as a domain id.
-*/
-#define ACM_EVTCHN_SHARING_VIOLATION 0x100
-#define ACM_GNTTAB_SHARING_VIOLATION 0x101
-#define ACM_DOMAIN_LOOKUP 0x102
-#define ACM_CHWALL_CONFLICT 0x103
-#define ACM_SSIDREF_IN_USE 0x104
-
-
-/* primary policy in lower 4 bits */
-#define ACM_NULL_POLICY 0
-#define ACM_CHINESE_WALL_POLICY 1
-#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
-#define ACM_POLICY_UNDEFINED 15
-
-/* combinations have secondary policy component in higher 4bit */
-#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \
- ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY)
-
-/* policy: */
-#define ACM_POLICY_NAME(X) \
- ((X) == (ACM_NULL_POLICY)) ? "NULL" : \
- ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL" : \
- ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT" : \
- ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT" : \
- "UNDEFINED"
-
-/* the following policy versions must be increased
- * whenever the interpretation of the related
- * policy's data structure changes
- */
-#define ACM_POLICY_VERSION 4
-#define ACM_CHWALL_VERSION 1
-#define ACM_STE_VERSION 1
-
-/* defines a ssid reference used by xen */
-typedef uint32_t ssidref_t;
-
-/* hooks that are known to domains */
-#define ACMHOOK_none 0
-#define ACMHOOK_sharing 1
-#define ACMHOOK_authorization 2
-#define ACMHOOK_conflictset 3
-
-/* -------security policy relevant type definitions-------- */
-
-/* type identifier; compares to "equal" or "not equal" */
-typedef uint16_t domaintype_t;
-
-/* CHINESE WALL POLICY DATA STRUCTURES
- *
- * current accumulated conflict type set:
- * When a domain is started and has a type that is in
- * a conflict set, the conflicting types are incremented in
- * the aggregate set. When a domain is destroyed, the
- * conflicting types to its type are decremented.
- * If a domain has multiple types, this procedure works over
- * all those types.
- *
- * conflict_aggregate_set[i] holds the number of
- * running domains that have a conflict with type i.
- *
- * running_types[i] holds the number of running domains
- * that include type i in their ssidref-referenced type set
- *
- * conflict_sets[i][j] is "0" if type j has no conflict
- * with type i and is "1" otherwise.
- */
-/* high-16 = version, low-16 = check magic */
-#define ACM_MAGIC 0x0001debc
-
-/* size of the SHA1 hash identifying the XML policy from which the
- binary policy was created */
-#define ACM_SHA1_HASH_SIZE 20
-
-/* each offset in bytes from start of the struct they
- * are part of */
-
-/* V3 of the policy buffer aded a version structure */
-struct acm_policy_version
-{
- uint32_t major;
- uint32_t minor;
-};
-
-
-/* each buffer consists of all policy information for
- * the respective policy given in the policy code
- *
- * acm_policy_buffer, acm_chwall_policy_buffer,
- * and acm_ste_policy_buffer need to stay 32-bit aligned
- * because we create binary policies also with external
- * tools that assume packed representations (e.g. the java tool)
- */
-struct acm_policy_buffer {
- uint32_t magic;
- uint32_t policy_version; /* ACM_POLICY_VERSION */
- uint32_t len;
- uint32_t policy_reference_offset;
- uint32_t primary_policy_code;
- uint32_t primary_buffer_offset;
- uint32_t secondary_policy_code;
- uint32_t secondary_buffer_offset;
- struct acm_policy_version xml_pol_version; /* add in V3 */
- uint8_t xml_policy_hash[ACM_SHA1_HASH_SIZE]; /* added in V4 */
-};
-
-
-struct acm_policy_reference_buffer {
- uint32_t len;
-};
-
-struct acm_chwall_policy_buffer {
- uint32_t policy_version; /* ACM_CHWALL_VERSION */
- uint32_t policy_code;
- uint32_t chwall_max_types;
- uint32_t chwall_max_ssidrefs;
- uint32_t chwall_max_conflictsets;
- uint32_t chwall_ssid_offset;
- uint32_t chwall_conflict_sets_offset;
- uint32_t chwall_running_types_offset;
- uint32_t chwall_conflict_aggregate_offset;
-};
-
-struct acm_ste_policy_buffer {
- uint32_t policy_version; /* ACM_STE_VERSION */
- uint32_t policy_code;
- uint32_t ste_max_types;
- uint32_t ste_max_ssidrefs;
- uint32_t ste_ssid_offset;
-};
-
-struct acm_stats_buffer {
- uint32_t magic;
- uint32_t len;
- uint32_t primary_policy_code;
- uint32_t primary_stats_offset;
- uint32_t secondary_policy_code;
- uint32_t secondary_stats_offset;
-};
-
-struct acm_ste_stats_buffer {
- uint32_t ec_eval_count;
- uint32_t gt_eval_count;
- uint32_t ec_denied_count;
- uint32_t gt_denied_count;
- uint32_t ec_cachehit_count;
- uint32_t gt_cachehit_count;
-};
-
-struct acm_ssid_buffer {
- uint32_t len;
- ssidref_t ssidref;
- uint32_t policy_reference_offset;
- uint32_t primary_policy_code;
- uint32_t primary_max_types;
- uint32_t primary_types_offset;
- uint32_t secondary_policy_code;
- uint32_t secondary_max_types;
- uint32_t secondary_types_offset;
-};
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/public/xsm/acm_ops.h b/xen/include/public/xsm/acm_ops.h
deleted file mode 100644
index 1fef7a0f8b..0000000000
--- a/xen/include/public/xsm/acm_ops.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * acm_ops.h: Xen access control module hypervisor commands
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Reiner Sailer <sailer@watson.ibm.com>
- * Copyright (c) 2005,2006 International Business Machines Corporation.
- */
-
-#ifndef __XEN_PUBLIC_ACM_OPS_H__
-#define __XEN_PUBLIC_ACM_OPS_H__
-
-#include "../xen.h"
-#include "acm.h"
-
-/*
- * Make sure you increment the interface version whenever you modify this file!
- * This makes sure that old versions of acm tools will stop working in a
- * well-defined way (rather than crashing the machine, for instance).
- */
-#define ACM_INTERFACE_VERSION 0xAAAA000A
-
-/************************************************************************/
-
-/*
- * Prototype for this hypercall is:
- * int acm_op(int cmd, void *args)
- * @cmd == ACMOP_??? (access control module operation).
- * @args == Operation-specific extra arguments (NULL if none).
- */
-
-
-#define ACMOP_setpolicy 1
-struct acm_setpolicy {
- /* IN */
- XEN_GUEST_HANDLE_64(void) pushcache;
- uint32_t pushcache_size;
-};
-
-
-#define ACMOP_getpolicy 2
-struct acm_getpolicy {
- /* IN */
- XEN_GUEST_HANDLE_64(void) pullcache;
- uint32_t pullcache_size;
-};
-
-
-#define ACMOP_dumpstats 3
-struct acm_dumpstats {
- /* IN */
- XEN_GUEST_HANDLE_64(void) pullcache;
- uint32_t pullcache_size;
-};
-
-
-#define ACMOP_getssid 4
-#define ACM_GETBY_ssidref 1
-#define ACM_GETBY_domainid 2
-struct acm_getssid {
- /* IN */
- uint32_t get_ssid_by; /* ACM_GETBY_* */
- union {
- domaintype_t domainid;
- ssidref_t ssidref;
- } id;
- XEN_GUEST_HANDLE_64(void) ssidbuf;
- uint32_t ssidbuf_size;
-};
-
-#define ACMOP_getdecision 5
-struct acm_getdecision {
- /* IN */
- uint32_t get_decision_by1; /* ACM_GETBY_* */
- uint32_t get_decision_by2; /* ACM_GETBY_* */
- union {
- domaintype_t domainid;
- ssidref_t ssidref;
- } id1;
- union {
- domaintype_t domainid;
- ssidref_t ssidref;
- } id2;
- uint32_t hook;
- /* OUT */
- uint32_t acm_decision;
-};
-
-
-#define ACMOP_chgpolicy 6
-struct acm_change_policy {
- /* IN */
- XEN_GUEST_HANDLE_64(void) policy_pushcache;
- uint32_t policy_pushcache_size;
- XEN_GUEST_HANDLE_64(void) del_array;
- uint32_t delarray_size;
- XEN_GUEST_HANDLE_64(void) chg_array;
- uint32_t chgarray_size;
- /* OUT */
- /* array with error code */
- XEN_GUEST_HANDLE_64(void) err_array;
- uint32_t errarray_size;
-};
-
-#define ACMOP_relabeldoms 7
-struct acm_relabel_doms {
- /* IN */
- XEN_GUEST_HANDLE_64(void) relabel_map;
- uint32_t relabel_map_size;
- /* OUT */
- XEN_GUEST_HANDLE_64(void) err_array;
- uint32_t errarray_size;
-};
-
-/* future interface to Xen */
-struct xen_acmctl {
- uint32_t cmd;
- uint32_t interface_version;
- union {
- struct acm_setpolicy setpolicy;
- struct acm_getpolicy getpolicy;
- struct acm_dumpstats dumpstats;
- struct acm_getssid getssid;
- struct acm_getdecision getdecision;
- struct acm_change_policy change_policy;
- struct acm_relabel_doms relabel_doms;
- } u;
-};
-
-typedef struct xen_acmctl xen_acmctl_t;
-DEFINE_XEN_GUEST_HANDLE(xen_acmctl_t);
-
-#endif /* __XEN_PUBLIC_ACM_OPS_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 652a39c5b0..c86759596f 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -11,7 +11,6 @@
#include <public/domctl.h>
#include <public/sysctl.h>
#include <public/vcpu.h>
-#include <public/xsm/acm.h>
#include <xen/time.h>
#include <xen/timer.h>
#include <xen/grant_table.h>
@@ -401,7 +400,7 @@ static inline void get_knownalive_domain(struct domain *d)
void domain_update_node_affinity(struct domain *d);
struct domain *domain_create(
- domid_t domid, unsigned int domcr_flags, ssidref_t ssidref);
+ domid_t domid, unsigned int domcr_flags, uint32_t ssidref);
/* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
#define _DOMCRF_hvm 0
#define DOMCRF_hvm (1U<<_DOMCRF_hvm)
diff --git a/xen/include/xsm/acm/acm_core.h b/xen/include/xsm/acm/acm_core.h
deleted file mode 100644
index 718f9b7f89..0000000000
--- a/xen/include/xsm/acm/acm_core.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/****************************************************************
- * acm_core.h
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype header file describing core data types and constants
- * for the access control module and relevant policies
- *
- */
-
-#ifndef _ACM_CORE_H
-#define _ACM_CORE_H
-
-#include <xen/spinlock.h>
-#include <xen/list.h>
-#include <public/xsm/acm.h>
-#include <public/xsm/acm_ops.h>
-#include <xsm/acm/acm_endian.h>
-
-#define ACM_DEFAULT_SECURITY_POLICY \
- ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
-
-/* Xen-internal representation of the binary policy */
-struct acm_binary_policy {
- char *policy_reference_name;
- u16 primary_policy_code;
- u16 secondary_policy_code;
- struct acm_policy_version xml_pol_version;
- u8 xml_policy_hash[ACM_SHA1_HASH_SIZE];
-};
-
-struct chwall_binary_policy {
- u32 max_types;
- u32 max_ssidrefs;
- u32 max_conflictsets;
- domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */
- domaintype_t *conflict_aggregate_set; /* [max_types] */
- domaintype_t *running_types; /* [max_types] */
- domaintype_t *conflict_sets; /* [max_conflictsets][max_types]*/
-};
-
-struct ste_binary_policy {
- u32 max_types;
- u32 max_ssidrefs;
- domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */
- atomic_t ec_eval_count, gt_eval_count;
- atomic_t ec_denied_count, gt_denied_count;
- atomic_t ec_cachehit_count, gt_cachehit_count;
-};
-
-/* global acm policy */
-extern u16 acm_active_security_policy;
-extern struct acm_binary_policy acm_bin_pol;
-extern struct chwall_binary_policy chwall_bin_pol;
-extern struct ste_binary_policy ste_bin_pol;
-/* use the lock when reading / changing binary policy ! */
-extern rwlock_t acm_bin_pol_rwlock;
-extern rwlock_t ssid_list_rwlock;
-
-/* subject and object type definitions */
-#define ACM_DATATYPE_domain 1
-
-/* defines number of access decisions to other domains can be cached
- * one entry per domain, TE does not distinguish evtchn or grant_table */
-#define ACM_TE_CACHE_SIZE 8
-#define ACM_STE_valid 0
-#define ACM_STE_free 1
-
-/* cache line:
- * if cache_line.valid==ACM_STE_valid, then
- * STE decision is cached as "permitted"
- * on domain cache_line.id
- */
-struct acm_ste_cache_line {
- int valid; /* ACM_STE_* */
- domid_t id;
-};
-
-/* general definition of a subject security id */
-struct acm_ssid_domain {
- struct list_head node; /* all are chained together */
- int datatype; /* type of subject (e.g., partition): ACM_DATATYPE_* */
- ssidref_t ssidref; /* combined security reference */
- ssidref_t old_ssidref; /* holds previous value of ssidref during relabeling */
- void *primary_ssid; /* primary policy ssid part (e.g. chinese wall) */
- void *secondary_ssid; /* secondary policy ssid part (e.g. type enforcement) */
- struct domain *subject;/* backpointer to subject structure */
- domid_t domainid; /* replicate id */
-};
-
-/* chinese wall ssid type */
-struct chwall_ssid {
- ssidref_t chwall_ssidref;
-};
-
-/* simple type enforcement ssid type */
-struct ste_ssid {
- ssidref_t ste_ssidref;
- struct acm_ste_cache_line ste_cache[ACM_TE_CACHE_SIZE]; /* decision cache */
-};
-
-/* macros to access ssidref for primary / secondary policy
- * primary ssidref = lower 16 bit
- * secondary ssidref = higher 16 bit
- */
-#define ACM_PRIMARY(ssidref) \
- ((ssidref) & 0xffff)
-
-#define ACM_SECONDARY(ssidref) \
- ((ssidref) >> 16)
-
-#define GET_SSIDREF(POLICY, ssidref) \
- ((POLICY) == acm_bin_pol.primary_policy_code) ? \
- ACM_PRIMARY(ssidref) : ACM_SECONDARY(ssidref)
-
-/* macros to access ssid pointer for primary / secondary policy */
-#define GET_SSIDP(POLICY, ssid) \
- ((POLICY) == acm_bin_pol.primary_policy_code) ? \
- ((ssid)->primary_ssid) : ((ssid)->secondary_ssid)
-
-#define ACM_INVALID_SSIDREF (0xffffffff)
-
-struct acm_sized_buffer
-{
- uint32_t *array;
- uint num_items;
- uint position;
-};
-
-static inline int acm_array_append_tuple(struct acm_sized_buffer *buf,
- uint32_t a, uint32_t b)
-{
- uint i;
- if (buf == NULL)
- return 0;
-
- i = buf->position;
-
- if ((i + 2) > buf->num_items)
- return 0;
-
- buf->array[i] = cpu_to_be32(a);
- buf->array[i+1] = cpu_to_be32(b);
- buf->position += 2;
- return 1;
-}
-
-/* protos */
-int acm_init_domain_ssid(struct domain *, ssidref_t ssidref);
-void acm_free_domain_ssid(struct domain *);
-int acm_init_binary_policy(u32 policy_code);
-int acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size);
-int do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *, struct acm_sized_buffer *,
- struct acm_sized_buffer *);
-int acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size);
-int acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size);
-int acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size);
-int acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook);
-int acm_set_policy_reference(u8 * buf, u32 buf_size);
-int acm_dump_policy_reference(u8 *buf, u32 buf_size);
-int acm_change_policy(struct acm_change_policy *);
-int acm_relabel_domains(struct acm_relabel_doms *);
-int do_chwall_init_state_curr(struct acm_sized_buffer *);
-int do_ste_init_state_curr(struct acm_sized_buffer *);
-
-/* variables */
-extern ssidref_t dom0_chwall_ssidref;
-extern ssidref_t dom0_ste_ssidref;
-#define ACM_MAX_NUM_TYPES (256)
-
-/* traversing the list of ssids */
-extern struct list_head ssid_list;
-#define for_each_acmssid( N ) \
- for ( N = (struct acm_ssid_domain *)ssid_list.next; \
- N != (struct acm_ssid_domain *)&ssid_list; \
- N = (struct acm_ssid_domain *)N->node.next )
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/xsm/acm/acm_endian.h b/xen/include/xsm/acm/acm_endian.h
deleted file mode 100644
index 11781dd4f4..0000000000
--- a/xen/include/xsm/acm/acm_endian.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************
- * acm_endian.h
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * Contributions:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype header file defining endian-dependent functions for the
- * big-endian policy interface
- *
- */
-
-#ifndef _ACM_ENDIAN_H
-#define _ACM_ENDIAN_H
-
-#include <asm/byteorder.h>
-
-static inline void arrcpy16(u16 *dest, const u16 *src, size_t n)
-{
- unsigned int i;
- for ( i = 0; i < n; i++ )
- dest[i] = cpu_to_be16(src[i]);
-}
-
-static inline void arrcpy32(u32 *dest, const u32 *src, size_t n)
-{
- unsigned int i;
- for ( i = 0; i < n; i++ )
- dest[i] = cpu_to_be32(src[i]);
-}
-
-static inline void arrcpy(
- void *dest, const void *src, unsigned int elsize, size_t n)
-{
- switch ( elsize )
- {
- case sizeof(u16):
- arrcpy16((u16 *)dest, (u16 *)src, n);
- break;
-
- case sizeof(u32):
- arrcpy32((u32 *)dest, (u32 *)src, n);
- break;
-
- default:
- memcpy(dest, src, elsize*n);
- }
-}
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/xsm/acm/acm_hooks.h b/xen/include/xsm/acm/acm_hooks.h
deleted file mode 100644
index 67bd49f570..0000000000
--- a/xen/include/xsm/acm/acm_hooks.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/****************************************************************
- * acm_hooks.h
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * acm header file implementing the global (policy-independent)
- * sHype hooks that are called throughout Xen.
- *
- */
-
-#ifndef _ACM_HOOKS_H
-#define _ACM_HOOKS_H
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <xen/multiboot.h>
-#include <public/xsm/acm.h>
-#include <xsm/acm/acm_core.h>
-#include <public/domctl.h>
-#include <public/event_channel.h>
-#include <asm/current.h>
-
-/*
- * HOOK structure and meaning (justifies a few words about our model):
- *
- * General idea: every policy-controlled system operation is reflected in a
- * transaction in the system's security state
- *
- * Keeping the security state consistent requires "atomic" transactions.
- * The name of the hooks to place around policy-controlled transactions
- * reflects this. If authorizations do not involve security state changes,
- * then and only then POST and FAIL hooks remain empty since we don't care
- * about the eventual outcome of the operation from a security viewpoint.
- *
- * PURPOSE of hook types:
- * ======================
- * PRE-Hooks
- * a) general authorization to guard a controlled system operation
- * b) prepare security state change
- * (means: fail hook must be able to "undo" this)
- *
- * POST-Hooks
- * a) commit prepared state change
- *
- * FAIL-Hooks
- * a) roll-back prepared security state change from PRE-Hook
- *
- *
- * PLACEMENT of hook types:
- * ========================
- * PRE-Hooks must be called before a guarded/controlled system operation
- * is started. They return ACM_ACCESS_PERMITTED, ACM_ACCESS_DENIED or
- * error. Operation must be aborted if return is not ACM_ACCESS_PERMITTED.
- *
- * POST-Hooks must be called after a successful system operation.
- * There is no return value: commit never fails.
- *
- * FAIL-Hooks must be called:
- * a) if system transaction (operation) fails after calling the PRE-hook
- * b) if another (secondary) policy denies access in its PRE-Hook
- * (policy layering is useful but requires additional handling)
- *
- * Hook model from a security transaction viewpoint:
- * start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success
- * (pre-hook) \ (post-hook)
- * \
- * fail
- * \
- * \
- * roll-back
- * (fail-hook)
- * \
- * sys-ops error
- *
- */
-
-struct acm_operations {
- /* policy management functions (must always be defined!) */
- int (*init_domain_ssid) (void **ssid, ssidref_t ssidref);
- void (*free_domain_ssid) (void *ssid);
- int (*dump_binary_policy) (u8 *buffer, u32 buf_size);
- int (*test_binary_policy) (u8 *buffer, u32 buf_size,
- int is_bootpolicy,
- struct acm_sized_buffer *);
- int (*set_binary_policy) (u8 *buffer, u32 buf_size);
- int (*dump_statistics) (u8 *buffer, u16 buf_size);
- int (*dump_ssid_types) (ssidref_t ssidref, u8 *buffer, u16 buf_size);
- /* domain management control hooks (can be NULL) */
- int (*domain_create) (void *subject_ssid, ssidref_t ssidref,
- domid_t domid);
- void (*domain_destroy) (void *object_ssid, struct domain *d);
- /* event channel control hooks (can be NULL) */
- int (*pre_eventchannel_unbound) (domid_t id1, domid_t id2);
- void (*fail_eventchannel_unbound) (domid_t id1, domid_t id2);
- int (*pre_eventchannel_interdomain) (domid_t id);
- void (*fail_eventchannel_interdomain) (domid_t id);
- /* grant table control hooks (can be NULL) */
- int (*pre_grant_map_ref) (domid_t id);
- void (*fail_grant_map_ref) (domid_t id);
- int (*pre_grant_setup) (domid_t id);
- void (*fail_grant_setup) (domid_t id);
- /* generic domain-requested decision hooks (can be NULL) */
- int (*sharing) (ssidref_t ssidref1,
- ssidref_t ssidref2);
- int (*authorization) (ssidref_t ssidref1,
- ssidref_t ssidref2);
- int (*conflictset) (ssidref_t ssidref1);
- /* determine whether the default policy is installed */
- int (*is_default_policy) (void);
-};
-
-/* global variables */
-extern struct acm_operations *acm_primary_ops;
-extern struct acm_operations *acm_secondary_ops;
-
-/* if ACM_TRACE_MODE defined, all hooks should
- * print a short trace message */
-/* #define ACM_TRACE_MODE */
-
-#ifdef ACM_TRACE_MODE
-# define traceprintk(fmt, args...) printk(fmt, ## args)
-#else
-# define traceprintk(fmt, args...)
-#endif
-
-/* if ACM_DEBUG defined, all hooks should
- * print a short trace message (comment it out
- * when not in testing mode )
- */
-/* #define ACM_DEBUG */
-
-#ifdef ACM_DEBUG
-# define printkd(fmt, args...) printk(fmt, ## args)
-#else
-# define printkd(fmt, args...)
-#endif
-
-#ifndef ACM_SECURITY
-
-static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
-{ return 0; }
-static inline int acm_pre_eventchannel_interdomain(domid_t id)
-{ return 0; }
-static inline int acm_pre_grant_map_ref(domid_t id)
-{ return 0; }
-static inline int acm_pre_grant_setup(domid_t id)
-{ return 0; }
-static inline int acm_is_policy(char *buf, unsigned long len)
-{ return 0; }
-static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
-{ return 0; }
-static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
-{ return 0; }
-static inline int acm_conflictset(ssidref_t ssidref1)
-{ return 0; }
-static inline int acm_domain_create(struct domain *d, ssidref_t ssidref)
-{ return 0; }
-static inline void acm_domain_destroy(struct domain *d)
-{ return; }
-
-#define DOM0_SSIDREF 0x0
-
-#else
-
-static inline void acm_domain_ssid_onto_list(struct acm_ssid_domain *ssid)
-{
- write_lock(&ssid_list_rwlock);
- list_add(&ssid->node, &ssid_list);
- write_unlock(&ssid_list_rwlock);
-}
-
-static inline void acm_domain_ssid_off_list(struct acm_ssid_domain *ssid)
-{
- write_lock(&ssid_list_rwlock);
- list_del(&ssid->node);
- write_unlock(&ssid_list_rwlock);
-}
-
-static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
-{
- if ((acm_primary_ops->pre_eventchannel_unbound != NULL) &&
- acm_primary_ops->pre_eventchannel_unbound(id1, id2))
- return ACM_ACCESS_DENIED;
- else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) &&
- acm_secondary_ops->pre_eventchannel_unbound(id1, id2)) {
- /* roll-back primary */
- if (acm_primary_ops->fail_eventchannel_unbound != NULL)
- acm_primary_ops->fail_eventchannel_unbound(id1, id2);
- return ACM_ACCESS_DENIED;
- } else
- return ACM_ACCESS_PERMITTED;
-}
-
-static inline int acm_pre_eventchannel_interdomain(domid_t id)
-{
- if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
- acm_primary_ops->pre_eventchannel_interdomain(id))
- return ACM_ACCESS_DENIED;
- else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
- acm_secondary_ops->pre_eventchannel_interdomain(id)) {
- /* roll-back primary */
- if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
- acm_primary_ops->fail_eventchannel_interdomain(id);
- return ACM_ACCESS_DENIED;
- } else
- return ACM_ACCESS_PERMITTED;
-}
-
-
-static inline int acm_pre_grant_map_ref(domid_t id)
-{
- if ( (acm_primary_ops->pre_grant_map_ref != NULL) &&
- acm_primary_ops->pre_grant_map_ref(id) )
- {
- return ACM_ACCESS_DENIED;
- }
- else if ( (acm_secondary_ops->pre_grant_map_ref != NULL) &&
- acm_secondary_ops->pre_grant_map_ref(id) )
- {
- /* roll-back primary */
- if ( acm_primary_ops->fail_grant_map_ref != NULL )
- acm_primary_ops->fail_grant_map_ref(id);
- return ACM_ACCESS_DENIED;
- }
- else
- {
- return ACM_ACCESS_PERMITTED;
- }
-}
-
-static inline int acm_pre_grant_setup(domid_t id)
-{
- if ( (acm_primary_ops->pre_grant_setup != NULL) &&
- acm_primary_ops->pre_grant_setup(id) )
- {
- return ACM_ACCESS_DENIED;
- }
- else if ( (acm_secondary_ops->pre_grant_setup != NULL) &&
- acm_secondary_ops->pre_grant_setup(id) )
- {
- /* roll-back primary */
- if (acm_primary_ops->fail_grant_setup != NULL)
- acm_primary_ops->fail_grant_setup(id);
- return ACM_ACCESS_DENIED;
- }
- else
- {
- return ACM_ACCESS_PERMITTED;
- }
-}
-
-
-static inline void acm_domain_destroy(struct domain *d)
-{
- void *ssid = d->ssid;
- if (ssid != NULL) {
- if (acm_primary_ops->domain_destroy != NULL)
- acm_primary_ops->domain_destroy(ssid, d);
- if (acm_secondary_ops->domain_destroy != NULL)
- acm_secondary_ops->domain_destroy(ssid, d);
- /* free security ssid for the destroyed domain (also if null policy */
- acm_domain_ssid_off_list(ssid);
- acm_free_domain_ssid(d);
- }
-}
-
-
-static inline int acm_domain_create(struct domain *d, ssidref_t ssidref)
-{
- void *subject_ssid = current->domain->ssid;
- domid_t domid = d->domain_id;
- int rc;
-
- read_lock(&acm_bin_pol_rwlock);
- /*
- To be called when a domain is created; returns '0' if the
- domain is allowed to be created, != '0' if not.
- */
- rc = acm_init_domain_ssid(d, ssidref);
- if (rc != ACM_OK)
- goto error_out;
-
- if ((acm_primary_ops->domain_create != NULL) &&
- acm_primary_ops->domain_create(subject_ssid, ssidref, domid)) {
- rc = ACM_ACCESS_DENIED;
- } else if ((acm_secondary_ops->domain_create != NULL) &&
- acm_secondary_ops->domain_create(subject_ssid, ssidref,
- domid)) {
- /* roll-back primary */
- if (acm_primary_ops->domain_destroy != NULL)
- acm_primary_ops->domain_destroy(d->ssid, d);
- rc = ACM_ACCESS_DENIED;
- }
-
- if ( rc == ACM_OK )
- {
- acm_domain_ssid_onto_list(d->ssid);
- } else {
- acm_free_domain_ssid(d);
- }
-
-error_out:
- read_unlock(&acm_bin_pol_rwlock);
- return rc;
-}
-
-
-static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
-{
- if ((acm_primary_ops->sharing != NULL) &&
- acm_primary_ops->sharing(ssidref1, ssidref2))
- return ACM_ACCESS_DENIED;
- else if ((acm_secondary_ops->sharing != NULL) &&
- acm_secondary_ops->sharing(ssidref1, ssidref2)) {
- return ACM_ACCESS_DENIED;
- } else
- return ACM_ACCESS_PERMITTED;
-}
-
-
-static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
-{
- if ((acm_primary_ops->authorization != NULL) &&
- acm_primary_ops->authorization(ssidref1, ssidref2))
- return ACM_ACCESS_DENIED;
- else if ((acm_secondary_ops->authorization != NULL) &&
- acm_secondary_ops->authorization(ssidref1, ssidref2)) {
- return ACM_ACCESS_DENIED;
- } else
- return acm_sharing(ssidref1, ssidref2);
-}
-
-
-static inline int acm_conflictset(ssidref_t ssidref1)
-{
- if ((acm_primary_ops->conflictset != NULL) &&
- acm_primary_ops->conflictset(ssidref1))
- return ACM_ACCESS_DENIED;
- else if ((acm_secondary_ops->conflictset != NULL) &&
- acm_secondary_ops->conflictset(ssidref1))
- return ACM_ACCESS_DENIED;
- return ACM_ACCESS_PERMITTED;
-}
-
-/* Return true iff buffer has an acm policy magic number. */
-extern int acm_is_policy(char *buf, unsigned long len);
-
-#define DOM0_SSIDREF (dom0_ste_ssidref << 16 | dom0_chwall_ssidref)
-
-#endif
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/Makefile b/xen/xsm/Makefile
index 02f55d8e1a..16c13b507f 100644
--- a/xen/xsm/Makefile
+++ b/xen/xsm/Makefile
@@ -5,4 +5,3 @@ obj-y += dummy.o
endif
subdir-$(FLASK_ENABLE) += flask
-subdir-$(ACM_SECURITY) += acm
diff --git a/xen/xsm/acm/Makefile b/xen/xsm/acm/Makefile
deleted file mode 100644
index b3ddbc13c8..0000000000
--- a/xen/xsm/acm/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-y += acm_core.o
-obj-y += acm_policy.o
-obj-y += acm_simple_type_enforcement_hooks.o
-obj-y += acm_chinesewall_hooks.o
-obj-y += acm_null_hooks.o
-obj-y += acm_xsm_hooks.o
-obj-y += acm_ops.o
diff --git a/xen/xsm/acm/acm_chinesewall_hooks.c b/xen/xsm/acm/acm_chinesewall_hooks.c
deleted file mode 100644
index 977c45ff2a..0000000000
--- a/xen/xsm/acm/acm_chinesewall_hooks.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/****************************************************************
- * acm_chinesewall_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributions:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype Chinese Wall Policy for Xen
- * This code implements the hooks that are called
- * throughout Xen operations and decides authorization
- * based on domain types and Chinese Wall conflict type
- * sets. The CHWALL policy decides if a new domain can be started
- * based on the types of running domains and the type of the
- * new domain to be started. If the new domain's type is in
- * conflict with types of running domains, then this new domain
- * is not allowed to be created. A domain can have multiple types,
- * in which case all types of a new domain must be conflict-free
- * with all types of already running domains.
- *
- * indent -i4 -kr -nut
- *
- */
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <public/xsm/acm.h>
-#include <asm/atomic.h>
-#include <xsm/acm/acm_core.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-
-ssidref_t dom0_chwall_ssidref = 0x0001;
-
-/* local cache structures for chinese wall policy */
-struct chwall_binary_policy chwall_bin_pol;
-
-/*
- * Initializing chinese wall policy (will be filled by policy partition
- * using setpolicy command)
- */
-int acm_init_chwall_policy(void)
-{
- /* minimal startup policy; policy write-locked already */
- chwall_bin_pol.max_types = 1;
- chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref;
- chwall_bin_pol.max_conflictsets = 1;
- chwall_bin_pol.ssidrefs =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_ssidrefs *
- chwall_bin_pol.max_types);
- chwall_bin_pol.conflict_sets =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_conflictsets *
- chwall_bin_pol.max_types);
- chwall_bin_pol.running_types =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_types);
- chwall_bin_pol.conflict_aggregate_set =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_types);
-
- if ( (chwall_bin_pol.conflict_sets == NULL)
- || (chwall_bin_pol.running_types == NULL)
- || (chwall_bin_pol.ssidrefs == NULL)
- || (chwall_bin_pol.conflict_aggregate_set == NULL) )
- return ACM_INIT_SSID_ERROR;
-
- /* initialize state */
- memset((void *) chwall_bin_pol.ssidrefs, 0,
- chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types *
- sizeof(domaintype_t));
- memset((void *) chwall_bin_pol.conflict_sets, 0,
- chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types *
- sizeof(domaintype_t));
- memset((void *) chwall_bin_pol.running_types, 0,
- chwall_bin_pol.max_types * sizeof(domaintype_t));
- memset((void *) chwall_bin_pol.conflict_aggregate_set, 0,
- chwall_bin_pol.max_types * sizeof(domaintype_t));
- return ACM_OK;
-}
-
-
-static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
-{
- struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
- traceprintk("%s.\n", __func__);
-
- if ( chwall_ssidp == NULL )
- return ACM_INIT_SSID_ERROR;
-
- chwall_ssidp->chwall_ssidref =
- GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
-
- if ( chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
- {
- printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset "
- "(0).\n",
- __func__, chwall_ssidp->chwall_ssidref);
- xfree(chwall_ssidp);
- return ACM_INIT_SSID_ERROR;
- }
- (*chwall_ssid) = chwall_ssidp;
- printkd("%s: determined chwall_ssidref to %x.\n",
- __func__, chwall_ssidp->chwall_ssidref);
- return ACM_OK;
-}
-
-
-static void chwall_free_domain_ssid(void *chwall_ssid)
-{
- xfree(chwall_ssid);
- return;
-}
-
-
-/* dump chinese wall cache; policy read-locked already */
-static int chwall_dump_policy(u8 * buf, u32 buf_size)
-{
- struct acm_chwall_policy_buffer *chwall_buf =
- (struct acm_chwall_policy_buffer *) buf;
- int ret = 0;
-
- if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
- return -EINVAL;
-
- chwall_buf->chwall_max_types = cpu_to_be32(chwall_bin_pol.max_types);
- chwall_buf->chwall_max_ssidrefs = cpu_to_be32(chwall_bin_pol.max_ssidrefs);
- chwall_buf->policy_code = cpu_to_be32(ACM_CHINESE_WALL_POLICY);
- chwall_buf->chwall_ssid_offset =
- cpu_to_be32(sizeof(struct acm_chwall_policy_buffer));
- chwall_buf->chwall_max_conflictsets =
- cpu_to_be32(chwall_bin_pol.max_conflictsets);
- chwall_buf->chwall_conflict_sets_offset =
- cpu_to_be32(be32_to_cpu(chwall_buf->chwall_ssid_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
- chwall_bin_pol.max_types);
- chwall_buf->chwall_running_types_offset =
- cpu_to_be32(be32_to_cpu(chwall_buf->chwall_conflict_sets_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
- chwall_bin_pol.max_types);
- chwall_buf->chwall_conflict_aggregate_offset =
- cpu_to_be32(be32_to_cpu(chwall_buf->chwall_running_types_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_types);
-
- ret = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_types;
-
- ret = (ret + 7) & ~7;
-
- if ( buf_size < ret )
- return -EINVAL;
-
- /* now copy buffers over */
- arrcpy16((u16 *) (buf + be32_to_cpu(chwall_buf->chwall_ssid_offset)),
- chwall_bin_pol.ssidrefs,
- chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
-
- arrcpy16((u16 *) (buf +
- be32_to_cpu(chwall_buf->chwall_conflict_sets_offset)),
- chwall_bin_pol.conflict_sets,
- chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
-
- arrcpy16((u16 *) (buf +
- be32_to_cpu(chwall_buf->chwall_running_types_offset)),
- chwall_bin_pol.running_types, chwall_bin_pol.max_types);
-
- arrcpy16((u16 *) (buf +
- be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset)),
- chwall_bin_pol.conflict_aggregate_set,
- chwall_bin_pol.max_types);
- return ret;
-}
-
-/*
- * Adapt security state (running_types and conflict_aggregate_set) to all
- * running domains; chwall_init_state is called when a policy is changed
- * to bring the security information into a consistent state and to detect
- * violations (return != 0) from a security point of view, we simulate
- * that all running domains are re-started
- */
-static int
-chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
- domaintype_t * ssidrefs,
- domaintype_t * conflict_sets,
- domaintype_t * running_types,
- domaintype_t * conflict_aggregate_set,
- struct acm_sized_buffer *errors /* may be NULL */)
-{
- int violation = 0, i, j;
- struct chwall_ssid *chwall_ssid;
- ssidref_t chwall_ssidref;
- struct acm_ssid_domain *rawssid;
-
- read_lock(&ssid_list_rwlock);
-
- /* go through all domains and adjust policy as if this domain was
- * started now
- */
- for_each_acmssid( rawssid )
- {
- chwall_ssid =
- GET_SSIDP(ACM_CHINESE_WALL_POLICY, rawssid);
- chwall_ssidref = chwall_ssid->chwall_ssidref;
- traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
- __func__, d->domain_id, chwall_ssidref);
- /* a) adjust types ref-count for running domains */
- for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
- running_types[i] +=
- ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
-
- /* b) check for conflict */
- for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
- if ( conflict_aggregate_set[i] &&
- ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i] )
- {
- printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
- __func__, i);
- violation = 1;
-
- acm_array_append_tuple(errors, ACM_CHWALL_CONFLICT, i);
-
- goto out;
- }
-
- /* set violation and break out of the loop */
- /* c) adapt conflict aggregate set for this domain
- * (notice conflicts)
- */
- for ( i = 0; i < chwall_buf->chwall_max_conflictsets; i++ )
- {
- int common = 0;
- /* check if conflict_set_i and ssidref have common types */
- for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
- if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
- ssidrefs[chwall_ssidref *
- chwall_buf->chwall_max_types + j] )
- {
- common = 1;
- break;
- }
-
- if ( common == 0 )
- continue; /* try next conflict set */
-
- /* now add types of the conflict set to conflict_aggregate_set
- * (except types in chwall_ssidref)
- */
- for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
- if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
- !ssidrefs[chwall_ssidref *
- chwall_buf->chwall_max_types + j] )
- conflict_aggregate_set[j]++;
- }
- }
- out:
- read_unlock(&ssid_list_rwlock);
- return violation;
- /* returning "violation != 0" means that the currently running set of
- * domains would not be possible if the new policy had been enforced
- * before starting them; for chinese wall, this means that the new
- * policy includes at least one conflict set of which more than one
- * type is currently running
- */
-}
-
-
-int
-do_chwall_init_state_curr(struct acm_sized_buffer *errors)
-{
- struct acm_chwall_policy_buffer chwall_buf =
- {
- /* only these two are important */
- .chwall_max_types = chwall_bin_pol.max_types,
- .chwall_max_conflictsets = chwall_bin_pol.max_conflictsets,
- };
- /* reset running_types and aggregate set for recalculation */
- memset(chwall_bin_pol.running_types,
- 0x0,
- sizeof(domaintype_t) * chwall_bin_pol.max_types);
- memset(chwall_bin_pol.conflict_aggregate_set,
- 0x0,
- sizeof(domaintype_t) * chwall_bin_pol.max_types);
- return chwall_init_state(&chwall_buf,
- chwall_bin_pol.ssidrefs,
- chwall_bin_pol.conflict_sets,
- chwall_bin_pol.running_types,
- chwall_bin_pol.conflict_aggregate_set,
- errors);
-}
-
-/*
- * Attempt to set the policy. This function must be called in test_only
- * mode first to only perform checks. A second call then does the
- * actual changes.
- */
-static int _chwall_update_policy(u8 *buf, u32 buf_size, int test_only,
- struct acm_sized_buffer *errors)
-{
- int rc = -EFAULT;
- /* policy write-locked already */
- struct acm_chwall_policy_buffer *chwall_buf =
- (struct acm_chwall_policy_buffer *) buf;
- void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL,
- *conflict_aggregate_set = NULL;
-
- /* 1. allocate new buffers */
- ssids =
- xmalloc_array(domaintype_t,
- chwall_buf->chwall_max_types *
- chwall_buf->chwall_max_ssidrefs);
- conflict_sets =
- xmalloc_array(domaintype_t,
- chwall_buf->chwall_max_conflictsets *
- chwall_buf->chwall_max_types);
- running_types =
- xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
- conflict_aggregate_set =
- xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
-
- if ( (ssids == NULL) || (conflict_sets == NULL) ||
- (running_types == NULL) || (conflict_aggregate_set == NULL) )
- goto error_free;
-
- /* 2. set new policy */
- if ( chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
- chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
- buf_size )
- goto error_free;
-
- arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
- sizeof(domaintype_t),
- chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
-
- if ( chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
- chwall_buf->chwall_max_types *
- chwall_buf->chwall_max_conflictsets > buf_size )
- goto error_free;
-
- arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
- sizeof(domaintype_t),
- chwall_buf->chwall_max_types *
- chwall_buf->chwall_max_conflictsets);
-
- /* we also use new state buffers since max_types can change */
- memset(running_types, 0,
- sizeof(domaintype_t) * chwall_buf->chwall_max_types);
- memset(conflict_aggregate_set, 0,
- sizeof(domaintype_t) * chwall_buf->chwall_max_types);
-
- /* 3. now re-calculate the state for the new policy based on
- * running domains; this can fail if new policy is conflicting
- * with running domains
- */
- if ( chwall_init_state(chwall_buf, ssids,
- conflict_sets, running_types,
- conflict_aggregate_set,
- errors))
- {
- printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
- __func__);
- goto error_free; /* new policy conflicts with running domains */
- }
-
- /* if this was only a test run, exit with ACM_OK */
- if ( test_only )
- {
- rc = ACM_OK;
- goto error_free;
- }
-
- /* 4. free old policy buffers, replace with new ones */
- chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
- chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
- chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
- xfree(chwall_bin_pol.ssidrefs);
- xfree(chwall_bin_pol.conflict_aggregate_set);
- xfree(chwall_bin_pol.running_types);
- xfree(chwall_bin_pol.conflict_sets);
- chwall_bin_pol.ssidrefs = ssids;
- chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
- chwall_bin_pol.running_types = running_types;
- chwall_bin_pol.conflict_sets = conflict_sets;
-
- return ACM_OK;
-
- error_free:
- if ( !test_only )
- printk("%s: ERROR setting policy.\n", __func__);
-
- xfree(ssids);
- xfree(conflict_sets);
- xfree(running_types);
- xfree(conflict_aggregate_set);
- return rc;
-}
-
-/*
- * This function MUST be called before the chwall_ste_policy function!
- */
-static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *errors)
-{
- struct acm_chwall_policy_buffer *chwall_buf =
- (struct acm_chwall_policy_buffer *) buf;
-
- if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
- return -EINVAL;
-
- /* rewrite the policy due to endianess */
- chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code);
- chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version);
- chwall_buf->chwall_max_types =
- be32_to_cpu(chwall_buf->chwall_max_types);
- chwall_buf->chwall_max_ssidrefs =
- be32_to_cpu(chwall_buf->chwall_max_ssidrefs);
- chwall_buf->chwall_max_conflictsets =
- be32_to_cpu(chwall_buf->chwall_max_conflictsets);
- chwall_buf->chwall_ssid_offset =
- be32_to_cpu(chwall_buf->chwall_ssid_offset);
- chwall_buf->chwall_conflict_sets_offset =
- be32_to_cpu(chwall_buf->chwall_conflict_sets_offset);
- chwall_buf->chwall_running_types_offset =
- be32_to_cpu(chwall_buf->chwall_running_types_offset);
- chwall_buf->chwall_conflict_aggregate_offset =
- be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset);
-
- /* policy type and version checks */
- if ( (chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
- (chwall_buf->policy_version != ACM_CHWALL_VERSION) )
- return -EINVAL;
-
- /* during boot dom0_chwall_ssidref is set */
- if ( is_bootpolicy &&
- (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs) )
- return -EINVAL;
-
- return _chwall_update_policy(buf, buf_size, 1, errors);
-}
-
-static int chwall_set_policy(u8 *buf, u32 buf_size)
-{
- return _chwall_update_policy(buf, buf_size, 0, NULL);
-}
-
-static int chwall_dump_stats(u8 * buf, u16 len)
-{
- /* no stats for Chinese Wall Policy */
- return 0;
-}
-
-static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
-{
- int i;
-
- /* fill in buffer */
- if ( chwall_bin_pol.max_types > len )
- return -EFAULT;
-
- if ( ssidref >= chwall_bin_pol.max_ssidrefs )
- return -EFAULT;
-
- /* read types for chwall ssidref */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- {
- if ( chwall_bin_pol.
- ssidrefs[ssidref * chwall_bin_pol.max_types + i] )
- buf[i] = 1;
- else
- buf[i] = 0;
- }
- return chwall_bin_pol.max_types;
-}
-
-/***************************
- * Authorization functions
- ***************************/
-
-/* -------- DOMAIN OPERATION HOOKS -----------*/
-
-static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
-{
- ssidref_t chwall_ssidref;
- int i, j;
-
- chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
-
- if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
- {
- printk("%s: ERROR chwall_ssidref > max(%x).\n",
- __func__, chwall_bin_pol.max_ssidrefs - 1);
- return ACM_ACCESS_DENIED;
- }
-
- /* A: chinese wall check for conflicts */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- if ( chwall_bin_pol.conflict_aggregate_set[i] &&
- chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + i] )
- {
- printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
- return ACM_ACCESS_DENIED;
- }
-
- /* B: chinese wall conflict set adjustment (so that other
- * other domains simultaneously created are evaluated against
- * this new set)
- */
- for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
- {
- int common = 0;
- /* check if conflict_set_i and ssidref have common types */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.
- conflict_sets[i * chwall_bin_pol.max_types + j]
- && chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j] )
- {
- common = 1;
- break;
- }
- if ( common == 0 )
- continue; /* try next conflict set */
- /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.
- conflict_sets[i * chwall_bin_pol.max_types + j]
- && !chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j])
- chwall_bin_pol.conflict_aggregate_set[j]++;
- }
- return ACM_ACCESS_PERMITTED;
-}
-
-
-static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
-{
- int i;
- ssidref_t chwall_ssidref;
-
- chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
- /* adjust types ref-count for running domains */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- chwall_bin_pol.running_types[i] +=
- chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + i];
-}
-
-
-/*
- * To be called when creating a domain. If this call is unsuccessful,
- * no state changes have occurred (adjustments of counters etc.). If it
- * was successful, state was changed and can be undone using
- * chwall_domain_destroy.
- */
-static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref,
- domid_t domid)
-{
- int rc;
- read_lock(&acm_bin_pol_rwlock);
-
- rc = _chwall_pre_domain_create(subject_ssid, ssidref);
- if ( rc == ACM_ACCESS_PERMITTED )
- _chwall_post_domain_create(domid, ssidref);
-
- read_unlock(&acm_bin_pol_rwlock);
- return rc;
-}
-
-/*
- * This function undoes everything a successful call to
- * chwall_domain_create has done.
- */
-static void chwall_domain_destroy(void *object_ssid, struct domain *d)
-{
- int i, j;
- struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
- (struct acm_ssid_domain *)
- object_ssid);
- ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
-
- read_lock(&acm_bin_pol_rwlock);
-
- /* adjust running types set */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- chwall_bin_pol.running_types[i] -=
- chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + i];
-
- /* roll-back: re-adjust conflicting types aggregate */
- for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
- {
- int common = 0;
- /* check if conflict_set_i and ssidref have common types */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.conflict_sets[i * chwall_bin_pol.max_types + j]
- && chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j])
- {
- common = 1;
- break;
- }
- if ( common == 0 )
- {
- /* try next conflict set, this one does not include
- any type of chwall_ssidref */
- continue;
- }
-
- /* now add types of the conflict set to conflict_aggregate_set
- (except types in chwall_ssidref) */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.
- conflict_sets[i * chwall_bin_pol.max_types + j]
- && !chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j])
- chwall_bin_pol.conflict_aggregate_set[j]--;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return;
-}
-
-
-static int chwall_is_default_policy(void)
-{
- static const domaintype_t def_policy[2] = { 0x0, 0x0 };
- return ( ( chwall_bin_pol.max_types == 1 ) &&
- ( chwall_bin_pol.max_ssidrefs == 2 ) &&
- ( memcmp(chwall_bin_pol.ssidrefs,
- def_policy,
- sizeof(def_policy)) == 0 ) );
-}
-
-
-static int chwall_is_in_conflictset(ssidref_t ssidref1)
-{
- /* is ssidref1 in conflict with any running domains ? */
- int rc = 0;
- int i, j;
- ssidref_t ssid_chwall;
-
- read_lock(&acm_bin_pol_rwlock);
-
- ssid_chwall = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref1);
-
- if ( ssid_chwall >= 0 && ssid_chwall < chwall_bin_pol.max_ssidrefs ) {
- for ( i = 0; i < chwall_bin_pol.max_conflictsets && rc == 0; i++ ) {
- for ( j = 0; j < chwall_bin_pol.max_types; j++ ) {
- if ( chwall_bin_pol.conflict_aggregate_set
- [i * chwall_bin_pol.max_types + j] &&
- chwall_bin_pol.ssidrefs
- [ssid_chwall * chwall_bin_pol.max_types + j])
- {
- rc = 1;
- break;
- }
- }
- }
- } else {
- rc = 1;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return rc;
-}
-
-
-struct acm_operations acm_chinesewall_ops = {
- /* policy management services */
- .init_domain_ssid = chwall_init_domain_ssid,
- .free_domain_ssid = chwall_free_domain_ssid,
- .dump_binary_policy = chwall_dump_policy,
- .test_binary_policy = chwall_test_policy,
- .set_binary_policy = chwall_set_policy,
- .dump_statistics = chwall_dump_stats,
- .dump_ssid_types = chwall_dump_ssid_types,
- /* domain management control hooks */
- .domain_create = chwall_domain_create,
- .domain_destroy = chwall_domain_destroy,
- /* event channel control hooks */
- .pre_eventchannel_unbound = NULL,
- .fail_eventchannel_unbound = NULL,
- .pre_eventchannel_interdomain = NULL,
- .fail_eventchannel_interdomain = NULL,
- /* grant table control hooks */
- .pre_grant_map_ref = NULL,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = NULL,
- .fail_grant_setup = NULL,
- /* generic domain-requested decision hooks */
- .sharing = NULL,
- .authorization = NULL,
- .conflictset = chwall_is_in_conflictset,
-
- .is_default_policy = chwall_is_default_policy,
-};
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_core.c b/xen/xsm/acm/acm_core.c
deleted file mode 100644
index b8b7b4f59c..0000000000
--- a/xen/xsm/acm/acm_core.c
+++ /dev/null
@@ -1,406 +0,0 @@
-#/****************************************************************
- * acm_core.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype access control module (ACM)
- * This file handles initialization of the ACM
- * as well as initializing/freeing security
- * identifiers for domains (it calls on active
- * policy hook functions).
- *
- */
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <xen/multiboot.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-#include <xsm/xsm.h>
-
-/* debug:
- * include/xsm/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
- * define/undefine this constant to receive / suppress any
- * security hook debug output of sHype
- *
- * include/xsm/acm/acm_hooks.h defines a constant ACM_DEBUG
- * define/undefine this constant to receive non-hook-related
- * debug output.
- */
-
-/* function prototypes */
-void acm_init_chwall_policy(void);
-void acm_init_ste_policy(void);
-
-extern struct acm_operations acm_chinesewall_ops,
- acm_simple_type_enforcement_ops, acm_null_ops;
-
-extern struct xsm_operations acm_xsm_ops;
-
-/* global ACM policy (now dynamically determined at boot time) */
-u16 acm_active_security_policy = ACM_POLICY_UNDEFINED;
-
-/* global ops structs called by the hooks */
-struct acm_operations *acm_primary_ops = NULL;
-/* called in hook if-and-only-if primary succeeds */
-struct acm_operations *acm_secondary_ops = NULL;
-
-/* acm global binary policy (points to 'local' primary and secondary policies */
-struct acm_binary_policy acm_bin_pol;
-/* acm binary policy lock */
-DEFINE_RWLOCK(acm_bin_pol_rwlock);
-
-/* ACM's only accepted policy name during boot */
-char polname[80];
-char *acm_accepted_boot_policy_name = NULL;
-
-/* a lits of all chained ssid structures */
-LIST_HEAD(ssid_list);
-DEFINE_RWLOCK(ssid_list_rwlock);
-
-static void __init set_dom0_ssidref(const char *val)
-{
- /* expected format:
- ssidref=<hex number>:<policy name>
- Policy name must not have a 'space'.
- */
- const char *c;
- int lo, hi;
- int i;
- int dom0_ssidref = simple_strtoull(val, &c, 0);
-
- if (!strncmp(&c[0],":ACM:", 5)) {
- lo = dom0_ssidref & 0xffff;
- if (lo < ACM_MAX_NUM_TYPES && lo >= 1)
- dom0_chwall_ssidref = lo;
- hi = dom0_ssidref >> 16;
- if (hi < ACM_MAX_NUM_TYPES && hi >= 1)
- dom0_ste_ssidref = hi;
- for (i = 0; i < sizeof(polname); i++) {
- polname[i] = c[5+i];
- if (polname[i] == '\0' || polname[i] == '\t' ||
- polname[i] == '\n' || polname[i] == ' ' ||
- polname[i] == ':') {
- break;
- }
- }
- polname[i] = 0;
- acm_accepted_boot_policy_name = polname;
- }
-}
-
-custom_param("ssidref", set_dom0_ssidref);
-
-int
-acm_set_policy_reference(u8 *buf, u32 buf_size)
-{
- char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer));
- struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
-
- if (acm_accepted_boot_policy_name != NULL) {
- if (strcmp(acm_accepted_boot_policy_name, name)) {
- printk("Policy's name '%s' is not the expected one '%s'.\n",
- name, acm_accepted_boot_policy_name);
- return ACM_ERROR;
- }
- }
-
- acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len));
-
- if (!acm_bin_pol.policy_reference_name)
- return -ENOMEM;
- strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len));
-
- printk("%s: Activating policy %s\n", __func__,
- acm_bin_pol.policy_reference_name);
- return 0;
-}
-
-int
-acm_dump_policy_reference(u8 *buf, u32 buf_size)
-{
- struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
- int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
-
- ret = (ret + 7) & ~7;
- if (buf_size < ret)
- return -EINVAL;
-
- memset(buf, 0, ret);
- pr_buf->len = cpu_to_be32(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
- strlcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
- acm_bin_pol.policy_reference_name,
- be32_to_cpu(pr_buf->len));
- return ret;
-}
-
-int
-acm_init_binary_policy(u32 policy_code)
-{
- int ret = ACM_OK;
-
- acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
- acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
-
- write_lock(&acm_bin_pol_rwlock);
-
- /* set primary policy component */
- switch ((policy_code) & 0x0f)
- {
-
- case ACM_CHINESE_WALL_POLICY:
- acm_init_chwall_policy();
- acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
- acm_primary_ops = &acm_chinesewall_ops;
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- acm_init_ste_policy();
- acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
- acm_primary_ops = &acm_simple_type_enforcement_ops;
- break;
-
- case ACM_NULL_POLICY:
- acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
- acm_primary_ops = &acm_null_ops;
- break;
-
- default:
- /* Unknown policy not allowed primary */
- ret = -EINVAL;
- goto out;
- }
-
- /* secondary policy component part */
- switch ((policy_code) >> 4)
- {
-
- case ACM_NULL_POLICY:
- acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
- acm_secondary_ops = &acm_null_ops;
- break;
-
- case ACM_CHINESE_WALL_POLICY:
- if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
- { /* not a valid combination */
- ret = -EINVAL;
- goto out;
- }
- acm_init_chwall_policy();
- acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
- acm_secondary_ops = &acm_chinesewall_ops;
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
- { /* not a valid combination */
- ret = -EINVAL;
- goto out;
- }
- acm_init_ste_policy();
- acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
- acm_secondary_ops = &acm_simple_type_enforcement_ops;
- break;
-
- default:
- ret = -EINVAL;
- goto out;
- }
-
- out:
- write_unlock(&acm_bin_pol_rwlock);
- return ret;
-}
-
-int
-acm_is_policy(char *buf, unsigned long len)
-{
- struct acm_policy_buffer *pol;
-
- if (buf == NULL || len < sizeof(struct acm_policy_buffer))
- return 0;
-
- pol = (struct acm_policy_buffer *)buf;
- return be32_to_cpu(pol->magic) == ACM_MAGIC;
-}
-
-
-static int
-acm_setup(char *policy_start,
- unsigned long policy_len,
- int is_bootpolicy)
-{
- int rc = ACM_OK;
- struct acm_policy_buffer *pol;
-
- if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
- return rc;
-
- pol = (struct acm_policy_buffer *)policy_start;
- if (be32_to_cpu(pol->magic) != ACM_MAGIC)
- return rc;
-
- rc = do_acm_set_policy((void *)policy_start, (u32)policy_len,
- is_bootpolicy,
- NULL, NULL, NULL);
- if (rc == ACM_OK)
- {
- printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start);
- }
- else
- {
- printk("Invalid policy.\n");
- /* load default policy later */
- acm_active_security_policy = ACM_POLICY_UNDEFINED;
- }
- return rc;
-}
-
-
-int
-acm_init(void)
-{
- int ret = ACM_OK;
-
- printk("ACM-XSM: Initializing.\n");
-
- /* first try to load the boot policy (uses its own locks) */
- acm_setup(policy_buffer, policy_size, 1);
-
- /* a user-provided policy may have any name; only matched during boot */
- acm_accepted_boot_policy_name = NULL;
-
- if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
- {
- printk("%s: Enforcing %s boot policy.\n", __func__,
- ACM_POLICY_NAME(acm_active_security_policy));
- goto out;
- }
- /* else continue with the minimal hardcoded default startup policy */
- printk("%s: Loading default policy (%s).\n",
- __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
-
- /* (re-)set dom-0 ssidref to default */
- dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001;
-
- if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
- ret = -EINVAL;
- goto out;
- }
- acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
- if (acm_active_security_policy != ACM_NULL_POLICY)
- acm_bin_pol.policy_reference_name = "DEFAULT";
- else
- acm_bin_pol.policy_reference_name = "NULL";
-
- out:
- if (ret != ACM_OK)
- {
- printk("%s: Error initializing policies.\n", __func__);
- /* here one could imagine a clean panic */
- return -EINVAL;
- }
-
- if (register_xsm(&acm_xsm_ops))
- panic("ACM-XSM: Unable to register with XSM.\n");
-
- return ret;
-}
-
-xsm_initcall(acm_init);
-
-int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref)
-{
- struct acm_ssid_domain *ssid;
- int ret1, ret2;
- if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
- {
- return ACM_INIT_SSID_ERROR;
- }
-
- INIT_LIST_HEAD(&ssid->node);
- ssid->datatype = ACM_DATATYPE_domain;
- ssid->subject = subj;
- ssid->domainid = subj->domain_id;
- ssid->primary_ssid = NULL;
- ssid->secondary_ssid = NULL;
-
- if (acm_active_security_policy != ACM_NULL_POLICY)
- ssid->ssidref = ssidref;
- else
- ssid->ssidref = ACM_DEFAULT_SSID;
-
- subj->ssid = ssid;
- /* now fill in primary and secondary parts; we only get here through hooks */
- if (acm_primary_ops->init_domain_ssid != NULL)
- ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
- else
- ret1 = ACM_OK;
-
- if (acm_secondary_ops->init_domain_ssid != NULL)
- ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
- else
- ret2 = ACM_OK;
-
- if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
- {
- printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
- __func__, subj->domain_id);
- acm_free_domain_ssid(subj);
- return ACM_INIT_SSID_ERROR;
- }
-
- printkd("%s: assigned domain %x the ssidref=%x.\n",
- __func__, subj->domain_id, ssid->ssidref);
- return ACM_OK;
-}
-
-
-void
-acm_free_domain_ssid(struct domain *d)
-{
- struct acm_ssid_domain *ssid = d->ssid;
-
- /* domain is already gone, just ssid is left */
- if (ssid == NULL)
- return;
-
- ssid->subject = NULL;
- if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
- acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
- ssid->primary_ssid = NULL;
- if (acm_secondary_ops->free_domain_ssid != NULL)
- acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
- ssid->secondary_ssid = NULL;
-
- xfree(ssid);
- d->ssid = NULL;
-
- printkd("%s: Freed individual domain ssid (domain=%02x).\n",
- __func__, id);
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_null_hooks.c b/xen/xsm/acm/acm_null_hooks.c
deleted file mode 100644
index 440ee61bd8..0000000000
--- a/xen/xsm/acm/acm_null_hooks.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************
- * acm_null_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-
-#include <xsm/acm/acm_hooks.h>
-
-static int
-null_init_domain_ssid(void **ssid, ssidref_t ssidref)
-{
- return ACM_OK;
-}
-
-static void
-null_free_domain_ssid(void *ssid)
-{
- return;
-}
-
-static int
-null_dump_binary_policy(u8 *buf, u32 buf_size)
-{
- return 0;
-}
-
-static int
-null_test_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *errors)
-{
- return ACM_OK;
-}
-
-static int
-null_set_binary_policy(u8 *buf, u32 buf_size)
-{
- return ACM_OK;
-}
-
-static int
-null_dump_stats(u8 *buf, u16 buf_size)
-{
- /* no stats for NULL policy */
- return 0;
-}
-
-static int
-null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
-{
- /* no types */
- return 0;
-}
-
-
-/* now define the hook structure similarly to LSM */
-struct acm_operations acm_null_ops = {
- .init_domain_ssid = null_init_domain_ssid,
- .free_domain_ssid = null_free_domain_ssid,
- .dump_binary_policy = null_dump_binary_policy,
- .test_binary_policy = null_test_binary_policy,
- .set_binary_policy = null_set_binary_policy,
- .dump_statistics = null_dump_stats,
- .dump_ssid_types = null_dump_ssid_types,
- /* domain management control hooks */
- .domain_create = NULL,
- .domain_destroy = NULL,
- /* event channel control hooks */
- .pre_eventchannel_unbound = NULL,
- .fail_eventchannel_unbound = NULL,
- .pre_eventchannel_interdomain = NULL,
- .fail_eventchannel_interdomain = NULL,
- /* grant table control hooks */
- .pre_grant_map_ref = NULL,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = NULL,
- .fail_grant_setup = NULL
-};
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_ops.c b/xen/xsm/acm/acm_ops.c
deleted file mode 100644
index 5836241a98..0000000000
--- a/xen/xsm/acm/acm_ops.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/******************************************************************************
- * acm_ops.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * Process acm command requests from guest OS.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <public/xsm/acm.h>
-#include <public/xsm/acm_ops.h>
-#include <xen/sched.h>
-#include <xen/event.h>
-#include <xen/trace.h>
-#include <xen/console.h>
-#include <xen/guest_access.h>
-#include <xsm/acm/acm_hooks.h>
-
-#ifndef ACM_SECURITY
-
-long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
-{
- return -ENOSYS;
-}
-
-#else
-
-int acm_authorize_acm_ops(struct domain *d)
-{
- /* currently, policy management functions are restricted to privileged domains */
- return (IS_PRIV(d) ? 0 : -EPERM);
-}
-
-
-long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
-{
- long rc = -EFAULT;
- struct xen_acmctl curop, *op = &curop;
-
- if (acm_authorize_acm_ops(current->domain))
- return -EPERM;
-
- if ( copy_from_guest(op, u_acmctl, 1) )
- return -EFAULT;
-
- if (op->interface_version != ACM_INTERFACE_VERSION)
- return -EACCES;
-
- switch ( op->cmd )
- {
-
- case ACMOP_setpolicy: {
- rc = acm_set_policy(op->u.setpolicy.pushcache,
- op->u.setpolicy.pushcache_size);
- break;
- }
-
- case ACMOP_getpolicy: {
- rc = acm_get_policy(op->u.getpolicy.pullcache,
- op->u.getpolicy.pullcache_size);
- break;
- }
-
- case ACMOP_dumpstats: {
- rc = acm_dump_statistics(op->u.dumpstats.pullcache,
- op->u.dumpstats.pullcache_size);
- break;
- }
-
- case ACMOP_getssid: {
- ssidref_t ssidref;
-
- if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
- ssidref = op->u.getssid.id.ssidref;
- else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
- {
- struct domain *subj = rcu_lock_domain_by_id(op->u.getssid.id.domainid);
- if (!subj)
- {
- rc = -ESRCH; /* domain not found */
- break;
- }
- if (subj->ssid == NULL)
- {
- rcu_unlock_domain(subj);
- rc = -ESRCH;
- break;
- }
- ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
- rcu_unlock_domain(subj);
- }
- else
- {
- rc = -ESRCH;
- break;
- }
- rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
- op->u.getssid.ssidbuf_size);
- break;
- }
-
- case ACMOP_getdecision: {
- ssidref_t ssidref1, ssidref2;
-
- if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
- ssidref1 = op->u.getdecision.id1.ssidref;
- else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
- {
- struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
- if (!subj)
- {
- rc = -ESRCH; /* domain not found */
- break;
- }
- if (subj->ssid == NULL)
- {
- rcu_unlock_domain(subj);
- rc = -ESRCH;
- break;
- }
- ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
- rcu_unlock_domain(subj);
- }
- else
- {
- rc = -ESRCH;
- break;
- }
- if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
- ssidref2 = op->u.getdecision.id2.ssidref;
- else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
- {
- struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
- if (!subj)
- {
- rc = -ESRCH; /* domain not found */
- break;
- }
- if (subj->ssid == NULL)
- {
- rcu_unlock_domain(subj);
- rc = -ESRCH;
- break;
- }
- ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
- rcu_unlock_domain(subj);
- }
- else
- {
- rc = -ESRCH;
- break;
- }
- rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
-
- if (rc == ACM_ACCESS_PERMITTED)
- {
- op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
- rc = 0;
- }
- else if (rc == ACM_ACCESS_DENIED)
- {
- op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
- rc = 0;
- }
- else
- rc = -ESRCH;
-
- if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
- rc = -EFAULT;
- break;
- }
-
- case ACMOP_chgpolicy: {
- rc = acm_change_policy(&op->u.change_policy);
- break;
- }
-
- case ACMOP_relabeldoms: {
- rc = acm_relabel_domains(&op->u.relabel_doms);
- break;
- }
-
- default:
- rc = -ENOSYS;
- break;
- }
-
- return rc;
-}
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_policy.c b/xen/xsm/acm/acm_policy.c
deleted file mode 100644
index 31219d9aae..0000000000
--- a/xen/xsm/acm/acm_policy.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/****************************************************************
- * acm_policy.c
- *
- * Copyright (C) 2005-2007 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype access control policy management for Xen.
- * This interface allows policy tools in authorized
- * domains to interact with the Xen access control module
- *
- */
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <xen/guest_access.h>
-#include <public/xen.h>
-#include <xsm/acm/acm_core.h>
-#include <public/xsm/acm_ops.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-#include <asm/current.h>
-
-static int acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
- struct acm_sized_buffer *errors);
-static void acm_doms_change_ssidref(ssidref_t (*translator)
- (const struct acm_ssid_domain *,
- const struct acm_sized_buffer *),
- struct acm_sized_buffer *translation_map);
-static void acm_doms_restore_ssidref(void);
-static ssidref_t oldssid_to_newssid(const struct acm_ssid_domain *,
- const struct acm_sized_buffer *map);
-
-
-int
-acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
-{
- u8 *policy_buffer = NULL;
- int ret = -EFAULT;
-
- if ( buf_size < sizeof(struct acm_policy_buffer) )
- return -EFAULT;
-
- /* copy buffer from guest domain */
- if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- if ( copy_from_guest(policy_buffer, buf, buf_size) )
- {
- printk("%s: Error copying!\n",__func__);
- goto error_free;
- }
- ret = do_acm_set_policy(policy_buffer, buf_size, 0,
- NULL, NULL, NULL);
-
- error_free:
- xfree(policy_buffer);
- return ret;
-}
-
-
-/*
- * Update the policy of the running system by:
- * - deleting ssidrefs that are not in the new policy anymore
- * -> no running domain may use such an ssidref
- * - assign new ssidrefs to domains based on their old ssidrefs
- *
- */
-static int
-_acm_update_policy(void *buf, u32 buf_size, int is_bootpolicy,
- struct acm_policy_buffer *pol,
- struct acm_sized_buffer *deletions,
- struct acm_sized_buffer *ssidchanges,
- struct acm_sized_buffer *errors)
-{
- uint32_t offset, length;
- static int require_update = 0;
-
- write_lock(&acm_bin_pol_rwlock);
-
- if ( require_update != 0 &&
- ( deletions == NULL || ssidchanges == NULL ) )
- goto error_lock_free;
-
- require_update = 1;
- /*
- first some tests to check compatibility of new policy with
- current state of system/domains
- */
-
- /* if ssidrefs are to be deleted, make sure no domain is using them */
- if ( deletions != NULL )
- if ( acm_check_deleted_ssidrefs(deletions, errors) )
- goto error_lock_free_nossidchange;
-
- if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
- /* assign all running domains new ssidrefs as requested */
- acm_doms_change_ssidref(oldssid_to_newssid, ssidchanges);
-
- /* test primary policy data with the new ssidrefs */
- offset = be32_to_cpu(pol->primary_buffer_offset);
- length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
-
- if ( (offset + length) > buf_size ||
- acm_primary_ops->test_binary_policy(buf + offset, length,
- is_bootpolicy,
- errors))
- goto error_lock_free;
-
- /* test secondary policy data with the new ssidrefs */
- offset = be32_to_cpu(pol->secondary_buffer_offset);
- length = be32_to_cpu(pol->len) - offset;
- if ( (offset + length) > buf_size ||
- acm_secondary_ops->test_binary_policy(buf + offset, length,
- is_bootpolicy,
- errors))
- goto error_lock_free;
-
- /* end of testing --- now real updates */
-
- offset = be32_to_cpu(pol->policy_reference_offset);
- length = be32_to_cpu(pol->primary_buffer_offset) - offset;
-
- /* set label reference name */
- if ( (offset + length) > buf_size ||
- acm_set_policy_reference(buf + offset, length) )
- goto error_lock_free;
-
- /* set primary policy data */
- offset = be32_to_cpu(pol->primary_buffer_offset);
- length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
-
- if ( acm_primary_ops->set_binary_policy(buf + offset, length) )
- goto error_lock_free;
-
- /* set secondary policy data */
- offset = be32_to_cpu(pol->secondary_buffer_offset);
- length = be32_to_cpu(pol->len) - offset;
- if ( acm_secondary_ops->set_binary_policy(buf + offset, length) )
- goto error_lock_free;
-
- memcpy(&acm_bin_pol.xml_pol_version,
- &pol->xml_pol_version,
- sizeof(acm_bin_pol.xml_pol_version));
-
- memcpy(&acm_bin_pol.xml_policy_hash,
- pol->xml_policy_hash,
- sizeof(acm_bin_pol.xml_policy_hash));
-
- if ( acm_primary_ops->is_default_policy() &&
- acm_secondary_ops->is_default_policy() )
- require_update = 0;
-
- write_unlock(&acm_bin_pol_rwlock);
-
- return ACM_OK;
-
-error_lock_free:
- if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
- {
- acm_doms_restore_ssidref();
- }
-error_lock_free_nossidchange:
- do_chwall_init_state_curr(NULL);
- write_unlock(&acm_bin_pol_rwlock);
-
- return -EFAULT;
-}
-
-
-int
-do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *deletions,
- struct acm_sized_buffer *ssidchanges,
- struct acm_sized_buffer *errors)
-{
- struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
-
- /* some sanity checking */
- if ( (be32_to_cpu(pol->magic) != ACM_MAGIC) ||
- (buf_size != be32_to_cpu(pol->len)) ||
- (be32_to_cpu(pol->policy_version) != ACM_POLICY_VERSION) )
- {
- printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
- goto error_free;
- }
-
- if ( acm_active_security_policy == ACM_POLICY_UNDEFINED )
- {
- /* setup the policy with the boot policy */
- if ( acm_init_binary_policy(
- (be32_to_cpu(pol->secondary_policy_code) << 4) |
- be32_to_cpu(pol->primary_policy_code)) )
- {
- goto error_free;
- }
- acm_active_security_policy = (acm_bin_pol.secondary_policy_code << 4) |
- acm_bin_pol.primary_policy_code;
- }
-
- /* once acm_active_security_policy is set, it cannot be changed */
- if ( (be32_to_cpu(pol->primary_policy_code) !=
- acm_bin_pol.primary_policy_code) ||
- (be32_to_cpu(pol->secondary_policy_code) !=
- acm_bin_pol.secondary_policy_code) )
- {
- printkd("%s: Wrong policy type in boot policy!\n", __func__);
- goto error_free;
- }
-
- return _acm_update_policy(buf, buf_size, is_bootpolicy,
- pol,
- deletions, ssidchanges,
- errors);
-
- error_free:
- printk("%s: Error setting policy.\n", __func__);
- return -EFAULT;
-}
-
-int
-acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
-{
- u8 *policy_buffer;
- int ret;
- struct acm_policy_buffer *bin_pol;
-
- if ( buf_size < sizeof(struct acm_policy_buffer) )
- return -EFAULT;
-
- if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- read_lock(&acm_bin_pol_rwlock);
-
- bin_pol = (struct acm_policy_buffer *)policy_buffer;
- bin_pol->magic = cpu_to_be32(ACM_MAGIC);
- bin_pol->primary_policy_code =
- cpu_to_be32(acm_bin_pol.primary_policy_code);
- bin_pol->secondary_policy_code =
- cpu_to_be32(acm_bin_pol.secondary_policy_code);
-
- bin_pol->len = cpu_to_be32(sizeof(struct acm_policy_buffer));
- bin_pol->policy_reference_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
- bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
- bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
-
- memcpy(&bin_pol->xml_pol_version,
- &acm_bin_pol.xml_pol_version,
- sizeof(struct acm_policy_version));
-
- memcpy(&bin_pol->xml_policy_hash,
- &acm_bin_pol.xml_policy_hash,
- sizeof(acm_bin_pol.xml_policy_hash));
-
- ret = acm_dump_policy_reference(
- policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset),
- buf_size - be32_to_cpu(bin_pol->policy_reference_offset));
-
- if ( ret < 0 )
- goto error_free_unlock;
-
- bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
- bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
-
- ret = acm_primary_ops->dump_binary_policy(
- policy_buffer + be32_to_cpu(bin_pol->primary_buffer_offset),
- buf_size - be32_to_cpu(bin_pol->primary_buffer_offset));
-
- if ( ret < 0 )
- goto error_free_unlock;
-
- bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
- bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
-
- ret = acm_secondary_ops->dump_binary_policy(
- policy_buffer + be32_to_cpu(bin_pol->secondary_buffer_offset),
- buf_size - be32_to_cpu(bin_pol->secondary_buffer_offset));
-
- if ( ret < 0 )
- goto error_free_unlock;
-
- bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
- if ( copy_to_guest(buf, policy_buffer, be32_to_cpu(bin_pol->len)) )
- goto error_free_unlock;
-
- read_unlock(&acm_bin_pol_rwlock);
- xfree(policy_buffer);
-
- return ACM_OK;
-
- error_free_unlock:
- read_unlock(&acm_bin_pol_rwlock);
- printk("%s: Error getting policy.\n", __func__);
- xfree(policy_buffer);
-
- return -EFAULT;
-}
-
-int
-acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
-{
- /* send stats to user space */
- u8 *stats_buffer;
- int len1, len2;
- struct acm_stats_buffer acm_stats;
-
- if ( (stats_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- read_lock(&acm_bin_pol_rwlock);
-
- len1 = acm_primary_ops->dump_statistics(
- stats_buffer + sizeof(struct acm_stats_buffer),
- buf_size - sizeof(struct acm_stats_buffer));
- if ( len1 < 0 )
- goto error_lock_free;
-
- len2 = acm_secondary_ops->dump_statistics(
- stats_buffer + sizeof(struct acm_stats_buffer) + len1,
- buf_size - sizeof(struct acm_stats_buffer) - len1);
- if ( len2 < 0 )
- goto error_lock_free;
-
- acm_stats.magic = cpu_to_be32(ACM_MAGIC);
- acm_stats.primary_policy_code =
- cpu_to_be32(acm_bin_pol.primary_policy_code);
- acm_stats.secondary_policy_code =
- cpu_to_be32(acm_bin_pol.secondary_policy_code);
- acm_stats.primary_stats_offset =
- cpu_to_be32(sizeof(struct acm_stats_buffer));
- acm_stats.secondary_stats_offset =
- cpu_to_be32(sizeof(struct acm_stats_buffer) + len1);
- acm_stats.len = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1 + len2);
-
- memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
-
- if ( copy_to_guest(buf,
- stats_buffer,
- sizeof(struct acm_stats_buffer) + len1 + len2) )
- goto error_lock_free;
-
- read_unlock(&acm_bin_pol_rwlock);
- xfree(stats_buffer);
-
- return ACM_OK;
-
- error_lock_free:
- read_unlock(&acm_bin_pol_rwlock);
- xfree(stats_buffer);
-
- return -EFAULT;
-}
-
-
-int
-acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
-{
- /* send stats to user space */
- u8 *ssid_buffer;
- int ret;
- struct acm_ssid_buffer *acm_ssid;
- if ( buf_size < sizeof(struct acm_ssid_buffer) )
- return -EFAULT;
-
- if ( (ssid_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- read_lock(&acm_bin_pol_rwlock);
-
- acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
- acm_ssid->len = sizeof(struct acm_ssid_buffer);
- acm_ssid->ssidref = ssidref;
- acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
- acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
-
- acm_ssid->policy_reference_offset = acm_ssid->len;
- ret = acm_dump_policy_reference(
- ssid_buffer + acm_ssid->policy_reference_offset,
- buf_size - acm_ssid->policy_reference_offset);
- if ( ret < 0 )
- goto error_free_unlock;
-
- acm_ssid->len += ret;
- acm_ssid->primary_types_offset = acm_ssid->len;
-
- /* ret >= 0 --> ret == max_types */
- ret = acm_primary_ops->dump_ssid_types(
- ACM_PRIMARY(ssidref),
- ssid_buffer + acm_ssid->primary_types_offset,
- buf_size - acm_ssid->primary_types_offset);
- if ( ret < 0 )
- goto error_free_unlock;
-
- acm_ssid->len += ret;
- acm_ssid->primary_max_types = ret;
- acm_ssid->secondary_types_offset = acm_ssid->len;
-
- ret = acm_secondary_ops->dump_ssid_types(
- ACM_SECONDARY(ssidref),
- ssid_buffer + acm_ssid->secondary_types_offset,
- buf_size - acm_ssid->secondary_types_offset);
- if ( ret < 0 )
- goto error_free_unlock;
-
- acm_ssid->len += ret;
- acm_ssid->secondary_max_types = ret;
-
- if ( copy_to_guest(buf, ssid_buffer, acm_ssid->len) )
- goto error_free_unlock;
-
- read_unlock(&acm_bin_pol_rwlock);
- xfree(ssid_buffer);
-
- return ACM_OK;
-
- error_free_unlock:
- read_unlock(&acm_bin_pol_rwlock);
- printk("%s: Error getting ssid.\n", __func__);
- xfree(ssid_buffer);
-
- return -ENOMEM;
-}
-
-int
-acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook)
-{
- int ret = ACM_ACCESS_DENIED;
-
- read_lock(&acm_bin_pol_rwlock);
-
- switch ( hook )
- {
-
- case ACMHOOK_sharing:
- /* Sharing hook restricts access in STE policy only */
- ret = acm_sharing(ssidref1, ssidref2);
- break;
-
- case ACMHOOK_authorization:
- ret = acm_authorization(ssidref1, ssidref2);
- break;
-
- case ACMHOOK_conflictset:
- ret = acm_conflictset(ssidref1);
-
- default:
- /* deny */
- break;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n",
- __func__, ssidref1, ssidref2,
- (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED");
-
- return ret;
-}
-
-
-
-/*
- Check if an ssidref of the current policy type is being used by any
- domain.
- */
-static int
-acm_check_used_ssidref(uint32_t policy_type, uint32_t search_ssidref,
- struct acm_sized_buffer *errors)
-{
- int rc = 0;
- struct acm_ssid_domain *rawssid;
-
- read_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ssidref_t ssidref;
- void *s = GET_SSIDP(policy_type, rawssid);
-
- if ( policy_type == ACM_CHINESE_WALL_POLICY )
- {
- ssidref = ((struct chwall_ssid *)s)->chwall_ssidref;
- } else {
- ssidref = ((struct ste_ssid *)s)->ste_ssidref;
- }
- gdprintk(XENLOG_INFO,"domid=%d: search ssidref=%d, ssidref=%d\n",
- rawssid->domainid,search_ssidref,ssidref);
- if ( ssidref == search_ssidref )
- {
- /* one is enough */
- acm_array_append_tuple(errors, ACM_SSIDREF_IN_USE, search_ssidref);
- rc = 1;
- break;
- }
- }
-
- read_unlock(&ssid_list_rwlock);
-
- return rc;
-}
-
-
-/*
- * Translate a current ssidref into its future representation under
- * the new policy.
- * The map provides translation of ssidrefs from old to new in tuples
- * of (old ssidref, new ssidref).
- */
-static ssidref_t
-oldssid_to_newssid(const struct acm_ssid_domain *rawssid,
- const struct acm_sized_buffer *map)
-{
- uint i;
-
- if ( rawssid != NULL )
- {
- ssidref_t ssid = rawssid->ssidref & 0xffff;
- for ( i = 0; i + 1 < map->num_items; i += 2 )
- {
- if ( map->array[i] == ssid )
- {
- return (map->array[i+1] << 16 | map->array[i+1]);
- }
- }
- }
- return ACM_INVALID_SSIDREF;
-}
-
-
-/*
- * Assign an ssidref to the CHWALL policy component of the domain
- */
-static void
-acm_pri_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
- ssidref_t new_ssid)
-{
- struct chwall_ssid *chwall = (struct chwall_ssid *)rawssid->primary_ssid;
- chwall->chwall_ssidref = new_ssid;
-}
-
-
-/*
- * Assign an ssidref to the STE policy component of the domain
- */
-static void
-acm_sec_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
- ssidref_t new_ssid)
-{
- struct ste_ssid *ste = (struct ste_ssid *)rawssid->secondary_ssid;
- ste->ste_ssidref = new_ssid;
-}
-
-/*
- Change the ssidrefs on each domain using a passed translation function;
- */
-static void
-acm_doms_change_ssidref(ssidref_t (*translator_fn)
- (const struct acm_ssid_domain *,
- const struct acm_sized_buffer *),
- struct acm_sized_buffer *translation_map)
-{
- struct acm_ssid_domain *rawssid;
-
- write_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ssidref_t new_ssid;
-
- rawssid->old_ssidref = rawssid->ssidref;
-
- new_ssid = translator_fn(rawssid, translation_map);
- if ( new_ssid == ACM_INVALID_SSIDREF )
- {
- /* means no mapping found, so no change -- old = new */
- continue;
- }
-
- acm_pri_policy_assign_ssidref(rawssid, ACM_PRIMARY (new_ssid) );
- acm_sec_policy_assign_ssidref(rawssid, ACM_SECONDARY(new_ssid) );
-
- rawssid->ssidref = new_ssid;
- }
-
- write_unlock(&ssid_list_rwlock);
-}
-
-/*
- * Restore the previous ssidref values on all domains
- */
-static void
-acm_doms_restore_ssidref(void)
-{
- struct acm_ssid_domain *rawssid;
-
- write_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ssidref_t old_ssid;
-
- if ( rawssid->old_ssidref == rawssid->ssidref )
- continue;
-
- old_ssid = rawssid->old_ssidref & 0xffff;
- rawssid->ssidref = rawssid->old_ssidref;
-
- acm_pri_policy_assign_ssidref(rawssid, old_ssid);
- acm_sec_policy_assign_ssidref(rawssid, old_ssid);
- }
-
- write_unlock(&ssid_list_rwlock);
-}
-
-
-/*
- Check the list of domains whether either one of them uses a
- to-be-deleted ssidref.
- */
-static int
-acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
- struct acm_sized_buffer *errors)
-{
- int rc = 0;
- uint idx;
- /* check for running domains that should not be there anymore */
- for ( idx = 0; idx < dels->num_items; idx++ )
- {
- if ( acm_check_used_ssidref(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- dels->array[idx],
- errors) > 0 ||
- acm_check_used_ssidref(ACM_CHINESE_WALL_POLICY,
- dels->array[idx],
- errors) > 0)
- {
- rc = ACM_ERROR;
- break;
- }
- }
- return rc;
-}
-
-
-/*
- * Change the policy of the system.
- */
-int
-acm_change_policy(struct acm_change_policy *chgpolicy)
-{
- int rc = 0;
- u8 *binpolicy = NULL;
- struct acm_sized_buffer dels =
- {
- .array = NULL,
- };
- struct acm_sized_buffer ssidmap =
- {
- .array = NULL,
- };
- struct acm_sized_buffer errors =
- {
- .array = NULL,
- };
-
- gdprintk(XENLOG_INFO, "change policy operation\n");
-
- if ( (chgpolicy->delarray_size > 4096) ||
- (chgpolicy->chgarray_size > 4096) ||
- (chgpolicy->errarray_size > 4096))
- {
- return ACM_ERROR;
- }
-
- dels.num_items = chgpolicy->delarray_size / sizeof(uint32_t);
- if ( dels.num_items > 0 )
- {
- dels.array = xmalloc_array(uint32_t, dels.num_items);
- if ( dels.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
- }
-
- ssidmap.num_items = chgpolicy->chgarray_size / sizeof(uint32_t);
- if ( ssidmap.num_items > 0 )
- {
- ssidmap.array = xmalloc_array(uint32_t, ssidmap.num_items);
- if ( ssidmap.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
- }
-
- errors.num_items = chgpolicy->errarray_size / sizeof(uint32_t);
- if ( errors.num_items > 0 )
- {
- errors.array = xmalloc_array(uint32_t, errors.num_items);
- if ( errors.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
- memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
- }
-
- binpolicy = xmalloc_array(u8,
- chgpolicy->policy_pushcache_size);
- if ( binpolicy == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
-
- if ( copy_from_guest(dels.array,
- chgpolicy->del_array,
- dels.num_items) ||
- copy_from_guest(ssidmap.array,
- chgpolicy->chg_array,
- ssidmap.num_items) ||
- copy_from_guest(binpolicy,
- chgpolicy->policy_pushcache,
- chgpolicy->policy_pushcache_size ))
- {
- rc = -EFAULT;
- goto acm_chg_policy_exit;
- }
-
- rc = do_acm_set_policy(binpolicy,
- chgpolicy->policy_pushcache_size,
- 0,
- &dels, &ssidmap, &errors);
-
- if ( (errors.num_items > 0) &&
- copy_to_guest(chgpolicy->err_array,
- errors.array,
- errors.num_items ) )
- {
- rc = -EFAULT;
- goto acm_chg_policy_exit;
- }
-
-
-acm_chg_policy_exit:
- xfree(dels.array);
- xfree(ssidmap.array);
- xfree(errors.array);
- xfree(binpolicy);
-
- return rc;
-}
-
-
-/*
- * Lookup the new ssidref given the domain's id.
- * The translation map provides a list of tuples in the format
- * (domid, new ssidref).
- */
-static ssidref_t
-domid_to_newssid(const struct acm_ssid_domain *rawssid,
- const struct acm_sized_buffer *map)
-{
- domid_t domid = rawssid->domainid;
- uint i;
- for ( i = 0; (i+1) < map->num_items; i += 2 )
- {
- if ( map->array[i] == domid )
- return (ssidref_t)map->array[i+1];
- }
- return ACM_INVALID_SSIDREF;
-}
-
-
-int
-do_acm_relabel_doms(struct acm_sized_buffer *relabel_map,
- struct acm_sized_buffer *errors)
-{
- int rc = 0, irc;
-
- write_lock(&acm_bin_pol_rwlock);
-
- acm_doms_change_ssidref(domid_to_newssid, relabel_map);
-
- /* run tests; collect as much error info as possible */
- irc = do_chwall_init_state_curr(errors);
- irc += do_ste_init_state_curr(errors);
- if ( irc != 0 )
- {
- rc = -EFAULT;
- goto acm_relabel_doms_lock_err_exit;
- }
-
- write_unlock(&acm_bin_pol_rwlock);
-
- return rc;
-
-acm_relabel_doms_lock_err_exit:
- /* revert the new ssidref assignment */
- acm_doms_restore_ssidref();
- do_chwall_init_state_curr(NULL);
-
- write_unlock(&acm_bin_pol_rwlock);
-
- return rc;
-}
-
-
-int
-acm_relabel_domains(struct acm_relabel_doms *relabel)
-{
- int rc = ACM_OK;
- struct acm_sized_buffer relabels =
- {
- .array = NULL,
- };
- struct acm_sized_buffer errors =
- {
- .array = NULL,
- };
-
- if ( relabel->relabel_map_size > 4096 )
- {
- return ACM_ERROR;
- }
-
- relabels.num_items = relabel->relabel_map_size / sizeof(uint32_t);
- if ( relabels.num_items > 0 )
- {
- relabels.array = xmalloc_array(uint32_t, relabels.num_items);
- if ( relabels.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_relabel_doms_exit;
- }
- }
-
- errors.num_items = relabel->errarray_size / sizeof(uint32_t);
- if ( errors.num_items > 0 )
- {
- errors.array = xmalloc_array(uint32_t, errors.num_items);
- if ( errors.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_relabel_doms_exit;
- }
- memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
- }
-
- if ( copy_from_guest(relabels.array,
- relabel->relabel_map,
- relabels.num_items) )
- {
- rc = -EFAULT;
- goto acm_relabel_doms_exit;
- }
-
- rc = do_acm_relabel_doms(&relabels, &errors);
-
- if ( copy_to_guest(relabel->err_array,
- errors.array,
- errors.num_items ) )
- rc = -EFAULT;
-
-acm_relabel_doms_exit:
- xfree(relabels.array);
- xfree(errors.array);
- return rc;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c
deleted file mode 100644
index 1ceb89fb9c..0000000000
--- a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c
+++ /dev/null
@@ -1,924 +0,0 @@
-/****************************************************************
- * acm_simple_type_enforcement_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Stefan Berger <stefanb@watson.ibm.com>
- * support for network order binary policies
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype Simple Type Enforcement for Xen
- * STE allows to control which domains can setup sharing
- * (eventchannels right now) with which other domains. Hooks
- * are defined and called throughout Xen when domains bind to
- * shared resources (setup eventchannels) and a domain is allowed
- * to setup sharing with another domain if and only if both domains
- * share at least on common type.
- *
- */
-
-#include <xen/lib.h>
-#include <asm/types.h>
-#include <asm/current.h>
-#include <asm/atomic.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-#include <xsm/acm/acm_core.h>
-
-ssidref_t dom0_ste_ssidref = 0x0001;
-
-/* local cache structures for STE policy */
-struct ste_binary_policy ste_bin_pol;
-
-static inline int have_common_type (ssidref_t ref1, ssidref_t ref2)
-{
- int i;
-
- if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
- ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
- {
- for( i = 0; i< ste_bin_pol.max_types; i++ )
- if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
- ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
- {
- printkd("%s: common type #%02x.\n", __func__, i);
- return 1;
- }
- }
- return 0;
-}
-
-static inline int is_superset(ssidref_t ref1, ssidref_t ref2)
-{
- int i;
-
- if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
- ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
- {
- for( i = 0; i< ste_bin_pol.max_types; i++ )
- if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
- ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
- {
- return 0;
- }
- } else {
- return 0;
- }
- return 1;
-}
-
-
-/* Helper function: return = (subj and obj share a common type) */
-static int share_common_type(struct domain *subj, struct domain *obj)
-{
- ssidref_t ref_s, ref_o;
- int ret;
-
- if ( (subj == NULL) || (obj == NULL) ||
- (subj->ssid == NULL) || (obj->ssid == NULL) )
- return 0;
-
- read_lock(&acm_bin_pol_rwlock);
-
- /* lookup the policy-local ssids */
- ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
- ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
- /* check whether subj and obj share a common ste type */
- ret = have_common_type(ref_s, ref_o);
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return ret;
-}
-
-/*
- * Initializing STE policy (will be filled by policy partition
- * using setpolicy command)
- */
-int acm_init_ste_policy(void)
-{
- /* minimal startup policy; policy write-locked already */
- ste_bin_pol.max_types = 2;
- ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref;
- ste_bin_pol.ssidrefs =
- (domaintype_t *)xmalloc_array(domaintype_t,
- ste_bin_pol.max_types *
- ste_bin_pol.max_ssidrefs);
-
- if (ste_bin_pol.ssidrefs == NULL)
- return ACM_INIT_SSID_ERROR;
-
- memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) *
- ste_bin_pol.max_types *
- ste_bin_pol.max_ssidrefs);
-
- /* initialize state so that dom0 can start up and communicate with itself */
- ste_bin_pol.ssidrefs[ste_bin_pol.max_types - 1 ] = 1;
- ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1;
- ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref + 1] = 1;
-
- /* init stats */
- atomic_set(&(ste_bin_pol.ec_eval_count), 0);
- atomic_set(&(ste_bin_pol.ec_denied_count), 0);
- atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
- atomic_set(&(ste_bin_pol.gt_eval_count), 0);
- atomic_set(&(ste_bin_pol.gt_denied_count), 0);
- atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
-
- return ACM_OK;
-}
-
-
-/* ste initialization function hooks */
-static int
-ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
-{
- int i;
- struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
-
- if ( ste_ssidp == NULL )
- return ACM_INIT_SSID_ERROR;
-
- /* get policy-local ssid reference */
- ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- ssidref);
-
- if ( (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) )
- {
- printkd("%s: ERROR ste_ssidref (%x) undefined or unset (0).\n",
- __func__, ste_ssidp->ste_ssidref);
- xfree(ste_ssidp);
- return ACM_INIT_SSID_ERROR;
- }
- /* clean ste cache */
- for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- ste_ssidp->ste_cache[i].valid = ACM_STE_free;
-
- (*ste_ssid) = ste_ssidp;
- printkd("%s: determined ste_ssidref to %x.\n",
- __func__, ste_ssidp->ste_ssidref);
-
- return ACM_OK;
-}
-
-
-static void
-ste_free_domain_ssid(void *ste_ssid)
-{
- xfree(ste_ssid);
- return;
-}
-
-/* dump type enforcement cache; policy read-locked already */
-static int
-ste_dump_policy(u8 *buf, u32 buf_size) {
- struct acm_ste_policy_buffer *ste_buf =
- (struct acm_ste_policy_buffer *)buf;
- int ret = 0;
-
- if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
- return -EINVAL;
-
- ste_buf->ste_max_types = cpu_to_be32(ste_bin_pol.max_types);
- ste_buf->ste_max_ssidrefs = cpu_to_be32(ste_bin_pol.max_ssidrefs);
- ste_buf->policy_code = cpu_to_be32(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
- ste_buf->ste_ssid_offset =
- cpu_to_be32(sizeof(struct acm_ste_policy_buffer));
- ret = be32_to_cpu(ste_buf->ste_ssid_offset) +
- sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
-
- ret = (ret + 7) & ~7;
-
- if (buf_size < ret)
- return -EINVAL;
-
- /* now copy buffer over */
- arrcpy(buf + be32_to_cpu(ste_buf->ste_ssid_offset),
- ste_bin_pol.ssidrefs,
- sizeof(domaintype_t),
- ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
-
- return ret;
-}
-
-/*
- * ste_init_state is called when a policy is changed to detect violations
- * (return != 0). from a security point of view, we simulate that all
- * running domains are re-started and all sharing decisions are replayed
- * to detect violations or current sharing behavior (right now:
- * event_channels, future: also grant_tables)
- */
-static int
-ste_init_state(struct acm_sized_buffer *errors)
-{
- int violation = 1;
- struct ste_ssid *ste_ssid, *ste_rssid;
- ssidref_t ste_ssidref, ste_rssidref;
- struct domain *d, *rdom;
- domid_t rdomid;
- struct active_grant_entry *act;
- int port, i;
-
- rcu_read_lock(&domlist_read_lock);
- read_lock(&ssid_list_rwlock);
-
- /* go through all domains and adjust policy as if this domain was
- started now */
-
- for_each_domain ( d )
- {
- struct evtchn *ports;
- unsigned int bucket;
-
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)d->ssid);
- ste_ssidref = ste_ssid->ste_ssidref;
- traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
- __func__, d->domain_id, ste_ssidref);
- /* a) check for event channel conflicts */
- for ( bucket = 0; bucket < NR_EVTCHN_BUCKETS; bucket++ )
- {
- spin_lock(&d->event_lock);
- ports = d->evtchn[bucket];
- if ( ports == NULL)
- {
- spin_unlock(&d->event_lock);
- break;
- }
-
- for ( port = 0; port < EVTCHNS_PER_BUCKET; port++ )
- {
- if ( ports[port].state == ECS_INTERDOMAIN )
- {
- rdom = ports[port].u.interdomain.remote_dom;
- rdomid = rdom->domain_id;
- } else {
- continue; /* port unused */
- }
-
- /* rdom now has remote domain */
- ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(rdom->ssid));
- ste_rssidref = ste_rssid->ste_ssidref;
- traceprintk("%s: eventch: domain %x (ssidref %x) --> "
- "domain %x (rssidref %x) used (port %x).\n",
- __func__, d->domain_id, ste_ssidref,
- rdom->domain_id, ste_rssidref, port);
- /* check whether on subj->ssid, obj->ssid share a common type*/
- if ( ! have_common_type(ste_ssidref, ste_rssidref) )
- {
- printkd("%s: Policy violation in event channel domain "
- "%x -> domain %x.\n",
- __func__, d->domain_id, rdomid);
- spin_unlock(&d->event_lock);
-
- acm_array_append_tuple(errors,
- ACM_EVTCHN_SHARING_VIOLATION,
- d->domain_id << 16 | rdomid);
- goto out;
- }
- }
- spin_unlock(&d->event_lock);
- }
-
-
- /* b) check for grant table conflicts on shared pages */
- spin_lock(&d->grant_table->lock);
- for ( i = 0; i < nr_active_grant_frames(d->grant_table); i++ )
- {
-#define APP (PAGE_SIZE / sizeof(struct active_grant_entry))
- act = &d->grant_table->active[i/APP][i%APP];
- if ( act->pin != 0 ) {
- printkd("%s: grant dom (%hu) SHARED (%d) pin (%d) "
- "dom:(%hu) frame:(%lx)\n",
- __func__, d->domain_id, i, act->pin,
- act->domid, (unsigned long)act->frame);
- rdomid = act->domid;
- if ( (rdom = rcu_lock_domain_by_id(rdomid)) == NULL )
- {
- spin_unlock(&d->grant_table->lock);
- printkd("%s: domain not found ERROR!\n", __func__);
-
- acm_array_append_tuple(errors,
- ACM_DOMAIN_LOOKUP,
- rdomid);
- goto out;
- }
- /* rdom now has remote domain */
- ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(rdom->ssid));
- ste_rssidref = ste_rssid->ste_ssidref;
- rcu_unlock_domain(rdom);
- if ( ! have_common_type(ste_ssidref, ste_rssidref) )
- {
- spin_unlock(&d->grant_table->lock);
- printkd("%s: Policy violation in grant table "
- "sharing domain %x -> domain %x.\n",
- __func__, d->domain_id, rdomid);
-
- acm_array_append_tuple(errors,
- ACM_GNTTAB_SHARING_VIOLATION,
- d->domain_id << 16 | rdomid);
- goto out;
- }
- }
- }
- spin_unlock(&d->grant_table->lock);
- }
- violation = 0;
- out:
- read_unlock(&ssid_list_rwlock);
- rcu_read_unlock(&domlist_read_lock);
- return violation;
- /*
- returning "violation != 0" means that existing sharing between domains
- would not have been allowed if the new policy had been enforced before
- the sharing; for ste, this means that there are at least 2 domains
- that have established sharing through event-channels or grant-tables
- but these two domains don't have no longer a common type in their
- typesets referenced by their ssidrefs
- */
-}
-
-
-/*
- * Call ste_init_state with the current policy.
- */
-int
-do_ste_init_state_curr(struct acm_sized_buffer *errors)
-{
- return ste_init_state(errors);
-}
-
-
-/* set new policy; policy write-locked already */
-static int
-_ste_update_policy(u8 *buf, u32 buf_size, int test_only,
- struct acm_sized_buffer *errors)
-{
- int rc = -EFAULT;
- struct acm_ste_policy_buffer *ste_buf =
- (struct acm_ste_policy_buffer *)buf;
- void *ssidrefsbuf;
- struct ste_ssid *ste_ssid;
- struct acm_ssid_domain *rawssid;
- int i;
-
-
- /* 1. create and copy-in new ssidrefs buffer */
- ssidrefsbuf = xmalloc_array(u8,
- sizeof(domaintype_t) *
- ste_buf->ste_max_types *
- ste_buf->ste_max_ssidrefs);
- if ( ssidrefsbuf == NULL ) {
- return -ENOMEM;
- }
- if ( ste_buf->ste_ssid_offset +
- sizeof(domaintype_t) *
- ste_buf->ste_max_ssidrefs *
- ste_buf->ste_max_types > buf_size )
- goto error_free;
-
- arrcpy(ssidrefsbuf,
- buf + ste_buf->ste_ssid_offset,
- sizeof(domaintype_t),
- ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
-
-
- /*
- * 3. in test mode: re-calculate sharing decisions based on running
- * domains; this can fail if new policy is conflicting with sharing
- * of running domains
- * now: reject violating new policy; future: adjust sharing through
- * revoking sharing
- */
-
- if ( test_only ) {
- /* temporarily replace old policy with new one for the testing */
- struct ste_binary_policy orig_ste_bin_pol = ste_bin_pol;
- ste_bin_pol.max_types = ste_buf->ste_max_types;
- ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
- ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
-
- if ( ste_init_state(errors) )
- {
- /* new policy conflicts with sharing of running domains */
- printk("%s: New policy conflicts with running domains. "
- "Policy load aborted.\n", __func__);
- } else {
- rc = ACM_OK;
- }
- /* revert changes, no matter whether testing was successful or not */
- ste_bin_pol = orig_ste_bin_pol;
- goto error_free;
- }
-
- /* 3. replace old policy (activate new policy) */
- ste_bin_pol.max_types = ste_buf->ste_max_types;
- ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
- xfree(ste_bin_pol.ssidrefs);
- ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
-
- /* clear all ste caches */
- read_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
- for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- ste_ssid->ste_cache[i].valid = ACM_STE_free;
- }
-
- read_unlock(&ssid_list_rwlock);
-
- return ACM_OK;
-
- error_free:
- if ( !test_only )
- printk("%s: ERROR setting policy.\n", __func__);
- xfree(ssidrefsbuf);
- return rc;
-}
-
-static int
-ste_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *errors)
-{
- struct acm_ste_policy_buffer *ste_buf =
- (struct acm_ste_policy_buffer *)buf;
-
- if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
- return -EINVAL;
-
- /* Convert endianess of policy */
- ste_buf->policy_code = be32_to_cpu(ste_buf->policy_code);
- ste_buf->policy_version = be32_to_cpu(ste_buf->policy_version);
- ste_buf->ste_max_types = be32_to_cpu(ste_buf->ste_max_types);
- ste_buf->ste_max_ssidrefs = be32_to_cpu(ste_buf->ste_max_ssidrefs);
- ste_buf->ste_ssid_offset = be32_to_cpu(ste_buf->ste_ssid_offset);
-
- /* policy type and version checks */
- if ( (ste_buf->policy_code != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ||
- (ste_buf->policy_version != ACM_STE_VERSION) )
- return -EINVAL;
-
- /* during boot dom0_chwall_ssidref is set */
- if ( is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs) )
- return -EINVAL;
-
- return _ste_update_policy(buf, buf_size, 1, errors);
-}
-
-static int
-ste_set_policy(u8 *buf, u32 buf_size)
-{
- return _ste_update_policy(buf, buf_size, 0, NULL);
-}
-
-static int
-ste_dump_stats(u8 *buf, u16 buf_len)
-{
- struct acm_ste_stats_buffer stats;
-
- /* now send the hook counts to user space */
- stats.ec_eval_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.ec_eval_count));
- stats.gt_eval_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.gt_eval_count));
- stats.ec_denied_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.ec_denied_count));
- stats.gt_denied_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.gt_denied_count));
- stats.ec_cachehit_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.ec_cachehit_count));
- stats.gt_cachehit_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.gt_cachehit_count));
-
- if ( buf_len < sizeof(struct acm_ste_stats_buffer) )
- return -ENOMEM;
-
- memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
-
- return sizeof(struct acm_ste_stats_buffer);
-}
-
-static int
-ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
-{
- int i;
-
- /* fill in buffer */
- if ( ste_bin_pol.max_types > len )
- return -EFAULT;
-
- if ( ssidref >= ste_bin_pol.max_ssidrefs )
- return -EFAULT;
-
- /* read types for chwall ssidref */
- for( i = 0; i< ste_bin_pol.max_types; i++ )
- {
- if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
- buf[i] = 1;
- else
- buf[i] = 0;
- }
- return ste_bin_pol.max_types;
-}
-
-/* we need to go through this before calling the hooks,
- * returns 1 == cache hit */
-static int inline
-check_cache(struct domain *dom, domid_t rdom)
-{
- struct ste_ssid *ste_ssid;
- int i;
-
- printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
-
- if (dom->ssid == NULL)
- return 0;
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(dom->ssid));
-
- for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- {
- if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
- (ste_ssid->ste_cache[i].id == rdom) )
- {
- printkd("cache hit (entry %x, id= %x!\n",
- i,
- ste_ssid->ste_cache[i].id);
- return 1;
- }
- }
- return 0;
-}
-
-
-/* we only get here if there is NO entry yet; no duplication check! */
-static void inline
-cache_result(struct domain *subj, struct domain *obj) {
- struct ste_ssid *ste_ssid;
- int i;
-
- printkd("caching from doms: %x --> %x.\n",
- subj->domain_id, obj->domain_id);
-
- if ( subj->ssid == NULL )
- return;
-
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(subj)->ssid);
-
- for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- if ( ste_ssid->ste_cache[i].valid == ACM_STE_free )
- break;
- if ( i < ACM_TE_CACHE_SIZE )
- {
- ste_ssid->ste_cache[i].valid = ACM_STE_valid;
- ste_ssid->ste_cache[i].id = obj->domain_id;
- } else
- printk ("Cache of dom %x is full!\n", subj->domain_id);
-}
-
-/* deletes entries for domain 'id' from all caches (re-use) */
-static void inline
-clean_id_from_cache(domid_t id)
-{
- struct ste_ssid *ste_ssid;
- int i;
- struct acm_ssid_domain *rawssid;
-
- printkd("deleting cache for dom %x.\n", id);
-
- read_lock(&ssid_list_rwlock);
- /* look through caches of all domains */
-
- for_each_acmssid ( rawssid )
- {
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
-
- if ( !ste_ssid )
- {
- printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n",
- __func__);
- goto out;
- }
- for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
- (ste_ssid->ste_cache[i].id == id) )
- ste_ssid->ste_cache[i].valid = ACM_STE_free;
- }
-
- out:
- read_unlock(&ssid_list_rwlock);
-}
-
-/***************************
- * Authorization functions
- **************************/
-static int
-ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
-{
- /* check for ssidref in range for policy */
- ssidref_t ste_ssidref;
-
- traceprintk("%s.\n", __func__);
-
- read_lock(&acm_bin_pol_rwlock);
-
- ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
-
- if ( ste_ssidref >= ste_bin_pol.max_ssidrefs )
- {
- printk("%s: ERROR ste_ssidref > max(%x).\n",
- __func__, ste_bin_pol.max_ssidrefs-1);
- read_unlock(&acm_bin_pol_rwlock);
- return ACM_ACCESS_DENIED;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return ACM_ACCESS_PERMITTED;
-}
-
-static int
-ste_domain_create(void *subject_ssid, ssidref_t ssidref, domid_t domid)
-{
- return ste_pre_domain_create(subject_ssid, ssidref);
-}
-
-
-static void
-ste_domain_destroy(void *subject_ssid, struct domain *d)
-{
- /* clean all cache entries for destroyed domain (might be re-used) */
- clean_id_from_cache(d->domain_id);
-}
-
-/* -------- EVENTCHANNEL OPERATIONS -----------*/
-static int
-ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) {
- struct domain *subj, *obj;
- int ret;
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- (id1 == DOMID_SELF) ? current->domain->domain_id : id1,
- (id2 == DOMID_SELF) ? current->domain->domain_id : id2);
-
- if ( id1 == DOMID_SELF )
- id1 = current->domain->domain_id;
- if ( id2 == DOMID_SELF )
- id2 = current->domain->domain_id;
-
- subj = rcu_lock_domain_by_id(id1);
- obj = rcu_lock_domain_by_id(id2);
- if ( (subj == NULL) || (obj == NULL) )
- {
- ret = ACM_ACCESS_DENIED;
- goto out;
- }
- /* cache check late */
- if ( check_cache(subj, obj->domain_id) )
- {
- atomic_inc(&ste_bin_pol.ec_cachehit_count);
- ret = ACM_ACCESS_PERMITTED;
- goto out;
- }
- atomic_inc(&ste_bin_pol.ec_eval_count);
-
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.ec_denied_count);
- ret = ACM_ACCESS_DENIED;
- }
-
- out:
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- if ( subj != NULL )
- rcu_unlock_domain(subj);
- return ret;
-}
-
-static int
-ste_pre_eventchannel_interdomain(domid_t id)
-{
- struct domain *subj=NULL, *obj=NULL;
- int ret;
-
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- current->domain->domain_id,
- (id == DOMID_SELF) ? current->domain->domain_id : id);
-
- /* following is a bit longer but ensures that we
- * "put" only domains that we where "find"-ing
- */
- if ( id == DOMID_SELF )
- id = current->domain->domain_id;
-
- subj = current->domain;
- obj = rcu_lock_domain_by_id(id);
- if ( obj == NULL )
- {
- ret = ACM_ACCESS_DENIED;
- goto out;
- }
-
- /* cache check late, but evtchn is not on performance critical path */
- if ( check_cache(subj, obj->domain_id) )
- {
- atomic_inc(&ste_bin_pol.ec_cachehit_count);
- ret = ACM_ACCESS_PERMITTED;
- goto out;
- }
-
- atomic_inc(&ste_bin_pol.ec_eval_count);
-
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.ec_denied_count);
- ret = ACM_ACCESS_DENIED;
- }
-
- out:
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- return ret;
-}
-
-/* -------- SHARED MEMORY OPERATIONS -----------*/
-
-static int
-ste_pre_grant_map_ref (domid_t id)
-{
- struct domain *obj, *subj;
- int ret;
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- current->domain->domain_id, id);
-
- if ( check_cache(current->domain, id) )
- {
- atomic_inc(&ste_bin_pol.gt_cachehit_count);
- return ACM_ACCESS_PERMITTED;
- }
- atomic_inc(&ste_bin_pol.gt_eval_count);
- subj = current->domain;
- obj = rcu_lock_domain_by_id(id);
-
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.gt_denied_count);
- printkd("%s: ACCESS DENIED!\n", __func__);
- ret = ACM_ACCESS_DENIED;
- }
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- return ret;
-}
-
-
-/* since setting up grant tables involves some implicit information
- flow from the creating domain to the domain that is setup, we
- check types in addition to the general authorization */
-static int
-ste_pre_grant_setup (domid_t id)
-{
- struct domain *obj, *subj;
- int ret;
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- current->domain->domain_id, id);
-
- if ( check_cache(current->domain, id) )
- {
- atomic_inc(&ste_bin_pol.gt_cachehit_count);
- return ACM_ACCESS_PERMITTED;
- }
- atomic_inc(&ste_bin_pol.gt_eval_count);
- subj = current->domain;
- obj = rcu_lock_domain_by_id(id);
-
- /* a) check authorization (eventually use specific capabilities) */
- if ( obj && !IS_PRIV_FOR(current->domain, obj) )
- {
- printk("%s: Grant table management authorization denied ERROR!\n",
- __func__);
- rcu_unlock_domain(obj);
- return ACM_ACCESS_DENIED;
- }
-
- /* b) check types */
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.gt_denied_count);
- ret = ACM_ACCESS_DENIED;
- }
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- return ret;
-}
-
-/* -------- DOMAIN-Requested Decision hooks -----------*/
-
-static int
-ste_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
-{
- int hct = have_common_type(
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
- return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
-}
-
-static int
-ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
-{
- int iss = is_superset(
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
- return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
-}
-
-static int
-ste_is_default_policy(void)
-{
- const static domaintype_t def_policy[4] = { 0x0, 0x1, 0x1, 0x1};
- return ((ste_bin_pol.max_types == 2) &&
- (ste_bin_pol.max_ssidrefs == 2) &&
- (memcmp(ste_bin_pol.ssidrefs,
- def_policy,
- sizeof(def_policy)) == 0));
-}
-
-/* now define the hook structure similarly to LSM */
-struct acm_operations acm_simple_type_enforcement_ops = {
-
- /* policy management services */
- .init_domain_ssid = ste_init_domain_ssid,
- .free_domain_ssid = ste_free_domain_ssid,
- .dump_binary_policy = ste_dump_policy,
- .test_binary_policy = ste_test_policy,
- .set_binary_policy = ste_set_policy,
- .dump_statistics = ste_dump_stats,
- .dump_ssid_types = ste_dump_ssid_types,
-
- /* domain management control hooks */
- .domain_create = ste_domain_create,
- .domain_destroy = ste_domain_destroy,
-
- /* event channel control hooks */
- .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
- .fail_eventchannel_unbound = NULL,
- .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
- .fail_eventchannel_interdomain = NULL,
-
- /* grant table control hooks */
- .pre_grant_map_ref = ste_pre_grant_map_ref,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = ste_pre_grant_setup,
- .fail_grant_setup = NULL,
- /* generic domain-requested decision hooks */
- .sharing = ste_sharing,
- .authorization = ste_authorization,
- .conflictset = NULL,
-
- .is_default_policy = ste_is_default_policy,
-};
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_xsm_hooks.c b/xen/xsm/acm/acm_xsm_hooks.c
deleted file mode 100644
index 6d3202b45f..0000000000
--- a/xen/xsm/acm/acm_xsm_hooks.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************
- * acm_xsm_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Michael LeMay, <mdlemay@epoch.ncsc.mil>
- * George Coker, <gscoker@alpha.ncsc.mil>
- *
- * sHype hooks for XSM based on the original ACM hooks.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- */
-
-#include <xsm/xsm.h>
-#include <xsm/acm/acm_hooks.h>
-#include <public/xsm/acm.h>
-
-static int acm_grant_mapref(
- struct domain *ld, struct domain *rd, uint32_t flags)
-{
- domid_t id = rd->domain_id;
-
- return acm_pre_grant_map_ref(id);
-}
-
-static int acm_evtchn_unbound(
- struct domain *d1, struct evtchn *chn1, domid_t id2)
-{
- domid_t id1 = d1->domain_id;
-
- return acm_pre_eventchannel_unbound(id1, id2);
-}
-
-static int acm_evtchn_interdomain(
- struct domain *d1, struct evtchn *chn1,
- struct domain *d2, struct evtchn *chn2)
-{
- domid_t id2 = d2->domain_id;
-
- return acm_pre_eventchannel_interdomain(id2);
-}
-
-static void acm_security_domaininfo(
- struct domain *d, struct xen_domctl_getdomaininfo *info)
-{
- if ( d->ssid != NULL )
- info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
- else
- info->ssidref = ACM_DEFAULT_SSID;
-}
-
-extern long do_acm_op(XEN_GUEST_HANDLE(xsm_op_t) arg);
-
-struct xsm_operations acm_xsm_ops = {
- .domain_create = acm_domain_create,
- .free_security_domain = acm_domain_destroy,
-
- .grant_mapref = acm_grant_mapref,
-
- .evtchn_unbound = acm_evtchn_unbound,
- .evtchn_interdomain = acm_evtchn_interdomain,
-
- .security_domaininfo = acm_security_domaininfo,
-
- .__do_xsm_op = do_acm_op,
-};
diff --git a/xen/xsm/xsm_policy.c b/xen/xsm/xsm_policy.c
index dcab94d580..c5b334e7e9 100644
--- a/xen/xsm/xsm_policy.c
+++ b/xen/xsm/xsm_policy.c
@@ -15,7 +15,6 @@
*
*
* This file contains the XSM policy init functions for Xen.
- * This file is based on the ACM functions of the same name.
*
*/