aboutsummaryrefslogtreecommitdiffstats
path: root/libpathod/pathoc.py
diff options
context:
space:
mode:
Diffstat (limited to 'libpathod/pathoc.py')
-rw-r--r--libpathod/pathoc.py170
1 files changed, 132 insertions, 38 deletions
diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py
index 938dbeba..e7aff520 100644
--- a/libpathod/pathoc.py
+++ b/libpathod/pathoc.py
@@ -1,10 +1,17 @@
-import sys, os
+import sys
+import os
+import hashlib
+import random
from netlib import tcp, http, certutils
import netlib.utils
-import language, utils
+
+import language
+import utils
import OpenSSL.crypto
-class PathocError(Exception): pass
+
+class PathocError(Exception):
+ pass
class SSLInfo:
@@ -13,8 +20,17 @@ class SSLInfo:
class Response:
- def __init__(self, httpversion, status_code, msg, headers, content, sslinfo):
- self.httpversion, self.status_code, self.msg = httpversion, status_code, msg
+ def __init__(
+ self,
+ httpversion,
+ status_code,
+ msg,
+ headers,
+ content,
+ sslinfo
+ ):
+ self.httpversion, self.status_code = httpversion, status_code
+ self.msg = msg
self.headers, self.content = headers, content
self.sslinfo = sslinfo
@@ -23,7 +39,14 @@ class Response:
class Pathoc(tcp.TCPClient):
- def __init__(self, address, ssl=None, sni=None, sslversion=4, clientcert=None, ciphers=None):
+ def __init__(
+ self,
+ address,
+ ssl=None,
+ sni=None,
+ sslversion=4,
+ clientcert=None,
+ ciphers=None):
tcp.TCPClient.__init__(self, address)
self.settings = dict(
staticdir = os.getcwd(),
@@ -36,9 +59,9 @@ class Pathoc(tcp.TCPClient):
def http_connect(self, connect_to):
self.wfile.write(
- 'CONNECT %s:%s HTTP/1.1\r\n'%tuple(connect_to) +
- '\r\n'
- )
+ 'CONNECT %s:%s HTTP/1.1\r\n'%tuple(connect_to) +
+ '\r\n'
+ )
self.wfile.flush()
l = self.rfile.readline()
if not l:
@@ -60,17 +83,17 @@ class Pathoc(tcp.TCPClient):
if self.ssl:
try:
self.convert_to_ssl(
- sni=self.sni,
- cert=self.clientcert,
- method=self.sslversion,
- cipher_list = self.ciphers
- )
+ sni=self.sni,
+ cert=self.clientcert,
+ method=self.sslversion,
+ cipher_list = self.ciphers
+ )
except tcp.NetLibError, v:
raise PathocError(str(v))
self.sslinfo = SSLInfo(
- self.connection.get_peer_cert_chain(),
- self.get_current_cipher()
- )
+ self.connection.get_peer_cert_chain(),
+ self.get_current_cipher()
+ )
def request(self, spec):
"""
@@ -79,7 +102,7 @@ class Pathoc(tcp.TCPClient):
May raise language.ParseException, netlib.http.HttpError or
language.FileAccessDenied.
"""
- r = language.parse_request(self.settings, spec)
+ r = language.parse_requests(spec)[0]
language.serve(r, self.wfile, self.settings, self.address.host)
self.wfile.flush()
ret = list(http.read_response(self.rfile, r.method.string(), None))
@@ -87,7 +110,9 @@ class Pathoc(tcp.TCPClient):
return Response(*ret)
def _show_summary(self, fp, httpversion, code, msg, headers, content):
- print >> fp, "<< %s %s: %s bytes"%(code, utils.xrepr(msg), len(content))
+ print >> fp, "<< %s %s: %s bytes"%(
+ code, utils.xrepr(msg), len(content)
+ )
def _show(self, fp, header, data, hexdump):
if hexdump:
@@ -98,7 +123,18 @@ class Pathoc(tcp.TCPClient):
print >> fp, "%s (unprintables escaped):"%header
print >> fp, netlib.utils.cleanBin(data)
- def print_request(self, spec, showreq, showresp, explain, showssl, hexdump, ignorecodes, ignoretimeout, fp=sys.stdout):
+ def print_request(
+ self,
+ r,
+ showreq,
+ showresp,
+ explain,
+ showssl,
+ hexdump,
+ ignorecodes,
+ ignoretimeout,
+ fp=sys.stdout
+ ):
"""
Performs a series of requests, and prints results to the specified
file descriptor.
@@ -113,26 +149,18 @@ class Pathoc(tcp.TCPClient):
Returns True if we have a non-ignored response.
"""
- try:
- r = language.parse_request(self.settings, spec)
- except language.ParseException, v:
- print >> fp, "Error parsing request spec: %s"%v.msg
- print >> fp, v.marked()
- return
- except language.FileAccessDenied, v:
- print >> fp, "File access error: %s"%v
- return
-
- if explain:
- r = r.freeze(self.settings, self.address.host)
-
resp, req = None, None
if showreq:
self.wfile.start_log()
if showresp:
self.rfile.start_log()
try:
- req = language.serve(r, self.wfile, self.settings, self.address.host)
+ req = language.serve(
+ r,
+ self.wfile,
+ self.settings,
+ self.address.host
+ )
self.wfile.flush()
resp = http.read_response(self.rfile, r.method.string(), None)
except http.HttpError, v:
@@ -160,7 +188,7 @@ class Pathoc(tcp.TCPClient):
if resp:
self._show_summary(fp, *resp)
- if self.sslinfo:
+ if showssl and self.sslinfo:
print >> fp, "Cipher: %s, %s bit, %s"%self.sslinfo.cipher
print >> fp, "SSL certificate chain:\n"
for i in self.sslinfo.certchain:
@@ -173,13 +201,15 @@ class Pathoc(tcp.TCPClient):
print >> fp, "%s=%s"%cn,
print >> fp
print >> fp, "\tVersion: %s"%i.get_version()
- print >> fp, "\tValidity: %s - %s"%(i.get_notBefore(),i.get_notAfter())
+ print >> fp, "\tValidity: %s - %s"%(
+ i.get_notBefore(), i.get_notAfter()
+ )
print >> fp, "\tSerial: %s"%i.get_serial_number()
print >> fp, "\tAlgorithm: %s"%i.get_signature_algorithm()
pk = i.get_pubkey()
types = {
- OpenSSL.crypto.TYPE_RSA: "RSA",
- OpenSSL.crypto.TYPE_DSA: "DSA"
+ OpenSSL.crypto.TYPE_RSA: "RSA",
+ OpenSSL.crypto.TYPE_DSA: "DSA"
}
t = types.get(pk.type(), "Uknown")
print >> fp, "\tPubkey: %s bit %s"%(pk.bits(), t)
@@ -190,4 +220,68 @@ class Pathoc(tcp.TCPClient):
return True
+def main(args):
+ memo = set([])
+ trycount = 0
+ try:
+ cnt = 0
+ while 1:
+ if trycount > args.memolimit:
+ print >> sys.stderr, "Memo limit exceeded..."
+ return
+ cnt += 1
+ if args.random:
+ playlist = [random.choice(args.requests)]
+ else:
+ playlist = args.requests
+ p = Pathoc(
+ (args.host, args.port),
+ ssl=args.ssl,
+ sni=args.sni,
+ sslversion=args.sslversion,
+ clientcert=args.clientcert,
+ ciphers=args.ciphers
+ )
+ if args.explain or args.memo:
+ playlist = [
+ i.freeze(p.settings, p.address.host) for i in playlist
+ ]
+ if args.memo:
+ newlist = []
+ for spec in playlist:
+ h = hashlib.sha256(spec.spec()).digest()
+ if h not in memo:
+ memo.add(h)
+ newlist.append(spec)
+ playlist = newlist
+ if not playlist:
+ trycount += 1
+ continue
+
+ trycount = 0
+ try:
+ p.connect(args.connect_to)
+ except (tcp.NetLibError, PathocError), v:
+ print >> sys.stderr, str(v)
+ sys.exit(1)
+ if args.timeout:
+ p.settimeout(args.timeout)
+ for spec in playlist:
+ ret = p.print_request(
+ spec,
+ showreq=args.showreq,
+ showresp=args.showresp,
+ explain=args.explain,
+ showssl=args.showssl,
+ hexdump=args.hexdump,
+ ignorecodes=args.ignorecodes,
+ ignoretimeout=args.ignoretimeout
+ )
+ sys.stdout.flush()
+ if ret and args.oneshot:
+ sys.exit(0)
+ if cnt == args.repeat:
+ break
+ except KeyboardInterrupt:
+ pass