cap2 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -32,8 +32,8 @@ $ sudo make install
32
32
  $ gem install cap2
33
33
  ```
34
34
 
35
- Usage
36
- -----
35
+ Process and File Objects
36
+ ------------------------
37
37
 
38
38
  Cap2 provides methods for querying and modifying capabilities for both processes and files.
39
39
 
@@ -45,11 +45,18 @@ Cap2.process(1000) # Returns a Cap2::Process for the process with pid 100
45
45
  Cap2.file('/sbin/init') # Returns a Cap2::File for the /sbin/init file
46
46
  ```
47
47
 
48
+ Querying Capabilities
49
+ ---------------------
50
+
48
51
  Capabilities are referenced using lower cased symbols, and without the CAP_ prefix (e.g. `:kill` represents CAP_KILL).
49
52
 
50
- ### Querying Capabilities
53
+ There are three methods defined on both `Cap2::Process` and `Cap2::File` for querying capabilities:
51
54
 
52
- There are three methods - `permitted?`, `enabled?` and `inheritable?` - defined on both `Cap2::Process` and `Cap2::File` for querying capabilities. Each of these methods, Cap2::File#enabled? being the exception, take a list of capability symbols and return true / false if the capabilities are in / not in the relevant set:
55
+ * `permitted?`
56
+ * `enabled?`
57
+ * `inheritable?`
58
+
59
+ Each of these methods, `Cap2::File#enabled?` being the exception, take a list of capability symbols and return true / false if the capabilities are in / not in the relevant set:
53
60
 
54
61
  ```
55
62
  # the init daemon - all caps permitted & enabled but not inheritable
@@ -63,7 +70,9 @@ init.enabled?(:kill, :chown) # => true
63
70
 
64
71
  init.inheritable?(:chown) # => false
65
72
  init.inheritable?(:fowner, :kill) # => false
73
+ ```
66
74
 
75
+ ```
67
76
  # assume /bin/ping is using file capabilities to enable CAP_NET_RAW on exec
68
77
  ping = Cap2.file('/bin/ping') # => #<Cap2::File @filename="/bin/ping">
69
78
 
@@ -75,15 +84,39 @@ ping.enabled? # => true
75
84
  ping.inheritable?(:net_raw) # => false
76
85
  ```
77
86
 
78
- #### Why does Cap2::File#enabled? not take an arguement?
87
+ ### Why does Cap2::File#enabled? not take an arguement?
79
88
 
80
89
  Under the hood, the file effective set is just a single bit. When enabled, any process which exec's the file will have the capabilities from it's resulting permitted set also in it's effective set.
81
90
 
82
- ### Modifying Capabilities
91
+ Modifying File Capabilities
92
+ ---------------------------
93
+
94
+ The file capability modification methods are:
83
95
 
84
- Cap2 provides different levels of control over process and file capabilities.
96
+ * `permit(capabilities)`
97
+ * `unpermit(capabilities)`
98
+ * `allow_inherit(capabilities)`
99
+ * `disallow_inherit(capabilities)`
100
+ * `enable`
101
+ * `disable`
85
102
 
86
- #### Files
103
+ where `capabilities` can take any of the following forms:
104
+
105
+ ```
106
+ # list of one or more symbols
107
+ (:chown)
108
+ (:mknod, :kill, :mac_admin)
109
+
110
+ # hash with an :only key
111
+ (:only => :fowner)
112
+ (:only => [:lease, :net_raw])
113
+
114
+ # hash with an :except key
115
+ (:except => :sys_time)
116
+ (:except => [:syslog, :fsetid])
117
+ ```
118
+
119
+ ### Permitting capabilities
87
120
 
88
121
  To modify the permitted capabilities of a file (i.e. the capabilities which will be permitted in any process that exec's the file), use `Cap2::File#permit` and `Cap2::File#unpermit`:
89
122
 
@@ -103,6 +136,8 @@ file.unpermit(:chown, :fowner) # => true
103
136
  file.permitted?(:mknod, :chown, :fowner) # => false
104
137
  ```
105
138
 
139
+ ### Enabling capabilities
140
+
106
141
  To modify the effective bit of a file (i.e. whether the resulting permitted capabilities of any process that exec's the file will also be enabled in it's effective set), use `Cap2::File#enable` and `Cap2::File#disable`:
107
142
 
108
143
  ```
@@ -120,6 +155,8 @@ file.disable # => true
120
155
  file.enabled? # => false
121
156
  ```
122
157
 
158
+ ### Inheriting capabilities
159
+
123
160
  To modify the inheritable capabilities of a file (i.e. the capabilities which will be ANDed with the inheritable set of any process that exec's the file to determine which capabilities are in the permitted set of the process), use `Cap2::File#allow_inherit` and `Cap2::File#disallow_inherit`:
124
161
 
125
162
  ```
@@ -136,7 +173,9 @@ file.disallow_inherit(:fowner) # => true
136
173
  file.inheritable?(:fowner) # => false
137
174
  ```
138
175
 
139
- To clear all capabilities for a file, use Cap2::File#clear:
176
+ ### Clearing capabilities
177
+
178
+ To clear all capabilities for a file, use `Cap2::File#clear`:
140
179
 
141
180
  ```
142
181
  Cap2.process.enabled?(:setfcap) # => true - needed to set file capabilities
@@ -158,7 +197,8 @@ file.inheritable?(:kill, :mknod) # => false
158
197
  file.enabled? # => false
159
198
  ```
160
199
 
161
- #### Processes
200
+ Modifying Process Capabilities
201
+ ------------------------------
162
202
 
163
203
  Cap2 can be used to enable / disable capabilities of the current Ruby process.
164
204
 
@@ -79,6 +79,18 @@ VALUE cap2_caps_to_hash(cap_t cap_d) {
79
79
  return caps;
80
80
  }
81
81
 
82
+ VALUE cap2_allcaps(VALUE self) {
83
+ int i;
84
+ VALUE caps;
85
+
86
+ caps = rb_ary_new();
87
+
88
+ for(i = 0; i < __CAP_COUNT; i++)
89
+ rb_ary_push(caps, ID2SYM(rb_intern(cap2_caps[i].name)));
90
+
91
+ return caps;
92
+ }
93
+
82
94
  /*
83
95
  * Convert @pid stored in the given Process object to an int and return it.
84
96
  */
@@ -292,6 +304,7 @@ void Init_cap2(void) {
292
304
  VALUE rb_cCap2Process;
293
305
 
294
306
  rb_mCap2 = rb_define_module("Cap2");
307
+ rb_define_module_function(rb_mCap2, "allcaps", cap2_allcaps, 0);
295
308
 
296
309
  rb_cCap2Process = rb_define_class_under(rb_mCap2, "Process", rb_cObject);
297
310
  rb_define_method(rb_cCap2Process, "getcaps", cap2_process_getcaps, 0);
Binary file
@@ -27,27 +27,27 @@ module Cap2
27
27
  !@caps[:effective].empty?
28
28
  end
29
29
 
30
- # Permit processes executing this file to enable the given capability.
30
+ # Permit processes executing this file to enable the given capabilities.
31
31
  def permit(*capabilities)
32
- @caps[:permitted].merge(capabilities)
32
+ @caps[:permitted].merge parse(capabilities)
33
33
  save
34
34
  end
35
35
 
36
- # Dont permit processes executing this file to enable the given capability.
36
+ # Dont permit processes executing this file to enable the given capabilities.
37
37
  def unpermit(*capabilities)
38
- @caps[:permitted].subtract(capabilities)
38
+ @caps[:permitted].subtract parse(capabilities)
39
39
  save
40
40
  end
41
41
 
42
- # Allow processes executing this file to inherit the given capability.
42
+ # Allow processes executing this file to inherit the given capabilities.
43
43
  def allow_inherit(*capabilities)
44
- @caps[:inheritable].merge(capabilities)
44
+ @caps[:inheritable].merge parse(capabilities)
45
45
  save
46
46
  end
47
47
 
48
- # Dont allow processes executing this file to inherit the given capability.
48
+ # Dont allow processes executing this file to inherit the given capabilities.
49
49
  def disallow_inherit(*capabilities)
50
- @caps[:inheritable].subtract(capabilities)
50
+ @caps[:inheritable].subtract parse(capabilities)
51
51
  save
52
52
  end
53
53
 
@@ -73,5 +73,29 @@ module Cap2
73
73
  def reload
74
74
  @caps = getcaps
75
75
  end
76
+
77
+ def parse(caps)
78
+ if (options = caps.first).is_a? Hash
79
+ if caps.size > 1
80
+ raise(
81
+ ArgumentError,
82
+ 'cannot pass both a hash and a list of capabilities'
83
+ )
84
+ end
85
+
86
+ if options.has_key?(:only) && !options.has_key?(:except)
87
+ Array(options[:only])
88
+ elsif options.has_key?(:except) && !options.has_key?(:only)
89
+ Cap2.allcaps - Array(options[:except])
90
+ else
91
+ raise(
92
+ ArgumentError,
93
+ "expected exactly one of [:only, :except], got #{options.keys}"
94
+ )
95
+ end
96
+ else
97
+ caps
98
+ end
99
+ end
76
100
  end
77
101
  end
@@ -1,3 +1,3 @@
1
1
  module Cap2
2
- Version = '0.2.1'
2
+ Version = '0.2.2'
3
3
  end
@@ -52,14 +52,50 @@ describe Cap2::File do
52
52
  end
53
53
 
54
54
  describe '#permit' do
55
- specify do
56
- expect { running_as_root('permit(:fowner, :kill)') }.to \
57
- change { subject.permitted?(:fowner) }.from(false).to(true)
55
+ context 'with a list of capability symbols' do
56
+ specify do
57
+ expect { running_as_root('permit(:fowner, :kill)') }.to \
58
+ change { subject.permitted?(:fowner) }.from(false).to(true)
59
+ end
60
+
61
+ specify do
62
+ expect { running_as_root('permit(:fowner, :kill)') }.to \
63
+ change { subject.permitted?(:kill) }.from(false).to(true)
64
+ end
58
65
  end
59
66
 
60
- specify do
61
- expect { running_as_root('permit(:fowner, :kill)') }.to \
62
- change { subject.permitted?(:kill) }.from(false).to(true)
67
+ context 'with an :only option' do
68
+ specify do
69
+ expect { running_as_root('permit(:only => :fowner)') }.to \
70
+ change { subject.permitted?(:fowner) }.from(false).to(true)
71
+ end
72
+
73
+ specify do
74
+ expect { running_as_root('permit(:only => :fowner)') }.to_not \
75
+ change { subject.permitted?(:kill) }.from(false)
76
+ end
77
+
78
+ specify do
79
+ expect { running_as_root('permit(:only => [:fowner, :kill])') }.to \
80
+ change { subject.permitted?(:fowner, :kill) }.from(false).to(true)
81
+ end
82
+ end
83
+
84
+ context 'with an :except option' do
85
+ specify do
86
+ expect { running_as_root('permit(:except => :fowner)') }.to \
87
+ change { subject.permitted?(:kill) }.from(false).to(true)
88
+ end
89
+
90
+ specify do
91
+ expect { running_as_root('permit(:except => :fowner)') }.to_not \
92
+ change { subject.permitted?(:fowner) }.from(false)
93
+ end
94
+
95
+ specify do
96
+ expect { running_as_root('permit(:except => [:fowner, :kill])') }.to_not \
97
+ change { subject.permitted?(:fowner, :kill) }.from(false)
98
+ end
63
99
  end
64
100
  end
65
101
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cap2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: