Prevent users from setting JOBSERIAL and from setting variables with invalid names.
authorRichard W.M. Jones <rjones@redhat.com>
Tue, 21 Feb 2012 15:06:49 +0000 (15:06 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Tue, 21 Feb 2012 15:06:49 +0000 (15:06 +0000)
daemon/daemon.ml
lib/whenproto.x
lib/whenutils.ml
lib/whenutils.mli
tools/whenjobs.ml

index a8bd514..47a67ed 100644 (file)
@@ -97,12 +97,35 @@ and proc_reload_file () =
 and proc_set_variable (name, value) =
   if !debug then Syslog.notice "remote call: set_variable %s" name;
 
-  let value = variable_of_rpc value in
-  variables := StringMap.add name value !variables;
+  try
+    (* Don't permit certain names. *)
+    if name = "JOBSERIAL" then
+      failwith "JOBSERIAL variable cannot be set";
+
+    let len = String.length name in
+    if len = 0 then
+      failwith "variable name is an empty string";
+    if name.[0] <> '_' && not (isalpha name.[0]) then
+      failwith "variable name must start with alphabetic character or underscore";
+
+    let rec loop i =
+      if i >= len then ()
+      else if name.[i] <> '_' && not (isalnum name.[i]) then
+        failwith "variable name contains non-alphanumeric non-underscore character"
+      else loop (i+1)
+    in
+    loop 1;
+
+    let value = variable_of_rpc value in
+    variables := StringMap.add name value !variables;
+
+    (* Which jobs need to be re-evaluated? *)
+    let jobnames = try StringMap.find name !dependencies with Not_found -> [] in
+    reevaluate_whenjobs jobnames;
 
-  (* Which jobs need to be re-evaluated? *)
-  let jobnames = try StringMap.find name !dependencies with Not_found -> [] in
-  reevaluate_whenjobs jobnames
+    `ok
+  with
+    Failure msg -> `error msg
 
 and proc_get_variable name =
   if !debug then Syslog.notice "remote call: get_variable %s" name;
index 58d3ca2..2e64636 100644 (file)
@@ -65,7 +65,7 @@ union variable switch (variable_type t) {
 program When {
   version V1 {
     status reload_file (void) = 1;
-    void set_variable (variable_name, variable) = 2;
+    status set_variable (variable_name, variable) = 2;
     variable get_variable (variable_name) = 3;
     variable_name_list get_variable_names (void) = 4;
     status exit_daemon (void) = 5;
index 9614ef8..cdfca47 100644 (file)
@@ -41,6 +41,9 @@ module StringSet = Set.Make (String)
 
 let (//) = Filename.concat
 
+let isalpha = function 'a'..'z' | 'A'..'Z' -> true | _ -> false
+let isalnum = function 'a'..'z' | 'A'..'Z' | '0'..'9' -> true | _ -> false
+
 let rec filter_map f = function
   | [] -> []
   | x :: xs ->
index f0fb306..73d5084 100644 (file)
@@ -117,6 +117,10 @@ end
 val (//) : string -> string -> string
 (** [dir // file] concatenates directory and file. *)
 
+val isalpha : char -> bool
+val isalnum : char -> bool
+(** Character tests. *)
+
 val filter_map : ('a -> 'b option) -> 'a list -> 'b list
 (** Filter + map. *)
 
index 0810649..60795ba 100644 (file)
@@ -296,7 +296,13 @@ and set_variable name value typ =
       ) in
 
   let client = start_client () in
-  Whenproto_clnt.When.V1.set_variable client (name, value);
+  (match Whenproto_clnt.When.V1.set_variable client (name, value) with
+  | `ok -> ()
+  | `error msg ->
+    eprintf "whenjobs: set: %s\n" msg;
+    suggest_check_server_logs ();
+    exit 1
+  );
   stop_client client
 
 and get_variable name =