package xenstore

  1. Overview
  2. Docs

Source file perms.ml

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(*
 * Copyright (C) Citrix Systems Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 only. with the special
 * exception on linking described in file LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *)

let info fmt = Logging.info "perms" fmt

exception Permission_denied

(* permission of connections *)
open Xs_protocol.ACL

type elt = domid * (perm list)
type t =
  { main: elt;
    target: elt option; }

let superuser : t =
  { main = 0, [READ; WRITE];
    target = None }

let of_domain domid : t =
  { main = (domid, [READ; WRITE]);
    target = None }

let set_target (connection:t)  domid =
  { connection with target = Some (domid, [READ; WRITE]) }

let get_owners (connection:t) =
  match connection.main, connection.target with
  | c1, Some c2 -> [ fst c1; fst c2 ]
  | c1, None    -> [ fst c1 ]

let is_owner (connection:t) id =
  match connection.target with
  | Some target -> fst connection.main = id || fst target = id
  | None        -> fst connection.main = id

let is_dom0 (connection:t) =
  is_owner connection 0

let restrict (connection:t) domid =
  match connection.target, connection.main with
  | None, (0, perms) ->
    info "restricting connection from domid %d to domid %d" 0 domid;
    { connection with main = (domid, perms) }
  | _                -> raise Permission_denied

type permission =
  | READ
  | WRITE
  | CHANGE_ACL
  | DEBUG
  | INTRODUCE
  | ISINTRODUCED
  | RESUME
  | RELEASE
  | SET_TARGET
  | RESTRICT
  | CONFIGURE

let has (t: t) _p =
  if not(is_dom0 t) then raise Permission_denied

(* check if owner of the current connection and of the current node are the same *)
let check_owner (connection:t) (node:Xs_protocol.ACL.t) =
  if not (is_dom0 connection)
  then is_owner connection node.Xs_protocol.ACL.owner
  else true

(* check if the current connection has the requested perm on the current node *)
let check (connection:t) request (node:Xs_protocol.ACL.t) =
  let check_acl domainid =
    let perm =
      if List.mem_assoc domainid node.Xs_protocol.ACL.acl
      then List.assoc domainid node.Xs_protocol.ACL.acl
      else node.Xs_protocol.ACL.other
    in
    match perm, request with
    | Xs_protocol.ACL.NONE, _ ->
      info "Permission denied: Domain %d has no permission" domainid;
      false
    | Xs_protocol.ACL.RDWR, _ -> true
    | Xs_protocol.ACL.READ, READ -> true
    | Xs_protocol.ACL.WRITE, WRITE -> true
    | Xs_protocol.ACL.READ, _ ->
      info "Permission denied: Domain %d has read only access" domainid;
      false
    | Xs_protocol.ACL.WRITE, _ ->
      info "Permission denied: Domain %d has write only access" domainid;
      false
  in
  if true
  && not (is_dom0 connection)
  && not (check_owner connection node)
  && not (List.exists check_acl (get_owners connection))
  then raise Permission_denied


OCaml

Innovation. Community. Security.