From 9a78c841dee8d8165af7d68a17b206f5c297b570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reynir=20Bj=C3=B6rnsson?= Date: Fri, 18 Feb 2022 14:50:57 +0000 Subject: [PATCH 1/2] more SASL mechanisms --- src/core/irc_client.ml | 30 +++++++++++++++++++++--------- src/core/irc_client.mli | 4 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/core/irc_client.ml b/src/core/irc_client.ml index 119a407..a9a1a7a 100644 --- a/src/core/irc_client.ml +++ b/src/core/irc_client.ml @@ -1,5 +1,7 @@ module Log = Irc_helpers.Log +type sasl = [`None | `Plain | `External] + module type CLIENT = sig module Io : sig type 'a t @@ -42,7 +44,7 @@ module type CLIENT = sig val connect : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:bool -> ?config:Io.config -> + ?sasl:sasl -> ?config:Io.config -> addr:Io.inet_addr -> port:int -> nick:string -> unit -> connection_t Io.t (** Connect to an IRC server at address [addr]. The PASS command will be @@ -50,7 +52,7 @@ module type CLIENT = sig val connect_by_name : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:bool -> ?config:Io.config -> + ?sasl:sasl -> ?config:Io.config -> server:string -> port:int -> nick:string -> unit -> connection_t option Io.t (** Try to resolve the [server] name using DNS, otherwise behaves like @@ -142,8 +144,8 @@ module Make(Io: Irc_transport.IO) = struct let send_nick ~connection ~nick = send ~connection (M.nick nick) - let send_auth_sasl ~connection ~user ~password = - Log.debug (fun k->k"login using SASL with user=%S" user); + let send_auth_sasl_plain ~connection ~user ~password = + Log.debug (fun k->k"login using SASL/plain with user=%S" user); send_raw ~connection ~data:"CAP REQ :sasl" >>= fun () -> send_raw ~connection ~data:"AUTHENTICATE PLAIN" >>= fun () -> let b64_login = @@ -153,6 +155,13 @@ module Make(Io: Irc_transport.IO) = struct let data = Printf.sprintf "AUTHENTICATE %s" b64_login in send_raw ~connection ~data + let send_auth_sasl_external ~connection ~user = + Log.debug (fun k -> k "login using SASL/external with user=%S" user); + send_raw ~connection ~data:"CAP REQ :sasl" >>= fun () -> + send_raw ~connection ~data:"AUTHENTICATE EXTERNAL" >>= fun () -> + let data = "AUTHENTICATE " ^ Base64.encode_string user in + send_raw ~connection ~data + let send_pass ~connection ~password = send ~connection (M.pass password) @@ -265,17 +274,20 @@ module Make(Io: Irc_transport.IO) = struct let connect ?username ?(mode=0) ?(realname="irc-client") - ?password ?(sasl=true) ?config ~addr ~port ~nick () = + ?password ?(sasl=`Plain) ?config ~addr ~port ~nick () = Io.open_socket ?config addr port >>= (fun sock -> let connection = mk_connection_ sock in let cap_end = ref false in begin - match username, password with - | Some user, Some password when sasl -> + match username, password, sasl with + | Some user, Some password, `Plain -> + cap_end := true; + send_auth_sasl_plain ~connection ~user ~password + | Some user, _, `External -> cap_end := true; - send_auth_sasl ~connection ~user ~password - | _, Some password -> send_pass ~connection ~password + send_auth_sasl_external ~connection ~user + | _, Some password, _ -> send_pass ~connection ~password | _ -> return () end >>= fun () -> diff --git a/src/core/irc_client.mli b/src/core/irc_client.mli index dfefc1e..902fae6 100644 --- a/src/core/irc_client.mli +++ b/src/core/irc_client.mli @@ -43,7 +43,7 @@ module type CLIENT = sig val connect : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:bool -> ?config:Io.config -> + ?sasl:[`None | `Plain | `External] -> ?config:Io.config -> addr:Io.inet_addr -> port:int -> nick:string -> unit -> connection_t Io.t (** Connect to an IRC server at address [addr]. The PASS command will be @@ -56,7 +56,7 @@ module type CLIENT = sig val connect_by_name : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:bool -> ?config:Io.config -> + ?sasl:[`None | `Plain | `External]-> ?config:Io.config -> server:string -> port:int -> nick:string -> unit -> connection_t option Io.t (** Try to resolve the [server] name using DNS, otherwise behaves like From 0184d5b2d0b7860f221eeab5d0797706c86c3e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reynir=20Bj=C3=B6rnsson?= Date: Fri, 4 Mar 2022 13:04:13 +0000 Subject: [PATCH 2/2] Apply suggestions from code review --- src/core/irc_client.ml | 14 +++++++------- src/core/irc_client.mli | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/irc_client.ml b/src/core/irc_client.ml index a9a1a7a..41a7d59 100644 --- a/src/core/irc_client.ml +++ b/src/core/irc_client.ml @@ -1,6 +1,6 @@ module Log = Irc_helpers.Log -type sasl = [`None | `Plain | `External] +type sasl = [`Plain | `External] module type CLIENT = sig module Io : sig @@ -44,7 +44,7 @@ module type CLIENT = sig val connect : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:sasl -> ?config:Io.config -> + ?sasl:sasl option -> ?config:Io.config -> addr:Io.inet_addr -> port:int -> nick:string -> unit -> connection_t Io.t (** Connect to an IRC server at address [addr]. The PASS command will be @@ -52,7 +52,7 @@ module type CLIENT = sig val connect_by_name : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:sasl -> ?config:Io.config -> + ?sasl:sasl option -> ?config:Io.config -> server:string -> port:int -> nick:string -> unit -> connection_t option Io.t (** Try to resolve the [server] name using DNS, otherwise behaves like @@ -274,20 +274,20 @@ module Make(Io: Irc_transport.IO) = struct let connect ?username ?(mode=0) ?(realname="irc-client") - ?password ?(sasl=`Plain) ?config ~addr ~port ~nick () = + ?password ?(sasl=Some `Plain) ?config ~addr ~port ~nick () = Io.open_socket ?config addr port >>= (fun sock -> let connection = mk_connection_ sock in let cap_end = ref false in begin match username, password, sasl with - | Some user, Some password, `Plain -> + | Some user, Some password, Some `Plain -> cap_end := true; send_auth_sasl_plain ~connection ~user ~password - | Some user, _, `External -> + | Some user, _, Some `External -> cap_end := true; send_auth_sasl_external ~connection ~user - | _, Some password, _ -> send_pass ~connection ~password + | _, Some password, None -> send_pass ~connection ~password | _ -> return () end >>= fun () -> diff --git a/src/core/irc_client.mli b/src/core/irc_client.mli index 902fae6..5c9b722 100644 --- a/src/core/irc_client.mli +++ b/src/core/irc_client.mli @@ -43,7 +43,7 @@ module type CLIENT = sig val connect : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:[`None | `Plain | `External] -> ?config:Io.config -> + ?sasl:[`Plain | `External] option -> ?config:Io.config -> addr:Io.inet_addr -> port:int -> nick:string -> unit -> connection_t Io.t (** Connect to an IRC server at address [addr]. The PASS command will be @@ -56,7 +56,7 @@ module type CLIENT = sig val connect_by_name : ?username:string -> ?mode:int -> ?realname:string -> ?password:string -> - ?sasl:[`None | `Plain | `External]-> ?config:Io.config -> + ?sasl:[`Plain | `External] option -> ?config:Io.config -> server:string -> port:int -> nick:string -> unit -> connection_t option Io.t (** Try to resolve the [server] name using DNS, otherwise behaves like