def clean_context(self): """ taken from urllib2_kerberos, see http://limedav.com/hg/urllib2_kerberos """ if self.context is not None: kerberos.authGSSClientClean(self.context) self.context = None
def __request_authenticate(self, method, url, body, extra_hdrs): self.__probe_mechanisms() try: result, gssctx = kerberos.authGSSClientInit(self.__spn, principal=self.__upn) except kerberos.GSSError as ex: raise Krb5Error('%s (%s)' % (ex[0][0], ex[1][0])) response = None blob = '' while True: try: result, blob = self.__challenge(gssctx, blob) except Krb5Error as ex: kerberos.authGSSClientClean(gssctx) raise ex if result: self.__upn = kerberos.authGSSClientUserName(gssctx) break self.close() extra_hdrs['Authorization'] = 'Negotiate %s' % (blob, ) response = davlib.DAV._request(self, method, url, body, extra_hdrs) self.__store_cookies(response) authstr = response.getheader('www-authenticate') (mech, blob) = authstr.split(' ') persistauth = response.getheader('persistent-auth') self.__persistauth = persistauth == 'true' kerberos.authGSSClientClean(gssctx) return response
def process(self, challenge=b''): b64_challenge = b64encode(challenge) try: if self.step == 0: result = kerberos.authGSSClientStep( self.gss, b64_challenge) if result != kerberos.AUTH_GSS_CONTINUE: self.step = 1 elif not challenge: kerberos.authGSSClientClean(self.gss) return b'' elif self.step == 1: username = self.credentials['username'] kerberos.authGSSClientUnwrap(self.gss, b64_challenge) resp = kerberos.authGSSClientResponse(self.gss) kerberos.authGSSClientWrap(self.gss, resp, username) resp = kerberos.authGSSClientResponse(self.gss) except kerberos.GSSError as e: raise SASLCancelled('Kerberos error: %s' % e) if not resp: return b'' else: return b64decode(resp)
def get_current_principal(): try: import kerberos rc, vc = kerberos.authGSSClientInit("notempty") rc = kerberos.authGSSClientInquireCred(vc) username = kerberos.authGSSClientUserName(vc) kerberos.authGSSClientClean(vc) return unicode(username) except ImportError: raise RuntimeError('python-kerberos is not available.') except kerberos.GSSError, e: #TODO: do a kinit? raise errors.CCacheError()
def check_auth_header(self, auth_header): if not self.ctx: raise RuntimeError("Invalid context: " + self.ctx) if not auth_header: raise RuntimeError("www-authenticate header is not valid: " + auth_header) auth_val = auth_header.split(" ", 1) if len(auth_val) != 2 or auth_val[0].lower() != "negotiate": raise RuntimeError("www-authenticate header is not valid: " + auth_header) kerberos.authGSSClientStep(self.ctx, auth_val[1]) kerberos.authGSSClientClean(self.ctx) self.ctx = None
def _set_kerberos_header(transport, kerberos_service_name, host): import kerberos __, krb_context = kerberos.authGSSClientInit( service="{kerberos_service_name}@{host}".format( kerberos_service_name=kerberos_service_name, host=host)) kerberos.authGSSClientClean(krb_context, "") kerberos.authGSSClientStep(krb_context, "") auth_header = kerberos.authGSSClientResponse(krb_context) transport.setCustomHeaders({ "Authorization": "Negotiate {auth_header}".format(auth_header=auth_header) })
def noImpersonationCalls(args): """ A non impersonated call using the kerberos package. """ import kerberos _ignore, ctx = kerberos.authGSSClientInit(args.servicename) h = getConn(args.host, args.port) callserver(h, args.path, ctx, kerberos.authGSSClientStep, kerberos.authGSSClientResponse) callserver(h, args.path, ctx, kerberos.authGSSClientStep, kerberos.authGSSClientResponse) print "username", kerberos.authGSSClientUserName(ctx) kerberos.authGSSClientClean(ctx) # clean up
def verify_response(self, auth_header): for field in auth_header.split(","): kind, __, details = field.strip().partition(" ") if kind.lower() == "negotiate": auth_details = details.strip() break else: raise ValueError("Negotiate not found in %s" % auth_header) krb_context = self._krb_context if krb_context is None: raise RuntimeError("Ticket already used for verification") self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) kerberos.authGSSClientClean(krb_context)
def _kerberos_verify_response(self, vc, host, handler, errcode, errmsg, headers): """Kerberos auth - verify client identity""" # verify that headers contain WWW-Authenticate header auth_header = headers.get("WWW-Authenticate", None) if auth_header is None: errcode = 401 errmsg = "KERBEROS: No WWW-Authenticate header in second HTTP response" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # verify that WWW-Authenticate contains Negotiate splits = auth_header.split(" ", 1) if (len(splits) != 2) or (splits[0].lower() != "negotiate"): errcode = 401 errmsg = "KERBEROS: Incorrect WWW-Authenticate header in second HTTP response: %s" % auth_header raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # do another client step to verify response from server errmsg = "KERBEROS: Could not verify server WWW-Authenticate header in second HTTP response" try: rc = kerberos.authGSSClientStep(vc, splits[1]) if rc == -1: errcode = 401 raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) except kerberos.GSSError as ex: errcode = 401 errmsg += ": %s/%s" % (ex[0][0], ex[1][0]) raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # cleanup rc = kerberos.authGSSClientClean(vc) if rc != 1: errcode = 401 errmsg = "KERBEROS: Could not clean-up GSSAPI: %s/%s" % (ex[0][0], ex[1][0]) raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
def verify_response(self, auth_header): """Handle comma-separated lists of authentication fields.""" for field in auth_header.split(","): kind, __, details = field.strip().partition(" ") if kind.lower() == "negotiate": auth_details = details.strip() break else: raise ValueError("Negotiate not found in %s" % auth_header) # Finish the Kerberos handshake krb_context = self._krb_context if krb_context is None: raise RuntimeError("Ticket already used for verification") self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) kerberos.authGSSClientClean(krb_context)
def verify_response(self, auth_header): # Handle comma-separated lists of authentication fields for field in auth_header.split(","): kind, ignored_space, details = field.strip().partition(" ") if kind.lower() == "negotiate": auth_details = details.strip() break else: raise ValueError("Negotiate not found in {0}".format(auth_header)) # Finish the Kerberos handshake krb_context = self._krb_context if krb_context is None: raise RuntimeError("Ticket already used for verification") self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) # print('User {0} authenticated successfully using Kerberos authentication'.format(kerberos.authGSSClientUserName(krb_context))) kerberos.authGSSClientClean(krb_context)
def clean_client_context(self): # Destroy the context for client-side authentication try: result = kerberos.authGSSClientClean(self.krb_context) logger.debug("authGSSClientClean result:{0}".format(result)) except kerberos.GSSError, e: logger.warn('authGSSClientClean exception: %s' % str(e)) result = -1
def verify_response(self, auth_header): # Handle comma-separated lists of authentication fields for field in auth_header.split(','): kind, ignored_space, details = field.strip().partition(' ') if kind.lower() == 'negotiate': auth_details = details.strip() break else: raise ValueError('Negotiate not found in {0}'.format(auth_header)) # Finish the Kerberos handshake krb_context = self._krb_context if krb_context is None: raise RuntimeError('Ticket already used for verification') self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) print('User {0} authenticated successfully using Kerberos authentication'.format(kerberos.authGSSClientUserName(krb_context))) kerberos.authGSSClientClean(krb_context)
def __del__(self): if self._context is not None: if not kerberos: return result_code = kerberos.authGSSClientClean(self._context) if result_code != kerberos.AUTH_GSS_COMPLETE: raise Exception('kerberos authGSSClientClean failed')
def verify_response(self, auth_header): # Handle comma-separated lists of authentication fields for field in auth_header.split(","): kind, __, details = field.strip().partition(" ") print(kind) if kind.lower() == "negotiate": auth_details = details.strip() break else: raise ValueError("Negotiate not found in %s" % auth_header) # Finish the Kerberos handshake krb_context = self._krb_context if krb_context is None: raise RuntimeError("Ticket already used for verification") self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) kerberos.authGSSClientClean(krb_context)
def _PassthroughLoginGSSAPI(self, host, sessionMgr, passthroughAuthPackage): """ Passthrough Authentication """ userSession = None try: import kerberos except ImportError as err: LogException(err) return userSession context = None service = "host@%s" % host try: result, context = kerberos.authGSSClientInit(service, 0) challenge = "" while True: # Call GSS step result = kerberos.authGSSClientStep(context, challenge) if result < 0: logging.error("authGSSClientStep failed for %s" % service) break secToken = kerberos.authGSSClientResponse(context) try: userSession = sessionMgr.LoginBySSPI(secToken) # No exception => logged in userName = kerberos.authGSSClientUserName(context) logging.info("Passthru authentication: Logged in %s as %s" % \ service, userName) del secToken break except vim.fault.SSPIChallenge as err: # Continue gssapi challenges challenge = err.base64Token del challenge except Exception as err: LogException(err) logging.error("Login failed for %s" % service) if context: try: kerberos.authGSSClientClean(context) except Exception as err: LogException(err) return userSession
def test_http_endpoint(): service = "HTTP@%s" % hostname url = "http://%s:%s/" % (hostname, port) session = requests.Session() # Send the initial request un-authenticated request = requests.Request('GET', url) prepared_request = session.prepare_request(request) response = session.send(prepared_request) # Expect a 401 response assert response.status_code == 401, "Initial HTTP request did not result in a 401 response" # Validate the response supports the Negotiate protocol header = response.headers.get('www-authenticate', None) assert header is not None, "Initial HTTP response did not contain the www-authenticate header" assert header == 'Negotiate', "Initial HTTP response header www-authenticate does not support Negotiate" # Generate the first Kerberos token mech_oid = kerberos.GSS_MECH_OID_KRB5 rc, vc = kerberos.authGSSClientInit(service=service, mech_oid=mech_oid) kerberos.authGSSClientStep(vc, "") kerberos_token = kerberos.authGSSClientResponse(vc) # Attach the Kerberos token and resend back to the host request = requests.Request('GET', url) prepared_request = session.prepare_request(request) prepared_request.headers['Authorization'] = "Negotiate %s" % kerberos_token response = session.send(prepared_request) # Expect a 200 response assert response.status_code == 200, "Second HTTP request did not result in a 200 response" # Validate the headers exist and contain a www-authenticate message header = response.headers.get('www-authenticate', None) assert header is not None, "Second HTTP response did not contain the www-authenticate header" assert header.startswith("Negotiate ") # Verify the return Kerberos token server_kerberos_token = header.split(' ')[-1] kerberos.authGSSClientStep(vc, server_kerberos_token) # Cleanup any objects still stored in memory kerberos.authGSSClientClean(vc)
def __authn_gssapi(self, imapobj): if not have_gss: return False self.connectionlock.acquire() try: imapobj.authenticate('GSSAPI', self.__gssauth) return True except imapobj.error as e: self.gssapi = False raise else: self.gssapi = True kerberos.authGSSClientClean(self.gss_vc) self.gss_vc = None self.gss_step = self.GSS_STATE_STEP finally: self.connectionlock.release()
def create_http_transport(host, port, http_path, username, password, kerberos_service_name, auth): if port is None: port = 10001 if auth is None: auth = 'NONE' if http_path is None: http_path = '/' socket = TCookieHttpClient('http://{}:{}{}'.format( host, port, http_path)) if auth == 'KERBEROS': import kerberos __, krb_context = kerberos.authGSSClientInit( service='{}@{}'.format(kerberos_service_name, host)) kerberos.authGSSClientClean(krb_context, '') kerberos.authGSSClientStep(krb_context, '') auth_header = kerberos.authGSSClientResponse(krb_context) socket.setCustomHeaders( {'Authorization': 'Negotiate {}'.format(auth_header)}) elif auth in ('BASIC', 'NOSASL', 'NONE'): if auth == 'BASIC' and password is None: raise ValueError("BASIC authentication requires password.") auth_credentials = '{}:{}'.format(username, password)\ .encode('UTF-8') auth_credentials_base64 = base64.standard_b64encode( auth_credentials).decode('UTF-8') # we're using the Authorization header for auth NONE or NOSASL because that's where # Hive gets the username when doAs is enabled socket.setCustomHeaders( {'Authorization': 'Basic {}'.format(auth_credentials_base64)}) else: raise NotImplementedError( "Only NONE, NOSASL, BASIC and KERBEROS authentication are supported " "when using HTTP transport, got {}".format(auth)) return thrift.transport.TTransport.TBufferedTransport(socket)
def http_error_401(self, req, fp, code, msg, headers): logger.debug("INSIDE http_error_401") try: try: krb_req = self._extract_krb_value(headers) except ValueError: # Negotiate header not found or a similar error # we can't handle this, let the next handler have a go return None if not krb_req: # First reply from server (no neg value) self.tries = 0 krb_req = "" else: if self.tries > self.max_tries: raise error.HTTPError( req.get_full_url(), 401, "Negotiate auth failed", headers, None) self.tries += 1 try: krb_resp = self._krb_response(req.get_host(), krb_req) req.add_unredirected_header('Authorization', "Negotiate %s" % krb_resp) resp = self.parent.open(req, timeout=req.timeout) self._authenticate_server(resp.headers) return resp except kerberos.GSSError as err: try: msg = err.args[1][0] except Exception: msg = "Negotiate auth failed" logger.debug(msg) return None # let the next handler (if any) have a go finally: if self.krb_context is not None: kerberos.authGSSClientClean(self.krb_context) self.krb_context = None
def __create_http_transport(host, username, password, kerberos_service_name, port=10001, auth='KERBEROS'): if auth == 'KERBEROS': import kerberos __, krb_context = kerberos.authGSSClientInit( service='{}@{}'.format(kerberos_service_name, host)) kerberos.authGSSClientClean(krb_context, '') kerberos.authGSSClientStep(krb_context, '') auth_header = kerberos.authGSSClientResponse(krb_context) socket = TCookieHttpClient(uri_or_host=host, port=port, path='/') socket.setCustomHeaders( {'Authorization': 'Negotiate {}'.format(auth_header)}) elif auth == 'BASIC': if username is None or password is None: raise ValueError("BASIC authentication require username and password.") socket = TCookieHttpClient(uri_or_host=host, port=port, path='/') auth_credentials = '{}:{}'.format(username, password)\ .encode('UTF-8') auth_credentials_base64 = base64.standard_b64encode( auth_credentials).decode('UTF-8') socket.setCustomHeaders( {'Authorization': 'Basic {}'.format(auth_credentials_base64)}) elif auth == 'NONE': socket = thrift.transport.THttpClient.THttpClient(host, port, '/') else: raise NotImplementedError( "Only NONE, BASIC and KERBEROS authentication are supported " "when using HTTP transport, got {}".format(auth)) return thrift.transport.TTransport.TBufferedTransport(socket)
def get_ticket(self, hostname, service_type): status, context = kerberos.authGSSClientInit('%s@%s' % ( service_type, hostname, )) if not status: ERROR('Kerberos: Could not initialize context') return '' status = kerberos.authGSSClientStep(context, '') if status: ERROR('Kerberos: Client step failed') return '' ticket = kerberos.authGSSClientResponse(context) kerberos.authGSSClientClean(context) return ticket
def http_error_401(self, req, fp, code, msg, headers): logger.debug("INSIDE http_error_401") try: try: krb_req = self._extract_krb_value(headers) except ValueError: # Negotiate header not found or a similar error # we can't handle this, let the next handler have a go return None if not krb_req: # First reply from server (no neg value) self.tries = 0 krb_req = "" else: if self.tries > self.max_tries: raise error.HTTPError(req.get_full_url(), 401, "Negotiate auth failed", headers, None) self.tries += 1 try: krb_resp = self._krb_response(req.get_host(), krb_req) req.add_unredirected_header('Authorization', "Negotiate %s" % krb_resp) resp = self.parent.open(req, timeout=req.timeout) self._authenticate_server(resp.headers) return resp except kerberos.GSSError as err: try: msg = err.args[1][0] except Exception: msg = "Negotiate auth failed" logger.debug(msg) return None # let the next handler (if any) have a go finally: if self.krb_context is not None: kerberos.authGSSClientClean(self.krb_context) self.krb_context = None
def process(self, challenge=b''): b64_challenge = b64encode(challenge) try: if self.step == 0: result = kerberos.authGSSClientStep(self.gss, b64_challenge) if result != kerberos.AUTH_GSS_CONTINUE: self.step = 1 elif not challenge: kerberos.authGSSClientClean(self.gss) return b'' elif self.step == 1: username = self.credentials['username'] kerberos.authGSSClientUnwrap(self.gss, b64_challenge) resp = kerberos.authGSSClientResponse(self.gss) kerberos.authGSSClientWrap(self.gss, resp, username) resp = kerberos.authGSSClientResponse(self.gss) except kerberos.GSSError as e: raise SASLCancelled('Kerberos error: %s' % e) if not resp: return b'' else: return b64decode(resp)
def testGSSAPI(service): def statusText(r): if r == 1: return "Complete" elif r == 0: return "Continue" else: return "Error" rc, vc = kerberos.authGSSClientInit(service) print("Status for authGSSClientInit = %s" % statusText(rc)) if rc != 1: return rs, vs = kerberos.authGSSServerInit(service) print("Status for authGSSServerInit = %s" % statusText(rs)) if rs != 1: return rc = kerberos.authGSSClientStep(vc, "") print("Status for authGSSClientStep = %s" % statusText(rc)) if rc != 0: return rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc)) print("Status for authGSSServerStep = %s" % statusText(rs)) if rs == -1: return rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs)) print("Status for authGSSClientStep = %s" % statusText(rc)) if rc == -1: return print("Server user name: %s" % kerberos.authGSSServerUserName(vs)) print("Server target name: %s" % kerberos.authGSSServerTargetName(vs)) print("Client user name: %s" % kerberos.authGSSClientUserName(vc)) rc = kerberos.authGSSClientClean(vc) print("Status for authGSSClientClean = %s" % statusText(rc)) rs = kerberos.authGSSServerClean(vs) print("Status for authGSSServerClean = %s" % statusText(rs))
def testGSSAPI(service): def statusText(r): if r == 1: return "Complete" elif r == 0: return "Continue" else: return "Error" rc, vc = kerberos.authGSSClientInit(service); print "Status for authGSSClientInit = %s" % statusText(rc); if rc != 1: return rs, vs = kerberos.authGSSServerInit(service); print "Status for authGSSServerInit = %s" % statusText(rs); if rs != 1: return rc = kerberos.authGSSClientStep(vc, ""); print "Status for authGSSClientStep = %s" % statusText(rc); if rc != 0: return rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc)); print "Status for authGSSServerStep = %s" % statusText(rs); if rs == -1: return rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs)); print "Status for authGSSClientStep = %s" % statusText(rc); if rc == -1: return print "Server user name: %s" % kerberos.authGSSServerUserName(vs); print "Server target name: %s" % kerberos.authGSSServerTargetName(vs); print "Client user name: %s" % kerberos.authGSSClientUserName(vc); rc = kerberos.authGSSClientClean(vc); print "Status for authGSSClientClean = %s" % statusText(rc); rs = kerberos.authGSSServerClean(vs); print "Status for authGSSServerClean = %s" % statusText(rs);
def test_gssapi(): """ Return Code Values 0 = Continue 1 = Complete Other = Error """ service = "HTTP@%s" % hostname rc, vc = kerberos.authGSSClientInit(service) assert rc == 1, "authGSSClientInit = %d, expecting 1" % rc rs, vs = kerberos.authGSSServerInit(service) assert rs == 1, "authGSSServerInit = %d, expecting 1" % rs rc = kerberos.authGSSClientStep(vc, "") assert rc == 0, "authGSSClientStep = %d, expecting 0" % rc rs = kerberos.authGSSServerStep(vs, kerberos.authGSSClientResponse(vc)) assert rs != -1, "authGSSServerStep = %d, not expecting it to be -1" % rs rc = kerberos.authGSSClientStep(vc, kerberos.authGSSServerResponse(vs)) assert rc != -1, "authGSSClientStep = %d, not expecting it to be -1" % rc expected_username = "******" % (username, realm.upper()) server_user_name = kerberos.authGSSServerUserName(vs) assert server_user_name == expected_username, "Invalid server username returned" client_user_name = kerberos.authGSSClientUserName(vc) assert client_user_name == expected_username, "Invalid client username returned" server_target_name = kerberos.authGSSServerTargetName(vs) assert server_target_name is None, "Server target name is not None" rc = kerberos.authGSSClientClean(vc) assert rc == 1, "authGSSClientClean = %d, expecting it to be 0" % rc rs = kerberos.authGSSServerClean(vs) assert rs == 1, "authGSSServerClean = %d, expecting it to be 0" % rs
def __del__(self): result_code = kerberos.authGSSClientClean(self._context) if result_code != kerberos.AUTH_GSS_COMPLETE: raise Exception('kerberos authGSSClientClean failed')
def _clean_context(self): if self.context is not None: kerberos.authGSSClientClean(self.context) self.context = None
def _authenticate_gssapi(credentials, sock_info, cmd_func): """Authenticate using GSSAPI. """ try: dummy, username, gsn = credentials # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. result, ctx = kerberos.authGSSClientInit( gsn + '@' + sock_info.host, gssflags=kerberos.GSS_C_MUTUAL_FLAG) if result != kerberos.AUTH_GSS_COMPLETE: raise OperationFailure('Kerberos context failed to initialize.') try: # pykerberos uses a weird mix of exceptions and return values # to indicate errors. # 0 == continue, 1 == complete, -1 == error # Only authGSSClientStep can return 0. if kerberos.authGSSClientStep(ctx, '') != 0: raise OperationFailure('Unknown kerberos ' 'failure in step function.') # Start a SASL conversation with mongod/s # Note: pykerberos deals with base64 encoded byte strings. # Since mongo accepts base64 strings as the payload we don't # have to use bson.binary.Binary. payload = kerberos.authGSSClientResponse(ctx) cmd = SON([('saslStart', 1), ('mechanism', 'GSSAPI'), ('payload', payload), ('autoAuthorize', 1)]) response, _ = cmd_func(sock_info, '$external', cmd) # Limit how many times we loop to catch protocol / library issues for _ in xrange(10): result = kerberos.authGSSClientStep(ctx, str(response['payload'])) if result == -1: raise OperationFailure('Unknown kerberos ' 'failure in step function.') payload = kerberos.authGSSClientResponse(ctx) or '' cmd = SON([('saslContinue', 1), ('conversationId', response['conversationId']), ('payload', payload)]) response, _ = cmd_func(sock_info, '$external', cmd) if result == kerberos.AUTH_GSS_COMPLETE: break else: raise OperationFailure('Kerberos ' 'authentication failed to complete.') # Once the security context is established actually authenticate. # See RFC 4752, Section 3.1, last two paragraphs. if kerberos.authGSSClientUnwrap(ctx, str( response['payload'])) != 1: raise OperationFailure('Unknown kerberos ' 'failure during GSS_Unwrap step.') if kerberos.authGSSClientWrap( ctx, kerberos.authGSSClientResponse(ctx), username) != 1: raise OperationFailure('Unknown kerberos ' 'failure during GSS_Wrap step.') payload = kerberos.authGSSClientResponse(ctx) cmd = SON([('saslContinue', 1), ('conversationId', response['conversationId']), ('payload', payload)]) response, _ = cmd_func(sock_info, '$external', cmd) finally: kerberos.authGSSClientClean(ctx) except kerberos.KrbError, exc: raise OperationFailure(str(exc))
def testHTTP(host, port, use_ssl, service): class HTTPSConnection_SSLv3(httplib.HTTPSConnection): "This class allows communication via SSL." def connect(self): "Connect to a host on a given (SSL) port." sock = socket.create_connection((self.host, self.port), self.timeout) self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3) def sendRequest(host, port, ssl, method, uri, headers): response = None if use_ssl: http = HTTPSConnection_SSLv3(host, port) else: http = httplib.HTTPConnection(host, port) try: http.request(method, uri, "", headers) response = http.getresponse() finally: http.close() return response # Initial request without auth header uri = "/principals/" response = sendRequest(host, port, use_ssl, "OPTIONS", uri, {}) if response is None: print("Initial HTTP request to server failed") return if response.status != 401: print("Initial HTTP request did not result in a 401 response") return hdrs = response.msg.getheaders("www-authenticate") if (hdrs is None) or (len(hdrs) == 0): print("No www-authenticate header in initial HTTP response.") for hdr in hdrs: hdr = hdr.strip() splits = hdr.split(" ", 1) if (len(splits) != 1) or (splits[0].lower() != "negotiate"): continue else: break else: print("No www-authenticate header with negotiate in initial HTTP response.") return try: rc, vc = kerberos.authGSSClientInit(service=service) except kerberos.GSSError as e: print("Could not initialize GSSAPI: %s/%s" % (e[0][0], e[1][0])) return try: kerberos.authGSSClientStep(vc, "") except kerberos.GSSError as e: print("Could not do GSSAPI step with continue: %s/%s" % (e[0][0], e[1][0])) return hdrs = {} hdrs["Authorization"] = "negotiate %s" % kerberos.authGSSClientResponse(vc) # Second request with auth header response = sendRequest(host, port, use_ssl, "OPTIONS", uri, hdrs) if response is None: print("Second HTTP request to server failed") return if response.status / 100 != 2: print("Second HTTP request did not result in a 2xx response: %d" % (response.status,)) return hdrs = response.msg.getheaders("www-authenticate") if (hdrs is None) or (len(hdrs) == 0): print("No www-authenticate header in second HTTP response.") return for hdr in hdrs: hdr = hdr.strip() splits = hdr.split(" ", 1) if (len(splits) != 2) or (splits[0].lower() != "negotiate"): continue else: break else: print("No www-authenticate header with negotiate in second HTTP response.") return try: kerberos.authGSSClientStep(vc, splits[1]) except kerberos.GSSError as e: print("Could not verify server www-authenticate header in second HTTP response: %s/%s" % (e[0][0], e[1][0])) return try: rc = kerberos.authGSSClientClean(vc) except kerberos.GSSError as e: print("Could not clean-up GSSAPI: %s/%s" % (e[0][0], e[1][0])) return print("Authenticated successfully") return
print "No www-authenticate header in second HTTP response." return for hdr in hdrs: hdr = hdr.strip() splits = hdr.split(' ', 1) if (len(splits) != 2) or (splits[0].lower() != "negotiate"): continue else: break else: print "No www-authenticate header with negotiate in second HTTP response." return try: kerberos.authGSSClientStep(vc, splits[1]) except kerberos.GSSError, e: print "Could not verify server www-authenticate header in second HTTP response: %s/%s" % (e[0][0], e[1][0]) return try: rc = kerberos.authGSSClientClean(vc); except kerberos.GSSError, e: print "Could not clean-up GSSAPI: %s/%s" % (e[0][0], e[1][0]) return print "Authenticated successfully" return if __name__=='__main__': main()
def clean_context(self): if self._context is not None: krb.authGSSClientClean(self._context)
def acquireconnection(self): """Fetches a connection from the pool, making sure to create a new one if needed, to obey the maximum connection limits, etc. Opens a connection to the server and returns an appropriate object.""" self.semaphore.acquire() self.connectionlock.acquire() curThread = currentThread() imapobj = None if len(self.availableconnections): # One is available. # Try to find one that previously belonged to this thread # as an optimization. Start from the back since that's where # they're popped on. imapobj = None for i in range(len(self.availableconnections) - 1, -1, -1): tryobj = self.availableconnections[i] if self.lastowner[tryobj] == curThread.ident: imapobj = tryobj del(self.availableconnections[i]) break if not imapobj: imapobj = self.availableconnections[0] del(self.availableconnections[0]) self.assignedconnections.append(imapobj) self.lastowner[imapobj] = curThread.ident self.connectionlock.release() return imapobj self.connectionlock.release() # Release until need to modify data """ Must be careful here that if we fail we should bail out gracefully and release locks / threads so that the next attempt can try... """ success = 0 try: while not success: # Generate a new connection. if self.tunnel: self.ui.connecting('tunnel', self.tunnel) imapobj = imaplibutil.IMAP4_Tunnel(self.tunnel, timeout=socket.getdefaulttimeout()) success = 1 elif self.usessl: self.ui.connecting(self.hostname, self.port) fingerprint = self.repos.get_ssl_fingerprint() imapobj = imaplibutil.WrappedIMAP4_SSL(self.hostname, self.port, self.sslclientkey, self.sslclientcert, self.sslcacertfile, self.verifycert, timeout=socket.getdefaulttimeout(), fingerprint=fingerprint ) else: self.ui.connecting(self.hostname, self.port) imapobj = imaplibutil.WrappedIMAP4(self.hostname, self.port, timeout=socket.getdefaulttimeout()) if not self.tunnel: try: # Try GSSAPI and continue if it fails if 'AUTH=GSSAPI' in imapobj.capabilities and have_gss: self.connectionlock.acquire() self.ui.debug('imap', 'Attempting GSSAPI authentication') try: imapobj.authenticate('GSSAPI', self.gssauth) except imapobj.error as val: self.gssapi = False self.ui.debug('imap', 'GSSAPI Authentication failed') else: self.gssapi = True kerberos.authGSSClientClean(self.gss_vc) self.gss_vc = None self.gss_step = self.GSS_STATE_STEP #if we do self.password = None then the next attempt cannot try... #self.password = None self.connectionlock.release() if not self.gssapi: if 'STARTTLS' in imapobj.capabilities and not\ self.usessl: self.ui.debug('imap', 'Using STARTTLS connection') imapobj.starttls() if 'AUTH=CRAM-MD5' in imapobj.capabilities: self.ui.debug('imap', 'Attempting CRAM-MD5 authentication') try: imapobj.authenticate('CRAM-MD5', self.md5handler) except imapobj.error as val: self.plainauth(imapobj) else: # Use plaintext login, unless # LOGINDISABLED (RFC2595) if 'LOGINDISABLED' in imapobj.capabilities: raise OfflineImapError("Plaintext login " "disabled by server. Need to use SSL?", OfflineImapError.ERROR.REPO) self.plainauth(imapobj) # Would bail by here if there was a failure. success = 1 self.goodpassword = self.password except imapobj.error as val: self.passworderror = str(val) raise # update capabilities after login, e.g. gmail serves different ones typ, dat = imapobj.capability() if dat != [None]: imapobj.capabilities = tuple(dat[-1].upper().split()) if self.delim == None: listres = imapobj.list(self.reference, '""')[1] if listres == [None] or listres == None: # Some buggy IMAP servers do not respond well to LIST "" "" # Work around them. listres = imapobj.list(self.reference, '"*"')[1] if listres == [None] or listres == None: # No Folders were returned. This occurs, e.g. if the # 'reference' prefix does not exist on the mail # server. Raise exception. err = "Server '%s' returned no folders in '%s'" % \ (self.repos.getname(), self.reference) self.ui.warn(err) raise Exception(err) self.delim, self.root = \ imaputil.imapsplit(listres[0])[1:] self.delim = imaputil.dequote(self.delim) self.root = imaputil.dequote(self.root) self.connectionlock.acquire() self.assignedconnections.append(imapobj) self.lastowner[imapobj] = curThread.ident self.connectionlock.release() return imapobj except Exception as e: """If we are here then we did not succeed in getting a connection - we should clean up and then re-raise the error...""" self.semaphore.release() if(self.connectionlock.locked()): self.connectionlock.release() severity = OfflineImapError.ERROR.REPO if type(e) == gaierror: #DNS related errors. Abort Repo sync #TODO: special error msg for e.errno == 2 "Name or service not known"? reason = "Could not resolve name '%s' for repository "\ "'%s'. Make sure you have configured the ser"\ "ver name correctly and that you are online."%\ (self.hostname, self.repos) raise OfflineImapError(reason, severity) elif isinstance(e, SSLError) and e.errno == 1: # SSL unknown protocol error # happens e.g. when connecting via SSL to a non-SSL service if self.port != 993: reason = "Could not connect via SSL to host '%s' and non-s"\ "tandard ssl port %d configured. Make sure you connect"\ " to the correct port." % (self.hostname, self.port) else: reason = "Unknown SSL protocol connecting to host '%s' for"\ "repository '%s'. OpenSSL responded:\n%s"\ % (self.hostname, self.repos, e) raise OfflineImapError(reason, severity) elif isinstance(e, socket.error) and e.args[0] == errno.ECONNREFUSED: # "Connection refused", can be a non-existing port, or an unauthorized # webproxy (open WLAN?) reason = "Connection to host '%s:%d' for repository '%s' was "\ "refused. Make sure you have the right host and port "\ "configured and that you are actually able to access the "\ "network." % (self.hostname, self.port, self.reposname) raise OfflineImapError(reason, severity) # Could not acquire connection to the remote; # socket.error(last_error) raised if str(e)[:24] == "can't open socket; error": raise OfflineImapError("Could not connect to remote server '%s' "\ "for repository '%s'. Remote does not answer." % (self.hostname, self.repos), OfflineImapError.ERROR.REPO) else: # re-raise all other errors raise
def dispose(self): kerberos.authGSSClientClean(self.context)
def clean_context(self): if self.context is not None: log.debug("cleaning context") k.authGSSClientClean(self.context) self.context = None
def acquireconnection(self): """Fetches a connection from the pool, making sure to create a new one if needed, to obey the maximum connection limits, etc. Opens a connection to the server and returns an appropriate object.""" self.semaphore.acquire() self.connectionlock.acquire() imapobj = None if len(self.availableconnections): # One is available. # Try to find one that previously belonged to this thread # as an optimization. Start from the back since that's where # they're popped on. imapobj = None for i in range(len(self.availableconnections) - 1, -1, -1): tryobj = self.availableconnections[i] if self.lastowner[tryobj] == get_ident(): imapobj = tryobj del(self.availableconnections[i]) break if not imapobj: imapobj = self.availableconnections[0] del(self.availableconnections[0]) self.assignedconnections.append(imapobj) self.lastowner[imapobj] = get_ident() self.connectionlock.release() return imapobj self.connectionlock.release() # Release until need to modify data """ Must be careful here that if we fail we should bail out gracefully and release locks / threads so that the next attempt can try... """ success = 0 try: while not success: # Generate a new connection. if self.tunnel: self.ui.connecting('tunnel', self.tunnel) imapobj = imaplibutil.IMAP4_Tunnel(self.tunnel, timeout=socket.getdefaulttimeout()) success = 1 elif self.usessl: self.ui.connecting(self.hostname, self.port) fingerprint = self.repos.get_ssl_fingerprint() imapobj = imaplibutil.WrappedIMAP4_SSL(self.hostname, self.port, self.sslclientkey, self.sslclientcert, self.sslcacertfile, self.verifycert, timeout=socket.getdefaulttimeout(), fingerprint=fingerprint ) else: self.ui.connecting(self.hostname, self.port) imapobj = imaplibutil.WrappedIMAP4(self.hostname, self.port, timeout=socket.getdefaulttimeout()) if not self.tunnel: try: # Try GSSAPI and continue if it fails if 'AUTH=GSSAPI' in imapobj.capabilities and have_gss: self.connectionlock.acquire() self.ui.debug('imap', 'Attempting GSSAPI authentication') try: imapobj.authenticate('GSSAPI', self.gssauth) except imapobj.error, val: self.gssapi = False self.ui.debug('imap', 'GSSAPI Authentication failed') else: self.gssapi = True kerberos.authGSSClientClean(self.gss_vc) self.gss_vc = None self.gss_step = self.GSS_STATE_STEP #if we do self.password = None then the next attempt cannot try... #self.password = None self.connectionlock.release() if not self.gssapi: if 'STARTTLS' in imapobj.capabilities and not\ self.usessl: self.ui.debug('imap', 'Using STARTTLS connection') imapobj.starttls() if 'AUTH=CRAM-MD5' in imapobj.capabilities: self.ui.debug('imap', 'Attempting CRAM-MD5 authentication') try: imapobj.authenticate('CRAM-MD5', self.md5handler) except imapobj.error, val: self.plainauth(imapobj) else: self.plainauth(imapobj) # Would bail by here if there was a failure. success = 1 self.goodpassword = self.password except imapobj.error, val: self.passworderror = str(val) raise
def acquireconnection(self): """Fetches a connection from the pool, making sure to create a new one if needed, to obey the maximum connection limits, etc. Opens a connection to the server and returns an appropriate object.""" self.semaphore.acquire() self.connectionlock.acquire() curThread = currentThread() imapobj = None if len(self.availableconnections): # One is available. # Try to find one that previously belonged to this thread # as an optimization. Start from the back since that's where # they're popped on. imapobj = None for i in range(len(self.availableconnections) - 1, -1, -1): tryobj = self.availableconnections[i] if self.lastowner[tryobj] == curThread.ident: imapobj = tryobj del (self.availableconnections[i]) break if not imapobj: imapobj = self.availableconnections[0] del (self.availableconnections[0]) self.assignedconnections.append(imapobj) self.lastowner[imapobj] = curThread.ident self.connectionlock.release() return imapobj self.connectionlock.release() # Release until need to modify data """ Must be careful here that if we fail we should bail out gracefully and release locks / threads so that the next attempt can try... """ success = 0 try: while not success: # Generate a new connection. if self.tunnel: self.ui.connecting('tunnel', self.tunnel) imapobj = imaplibutil.IMAP4_Tunnel( self.tunnel, timeout=socket.getdefaulttimeout()) success = 1 elif self.usessl: self.ui.connecting(self.hostname, self.port) fingerprint = self.repos.get_ssl_fingerprint() imapobj = imaplibutil.WrappedIMAP4_SSL( self.hostname, self.port, self.sslclientkey, self.sslclientcert, self.sslcacertfile, self.verifycert, timeout=socket.getdefaulttimeout(), fingerprint=fingerprint) else: self.ui.connecting(self.hostname, self.port) imapobj = imaplibutil.WrappedIMAP4( self.hostname, self.port, timeout=socket.getdefaulttimeout()) if not self.tunnel: try: # Try GSSAPI and continue if it fails if 'AUTH=GSSAPI' in imapobj.capabilities and have_gss: self.connectionlock.acquire() self.ui.debug('imap', 'Attempting GSSAPI authentication') try: imapobj.authenticate('GSSAPI', self.gssauth) except imapobj.error as val: self.gssapi = False self.ui.debug('imap', 'GSSAPI Authentication failed') else: self.gssapi = True kerberos.authGSSClientClean(self.gss_vc) self.gss_vc = None self.gss_step = self.GSS_STATE_STEP #if we do self.password = None then the next attempt cannot try... #self.password = None self.connectionlock.release() if not self.gssapi: if 'STARTTLS' in imapobj.capabilities and not\ self.usessl: self.ui.debug('imap', 'Using STARTTLS connection') imapobj.starttls() if 'AUTH=CRAM-MD5' in imapobj.capabilities: self.ui.debug( 'imap', 'Attempting CRAM-MD5 authentication') try: imapobj.authenticate( 'CRAM-MD5', self.md5handler) except imapobj.error as val: self.plainauth(imapobj) else: # Use plaintext login, unless # LOGINDISABLED (RFC2595) if 'LOGINDISABLED' in imapobj.capabilities: raise OfflineImapError( "Plaintext login " "disabled by server. Need to use SSL?", OfflineImapError.ERROR.REPO) self.plainauth(imapobj) # Would bail by here if there was a failure. success = 1 self.goodpassword = self.password except imapobj.error as val: self.passworderror = str(val) raise # update capabilities after login, e.g. gmail serves different ones typ, dat = imapobj.capability() if dat != [None]: imapobj.capabilities = tuple(dat[-1].upper().split()) if self.delim == None: listres = imapobj.list(self.reference, '""')[1] if listres == [None] or listres == None: # Some buggy IMAP servers do not respond well to LIST "" "" # Work around them. listres = imapobj.list(self.reference, '"*"')[1] if listres == [None] or listres == None: # No Folders were returned. This occurs, e.g. if the # 'reference' prefix does not exist on the mail # server. Raise exception. err = "Server '%s' returned no folders in '%s'" % \ (self.repos.getname(), self.reference) self.ui.warn(err) raise Exception(err) self.delim, self.root = \ imaputil.imapsplit(listres[0])[1:] self.delim = imaputil.dequote(self.delim) self.root = imaputil.dequote(self.root) self.connectionlock.acquire() self.assignedconnections.append(imapobj) self.lastowner[imapobj] = curThread.ident self.connectionlock.release() return imapobj except Exception as e: """If we are here then we did not succeed in getting a connection - we should clean up and then re-raise the error...""" self.semaphore.release() if (self.connectionlock.locked()): self.connectionlock.release() severity = OfflineImapError.ERROR.REPO if type(e) == gaierror: #DNS related errors. Abort Repo sync #TODO: special error msg for e.errno == 2 "Name or service not known"? reason = "Could not resolve name '%s' for repository "\ "'%s'. Make sure you have configured the ser"\ "ver name correctly and that you are online."%\ (self.hostname, self.repos) raise OfflineImapError(reason, severity) elif isinstance(e, SSLError) and e.errno == 1: # SSL unknown protocol error # happens e.g. when connecting via SSL to a non-SSL service if self.port != 993: reason = "Could not connect via SSL to host '%s' and non-s"\ "tandard ssl port %d configured. Make sure you connect"\ " to the correct port." % (self.hostname, self.port) else: reason = "Unknown SSL protocol connecting to host '%s' for"\ "repository '%s'. OpenSSL responded:\n%s"\ % (self.hostname, self.repos, e) raise OfflineImapError(reason, severity) elif isinstance(e, socket.error) and e.args[0] == errno.ECONNREFUSED: # "Connection refused", can be a non-existing port, or an unauthorized # webproxy (open WLAN?) reason = "Connection to host '%s:%d' for repository '%s' was "\ "refused. Make sure you have the right host and port "\ "configured and that you are actually able to access the "\ "network." % (self.hostname, self.port, self.reposname) raise OfflineImapError(reason, severity) # Could not acquire connection to the remote; # socket.error(last_error) raised if str(e)[:24] == "can't open socket; error": raise OfflineImapError("Could not connect to remote server '%s' "\ "for repository '%s'. Remote does not answer." % (self.hostname, self.repos), OfflineImapError.ERROR.REPO) else: # re-raise all other errors raise
def _authenticate_gssapi(credentials, sock_info, cmd_func): """Authenticate using GSSAPI. """ try: dummy, username, gsn = credentials # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. result, ctx = kerberos.authGSSClientInit( gsn + '@' + sock_info.host, gssflags=kerberos.GSS_C_MUTUAL_FLAG) if result != kerberos.AUTH_GSS_COMPLETE: raise OperationFailure('Kerberos context failed to initialize.') try: # pykerberos uses a weird mix of exceptions and return values # to indicate errors. # 0 == continue, 1 == complete, -1 == error # Only authGSSClientStep can return 0. if kerberos.authGSSClientStep(ctx, '') != 0: raise OperationFailure('Unknown kerberos ' 'failure in step function.') # Start a SASL conversation with mongod/s # Note: pykerberos deals with base64 encoded byte strings. # Since mongo accepts base64 strings as the payload we don't # have to use bson.binary.Binary. payload = kerberos.authGSSClientResponse(ctx) cmd = SON([('saslStart', 1), ('mechanism', 'GSSAPI'), ('payload', payload), ('autoAuthorize', 1)]) response, _ = cmd_func(sock_info, '$external', cmd) # Limit how many times we loop to catch protocol / library issues for _ in xrange(10): result = kerberos.authGSSClientStep(ctx, str(response['payload'])) if result == -1: raise OperationFailure('Unknown kerberos ' 'failure in step function.') payload = kerberos.authGSSClientResponse(ctx) or '' cmd = SON([('saslContinue', 1), ('conversationId', response['conversationId']), ('payload', payload)]) response, _ = cmd_func(sock_info, '$external', cmd) if result == kerberos.AUTH_GSS_COMPLETE: break else: raise OperationFailure('Kerberos ' 'authentication failed to complete.') # Once the security context is established actually authenticate. # See RFC 4752, Section 3.1, last two paragraphs. if kerberos.authGSSClientUnwrap(ctx, str(response['payload'])) != 1: raise OperationFailure('Unknown kerberos ' 'failure during GSS_Unwrap step.') if kerberos.authGSSClientWrap(ctx, kerberos.authGSSClientResponse(ctx), username) != 1: raise OperationFailure('Unknown kerberos ' 'failure during GSS_Wrap step.') payload = kerberos.authGSSClientResponse(ctx) cmd = SON([('saslContinue', 1), ('conversationId', response['conversationId']), ('payload', payload)]) response, _ = cmd_func(sock_info, '$external', cmd) finally: kerberos.authGSSClientClean(ctx) except kerberos.KrbError, exc: raise OperationFailure(str(exc))
def cleanup(self): kerberos.authGSSClientClean(self._context) self._context = None
class CookieTransport(xmlrpclib.Transport): """ Cookie enabled XML-RPC transport. USAGE: >>> import xmlrpclib import kobo.xmlrpc client = xmlrpclib.ServerProxy("http://<server>/xmlrpc", transport=kobo.xmlrpc.CookieTransport()) # for https:// connections use kobo.xmlrpc.SafeCookieTransport() instead. """ _use_datetime = False # fix for python 2.5+ scheme = "http" def __init__(self, *args, **kwargs): cookiejar = kwargs.pop("cookiejar", None) self.timeout = kwargs.pop("timeout", 0) self.proxy_config = self._get_proxy(**kwargs) self.no_proxy = os.environ.get("no_proxy", "").lower().split(',') self.context = kwargs.pop('context', None) if hasattr(xmlrpclib.Transport, "__init__"): xmlrpclib.Transport.__init__(self, *args, **kwargs) self.cookiejar = cookiejar or cookielib.CookieJar() if hasattr(self.cookiejar, "load"): if not os.path.exists(self.cookiejar.filename): if hasattr(self.cookiejar, "save"): self.cookiejar.save(self.cookiejar.filename) self.cookiejar.load(self.cookiejar.filename) def _get_proxy(self, **kwargs): """Return dict with appropriate proxy settings""" proxy = None proxy_user = None proxy_password = None if kwargs.get("proxy", None): # Use proxy from __init__ params proxy = kwargs["proxy"] if kwargs.get("proxy_user", None): proxy_user = kwargs["proxy_user"] if kwargs.get("proxy_password", None): proxy_password = kwargs["proxy_user"] else: # Try to get proxy settings from environmental vars if self.scheme == "http" and os.environ.get("http_proxy", None): proxy = os.environ["http_proxy"] elif self.scheme == "https" and os.environ.get("https_proxy", None): proxy = os.environ["https_proxy"] if proxy: # Parse proxy address # e.g. http://user:[email protected]:8001/foo/bar # Get raw location without path location = urlparse.urlparse(proxy)[1] if not location: # proxy probably doesn't have a protocol in prefix location = urlparse.urlparse("http://%s" % proxy)[1] # Parse out username and password if present if '@' in location: userpas, location = location.split('@', 1) if userpas and location and not proxy_user: # Set proxy user only if proxy_user is not set yet proxy_user = userpas if ':' in userpas: proxy_user, proxy_password = userpas.split(':', 1) proxy = location proxy_settings = { "proxy": proxy, "proxy_user": proxy_user, "proxy_password": proxy_password, } return proxy_settings def make_connection(self, host): host.lower() host_ = host # Host with(out) port if ':' in host: # Remove port from the host host_ = host.split(':')[0] else: host_ = "%s:%s" % (host, TimeoutHTTPProxyConnection.default_port) if self.proxy_config["proxy"] and host not in self.no_proxy and host_ not in self.no_proxy: if sys.version_info[:2] < (2, 7): host, extra_headers, x509 = self.get_host_info(host) conn = TimeoutProxyHTTP(host, **self.proxy_config) conn.set_timeout(self.timeout) return conn else: CONNECTION_LOCK.acquire() host, extra_headers, x509 = self.get_host_info(host) conn = TimeoutProxyHTTPS(host, **self.proxy_config) conn.set_timeout(self.timeout) CONNECTION_LOCK.release() return conn if sys.version_info[:2] < (2, 7): host, extra_headers, x509 = self.get_host_info(host) conn = TimeoutHTTP(host) conn.set_timeout(self.timeout) return conn else: CONNECTION_LOCK.acquire() self._connection = (None, None) # this disables connection caching which causes a race condition when running in threads conn = xmlrpclib.Transport.make_connection(self, host) CONNECTION_LOCK.release() if self.timeout: conn.timeout = self.timeout return conn def send_request(self, connection, handler, request_body): return xmlrpclib.Transport.send_request(self, connection, handler, request_body) def send_host(self, connection, host): return xmlrpclib.Transport.send_host(self, connection, host) def send_cookies(self, connection, cookie_request): """Add cookies to the header.""" self.cookiejar.add_cookie_header(cookie_request) for header, value in cookie_request.header_items(): if header.startswith("Cookie"): connection.putheader(header, value) def _save_cookies(self, headers, cookie_request): cookie_response = CookieResponse(headers) self.cookiejar.extract_cookies(cookie_response, cookie_request) if hasattr(self.cookiejar, "save"): self.cookiejar.save(self.cookiejar.filename) def _kerberos_client_request(self, host, handler, errcode, errmsg, headers): """Kerberos auth - create a client request string""" # check if "Negotiate" challenge is present in headers negotiate = [i.lower() for i in headers.get("WWW-Authenticate", "").split(", ")] if "negotiate" not in negotiate: # negotiate not supported, raise 401 error raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # initialize GSSAPI service = "HTTP@%s" % host rc, vc = kerberos.authGSSClientInit(service) if rc != 1: errmsg = "KERBEROS: Could not initialize GSSAPI" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # do a client step rc = kerberos.authGSSClientStep(vc, "") if rc != 0: errmsg = "KERBEROS: Client step failed" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) return vc, kerberos.authGSSClientResponse(vc) def _kerberos_verify_response(self, vc, host, handler, errcode, errmsg, headers): """Kerberos auth - verify client identity""" # verify that headers contain WWW-Authenticate header auth_header = headers.get("WWW-Authenticate", None) if auth_header is None: errcode = 401 errmsg = "KERBEROS: No WWW-Authenticate header in second HTTP response" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # verify that WWW-Authenticate contains Negotiate splits = auth_header.split(" ", 1) if (len(splits) != 2) or (splits[0].lower() != "negotiate"): errcode = 401 errmsg = "KERBEROS: Incorrect WWW-Authenticate header in second HTTP response: %s" % auth_header raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # do another client step to verify response from server errmsg = "KERBEROS: Could not verify server WWW-Authenticate header in second HTTP response" try: rc = kerberos.authGSSClientStep(vc, splits[1]) if rc == -1: errcode = 401 raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) except kerberos.GSSError, ex: errcode = 401 errmsg += ": %s/%s" % (ex[0][0], ex[1][0]) raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # cleanup rc = kerberos.authGSSClientClean(vc) if rc != 1: errcode = 401 errmsg = "KERBEROS: Could not clean-up GSSAPI: %s/%s" % (ex[0][0], ex[1][0]) raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
resp = s.request('POST', url, headers=k_headers,data=body) if resp.status_code == httplib.FORBIDDEN: logging.error( "Forbidden: Check WinRM port and version") elif resp.status_code == httplib.UNAUTHORIZED: logging.error( "Unauthorized: Check username and password") elif resp.status_code == httplib.OK: logging.debug("HTTP OK! Query Sent") print("HTTP OK! Query Sent") print_body = ''.join([i if isprint(i) else '.' for i in resp.content]) print("Response from server:\n{0}".format(print_body)) b_start = resp.content.index("Content-Type: application/octet-stream") + \ len("Content-Type: application/octet-stream\r\n") b_end = resp.content.index("--Encrypted Boundary",b_start) ebody = base64.b64encode(resp.content[b_start:b_end]) rc = kerberos.authGSSClientUnwrapIov(context, ebody) if rc == kerberos.AUTH_GSS_COMPLETE: body = base64.b64decode(kerberos.authGSSClientResponse(context)) body_xml = xml.dom.minidom.parseString(body) pretty_xml_as_string = body_xml.toprettyxml(indent=" ") print("{0}".format(pretty_xml_as_string)) else: logging.debug("HTTP status: {0}, {1}".format( resp.status_code,resp.content)) s.close() kerberos.authGSSClientClean(context)