Ejemplo n.º 1
0
    def testSigning(self):
        envelope = magicsig.Envelope(self.protocol,
                                     raw_data_to_sign=self.test_atom,
                                     signer_uri='acct:[email protected]',
                                     signer_key=TEST_PRIVATE_KEY,
                                     data_type='application/atom+xml',
                                     encoding='base64url',
                                     alg='RSA-SHA256')

        # Turn envelope into text:
        xml = envelope.ToXML()

        # Now round-trip it:
        magicsig.Envelope(self.protocol,
                          mime_type='application/magic-envelope+xml',
                          document=xml)
Ejemplo n.º 2
0
 def testInvalidEnvelopes(self):
     self.assertRaises(magicsig.EnvelopeError, magicsig.Envelope, 'blah')
     try:
         magicsig.Envelope(foo=5, biff=23)
         # Should never get here
         self.assertTrue(None)
     except magicsig.Error:
         pass
Ejemplo n.º 3
0
  def post(self):
    """Handles posting back of data and returns a result via XHR.
       Just for demo purposes.  Accepts either data (an XML document)
       or env (a magic envelope) and returns output of magic-envelope
       or atom depending on format parameter."""

    # TODO: Verify that current user session matches author of content, or throw
    data = self.request.get('data')
    envText = self.request.get('env')
    format = self.request.get('format') or 'magic-envelope'
    if data:
      logging.info('posted Atom data = %s\n',data)
      userid = magicsig.NormalizeUserIdToUri(
          users.get_current_user().email())

      # Do an ACL check to see if current user is the author:
      if not self.magicenv.IsAllowedSigner(data, userid):
        logging.info("Authorship check failed for user %s\n",userid)
        self.response.set_status(400)
        self.response.out.write("User "+userid+" not first author of entry,"
                                " cannot sign.")
        return

      # Sign the content on behalf of user:
      envelope = magicsig.Envelope(raw_data_to_sign=data,
                                   data_type='application/atom+xml',
                                   signer_uri=userid,
                                   signer_key='TEST')
      #env = self.magicenv.SignMessage(data, 'application/atom+xml', userid)
    elif envText:
      logging.info('posted Magic envelope env = %s\n',envText)
      envelope = magicsig.Envelope(document=envText,
                                   mime_type='applicaton/magic-envelope+xml')
      #env = self.magicenv.Parse(envText)

    logging.info('Created magic envelope: \n%s\n' % envelope)

    self.response.set_status(200) # The default
    if format == 'magic-envelope':
      self.response.out.write(envelope.ToXML())
    elif format == 'atom':
      self.response.out.write(envelope.ToAtom())
    else:
      self.response.set_status(400)
      raise "Unsupported format: "+format
Ejemplo n.º 4
0
    def post(self):
        # Retrieve putative Salmon from input body.
        body = self.request.body
        mime_type = self.request.headers['Content-Type']

        protocol = magicsig.MagicEnvelopeProtocol()
        protocol.key_retriever = RealKeyRetriever()
        logging.info("Saw body:\n%s\n" % body)
        envelope = magicsig.Envelope(protocol,
                                     document=body,
                                     mime_type=mime_type)
        # If we got here, the Salmon validated.

        # Grab out the fields of interest:
        entry = envelope.GetParsedData().getroot()

        s = et.tostring(entry, encoding='utf-8')
        logging.info('Saw entry:\n%s\n' % s)

        ns = '{http://www.w3.org/2005/Atom}'
        ans = '{http://activitystrea.ms/spec/1.0/}'
        author = entry.findtext(ns + 'author/' + ns + 'uri')
        posted_at_str = entry.findtext(ns + 'updated')
        content = entry.findtext(ns + 'content')
        if not content:
            content = entry.findtext(ans + 'object/' + ns + 'content')
        if not content:
            content = entry.findtext(ns + 'summary')
        if not content:
            content = entry.findtext(ns + 'title')
        if not content:
            content = ''
        content = content.strip()
        logging.info('Content = %s' % content)

        # Ensure we have a virtual profile for remote user!
        p = profile_handler.ensure_virtual_profile(
            author
        )  # TODO: WRITE THIS FUNCTION!!!                                             )

        mentions = comment_handler.extract_mentions(content)

        logging.info('About to add: author=%s, content=%s, mentions=%s' %
                     (author, content, mentions))
        c = datamodel.Comment(
            author_profile=p,
            posted_at=datetime.datetime.now(
            ),  #TODO: should convert posted_at_str,
            content=content,
            mentions=mentions)
        c.put()
        self.response.set_status(202)
        self.response.out.write("Salmon accepted!\n")
Ejemplo n.º 5
0
  def ParseSalmon(self, text, mimetype):
    """Parses a salmon from text with given mimetype.

    Returns:
      The salmon data as a dict, with fields:
    """

    self.magicenv.key_retriever = self.key_retriever

    return magicsig.Envelope(
       self.magicenv,
       mime_type=mimetype,
       document=text).ToAtom()
Ejemplo n.º 6
0
    def testToAtom(self):
        envelope = magicsig.Envelope(self.protocol,
                                     raw_data_to_sign=self.test_atom,
                                     signer_uri='acct:[email protected]',
                                     signer_key=TEST_PRIVATE_KEY,
                                     data_type='application/atom+xml',
                                     encoding='base64url',
                                     alg='RSA-SHA256')

        text = envelope.ToAtom()

        assert re.search('atom:entry', text)
        assert re.search('me:provenance', text)
        assert re.search('test@example\.com', text)
Ejemplo n.º 7
0
    def testTampering(self):
        envelope = magicsig.Envelope(self.protocol,
                                     raw_data_to_sign=self.test_atom,
                                     signer_uri='acct:[email protected]',
                                     signer_key=TEST_PRIVATE_KEY,
                                     data_type='application/atom+xml',
                                     encoding='base64url',
                                     alg='RSA-SHA256')

        xml = envelope.ToXML()

        self.assertRaises(Exception,
                          magicsig.Envelope,
                          self.protocol,
                          mime_type='application/magic-envelope+xml',
                          document=re.sub('U2FsbW9', 'U2GsbW9', xml))
Ejemplo n.º 8
0
 def post(self):
   """  Intended to be called via XHR from magicsigdemo.html. """
   logging.error('MagicSigDemoVerify post')
   data = self.request.get('data').strip()
   logging.info('The data = %s\n',data)
   env = self.magicenv.Parse(data)
   try:
     envelope = magicsig.Envelope(document=data,
                                  mime_type='application/magic-envelope+xml')
     self.response.set_status(200) # The default
     self.response.out.write("OK")
     logging.info("SPLASH! Salmon signature verified!")
   except magicsig.Error:
     self.response.set_status(400)
     info = "Details: Exception %s:\n%s\nTraceback:\n%s" % sys.exc_info()
     logging.info(info)
     self.response.out.write('Signature does not validate. Details: %s' % info)
Ejemplo n.º 9
0
  def dump(self):
    envelope = magicsig.Envelope(
        raw_data_to_sign=self.test_atom,
        signer_uri='acct:[email protected]',
        signer_key=TEST_PRIVATE_KEY,
        data_type='application/atom+xml',
        encoding='base64url',
        alg='RSA-SHA256')

    # Turn envelope into text:
    xml = envelope.ToXML()

    # And provenanced Atom:
    atom = envelope.ToAtom()

    print "Original data:\n%s\n" % self.test_atom
    print "Magic Envelope:\n%s\n" % xml
    print "Atom with provenance:\n%s\n" % atom
Ejemplo n.º 10
0
def do_salmon_slaps(mentions, c):
    client = webfinger.Client()
    for id in mentions:
        try:
            logging.info('Looking up id %s' % id)
            xrd_list = client.lookup(id)
            for item in xrd_list:
                logging.info("Got webfinger result for %s: %s" % (id, item))
                # item is a Xrd proto2, not a string, no need to decode.
                subject = item.subject
                slap_urls = key_urls = [
                    link.href for link in item.links if link.rel ==
                    'http://salmon-protocol.org/ns/salmon-mention'
                ]
                logging.info('About to do salmon slaps: subject %s, %s' %
                             (subject, slap_urls))

                # Build an envelope:
                text = to_atom_entry(c)
                logging.info('signing text: %s' % text)
                envelope = magicsig.Envelope(
                    raw_data_to_sign=text,
                    data_type='application/atom+xml',
                    signer_uri=c.author_profile.profile_url,
                    signer_key=private_signing_key(
                        c.author_profile.profile_url))

                # Now send the envelope:
                body_to_send = envelope.ToXML()

                # TODO: Get our own frickin' HTTP client
                headers = {'Content-Type': 'application/atom+xml'}
                for url in slap_urls:
                    logging.info('Sending salmon slap to %s' % url)
                    response, content = client._http_client.request(
                        url, 'POST', headers=headers, body=body_to_send)
                    logging.info('Got response %s' % response)

        except webfinger.FetchError:
            pass
Ejemplo n.º 11
0
  def SignSalmon(self, text, mimetype, requestor_id):
    """Signs a Salmon on behalfo the the current_user.

    Input text must be in a recognized format so authorship can be
    verified.

    Args:
      text: Text of message to be signed.
      mimetype: The MIME type of the message to sign.
      requestor_id: The id of the requestor (usually current logged in user).
    Returns:
      The Magic Envelope parameters from section 3.1 of the
      Magic Signatures spec, as a dict.
    """
    
    assert mimetype == 'application/atom+xml'

    requestor_id = magicsig.NormalizeUserIdToUri(requestor_id)

    if not self.magicenv.IsAllowedSigner(text, 
        magicsig.NormalizeUserIdToUri(requestor_id)):
        # TODO: Fix authorship if missing author, raise
        # exception otherwise.
        return

    env = magicsig.Envelope(
        self.magicenv,
        raw_data_to_sign=text,
        signer_uri=requestor_id,
        signer_key=self._GetKeypair(requestor_id),
        data_type='application/atom+xml',
        encoding='base64url',
        alg='RSA-SHA256')


    return env.ToXML()