"""
Testbed for figuring out how to write asynchronous HTTPS code.

$Id$

Copyright (C) 2009  Internet Systems Consortium ("ISC")

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""

# Command that may be useful for testing server side of this:
#
#    lynx -post_data -mime_header -source http://127.0.0.1:8000/
#
# Testing the client side of this is more entertaining, both because
# we need to be liberal in what we accept and also because servers do
# wildly different things depending both on HTTP version number and
# options signaled by the client and also on internal details in the
# server context (such as whether the content is static or generated
# by CGI).  It's useful to test against static content, but also to
# test against CGI-generated output, eg, the following trivial script:
#
#    print "Content-Type: text/plain; charset=US-ASCII\r"
#    print "\r"
#    for i in xrange(100):
#      print "%08d" % i, "." * 120, "\r"
#
# At least with Apache 2.0, result of running this differs
# significantly depending on whether client signals HTTP 1.0 or 1.1;
# the latter produces chunked output.

import sys, os, time, socket, asyncore, asynchat, traceback, urlparse
import rpki.async, rpki.sundial

debug = True

want_persistent_client = True
want_persistent_server = True

idle_timeout_default   = rpki.sundial.timedelta(seconds = 60)
active_timeout_default = rpki.sundial.timedelta(seconds = 15)

default_http_version = (1, 0)

class http_message(object):

  software_name = "BalmyBandicoot HTTP test code"

  def __init__(self, version = None, body = None, headers = None):
    self.version = version
    self.body = body
    self.headers = headers
    self.normalize_headers()

  def normalize_headers(self, headers = None):
    if headers is None:
      headers = () if self.headers is None else self.headers.items()
      translate_underscore = True
    else:
      translate_underscore = False
    result = {}
    for k,v in headers:
      if translate_underscore:
        k = k.replace("_", "-")
      k = "-".join(s.capitalize() for s in k.split("-"))
      v = v.strip()
      if k in result:
        result[k] += ", " + v
      else:
        result[k] = v
    self.headers = result

  @classmethod
  def parse_from_wire(cls, headers):
    self = cls()
    headers = headers.split("\r\n")
    self.parse_first_line(*headers.pop(0).split(None, 2))
    for i in xrange(len(headers) - 2, -1, -1):
      if headers[i + 1][0].isspace():
        headers[i] += headers[i + 1]
        del headers[i + 1]
    self.normalize_headers([h.split(":", 1) for h in headers])
    return self

  def format(self):
    s = self.format_first_line()
    if self.body is not None:
      assert isinstance(self.body, str)
      self.headers["Content-Length"] = len(self.body)
    for kv in self.headers.iteritems():
      s += "%s: %s\r\n" % kv
    s += "\r\n"
    if self.body is not None:
      s += self.body
    return s

  def __str__(self):
    return self.format()

  def parse_version(self, version):
    if version[:5] != "HTTP/":
      raise RuntimeError, "Couldn't parse version %s" % version
    self.version = tuple(int(i) for i in version[5:].split("."))

  def persistent(self):
    c = self.headers.get("Connection")
    if self.version == (1, 1):
      return c is None or "close" not in c.lower()
    elif self.version == (1, 0):
      return c is not None and "keep-alive" in c.lower()
    else:
      return False

class http_request(http_message):

  def __init__(self, cmd = None, path = None, version = default_http_version, body = None, **headers):
    if cmd is not None and cmd != "POST" and body is not None:
      raise RuntimeError
    http_message.__init__(self, version = version, body = body, headers = headers)
    self.cmd = cmd
    self.path = path

  def parse_first_line(self, cmd, path, version):
    self.parse_version(version)
    self.cmd = cmd
    self.path = path

  def format_first_line(self):
    self.headers.setdefault("User-Agent", self.software_name)
    return "%s %s HTTP/%d.%d\r\n" % (self.cmd, self.path, self.version[0], self.version[1])

class http_response(http_message):

  def __init__(self, code = None, reason = None, version = default_http_version, body = None, **headers):
    http_message.__init__(self, version = version, body = body, headers = headers)
    self.code = code
   <style>pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">$Id$</span>

<span class="sd">Copyright (C) 2008  American Registry for Internet Numbers (&quot;ARIN&quot;)</span>

<span class="sd">Permission to use, copy, modify, and distribute this software for any</span>
<span class="sd">purpose with or without fee is hereby granted, provided that the above</span>
<span class="sd">copyright notice and this permission notice appear in all copies.</span>

<span class="sd">THE SOFTWARE IS PROVIDED &quot;AS IS&quot; AND ARIN DISCLAIMS ALL WARRANTIES WITH</span>
<span class="sd">REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY</span>
<span class="sd">AND FITNESS.  IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,</span>
<span class="sd">INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM</span>
<span class="sd">LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE</span>
<span class="sd">OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR</span>
<span class="sd">PERFORMANCE OF THIS SOFTWARE.</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">POW</span><span class="o">,</span> <span class="nn">rpki.x509</span><span class="o">,</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">traceback</span>

<span class="n">key</span> <span class="o">=</span> <span class="n">rpki</span><span class="o">.</span><span class="n">x509</span><span class="o">.</span><span class="n">RSA</span><span class="p">(</span><span class="n">Auto_file</span> <span class="o">=</span> <span class="s2">&quot;biz-certs/Alice-EE.key&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">get_POW</span><span class="p">()</span>
<span class="n">ee</span> <span class="o">=</span> <span class="n">rpki</span><span class="o">.</span><span class="n">x509</span><span class="o">.</span><span class="n">X509</span><span class="p">(</span><span class="n">Auto_file</span> <span class="o">=</span> <span class="s2">&quot;biz-certs/Alice-EE.cer&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">get_POW</span><span class="p">()</span>

<span class="n">ca</span> <span class="o">=</span> <span class="n">rpki</span><span class="o">.</span><span class="n">x509</span><span class="o">.</span><span class="n">X509</span><span class="p">(</span><span class="n">Auto_file</span> <span class="o">=</span> <span class="s2">&quot;biz-certs/Alice-CA.cer&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">get_POW</span><span class="p">()</span>
<span class="n">ta</span> <span class="o">=</span> <span class="n">rpki</span><span class="o">.</span><span class="n">x509</span><span class="o">.</span><span class="n">X509</span><span class="p">(</span><span class="n">Auto_file</span> <span class="o">=</span> <span class="s2">&quot;biz-certs/Alice-Root.cer&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">get_POW</span><span class="p">()</span>

<span class="n">store</span> <span class="o">=</span> <span class="n">POW</span><span class="o">.</span><span class="n">X509Store</span><span class="p">()</span>
<span class="n">store</span><span class="o">.</span><span class="n">addTrust</span><span class="p">(</span><span class="n">ta</span><span class="p">)</span>

<span class="k">if</span> <span class="n">store</span><span class="o">.</span><span class="n">verify</span><span class="p">(</span><span class="n">ca</span><span class="p">):</span>
  <span class="nb">print</span> <span class="s2">&quot;Verified CA&quot;</span>
  <span class="n">store</span><span class="o">.</span><span class="n">addTrust</span><span class="p">(</span><span class="n">ca</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
  <span class="nb">print</span> <span class="s2">&quot;Couldn&#39;t verify CA&quot;</span>

<span class="k">if</span> <span class="n">store</span><span class="o">.</span><span class="n">verify</span><span class="p">(</span><span class="n">ee</span><span class="p">):</span>
  <span class="nb">print</span> <span class="s2">&quot;Verified EE&quot;</span>
  <span class="n">store</span><span class="o">.</span><span class="n">addTrust</span><span class="p">(</span><span class="n">ee</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
  <span class="nb">print</span> <span class="s2">&quot;Couldn&#39;t verify EE&quot;</span>

<span class="n">oid</span> <span class="o">=</span> <span class="s2">&quot;1.2.840.113549.1.9.16.1.24&quot;</span>

<span class="n">plaintext</span> <span class="o">=</span> <span class="s2">&quot;Wombats Are Us&quot;</span>

<span class="k">for</span> <span class="n">args</span> <span class="ow">in</span> <span class="p">((</span><span class="n">ee</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">,</span> <span class="p">[</span><span class="n">ca</span><span class="p">],</span> <span class="p">(),</span> <span class="n">oid</span><span class="p">),</span>
             <span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">,</span> <span class="p">[</span><span class="n">ca</span><span class="p">],</span> <span class="p">(),</span> <span class="n">oid</span><span class="p">,</span> <span class="n">POW</span><span class="o">.</span><span class="n">CMS_NOATTR</span><span class="p">),</span>
             <span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">,</span> <span class="p">[</span><span class="n">ca</span><span class="p">],</span> <span class="p">(),</span> <span class="n">oid</span><span class="p">,</span> <span class="n">POW</span><span class="o">.</span><span class="n">CMS_NOCERTS</span><span class="p">),</span>
             <span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">,</span> <span class="p">[],</span>   <span class="p">(),</span> <span class="n">oid</span><span class="p">),</span>
             <span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">,</span> <span class="p">[],</span>   <span class="p">(),</span> <span class="n">oid</span><span class="p">,</span> <span class="n">POW</span><span class="o">.</span><span class="n">CMS_NOATTR</span><span class="p">),</span>
             <span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">,</span> <span class="p">[],</span>   <span class="p">(),</span> <span class="n">oid</span><span class="p">,</span> <span class="n">POW</span><span class="o">.</span><span class="n">CMS_NOCERTS</span><span class="p">)):</span>

  <span class="nb">print</span> <span class="s2">&quot;Testing&quot;</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>

  <span class="n">cms</span> <span class="o">=</span> <span class="n">POW</span><span class="o">.</span><span class="n">CMS</span><span class="p">()</span>
  <span class="n">cms</span><span class="o">.</span><span class="n">sign</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>

  <span class="c1">#print cms.pprint()</span>

  <span class="nb">print</span> <span class="s2">&quot;Certs:&quot;</span>
  <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">cms</span><span class="o">.</span><span class="n">certs</span><span class="p">():</span>
    <span class="nb">print</span> <span class="n">x</span><span class="o">.</span><span class="n">pprint</span><span class="p">()</span>

  <span class="nb">print</span> <span class="s2">&quot;CRLs:&quot;</span>
  <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">cms</span><span class="o">.</span><span class="n">crls</span><span class="p">():</span>
    <span class="nb">print</span> <span class="n">c</span><span class="o">.</span><span class="n">pprint</span><span class="p">()</span>

  <span class="n">cms</span><span class="o">.</span><span class="n">verify</span><span class="p">(</span><span class="n">store</span><span class="p">,</span> <span class="p">[</span><span class="n">ee</span><span class="p">])</span>
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2025-05-20 15:01:28 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>