From 8f52e91dab637e4d37fa160944997b1e9f1f9361 Mon Sep 17 00:00:00 2001
From: Marcus Rohrmoser
Copy Emoji to Clipboard:
+
diff --git a/lib/cgi.ml b/lib/cgi.ml
index dc1571e..69741d4 100644
--- a/lib/cgi.ml
+++ b/lib/cgi.ml
@@ -73,6 +73,22 @@ module Request = struct
server_port : string;
raw_string : string -> string option
}
+
+ let empty = {
+ content_type = "text/plain";
+ content_length = None;
+ host = "127.0.0.1";
+ http_cookie = "";
+ path_info = "/";
+ query_string = "";
+ remote_addr = "127.0.0.1";
+ request_method = "GET";
+ scheme = "http";
+ script_name = "";
+ server_port = "80";
+ raw_string = (fun _ -> None);
+ }
+
(** Request meta data. https://tools.ietf.org/html/rfc3875#section-4.1.13 *)
(* https://tools.ietf.org/html/rfc3875 *)
@@ -206,6 +222,21 @@ module Request = struct
match r.query_string with
| "" -> u
| q -> q |> Uri.query_of_encoded |> Uri.with_query u
+
+ (** fetch http header values and map from lowercase plus the special name (request-target) *)
+ let header_get (r : t) = function
+ | "(request-target)" -> Printf.sprintf "%s %s"
+ (r.request_method |> String.Ascii.lowercase)
+ (r |> path_and_query |> Uri.to_string)
+ |> Option.some
+ | k ->
+ let toenv = String.map (function
+ | '-' -> '_'
+ | c -> Char.Ascii.uppercase c) in
+ match toenv k with
+ | "CONTENT_LENGTH"
+ | "CONTENT_TYPE" as k -> k |> r.raw_string
+ | k -> ("HTTP_" ^ k) |> r.raw_string
end
module Response = struct
diff --git a/lib/http.ml b/lib/http.ml
index 4deff0d..98368c1 100644
--- a/lib/http.ml
+++ b/lib/http.ml
@@ -286,6 +286,7 @@ module Signature = struct
*)
Tyre.eval P.list_auth_param
+ (** add (request-target) iff request given *)
let to_sign_string0 ~request h : string =
let h = h |> Cohttp.Header.to_frames in
(match request with
diff --git a/lib/is2s.ml b/lib/is2s.ml
index 46d027a..4a8be9b 100644
--- a/lib/is2s.ml
+++ b/lib/is2s.ml
@@ -26,21 +26,9 @@
* along with this program. If not, see Resolve names like @alice@example.com (WebFinger URIs),
- http GET the JSON Resource
- Descriptor, parse as understood by #Seppo, re-encode and
- return as json. Usually a subset of the input. Http GET the ActivityPub Actor
- Profile, parse as understood by #Seppo, re-encode and
- return as json. Usually a subset of the input.
- Signs the GET request with https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12#appendix-C as
- key of actor.jsa.
- Signs the GET request with
+ https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12#appendix-C as key of
+ actor.jsa. This is a stateless, single-file cgi program. Operate it
- yourself on commodity shared webspace: Download apchk.cgi,
- drop it on a cgi-capable webserver and you're set. To style it, redirect ./css or ./xsl. The source
- is free and open. Version,
- Issues & Improvements. This is an ephemeral (stateless), single-file cgi program. Operate it yourself on commodity shared
+ webspace: Download apchk.cgi, copy it
+ to a cgi-capable webserver, make it executable (chmod 555) and you're set. To style it to your
+ liking, redirect ./css or ./xsl to yours. The source is free and open. Version, Issues & Improvements. Generously supported by 🇪🇺
- @EC_NGI@social.network.europa.eu under NLnet grant #Seppo.WebFinger RFC7033
- WebFinger RFC7033
+
+
- AP actor profile
- AP actor profile
+
+
+ About
- apchk.cgi
About
+ apchk.cgi
Copy Emoji to Clipboard: + @@ -102,7 +103,7 @@ - + diff --git a/test/t_http.ml b/test/t_http.ml index 6943b55..c800a7d 100644 --- a/test/t_http.ml +++ b/test/t_http.ml @@ -729,6 +729,69 @@ digest: SHA-256=N0m+gyYe/GieNBzMEOStVqf7hq/qdmh7bqdWanZSE1o= content-type: application/activity+json *) () + + + let tc_sign_api () = + (* + sign != verify + + but has overlap + + constructing the signagee payload + - keys + - values + - + + signing ig + + verifying it + *) + (** @TODO *) + let _list_header_get l (k : string) : string option = l |> List.assoc_opt k in + let compute_verify_signature_payload fetcher : string = + (match fetcher "signature" with + | None -> Some "header not found: signature" + | Some si -> + match si |> Http.Signature.decode with + | Error _ -> Some "error decoding signature" + | Ok si -> + match si |> List.assoc_opt "headers" with + | None -> Some "signature field not found: headers" + | Some v -> + (* assert lowercase *) + v + |> Astring.String.cuts ~sep:" " |> List.rev |> List.fold_left + (fun init k -> match k |> fetcher with + | None -> init + | Some v -> (k,v) :: init) [] + |> Cohttp.Header.of_list + |> Cohttp.Header.to_frames + |> Astring.String.concat ~sep:"\n" + |> Option.some ) + |> Option.value ~default:"" + in + let r = {Cgi.Request.empty with + request_method = "POST"; + raw_string = (function + | "HTTP_HOST" -> Some "example.com" + | "HTTP_DATE" -> Some "tomorrow" + | "HTTP_SIGNATURE" -> Some {|keyId="Test",algorithm="rsa-sha256",headers="(request-target) host date",signature="qdx+H7PHHDZgy4y/Ahn9Tny9V3GP6YgBPyUXMmoxWtLbHpUnXS2mg2+SbrQDMCJypxBLSPQR2aAjn7ndmw2iicw3HMbe8VfEdKFYRqzic+efkb3nndiv/x1xSHDJWeSWkx3ButlYSuBskLu6kd9Fswtemr3lgdDEmn04swr2Os0="|} + | _ -> None)} in + Cgi.Request.header_get r "SIGNATURE" |> Option.get + |> Http.Signature.decode |> Result.get_ok + |> List.assoc "headers" + |> Astring.String.cuts ~sep:" " + |> List.length + |> Assrt.equals_int __LOC__ 3; + (* typical for verify *) + r + |> Cgi.Request.header_get + |> compute_verify_signature_payload + |> Assrt.equals_string __LOC__ {|(request-target): post / +host: example.com +date: tomorrow|}; + (); + () end let () = @@ -764,5 +827,6 @@ let () = "tc_verify_hs2019_richanna_nonn", `Quick, Header.tc_verify_hs2019_richanna_nonn; "tc_verify_hs2019_gotosocial", `Quick, Header.tc_verify_hs2019_gotosocial; "tc_verify_masto430", `Quick, Header.tc_verify_masto430; + "tc_sign_api", `Quick, Header.tc_sign_api; ] ] diff --git a/test/t_storage.ml b/test/t_storage.ml index 4d111c3..3484e97 100644 --- a/test/t_storage.ml +++ b/test/t_storage.ml @@ -70,7 +70,7 @@ let set_up = "setup", `Quick, (fun () -> Unix.chdir "../../../test/" ) -let tc_fifo = "tc_fifo", `Quick, (fun () -> +let _tc_fifo = "tc_fifo", `Quick, (fun () -> let bu = Fifo.make 12 "buffer.fifo" in let by = Bytes.make 2 '_' in let _ = Fifo.push bu by in @@ -273,7 +273,7 @@ let () = "seppo_suite" [ __FILE__ , [ set_up; - tc_fifo; + (* tc_fifo; *) tc_dir_of_ix; tc_tuple; tc_strut; -- 2.45.2