summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2018-10-26 01:47:04 +0200
committerPhilipp Gesang <phg@phi-gamma.net>2018-10-28 23:07:51 +0100
commit442a0edc90451478d560c2d185e411afbcc1181c (patch)
treea9634783136652475da00d1c1b035814870cf5f1 /util
parent04be611be6ab6bcfa7617365ab824ca2b1dc2f9b (diff)
downloadocaml-sid-442a0edc90451478d560c2d185e411afbcc1181c.tar.gz
util/sidparse: add cli SID utility
Diffstat (limited to 'util')
-rw-r--r--util/sidparse.ml135
1 files changed, 135 insertions, 0 deletions
diff --git a/util/sidparse.ml b/util/sidparse.ml
new file mode 100644
index 0000000..e99d27f
--- /dev/null
+++ b/util/sidparse.ml
@@ -0,0 +1,135 @@
+let err q v =
+ match q, v with
+ | true, _ -> Printf.ifprintf stdout
+ | _ -> Printf.eprintf
+and out q v =
+ match q, v with
+ | true, _
+ | _, true -> Printf.ifprintf stdout
+ | _ -> Printf.printf
+
+let header q v =
+ out q v "SID \
+ IDAUTH \
+ NSUB SUBAUTHS\n%!"
+
+let emit q v s =
+ let ss = Sid.to_string s
+ and ia = Sid.get_ident_auth s
+ and sas = Sid.get_sub_auths s in
+ out q v "%-30s %-15s %-4d %s\n"
+ ss
+ (Stdint.Uint64.to_string ia)
+ (Array.length sas)
+ (Array.map Stdint.Uint32.to_string sas
+ |> Array.to_list
+ |> String.concat " ")
+
+let handle_input q v s =
+ match String.trim s with
+ | "" -> `Nothing
+ | s ->
+ try `Done (Sid.of_string s)
+ with Invalid_argument e -> err q v "ERROR: %s\n%!" e; `Junk
+
+let from_argv sids =
+ let rest = ref sids in
+ let next () =
+ match !rest with
+ | [] -> `Done
+ | hd::tl ->
+ rest := tl;
+ `Sid hd
+ in
+ next
+
+let from_stdin () =
+ try `Sid (input_line stdin)
+ with End_of_file -> `Done
+
+let traverse q v next =
+ let rec aux n ne =
+ match next () with
+ | `Done -> if ne = 0 then Ok n else Error (n, ne)
+ | `Sid s -> begin
+ match handle_input q v s with
+ | `Nothing -> aux n ne
+ | `Junk -> aux (n + 1) (ne + 1)
+ | `Done s -> begin
+ if n = 0 then header q v;
+ emit q v s;
+ aux (n + 1) ne
+ end
+ end
+ in
+ aux 0 0
+
+let sidparse validate quiet args =
+ let next =
+ match args with
+ | [] -> begin
+ if Unix.(isatty stdin) then
+ err quiet validate "reading input from stdin\n%!";
+ from_stdin
+ end
+ | sids -> from_argv sids
+ in
+ match traverse quiet validate next with
+ | Ok _ -> 0
+ | Error (n, ne) ->
+ if not quiet then
+ err quiet validate "processed %d items with %d errors\n" n ne;
+ -1
+
+open Cmdliner
+
+let arg_validate =
+ let doc = "Do not print table of constituent parts, only error messages." in
+ Arg.(value & flag & info ["v"; "validate"] ~doc)
+
+let arg_quiet =
+ let doc = "Do not print anything at all." in
+ Arg.(value & flag & info ["q"; "quiet"] ~doc)
+
+let arg_sid =
+ let doc = "Inputs specified on command line as positional arguments." in
+ Arg.(value & (pos_all string []) & info [] ~docv:"SID" ~doc)
+
+let cmd_sidparse =
+ let exits = Term.exit_info ~doc:"errors occurred" (-1) :: Term.default_exits in
+ let doc = "Process Windows security identifiers." in
+ let man =
+ [ `P "This command will parse SIDs (security identifiers) \
+ from the command line and standard input."
+ ; `P "The input is expected to consist of one SID per argument or \
+ line, respectively, in “string format” (cf. [MS-DTYP] 2.4.21)."
+ ; `S Manpage.s_see_also
+ ; `P "Consult Microsoft’s documentation for more information. \
+ SIDs are specified in MS-DTYP \
+ (https://msdn.microsoft.com/en-us/library/cc230273.aspx) \
+ with references to the Open Group RPC standard \
+ (http://www.opengroup.org/dce/download/)."
+ ; `S Manpage.s_examples
+ ; `P "Parse a number of SIDs supplied on command line:"
+ ; `Pre "$ sidparse S-1-0 S-1-1\n\
+ SID IDAUTH NSUB SUBAUTHS\n\
+ S-1-0 0 0\n\
+ S-1-1 1 0\n"
+ ; `P "Parse a number of SIDs from standard input:"
+ ; `Pre "$ sidparse <<THATSALL\n\
+ S-1-0\n\
+ S-1-42-1337-2187\n\
+ THATSALL\n\
+ SID IDAUTH NSUB SUBAUTHS\n\
+ S-1-0 0 0 \n\
+ S-1-42-1337-2187 42 2 1337 2187"
+ ]
+ in
+ Term.(const sidparse $ arg_validate $ arg_quiet $ arg_sid),
+ Term.info ~doc ~man ~exits "sidparse"
+
+let () =
+ Term.eval (cmd_sidparse)
+ |> Term.exit_status
+;;
+