aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClombrong <cromblong@egregore.fun>2025-06-29 06:56:36 +0200
committerClombrong <cromblong@egregore.fun>2025-06-29 06:56:36 +0200
commit32fe064825f5a495c5c291df494c4e4dd9846c53 (patch)
tree3b000a76a15e0ffe87785d34bf975e0acfbc58af
parentbc449c40dd8a98f8da119fc1c0c0f053734c30cf (diff)
fix(stream): allow <starttls/> required special case
-rw-r--r--lib/stream.ml16
1 files changed, 12 insertions, 4 deletions
diff --git a/lib/stream.ml b/lib/stream.ml
index b997a25..d544f14 100644
--- a/lib/stream.ml
+++ b/lib/stream.ml
@@ -30,10 +30,18 @@ let parse_features (el : Xml.element) : features =
| "mechanisms" -> {acc with mechanisms=parse_mechanisms feature.children}
| "starttls" -> {acc with starttls=parse_starttls feature.children}
| _ -> {acc with unknown = feature :: acc.unknown}
- in List.fold_left
- parse_feature
- {mechanisms=[]; starttls=`None; unknown=[]}
- (List.filter_map find_left el.children)
+ in
+ (* The XMPP spec mandates that sending a features element that contains only a
+ <starttls/> means the STARTTLS negotiation is required. *)
+ match el.children with
+ | [Left {local_name="starttls";
+ attributes=[];
+ children=[];
+ namespace; _}] when namespace = Xmlns.tls ->
+ {mechanisms=[]; starttls=`Required; unknown=[]}
+ | _ -> List.fold_left parse_feature
+ {mechanisms=[]; starttls=`None; unknown=[]}
+ (List.filter_map find_left el.children)
(** [negotiate domain portal auth] is a promise containing the features supported by the
XMPP server [portal], after eventual STARTTLS negotiation and authentication using