summaryrefslogtreecommitdiffstats
path: root/source4/scripting/python/samba/sd_utils.py
blob: 66ff6cc559b7c4935763784b7cfa0715ef7722ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env python
#
# Utility methods for security descriptor manipulation
#
# Copyright Nadezhda Ivanova 2010 <nivanova@samba.org>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#

"""Utility methods for security descriptor manipulation."""

import samba
from ldb import Message, MessageElement, Dn
from ldb import FLAG_MOD_REPLACE, SCOPE_BASE
from samba.ndr import ndr_pack, ndr_unpack
from samba.dcerpc import security


class SDUtils(object):
    """Some utilities for manipulation of security descriptors
    on objects"""

    def __init__(self, samdb):
        self.ldb = samdb
        self.domain_sid = security.dom_sid(self.ldb.get_domain_sid())

    def modify_sd_on_dn(self, object_dn, sd, controls=None):
        """ Modify security descriptor using either SDDL string
            or security.descriptor object
        """
        m = Message()
        m.dn = Dn(self.ldb, object_dn)
        assert(isinstance(sd, str) or isinstance(sd, security.descriptor))
        if isinstance(sd, str):
            tmp_desc = security.descriptor.from_sddl(sd, self.domain_sid)
        elif isinstance(sd, security.descriptor):
            tmp_desc = sd

        m["nTSecurityDescriptor"] = MessageElement(ndr_pack(tmp_desc),
                                                       FLAG_MOD_REPLACE,
                                                       "nTSecurityDescriptor")
        self.ldb.modify(m, controls)

    def read_sd_on_dn(self, object_dn, controls=None):
        res = self.ldb.search(object_dn, SCOPE_BASE, None,
                              ["nTSecurityDescriptor"], controls=controls)
        desc = res[0]["nTSecurityDescriptor"][0]
        return ndr_unpack(security.descriptor, desc)

    def get_object_sid(self, object_dn):
        res = self.ldb.search(object_dn)
        return ndr_unpack(security.dom_sid, res[0]["objectSid"][0])

    def dacl_add_ace(self, object_dn, ace):
        """ Adds an ACE to an objects security descriptor
        """
        desc = self.read_sd_on_dn(object_dn)
        desc_sddl = desc.as_sddl(self.domain_sid)
        if ace in desc_sddl:
            return
        if desc_sddl.find("(") >= 0:
            desc_sddl = (desc_sddl[:desc_sddl.index("(")] + ace +
                         desc_sddl[desc_sddl.index("("):])
        else:
            desc_sddl = desc_sddl + ace
        self.modify_sd_on_dn(object_dn, desc_sddl)

    def get_sd_as_sddl(self, object_dn, controls=None):
        """ Return object nTSecutiryDescriptor in SDDL format
        """
        desc = self.read_sd_on_dn(object_dn, controls=controls)
        return desc.as_sddl(self.domain_sid)
^`rI`W5p'{J[?Le_O0yL<Մ$&)&~+TYGxRx#ЖߋWx</酮zn^ZUkClQJ#%r:33~k`8`(WmBԍ{ 76"oS|{yO8]]8ᓪS7WX(Έyxnİ _VQ:~YM'XY[JYG9=*ThsIpS *$o1w3?ߝxn.ѻvo*깋!G0P8sc:F+`ănCq]5:~X&z`G' yY[Ք Fќ@DM*~#v%22} d֞%"*ιkd&0[ȃ"Ҝ|jK`Mn;?zafht7euFy_Ne8$e%G8:ZYU̻l\J{̑wbss'>~ \oo-< {,4R:0fϷ.rLy0Ck?U;SQCwJ8.~U<EسbL^9-E΍ʹ=sGkvخk:ß.o#{hq( bK lŪ`/*믡3ec]Jqdn%ׄX #/gbUW`lJyb[׎9N& 4N\n4Uȑ Lvٙl#BvA'EcAhKEtZF Н]TPQ-J瑋eV?નdH' D!ߺ~!{@$ M&\.6:apV+?zft1[`58dBP'R9m@Y]#وOAT+FZB/}5]f=@=$+Wվ`VMFi*#VKO|IB1R{Qp-[bK1+32⥔tÇnR ^"o"CI!O1\_Fk[ay1M^5?\9$otdr&R[."OՈay PӷFJGq>b'ku\dM/ H,2K1 8'`?Td )&fjҡjSk| CE`*yQ ݴngŅyAu!IDN~jy{)Vgpb_l7D v);X#tth'&} my M{7<`:^t-E2Q&8ZS}La\)Y\w$c H B>OECvo"򋕺Kq m|--ɐB5ܚ?z#5mlXgdς\ \f~p ˑ[TMQDaUmb31xlv"8~\DzTZɦyup'/Ӧax֧ &f`]+ \XԩL1dP-77rcwUP"=,"9'S=k=>zCDKr1-|GZ3Iﱮ\&^:X=pb~veozy 5}D'^%pgqQU=v#Lψc e"cwkvI?O@-!ed2HN<<ɞ#5u Tkm)F1|0͐XD'1B܅H#(&S6& nt^AO|I :\6|f7z #Ԓn鞍 .mոi{']YR`À2e60$Uc<&xڷX2;YzRL(g_ZNsy~z UulX$& bUqI]"+o"nt ]YV2)Ce %S;*Ж{6Y=L2q`ƉЍo>UÐ,Y-?4$ybBwRYKg穠37kR-0&.?%Rap4JkkXd+ ]B!ʒY-ۂJ䉦(pe lLp]ILZSlA䱄 OQ{Pb`NLWTՊ2h=s+ G&6@5U1ΰH'|Y-V=ҬUžKh YCڲj5H15 v9@|,WbC+P{*n@nSLJ9r rE6x0vX1jov|i{ wŢJ̛_$-e(j4:?I'DHK Iw47E>^k6271VșҌǣ R;[>|0o}bt;HJB!6m^=bYޟ2 YnOrKu;eXPo P $ sݏ;aRWK\_:Ry*PKD-5̐P?oyhŘd{%U))Ţ*zW+NI\gO"x_@e랤[#d`T}.m80K3ieJ%l֞sVaMv%cTl RLwSF醘tB-͂ VNz+d\jFĩh_-WR3E ' (!C+cǴV، Jid+1b5|y <w܀ˡyG7MSu`ީ߮ca6% )o>eK! ?U³pڋυl;te e7* p3 a68"2M;P&[s:v 2 w erx|hɌ@=]4G^5N`hJ'j~5idr:}?ahf])A\Q w-m -"?P>+^" " ޫctcq$nϩ4ړ| 7(< MŬ}Ea/nʢ{S$ϧBճHҺ 2vk|1_tyCW0YyI0&.ZxYAiyB+D7UFX{f@>&ZX2r ~/'B @a }uRg+cBA)vRm-סF$CxG˸}'#$MaFW0 T.Hܶ\ X}"L9)8ܭ'RFf$iv\ >ލ{/՞ ^Ti(Fɠ/C1BEGIh]{6q@/gŷ]ŦEeI4` zϞe_VՐ0'̞WtxbNL@04e+L61~I*c%ċ Y#АE!Ӣ*._vn[APC]h4}j\CpڮUzR WT=`)<@ YPFVV/)طuE'WhK#2/b:PVd>D5RYF5;.~WmT_3sy>m/PkF)Jx` օ|X^(KbN,^!|bT1A`#TNڶ63v@6S& f]\ODpBbk"-/q Ml\BV*25}4هrrI !/ >kϳa Mj[]Sb 5!@\*{y@>f-=ñpK 9p;p7g.+`&\qH'B=, )8l`(|<@[20s6X2F_)id8E!=sD¾'4 Q8G@a02~!VJcanw0܄}䝚~ӄF8  7xd;Mj 2ܤrd[CP`!ZgTg%գ" svZ(\M:6v6#"NJz-ٝ;B_㭚g- ̍mS.[ypA A__̝/#G,R拟2,DVѪ8o5&]7iL˩(ZΕan{/q>&37n 녱@򕐲Rby&ޯLĩ~苠a4ud}h͖e(#)ʆ[k dƛSDۥÍ8_Kkb krhIe2t7>Kuu{IxbLwÐ~^lCz4isz `J't]-V)`dI*╦׮Ae>5!TV!%#Zb}{9Oz@3 >_ 7iN~Ө;>9 Qc{<R2F 1=RH` V6' خBznܦϲ@A;o Wʯ,0 NPe~+PlZC(w RI!1FÊ?P]v^D^>qi *FϞ;%GUźAH(`vV ߑ+_cL`o&NV&sC(qu2I.F)~X\TbR{M_Kbc$R mVt(8wWx[o֫8O4|`wfP~5 Q<)xWPrIm;'U8Qߧq#N#.w-t%/{Qw5¿ZXJ3쵡}2'mQ5SA- ^'I\;-߲ǠcK-ou~H*]b7,{Z#ӝ8$"\1 @.ì>_M/ǵT@.kS=;0 ttdMłg؅#{i:uL )ae"+kAFVEOHIlHmyL]XGyV =$!Et;V kuc ŀ@>ۣ!2Sg85@r֓\g`bv 6)3ȒuG=vҲu*|@ ":RcܢVD~ Ҩ!iA,$iL +4T2;1@YQ$ >ǀng/*zJ붸&@Z%EХZ,  A 6᧸r(ndt0 }YH 1y25k!W{#D9?n01ވX@@ wY륢چSV6̓A_"0u erofdrݲkF.UVu!8;E@z L,7rqp=ڼd);jwScq ay0k|%ICOD aB'F.Ys2x(lA$)8vˏʉ>ZU*GU" %-ԟ=+azЄ!D}<"|HXeà^D$%{Ury{TX!`'ّgX* U۳掸-Ď~!Kwnm9x6 * YH 0vhU43ubbNMJu~GtcּP1nG3Rx!{32ͮjf!{*e:Ӿ5M}8748uˉ|+%8ފR% 2~᩷1Dh/po\?u:HrPe=] EExe䋲M;bL:.kH"{ 9?in8FnYC{Wg-z, ~(\x/wKe;KM3 r,g/"R:&ɉ{:GeX̯ #Cyn@# VGgP~eQ[U\7?MAQ_JĖ I@YгO,o>gv3OsX0J?I4㵴{EK@*vK2fhXʲb$> FQ䔩g2 5B?Nۑ5F޹8C 㹊Ŧ#g!d /q %=:=6Xs0ukܳ/s/GVO +;p1E *K<)z 鮀ApdcJU?G^toSMu9>%[GiĦCqZEZ9HAmfmp9Bs;{ 7X4E+@M3bu*4,3.!ډCAڬs%j1{o=)CFߖ& 7HKtoIJ J9IJ֥(1neۃ"&/ڐ)MBu|@`UƑ$=.zIddp Q$8Zv >yҙw[RQZI6@-)^붕m"`7&e]QZw2\)9+2@Āz_f(+Y)x'&|):^7I$Vԉ' ܄Plf#U&zoxbdW^6k?Ka;ym <4drM.CV6Zs_/PPSIQ?9S C42nqƱ)OMg`MTGzbDi tf6s/Y AinjJ XC甫IB\$p b^uzyJ:(6)!tkrÉ83OLjC=C SY.%uTC~NEnʭ >PRIד*g O!+9wx֤D }@Bp$ˍ$}gtsՋ.rÝ7&ĺD12pjN+$8ɂ=^Y~3b.75ҖUSIsDK~ 8ˌ'2D 3GOjRm3&!LɔwZ.E|+<8v4bL[ @0Fmk6 \'A?LP֒Zb|BO{H?$px/ܯdl6)xjIv*1;DS{f6r zvXS- ;T?0CZ95cS({4jڦ{ /M|3<~s\e;ΓR}c!b^n ]§m3[ M!>Npn؀@̩?^Ykɐ?@WH;MMf\H(vufY*ۥ#vzˬ>/j~i rnRSUj[,JM[&ܥc—-IR{8T?)ke 7  &7'0ټ6`Ap4M Tw&zQjW2՞4)wk%ED X2{"+6kjco]}8) MH~p3/tI)d(~y _W_nM5 . Y!e#IMPo-rSpl4fK9Pk}uMN`V]>Z hrn("2 gku͹8>iAxl/Dx0葐7FȂ] ;~%&W>\I R7X [Ұn>ѵ2N7Rn#"7kI u8=DRŴsFkT*0-p rLx}v~38m[% kR>KʠY{4V?[os<+LkAN[9֞_Ώk懨@CTD7y0NYh:]JWΨW><,kK75M7׃ H ;$;bG~a'HA3> VO38:5!KDHCMPvU$V&cXIULƈUϭZꞶ קMBh]Aٲsb [*K]۝тG]quAG'MJwnR9Qن)9"P3V(e9(dk2^onXr^{$<0kY+lܐMz(9'YwJ)3WO׫_67cIK2})5>$.=7fr$o8(2+iOqIR1mpjs"[ _*k %k!;a@ /cdqE5I>"1VX#gQ3 iA;)[MO;D[e f[9.rt IְPwB=A胴ϻԁ:B pSS:yDrHId<~([ sF)䊻6DbK_ 3jU̺XsOlsI-kvbha}Cxr xh@R7)Yu.p E[ LL&0pX |aM-[ oV8qK)F;ڟ45&*x`eCz(юp"nBQ}+}^Ԏ넊ARc$0 d܊$R !؂h42jglCɰ9?7ɼَixVR5 9br zμ:jy!!R) 9ohO͒ ltppv0Q 0"1JE7* ͛"oF,-Q*-}$dFdqJحQؘ;+74'2g )?S`zǽ[എ~ ( ֳhǃe"XN2]ܔ6r?-4pV"WyVV+Q(`vW,("$L*VTKQ J ol+='7BeͅryPR/i~f؍JP j->s>e"Dd-_PgI[X/@ UVuG!$;y.yˀl+b?2cVw4D`**dGN)uȐ Йkc qms[vzL,' a@dw9"ukoyr io0"#N䢔i' `Ċ^& f<۳c!%V7T+xDq֭!qקCCRV'[֏ 8'}b*ƦAԱ a; 1cѶ}Y1N)x$ҩǂoQV3BxIzI,x!PG^21*Sp\K)z#lsd!wJ6h<NG<-=%^Xh<]!vO八6RsM Mfӯ jsL}h3f͕̂!@YQ b^N]0Z)U-MBdDw巽xOFqj:6W0:3 }qJoh2Kc!C!ik'~3mIO=xU#Zn)&7NBqf0bir"Dެ(^k ߘ4QGm٘LT:@nL)o//Rc£QP{z-%;hʌsucy+:-tZ^>ք#⒧3Cl_ydºAljp~_^tH~uq䛃 ^~A01ْ!AYH+TϚmm"ϵ(<((c^"_ vh3ܷأz*6qPXa9a `]1T U*i5c4!I'\Z2ZSS1LZ ]~!RV~쐼[clW뫗 p[u#bqTdx1þ38qA-JexcMaUw@pH_ p@jU;!mF3jtZ5FV;2E<"ZOL km" 3W5LQ?i12IT.e-7#)jCN&~g٢;uN߅E?x0{X'8ܙ3Am>6hb O?L:`PWa|_nkƟqrTdBB$.[ޡH;TOUNhL * 8gϤR"lB~T͇6JdPA|D:s#6L+  ]nCch| $~oj4zR ?n?--SJxGSP$@+(d#KT 4UPvcERϭ,?2lw׼]bD9wë11:ZhjT/ T"[?yocEs23u4}"b4<"|j*Rp<'"A{}UO DzuSz` 6,*twYa!4F* }ӒC#e͇k2,ʰQ=8KVw8eN\pıN X5Z{pcqx2a\hy8IPk$؃/asx1- dn:fv4Rvcr6Jcd.)[EH{ߦAMFsri^ {\= 2nM@nTQ 74bHf̊;sgk֎N,;-ٔ1_#Ql.EQBYIP?haKK۳cLWLWY?5;F[b9$R pVXSK C倆,aUhǕ2۝14n㩞&p(e_=A[bfb1ʭin Tu%_az*G26p4 ZN!8~3a^!w#vrT'@ܤb-K{^ C-Cx ڊo >c.t!NLdd%VZf`t96yvPe+m/N$-@dJ|?'kxݝ[BD-,Rɳ:v`rݵ`MsUAlYsF7gNc=MI@Q(r~#lͺ >C0heU-kp4b<0"pY¡>a7ۈ 1T=SEMBxtb6q*(WqYFdw@ef6"9\{E@pG>ٓE.cN7[m1 Aj8 sanO5+ z7 ЇU7ޣ{YFKR,|d,=-SU4J+I jA!ĵ M ,5— =Q f*Pym MeMk6N+'Nbze0Np8(?0I|ωϿE n@v1>2DӺ:)|y<5V ,*lsJAhL‚MQ)ܳ`ֶz*/U֠^*WK_!/'BdoK.T1>JAsc3J@zcy͵؟1I̔yNAϡZ'bv)Nߞ. =hXBxsFtA]fE{wVPRjGL±Hp’Rz MFb2u)U 'O@XoH]1=xc0aJBX̕_u1;*9b^pfNQɉ7b3Y*'ix$-5aaA]^o8/ @rmbZ8N<$󥺘-ol$\WG,TxGJ-ސW4%TcaaxtDhqw@{([&Ģ[~Yk *>x{(IoYP]^a!VwFҮ!, mmp-;׆f ?/|S`/@<56\H1U"BSXvwf{1xE&~t:ZZt:H}C =i $uP:6w S*LԀbCu?\e3jVMS P/g۱C!QqWW~&RYߗldZdm-~ @6^ HnmkNFyaǾ-h/Y!B Gf#zojXu4|4ɞ[+\v:7T4-1RtޅL !5M層3T ҫ!eW;鏾/*f/"7줌^XFKy TT{|I !ĺwzjEo[Mbnu/wZ}AL#=56A!XV([0,xBT!OչW]8*$C#1DMj ,Z֖;4N6Tuͤ',5wjp޵Fz#9B3S [70݆}:a W㼐pP CX.Q2b9#wvU!p zDW8#KmcsVdUNO:dol_F73!05(@ &bXaU>ѝ*;0Ŋ}H NN2t?Cc9s!XUǃoD- n*uyeoe;lXiﲍ8Y:dNŠ=gqu)#p/7M6 ѹژӈz T[_, >ve%W7#TEs!G+|o L]Mn,p9bVF&r^ #X֋w3Tmx=t KmJ\ź`GhYvE_nmϿ!&)o*M+*)~䖺ΑJ59H&{ݐ;Q6':dŨбŊ '̓}2ne^ *Oɒ ѼS -VJS><AF F=VV1'aŏoG\̺5Qeh T;`~kǁbb@ÛXg3!敏n\bYKL'Fx*Mm'2s;2 Ɏ \Sew& Vf|& X;lO1B8leQ(`DqMԚQJQe{m^lnZ#/̄C$l߬rk?}-Fr=%s}UuIσ~_Lٍ> -&gW/쳽9;oY^ɶ/eE=Nt j(L5:n'3>|ϕȼ7Xv*l=k,quĦ6ޒ=v4_Ex{TSv޲7k'eڵK|qؼ&$8 LD"!хWx_aDQvh2Wa2bYbL1ZS{Ɍ-}XLT9-ʐ:Zo$GPIBP̫;4߸;e*.5C ឌNUYs ZGW3UP*Vi$O5?c/[_9&}Z<:! s} m@L[K-"E-a&V9(Y0T&"{f`g0uZFldFBy~65M/^-t};f`J99^!0t9KdBKpym,-l q3-#FvIJ*6h K|!އ a12T9ĞuG]aٳeFחH\Gz%1XŅhPU) Ek6/cV\̀:c?L`^d2ÿ&Oz12nɻ`4Ve/f_qw Z(LaGH8 zGINO焷0m4O gg)~pN!TPwJΌP s,64ª*w>PwjwڔNc9<ֺ:8jnC{-ҤFxpma3n  (DzG{kS%(13 ~"U75Hz|n8?m%"ﶖ{)|~3Y R}^>?N7 mԿdU5 ve2)wԜ{|$Z.k3!OKQO&(pN5<6$q+@V<>4L5QJ 1"6R"^Ly {X?% ,f{&7!3Ѫ|~\ 1[߇;3LS2pDߚ)t\)lF48Acn Xe꬏<{38A#E39( FR8,DlCYMfBa83%.%uY,A"uKwi~^2%JCsL¸'(J}ܝ o#PΑhБj17;7gu.g/ʽ zm]'ΨBfYFlzVC 36=R*&z}k]Ĩ6+^k%T0>?s'٩ &fJn0 O\c Q1Ar?|zG?Ϛ{N~z!Z]< SdQ\ (I,`Oa6_\ ,ٹj*7?UPank%KT$I49/8d^f8 t%iBLK%}dÄsЂݙKoGNI-8=8JZ,XUB63E t]=,m_z:} Qn(>`?y=Z|`":&6'sYέ5̐]QuOr5X3N}#KNÌiGmuBͳiP猉B&̧y-W.P=fb n^]I7D^u瑼CdS/݁ S T]¡3LpKĪs.V6孡e˿Št-)=B_,kzecD"번N_CuyTk$o$,6~V}Fk8,^D'sVkS"z4^Ev ;N_i=d“6 U"U/^Ax7H;Z91x;ÙZYZl3F٧;&<7VkLNCdtȒYYf Bh~%wi `fw϶:Ŕ,p\DP?Nzt^j sEoW[#Yݦ[Itb\is#l?^q0'>NeJ^x/nL.H!5LƯӭe@Ӥ1XP]*>lO9ռ\aa74˞IU4OA(>2k,r%P{,8.ws_/ҷۧgY::7AdBWXt`[1\Xb0ݲcQ ^x^,ygRy9j0 cc /p ϗ|HcEuH^ qJ /=V6~ȿQtUoyl$$,$RZt(u)V˙$R |7m 6[+ Zr'Vi.A1ˢN=ڑ8^2ŰP %ӝÒEJkzԕd>ł5]?v|p=6EldCBq_ qp+y)q Njt$@A޸,J)"DqlHau)΃)UpC*IZ%FcVmms?˶uIY!O31+O|:NV y~c!VVHT+_/$ٝ4 2Q;BbYybv=uI3u׻Z >qr>NiBEb&msi֭V40$^uV|"8,lzK<#MSJ*%68>Q)VfvնOC^M tӽND Dy;1%f4> 7ae:qUF"]< !Lckw(bR-ѷ$Xj6,-\טYY5A$S(z Q+;}ra2])ucO񚜜rVX\5J鉁Rg@wQFW.ކ Kp#V q`• n NV$:ggaG1nTLGAt(-sU/oz(hrXETMUK2=(Xw)zyx(~ h8NfYnȸnia#}/zlx'vPks&&tpoy{SNzYMI1DmsT*~K#!|᱑n  Qot襸2ʣV#غ35w- EJ 8 C%"]=76X=6 vc(O,nʡXA~3F >GQ^C&^ QQNf|2:OT|CZ_qB90#I7 .0p~DPW~hl[O-4 `  ˛KHxS&~m #Y00t#r7&'kѡ:J.Ł Sx7Zq}̙N"mU<QL #RZ;CϹIO"JZݘ飰FE]")}s}@7u f~7I(%[*}`Kd'KK0,#P?@Dnb32.ѝN(Wrr#@L+bsk}>߽.oJ7Q`(^XVZ"I5Vى&2ĜI7%ZWq,{sh5jF2@.{?a)gO#Y(G'ϓiiZs4Ijim^ϡ>G؇{]"ܤ0/}Y]L(<$ʢuJldUؗ|$뵁b0Tnٗ rŦ4`Upn2JV5U 8DJBNذynR^:؆Ake,Seפ{%Nn.5TWA:}oԆ*Oс«xkXd!"_F"fm]?x@}{pd.u`Lzw{oowWoU6>=E;\ Ay7S (LtTV>޴<hY WF/#'V`:>cuHCvc܉jYyS֝*x@V@dWPIbw]|'t(=hQl.XZߣΓ6 }ΆZiEh+ cde/-\ Y6D^#<7#-Zrv9[Z5`u/@w݉$j ?uc4zP]c("Y,zj'Yf8ND'Q1!#e`=ԢR1KC #0\;9)3xD4I'D u\s<C\5r`%Ǐ ?PcPn|Z"ÔG7!4 DocᲯTZ)i| l./:2^|/KA8#X93%EF1Iыq0n-i⫵ β h\^ uo(Ḧ́{0=lU(4 qCdceP_cYA`WtY^Ȇ0iAX+}*2wغD`]9q $ڈ& QȬEqn^DV&fQ6ss5AzS̼?LJ݇2 K$3Hk7o !}XTqΐ8`8FntL ixԦDH[]JV+oAwYpƒ xh4{ogbMS~s6|7,<'L!n9)Ӎ6 g8H % DC Ɉ{Z⠇Htu7 e2i+#hDžN*Ze*8}V9-JbIVT~Prn(w@[p'샾\*-˸>ej4ŦQALhEemYbB4EmLh'\,UuHE"f7s7.Υ_ƉL˕?x諪; rT DP.Zjxd * b}>okZ0*]~ 9x+7>_Pџ'np׊=b$p6<~c]zWJսr޶]V `! dQe镟Zi]2П)5/o3\ݥe'-KkFH-2K]λpUHa;jz_QJQ3DJ]簖ZdzrD!V`y8 khs^z|ͅ/$>D u=\/" :ewF5eU7~񚊌QbWZ xְ+C:G OOEEٻRiLy@%Iy b\dfʭG|N;yD꺀{z>r/wh:䪂bH?Ax{#8kCٷPlW[)4^oQeP6rO(7 z&]+4r]wz27D2LGu1K/${}BK>C2) fKbD"Aܩ(=yz7׿|bpo"~P؂uhsXswk>4E3o]/|8nj P< |uI==5|e3k73CP|-"g3EJOTVMeӱۢ-bܐYZ%PX;aY% 4$ o~Ujڮ>?Ovtα~BsUiD/ /wqY}z{on;Vd\y!vHG2tfmSخ!\sNׁVrE\?!-GPiÉ`^<nw,IMYI*R 7 Ƨhr-`+6F^a϶8ہ|S8ŕeݎ5[bC;5Nڠ&>X@PeگٮX9L&v_} v2Y#.ִy2R, D"}!ZKTs-n;Cmę7_Hx]sȠ3?\?&6 Fiax6l+1@ զ1GC#Veψ<#)f9!IoKˌLe]&hFTMB^O[qOqX{s g*zwWݝCְ@+hama #6&|7pXo6\tE}Pڽ`o=mjhul;x `tnºSgjO bz2Nf3;,-tr-) ݚ+ GsDMCցX&*E.Q]Z# m}0+D4͠"PМ|UO*.vydAbv6 `;Cs"zأ tq #f& m-}'it3XO A+U ˩%ԃ~C j[@󘺤|%D[Yi=3e='^xI(JeO!~T'@?__\'\7KTTr҄w*~:@/:@'B ݹJmLA=8he] W/3SvAjʮE ܂ _n }1Vs\a,({"Okđ7Nil99O!r!L^jʫe,e{% @^N!Ffp4B؃zg7%j^C5qg7ބWo7>i \$!JW>MG+$34Ic:Ks )o-_߸F"g7˰w/4B-qCbt͠CMO+O/WD/$9w/7g;F W1J(*|9)K̍s[Es""Y] ][:OqG.k"ݧw-1B3^bmo2ՆOk2;}w@ t<>:yzT?x|@^m&}&ȑy.P(߁^i0 ^\+^vS"s&0 br[&m*mt. 2s2u}hY{vˏem}v1\;Ll1!qI/2Kvn],6b CIyp"0K Yʾ@䯽c44'(Q+/س(qs,c_&~"2oô{SO}K,[sWnBA n"hpB߿ "O@hȬjw¹ E0)C#bta@cH؋L snx}';N)6oZ]9;aX6yv CJZgKmG(ncBwH|()D ;`4V$j8C@H Βe8\µtlߵRo+dw7{4DvW`K?l;u\4SO,BuH!eBK$ bFbзM,+Syk65VczMr<5^M s/;\ ;HQy@ѹ1ZCcXtMƒ_{cP&R3Fdtxl6i0sQssgPB_⽆j>PoXhzշC"VJ$GAe{x_Y2cyj^9V V53Xb%_D}%)h(EEZ)L"%Op~"t*qETl'ŹdץTw» AO(kI^-7QNrP!|ʓ\“!yQ5`b$X&&`Q^P]; 2MR7o.pg_q;{ܨ"L_\vWG,U)_L3hI(y&8L['c!|Y̸M9K_%gT[D@ofm@AVߦAǒ1Gt;M ݊ J*(WE6T g+w0fty4t..R6eCfJ;cy޴0nFK7?]K/xVʥLZ}!WOWPiyg?" l OA,t@@Oka)hP=n\({%Zq%]{UDE(~ 'O^M۟GX `?8G}l ia_k-ga]e~avOm$Tź:R,sԏ[b癃Ͻ0x{ h@rLV75"%?a| X_#Yk|&Upm`EAE/Ԯ NLm_>Ӯ\_A-P +`bǑ!))#Coo)liQZ=IokltP߉G=Z5”J,3^~45!x%fMªAwxsJ669H)QeIɌAp*"s`U5E-:DfǨu*J.Zm$ {0Ey fVAװH{>Ϭ\'ZC ;KMgVHk1_R3ְ$EGN .tIDF@Otx ) 8uߖTBwXZi&H߆ m- _-QUkO˒m g .Wu/E}˒H:ڹT9r9:骴LH.ϔ3p&O#jTyMkh?k|Ɉtr Rw@-)cHuyn= ẓd(DVcJ@aWf/ ~@P.3 WǗV kFR7g%?Q%ߍcVZ¯Wp  #Rz3:5{XӫkfHox?eٷgƭN>J1JNU 6yƘ+NaQHcFzsFxah_nB7apJYյb6*&y7z}pud!d KL ڕ>szU?It2`(۰ib=$Lڕ_3FK XΩ{q+CRƼ\Z9zK\dbw(O V1.{BYeq.Z3}n\NX 5mf^>2pdy܌HlrU`к=jh/I|ّS=5MiyGUЗ_]<i-o.sZLqz2IӴ q(Խ}jO(b{yۭ-=@[֯}[WkBJ\ }Y fPN{{I'^r`t1סL#7Fc7sD1*؏BV?7CI9V`{py'T{ {E! 0EBS 3h0pL(Vs=sg!>ז߮?v{Ki.$a PDv S񹆲Te+D֬hbvsޱiAJ â BtQ!}g[k}[ TہLIC8H5B7v0$L TWy<`'@l˘p;?Vmv6Hʜ[=`"c #V]/^։ΐogMBTRq)\𜞜\>P7v2~JV,4 m@ O97\N"~ DJ9}y㣭ʉׯv݄o}5MCUSrH+xDHso+I0fy#YzHNHɐRI JC8e7 E#i8!ʦ3ezƘ/'GY-t}X}gϣVa=_]%!,F&aaTͦ.ZX!*Cll&Lrʄvѥ4h-;^ϡmD@`Au WlEPFj%+iu;;4 {n7pgcrUs}@h1wMiHiNT`A0Z5 *7K2?X$U0 vdFx/Q7pVe:rC;+ g`ImR߂8PQ0_WANrU{tAKF΃#̽גu#fHπW .ֶ#mi{ڣݴE]Jṉ^0C"#Nu@CpA{U9s|,8A4,+u2ܰeDAq8Q (\9'ʗBxH뚲\ ó5&"{ya'W6#_IJ,S5_)#vWx 5/r_)U|ڑ7|\Sl 92AYV)uP@o FHZw hɴ`%zL F%^]iœk.$9o sYjo|&wi8jx gh?>];L%MXJ;nI0TYy-8=ْ|h'L jDȖ)<|XreT-5  Qymw_9}P0}}0LeVQ2L ~ w0*LH#лZv-l(uLok+@8/͕>pOgή*mXUA8Aȏ"?Wy# eb9̹C`DBn6,1濛a%0M\k֏oQzO8XBE9| \M$5܇ wwwI꺍v\Bt[ vKr~aKi7W5G 1,Yfi)׾S%n 1znǜOyiNeE}륦E|T(v 7E\G'kpRcy3VOp35ĩ=EC4b̏P0#&'>z턮Y]oK'r裝ZBK@*@Ȭf}>*JHc\nҠ8CTF:l/ Cg I̸7=-KNCp( 7w8$5Qog=.8w/SA*#YkGQ";|!έIPV- t