U q`p @sLdZddlZddlZddlZdZdZdZzDddlZeedrTej dkrTdZej fZndZej j ej jjfZWn^eefk rz(ddlZddlZddlZd ZejfZWnek rd ZdZYnXYnXdd lmZdd lmZdd lmZdddZGdddeZGdddeZedkr(eZ GdddeZ!GdddeZ"dS)z This module provides GSS-API / SSPI authentication as defined in :rfc:`4462`. .. note:: Credential delegation is not supported in server mode. .. seealso:: :doc:`/api/kex_gss` .. versionadded:: 1.15 NT __title__z python-gssapiMITPYTHON-GSSAPI-NEWSSPIF)MSG_USERAUTH_REQUEST) SSHException)__version_info__cCsLtdkrt||Stdkr$t||Stdkr@tjdkr@t||StddS)a Provide SSH2 GSS-API / SSPI authentication. :param str auth_method: The name of the SSH authentication mechanism (gssapi-with-mic or gss-keyex) :param bool gss_deleg_creds: Delegate client credentials or not. We delegate credentials by default. :return: Either an `._SSH_GSSAPI_OLD` or `._SSH_GSSAPI_NEW` (Unix) object or an `_SSH_SSPI` (Windows) object :rtype: object :raises: ``ImportError`` -- If no GSS-API / SSPI module could be imported. :see: `RFC 4462 `_ :note: Check for the available API and return either an `._SSH_GSSAPI_OLD` (MIT GSSAPI using python-gssapi package) object, an `._SSH_GSSAPI_NEW` (MIT GSSAPI using gssapi package) object or an `._SSH_SSPI` (MS SSPI) object. If there is no supported API available, ``None`` will be returned. rrrntz)Unable to import a GSS-API / SSPI module!N)_API_SSH_GSSAPI_OLD_SSH_GSSAPI_NEWosname _SSH_SSPI ImportError) auth_methodgss_deleg_credsrr7/tmp/pip-target-nv4zd3e_/lib/python/paramiko/ssh_gss.pyGSSAuthNs   rc@sJeZdZdZddZddZddZdd d Zd d Zd dZ ddZ dS) _SSH_GSSAuthzs Contains the shared variables and methods of `._SSH_GSSAPI_OLD`, `._SSH_GSSAPI_NEW` and `._SSH_SSPI`. cCsL||_||_d|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ dS) :param str auth_method: The name of the SSH authentication mechanism (gssapi-with-mic or gss-keyex) :param bool gss_deleg_creds: Delegate client credentials or not Nzssh-connectionz1.2.840.113554.1.2.2F) _auth_method_gss_deleg_creds _gss_host _username _session_id_service _krb5_mech _gss_ctxt_gss_ctxt_status _gss_srv_ctxt_gss_srv_ctxt_statusZcc_fileselfrrrrr__init__tsz_SSH_GSSAuth.__init__cCs|dr||_dS)z This is just a setter to use a non default service. I added this method, because RFC 4462 doesn't specify "ssh-connection" as the only service value. :param str service: The desired SSH service zssh-N)findr)r$servicerrr set_services z_SSH_GSSAuth.set_servicecCs ||_dS)z Setter for C{username}. If GSS-API Key Exchange is performed, the username is not set by C{ssh_init_sec_context}. :param str username: The name of the user who attempts to login N)r)r$usernamerrr set_usernamesz_SSH_GSSAuth.set_usernameclientcCs\ddlm}ddlm}|d}|||j}|t|}|dkrP||S|||S)a This method returns a single OID, because we only support the Kerberos V5 mechanism. :param str mode: Client for client mode and server for server mode :return: A byte sequence containing the number of supported OIDs, the length of the OID and the actual OID encoded with DER :note: In server mode we just return the OID length and the DER encoded OID. r)ObjectIdentifier)encoderserver)Zpyasn1.type.univr,pyasn1.codec.derr- _make_uint32encoderlen)r$moder,r-ZOIDsZkrb5_OIDZOID_lenrrr ssh_gss_oidss   z_SSH_GSSAuth.ssh_gss_oidscCs0ddlm}||\}}||jkr,dSdS)z Check if the given OID is the Kerberos V5 OID (server mode). :param str desired_mech: The desired GSS-API mechanism of the client :return: ``True`` if the given OID is supported, otherwise C{False} rdecoderFT)r0r7decode__str__r)r$ desired_mechr7mech__rrrssh_check_mechs  z_SSH_GSSAuth.ssh_check_mechcCs td|S)z Create a 32 bit unsigned integer (The byte sequence of an integer). :param int integer: The integer value to convert :return: The byte sequence of an 32 bit integer z!I)structpack)r$integerrrrr1sz_SSH_GSSAuth._make_uint32cCs|t|}||7}|tdt7}||t|7}||7}||t|7}||7}||t|7}||7}|S)a Create the SSH2 MIC filed for gssapi-with-mic. :param str session_id: The SSH session ID :param str username: The name of the user who attempts to login :param str service: The requested SSH service :param str auth_method: The requested SSH authentication mechanism :return: The MIC as defined in RFC 4462. The contents of the MIC field are: string session_identifier, byte SSH_MSG_USERAUTH_REQUEST, string user-name, string service (ssh-connection), string authentication-method (gssapi-with-mic or gssapi-keyex) B)r1r3r>r?rr2)r$ session_idr)r'rZmicrrr_ssh_build_mics   z_SSH_GSSAuth._ssh_build_micN)r+) __name__ __module__ __qualname____doc__r%r(r*r5r=r1rCrrrrrns   rc@sTeZdZdZddZdddZddd Zdd d Zdd d Ze ddZ ddZ dS)r z Implementation of the GSS-API MIT Kerberos Authentication for SSH2, using the older (unmaintained) python-gssapi package. :see: `.GSSAuth` cCsBt||||jr,tjtjtjtjf|_ntjtjtjf|_dSrN) rr%rgssapiZC_PROT_READY_FLAGZ C_INTEG_FLAGZ C_MUTUAL_FLAGZ C_DELEG_FLAG _gss_flagsr#rrrr%sz_SSH_GSSAPI_OLD.__init__Nc Cs ddlm}||_||_td|jtj}t}|j|_ |dkrTtj |j }n4| |\} } | |j krztdntj |j }d} z:|dkrtj|||j d|_|j| } n |j|} Wn6tjk rdtd|j} t| YnX|jj|_| S) a Initialize a GSS-API context. :param str username: The name of the user who attempts to login :param str target: The hostname of the target to connect to :param str desired_mech: The negotiated GSS-API mechanism ("pseudo negotiated" mechanism, because we support just the krb5 mechanism :-)) :param str recv_token: The GSS-API token received from the Server :raises: `.SSHException` -- Is raised if the desired mechanism of the client is not supported :return: A ``String`` if the GSS-API has returned a token or ``None`` if no token was returned rr6host@NUnsupported mechanism OID.)Z peer_nameZ mech_typeZ req_flagsz {} Target: {}r.)r0r7rrrINameZC_NT_HOSTBASED_SERVICEContextrJflagsZOIDZmech_from_stringrr8r9rZ InitContextrstep GSSExceptionformatsysexc_info establishedr ) r$targetr:r) recv_tokenr7 targ_namectx krb5_mechr;r<tokenmessagerrrssh_init_sec_context s<   z$_SSH_GSSAPI_OLD.ssh_init_sec_contextFcCsB||_|s0||j|j|j|j}|j|}n|j|j}|S)a Create the MIC token for a SSH2 message. :param str session_id: The SSH session ID :param bool gss_kex: Generate the MIC for GSS-API Key Exchange or not :return: gssapi-with-mic: Returns the MIC token from GSS-API for the message we created with ``_ssh_build_mic``. gssapi-keyex: Returns the MIC token from GSS-API with the SSH session ID as message. )rrCrrrrZget_micr!r$rBZgss_kex mic_field mic_tokenrrr ssh_get_micAs z_SSH_GSSAPI_OLD.ssh_get_miccCs:||_||_|jdkr t|_|j|}|jj|_|S) Accept a GSS-API context (server mode). :param str hostname: The servers hostname :param str username: The name of the user who attempts to login :param str recv_token: The GSS-API Token received from the server, if it's not the initial call. :return: A ``String`` if the GSS-API has returned a token or ``None`` if no token was returned N)rrr!rIZ AcceptContextrPrUr"r$hostnamerWr)r[rrrssh_accept_sec_context\s     z&_SSH_GSSAPI_OLD.ssh_accept_sec_contextcCsR||_||_|jdk r>||j|j|j|j}|j||n|j|j|dS)at Verify the MIC token for a SSH2 message. :param str mic_token: The MIC token received from the client :param str session_id: The SSH session ID :param str username: The name of the user who attempts to login :return: None if the MIC check was successful :raises: ``gssapi.GSSException`` -- if the MIC check failed N)rrrCrrr!Z verify_micrr$r`rBr)r_rrr ssh_check_micps  z_SSH_GSSAPI_OLD.ssh_check_miccCs|jjdk rdSdS) Checks if credentials are delegated (server mode). :return: ``True`` if credentials are delegated, otherwise ``False`` NTF)r!Zdelegated_credr$rrrcredentials_delegateds z%_SSH_GSSAPI_OLD.credentials_delegatedcCstdS)a~ Save the Client token in a file. This is used by the SSH server to store the client credentials if credentials are delegated (server mode). :param str client_token: The GSS-API token received form the client :raises: ``NotImplementedError`` -- Credential delegation is currently not supported in server mode NNotImplementedErrorr$Z client_tokenrrrsave_client_credss z!_SSH_GSSAPI_OLD.save_client_creds)NNN)F)N)N rDrErFrGr%r]rarergpropertyrjrnrrrrr s 4    r )c@sTeZdZdZddZdddZddd Zdd d Zdd d Ze ddZ ddZ dS)r z Implementation of the GSS-API MIT Kerberos Authentication for SSH2, using the newer, currently maintained gssapi package. :see: `.GSSAuth` cCsPt||||jr4tjjtjjtjjtjjf|_ ntjjtjjtjjf|_ dSrH) rr%rrIZRequirementFlagZprotection_readyZ integrityZmutual_authenticationZdelegate_to_peerrJr#rrrr%sz_SSH_GSSAPI_NEW.__init__Nc Csddlm}||_||_tjd|jtjjd}|dk r\||\}}| |j kr\t dtj j } d} |dkrtj||j| dd|_|j| } n |j|} |jj|_| S) ae Initialize a GSS-API context. :param str username: The name of the user who attempts to login :param str target: The hostname of the target to connect to :param str desired_mech: The negotiated GSS-API mechanism ("pseudo negotiated" mechanism, because we support just the krb5 mechanism :-)) :param str recv_token: The GSS-API token received from the Server :raises: `.SSHException` -- Is raised if the desired mechanism of the client is not supported :raises: ``gssapi.exceptions.GSSError`` if there is an error signaled by the GSS-API implementation :return: A ``String`` if the GSS-API has returned a token or ``None`` if no token was returned rr6rK)Z name_typeNrLZinitiate)rrOr;usage)r0r7rrrIrMZNameTypeZhostbased_servicer8r9rrZMechTypeZkerberosSecurityContextrJrrPcompleter ) r$rVr:r)rWr7rXr;r<rZr[rrrr]s0   z$_SSH_GSSAPI_NEW.ssh_init_sec_contextFcCsB||_|s0||j|j|j|j}|j|}n|j|j}|S)a Create the MIC token for a SSH2 message. :param str session_id: The SSH session ID :param bool gss_kex: Generate the MIC for GSS-API Key Exchange or not :return: gssapi-with-mic: Returns the MIC token from GSS-API for the message we created with ``_ssh_build_mic``. gssapi-keyex: Returns the MIC token from GSS-API with the SSH session ID as message. :rtype: str )rrCrrrrZ get_signaturer!r^rrrrasz_SSH_GSSAPI_NEW.ssh_get_miccCs>||_||_|jdkr$tjdd|_|j|}|jj|_|S)rbNaccept)rs)rrr!rIrtrPrur"rcrrrres    z&_SSH_GSSAPI_NEW.ssh_accept_sec_contextcCsR||_||_|jdk r>||j|j|j|j}|j||n|j|j|dS)a{ Verify the MIC token for a SSH2 message. :param str mic_token: The MIC token received from the client :param str session_id: The SSH session ID :param str username: The name of the user who attempts to login :return: None if the MIC check was successful :raises: ``gssapi.exceptions.GSSError`` -- if the MIC check failed N)rrrCrrr!Zverify_signaturerrfrrrrg$s  z_SSH_GSSAPI_NEW.ssh_check_miccCs|jjdk rdSdS)z Checks if credentials are delegated (server mode). :return: ``True`` if credentials are delegated, otherwise ``False`` :rtype: bool NTF)r!Zdelegated_credsrirrrrj>s z%_SSH_GSSAPI_NEW.credentials_delegatedcCstdS)aw Save the Client token in a file. This is used by the SSH server to store the client credentials if credentials are delegated (server mode). :param str client_token: The GSS-API token received form the client :raises: ``NotImplementedError`` -- Credential delegation is currently not supported in server mode NrkrmrrrrnJs z!_SSH_GSSAPI_NEW.save_client_creds)NNN)F)N)Nrorrrrr s .    r c@sReZdZdZddZdddZddd Zd d Zdd d Ze ddZ ddZ dS)rzf Implementation of the Microsoft SSPI Kerberos Authentication for SSH2. :see: `.GSSAuth` cCs<t||||jr*tjtjBtjB|_ntjtjB|_dSrH)rr%rsspiconZISC_REQ_INTEGRITYZISC_REQ_MUTUAL_AUTHISC_REQ_DELEGATErJr#rrrr%^s z_SSH_SSPI.__init__Nc Csddlm}||_||_d}d|j}|dk rR||\}} ||jkrRtdz:|dkrptj d|j |d|_ |j |\}} | dj } Wn<tjk r} z| jd|j7_W5d} ~ XYnX|dkrd |_d} | S) a Initialize a SSPI context. :param str username: The name of the user who attempts to login :param str target: The FQDN of the target to connect to :param str desired_mech: The negotiated SSPI mechanism ("pseudo negotiated" mechanism, because we support just the krb5 mechanism :-)) :param recv_token: The SSPI token received from the Server :raises: `.SSHException` -- Is raised if the desired mechanism of the client is not supported :return: A ``String`` if the SSPI has returned a token or ``None`` if no token was returned rr6host/NrLKerberos)ZscflagsZ targetspnz , Target: {}T)r0r7rrr8r9rrsspiZ ClientAuthrJr authorizeBuffer pywintypeserrorstrerrorrRr ) r$rVr:r)rWr7rrXr;r<r[errrr]qs2  z_SSH_SSPI.ssh_init_sec_contextFcCsB||_|s0||j|j|j|j}|j|}n|j|j}|S)a Create the MIC token for a SSH2 message. :param str session_id: The SSH session ID :param bool gss_kex: Generate the MIC for Key Exchange with SSPI or not :return: gssapi-with-mic: Returns the MIC token from SSPI for the message we created with ``_ssh_build_mic``. gssapi-keyex: Returns the MIC token from SSPI with the SSH session ID as message. )rrCrrrrsignr!r^rrrras z_SSH_SSPI.ssh_get_miccCsV||_||_d|j}tjd|d|_|j|\}}|dj}|dkrRd|_d}|S)a Accept a SSPI context (server mode). :param str hostname: The servers FQDN :param str username: The name of the user who attempts to login :param str recv_token: The SSPI Token received from the server, if it's not the initial call. :return: A ``String`` if the SSPI has returned a token or ``None`` if no token was returned ryrz)ZspnrTN)rrr{Z ServerAuthr!r|r}r")r$rdr)rWrXrr[rrrres   z _SSH_SSPI.ssh_accept_sec_contextcCsP||_||_|dk r<||j|j|j|j}|j||n|j|j|dS)ak Verify the MIC token for a SSH2 message. :param str mic_token: The MIC token received from the client :param str session_id: The SSH session ID :param str username: The name of the user who attempts to login :return: None if the MIC check was successful :raises: ``sspi.error`` -- if the MIC check failed N)rrrCrrr!verifyrrfrrrrgs z_SSH_SSPI.ssh_check_miccCs|jtj@o|jp|jS)rh)rJrwrxr"rirrrrjs  z_SSH_SSPI.credentials_delegatedcCstdS)a{ Save the Client token in a file. This is used by the SSH server to store the client credentails if credentials are delegated (server mode). :param str client_token: The SSPI token received form the client :raises: ``NotImplementedError`` -- Credential delegation is currently not supported in server mode Nrkrmrrrrns z_SSH_SSPI.save_client_creds)NNN)F)NrorrrrrWs 4   r)T)#rGr>rrSZGSS_AUTH_AVAILABLEZGSS_EXCEPTIONSr rIhasattrrrQ exceptionsZ GeneralErrorrawmiscZGSSErrorrOSErrorr~rwr{rZparamiko.commonrZparamiko.ssh_exceptionrZparamiko._versionr robjectrr Z _SSH_GSSAPIr rrrrrsL       5 0