aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/ostatus/feed_representer.ex2
-rw-r--r--lib/pleroma/web/salmon/salmon.ex73
2 files changed, 74 insertions, 1 deletions
diff --git a/lib/pleroma/web/ostatus/feed_representer.ex b/lib/pleroma/web/ostatus/feed_representer.ex
index 749cb10d0..14ac3ebf4 100644
--- a/lib/pleroma/web/ostatus/feed_representer.ex
+++ b/lib/pleroma/web/ostatus/feed_representer.ex
@@ -3,7 +3,7 @@ defmodule Pleroma.Web.OStatus.FeedRepresenter do
alias Pleroma.Web.OStatus.{UserRepresenter, ActivityRepresenter}
def to_simple_form(user, activities, users) do
- most_recent_update = List.first(activities).updated_at
+ most_recent_update = (List.first(activities) || user).updated_at
|> NaiveDateTime.to_iso8601
h = fn(str) -> [to_charlist(str)] end
diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex
new file mode 100644
index 000000000..3881f2758
--- /dev/null
+++ b/lib/pleroma/web/salmon/salmon.ex
@@ -0,0 +1,73 @@
+defmodule Pleroma.Web.Salmon do
+ use Bitwise
+
+ def decode(salmon) do
+ {doc, _rest} = :xmerl_scan.string(to_charlist(salmon))
+
+ {:xmlObj, :string, data} = :xmerl_xpath.string('string(//me:data[1])', doc)
+ {:xmlObj, :string, sig} = :xmerl_xpath.string('string(//me:sig[1])', doc)
+ {:xmlObj, :string, alg} = :xmerl_xpath.string('string(//me:alg[1])', doc)
+ {:xmlObj, :string, encoding} = :xmerl_xpath.string('string(//me:encoding[1])', doc)
+ {:xmlObj, :string, type} = :xmerl_xpath.string('string(//me:data[1]/@type)', doc)
+
+
+ {:ok, data} = Base.url_decode64(to_string(data), ignore: :whitespace)
+ {:ok, sig} = Base.url_decode64(to_string(sig), ignore: :whitespace)
+ alg = to_string(alg)
+ encoding = to_string(encoding)
+ type = to_string(type)
+
+ [data, type, encoding, alg, sig]
+ end
+
+ def fetch_magic_key(salmon) do
+ [data, _, _, _, _] = decode(salmon)
+ {doc, _rest} = :xmerl_scan.string(to_charlist(data))
+ {:xmlObj, :string, uri} = :xmerl_xpath.string('string(//author[1]/uri)', doc)
+
+ uri = to_string(uri)
+ base = URI.parse(uri).host
+
+ # TODO: Find out if this endpoint is mandated by the standard.
+ {:ok, response} = HTTPoison.get(base <> "/.well-known/webfinger", ["Accept": "application/xrd+xml"], [params: [resource: uri]])
+
+ {doc, _rest} = :xmerl_scan.string(to_charlist(response.body))
+
+ {:xmlObj, :string, magickey} = :xmerl_xpath.string('string(//Link[@rel="magic-public-key"]/@href)', doc)
+ "data:application/magic-public-key," <> magickey = to_string(magickey)
+
+ magickey
+ end
+
+ def decode_and_validate(magickey, salmon) do
+ [data, type, encoding, alg, sig] = decode(salmon)
+
+ signed_text = [data, type, encoding, alg]
+ |> Enum.map(&Base.url_encode64/1)
+ |> Enum.join(".")
+
+ key = decode_key(magickey)
+
+ verify = :public_key.verify(signed_text, :sha256, sig, key)
+
+ if verify do
+ {:ok, data}
+ else
+ :error
+ end
+ end
+
+ defp decode_key("RSA." <> magickey) do
+ make_integer = fn(bin) ->
+ list = :erlang.binary_to_list(bin)
+ Enum.reduce(list, 0, fn (el, acc) -> (acc <<< 8) ||| el end)
+ end
+
+ [modulus, exponent] = magickey
+ |> String.split(".")
+ |> Enum.map(&Base.url_decode64!/1)
+ |> Enum.map(make_integer)
+
+ {:RSAPublicKey, modulus, exponent}
+ end
+end