Exemple #1
0
 def toxml(self):
     return xmlrpclib.dumps(xmlrpclib.Fault(int(self.errno), str(self)), "", True)
Exemple #2
0
 def test_repr(self):
     f = xmlrpclib.Fault(42, 'Test Fault')
     self.assertEqual(repr(f), "<Fault 42: 'Test Fault'>")
     self.assertEqual(repr(f), str(f))
Exemple #3
0
 def boom(self, code, string):
     """
     Raise a Fault exception with the specified code and string
     """
     raise xmlrpclib.Fault(code, string)
Exemple #4
0
            if method == "RPC2":
                # prevent recursion
                raise AssertionError("method cannot be 'RPC2'")
            response = self.process_rpc(method,params)
            response = xmlrpclib.dumps((response,), methodresponse=1, allow_none=True)
        except identity.IdentityFailure, e:
            session.rollback()
            response = xmlrpclib.dumps(xmlrpclib.Fault(1,"%s: %s" % (e.__class__, str(e))))
        except xmlrpclib.Fault, fault:
            session.rollback()
            log.exception('Error handling XML-RPC method')
            # Can't marshal the result
            response = xmlrpclib.dumps(fault)
        except XMLRPCMethodDoesNotExist as e:
            session.rollback()
            response = xmlrpclib.dumps(xmlrpclib.Fault(1,
                    'XML-RPC method %s not implemented by this server' % e.args[0]))
        except Invalid, e:
             session.rollback()
             response = xmlrpclib.dumps(xmlrpclib.Fault(1, str(e)))
        except Exception:
            session.rollback()
            log.exception('Error handling XML-RPC method')
            # Some other error; send back some error info
            response = xmlrpclib.dumps(
                xmlrpclib.Fault(1, "%s:%s" % sys.exc_info()[:2])
                )

        if str(method).startswith('auth.'):
            log.debug('Time: %s %s', datetime.utcnow() - start, str(method))
        else:
            log.debug('Time: %s %s %s', datetime.utcnow() - start, str(method), str(params)[0:50])
 def getorraise(self, dlhash, key):
     try:
         d = self.downloads[dlhash]
         return d[key]
     except KeyError as e:
         raise xmlrpclib.Fault(-501, '')
Exemple #6
0
 def raiser(*args, **kw):
     raise xmlrpclib.Fault(100, 'error')
Exemple #7
0
        """
        try:
            params, method = xmlrpclib.loads(data)
            response = xmlrpclib.dumps(
                (self._wrap_obj(self._dispatch(method, params)), ),
                methodresponse=True,
                allow_none=True,
                encoding=self.charset)
        except xmlrpclib.Fault, fault:
            response = xmlrpclib.dumps(fault,
                                       allow_none=self.allow_none,
                                       encoding=self.charset)
        except:
            exc_type, exc_value, tb = exc_info = sys.exc_info()
            log.exception('Exception in XMLRPC request:', 'xmlrpc', exc_info)
            response = xmlrpclib.dumps(xmlrpclib.Fault(
                1, '%s:%s' % (exc_type, exc_value)),
                                       encoding=self.charset,
                                       allow_none=self.allow_none)

        return response

    def handle_request(self, request):
        if request.method == 'POST':
            response = self._marshaled_dispatch(request.data)
            return BaseResponse(response, mimetype='application/xml')
        return BaseResponse(
            '\n'.join(
                ('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">',
                 '<title>XMLRPC Interface</title>',
                 '<h1>XMLRPC Interface</h1>',
                 '<p>This URL provides an XMLRPC interface.  You have to '
 def __addToCollection(self, uid, request, pwd):
     """This is called after successful login to add an items
     to a certain collection, e.g. a new res.partner."""
     hello()
     if not self.desc:
         raise xmlrpclib.Fault("warning -- Object Error",
                               "no such collection")
     # check whether we got well-formed XML
     parser = etree.XMLParser(remove_comments=True)
     try:
         doc = etree.fromstring(request.content.read(), parser=parser)
     except Exception as e:
         request.setResponseCode(400)
         request.write("malformed XML: " + str(e))
         request.finish()
         return
     # check whether we got valid XML with the given schema
     ns = str(request.URLPath()) + "/schema"
     schemaxml = self.__desc2relaxNG(str(request.URLPath()), self.desc)
     schema = etree.fromstring(schemaxml)
     relaxng = etree.RelaxNG(schema)
     # to validate doc, we need to set "id" to a numeric value
     try:
         doc.find("{%s}id" % ns).text = "-1"
     except:
         pass
     if not relaxng.validate(doc):
         request.setResponseCode(400)
         err = relaxng.error_log
         request.write("invalid XML:\n" + str(err))
         request.finish()
         return
     # get default values for this model
     defaultDocRoot = etree.fromstring(self.__mkDefaultXml(
         str(request.URLPath()), self.desc, self.defaults[uid]),
                                       parser=parser)
     defaultDoc = defaultDocRoot.find(
         "{http://www.w3.org/2005/Atom}content").find(
             "{%s}%s" % (ns, self.model.replace(".", "_")))
     stripNsRe = re.compile(r'^{%s}(.+)$' % ns)
     whitespaceRe = re.compile(r'\s+')
     # collect all fields with non-default values
     fields = {}
     for c in doc.getchildren():
         if c.tag == "{%s}id" % ns or c.tag == "{%s}create_date" % ns:
             # will not update id or create_date
             continue
         elif whitespaceRe.sub(
                 " ",
                 etree.tostring(
                     c, pretty_print=True).strip()) == whitespaceRe.sub(
                         " ",
                         etree.tostring(defaultDoc.find(c.tag),
                                        pretty_print=True).strip()):
             # c has default value
             continue
         # we can assume the regex will match due to validation beforehand
         tagname = stripNsRe.search(c.tag).group(1)
         if c.attrib["type"] in ("char", "selection", "text", "datetime"):
             fields[tagname] = c.text
         elif c.attrib["type"] == "float":
             fields[tagname] = float(c.text)
         elif c.attrib["type"] == "integer":
             fields[tagname] = int(c.text)
         elif c.attrib["type"] == "boolean":
             fields[tagname] = (c.text == "True")
         elif c.attrib["type"] == "many2one":
             assert c.attrib['relation'] == defaultDoc.find(
                 c.tag).attrib['relation']
             uris = [link.attrib['href'] for link in c.getchildren()]
             ids = [
                 int(u[u.rfind('/') + 1:]) for u in uris
                 if u.startswith(c.attrib['relation'])
             ]
             if ids:
                 fields[tagname] = ids[0]
         elif c.attrib["type"] in ("many2many", "one2many"):
             assert c.attrib['relation'] == defaultDoc.find(
                 c.tag).attrib['relation']
             uris = [link.attrib['href'] for link in c.getchildren()]
             ids = [
                 int(u[u.rfind('/') + 1:]) for u in uris
                 if u.startswith(c.attrib['relation'])
             ]
             if ids:
                 fields[tagname] = [(6, 0, ids)]
         else:
             # TODO: date, many2one (we can't really set many2many and one2many here, can we?)
             raise NotImplementedError("don't know how to handle element " +
                                       c.tag + " of type " +
                                       c.attrib["type"])
     # compose the XML-RPC call from them
     proxy = quietProxy(self.openerpUrl + 'object')
     d = proxy.callRemote('execute', self.dbname, uid, pwd, self.model,
                          'create', fields)
     d.addCallback(self.__handleAddCollectionAnswer, request)
     return d
    def __updateItem(self, old, uid, pwd, request, lastModified):
        """This is called after successful login to add an items
        to a certain collection, e.g. a new res.partner."""
        hello()
        if not self.desc:
            raise xmlrpclib.Fault("warning -- Object Error",
                                  "no such collection")
        # check whether we got well-formed XML
        parser = etree.XMLParser(remove_comments=True)
        try:
            doc = etree.fromstring(request.content.read(), parser=parser)
        except Exception as e:
            request.setResponseCode(400)
            request.write("malformed XML: " + str(e))
            request.finish()
            return
        # check whether we got valid XML with the given schema
        ns = str(request.URLPath()) + "/schema"
        schemaxml = self.__desc2relaxNG(str(request.URLPath()), self.desc)
        schema = etree.fromstring(schemaxml)
        relaxng = etree.RelaxNG(schema)
        # try to validate object
        if not relaxng.validate(doc):
            request.setResponseCode(400)
            err = relaxng.error_log
            request.write("invalid XML:\n" + str(err))
            request.finish()
            return
        # compose old values for this object
        xmlns = "".join([word[0] for word in self.model.split('.')])
        basepath = str(request.URLPath())
        path = basepath + "/" + str(old[0]['id'])
        s = self.__mkItemXml(xmlns, basepath + "/schema", basepath, path,
                             lastModified, old[0])
        oldDocRoot = etree.fromstring(s, parser=parser)
        oldDoc = oldDocRoot.find("{http://www.w3.org/2005/Atom}content").find(
            "{%s}%s" % (ns, self.model.replace(".", "_")))
        stripNsRe = re.compile(r'^{%s}(.+)$' % ns)
        whitespaceRe = re.compile(r'\s+')

        def isEquivalentXml(a, b):
            wsNormalizedA = whitespaceRe.sub(
                " ",
                etree.tostring(a, pretty_print=True).strip())
            wsNormalizedB = whitespaceRe.sub(
                " ",
                etree.tostring(b, pretty_print=True).strip())
            if wsNormalizedA == wsNormalizedB:
                return True
            elif a.attrib["type"] in (
                    "char", "selection", "text", "datetime", "float",
                    "integer",
                    "boolean") and a.attrib["type"] == b.attrib["type"]:
                return a.text == b.text
            else:
                return False

        # collect all fields with new values
        fields = {}
        for c in doc.getchildren():
            if c.tag == "{%s}id" % ns or c.tag == "{%s}create_date" % ns:
                # will not update id or create_date
                continue
            elif isEquivalentXml(c, oldDoc.find(c.tag)):
                # c has old value
                continue
            # we can assume the regex will match due to validation beforehand
            tagname = stripNsRe.search(c.tag).group(1)
            if c.attrib["type"] in ("char", "selection", "text", "datetime"):
                fields[tagname] = c.text or ""
            elif c.attrib["type"] == "float":
                fields[tagname] = float(c.text)
            elif c.attrib["type"] == "integer":
                fields[tagname] = int(c.text)
            elif c.attrib["type"] == "boolean":
                fields[tagname] = (c.text == "True")
            elif c.attrib["type"] == "many2one":
                assert c.attrib['relation'] == oldDoc.find(
                    c.tag).attrib['relation']
                oldUris = [
                    link.attrib['href']
                    for link in oldDoc.find(c.tag).getchildren()
                ]
                uris = [link.attrib['href'] for link in c.getchildren()]
                ids = [
                    int(u[u.rfind('/') + 1:]) for u in uris
                    if u.startswith(c.attrib['relation'])
                ]
                if ids and oldUris != uris:
                    fields[tagname] = ids[0]
            elif c.attrib["type"] in ("many2many", "one2many"):
                assert c.attrib['relation'] == oldDoc.find(
                    c.tag).attrib['relation']
                oldUris = [
                    link.attrib['href']
                    for link in oldDoc.find(c.tag).getchildren()
                ]
                uris = [link.attrib['href'] for link in c.getchildren()]
                ids = [
                    int(u[u.rfind('/') + 1:]) for u in uris
                    if u.startswith(c.attrib['relation'])
                ]
                if ids and oldUris != uris:
                    fields[tagname] = [(6, 0, ids)]
            else:
                # TODO: date
                raise NotImplementedError("don't know how to handle element " +
                                          c.tag + " of type " +
                                          c.attrib["type"])
        # compose the XML-RPC call from them
        proxy = quietProxy(self.openerpUrl + 'object')
        d = proxy.callRemote('execute', self.dbname, uid, pwd, self.model,
                             'write', [old[0]['id']], fields)
        d.addCallback(self.__handleUpdateItemAnswer, request)
        return d
Exemple #10
0
 def return_fault(self, code, msg):
     return xmlrpclib.Fault(code, msg)
Exemple #11
0
                if getattr(e, "log", True):
                    self.logger.error(e, exc_info=True)
                raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e))

        need_to_lock = not getattr(method_func, 'locking', False)
        if need_to_lock:
            lock_start = time.time()
            self.lock.acquire()
            lock_done = time.time()
        try:
            method_start = time.time()
            result = method_func(*args)
        except Exception, e:
            if getattr(e, "log", True):
                self.logger.error(e, exc_info=True)
            raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e))
        finally:
            method_done = time.time()
            if need_to_lock:
                self.lock.release()
                self.statistics.add_value('component_lock',
                                          lock_done - lock_start)
            self.statistics.add_value(method, method_done - method_start)
        if getattr(method_func, "query", False):
            if not getattr(method_func, "query_all_methods", False):
                margs = args[:1]
            else:
                margs = []
            result = marshal_query_result(result, *margs)
        return result
Exemple #12
0
            if method == "RPC2":
                # prevent recursion
                raise AssertionError("method cannot be 'RPC2'")
            response = self.process_rpc(method,params)
            response = xmlrpclib.dumps((response,), methodresponse=1, allow_none=True)
        except identity.IdentityFailure, e:
            session.rollback()
            response = xmlrpclib.dumps(xmlrpclib.Fault(1,"%s: %s" % (e.__class__, str(e))))
        except xmlrpclib.Fault, fault:
            session.rollback()
            log.exception('Error handling XML-RPC method')
            # Can't marshal the result
            response = xmlrpclib.dumps(fault)
        except Invalid, e:
             session.rollback()
             response = xmlrpclib.dumps(xmlrpclib.Fault(1, str(e)))
        except Exception:
            session.rollback()
            log.exception('Error handling XML-RPC method')
            # Some other error; send back some error info
            response = xmlrpclib.dumps(
                xmlrpclib.Fault(1, "%s:%s" % sys.exc_info()[:2])
                )

        if str(method).startswith('auth.'):
            log.debug('Time: %s %s', datetime.utcnow() - start, str(method))
        else:
            log.debug('Time: %s %s %s', datetime.utcnow() - start, str(method), str(params)[0:50])
        cherrypy.response.headers["Content-Type"] = "text/xml"
        return response
Exemple #13
0
 def __call__(self):
     return xmlrpclib.Fault(
         premarshal(self.data.faultCode),
         premarshal(self.data.faultString),
     )
Exemple #14
0
#!/usr/bin/env python2
# -*- coding:utf-8 -*-

import sys
import xmlrpclib
import traceback
import ssl

server = xmlrpclib.ServerProxy('https://116.196.104.11:1337',context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
try:
    if not server.echo('try echo') == 'try echo':
        raise xmlrpclib.Fault(-1,'Try echo method failed, server invalid.')
except xmlrpclib.Fault,e:
    traceback.print_exc()
    print('__________________')
    print(e.faultString)
    sys.exit()
except Exception:
    traceback.print_exc()
    print('-------------NOT GOOD----------')
    sys.exit()

print('Available methods:'+str(server.system.listMethods()))
Exemple #15
0
    def _dispatch(self, method, args):
        """
    We provide a _dispatch function (which SimpleXMLRPCServer looks for and
    uses) so that we can log exceptions due to our programming errors within
    seattlegeni as well to detect incorrect usage by clients.
    """

        try:
            # Get the requested function (making sure it exists).
            try:
                func = getattr(self, method)
            except AttributeError:
                raise InvalidRequestError("The requested method '" + method +
                                          "' doesn't exist.")

            # Call the requested function.
            return func(*args)

        except InvalidRequestError:
            log.error("The xmlrpc server was used incorrectly: " +
                      traceback.format_exc())
            raise

        except xmlrpclib.Fault:
            # A xmlrpc Fault was intentionally raised by the code in this module.
            raise

        except Exception, e:
            # We assume all other exceptions are bugs in our code.

            # We use the log message as the basis for the email message, as well.
            logmessage = "Internal error while handling an xmlrpc request: " + traceback.format_exc(
            )
            log.critical(logmessage)

            # Normally django will send an email to the ADMINS defined in settings.py
            # when an exception occurs. However, our xmlrpc dispatcher will turn this
            # into a Fault that is returned to the client. So, django won't see it as
            # an uncaught exception. Therefore, we have to send it ourselves.
            if not settings.DEBUG:
                subject = "Error handling xmlrpc request '" + method + "': " + str(
                    type(e)) + " " + str(e)

                emailmessage = logmessage + "\n\n"
                emailmessage += "XMLRPC method called: " + method + "\n"

                # If the first argument looks like auth info, don't include the
                # api_key in the email we send. Otherwise, include all the args.
                # We wrap this in a try block just in case we screw this up we want to
                # be sure we get an email still.
                try:
                    if len(args) > 0 and isinstance(
                            args[0], dict) and "username" in args[0]:
                        emailmessage += "Username: "******"username"]) + "\n"
                        if len(args) > 1:
                            emailmessage += "Non-auth arguments: " + str(
                                args[1:]) + "\n"
                        else:
                            emailmessage += "There were no non-auth arguments." + "\n"
                    else:
                        emailmessage += "Arguments: " + str(args) + "\n"
                except:
                    pass

                # Send an email to the addresses listed in settings.ADMINS
                django.core.mail.mail_admins(subject, emailmessage)

            # It's not unlikely that the user ends up seeing this message, so we
            # are careful about what the content of the message is. We don't
            # include the exception trace.
            raise xmlrpclib.Fault(
                FAULTCODE_INTERNALERROR,
                "Internal error while handling the xmlrpc request.")
 def __handleLoginAnswer(self, uid):
     hello()
     if not uid:
         raise xmlrpclib.Fault("AccessDenied", "login failed")
     else:
         return uid
Exemple #17
0
    def make_custom_query(self, entity, conditions, limit=200):
        """
        Name
        ----
        `make_custom_query` (`entity`, `conditions`, `limit`)

        Description
        -----------
        Construct and run a custom query and return the results.

        Arguments
        ---------
        `entity`: string
            The entity you want to query
        `conditions`: string
            The conditions of the query
        `limit`: integer
            Add a limit to the number of results returned.
            Defaults to 200.

        Return value
        ------------
        A list of dictionaries containing the query results.

        The user should be authenticated with a username and token.

        Example
        -------

        # Get all test jobs submitted by the user 'kernel-ci', and which ended
        # as 'Incomplete':
        server.results.make_custom_query("testjob",
            "testjob__submitter__exact__kernel-ci,"
            "testjob__health__exact__Incomplete")
        [{ jobXX }, { jobXY }, ...]

        # Get all test cases in a test suite named 'custom-tests', that failed,
        # and for whom the job ended after '2017-04-26 00:00:00'.
        server.results.make_custom_query("testcase",
            "testsuite__name__exact__1_custom-tests,"
            "testcase__result__exact__Test failed,"
            "testjob__end_time__gt__2017-04-26 00:00:00")
        [{ testcaseXX }, { testcaseXY }, ...]

        """
        self._authenticate()
        try:
            content_type = Query.get_content_type(entity)
        except InvalidContentTypeError:
            raise xmlrpclib.Fault(
                400, "Wrong table name in entity parameter. "
                "Please refer to query docs.")

        if content_type.model_class() not in QueryCondition.RELATION_MAP:
            raise xmlrpclib.Fault(
                400, "Wrong table name in entity parameter. "
                "Please refer to query docs.")

        conditions = Query.parse_conditions(content_type, conditions)

        try:
            results = Query.get_queryset(content_type,
                                         conditions).visible_by_user(self.user)
        except FieldDoesNotExist:
            raise xmlrpclib.Fault(400,
                                  "Conditions URL incorrect: Field does not exist. "
                                  "Please refer to query docs.")
        return list(results[:limit])
Exemple #18
0
 def no_such_slice(self, slice_urn):
     """Raise a no such slice exception."""
     fault_code = 'No such slice.'
     fault_string = 'The slice named by %s does not exist' % (slice_urn)
     self.logger.warning(fault_string)
     raise xmlrpclib.Fault(fault_code, fault_string)
Exemple #19
0
            response = (handler.run(),)
            # note that we wrap response in a singleton tuple
            response = xmlrpclib.dumps(response, methodresponse=1, allow_none=1)
            self.logger.info("RESPONSE: %r" % response)
            self.session.host.closeTask(handler.id, response)
            return
        except xmlrpclib.Fault, fault:
            response = xmlrpclib.dumps(fault)
            tb = ''.join(traceback.format_exception(*sys.exc_info())).replace(r"\n", "\n")
            self.logger.warn("FAULT:\n%s" % tb)
        except (SystemExit, koji.tasks.ServerExit, KeyboardInterrupt):
            #we do not trap these
            raise
        except koji.tasks.ServerRestart:
            #freeing this task will allow the pending restart to take effect
            self.session.host.freeTasks([handler.id])
            return
        except:
            tb = ''.join(traceback.format_exception(*sys.exc_info()))
            self.logger.warn("TRACEBACK: %s" % tb)
            # report exception back to server
            e_class, e = sys.exc_info()[:2]
            faultCode = getattr(e_class, 'faultCode', 1)
            if issubclass(e_class, koji.GenericError):
                #just pass it through
                tb = str(e)
            response = xmlrpclib.dumps(xmlrpclib.Fault(faultCode, tb))

        # if we get here, then we're handling an exception, so fail the task
        self.session.host.failTask(handler.id, response)
Exemple #20
0
class CredentialVerifier(object):
    """Utilities to verify signed credentials from a given set of 
    root certificates. Will compare target and source URNs, and privileges.
    See verify and verify_from_strings methods in particular."""

    CATEDCERTSFNAME = 'CATedCACerts.pem'

    # root_cert_file is a trusted root file file or directory of
    # trusted roots for verifying credentials
    def __init__(self, root_cert_fileordir):
        self.logger = logging.getLogger('cred-verifier')
        if root_cert_fileordir is None:
            raise Exception("Missing Root certs argument")
        elif os.path.isdir(root_cert_fileordir):
            files = os.listdir(root_cert_fileordir)
            self.root_cert_files = []
            for file in files:
                # FIXME: exclude files that aren't cert files? The combo cert file?
                if file == CredentialVerifier.CATEDCERTSFNAME:
                    continue
                self.root_cert_files.append(
                    os.path.expanduser(os.path.join(root_cert_fileordir,
                                                    file)))
            self.logger.info(
                'Will accept credentials signed by any of %d root certs found in %s: %r'
                % (len(self.root_cert_files), root_cert_fileordir,
                   self.root_cert_files))
        elif os.path.isfile(root_cert_fileordir):
            self.logger.info(
                'Will accept credentials signed by the single root cert %s' %
                root_cert_fileordir)
            self.root_cert_files = [root_cert_fileordir]
        else:
            raise Exception("Couldn't find Root certs in %s" %
                            root_cert_fileordir)

    @classmethod
    def getCAsFileFromDir(cls, caCerts):
        '''Take a directory of CA certificates and concatenate them into a single
        file suitable for use by the Python SSL library to validate client 
        credentials. Existing file is replaced.'''
        if caCerts is None:
            raise Exception('Missing caCerts argument')
        if os.path.isfile(os.path.expanduser(caCerts)):
            return caCerts
        if not os.path.isdir(os.path.expanduser(caCerts)):
            raise Exception('caCerts arg Not a file or a dir: %s' % caCerts)

        logger = logging.getLogger('cred-verifier')

        # Now we have a dir of caCerts files
        # For each file in the dir (isfile), concatenate them into a new file
        comboFullPath = os.path.join(caCerts,
                                     CredentialVerifier.CATEDCERTSFNAME)

        caFiles = os.listdir(caCerts)
        #logger.debug('Got %d potential caCert files in the dir', len(caFiles))

        outfile = open(comboFullPath, "w")
        okFileCount = 0
        for filename in caFiles:
            filepath = os.path.join(caCerts, filename)
            # Confirm it's a CA file?
            #        if not file.endswith('.pem'):
            #            continue
            if not os.path.isfile(os.path.expanduser(filepath)):
                logger.debug('Skipping non file %s', filepath)
                continue
            if filename == CredentialVerifier.CATEDCERTSFNAME:
                # logger.debug('Skipping previous cated certs file')
                continue
            okFileCount += 1
            logger.info("Adding trusted cert file %s", filename)
            certfile = open(filepath)
            for line in certfile:
                outfile.write(line)
            certfile.close()
        outfile.close()
        if okFileCount == 0:
            sys.exit('Found NO trusted certs in %s!' % caCerts)
        else:
            logger.info(
                'Combined dir of %d trusted certs %s into file %s for Python SSL support',
                okFileCount, caCerts, comboFullPath)
        return comboFullPath

    def verify_from_strings(self, gid_string, cred_strings, target_urn,
                            privileges):
        '''Create Credential and GID objects from the given strings,
        and then verify the GID has the right privileges according 
        to the given credentials on the given target.'''
        def make_cred(cred_string):
            return cred.Credential(string=cred_string)

        return self.verify(gid.GID(string=gid_string),
                           map(make_cred, cred_strings), target_urn,
                           privileges)

    def verify_source(self, source_gid, credential):
        '''Ensure the credential is giving privileges to the caller/client.
        Return True iff the given source (client) GID's URN
        is == the given credential's Caller (Owner) URN'''
        source_urn = source_gid.get_urn()
        cred_source_urn = credential.get_gid_caller().get_urn()
        #self.logger.debug('Verifying source %r against credential source %r (cred target %s)',
        #              source_urn, cred_source_urn, credential.get_gid_object().get_urn())
        result = (cred_source_urn == source_urn)
        if result:
            #   self.logger.debug('Source URNs match')
            pass
        else:
            self.logger.debug(
                'Source URNs do not match. Source URN %r != credential source URN %r',
                source_urn, cred_source_urn)
        return result

    def verify_target(self, target_urn, credential):
        '''Ensure the credential is giving privileges on the right subject/target.
        Return True if no target is specified, or the target URN
        matches the credential's Object's (target's) URN, else return False.
        No target is required, for example, to ListResources.'''
        if not target_urn:
            #            self.logger.debug('No target specified, considering it a match.')
            return True
        else:
            cred_target_urn = credential.get_gid_object().get_urn()
            # self.logger.debug('Verifying target %r against credential target %r',
            #               target_urn, cred_target_urn)
            result = target_urn == cred_target_urn
            if result:
                #    self.logger.debug('Target URNs match.')
                pass
            else:
                self.logger.debug(
                    'Target URNs do NOT match. Target URN %r != Credential URN %r',
                    target_urn, cred_target_urn)
            return result

    def verify_privileges(self, privileges, credential):
        ''' Return True iff the given credential gives the privilege
        to perform ALL of the privileges (actions) in the given list.
        In particular, the given list of 'privileges' is really a list
        of names of operations. The privileges in credentials are
        each turned in to Rights objects (see sfa/trust/rights.py).
        And the SFA rights table is used to map from names of privileges
        as specified in credentials, to names of operations.'''
        result = True
        privs = credential.get_privileges()
        for priv in privileges:
            if not privs.can_perform(priv):
                self.logger.debug(
                    'Privilege %s not found on credential %s of %s', priv,
                    credential.get_gid_object().get_urn(),
                    credential.get_gid_caller().get_urn())
                result = False
        return result

    def verify(self, gid, credentials, target_urn, privileges):
        '''Verify that the given Source GID supplied at least one credential
        in the given list of credentials that has all the privileges required 
        in the privileges list on the given target.
        IE if any of the supplied credentials has a caller that matches gid 
        and a target that matches target_urn, and has all the privileges in 
        the given list, then return the list of credentials that were ok.
        Throw an Exception if we fail to verify any credential.'''

        # Note that here we treat a list of credentials as being options
        # Alternatively could accumulate privileges for example
        # The semantics of the list of credentials is under specified.

        self.logger.debug('Verifying privileges')
        result = list()
        failure = ""
        tried_creds = ""
        for cred in credentials:
            if tried_creds != "":
                tried_creds = "%s, %s" % (tried_creds,
                                          cred.get_gid_caller().get_urn())
            else:
                tried_creds = cred.get_gid_caller().get_urn()

            if not self.verify_source(gid, cred):
                failure = "Cred %s fails: Source URNs dont match" % cred.get_gid_caller(
                ).get_urn()
                continue
            if not self.verify_target(target_urn, cred):
                failure = "Cred %s on %s fails: Target URNs dont match" % (
                    cred.get_gid_caller().get_urn(),
                    cred.get_gid_object().get_urn())
                continue
            if not self.verify_privileges(privileges, cred):
                failure = "Cert %s doesn't have sufficient privileges" % cred.get_gid_caller(
                ).get_urn()
                continue

            print
            try:
                if not cred.verify(self.root_cert_files):
                    failure = "Couldn't validate credential for caller %s with target %s with any of %d known root certs" % (
                        cred.get_gid_caller().get_urn(),
                        cred.get_gid_object().get_urn(),
                        len(self.root_cert_files))
                    continue
            except Exception, exc:
                failure = "Couldn't validate credential for caller %s with target %s with any of %d known root certs: %s" % (
                    cred.get_gid_caller().get_urn(),
                    cred.get_gid_object().get_urn(), len(
                        self.root_cert_files), exc)
                self.logger.info(failure)
                continue
            # If got here it verified
            result.append(cred)

        if result and result != list():
            # At least one credential verified ok and was added to the list
            # return that list
            return result
        else:
            # We did not find any credential with sufficient privileges
            # Raise an exception.
            fault_code = 'Insufficient privileges'
            fault_string = 'No credential was found with appropriate privileges. Tried %s. Last failure: %s' % (
                tried_creds, failure)
            self.logger.error(fault_string)
            raise xmlrpclib.Fault(fault_code, fault_string)
Exemple #21
0
class XMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, threading.Thread):
    """
    Stoppable XMLRPC Server with custom dispatch to send over complete traceback
    in case of exception.
    """
    def __init__(self, *args, **kwargs):
        threading.Thread.__init__(self)
        SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(
            self,
            requestHandler=CustomXMLRPCRequestHandler,
            allow_none=True,
            *args,
            **kwargs)
        self._stop = False
        # set timeout for handle_request. If we don't the server will hang
        self.timeout = 2

    def run(self):
        self.serve_forever()
        api.devlog("serve_forever ended")
        return

    # overloaded method to be able to stop server
    def serve_forever(self):
        while not self._stop:
            self.handle_request()
        api.devlog("server forever stopped by flag")

    def stop_server(self):
        api.devlog("server stopping...")
        self._stop = True

    # The default dispatcher does not send across the whole stack trace.
    # Only type and value are passed back. The client has no way of knowing
    # the exact place where error occurred in the server (short of some
    # other means such as server logging). This dispatcher sends the whole
    # stack trace.
    def _dispatch(self, method, params):
        """Dispatches the XML-RPC method.

        XML-RPC calls are forwarded to a registered function that
        matches the called XML-RPC method name. If no such function
        exists then the call is forwarded to the registered instance,
        if available.

        If the registered instance has a _dispatch method then that
        method will be called with the name of the XML-RPC method and
        its parameters as a tuple
        e.g. instance._dispatch('add',(2,3))

        If the registered instance does not have a _dispatch method
        then the instance will be searched to find a matching method
        and, if found, will be called.

        Methods beginning with an '_' are considered private and will
        not be called.
        """

        func = None
        try:
            # check to see if a matching function has been registered
            func = self.funcs[method]
        except KeyError:
            if self.instance is not None:
                # check for a _dispatch method
                if hasattr(self.instance, '_dispatch'):
                    return self.instance._dispatch(method, params)
                else:
                    # call instance method directly
                    try:
                        func = SimpleXMLRPCServer.resolve_dotted_attribute(
                            self.instance, method, self.allow_dotted_names)
                    except AttributeError:
                        pass

        if func is not None:
            try:
                # since we are using a keyword xmlrpc proxy this is sending
                # the info comes in form of args and kwargs
                # so params has 2 items, the first being a list or tuple
                # and the second a dictionary
                if len(params) == 2 and  isinstance(params[1],dict) and\
                ( isinstance(params[0],list) or isinstance(params[0],tuple) ) :
                    return func(*params[0], **params[1])
                else:
                    # this is the default way in case a normal xmlrpclib.ServerProxy is used
                    return func(*params)
            except Exception:
                # extended functionality to let the client have the full traceback
                msg = traceback.format_exc()
                raise xmlrpclib.Fault(1, msg)
        else:
            raise Exception('method "%s" is not supported' % method)

    def _marshaled_dispatch(self, data, dispatch_method=None):
        """Dispatches an XML-RPC method from marshalled (XML) data.

        XML-RPC methods are dispatched from the marshalled (XML) data
        using the _dispatch method and the result is returned as
        marshalled data. For backwards compatibility, a dispatch
        function can be provided as an argument (see comment in
        SimpleXMLRPCRequestHandler.do_POST) but overriding the
        existing method through subclassing is the prefered means
        of changing method dispatch behavior.
        """

        try:
            params, method = xmlrpclib.loads(data)

            # generate response
            if dispatch_method is not None:
                response = dispatch_method(method, params)
            else:
                response = self._dispatch(method, params)
            # wrap response in a singleton tuple
            response = (response, )
            response = xmlrpclib.dumps(response,
                                       methodresponse=1,
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)
        except Fault, fault:
            response = xmlrpclib.dumps(fault,
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)
        except Exception:
            # report exception back to server
            exc_type, exc_value, exc_tb = sys.exc_info()
            response = xmlrpclib.dumps(
                xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
                encoding=self.encoding,
                allow_none=self.allow_none,
            )
            self._cbRender(f, request)

        else:
            instance_name = "cloudfactory"
            #modul_name = args[1]
            modul_name = "CloudFactory"
            instance = self.moduls.get(modul_name)
            if not instance:
                msg = "modul id not exists args [%s]" % str(args)
                print msg
                function = None
            else:
                function = getattr(instance, functionName, None)
                if function is None:
                    f = xmlrpclib.Fault(
                        self.FAILURE,
                        "The Resource didn't implement the %s method" %
                        functionName)
                    self._cbRender(f, request)
                else:
                    function = packageResult(function)
                    responseFailed = []
                    request.notifyFinish().addErrback(responseFailed.append)

                    d = threads.deferToThread(function, *args)
                    d.addErrback(self._ebRender)
                    d.addCallback(self._cbRender, request, responseFailed)
        return server.NOT_DONE_YET


def initResource():
Exemple #23
0
 def _error(self, code, message):
     fault = xmlrpclib.Fault(code, message)
     return xmlrpclib.dumps(fault, encoding=self.encoding, allow_none=True)
Exemple #24
0
 def make_fault(self):
     """Returns an xmlrpc fault."""
     return xmlrpclib.Fault(666, "Yoghurt and spanners.")
            else:
                response = self._dispatch(method, params)
            # wrap response in a singleton tuple
            response = (response, )
            response = xmlrpclib.dumps(response,
                                       methodresponse=1,
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)
        except Fault, fault:
            response = xmlrpclib.dumps(fault,
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)
        except:
            # report exception back to server
            response = xmlrpclib.dumps(
                xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)),
                encoding=self.encoding,
                allow_none=self.allow_none,
            )

        return response

    def system_listMethods(self):
        """system.listMethods() => ['add', 'subtract', 'multiple']

        Returns a list of the methods supported by the server."""

        methods = self.funcs.keys()
        if self.instance is not None:
            # Instance can implement _listMethod to return a list of
            # methods
Exemple #26
0
        # The interface.acquire_vessels() call expects 'rand' instead of 'random'.
        if resource_type == 'random':
            resource_type = 'rand'

        try:
            acquired_vessels = interface.acquire_vessels(
                geni_user, num_vessels, resource_type)
        except UnableToAcquireResourcesError, err:
            raise xmlrpclib.Fault(
                FAULTCODE_UNABLETOACQUIRE,
                "Unable to fulfill vessel acquire request at this given time. Details: "
                + str(err))
        except InsufficientUserResourcesError, err:
            raise xmlrpclib.Fault(
                FAULTCODE_NOTENOUGHCREDITS,
                "You do not have enough vessel credits to acquire the number of vessels requested."
            )

        # since acquire_vessels returns a list of Vessel objects, we
        # need to convert them into a list of 'info' dictionaries.
        return interface.get_vessel_infodict_list(acquired_vessels)

    @staticmethod
    @log_function_call
    def acquire_specific_vessels(auth, vesselhandle_list):
        """
    <Purpose>
      Acquires specific vessels for a user. This will be best effort. Zero or
      more of the vessels may be acquired. The list, however, cannot include
      more vessels than the maximum number the user is allowed to acquire.
    <Arguments>
Exemple #27
0
        params, method = xmlrpclib.loads(data)

        # add request to params
        params = (request, ) + params

        # generate response
        try:
            if dispatch_method is not None:
                response = dispatch_method(method, params)
            else:
                response = self._dispatch(method, params)
            # wrap response in a singleton tuple
            response = (response, )
            response = xmlrpclib.dumps(response,
                                       methodresponse=1,
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)

        except xmlrpclib.Fault, fault:
            response = xmlrpclib.dumps(fault,
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)

        except:
            response = xmlrpclib.dumps(xmlrpclib.Fault(
                1, "%s: %s" % (sys.exc_type.__name__, sys.exc_value)),
                                       allow_none=self.allow_none,
                                       encoding=self.encoding)

        return response
Exemple #28
0
    def get_encrypted_api_key(username):
        """
    <Purpose>
      Retrieve the account's API key encrypted with the account's public key.
      This provides the holder of an account's private key a means of obtaining
      the SeattleGENI API key for the account. A side effect is that this also
      provide a means of determining whether an account exists on seattlegeni.
      However, we do not protect against such querying here because the same
      can be determined in a handful of other ways through the html interface.
      
      This approach of obtaining the encrypted api key can be removed later if
      we implement a way to sign requests.
    <Arguments>
      username
        The username of the account whose encrypted API key we want.
    <Exceptions>
      Raises xmlrpclib Fault objects with fault codes:
        FAULTCODE_INVALIDREQUEST if a the provided username is not a string
          specifying a valid (existing) account username.
    <Returns>
      An string that represents DATA encrypted by (seattlelib) rsa.r2py's
      rsa_encrypt() function. DATA is a string that is the concatenation of
      a random string of 0-9a-fA-F of fixed length, an exclamation mark, and
      the API key.
      
      For example, DATA may be the following string:
        l28yDKLQGqhqdfDquDq0433!AD98OF2308Q9RYFHDHKJAC
      where
        AD98OF2308Q9RYFHDHKJAC
      is the API key.
      
      Note that this random data being prepended is just a dirty workaround for
      the lack of random padding being used by the encryption format offered by
      rsa.r2py or other repy libraries. This should be changed after a repy
      implementation of PKCS#1 is available.
    """
        try:
            assertions.assert_str(username)
        except AssertionError:
            raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST,
                                  "Username must be a string.")

        try:
            geniuser = interface.get_user_without_password(username)
        except DoesNotExistError:
            raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST,
                                  "Username does not exist.")

        # Don't change the number of bytes of random data without changing the API
        # spec and the xmlrpc client.
        randstring = ''.join(
            random.sample(string.letters + string.digits,
                          ENCRYPTED_API_KEY_PADDING_BYTES))
        data = randstring + "!" + geniuser.api_key
        data = str(
            data
        )  # make sure it's type str, not unicode, as required by rsa_encrypt
        user_pubkey_dict = rsa_string_to_publickey(geniuser.user_pubkey)
        encrypted_data = rsa_encrypt(data, user_pubkey_dict)
        # rsa_encrypt returns returns a string with an extra space in the front.
        encrypted_data = encrypted_data.strip()
        # If the encrypted_data is more than one "block" long, something odd is
        # going on and there may be no padding applied to one or more encrypted
        # blocks.
        if ' ' in encrypted_data:
            raise InternalError(
                "The encrypted_data to be returned by get_encrypted_api_key() "
                + "was more than one block long. user: "******" encrypted_data: " + encrypted_data)
        return encrypted_data
Exemple #29
0
 def boom(self):
     raise xmlrpclib.Fault(1, "boom")
"""Simple XML-RPC Server.