etcutils 0.1.5-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ data.tar.gz: 78693dd7e391e09bf3217755eec9d8eb5be4c7c3
4
+ metadata.gz: c457e9afacd35cce648123f0e14d9d7440537621
5
+ SHA512:
6
+ data.tar.gz: 70678a1790e113347c0f781aa2e48e750a237bb2b342a8587a3286e02a5f66ddb02e3b74abf4ef412d86fa190b369b12878c6b1c550cffef6cd902bcfb0a727a
7
+ metadata.gz: a4b448b257d94dcce0efc79e1582162d888db68b9e4fde01a9071510555c8dc1514bcd14979ec3654399ea73815ae12baf062eac27e4cf2014f0563e52f939a2
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ Makefile
2
+ *.*o
3
+ *.log
4
+ *~
5
+ *.gem
6
+ *.rbc
7
+ .bundle
8
+ .config
9
+ .yardoc
10
+ Gemfile.lock
11
+ InstalledFiles
12
+ _yardoc
13
+ coverage
14
+ doc/
15
+ lib/bundler/man
16
+ pkg
17
+ rdoc
18
+ spec/reports
19
+ test/tmp
20
+ test/version_tmp
21
+ tmp
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 David Campbell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,322 @@
1
+ EtcUtils
2
+ ======
3
+
4
+ Ruby C Extension for read and write access to the Linux user database.
5
+
6
+ gem install etcutils
7
+
8
+ This gem can have catastrophic effects on your system if used incorrectly. I eventually would like to get to the point that it does all the hard thinking for you when it comes to writing to file, but for now you'll need to write your own tmp file (like /etc/passwd-) before moving it into place. This has worked for years for ```useradd``` and ```adduser``` and you should try keep that same mentality.
9
+
10
+ ## Deprecation Warning
11
+
12
+ NOTE: In i386, #to_s was removed in 0.1.5.
13
+
14
+ In the transitional release 0.1.5, the Struct method #to_s should no longer be used to print UserDB style strings. I'm not printing a warning when it is used, however, since #inspect calls #to_s and warnings would get annoying quickly.
15
+
16
+ The #to_s method will be removed from EtcUtils in release 1.0.0 (see feature/classes), which is scheduled to be released in late May/early June.
17
+
18
+ Moving forward, please use #to_entry in-place of #to_s. See [parse](#parse) for more.
19
+
20
+ I apologize for the inconvience.
21
+
22
+
23
+ ## Know Issues
24
+
25
+ Verified on Ubuntu 12.04, nsswitch.conf is misconfigured due to a known [bug](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=699089). You will be unable to manipulate /etc/gshadow until this line is added to /etc/nsswitch.conf.
26
+
27
+ gshadow: files
28
+
29
+
30
+ ## Structs
31
+
32
+ ##### EtcUtils::Passwd
33
+
34
+ ```ruby
35
+ EtcUtils.find_pwd(1 || 'daemon')
36
+ EtcUtils::Passwd.find('daemon' || 1)
37
+ => # <struct EtcUtils::Passwd name="daemon", passwd="x", uid=1, gid=1, gecos="daemon", dir="/usr/sbin", shell="/bin/sh">
38
+ ```
39
+
40
+ * `:name`: This is the user’s login name. It should not contain capital letters.
41
+
42
+ * `:passwd`: This is either the encrypted user password, an asterisk (*), or the letter aqxaq. (See `pwconv(8)` for an explanation of aqxaq.)
43
+
44
+ * `:uid`: The privileged root login account (superuser) has the user ID 0.
45
+
46
+ * `:gid`: This is the numeric primary group ID for this user. (Additional groups for the user are defined in the system group file; see `group(5)`).
47
+
48
+ * `:gecos`: This field (sometimes called the “comment field”) is optional and used only for informational purposes. Usually, it contains the full username. Some programs (for example, `finger(1)`) display information from this field. GECOS stands for “General Electric Comprehensive Operating System”, which was renamed to GCOS when GE’s large systems division was sold to Honeywell. Dennis Ritchie has reported: “Sometimes we sent printer output or batch jobs to the GCOS machine. The gcos field in the password file was a place to stash the information for the $IDENTcard. Not elegant.”
49
+
50
+ * `:dir`: This is the user’s home directory: the initial directory where the user is placed after logging in. The value in this field is used to set the HOME environment variable.
51
+
52
+ * `:shell`: This is the program to run at login (if empty, use /bin/sh). If set to a nonexistent executable, the user will be unable to login through `login(1)`. The value in this field is used to set the SHELL environment variable.
53
+
54
+
55
+ ##### EtcUtils::Group
56
+
57
+ ```ruby
58
+ EtcUtils.find_grp(1 || 'daemon')
59
+ EtcUtils::Group.find('daemon' || 1)
60
+ => #<struct EtcUtils::Group name="daemon", passwd="x", gid=1, members=[]>
61
+ ```
62
+
63
+ * `:name`: The name of the group.
64
+
65
+ * `:passwd`: The (encrypted) group password. If this field is empty, no password is needed.
66
+
67
+ * `:gid`: The numeric group ID.
68
+
69
+ * `:members`: A list of the usernames that are members of this group, separated by commas.
70
+
71
+ ##### EtcUtils::Shadow
72
+
73
+ The user must be able to read `SHADOW` or nil is returned.
74
+
75
+ ```ruby
76
+ SHADOW
77
+ => "/etc/shadow"
78
+ EtcUtils.find_spwd(1 || 'daemon')
79
+ EtcUtils::Shadow.find('daemon' || 1)
80
+ => #<struct EtcUtils::Shadow name="daemon", passwd="*", last_change=15729, min_change=0, max_change=99999, warn=7, inactive=-1, expire=-1, flag=-1>
81
+ ```
82
+
83
+ * `:name`: This is the user’s login name. It should not contain capital letters.
84
+
85
+ * `:passwd`: Refer to crypt(3) for details on how this string is interpreted. If the password field contains some string that is not a valid result of crypt(3), for instance ! or *, the user will not be able to use a unix password to log in (but the user may log in the system by other means). This field may be empty, in which case no passwords are required to authenticate as the specified login name. However, some applications which read the /etc/shadow file may decide not to permit any access at all if the password field is empty. A password field which starts with a exclamation mark means that the password is locked. The remaining characters on the line represent the password field before the password was locked.
86
+
87
+ * `:last_change`: The date of the last password change, expressed as the number of days since Jan 1, 1970. The value 0 has a special meaning, which is that the user should change her pasword the next time she will log in the system. An empty field means that password aging features are disabled.
88
+
89
+ * `:min_change`: The minimum password age is the number of days the user will have to wait before she will be allowed to change her password again. An empty field and value 0 mean that there are no minimum password age.
90
+
91
+ * `:max_change`: The maximum password age is the number of days after which the user will have to change her password. After this number of days is elapsed, the password may still be valid. The user should be asked to change her password the next time she will log in. An empty field means that there are no maximum password age, no password warning period, and no password inactivity period (see below). If the maximum password age is lower than the minimum password age, the user cannot change her password.
92
+
93
+ * `:warn`: The number of days before a password is going to expire (see the maximum password age above) during which the user should be warned. An empty field and value 0 mean that there are no password warning period.
94
+
95
+ * `:inactive`: The number of days after a password has expired (see the maximum password age above) during which the password should still be accepted (and the user should update her password during the next login). After expiration of the password and this expiration period is elapsed, no login is possible using the current user’s password. The user should contact her administrator. An empty field means that there are no enforcement of an inactivity period.
96
+
97
+ * `:expire`: The date of expiration of the account, expressed as the number of days since Jan 1, 1970. Note that an account expiration differs from a password expiration. In case of an acount expiration, the user shall not be allowed to login. In case of a password expiration, the user is not allowed to login using her password. An empty field means that the account will never expire. The value 0 should not be used as it is interpreted as either an account with no expiration, or as an expiration on Jan 1, 1970.
98
+
99
+ * `:flag`: This field is reserved for future use.
100
+
101
+
102
+ ##### EtcUtils::GShadow
103
+
104
+ If you're having trouble with GShadow, even as root, please see [known issues](#known-issues). Your nsswitch.conf file may contain a known bug.
105
+
106
+ The user must be able to read `GSHADOW` or nil is returned.
107
+
108
+ ```ruby
109
+ GSHADOW
110
+ => "/etc/gshadow"
111
+ EtcUtils.find_sgrp('daemon' || 1)
112
+ EtcUtils::GShadow.find('daemon' || 1)
113
+ EtcUtils::Gshadow.find('daemon' || 1)
114
+ => #<struct EtcUtils::GShadow name="daemon", passwd="*", admins=[], members=[]>
115
+ ```
116
+
117
+ * `:name`: It must be a valid group name, which exist on the system.
118
+
119
+ * `:passwd`: Refer to `crypt(3)` for details on how this string is interpreted. If the password field contains some string that is not a valid result of `crypt(3)`, for instance ! or *, users will not be able to use a unix password to access the group (but group members do not need the password). The password is used when an user who is not a member of the group wants to gain the permissions of this group (see `newgrp(1)`). This field may be empty, in which case only the group members can gain the group permissions. A password field which starts with a exclamation mark means that the password is locked. The remaining characters on the line represent the password field before the password was locked. This password supersedes any password specified in _/etc/group_.
120
+
121
+ * `:admins`: It must be a comma-separated list of user names. Administrators can change the password or the members of the group. Administrators also have the same permissions as the members (see below).
122
+
123
+ * `:members`: It must be a comma-separated list of user names. Members can access the group without being prompted for a password. You should use the same list of users as in _/etc/group_.
124
+
125
+
126
+ # Usage
127
+
128
+ ## File locks
129
+
130
+ Passing a block to `EtcUtils.lock` is the preferred method of locking files, as unlock is always called regardless of exceptions
131
+
132
+ ```ruby
133
+ > begin
134
+ > lock {
135
+ > puts "INSIDE BLOCK: #{locked?}"
136
+ > raise "foobar"
137
+ > }
138
+ > rescue
139
+ > puts "RESCUED: #{locked?}"
140
+ > end
141
+ => INSIDE BLOCK: true
142
+ => RESCUED: false
143
+ ```
144
+
145
+ `:lckpwdf` `:lock`: Locking files will return true if locked. Calling lock on a locked file will return true. A return of false indicates lock failure.
146
+
147
+ `:ulckpwdf` `:unlock`: Unlocking will return true upon success. Subsequent calls against an unlocked file will return false.
148
+
149
+ To keep confusion at bay, calling `:locked?` will always return the true state of the lock.
150
+
151
+ ```ruby
152
+ EtcUtils.lckpwdf
153
+ => true
154
+ EtcUtils.lock
155
+ => true
156
+ EtcUtils.lock
157
+ => true
158
+ EtcUtils.locked?
159
+ => true
160
+ EtcUtils.ulckpwdf
161
+ => true
162
+ EtcUtils.ulckpwdf
163
+ => false
164
+ EtcUtils.unlock
165
+ => false
166
+ EtcUtils.locked?
167
+ => false
168
+ ```
169
+
170
+ ---
171
+
172
+ The below should apply to any of the above structs. If you find a bug, <b>please</b> open an issue.
173
+
174
+ XX can be replaced with
175
+
176
+ * pw # PASSWD
177
+ * gr # GROUP
178
+ * sp # SHADOW
179
+ * sg # GSHADOW
180
+
181
+ ## setXXent and getXXent
182
+
183
+ The `EtcUtils.setpwent` and `EtcUtils::Passwd.set` functions rewind to the beginning of the password database.
184
+
185
+ The `EtcUtils.endpwent` and `EtcUtils::Passwd.end` functions are used to close the password database after all processing has been performed.
186
+
187
+ Helper functions (literal 'XX') `EtcUtils.setXXent` and `EtcUtils.endXXent` rewind or close all database files.
188
+
189
+
190
+ ## Retrieving Entries
191
+
192
+ `#set` is not required on the initial attempt at retrieving entries.
193
+
194
+ ### getXXent
195
+
196
+ Calling `EtcUtils.getgrent` and `EtcUtils::Group.get` retrieves the first entry from the group database.
197
+
198
+ ```ruby
199
+ EtcUtils.getgrent
200
+ => #<struct EtcUtils::Group name="root", passwd="x", gid=0, members=[]>
201
+ ...
202
+ EtcUtils::Group.get
203
+ => #<struct EtcUtils::Group name="adm", passwd="x", gid=4, members=["ubuntu", "foobar"]>
204
+ EtcUtils.setgrent
205
+ => nil
206
+ EtcUtils::Group.get
207
+ => #<struct EtcUtils::Group name="root", passwd="x", gid=0, members=[]>
208
+ ```
209
+
210
+ ### find
211
+
212
+ `EtcUtils::GShadow.find` can be called with either a string or an integer. In the case of shadow files, the corresponding etc file will be queried by uid/gid and returned.
213
+
214
+ ```ruby
215
+ EtcUtils::GShadow.find 'adm'
216
+ => #<struct EtcUtils::Group name="adm", passwd="x", gid=4, members=["ubuntu", "foobar"]>
217
+ EtcUtils::GShadow.find 4
218
+ => #<struct EtcUtils::Group name="adm", passwd="x", gid=4, members=["ubuntu", "foobar"]>
219
+ ```
220
+
221
+ ## New Entries
222
+
223
+ ### parse
224
+
225
+ If an entry already exists in the corresponding file, that object (un-altered) is returned.
226
+
227
+ ```ruby
228
+ p = EtcUtils::Passwd.find 1
229
+ => #<struct EtcUtils::Passwd name="daemon", passwd="x", uid=1, gid=1, gecos="daemon", dir="/usr/sbin", shell="/bin/sh">
230
+ p.uid = 9999
231
+ => 9999
232
+ p.to_entry
233
+ => "daemon:x:9999:1:daemon:/usr/sbin:/bin/sh"
234
+ EtcUtils::Passwd.parse(p.to_entry)
235
+ => #<struct EtcUtils::Passwd name="daemon", passwd="x", uid=1, gid=1, gecos="daemon", dir="/usr/sbin", shell="/bin/sh">
236
+ ```
237
+
238
+ If no entry is found, the new object is returned.
239
+
240
+ If uid/gid fields are left blank, the next available id is returned.
241
+
242
+ ```ruby
243
+ EtcUtils::Passwd.parse("foobar:x:::Foobar User:/home/foobar:/bin/shell")
244
+ => #<struct EtcUtils::Passwd name="foobar", passwd="x", uid=11, gid=11, gecos="Foobar User", dir="/home/foobar", shell="/bin/shell">
245
+ ```
246
+ ### new
247
+
248
+ When called without args, an empty struct is returned. When called with args, those args are used to populate the object.
249
+
250
+ ```ruby
251
+ EtcUtils::GShadow.new("foobar", '!', nil, ['sudo','adm'])
252
+ => #<struct EtcUtils::GShadow name="foobar", passwd="!", admins=nil, members=["sudo", "adm"]>
253
+ EtcUtils::GShadow.new
254
+ => #<struct EtcUtils::GShadow name=nil, passwd=nil, admins=nil, members=nil>
255
+ ```
256
+ ## Writing Entries
257
+
258
+ **Please be careful when you're writing to user database files.**
259
+
260
+ Before writing to any file, you should first create a backup. Conventional nomenclature is to append a dash to the end of the string. You'll also need you preserve file permissions. See `File.stat`.
261
+
262
+ ```ruby
263
+ GSHADOW + '-'
264
+ => "/etc/gshadow-"
265
+
266
+ stat = File.stat(GSHADOW).dup
267
+ File.open(GSHADOW + '-', 'w+', 0600) { |bf| bf.puts IO.readlines(GSHADOW) }
268
+
269
+ if stat.size != File.stat(GSHADOW + '-').size
270
+ raise_retry "#{GSHADOW} backup error"
271
+ end
272
+ ```
273
+
274
+ To update etc files, you should write all entries, including your updates, first to a temp file.
275
+
276
+ ```ruby
277
+ tmp = "/etc/_#{SHADOW.split('/').last}"
278
+ fh = File.open(SHADOW, 'r')
279
+
280
+ EtcUtils.lock {
281
+ File.open(tmp, File::RDWR|File::CREAT, 0600) { |tmp_fh|
282
+ while ( ent = EtcUtils::Shadow.get )
283
+ ent.fputs(tmp_fh)
284
+ end
285
+ }
286
+ }
287
+ fh.close
288
+ ```
289
+
290
+ ## Next UID/GID
291
+
292
+ `:next_uid` will store and increment the next available uid. Each time next_uid is called, that counter is incremented to the next available.
293
+
294
+ `:next_gid` will store and increment the next available gid. Each time next_gid is called, that counter is incremented to the next available.
295
+
296
+ ```ruby
297
+ EtcUtils.next_uid = 12
298
+ => 12
299
+ EtcUtils.next_uid
300
+ => 12
301
+ EtcUtils.next_uid
302
+ => 14
303
+ ```
304
+
305
+ `:parse` assigns `:next_uid` to `:next_gid` then confirmed as available. This attempts uid/gid in sync for new users.
306
+
307
+
308
+ ```ruby
309
+ EtcUtils.next_uid = 1000
310
+ => 1000
311
+ EtcUtils::Passwd.parse("foobar:x:::Foobar User:/home/foobar:/bin/shell")
312
+ => #<struct EtcUtils::Passwd name="foobar", passwd="x", uid=1016, gid=1016, gecos="Foobar User", dir="/home/foobar", shell="/bin/shell">
313
+ ```
314
+
315
+ Although, when calling `:next_uid` or `:next_gid` they are not kept in sync. When creating new entries, it's recommended allow parse or new to manage uid/gids rather than assigning them yourself.
316
+
317
+ ```ruby
318
+ EtcUtils.next_uid = 19
319
+ => 19
320
+ EtcUtils.next_gid
321
+ => 1017
322
+ ```
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require "rake"
2
+ require "rake/testtask"
3
+ require "bundler/gem_tasks"
4
+ require 'rake/extensiontask'
5
+
6
+ desc "Default: run unit tests."
7
+ task :default => :test
8
+
9
+ desc "Test EtcUtils"
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << "tests"
12
+ t.test_files = FileList['tests/**/test_*.rb']
13
+ end
14
+
15
+ Rake::ExtensionTask.new('etcutils')
data/etcutils.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.platform = Gem::Platform::CURRENT
5
+ spec.name = "etcutils"
6
+ spec.version = "0.1.5"
7
+ spec.author = "David Campbell"
8
+ spec.email = "david@mrcampbell.org"
9
+ spec.description = "Ruby Extension that allows for reads and writes to the /etc user db."
10
+ spec.summary = %q{This gem is specific to *nix environments. It's a rewrite of libshadow-ruby allowing for reads and writes to passwd,shadow,group, and gshadow /etc files. There are probably still bugs, so use at your own risk.}
11
+ spec.homepage = "https://github.com/dacamp/etcutils"
12
+ spec.has_rdoc = false
13
+
14
+ spec.license = 'MIT'
15
+ spec.require_path = '.'
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+
19
+ spec.extensions = ['ext/etcutils/extconf.rb']
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rake-compiler"
24
+ end