mò *á¸Ec@s dZdklZlZlZlZlZd„Zd„Zei dƒZ ei dƒZ ei dƒZ ei dƒZ ei dƒZei d ƒZei d ƒZeidƒZeid ƒZed ƒiZed ƒZdfd„ƒYZdfd„ƒYZdS(sßModify AST to include security checks. RestrictionMutator modifies a tree produced by compiler.transformer.Transformer, restricting and enhancing the code in various ways before sending it to pycodegen. $Revision: 1.13 $ (sastsparses OP_ASSIGNs OP_DELETEsOP_APPLYcCsY|iidƒo |`nx5|iƒD]'}t|tiƒot |ƒq*q*WdS(s)Strip lineno attributes from a code tree.tlinenoN( tnodet__dict__thas_keyRt getChildrentchildt isinstancetasttNodetrmLineno(RR((tB/data/zmath/zope/lib/python/RestrictedPython/RestrictionMutator.pyR s  cCs$t|ƒiid}t|ƒ|S(sMake a "clean" statement node.iN(tparsettxtRtnodesR (R R((R tstmtNode#s t_apply_t _getattr_t _getitem_t _getiter_t_printt_write_t _inplacevar_twrites_print()s_print = _print_()tFuncInfocBstZeZeZRS(N(t__name__t __module__tFalset print_usedt printed_used(((R R;stRestrictionMutatorcBsàtZd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Z e Z d „Z d „Z d „Z d „ZeZd „Zd„Zd„ZeZd„Zd„Zd„Zd„Zd„Zd„Zd„ZRS(NcCs+g|_g|_h|_tƒ|_dS(N(tselftwarningsterrorst used_namesRtfuncinfo(R((R t__init__As   cCs^t|ddƒ}|dj o+|djo|iid||fƒn|ii|ƒdS(s7Records a security error discovered during compilation.Ris Line %d: %sN(tgetattrRtNoneRRR tappendtinfo(RRR'R((R terrorGs cCs‚|idƒo%|djo|i|d|ƒn|idƒo|i|d|ƒn|djo|i|dƒndS(shVerifies that a name being assigned is safe. This is to prevent people from doing things like: __metatype__ = mytype (opens up metaclasses, a big unknown in terms of security) __path__ = foo (could this confuse the import machinery?) _getattr = somefunc (not very useful, but could open a hole) Note that assigning a variable is not the only way to assign a name. def _badname, class _badname, import foo as _badname, and perhaps other statements assign names. Special case: '_' is allowed. t_s;"%s" is an invalid variable name because it starts with "_"t __roles__sB"%s" is an invalid variable name because it ends with "__roles__".tprinteds"printed" is a reserved name.N(tnamet startswithRR(Rtendswith(RRR,((R t checkNameOs cCsj|i}|idƒo%|djo|i|d|ƒn|idƒo|i|d|ƒndS(sÿVerifies that an attribute name does not start with _. As long as guards (security proxies) have underscored names, this underscore protection is important regardless of the security policy. Special case: '_' is allowed. R)s="%s" is an invalid attribute name because it starts with "_".R*sC"%s" is an invalid attribute name because it ends with "__roles__".N(RtattrnameR,R-RR(R.(RRR,((R t checkAttrNamehs  cCst|iip |iioV|idtƒ|iip|iidƒqp|iip|iidƒqpndS(s9Insert code for print at the beginning of the code suite.is+Prints, but never reads 'printed' variable.s,Doesn't print, but reads 'printed' variable.N( RR"RRtbodytinsertt_print_target_nodeRR&(RR2((R tprepBodyxs  cCsÆ|i||iƒxV|iD]K}t|tƒo|i||ƒqx|D]}|i||ƒqNWqW|i |i ƒ|i }t ƒ|_ |i|ddƒ}|i|iiƒ||_ |S(sãChecks and mutates a function definition. Checks the name of the function and the argument names using checkName(). It also calls prepBody() to prepend code to the beginning of the code suite. texcludetdefaultsN(sdefaults(RR/RR,targnamestargnameRtstrtwalkert visitSequenceR7R"tformer_funcinfoRtdefaultVisitNodeR5tcodeR (RRR;R,R9R=((R t visitFunction…s     cCs1x!|iD]}|i||ƒq W|i|ƒS(sÉChecks and mutates an anonymous function definition. Checks the argument names using checkName(). It also calls prepBody() to prepend code to the beginning of the code suite. N(RR8R9RR/R;R>(RRR;R9((R t visitLambdaœs  cCsl|i|ƒ}t|i_|idjo t |_n1t i t i t |itgƒ|igƒ|_|S(sdChecks and mutates a print statement. Adds a target to all print statements. 'print foo' becomes 'print >> _print, foo', where _print is the default print target defined for this scope. Alternatively, if the untrusted code provides its own target, we have to check the 'write' method of the target. 'print >> ob, foo' becomes 'print >> (_getattr(ob, 'write') and ob), foo'. Otherwise, it would be possible to call the write method of templates and scripts; 'write' happens to be the name of the method that changes them. N(R;R>RtTrueRR"RtdestR%t_print_target_nameRtAndtCallFunct _getattr_namet _write_const(RRR;((R t visitPrint¦s  0cCsK|idjot|i_tSn|i||iƒt|i|i<|S(s‰Prevents access to protected names as defined by checkName(). Also converts use of the name 'printed' to an expression. R+N( RR,RBRR"Rt _printed_exprR/R!(RRR;((R t visitNameÄs cCsZ|i|ƒ}|idjo|idjo|Sn|iid|iƒt |_|S(sŒChecks calls with *-args and **-args. That's a way of spelling apply(), and needs to use our safe _apply_ instead. iN( R;R>Rtwalkedt star_argsR%t dstar_argstargsR3t _apply_name(RRR;RL((R t visitCallFuncÑs   cCs|i||iƒ|S(s+Checks a name assignment using checkName().N(RR/RR,(RRR;((R t visitAssNameéscCs.|i|ƒ}tit|igƒ|_|S(N(R;R>RRRFt _getiter_nametlist(RRR;((R tvisitForîs cCs.|i|ƒ}tit|igƒ|_|S(N(R;R>RRRFRStiter(RRR;((R tvisitGenExprForÿscCsh|i|ƒ|i|ƒ}t|dtƒo|i|dƒnti t |i ti |i ƒgƒS(sÛConverts attribute access to a function call. 'foo.bar' becomes '_getattr(foo, "bar")'. Also prevents augmented assignment of attributes, which would be difficult to support correctly. t in_aug_assigns2Augmented assignment of attributes is not allowed.N(RR1RR;R>R$RR(RRFRGtexprtConstR0(RRR;((R t visitGetattrs  cCs>|i|ƒ}|itjoæt|dtƒo|i|dƒnt |dƒo=|i }t |ƒdjot i |ƒ}qè|d}nV|i}|djo t}n|i}|djo t}nt i||gƒ}t it|i|gƒSn6|ittfjot it|igƒ|_n|S(sLChecks all kinds of subscripts. 'foo[bar] += baz' is disallowed. 'a = foo[bar, baz]' becomes 'a = _getitem(foo, (bar, baz))'. 'a = foo[bar]' becomes 'a = _getitem(foo, bar)'. 'a = foo[bar:baz]' becomes 'a = _getitem(foo, slice(bar, baz))'. 'a = foo[:baz]' becomes 'a = _getitem(foo, slice(None, baz))'. 'a = foo[bar:]' becomes 'a = _getitem(foo, slice(bar, None))'. 'del foo[bar]' becomes 'del _write(foo)[bar]'. 'foo[bar] = a' becomes '_write(foo)[bar] = a'. The _write function returns a security proxy. RXs?Augmented assignment of object items and slices is not allowed.tsubsiiN(R;R>RtflagstOP_APPLYR$RRR(thasattrR\tlenRtTupletlowerR%t _None_consttuppertSliceobjRFt _getitem_nameRYt OP_DELETEt OP_ASSIGNt _write_name(RRR;RdRbR\((R tvisitSubscripts*        cCs;|i|ƒ|i|ƒ}tit|igƒ|_|S(s•Checks and mutates attribute assignment. 'a.b = c' becomes '_write(a).b = c'. The _write function returns a security proxy. N( RR1RR;R>RRFRiRY(RRR;((R t visitAssAttrKs  cCs|i|dƒdS(Ns Exec statements are not allowed.(RR(R(RRR;((R t visitExecVscCs|i|dƒdS(Ns!Yield statements are not allowed.(RR(R(RRR;((R t visitYieldYscCs |i||iƒ|i|ƒS(sîChecks the name of a class using checkName(). Should classes be allowed at all? They don't cause security issues, but they aren't very useful either since untrusted code can't assign instance attributes. N(RR/RR,R;R>(RRR;((R t visitClass\scCs&|i|ƒ}|i|iiƒ|S(s‘Adds prep code at module scope. Zope doesn't make use of this. The body of Python scripts is always at function scope. N(R;R>RRR5R (RRR;((R t visitModulefscCs°|iiidjo}|i|ƒ}titi|iit ƒgti t ti |i ƒti|iiƒ|igƒƒ}|i|_|Snt|i_|i|ƒSdS(skMakes a note that augmented assignment is in use. Note that although augmented assignment of attributes and subscripts is disallowed, augmented assignment of names (such as 'n += 1') is allowed. This could be a problem if untrusted code got access to a mutable database object that supports augmented assignment. tNameN(Rt __class__RR;R>RtAssigntAssNameR,RhRFt_inplacevar_nameRZtopRpRYtnewnodeRRBRX(RRR;Rv((R tvisitAugAssignps  3  cCsIxB|iD]7\}}|i||ƒ|o|i||ƒq q W|S(s(Checks names imported using checkName().N(RtnamesR,tasnameRR/(RRR;R,Ry((R t visitImportŒs (RRR#R(R/R1R5R@RARIt visitPrintnlRKRQRRRUtvisitListCompForRWR[Rjt visitSliceRkRlRmRnRoRwRz(((R R?s2           /   N(t__doc__tSelectCompilerRR RhRgR^R RRpRPRGRfRSRDRiRtRZR%RcRHRYRJR4RR(R4RRR RHRhRtRJRRfR RDRSRiRcRgRR^RPRG((R t?s %