Xc"@sdZddklZddklZddkZddkZddkZddkZddk Z ddk Z ddk l Z l Z lZlZlZlZlZlZlZddkZddklZddklZlZlZlZlZlZddkl Z dd k!l"Z"l#Z#dd k$l%Z%dd k&l'Z'dd k(l)Z)dd k(l*Z*ddk+l,Z,ddk-l.Z.ddk(l/Z/ddk0Z0ddk1Z1ddk2Z(ddk2l3Z3l4Z4ddk5l6Z6ddk7l8Z8ddk9l:Z:l;Z;l<Z<l=Z=l>Z>l?Z?ddk@lAZAddklBZBdZCdeCZDdZEdZFdZGdZHdZIddZJdeLdd ZMdd!ZNdd"ZOd#efd$YZPd%ePfd&YZQd'eQfd(YZRd)eRfd*YZSd+efd,YZTdS(-s? RPC client and shared RPC client/server functionality. This module adds some additional functionality on top of the ``xmlrpclib`` module in the Python standard library. For documentation on the ``xmlrpclib`` module, see: http://docs.python.org/library/xmlrpclib.html Also see the `ipaserver.rpcserver` module. i(tNoneType(tDecimalN( tBinarytFaulttdumpstloadst ServerProxyt Transportt ProtocolErrortMININTtMAXINT(t Connectible(t public_errorst PublicErrort UnknownErrort NetworkErrort KerberosErrortXMLRPCMarshallError(terrors(tcontextt Connection(tget_current_principal(t root_logger(tipautil(tkernel_keyring(tCookie(t_(t dnsclient(tNSSHTTPSt NSSConnection(t NSPRError(turlparse(tKRB5KDC_ERR_S_PRINCIPAL_UNKNOWNtKRB5KRB_AP_ERR_TKT_EXPIREDt KRB5_FCC_PERMtKRB5_FCC_NOFILEtKRB5_CC_FORMATtKRB5_REALM_CANT_RESOLVE(tDN(tapit ipa_sessions %s_cookie:%%scCst|S(sc Return the key name used for storing the client session data for the given principal. (tKEYRING_COOKIE_NAME(t principal((s./usr/lib/python2.6/site-packages/ipalib/rpc.pytclient_session_keyring_keynameHscCsNyt|}Wn'tj o}tt|nXti||dS(s Given a principal create or update the session data for that principal in the persistent secure storage. Raises ValueError if unable to perform the action for any reason. N(R+t Exceptiont ValueErrortstrRt update_key(R*tdatatkeynamete((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt%update_persistent_client_session_dataPs cCsGyt|}Wn'tj o}tt|nXti|S(s Given a principal return the stored session data for that principal from the persistent secure storage. Raises ValueError if unable to perform the action for any reason. (R+R,R-R.Rtread_key(R*R1R2((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt#read_persistent_client_session_data`s cCsKyt|}Wn'tj o}tt|nXti|dS(s Given a principal remove the session data for that principal from the persistent secure storage. Raises ValueError if unable to perform the action for any reason. N(R+R,R-R.Rtdel_key(R*R1R2((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt%delete_persistent_client_session_dataps cCst|ttfjotd|DSt|totd|iDSt|tjo t|St|tjo t |St|t t fo%|t jp |t jo t |St|to t|S|S(s Wrap all ``str`` in ``xmlrpclib.Binary``. Because ``xmlrpclib.dumps()`` will itself convert all ``unicode`` instances into UTF-8 encoded ``str`` instances, we don't do it here. So in total, when encoding data for an XML-RPC packet, the following transformations occur: * All ``str`` instances are treated as binary data and are wrapped in an ``xmlrpclib.Binary()`` instance. * Only ``unicode`` instances are treated as character data. They get converted to UTF-8 encoded ``str`` instances (although as mentioned, not by this function). Also see `xml_unwrap()`. :param value: The simple scalar or simple compound value to wrap. cssx|]}t|VqWdS(N(txml_wrap(t.0tv((s./usr/lib/python2.6/site-packages/ipalib/rpc.pys s css+x$|]\}}|t|fVqWdS(N(R8(R9tkR:((s./usr/lib/python2.6/site-packages/ipalib/rpc.pys s (ttypetlistttuplet isinstancetdictt iteritemsR.RRtunicodetinttlongR R R&(tvalue((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyR8s  0  sUTF-8cst|ttfjotfd|DSt|tjo!tfd|iDSt|tjo|iSt|to|i S|S(sE Unwrap all ``xmlrpc.Binary``, decode all ``str`` into ``unicode``. When decoding data from an XML-RPC packet, the following transformations occur: * The binary payloads of all ``xmlrpclib.Binary`` instances are returned as ``str`` instances. * All ``str`` instances are treated as UTF-8 encoded Unicode strings. They are decoded and the resulting ``unicode`` instance is returned. Also see `xml_wrap()`. :param value: The value to unwrap. :param encoding: The Unicode encoding to use (defaults to ``'UTF-8'``). c3s"x|]}t|VqWdS(N(t xml_unwrap(R9R:(tencoding(s./usr/lib/python2.6/site-packages/ipalib/rpc.pys s c3s.x'|] \}}|t|fVqWdS(N(RF(R9R;R:(RG(s./usr/lib/python2.6/site-packages/ipalib/rpc.pys s ( R<R=R>R@RAR.tdecodeR?RR0(RERG((RGs./usr/lib/python2.6/site-packages/ipalib/rpc.pyRFsc CsEt|tjot|}nt|d|d|d|dtS(s Encode an XML-RPC data packet, transparently wraping ``params``. This function will wrap ``params`` using `xml_wrap()` and will then encode the XML-RPC data packet using ``xmlrpclib.dumps()`` (from the Python standard library). For documentation on the ``xmlrpclib.dumps()`` function, see: http://docs.python.org/library/xmlrpclib.html#convenience-functions Also see `xml_loads()`. :param params: A ``tuple`` or an ``xmlrpclib.Fault`` instance. :param methodname: The name of the method to call if this is a request. :param methodresponse: Set this to ``True`` if this is a response. :param encoding: The Unicode encoding to use (defaults to ``'UTF-8'``). t methodnametmethodresponseRGt allow_none(R<R>R8RtTrue(tparamsRIRJRG((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt xml_dumpss cCs7t|itjot|i|ii|S|S(N(R<t faultStringR.Rt faultCodeRH(R2RG((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt decode_faultscCsNy&t|\}}t||fSWn!tj o}t|nXdS(st Decode the XML-RPC packet in ``data``, transparently unwrapping its params. This function will decode the XML-RPC packet in ``data`` using ``xmlrpclib.loads()`` (from the Python standard library). If ``data`` contains a fault, ``xmlrpclib.loads()`` will itself raise an ``xmlrpclib.Fault`` exception. Assuming an exception is not raised, this function will then unwrap the params in ``data`` using `xml_unwrap()`. Finally, a ``(params, methodname)`` tuple is returned containing the unwrapped params and the name of the method being called. If the packet contains no method name, ``methodname`` will be ``None``. For documentation on the ``xmlrpclib.loads()`` function, see: http://docs.python.org/library/xmlrpclib.html#convenience-functions Also see `xml_dumps()`. :param data: The XML-RPC packet to decode. N(RRFRRQ(R0RGRMtmethodR2((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt xml_loadss tLanguageAwareTransportcBseZdZdZRS(s(Transport sending Accept-Language headercCsti||\}}}y,titididdi}Wntij o d}nXt|t p g}n|i d|i ddf|i dd t |f|||fS( Ntt.iten_ussAccept-LanguageRt-tReferershttps://%s/ipa/xml( Rt get_host_infotlocalet setlocaletLC_ALLtsplittlowertErrorR?R=tappendtreplaceR.(tselfthostt extra_headerstx509tlang((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRZs,  (t__name__t __module__t__doc__RZ(((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRT st SSLTransportcBs eZdZdZdZRS(s2Handles an HTTPS transaction to an XML-RPC server.cCsvxotiiD]^}t|tpqnt|iitpqnt|iido|iii SqWdS(s If there is a connections open it may have already initialized NSS database. Return the database location used by the connection. tdbdirN( Rt__dict__tvaluesR?Rtconnt_ServerProxy__transportRkthasattrRltNone(RcRE((s./usr/lib/python2.6/site-packages/ipalib/rpc.pytget_connection_dbdir'sc Cs |i|\}|_}d}|i}|o||j}n|tiij}ti\}}}} } |djoD|djo7t|dd|d|dt i i dt i i } n4t |dd|d|dt i i dt i i } ||_| i| S( Ns/etc/pki/nssdbiiiRltno_initttls_version_minttls_version_max(RZt_extra_headersRst ipapythontnsslibt current_dbdirtsyst version_infoRR'tenvRuRvRRltconnect( RcRdRfRltconnection_dbdirRttmajortminortmicrot releaseleveltserialRo((s./usr/lib/python2.6/site-packages/ipalib/rpc.pytmake_connection5s"     (RhRiRjRsR(((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRk$s t KerbTransportcBsQeZdZeieiBZddZdZ dZ ddZ dZ RS(sK Handles Kerberos Negotiation authentication to an XML-RPC server. cCsti|\}}|dtjotid|n|dtjotin|dtjotin||dt joti n[|dt joti n:|dt jotintid|d|dS(NitserviceRR(Rt get_gsserrorR Rt ServiceErrorR#t NoCCacheErrorR!t TicketExpiredR"tBadCCachePermsR$tBadCCacheFormatR%tCannotResolveKDCR(RcR2RRR((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt_handle_exception[sc Csxti||\}}}t|tp g}nttdd }|o!|id|f|||fSd|idd}yt i ||i \}}Wn%t i j o}|i |nXyt i|dWn+t i j o}|i |d|nXx9|D]1\} } | djo|i| | fPqqW|idd t i|f|||fS( s Two things can happen here. If we have a session we will add a cookie for that. If not we will set an Authorization header. tsession_cookieRsHTTP@t:iRURt Authorizations negotiate %sN(RkRZR?R=tgetattrRRrRaR^tkerberostauthGSSClientInittflagstGSSErrorRtauthGSSClientSteptremovetauthGSSClientResponse( RcRdReRfRRtrctvcR2thR:((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRZls0    c Cs|djodSttdd}ttdd}tid|yti|t|}Wn)tj o}ti d||dSX|djodSt |}tid||yt ||Wntj o }nXdS(s Given the contents of a Set-Cookie header scan the header and extract each cookie contained within until the session cookie is located. Examine the session cookie if the domain and path are specified, if not update the cookie with those values from the request URL. Then write the session cookie into the key store for the principal. If the cookie header is None or the session cookie is not present in the header no action is taken. Context Dependencies: The per thread context is expected to contain: principal The current pricipal the HTTP request was issued for. request_url The URL of the HTTP request. NR*t request_urlsreceived Set-Cookie '%s's&unable to parse cookie header '%s': %ss$storing cookie '%s' for principal %s( RrRRRtdebugRtget_named_cookie_from_stringt COOKIE_NAMER,terrorR.R3(Rct cookie_headerR*RRR2t cookie_string((s./usr/lib/python2.6/site-packages/ipalib/rpc.pytstore_session_cookies&    icCs |i|}|o|idnyz|i||||i|||i||i|||ii}|idjo||_ |i |SWn5t j o n!t j o|i nX|iddo|int|||i|i|idS(Niiscontent-lengthi(Rtset_debuglevelt send_requestt send_hosttsend_user_agentt send_contentt_connt getresponsetstatustverbosetparse_responseRR,tcloset getheadertreadRtreasontmsg(RcRdthandlert request_bodyRRtresponse((s./usr/lib/python2.6/site-packages/ipalib/rpc.pytrequests.    cCs&|i|idti||S(Ns Set-Cookie(RRRkR(RcR((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRsN( RhRiRjRtGSS_C_MUTUAL_FLAGtGSS_C_SEQUENCE_FLAGRRrRRZRRR(((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRUs  ' / $tDelegatedKerbTransportcBs%eZdZeieiBeiBZRS(sb Handles Kerberos Negotiation authentication and TGT delegation to an XML-RPC server. (RhRiRjRtGSS_C_DELEG_FLAGRRR(((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRs t xmlclientcBsYeZdZdZdZdZdZdee edZ dZ dZ RS( sq Forwarding backend plugin for XML-RPC client. Also see the `ipaserver.rpcserver.xmlserver` plugin. cCs0tt|itdtD|_dS(Ncss"x|]}|i|fVqWdS(N(terrno(R9R2((s./usr/lib/python2.6/site-packages/ipalib/rpc.pys s (tsuperRt__init__R@R t_xmlclient__errors(Rc((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRscCs ti|\}}}}}}g}d|ii} ti| titi} xZ| D]R} | itijo9| ii i d} |i dt i | |fqYqYWtt|}|} | |jo!|i| |id| n|id| |S(sP Create a list of urls consisting of the available IPA servers. s_ldap._tcp.%s.RVs https://%s%si(RR}tdomainRtquerytDNS_C_INt DNS_T_SRVtdns_typetrdatatservertrstripRaRt format_netlocR=tsetRtinsert(Rct xmlrpc_uritschemetnetloctpathRMRtfragmenttserverstnametrstrtrsrvt cfg_server((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt get_url_lists !(  c Cs\yt|}Wntj o }dSXyti|t}Wntj o }dSX|S(s Retrieves the session cookie for the given principal from the persistent secure storage. Returns None if not found or unable to retrieve the session cookie for any reason, otherwise returns a Cookie object containing the session cookie. N(R5R,RrRRR(RcR*RR2R((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyt*get_session_cookie_from_persistent_storages c Cs|}ttdd }|i|}|d jo|iid||S|id||y|i|Wntij oC}|id||yt |Wnt j o }nX|Sti j o}|id||St j o}|i d||SX|iid|i ttd|i ti|\}}}} } } d }ti|||| | | f} | S( sE Attempt to load a session cookie for the current principal from the persistent secure storage. If the cookie is successfully loaded adjust the input url's to point to the session path and insert the session cookie into the per thread context for later insertion into the HTTP request. If the cookie is not successfully loaded then the original url is returned and the per thread context is not modified. Context Dependencies: The per thread context is expected to contain: principal The current pricipal the HTTP request was issued for. The per thread context will be updated with: session_cookie A cookie string to be inserted into the Cookie header of the HTPP request. R*sFfailed to find session_cookie in persistent storage for principal '%s'sKfound session_cookie in persistent storage for principal '%s', cookie: '%s's,deleting session data for principal '%s': %ss,not sending session cookie, URL mismatch: %ss-not sending session cookie, unknown error: %ss(setting session_cookie into context '%s'Rs/ipa/session/xmlN(RRRrRtlogRthttp_return_okRtExpiredR7R,t URLMismatchRt http_cookietsetattrRt urlunparse( Rcturlt original_urlR*RR2RRRRMRRt session_url((s./usr/lib/python2.6/site-packages/ipalib/rpc.pytapply_session_cookie2s<    !!cCs yC|ii}t}ttd||p|i|}nWntj onX|i|}d}xc|D][} t dt dd} || d<| i do)|ot | dt|ii"dd} | dj o|i d| qrnt#t|i!t$| |i%| dj o(tt|i!d}| |ii"_&n|i'|||Std |d|i(nct)i*j o$}td |dt|n1t+t,fj o}t-dt|nXdS(s Forward call to command named ``name`` over XML-RPC. This method will encode and forward an XML-RPC request, and will then decode and return the corresponding XML-RPC response. :param command: The name of the command being forwarded. :param args: Positional arguments to pass to remote command. :param kw: Keyword arguments to pass to remote command. s#%s.forward(): %r not in api.CommandRsForwarding %r to server %rs"Caught fault %d from server %s: %sRRRRRRiR*t KRB5CCNAMERlsUsing dbdir %sN(.tCommandR-RRRRrRRoR8RFRRQRRPRORRRRR.RRRR7R,RtostenvirontgetR}RRRtidRpRRt disconnectRltforwardterrmsgtsocketRt OverflowErrort TypeErrorR(RcRtargsRRRRMRR2RRR*RRlt current_conn((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRsb        6   N( RhRiRjRRRRRrtFalseRLRRR(((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyRs    @  M (URjttypesRtdecimalRt threadingR{RRR[tdatetimet xmlrpclibRRRRRRRR R Rtipalib.backendR t ipalib.errorsR R RRRRtipalibRtipalib.requestRRt ipalib.utilRtipapython.ipa_log_managerRRxRRtipapython.cookieRt ipalib.textRRthttplibRtipapython.nsslibRRt nss.errorRturllib2Rtipalib.krb_utilsR R!R"R#R$R%t ipapython.dnR&R'RR)R+R3R5R7R8RFRrRRNRQRSRTRkRRR(((s./usr/lib/python2.6/site-packages/ipalib/rpc.pyts\      @ .   .      ( !  1