summaryrefslogtreecommitdiff
path: root/src/value_checker.ml
blob: 9e6dae8440cff518b02e929316853785b25d7b8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
module F = Filename

(*type value_constraint = Regex of string | External of string * string option*)
type value_constraint =
    | Regex of string [@name "regex"]
    | External of string * string option [@name "exec"]
    [@@deriving yojson]

exception Bad_validator of string

let validate_value dir buf value_constraint value =
    match value_constraint with
    | Regex s ->
      (try
          let _ = Pcre.exec ~pat:(Printf.sprintf "^%s$" s) value in true
       with Not_found -> false)
    | External (v, c) ->
      (* XXX: Unix.open_process_in is "shelling out", which is a bad idea on multiple levels,
         especially when the input comes directly from the user...
         We should do something about it.
       *)
        let validator = F.concat dir v in
        let cmd =
            match c with
            | Some arg ->
                let safe_arg = Printf.sprintf "%s" (Pcre.qreplace ~pat:"\"" ~templ:"\\\"" arg) in
                Printf.sprintf "%s %s \'%s\' 2>&1" validator safe_arg value
            | None ->
                Printf.sprintf "%s \'%s\' 2>&1" validator value
        in
        let () = Unix.putenv "vyos_libexec_dir" "/usr/libexec/vyos" in
        let () = Unix.putenv "vyos_validators_dir" "/usr/libexec/vyos/validators" in
        let chan = Unix.open_process_in cmd in
        let out = try CCIO.read_all chan with _ -> "" in
        let result = Unix.close_process_in chan in
        match result with
        | Unix.WEXITED 0 -> true
        | Unix.WEXITED 127 ->
            raise (Bad_validator (Printf.sprintf "Could not execute validator %s" validator))
        | _ ->
            let () = Buffer.add_string buf out in
            false

(* If no constraints given, consider it valid.
   Otherwise consider it valid if it satisfies at least one constraint *)
let validate_any validators constraints value =
    let buf = Buffer.create 4096 in
    let validate_exists validators constraints value =
        match constraints with
        | [] -> true
        | _ ->
            try
                List.exists (fun c -> validate_value validators buf c value) constraints
            with Bad_validator e -> let () = Buffer.add_string buf e in false
    in
    match validate_exists validators constraints value with
    | true ->
        let () = Buffer.clear buf in
        None
    | false ->
        let out = Buffer.contents buf in
        let () = Buffer.clear buf in
        Some out

(* If no constraints given, consider it valid.
   Otherwise consider it valid if it satisfies all constraints *)
let validate_all validators constraints value =
    let buf = Buffer.create 4096 in
    let validate_forall validators constraints value =
        match constraints with
        | [] -> true
        | _ ->
            try
                List.for_all (fun c -> validate_value validators buf c value) constraints
            with Bad_validator e -> let () = Buffer.add_string buf e in false
    in
    match validate_forall validators constraints value with
    | true ->
        let () = Buffer.clear buf in
        None
    | false ->
        let out = Buffer.contents buf in
        let () = Buffer.clear buf in
        Some out