cap2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (C) 2012 Lewis Marshall
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,88 @@
1
+ Cap2
2
+ ====
3
+
4
+ Cap2 is a Ruby library for managing the POSIX 1003.1e capabilities available in Linux kernels. These capabilities are a partitioning of the all powerful root privilege into a set of distinct privileges. See capabilites(7) for more information.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ To install this library, you will need to be running Linux and have the libcap2 library and header files installed.
10
+
11
+ ### Install libcap2
12
+
13
+ #### Ubuntu
14
+
15
+ ```
16
+ $ sudo apt-get install libcap2 libcap-dev
17
+ ```
18
+
19
+ #### From source
20
+
21
+ ```
22
+ $ curl -O http://ftp.de.debian.org/debian/pool/main/libc/libcap2/libcap2_2.22.orig.tar.gz
23
+ $ tar xzf libcap2_2.22.orig.tar.gz
24
+ $ cd libcap2-2.22
25
+ $ make
26
+ $ sudo make install
27
+ ```
28
+
29
+ ### Install the gem
30
+
31
+ ```
32
+ $ gem install cap2
33
+ ```
34
+
35
+ Querying Capabilities
36
+ ---------------------
37
+
38
+ ### Processes
39
+
40
+ Suppose a process with pid 1000 exists with the following capabilities:
41
+
42
+ ```
43
+ Permitted - CAP_CHOWN, CAP_LEASE
44
+ Effective - CAP_CHOWN
45
+ Inheritable - CAP_LEASE
46
+ ```
47
+
48
+ Then:
49
+
50
+ ```
51
+ process = Cap2.process(1000) # => #<Cap2::Process>
52
+
53
+ process.permitted?(:chown) # => true
54
+ process.permitted?(:lease) # => true
55
+ process.permitted?(:fowner) # => false
56
+
57
+ process.effective?(:chown) # => true
58
+ process.effective?(:lease) # => false
59
+
60
+ process.inheritable?(:chown) # => false
61
+ process.inheritable?(:lease) # => true
62
+ ```
63
+
64
+ ### Files
65
+
66
+ Suppose the file "/tmp/cap_test" exists with the following capabilities:
67
+
68
+ ```
69
+ Permitted - CAP_CHOWN, CAP_LEASE
70
+ Effective - CAP_CHOWN
71
+ Inheritable - CAP_LEASE
72
+ ```
73
+
74
+ Then:
75
+
76
+ ```
77
+ file = Cap2.file('/tmp/cap_test') # => #<Cap2::File>
78
+
79
+ file.permitted?(:chown) # => true
80
+ file.permitted?(:lease) # => true
81
+ file.permitted?(:fowner) # => false
82
+
83
+ file.effective?(:chown) # => true
84
+ file.effective?(:lease) # => false
85
+
86
+ file.inheritable?(:chown) # => false
87
+ file.inheritable?(:lease) # => true
88
+ ```
@@ -0,0 +1,11 @@
1
+ require 'rake/extensiontask'
2
+
3
+ Rake::ExtensionTask.new('cap2')
4
+
5
+ require 'rspec/core'
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc 'Run all specs in the spec directory'
9
+ RSpec::Core::RakeTask.new(:spec => [:clobber, :compile]) do |t|
10
+ t.pattern = FileList['spec/**/*_spec.rb']
11
+ end
@@ -0,0 +1,149 @@
1
+ #include <ruby.h>
2
+ #include <errno.h>
3
+ #include <sys/capability.h>
4
+
5
+ static VALUE cap2_has_cap(cap_t cap_d, cap_flag_t set, cap_value_t cap) {
6
+ cap_flag_value_t flag_value = CAP_CLEAR;
7
+
8
+ cap_get_flag(cap_d, cap, set, &flag_value);
9
+
10
+ return flag_value == CAP_SET ? Qtrue : Qfalse;
11
+ }
12
+
13
+ static VALUE cap2_pid_has_cap(VALUE self, VALUE pid, VALUE set, VALUE cap) {
14
+ cap_t cap_d;
15
+ VALUE result;
16
+
17
+ int p = FIX2INT(pid);
18
+
19
+ cap_d = cap_get_pid(p);
20
+
21
+ if (cap_d == NULL) {
22
+ rb_raise(
23
+ rb_eRuntimeError,
24
+ "Failed to get capabilities for proccess %d: (%s)\n",
25
+ p, strerror(errno)
26
+ );
27
+ }
28
+
29
+ set = FIX2INT(set);
30
+ cap = FIX2INT(cap);
31
+
32
+ result = cap2_has_cap(
33
+ cap_d,
34
+ (cap_flag_t) set,
35
+ (cap_value_t) cap
36
+ );
37
+
38
+ cap_free(cap_d);
39
+
40
+ return result;
41
+ }
42
+
43
+ static VALUE cap2_file_has_cap(VALUE self, VALUE filename, VALUE set, VALUE cap) {
44
+ cap_t cap_d;
45
+ VALUE result;
46
+
47
+ char *f = StringValueCStr(filename);
48
+
49
+ cap_d = cap_get_file(f);
50
+
51
+ if (cap_d == NULL && errno != ENODATA) {
52
+ rb_raise(
53
+ rb_eRuntimeError,
54
+ "Failed to get capabilities for file %s: (%s)\n",
55
+ f, strerror(errno)
56
+ );
57
+ }
58
+
59
+ set = FIX2INT(set);
60
+ cap = FIX2INT(cap);
61
+
62
+ result = cap2_has_cap(
63
+ cap_d,
64
+ (cap_flag_t) set,
65
+ (cap_value_t) cap
66
+ );
67
+
68
+ cap_free(cap_d);
69
+
70
+ return result;
71
+ }
72
+
73
+ #define SetsHashSet(key,val) \
74
+ rb_hash_aset(sets_hash, rb_str_new2(key), INT2FIX(val))
75
+
76
+ #define CapsHashSet(key,val) \
77
+ rb_hash_aset(caps_hash, rb_str_new2(key), INT2FIX(val))
78
+
79
+ void Init_cap2(void) {
80
+ VALUE rb_mCap2;
81
+
82
+ // sets_hash and caps_hash act as maps between lower cased
83
+ // names of capabilities (e.g. 'dac_override') and the CAP_
84
+ // constants defined in linux/capability.h and
85
+ // sys/capability.h (e.g. CAP_DAC_OVERRIDE). They are
86
+ // assigned to Cap2::SETS and Cap2::CAPS respectively.
87
+ VALUE sets_hash, caps_hash;
88
+
89
+ rb_mCap2 = rb_define_module("Cap2");
90
+
91
+ sets_hash = rb_hash_new();
92
+ SetsHashSet("permitted", CAP_PERMITTED);
93
+ SetsHashSet("effective", CAP_EFFECTIVE);
94
+ SetsHashSet("inheritable", CAP_INHERITABLE);
95
+ rb_define_const(rb_mCap2, "SETS", sets_hash);
96
+
97
+ caps_hash = rb_hash_new();
98
+ CapsHashSet("chown", CAP_CHOWN);
99
+ CapsHashSet("dac_override", CAP_DAC_OVERRIDE);
100
+ CapsHashSet("dac_read_search", CAP_DAC_READ_SEARCH);
101
+ CapsHashSet("fowner", CAP_FOWNER);
102
+ CapsHashSet("fsetid", CAP_FSETID);
103
+ CapsHashSet("kill", CAP_KILL);
104
+ CapsHashSet("setgid", CAP_SETGID);
105
+ CapsHashSet("setuid", CAP_SETUID);
106
+ CapsHashSet("setpcap", CAP_SETPCAP);
107
+ CapsHashSet("linux_immutable", CAP_LINUX_IMMUTABLE);
108
+ CapsHashSet("net_bind_service", CAP_NET_BIND_SERVICE);
109
+ CapsHashSet("net_broadcast", CAP_NET_BROADCAST);
110
+ CapsHashSet("net_admin", CAP_NET_ADMIN);
111
+ CapsHashSet("net_raw", CAP_NET_RAW);
112
+ CapsHashSet("ipc_lock", CAP_IPC_LOCK);
113
+ CapsHashSet("ipc_owner", CAP_IPC_OWNER);
114
+ CapsHashSet("sys_module", CAP_SYS_MODULE);
115
+ CapsHashSet("sys_rawio", CAP_SYS_RAWIO);
116
+ CapsHashSet("sys_chroot", CAP_SYS_CHROOT);
117
+ CapsHashSet("sys_ptrace", CAP_SYS_PTRACE);
118
+ CapsHashSet("sys_pacct", CAP_SYS_PACCT);
119
+ CapsHashSet("sys_admin", CAP_SYS_ADMIN);
120
+ CapsHashSet("sys_boot", CAP_SYS_BOOT);
121
+ CapsHashSet("sys_nice", CAP_SYS_NICE);
122
+ CapsHashSet("sys_resource", CAP_SYS_RESOURCE);
123
+ CapsHashSet("sys_time", CAP_SYS_TIME);
124
+ CapsHashSet("sys_tty_config", CAP_SYS_TTY_CONFIG);
125
+ CapsHashSet("mknod", CAP_MKNOD);
126
+ CapsHashSet("lease", CAP_LEASE);
127
+ CapsHashSet("audit_write", CAP_AUDIT_WRITE);
128
+ CapsHashSet("audit_control", CAP_AUDIT_CONTROL);
129
+ CapsHashSet("setfcap", CAP_SETFCAP);
130
+ CapsHashSet("mac_override", CAP_MAC_OVERRIDE);
131
+ CapsHashSet("mac_admin", CAP_MAC_ADMIN);
132
+ CapsHashSet("syslog", CAP_SYSLOG);
133
+ CapsHashSet("wake_alarm", CAP_WAKE_ALARM);
134
+ rb_define_const(rb_mCap2, "CAPS", caps_hash);
135
+
136
+ rb_define_module_function(
137
+ rb_mCap2,
138
+ "pid_has_cap?",
139
+ cap2_pid_has_cap,
140
+ 3
141
+ );
142
+
143
+ rb_define_module_function(
144
+ rb_mCap2,
145
+ "file_has_cap?",
146
+ cap2_file_has_cap,
147
+ 3
148
+ );
149
+ }
@@ -0,0 +1,23 @@
1
+ require 'mkmf'
2
+
3
+ unless have_header('sys/capability.h')
4
+ abort <<-EOS
5
+ -----
6
+ ERROR
7
+ -----
8
+ sys/capability.h is missing. You should install the libcap2 header files
9
+
10
+ EOS
11
+ end
12
+
13
+ unless have_library('cap')
14
+ abort <<-EOS
15
+ -----
16
+ ERROR
17
+ -----
18
+ libcap is missing. You should install the libcap2 library
19
+
20
+ EOS
21
+ end
22
+
23
+ create_makefile('cap2')
@@ -0,0 +1,82 @@
1
+ require 'cap2.so'
2
+ require 'cap2/entity'
3
+ require 'cap2/process'
4
+ require 'cap2/file'
5
+
6
+ module Cap2
7
+ # = Cap2
8
+ #
9
+ # Cap2 is a module for querying the POSIX 1003.1e capabilities
10
+ # available in Linux kernels. These capabilities are a
11
+ # partitioning of the all powerful root privilege into a set
12
+ # of distinct privileges.
13
+ class << self
14
+ # A wrapper function around the native Cap2.pid_has_cap?
15
+ # and Cap2.file_has_cap?. Returns true if the given
16
+ # capability is enabled in the given set for the given pid /
17
+ # filename.
18
+ #
19
+ # @param [String, Fixnum] pid_or_filename
20
+ # When a Fixnum, query the capabilities for the process
21
+ # with this value. When a String, query for the file
22
+ # with a filename of this value.
23
+ #
24
+ # @param [Symbol] set
25
+ # One of :permitted, :effective or :inheritable.
26
+ #
27
+ # @param [Symbol] cap
28
+ # A lower cased name of a capability, without the 'CAP_'
29
+ # prefix. For example, :chown would query the CAP_CHOWN
30
+ # capability
31
+ def has_capability?(pid_or_filename, set, cap)
32
+ # See ext/cap2/cap2.c for the definition of SETS and CAPS
33
+ set = SETS[set.to_s]
34
+ cap = CAPS[cap.to_s]
35
+
36
+ case pid_or_filename
37
+ when Fixnum
38
+ pid_has_cap?(pid_or_filename, set, cap)
39
+ when String
40
+ file_has_cap?(pid_or_filename, set, cap)
41
+ else
42
+ raise ArgumentError, "wrong argument type, expected Fixnum or String, got #{pid_or_filename.class}"
43
+ end
44
+ end
45
+
46
+ # Returns a Cap2::Process initialized with the given pid,
47
+ # defaulting to the current pid.
48
+ def process(pid = ::Process.pid)
49
+ check_pid! pid
50
+
51
+ Process.new(pid)
52
+ end
53
+
54
+ # Returns a Cap2::File initialized with the given filename
55
+ def file(filename)
56
+ check_file! filename
57
+
58
+ File.new(filename)
59
+ end
60
+
61
+ private
62
+ # Check that a process with the given pid exists by sending
63
+ # a 0 signal to the process via Process.kill
64
+ def check_pid!(pid)
65
+ ::Process.kill(0, pid)
66
+ rescue Exception => e
67
+ if Errno::ESRCH === e
68
+ raise ProcessNotFound
69
+ end
70
+ end
71
+
72
+ # Check that a file exists with the given filename
73
+ def check_file!(filename)
74
+ unless ::File.exists?(filename)
75
+ raise FileNotFound
76
+ end
77
+ end
78
+ end
79
+
80
+ class ProcessNotFound < StandardError; end
81
+ class FileNotFound < StandardError; end
82
+ end
@@ -0,0 +1,31 @@
1
+ module Cap2
2
+ class Entity
3
+ # = Entity
4
+ #
5
+ # A superclass for the Cap2::Process and Cap2::File
6
+ # classes providing convenience methods for querying
7
+ # permitted, effective and inheritable capabilities.
8
+ #
9
+ # Each method takes a capability argument, a lower
10
+ # cased name of a capability, without the 'CAP_' prefix.
11
+ # For example, :chown would query the CAP_CHOWN capability.
12
+
13
+ def permitted?(capability)
14
+ has?(:permitted, capability)
15
+ end
16
+
17
+ def effective?(capability)
18
+ has?(:effective, capability)
19
+ end
20
+
21
+ def inheritable?(capability)
22
+ has?(:inheritable, capability)
23
+ end
24
+
25
+ private
26
+ def has?(set, cap)
27
+ Cap2.has_capability?(@entity_id, set, cap)
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,11 @@
1
+ module Cap2
2
+ class File < Entity
3
+ # = Cap2::File
4
+ #
5
+ # A class with methods for querying capabilities for the
6
+ # file with filename provided to the initialize method.
7
+ def initialize(filename)
8
+ @entity_id = filename
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Cap2
2
+ class Process < Entity
3
+ # = Cap2::Process
4
+ #
5
+ # A class with methods for querying capabilities for the
6
+ # process with pid provided to the initialize method.
7
+ def initialize(pid)
8
+ @entity_id = pid
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Cap2
2
+ Version = '0.0.1'
3
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cap2 do
4
+ describe '.has_capability?' do
5
+ context 'for processes' do
6
+ context 'when the given process does not have the given capability' do
7
+ it { should_not have_capability(
8
+ Process.pid, :permitted, :dac_override) }
9
+ end
10
+
11
+ context 'when the given process does have the given capability' do
12
+ it { should have_capability(
13
+ 1, :permitted, :dac_override) }
14
+ end
15
+ end
16
+
17
+ context 'for files' do
18
+ let(:file) { Tempfile.new('cap-test') }
19
+
20
+ context 'when the given file does not have the given capability' do
21
+ it { should_not have_capability(
22
+ file.path, :permitted, :dac_override) }
23
+ end
24
+
25
+ context 'when the given file does have the given capability' do
26
+ before(:each) do
27
+ system %{sudo setcap "cap_dac_override+p" #{file.path}}
28
+ end
29
+
30
+ it { should have_capability(
31
+ file.path, :permitted, :dac_override) }
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '.process' do
37
+ let(:process) { double 'process' }
38
+
39
+ before(:each) do
40
+ Cap2::Process.stub(:new => process)
41
+ end
42
+
43
+ context 'called without a pid' do
44
+ it 'should initialize a Cap2::Process with the current pid' do
45
+ Cap2::Process.should_receive(:new).with(Process.pid)
46
+ Cap2.process
47
+ end
48
+
49
+ it 'should return the new Cap2::Process' do
50
+ Cap2.process.should == process
51
+ end
52
+ end
53
+
54
+ context 'called with a pid' do
55
+ let(:pid) { double 'pid' }
56
+
57
+ context "when a process with the given pid doesn't exist" do
58
+ before(:each) do
59
+ Process.stub(:kill).with(0, pid).and_raise(Errno::ESRCH)
60
+ end
61
+
62
+ it 'should raise a Cap2::ProcessNotFound' do
63
+ expect { Cap2.process(pid) }.to \
64
+ raise_error(Cap2::ProcessNotFound)
65
+ end
66
+ end
67
+
68
+ context 'when a process with the given pid does exist' do
69
+ before(:each) do
70
+ Process.stub(:kill).with(0, pid).and_return(1)
71
+ end
72
+
73
+ it 'should initialize a Cap2::Process with the pid' do
74
+ Cap2::Process.should_receive(:new).with(pid)
75
+ Cap2.process(pid)
76
+ end
77
+
78
+ it 'should return the new Cap2::Process' do
79
+ Cap2.process(pid).should == process
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '.file' do
86
+ let(:file) { double 'file' }
87
+ let(:filename) { double 'filename' }
88
+
89
+ before(:each) do
90
+ Cap2::File.stub(:new => file)
91
+ end
92
+
93
+ context "when the file doesn't exist" do
94
+ before(:each) do
95
+ File.stub(:exists?).with(filename).and_return(false)
96
+ end
97
+
98
+ it 'should raise a Cap2::FileNotFound error' do
99
+ expect { Cap2.file(filename) }.to \
100
+ raise_error(Cap2::FileNotFound)
101
+ end
102
+ end
103
+
104
+ context 'when the file does exist' do
105
+ before(:each) do
106
+ File.stub(:exists?).with(filename).and_return(true)
107
+ end
108
+
109
+ it 'should initialize a Cap2::File with the filename' do
110
+ Cap2::File.should_receive(:new).with(filename)
111
+ Cap2.file(filename)
112
+ end
113
+
114
+ it 'should return the new Cap2::File' do
115
+ Cap2.file(filename).should == file
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cap2::File do
4
+ it_behaves_like 'an entity'
5
+ end
6
+
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cap2::Process do
4
+ it_behaves_like 'an entity'
5
+ end
@@ -0,0 +1,22 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require 'cap2'
9
+ require 'tempfile'
10
+ require 'support/entity'
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+
17
+ # Run specs in random order to surface order dependencies. If you find an
18
+ # order dependency and want to debug it, you can fix the order by providing
19
+ # the seed, which is printed after each run.
20
+ # --seed 1234
21
+ config.order = 'random'
22
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'an entity' do
4
+ let(:entity_id) { double 'entity id' }
5
+ let(:capability) { double 'capability' }
6
+
7
+ subject { described_class.new(entity_id) }
8
+
9
+ describe '#permitted?' do
10
+ it 'should call Cap2.has_capability? correctly' do
11
+ Cap2.
12
+ should_receive(:has_capability?).
13
+ with(entity_id, :permitted, capability)
14
+
15
+ subject.permitted?(capability)
16
+ end
17
+ end
18
+
19
+ describe '#effective?' do
20
+ it 'should call Cap2.has_capability? correctly' do
21
+ Cap2.
22
+ should_receive(:has_capability?).
23
+ with(entity_id, :effective, capability)
24
+
25
+ subject.effective?(capability)
26
+ end
27
+ end
28
+
29
+ describe '#inheritable?' do
30
+ it 'should call Cap2.has_capability? correctly' do
31
+ Cap2.
32
+ should_receive(:has_capability?).
33
+ with(entity_id, :inheritable, capability)
34
+
35
+ subject.inheritable?(capability)
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cap2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Lewis Marshall
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-18 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! " Cap2 is a Ruby library for managing the POSIX 1003.1e capabilities\n
15
+ \ available in Linux kernels.\n \n These capabilities are a partitioning
16
+ of the all powerful root\n privilege into a set of distinct privileges.\n \n
17
+ \ See capabilites(7) for more information.\n"
18
+ email:
19
+ - lewismarshall86@gmail.com
20
+ executables: []
21
+ extensions:
22
+ - ext/cap2/extconf.rb
23
+ extra_rdoc_files: []
24
+ files:
25
+ - README.md
26
+ - Rakefile
27
+ - LICENSE
28
+ - ext/cap2/extconf.rb
29
+ - ext/cap2/cap2.c
30
+ - lib/cap2.rb
31
+ - lib/cap2/process.rb
32
+ - lib/cap2/entity.rb
33
+ - lib/cap2/version.rb
34
+ - lib/cap2/file.rb
35
+ - spec/support/entity.rb
36
+ - spec/process_spec.rb
37
+ - spec/cap2_spec.rb
38
+ - spec/spec_helper.rb
39
+ - spec/file_spec.rb
40
+ homepage: https://github.com/lmars/cap2
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.23
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: A Ruby library for managing Linux file and process capabilities
64
+ test_files: []