Commit 3ad7d596 authored by Stephane Glondu's avatar Stephane Glondu
Browse files

Log some security-sensitive events

parent e89e7e22
......@@ -19,19 +19,33 @@ let file_exists x =
let populate accu f s = Lwt_stream.fold_s f s accu
lwt election_table =
let dir = ref None in
let secure_logfile = ref None
let data_dir = ref None
let () =
let open Ocsigen_extensions.Configuration in
Eliom_config.parse_config [
element
~name:"log"
~obligatory:true
~attributes:[
attribute ~name:"file" ~obligatory:true (fun s -> secure_logfile := Some s);
] ();
element
~name:"data"
~obligatory:false
~obligatory:true
~attributes:[
attribute ~name:"dir" ~obligatory:true (fun s -> dir := Some s);
]
()
];
match !dir with
attribute ~name:"dir" ~obligatory:true (fun s -> data_dir := Some s);
] ();
];;
lwt () =
match !secure_logfile with
| Some x -> Web_common.open_security_log x
| None -> return ()
lwt election_table =
match !data_dir with
| Some dir ->
Ocsigen_messages.debug (fun () ->
"Using data from " ^ dir ^ "..."
......@@ -183,6 +197,9 @@ let () = Eliom_registration.Html5.register
let open Web_common in
let user_type = Dummy in
Eliom_reference.set Services.user (Some {user_name; user_type}) >>
Web_common.security_log (fun () ->
user_name ^ " successfully logged in using dummy"
) >>
Services.get ())
in
Templates.dummy_login ~service)
......@@ -217,6 +234,9 @@ let () = Eliom_registration.Redirection.register
let open Web_common in
let user_name = String.sub info (i+1) (j-i-1) in
let user_type = CAS in
Web_common.security_log (fun () ->
user_name ^ " successfully logged in using CAS"
) >>
Eliom_reference.set Services.user
(Some {user_name; user_type}) >>
Services.get ()
......@@ -242,10 +262,19 @@ let () = Eliom_registration.Redirection.register
(* should ballot be unset here or not? *)
Eliom_reference.unset Services.user >>
match user with
| Some user when user.Web_common.user_type = Web_common.CAS ->
lwt service = Services.get () in
let uri = Eliom_uri.make_string_uri ~absolute:true ~service () in
return (Eliom_service.preapply Services.cas_logout uri)
| Some user ->
if user.Web_common.user_type = Web_common.CAS then (
lwt service = Services.get () in
let uri = Eliom_uri.make_string_uri ~absolute:true ~service () in
Web_common.(security_log (fun () ->
string_of_user user ^ " logged out, redirecting to CAS"
)) >>
return (Eliom_service.preapply Services.cas_logout uri)
) else (
Web_common.(security_log (fun () ->
string_of_user user ^ " logged out"
)) >> Services.get ()
)
| _ -> Services.get ()
)
......
......@@ -110,6 +110,37 @@ module type WEB_BBOX = sig
val extract_creds : unit -> SSet.t Lwt.t
end
let security_logfile = ref None
let open_security_log f =
lwt () =
match !security_logfile with
| Some ic -> Lwt_io.close ic
| None -> return ()
in
lwt ic = Lwt_io.(
open_file ~flags:Unix.(
[O_WRONLY; O_APPEND; O_CREAT]
) ~perm:0o600 ~mode:output f
) in
security_logfile := Some ic;
return ()
let security_log s =
match !security_logfile with
| None -> return ()
| Some ic -> Lwt_io.atomic (fun ic ->
Lwt_io.write ic (
Serializable_builtin_j.string_of_datetime (
CalendarLib.Fcalendar.Precise.now (),
None
)
) >>
Lwt_io.write ic ": " >>
Lwt_io.write_line ic (s ()) >>
Lwt_io.flush ic
) ic
module MakeBallotBox (P : Signatures.ELECTION_PARAMS) (E : LWT_ELECTION) = struct
(* TODO: enforce E is derived from P *)
......@@ -169,7 +200,7 @@ module MakeBallotBox (P : Signatures.ELECTION_PARAMS) (E : LWT_ELECTION) = struc
| Some s -> Lwt.return (Z.to_string s.s_commitment)
| None -> fail MissingCredential
in
lwt cred =
lwt old_cred =
try_lwt Ocsipersist.find cred_table credential
with Not_found -> fail InvalidCredential
and old_record =
......@@ -178,14 +209,17 @@ module MakeBallotBox (P : Signatures.ELECTION_PARAMS) (E : LWT_ELECTION) = struc
Lwt.return (Some x)
with Not_found -> Lwt.return None
in
match cred, old_record with
match old_cred, old_record with
| None, None ->
(* first vote *)
if E.check_ballot ballot then (
let hash = sha256_b64 rawballot in
Ocsipersist.add cred_table credential (Some hash) >>
Ocsipersist.add ballot_table hash rawballot >>
Ocsipersist.add record_table user (date, credential)
Ocsipersist.add record_table user (date, credential) >>
security_log (fun () ->
Printf.sprintf "%s successfully cast ballot %s" user hash
)
) else (
fail ProofCheck
)
......@@ -193,17 +227,34 @@ module MakeBallotBox (P : Signatures.ELECTION_PARAMS) (E : LWT_ELECTION) = struc
(* revote *)
if credential = old_credential then (
if E.check_ballot ballot then (
lwt old_ballot = Ocsipersist.find ballot_table h in
Ocsipersist.remove ballot_table h >>
security_log (fun () ->
Printf.sprintf "%s successfully removed ballot %S" user old_ballot
) >>
let hash = sha256_b64 rawballot in
Ocsipersist.add cred_table credential (Some hash) >>
Ocsipersist.add ballot_table hash rawballot >>
Ocsipersist.add record_table user (date, credential)
Ocsipersist.add record_table user (date, credential) >>
security_log (fun () ->
Printf.sprintf "%s successfully cast ballot %s" user hash
)
) else (
fail ProofCheck
)
) else fail WrongCredential
| None, Some _ -> fail RevoteNotAllowed
| Some _, None -> fail ReusedCredential
) else (
security_log (fun () ->
Printf.sprintf "%s attempted to revote with already used credential %s" user credential
) >> fail WrongCredential
)
| None, Some _ ->
security_log (fun () ->
Printf.sprintf "%s attempted to revote using a new credential %s" user credential
) >> fail RevoteNotAllowed
| Some _, None ->
security_log (fun () ->
Printf.sprintf "%s attempted to vote with already used credential %s" user credential
) >> fail ReusedCredential
let fold_ballots f x =
Ocsipersist.fold_step (fun k v x -> f v x) ballot_table x
......
......@@ -79,3 +79,9 @@ module type WEB_ELECTION = sig
module B : WEB_BBOX
val data : election_data
end
val open_security_log : string -> unit Lwt.t
(** Set the path to the security logger. *)
val security_log : (unit -> string) -> unit Lwt.t
(** Add an entry to the security log. *)
......@@ -30,6 +30,7 @@
<static dir="_SRCDIR_/media/booth" />
</site>
<eliom module="_build/src/web/server.cma">
<log file="_RUNDIR_/log/security.log"/>
<data dir="tests/data"/>
</eliom>
</host>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment