def gethttpdigestauth(self, si, wwwauthorize=None):

        # Check the nonce cache to see if we've used this user before
        user = [self.user, si.user][self.user == ""]
        pswd = [self.pswd, si.pswd][self.pswd == ""]
        details = None
        if user in self.manager.digestCache:
            details = self.manager.digestCache[user]
        else:
            http = SmartHTTPConnection(si.host, si.port, si.ssl)
            try:
                http.request("OPTIONS", self.getURI(si))

                response = http.getresponse()

            finally:
                http.close()

            if response.status == 401:

                wwwauthorize = response.msg.getheaders("WWW-Authenticate")
                for item in wwwauthorize:
                    if not item.startswith("digest "):
                        continue
                    wwwauthorize = item[7:]
                    def unq(s):
                        if s[0] == s[-1] == '"':
                            return s[1:-1]
                        return s
                    parts = wwwauthorize.split(',')

                    details = {}

                    for (k, v) in [p.split('=', 1) for p in parts]:
                        details[k.strip()] = unq(v.strip())

                    self.manager.digestCache[user] = details
                    break

        if details:
            digest = calcResponse(
                calcHA1(details.get('algorithm'), user, details.get('realm'), pswd, details.get('nonce'), details.get('cnonce')),
                details.get('algorithm'), details.get('nonce'), details.get('nc'), details.get('cnonce'), details.get('qop'), self.method, self.getURI(si), None
            )

            if details.get('qop'):
                response = ('Digest username="******", realm="%s", '
                        'nonce="%s", uri="%s", '
                        'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' % (user, details.get('realm'), details.get('nonce'), self.getURI(si), digest, details.get('algorithm'), details.get('cnonce'), details.get('qop'), details.get('nc'),))
            else:
                response = ('Digest username="******", realm="%s", '
                        'nonce="%s", uri="%s", '
                        'response=%s, algorithm=%s' % (user, details.get('realm'), details.get('nonce'), self.getURI(si), digest, details.get('algorithm'),))

            return response
        else:
            return ""
    def dorequest(self, req, details=False, doverify=True, forceverify=False, stats=None, etags=None, label="", count=1):

        req.count = count

        if isinstance(req, pause):
            # Useful for pausing at a particular point
            print "Paused"
            sys.stdin.readline()
            return True, "", None, None

        if len(req.missingFeatures()) != 0:
            return True, "", None, None
        if len(req.excludedFeatures()) != 0:
            return True, "", None, None

        # Special check for DELETEALL
        if req.method == "DELETEALL":
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                hrefs = self.dofindall(collection, label="%s | %s" % (label, "DELETEALL"))
                if not self.dodeleteall(hrefs, label="%s | %s" % (label, "DELETEALL")):
                    return False, "DELETEALL failed for: {r}".format(r=ruri), None, None
            return True, "", None, None

        # Special for delay
        elif req.method == "DELAY":
            # self.ruri contains a numeric delay in seconds
            delay = int(req.ruri)
            starttime = time.time()
            while (time.time() < starttime + delay):
                pass
            return True, "", None, None

        # Special for GETNEW
        elif req.method == "GETNEW":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(collection, label=label)
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            req.method = "GET"
            req.ruri = "$"

        # Special for FINDNEW
        elif req.method == "FINDNEW":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(collection, label=label)
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            return True, "", None, None

        # Special for GETOTHER
        elif req.method == "GETOTHER":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(collection, label=label, other=True)
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            req.method = "GET"
            req.ruri = "$"

        # Special check for WAITCOUNT
        elif req.method.startswith("WAITCOUNT"):
            count = int(req.method[10:])
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                waitresult, waitdetails = self.dowaitcount(collection, count, label=label)
                if not waitresult:
                    return False, "Count did not change: {w}".format(w=waitdetails), None, None
            else:
                return True, "", None, None

        # Special check for WAITDELETEALL
        elif req.method.startswith("WAITDELETEALL"):
            count = int(req.method[len("WAITDELETEALL"):])
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                waitresult, waitdetails = self.dowaitcount(collection, count, label=label)
                if waitresult:
                    hrefs = self.dofindall(collection, label="%s | %s" % (label, "DELETEALL"))
                    self.dodeleteall(hrefs, label="%s | %s" % (label, "DELETEALL"))
                else:
                    return False, "Count did not change: {w}".format(w=waitdetails), None, None
            else:
                return True, "", None, None

        result = True
        resulttxt = ""
        response = None
        respdata = None

        method = req.method
        uri = req.getURI(self.manager.server_info)
        if (uri == "$"):
            uri = self.grabbedlocation
        headers = req.getHeaders(self.manager.server_info)
        data = req.getData()

        # Cache delayed delete
        if req.end_delete:
            self.end_deletes.append((uri, req.user, req.pswd))

        if details:
            resulttxt += "        %s: %s\n" % (method, uri)

        # Special for GETCHANGED
        if req.method == "GETCHANGED":
            if not self.dowaitchanged(
                uri, etags[uri], req.user, req.pswd,
                label=label
            ):
                return False, "Resource did not change", None, None
            method = "GET"

        # Start request timer if required
        if stats:
            stats.startTimer()

        # Do the http request
        http = SmartHTTPConnection(req.host, req.port, self.manager.server_info.ssl)

        if 'User-Agent' not in headers and label is not None:
            headers['User-Agent'] = label.encode("utf-8")

        try:
            puri = list(urlparse.urlparse(uri))
            if req.ruri_quote:
                puri[2] = urllib.quote(puri[2])
            quri = urlparse.urlunparse(puri)

            http.request(method, quri, data, headers)

            response = http.getresponse()

            respdata = None
            respdata = response.read()

        finally:
            http.close()

            # Stop request timer before verification
            if stats:
                stats.endTimer()

        if doverify and (respdata != None):
            result, txt = self.verifyrequest(req, uri, response, respdata)
            resulttxt += txt
        elif forceverify:
            result = (response.status / 100 == 2)
            if not result:
                resulttxt += "Status Code Error: %d" % response.status

        if req.print_request or (self.manager.print_request_response_on_error and not result):
            resulttxt += "\n-------BEGIN:REQUEST-------\n"
            resulttxt += http.requestData
            resulttxt += "\n--------END:REQUEST--------\n"

        if req.print_response or (self.manager.print_request_response_on_error and not result):
            resulttxt += "\n-------BEGIN:RESPONSE-------\n"
            resulttxt += "%s %s %s\n" % (getVersionStringFromResponse(response), response.status, response.reason,)
            resulttxt += str(response.msg) + "\n" + respdata
            resulttxt += "\n--------END:RESPONSE--------\n"

        if etags is not None and req.method == "GET":
            hdrs = response.msg.getheaders("Etag")
            if hdrs:
                etags[uri] = hdrs[0].encode("utf-8")

        if req.graburi:
            self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})

        if req.grabcount:
            ctr = None
            if result and (response is not None) and (response.status == 207) and (respdata is not None):
                tree = ElementTree(file=StringIO(respdata))
                ctr = len(tree.findall("{DAV:}response")) - 1

            if ctr == None or ctr == -1:
                result = False
                resulttxt += "\nCould not count resources in response\n"
            else:
                self.manager.server_info.addextrasubs({req.grabcount: str(ctr)})

        if req.grabheader:
            for hdrname, variable in req.grabheader:
                hdrs = response.msg.getheaders(hdrname)
                if hdrs:
                    self.manager.server_info.addextrasubs({variable: hdrs[0].encode("utf-8")})
                else:
                    result = False
                    resulttxt += "\nHeader %s was not extracted from response\n" % (hdrname,)

        if req.grabproperty:
            if response.status == 207:
                for propname, variable in req.grabproperty:
                    # grab the property here
                    propvalue = self.extractProperty(propname, respdata)
                    if propvalue == None:
                        result = False
                        resulttxt += "\nProperty %s was not extracted from multistatus response\n" % (propname,)
                    else:
                        self.manager.server_info.addextrasubs({variable: propvalue.encode("utf-8")})

        if req.grabelement:
            for item in req.grabelement:
                if len(item) == 2:
                    elementpath, variables = item
                    parent = None
                else:
                    elementpath, parent, variables = item
                    parent = self.manager.server_info.extrasubs(parent)
                # grab the property here
                elementvalues = self.extractElements(elementpath, parent, respdata)
                if elementvalues == None:
                    result = False
                    resulttxt += "\nElement %s was not extracted from response\n" % (elementpath,)
                elif len(variables) != len(elementvalues):
                    result = False
                    resulttxt += "\n%d found but expecting %d for element %s from response\n" % (len(elementvalues), len(variables), elementpath,)
                else:
                    for variable, elementvalue in zip(variables, elementvalues):
                        self.manager.server_info.addextrasubs({variable: elementvalue.encode("utf-8") if elementvalue else ""})

        if req.grabjson:
            for pointer, variables in req.grabjson:
                # grab the JSON value here
                pointervalues = self.extractPointer(pointer, respdata)
                if pointervalues == None:
                    result = False
                    resulttxt += "\Pointer %s was not extracted from response\n" % (pointer,)
                elif len(variables) != len(pointervalues):
                    result = False
                    resulttxt += "\n%d found but expecting %d for pointer %s from response\n" % (len(pointervalues), len(variables), pointer,)
                else:
                    for variable, pointervalue in zip(variables, pointervalues):
                        self.manager.server_info.addextrasubs({variable: pointervalue.encode("utf-8") if pointervalue else ""})

        if req.grabcalprop:
            for propname, variable in req.grabcalprop:
                # grab the property here
                propname = self.manager.server_info.subs(propname)
                propname = self.manager.server_info.extrasubs(propname)
                propvalue = self.extractCalProperty(propname, respdata)
                if propvalue == None:
                    result = False
                    resulttxt += "\nCalendar property %s was not extracted from response\n" % (propname,)
                else:
                    self.manager.server_info.addextrasubs({variable: propvalue.encode("utf-8")})

        if req.grabcalparam:
            for paramname, variable in req.grabcalparam:
                # grab the property here
                paramname = self.manager.server_info.subs(paramname)
                paramname = self.manager.server_info.extrasubs(paramname)
                paramvalue = self.extractCalParameter(paramname, respdata)
                if paramvalue == None:
                    result = False
                    resulttxt += "\nCalendar Parameter %s was not extracted from response\n" % (paramname,)
                else:
                    self.manager.server_info.addextrasubs({variable: paramvalue.encode("utf-8")})

        return result, resulttxt, response, respdata
Exemple #3
0
    def gethttpdigestauth(self, si, wwwauthorize=None):

        # Check the nonce cache to see if we've used this user before, or if the nonce is more than 5 minutes old
        user = [self.user, si.user][self.user == ""]
        pswd = [self.pswd, si.pswd][self.pswd == ""]
        details = None
        if user in self.manager.digestCache and self.manager.digestCache[user][
                "max-nonce-time"] > time.time():
            details = self.manager.digestCache[user]
        else:
            # Redo digest auth from scratch to get a new nonce etc
            http = SmartHTTPConnection(si.host, si.port, si.ssl, si.afunix)
            try:
                puri = list(urlparse.urlparse(self.getURI(si)))
                puri[2] = urllib.quote(puri[2])
                quri = urlparse.urlunparse(puri)
                http.request("OPTIONS", quri)

                response = http.getresponse()

            finally:
                http.close()

            if response.status == 401:

                wwwauthorize = response.msg.getheaders("WWW-Authenticate")
                for item in wwwauthorize:
                    if not item.lower().startswith("digest "):
                        continue
                    wwwauthorize = item[7:]

                    def unq(s):
                        if s[0] == s[-1] == '"':
                            return s[1:-1]
                        return s

                    parts = wwwauthorize.split(',')

                    details = {}

                    for (k, v) in [p.split('=', 1) for p in parts]:
                        details[k.strip()] = unq(v.strip())

                    details["max-nonce-time"] = time.time() + 600
                    self.manager.digestCache[user] = details
                    break

        if details:
            if details.get('qop'):
                if self.nc.get(details.get('nonce')) is None:
                    self.nc[details.get('nonce')] = 1
                else:
                    self.nc[details.get('nonce')] += 1
                details['nc'] = "%08x" % self.nc[details.get('nonce')]
                if details.get('cnonce') is None:
                    details['cnonce'] = "D4AAE4FF-ADA1-4149-BFE2-B506F9264318"

            digest = calcResponse(
                calcHA1(details.get('algorithm', 'md5'), user,
                        details.get('realm'), pswd,
                        details.get('nonce'), details.get('cnonce')),
                details.get('algorithm', 'md5'), details.get('nonce'),
                details.get('nc'), details.get('cnonce'), details.get('qop'),
                self.method, self.getURI(si), None)

            if details.get('qop'):
                response = (
                    'Digest username="******", realm="%s", '
                    'nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' % (
                        user,
                        details.get('realm'),
                        details.get('nonce'),
                        self.getURI(si),
                        digest,
                        details.get('algorithm', 'md5'),
                        details.get('cnonce'),
                        details.get('qop'),
                        details.get('nc'),
                    ))
            else:
                response = ('Digest username="******", realm="%s", '
                            'nonce="%s", uri="%s", '
                            'response=%s, algorithm=%s' % (
                                user,
                                details.get('realm'),
                                details.get('nonce'),
                                self.getURI(si),
                                digest,
                                details.get('algorithm'),
                            ))

            return response
        else:
            return ""
Exemple #4
0
    def dorequest(self, req, details=False, doverify=True, forceverify=False, stats=None, etags=None, label="", count=1):

        req.count = count

        if isinstance(req, pause):
            # Useful for pausing at a particular point
            print "Paused"
            sys.stdin.readline()
            return True, "", None, None

        if len(req.missingFeatures()) != 0:
            return True, "", None, None
        if len(req.excludedFeatures()) != 0:
            return True, "", None, None

        # Special check for DELETEALL
        if req.method == "DELETEALL":
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                hrefs = self.dofindall(req, collection, label="%s | %s" % (label, "DELETEALL"))
                if not self.dodeleteall(req, hrefs, label="%s | %s" % (label, "DELETEALL")):
                    return False, "DELETEALL failed for: {r}".format(r=ruri), None, None
            return True, "", None, None

        # Special for delay
        elif req.method == "DELAY":
            # self.ruri contains a numeric delay in seconds
            delay = int(req.ruri)
            starttime = time.time()
            while (time.time() < starttime + delay):
                pass
            return True, "", None, None

        # Special for GETNEW
        elif req.method == "GETNEW":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(req, collection, label=label)
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            req.method = "GET"
            req.ruri = "$"

        # Special for FINDNEW
        elif req.method == "FINDNEW":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(req, collection, label=label)
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            return True, "", None, None

        # Special for GETOTHER
        elif req.method == "GETOTHER":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(req, collection, label=label, other=True)
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            req.method = "GET"
            req.ruri = "$"

        # Special for GETCONTAINS
        elif req.method.startswith("GETCONTAINS"):
            match = req.method[12:]
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindcontains(req, collection, match, label=label)
            if not self.grabbedlocation:
                return False, "No matching resource", None, None
            if req.graburi:
                self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})
            req.method = "GET"
            req.ruri = "$"

        # Special check for WAITCOUNT
        elif req.method.startswith("WAITCOUNT"):
            count = int(req.method[10:])
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                waitresult, waitdetails = self.dowaitcount(req, collection, count, label=label)
                if not waitresult:
                    return False, "Count did not change: {w}".format(w=waitdetails), None, None
            else:
                return True, "", None, None

        # Special check for WAITDELETEALL
        elif req.method.startswith("WAITDELETEALL"):
            count = int(req.method[len("WAITDELETEALL"):])
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                waitresult, waitdetails = self.dowaitcount(req, collection, count, label=label)
                if waitresult:
                    hrefs = self.dofindall(req, collection, label="%s | %s" % (label, "DELETEALL"))
                    self.dodeleteall(req, hrefs, label="%s | %s" % (label, "DELETEALL"))
                else:
                    return False, "Count did not change: {w}".format(w=waitdetails), None, None
            else:
                return True, "", None, None

        result = True
        resulttxt = ""
        response = None
        respdata = None

        method = req.method
        uri = req.getURI(self.manager.server_info)
        if (uri == "$"):
            uri = self.grabbedlocation
        headers = req.getHeaders(self.manager.server_info)
        data = req.getData()

        # Cache delayed delete
        if req.end_delete:
            self.end_deletes.append((uri, req,))

        if details:
            resulttxt += "        %s: %s\n" % (method, uri)

        # Special for GETCHANGED
        if req.method == "GETCHANGED":
            if not self.dowaitchanged(
                req,
                uri, etags[uri], req.user, req.pswd,
                label=label
            ):
                return False, "Resource did not change", None, None
            method = "GET"

        # Start request timer if required
        if stats:
            stats.startTimer()

        # Do the http request
        http = SmartHTTPConnection(
            req.host,
            req.port,
            self.manager.server_info.ssl,
            afunix=req.afunix,
            cert=os.path.join(self.manager.server_info.certdir, req.cert) if req.cert else None
        )

        if 'User-Agent' not in headers and label is not None:
            headers['User-Agent'] = label.encode("utf-8")

        try:
            puri = list(urlparse.urlparse(uri))
            if req.ruri_quote:
                puri[2] = urllib.quote(puri[2])
            quri = urlparse.urlunparse(puri)

            http.request(method, quri, data, headers)

            response = http.getresponse()

            respdata = None
            respdata = response.read()

        finally:
            http.close()

            # Stop request timer before verification
            if stats:
                stats.endTimer()

        if doverify and (respdata is not None):
            result, txt = self.verifyrequest(req, uri, response, respdata)
            resulttxt += txt
        elif forceverify:
            result = (response.status / 100 == 2)
            if not result:
                resulttxt += "Status Code Error: %d" % response.status

        if req.print_request or (self.manager.print_request_response_on_error and not result and not req.wait_for_success):
            requesttxt = "\n-------BEGIN:REQUEST-------\n"
            requesttxt += http.requestData
            requesttxt += "\n--------END:REQUEST--------\n"
            self.manager.message("protocol", requesttxt)

        if req.print_response or (self.manager.print_request_response_on_error and not result and not req.wait_for_success):
            responsetxt = "\n-------BEGIN:RESPONSE-------\n"
            responsetxt += "%s %s %s\n" % (getVersionStringFromResponse(response), response.status, response.reason,)
            responsetxt += str(response.msg) + "\n" + respdata
            responsetxt += "\n--------END:RESPONSE--------\n"
            self.manager.message("protocol", responsetxt)

        if etags is not None and req.method == "GET":
            hdrs = response.msg.getheaders("Etag")
            if hdrs:
                etags[uri] = hdrs[0].encode("utf-8")

        if req.graburi:
            self.manager.server_info.addextrasubs({req.graburi: self.grabbedlocation})

        if req.grabcount:
            ctr = None
            if result and (response is not None) and (response.status == 207) and (respdata is not None):
                tree = ElementTree(file=StringIO(respdata))
                ctr = len(tree.findall("{DAV:}response")) - 1

            if ctr is None or ctr == -1:
                result = False
                resulttxt += "\nCould not count resources in response\n"
            else:
                self.manager.server_info.addextrasubs({req.grabcount: str(ctr)})

        if req.grabheader:
            for hdrname, variable in req.grabheader:
                hdrs = response.msg.getheaders(hdrname)
                if hdrs:
                    self.manager.server_info.addextrasubs({variable: hdrs[0].encode("utf-8")})
                else:
                    result = False
                    resulttxt += "\nHeader %s was not extracted from response\n" % (hdrname,)

        if req.grabproperty:
            if response.status == 207:
                for propname, variable in req.grabproperty:
                    # grab the property here
                    propvalue = self.extractProperty(propname, respdata)
                    if propvalue is None:
                        result = False
                        resulttxt += "\nProperty %s was not extracted from multistatus response\n" % (propname,)
                    else:
                        self.manager.server_info.addextrasubs({variable: propvalue.encode("utf-8")})

        if req.grabelement:
            for item in req.grabelement:
                if len(item) == 2:
                    elementpath, variables = item
                    parent = None
                else:
                    elementpath, parent, variables = item
                    parent = self.manager.server_info.extrasubs(parent)
                # grab the property here
                elementvalues = self.extractElements(elementpath, parent, respdata)
                if elementvalues is None:
                    result = False
                    resulttxt += "\nElement %s was not extracted from response\n" % (elementpath,)
                elif len(variables) != len(elementvalues):
                    result = False
                    resulttxt += "\n%d found but expecting %d for element %s from response\n" % (len(elementvalues), len(variables), elementpath,)
                else:
                    for variable, elementvalue in zip(variables, elementvalues):
                        self.manager.server_info.addextrasubs({variable: elementvalue.encode("utf-8") if elementvalue else ""})

        if req.grabjson:
            for pointer, variables in req.grabjson:
                # grab the JSON value here
                pointervalues = self.extractPointer(pointer, respdata)
                if pointervalues is None:
                    result = False
                    resulttxt += "\Pointer %s was not extracted from response\n" % (pointer,)
                elif len(variables) != len(pointervalues):
                    result = False
                    resulttxt += "\n%d found but expecting %d for pointer %s from response\n" % (len(pointervalues), len(variables), pointer,)
                else:
                    for variable, pointervalue in zip(variables, pointervalues):
                        self.manager.server_info.addextrasubs({variable: pointervalue.encode("utf-8") if pointervalue else ""})

        if req.grabcalprop:
            for propname, variable in req.grabcalprop:
                # grab the property here
                propname = self.manager.server_info.subs(propname)
                propname = self.manager.server_info.extrasubs(propname)
                propvalue = self.extractCalProperty(propname, respdata)
                if propvalue is None:
                    result = False
                    resulttxt += "\nCalendar property %s was not extracted from response\n" % (propname,)
                else:
                    self.manager.server_info.addextrasubs({variable: propvalue.encode("utf-8")})

        if req.grabcalparam:
            for paramname, variable in req.grabcalparam:
                # grab the property here
                paramname = self.manager.server_info.subs(paramname)
                paramname = self.manager.server_info.extrasubs(paramname)
                paramvalue = self.extractCalParameter(paramname, respdata)
                if paramvalue is None:
                    result = False
                    resulttxt += "\nCalendar Parameter %s was not extracted from response\n" % (paramname,)
                else:
                    self.manager.server_info.addextrasubs({variable: paramvalue.encode("utf-8")})

        return result, resulttxt, response, respdata
    def dorequest( self, req, details=False, doverify = True, forceverify = False, stats = None, etags = None, label = "", count = 1 ):
        
        req.count = count

        if isinstance(req, pause):
            # Useful for pausing at a particular point
            print "Paused"
            sys.stdin.readline()
            return True, "", None, None
            
        if len(req.missingFeatures()) != 0:
            #self.manager.log(manager.LOG_HIGH, "[IGNORED]")
            #self.manager.log(manager.LOG_HIGH, "      Missing features: %s" % (", ".join(sorted(req.missingFeatures())),))
            return True, "", None, None
        if len(req.excludedFeatures()) != 0:
            #self.manager.log(manager.LOG_HIGH, "[IGNORED]")
            #self.manager.log(manager.LOG_HIGH, "      Excluded features: %s" % (", ".join(sorted(req.excludedFeatures())),))
            return True, "", None, None

        # Special check for DELETEALL
        if req.method == "DELETEALL":
            for ruri in req.ruris:
                collection = (ruri, req.user, req.pswd)
                hrefs = self.dofindall(collection, label="%s | %s" % (label, "DELETEALL"))
                self.dodeleteall(hrefs, label="%s | %s" % (label, "DELETEALL"))
            return True, "", None, None
        
        # Special for delay
        elif req.method == "DELAY":
            # self.ruri contains a numeric delay in seconds
            delay = int(req.ruri)
            starttime = time.time()
            while (time.time() < starttime + delay):
                pass
            return True, "", None, None

        # Special for GETNEW
        elif req.method == "GETNEW":
            collection = (req.ruri, req.user, req.pswd)
            self.grabbedlocation = self.dofindnew(collection, label=label)
            req.method = "GET"
            req.ruri = "$"
            
        # Special check for WAITCOUNT
        elif req.method.startswith("WAITCOUNT"):
            count = int(req.method[10:])
            collection = (req.ruri, req.user, req.pswd)
            if self.dowaitcount(collection, count, label=label):
                return True, "", None, None
            else:
                return False, "Count did not change", None, None

        elif req.method == "BREAK":
            # Useful for setting a break point
            return True, "", None, None

        elif req.method == "PAUSE":
            # Useful for pausing at a particular point
            print "Paused"
            sys.stdin.readline()
            return True, "", None, None

        result = True;
        resulttxt = ""
        response = None
        respdata = None

        method = req.method
        uri = req.getURI( self.manager.server_info )
        if (uri == "$"):
            uri = self.grabbedlocation
        headers = req.getHeaders( self.manager.server_info )
        data = req.getData()
        
        # Cache delayed delete
        if req.end_delete:
            self.end_deletes.append( (uri, req.user, req.pswd) )

        if details:
            resulttxt += "        %s: %s\n" % ( method, uri )

        # Special for GETCHANGED
        if req.method == "GETCHANGED":
            if not self.dowaitchanged(uri, etags[uri], req.user, req.pswd,
                label=label):
                return False, "Resource did not change", None, None
            method = "GET"

        # Start request timer if required
        if stats:
            stats.startTimer()

        # Do the http request
        http = SmartHTTPConnection( self.manager.server_info.host, self.manager.server_info.port, self.manager.server_info.ssl )

        if not headers.has_key('User-Agent') and label is not None:
            headers['User-Agent'] = label.encode("utf-8")

        try:
            #self.manager.log(manager.LOG_LOW, "Sending request")
            http.request( method, uri, data, headers )
            #self.manager.log(manager.LOG_LOW, "Sent request")
        
            response = http.getresponse()
        
            respdata = None
            respdata = response.read()
            #self.manager.log(manager.LOG_LOW, "Read response")

        finally:
            http.close()
        
            # Stop request timer before verification
            if stats:
                stats.endTimer()

        if doverify and (respdata != None):
            result, txt = self.verifyrequest( req, uri, response, respdata )
            resulttxt += txt
        elif forceverify:
            result = (response.status / 100 == 2)
            if not result:
                resulttxt += "Status Code Error: %d" % response.status
        
        if req.print_response:
            resulttxt += "\n-------BEGIN:RESPONSE-------\n"
            resulttxt += "Status = %d\n" % response.status
            resulttxt += str(response.msg) + "\n" + respdata
            resulttxt += "\n--------END:RESPONSE--------\n"
        
        if etags is not None and req.method == "GET":
            hdrs = response.msg.getheaders("Etag")
            if hdrs:
                etags[uri] = hdrs[0].encode("utf-8")

        if req.grabheader:
            for hdrname, variable in req.grabheader:
                hdrs = response.msg.getheaders(hdrname)
                if hdrs:
                    self.manager.server_info.addextrasubs({variable: hdrs[0].encode("utf-8")})
                else:
                    result = False
                    resulttxt += "\nHeader %s was not extracted from response\n" % (hdrname,)

        if req.grabproperty:
            if response.status == 207:
                for propname, variable in req.grabproperty:
                    # grab the property here
                    propvalue = self.extractProperty(propname, respdata)
                    if propvalue == None:
                        result = False
                        resulttxt += "\nProperty %s was not extracted from multistatus response\n" % (propname,)
                    else:
                        self.manager.server_info.addextrasubs({variable: propvalue.encode("utf-8")})

        if req.grabelement:
            for elementpath, variables in req.grabelement:
                # grab the property here
                elementvalues = self.extractElements(elementpath, respdata)
                if elementvalues == None:
                    result = False
                    resulttxt += "\nElement %s was not extracted from response\n" % (elementpath,)
                elif len(variables) != len(elementvalues):
                    result = False
                    resulttxt += "\n%d found but expecting %d for element %s from response\n" % (len(elementvalues), len(variables), elementpath,)
                else:
                    for variable, elementvalue in zip(variables, elementvalues):
                        self.manager.server_info.addextrasubs({variable: elementvalue.encode("utf-8") if elementvalue else ""})

        return result, resulttxt, response, respdata
Exemple #6
0
    def gethttpdigestauth(self, si, wwwauthorize=None):

        # Check the nonce cache to see if we've used this user before, or if the nonce is more than 5 minutes old
        user = [self.user, si.user][self.user == ""]
        pswd = [self.pswd, si.pswd][self.pswd == ""]
        details = None
        if user in self.manager.digestCache and self.manager.digestCache[user]["max-nonce-time"] > time.time():
            details = self.manager.digestCache[user]
        else:
            # Redo digest auth from scratch to get a new nonce etc
            http = SmartHTTPConnection(si.host, si.port, si.ssl, si.afunix)
            try:
                puri = list(urlparse.urlparse(self.getURI(si)))
                puri[2] = urllib.quote(puri[2])
                quri = urlparse.urlunparse(puri)
                http.request("OPTIONS", quri)

                response = http.getresponse()

            finally:
                http.close()

            if response.status == 401:

                wwwauthorize = response.msg.getheaders("WWW-Authenticate")
                for item in wwwauthorize:
                    if not item.lower().startswith("digest "):
                        continue
                    wwwauthorize = item[7:]
                    def unq(s):
                        if s[0] == s[-1] == '"':
                            return s[1:-1]
                        return s
                    parts = wwwauthorize.split(',')

                    details = {}

                    for (k, v) in [p.split('=', 1) for p in parts]:
                        details[k.strip()] = unq(v.strip())

                    details["max-nonce-time"] = time.time() + 600
                    self.manager.digestCache[user] = details
                    break

        if details:
            if details.get('qop'):
                if self.nc.get(details.get('nonce')) is None:
                    self.nc[details.get('nonce')] = 1
                else:
                    self.nc[details.get('nonce')] += 1
                details['nc'] = "%08x" % self.nc[details.get('nonce')]
                if details.get('cnonce') is None:
                    details['cnonce'] = "D4AAE4FF-ADA1-4149-BFE2-B506F9264318"

            digest = calcResponse(
                calcHA1(details.get('algorithm', 'md5'), user, details.get('realm'), pswd, details.get('nonce'), details.get('cnonce')),
                details.get('algorithm', 'md5'), details.get('nonce'), details.get('nc'), details.get('cnonce'), details.get('qop'), self.method, self.getURI(si), None
            )

            if details.get('qop'):
                response = (
                    'Digest username="******", realm="%s", '
                    'nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' %
                    (user, details.get('realm'), details.get('nonce'), self.getURI(si), digest, details.get('algorithm', 'md5'), details.get('cnonce'), details.get('qop'), details.get('nc'),)
                )
            else:
                response = (
                    'Digest username="******", realm="%s", '
                    'nonce="%s", uri="%s", '
                    'response=%s, algorithm=%s' %
                    (user, details.get('realm'), details.get('nonce'), self.getURI(si), digest, details.get('algorithm'),)
                )

            return response
        else:
            return ""