"domtool" => "/afs/hcoop.net/common/etc/domtool/.domtool"
| _ => OS.Path.joinDirFile {dir = Posix.SysDB.Passwd.home (Posix.SysDB.getpwnam user),
file = ".domtool"}
+
+val worldReadable = ["/usr/share/moin"]
val mailNodes_admin : string list
val domtoolDir : string -> string
+
+val worldReadable : string list
(defconst domtool-types-regexp
- (domtool-syms-re "proxy_target" "proxy_port" "mod_rewrite_cond_flag" "mod_rewrite_flag" "rewrite_arg" "redirect_code" "autoindex_option" "autoindex_width" "homedir_path" "dnsRecord" "apache_option" "authType" "location" "ssl" "ssl_cert_path" "suexec_flag" "web_node" "aliasTarget" "aliasSource" "email" "emailUser" "mail_node" "dnsKind" "master" "dns_node" "soa" "serial" "your_path" "your_group" "your_user" "group" "user" "node" "your_domain_host" "your_domain" "domain" "host" "ip" "no_newlines" "no_spaces" "bool" "string" "int")
+ (domtool-syms-re "proxy_target" "proxy_port" "mod_rewrite_cond_flag" "mod_rewrite_flag" "rewrite_arg" "redirect_code" "autoindex_option" "autoindex_width" "homedir_path" "dnsRecord" "apache_option" "authType" "location" "ssl" "ssl_cert_path" "suexec_flag" "web_node" "aliasTarget" "aliasSource" "email" "emailUser" "mail_node" "dnsKind" "master" "dns_node" "soa" "serial" "readable_path" "your_path" "your_group" "your_user" "group" "user" "node" "your_domain_host" "your_domain" "domain" "host" "ip" "no_newlines" "no_spaces" "bool" "string" "int")
"A regexp that matches Domtool types from the standard library.")
(defconst domtool-contexts-regexp
{{UNIX users and groups that you're allowed to run as}}
extern type your_path;
-{{A filesystem path that you're allowed to use.
+{{A filesystem path that you're allowed to write to.
The set of permitted values is generated from a set of roots by closing it
under the subdirectory relation.}}
+extern type readable_path;
+{{Like [your_path], but also includes some paths that everyone is allowed to
+ read.}}
+
context Domain;
{{Configuration directives specific to an Internet domain}}
{{Basic Apache URL handling}}
-extern val alias : location -> your_path -> [Vhost];
+extern val alias : location -> readable_path -> [Vhost];
{{All requests for the location should be served from the path.}}
extern val scriptAlias : location -> your_path -> [Vhost];
val your_pths = ref SS.empty
fun your_paths () = !your_pths
+val world_readable = SS.addList (SS.empty, Config.worldReadable)
+val readable_pths = ref SS.empty
+fun readable_paths () = !readable_pths
+
fun setUser user =
- (usr := user;
- your_doms := Acl.class {user = getUser (),
- class = "domain"};
- your_usrs := Acl.class {user = getUser (),
- class = "user"};
- your_grps := Acl.class {user = getUser (),
- class = "group"};
- your_pths := Acl.class {user = getUser (),
- class = "path"})
+ let
+ val () = usr := user
+
+ val your_paths = Acl.class {user = getUser (),
+ class = "path"}
+ in
+ your_doms := Acl.class {user = getUser (),
+ class = "domain"};
+ your_usrs := Acl.class {user = getUser (),
+ class = "user"};
+ your_grps := Acl.class {user = getUser (),
+ class = "group"};
+ your_pths := your_paths;
+ readable_pths := SS.union (your_paths, world_readable)
+ end
fun validIp s =
case map Int.fromString (String.fields (fn ch => ch = #".") s) of
fun yourDomain s = SS.member (your_domains (), s)
fun yourUser s = SS.member (your_users (), s)
fun yourGroup s = SS.member (your_groups (), s)
-fun yourPath path =
+fun checkPath paths path =
List.all (fn s => s <> "..") (String.fields (fn ch => ch = #"/") path)
andalso CharVector.all (fn ch => Char.isAlphaNum ch orelse ch = #"." orelse ch = #"/"
orelse ch = #"-" orelse ch = #"_") path
- andalso SS.exists (fn s' => path = s' orelse String.isPrefix (s' ^ "/") path) (your_paths ())
+ andalso SS.exists (fn s' => path = s' orelse String.isPrefix (s' ^ "/") path) (paths ())
+val yourPath = checkPath your_paths
+val readablePath = checkPath readable_paths
fun yourDomainHost s =
yourDomain s
Env.string
yourPath
+val _ = Env.type_one "readable_path"
+ Env.string
+ readablePath
+
val _ = Env.type_one "node"
Env.string
validNode
before OpenSSL.close bio
end
-fun regenerate context =
+fun regenerateEither tc checker context =
let
+ fun ifReal f =
+ if tc then
+ ()
+ else
+ f ()
+
val _ = ErrorMsg.reset ()
val b = basis ()
val () = Tycheck.disallowExterns ()
- val () = Domain.resetGlobal ()
+ val () = ifReal Domain.resetGlobal
val ok = ref true
(ErrorMsg.reset ();
print ("User " ^ user ^ "'s configuration has errors!\n"))
else
- app eval' files
+ app checker files
end
else
()
handle IO.Io {name, function, ...} =>
(print ("IO error processing user " ^ user ^ ": " ^ function ^ ": " ^ name ^ "\n");
ok := false)
- | OS.SysErr (s, _) => (print ("System error processing user " ^ user ^ ": " ^ s ^ "\n");
- ok := false)
+ | exn as OS.SysErr (s, _) => (print ("System error processing user " ^ user ^ ": " ^ s ^ "\n");
+ ok := false)
| ErrorMsg.Error => (ErrorMsg.reset ();
print ("User " ^ user ^ " had a compilation error.\n");
ok := false)
| _ => (print "Unknown exception during regeneration!\n";
ok := false)
in
- app contactNode Config.nodeIps;
- Env.pre ();
+ ifReal (fn () => (app contactNode Config.nodeIps;
+ Env.pre ()));
app doUser (Acl.users ());
- Env.post ();
+ ifReal Env.post;
!ok
end
-fun regenerateTc context =
- let
- val _ = ErrorMsg.reset ()
-
- val b = basis ()
- val () = Tycheck.disallowExterns ()
-
- val () = Domain.resetGlobal ()
-
- val ok = ref true
-
- fun doUser user =
- let
- val _ = Domain.setUser user
- val _ = ErrorMsg.reset ()
-
- val dname = Config.domtoolDir user
- in
- if Posix.FileSys.access (dname, []) then
- let
- val dir = Posix.FileSys.opendir dname
-
- fun loop files =
- case Posix.FileSys.readdir dir of
- NONE => (Posix.FileSys.closedir dir;
- files)
- | SOME fname =>
- if notTmp fname then
- loop (OS.Path.joinDirFile {dir = dname,
- file = fname}
- :: files)
- else
- loop files
-
- val files = loop []
- val (_, files) = Order.order (SOME b) files
- in
- if !ErrorMsg.anyErrors then
- (ErrorMsg.reset ();
- print ("User " ^ user ^ "'s configuration has errors!\n");
- ok := false)
- else
- app (ignore o check) files
- end
- else
- ()
- end
- handle IO.Io _ => ()
- | OS.SysErr (s, _) => print ("System error processing user " ^ user ^ ": " ^ s ^ "\n")
- | ErrorMsg.Error => (ErrorMsg.reset ();
- print ("User " ^ user ^ " had a compilation error.\n"))
- | _ => print "Unknown exception during -tc regeneration!\n"
- in
- app doUser (Acl.users ());
- !ok
- end
+val regenerate = regenerateEither false eval'
+val regenerateTc = regenerateEither true (ignore o check)
fun rmuser user =
let