|
|
ac7d03 |
From 0367e6dd66d47a78484e12e76119d9662356bf48 Mon Sep 17 00:00:00 2001
|
|
|
ac7d03 |
From: Stanislav Laznicka <slaznick@redhat.com>
|
|
|
ac7d03 |
Date: Fri, 26 May 2017 08:37:36 +0200
|
|
|
ac7d03 |
Subject: [PATCH] Avoid possible endless recursion in RPC call
|
|
|
ac7d03 |
|
|
|
ac7d03 |
This commit removes recursion in RPCClient.forward() which may lack
|
|
|
ac7d03 |
end condition.
|
|
|
ac7d03 |
|
|
|
ac7d03 |
https://pagure.io/freeipa/issue/6796
|
|
|
ac7d03 |
|
|
|
ac7d03 |
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
|
|
ac7d03 |
---
|
|
|
ac7d03 |
ipalib/rpc.py | 95 +++++++++++++++++++++++++++++++++--------------------------
|
|
|
ac7d03 |
1 file changed, 54 insertions(+), 41 deletions(-)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
|
|
|
ac7d03 |
index e23ca3d061645b2695a9e0deaa0b7d666f986e0e..297ed80414fae3d8b27558567425fec704f3e862 100644
|
|
|
ac7d03 |
--- a/ipalib/rpc.py
|
|
|
ac7d03 |
+++ b/ipalib/rpc.py
|
|
|
ac7d03 |
@@ -1088,50 +1088,63 @@ class RPCClient(Connectible):
|
|
|
ac7d03 |
:param kw: Keyword arguments to pass to remote command.
|
|
|
ac7d03 |
"""
|
|
|
ac7d03 |
server = getattr(context, 'request_url', None)
|
|
|
ac7d03 |
- self.log.info("Forwarding '%s' to %s server '%s'",
|
|
|
ac7d03 |
- name, self.protocol, server)
|
|
|
ac7d03 |
command = getattr(self.conn, name)
|
|
|
ac7d03 |
params = [args, kw]
|
|
|
ac7d03 |
- try:
|
|
|
ac7d03 |
- return self._call_command(command, params)
|
|
|
ac7d03 |
- except Fault as e:
|
|
|
ac7d03 |
- e = decode_fault(e)
|
|
|
ac7d03 |
- self.debug('Caught fault %d from server %s: %s', e.faultCode,
|
|
|
ac7d03 |
- server, e.faultString)
|
|
|
ac7d03 |
- if e.faultCode in errors_by_code:
|
|
|
ac7d03 |
- error = errors_by_code[e.faultCode]
|
|
|
ac7d03 |
- raise error(message=e.faultString)
|
|
|
ac7d03 |
- raise UnknownError(
|
|
|
ac7d03 |
- code=e.faultCode,
|
|
|
ac7d03 |
- error=e.faultString,
|
|
|
ac7d03 |
- server=server,
|
|
|
ac7d03 |
- )
|
|
|
ac7d03 |
- except SSLError as e:
|
|
|
ac7d03 |
- raise NetworkError(uri=server, error=str(e))
|
|
|
ac7d03 |
- except ProtocolError as e:
|
|
|
ac7d03 |
- # By catching a 401 here we can detect the case where we have
|
|
|
ac7d03 |
- # a single IPA server and the session is invalid. Otherwise
|
|
|
ac7d03 |
- # we always have to do a ping().
|
|
|
ac7d03 |
- session_cookie = getattr(context, 'session_cookie', None)
|
|
|
ac7d03 |
- if session_cookie and e.errcode == 401:
|
|
|
ac7d03 |
- # Unauthorized. Remove the session and try again.
|
|
|
ac7d03 |
- delattr(context, 'session_cookie')
|
|
|
ac7d03 |
- try:
|
|
|
ac7d03 |
- principal = getattr(context, 'principal', None)
|
|
|
ac7d03 |
- delete_persistent_client_session_data(principal)
|
|
|
ac7d03 |
- except Exception as e:
|
|
|
ac7d03 |
- # This shouldn't happen if we have a session but it isn't fatal.
|
|
|
ac7d03 |
- pass
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- # Create a new serverproxy with the non-session URI
|
|
|
ac7d03 |
- serverproxy = self.create_connection(os.environ.get('KRB5CCNAME'), self.env.verbose, self.env.fallback, self.env.delegate)
|
|
|
ac7d03 |
- setattr(context, self.id, Connection(serverproxy, self.disconnect))
|
|
|
ac7d03 |
- return self.forward(name, *args, **kw)
|
|
|
ac7d03 |
- raise NetworkError(uri=server, error=e.errmsg)
|
|
|
ac7d03 |
- except socket.error as e:
|
|
|
ac7d03 |
- raise NetworkError(uri=server, error=str(e))
|
|
|
ac7d03 |
- except (OverflowError, TypeError) as e:
|
|
|
ac7d03 |
- raise XMLRPCMarshallError(error=str(e))
|
|
|
ac7d03 |
+ # we'll be trying to connect multiple times with a new session cookie
|
|
|
ac7d03 |
+ # each time should we be getting UNAUTHORIZED error from the server
|
|
|
ac7d03 |
+ max_tries = 5
|
|
|
ac7d03 |
+ for try_num in range(0, max_tries):
|
|
|
ac7d03 |
+ self.log.info("[try %d]: Forwarding '%s' to %s server '%s'",
|
|
|
ac7d03 |
+ try_num+1, name, self.protocol, server)
|
|
|
ac7d03 |
+ try:
|
|
|
ac7d03 |
+ return self._call_command(command, params)
|
|
|
ac7d03 |
+ except Fault as e:
|
|
|
ac7d03 |
+ e = decode_fault(e)
|
|
|
ac7d03 |
+ self.debug('Caught fault %d from server %s: %s', e.faultCode,
|
|
|
ac7d03 |
+ server, e.faultString)
|
|
|
ac7d03 |
+ if e.faultCode in errors_by_code:
|
|
|
ac7d03 |
+ error = errors_by_code[e.faultCode]
|
|
|
ac7d03 |
+ raise error(message=e.faultString)
|
|
|
ac7d03 |
+ raise UnknownError(
|
|
|
ac7d03 |
+ code=e.faultCode,
|
|
|
ac7d03 |
+ error=e.faultString,
|
|
|
ac7d03 |
+ server=server,
|
|
|
ac7d03 |
+ )
|
|
|
ac7d03 |
+ except ProtocolError as e:
|
|
|
ac7d03 |
+ # By catching a 401 here we can detect the case where we have
|
|
|
ac7d03 |
+ # a single IPA server and the session is invalid. Otherwise
|
|
|
ac7d03 |
+ # we always have to do a ping().
|
|
|
ac7d03 |
+ session_cookie = getattr(context, 'session_cookie', None)
|
|
|
ac7d03 |
+ if session_cookie and e.errcode == 401:
|
|
|
ac7d03 |
+ # Unauthorized. Remove the session and try again.
|
|
|
ac7d03 |
+ delattr(context, 'session_cookie')
|
|
|
ac7d03 |
+ try:
|
|
|
ac7d03 |
+ principal = getattr(context, 'principal', None)
|
|
|
ac7d03 |
+ delete_persistent_client_session_data(principal)
|
|
|
ac7d03 |
+ except Exception as e:
|
|
|
ac7d03 |
+ # This shouldn't happen if we have a session
|
|
|
ac7d03 |
+ # but it isn't fatal.
|
|
|
ac7d03 |
+ self.debug("Error trying to remove persisent session "
|
|
|
ac7d03 |
+ "data: {err}".format(err=e))
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
+ # Create a new serverproxy with the non-session URI
|
|
|
ac7d03 |
+ serverproxy = self.create_connection(
|
|
|
ac7d03 |
+ os.environ.get('KRB5CCNAME'), self.env.verbose,
|
|
|
ac7d03 |
+ self.env.fallback, self.env.delegate)
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
+ setattr(context, self.id,
|
|
|
ac7d03 |
+ Connection(serverproxy, self.disconnect))
|
|
|
ac7d03 |
+ # try to connect again with the new session cookie
|
|
|
ac7d03 |
+ continue
|
|
|
ac7d03 |
+ raise NetworkError(uri=server, error=e.errmsg)
|
|
|
ac7d03 |
+ except (SSLError, socket.error) as e:
|
|
|
ac7d03 |
+ raise NetworkError(uri=server, error=str(e))
|
|
|
ac7d03 |
+ except (OverflowError, TypeError) as e:
|
|
|
ac7d03 |
+ raise XMLRPCMarshallError(error=str(e))
|
|
|
ac7d03 |
+ raise NetworkError(
|
|
|
ac7d03 |
+ uri=server,
|
|
|
ac7d03 |
+ error=_("Exceeded number of tries to forward a request."))
|
|
|
ac7d03 |
|
|
|
ac7d03 |
|
|
|
ac7d03 |
class xmlclient(RPCClient):
|
|
|
ac7d03 |
--
|
|
|
ac7d03 |
2.9.4
|
|
|
ac7d03 |
|