etcutils 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +22 -0
- data/.travis.yml +19 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +20 -0
- data/LICENSE +20 -0
- data/README.md +335 -0
- data/Rakefile +16 -0
- data/etcutils.gemspec +27 -0
- data/ext/etcutils/etcutils.c +1398 -0
- data/ext/etcutils/etcutils.h +189 -0
- data/ext/etcutils/extconf.rb +51 -0
- data/ext/etcutils/group.c +192 -0
- data/ext/etcutils/passwd.c +297 -0
- data/lib/etcutils.rb +4 -0
- data/lib/etcutils/version.rb +3 -0
- data/tests/README +141 -0
- data/tests/etcutils_test_helper.rb +8 -0
- data/tests/root/etc_utils.rb +5 -0
- data/tests/root/gshadow_tests.rb +153 -0
- data/tests/root/locking.rb +23 -0
- data/tests/root/shadow_tests.rb +161 -0
- data/tests/test_etc_utils.rb +107 -0
- data/tests/test_eu_locking.rb +15 -0
- data/tests/test_eu_next_uid_next_gid.rb +32 -0
- data/tests/test_eu_sgetpwent.rb +91 -0
- data/tests/test_group_class.rb +128 -0
- data/tests/test_passwd_class.rb +125 -0
- data/tests/user/etc_utils.rb +6 -0
- data/tests/user/locking.rb +7 -0
- metadata +119 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
#include "extconf.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include <errno.h>
|
4
|
+
|
5
|
+
|
6
|
+
#define EUVERSION "0.1.5"
|
7
|
+
|
8
|
+
#ifdef HAVE_RUBY_IO_H
|
9
|
+
#include "ruby/io.h"
|
10
|
+
#define RTIME_VAL(x) (x)
|
11
|
+
#else
|
12
|
+
#include "rubyio.h"
|
13
|
+
#define RTIME_VAL(x) (x.tv_sec)
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#ifdef HAVE_SHADOW_H
|
17
|
+
#include <shadow.h>
|
18
|
+
#ifndef SHADOW
|
19
|
+
#define SHADOW "/etc/shadow"
|
20
|
+
#endif
|
21
|
+
#define PW_DEFAULT_PASS setup_safe_str("x")
|
22
|
+
#else
|
23
|
+
#define PW_DEFAULT_PASS setup_safe_str("*")
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#ifdef HAVE_PWD_H
|
27
|
+
#include <pwd.h>
|
28
|
+
#ifndef PASSWD
|
29
|
+
#define PASSWD "/etc/passwd"
|
30
|
+
#endif
|
31
|
+
#endif
|
32
|
+
|
33
|
+
#ifdef HAVE_GSHADOW_H
|
34
|
+
#include <gshadow.h>
|
35
|
+
#elif defined(HAVE_GSHADOW__H)
|
36
|
+
#include <gshadow_.h>
|
37
|
+
#define HAVE_GSHADOW_H 1
|
38
|
+
#endif
|
39
|
+
|
40
|
+
#ifdef HAVE_GSHADOW_H
|
41
|
+
#ifndef GSHADOW
|
42
|
+
#define GSHADOW "/etc/gshadow"
|
43
|
+
#endif
|
44
|
+
#endif
|
45
|
+
|
46
|
+
#ifdef HAVE_GRP_H
|
47
|
+
#include <grp.h>
|
48
|
+
#ifndef GROUP
|
49
|
+
#define GROUP "/etc/group"
|
50
|
+
#endif
|
51
|
+
#endif
|
52
|
+
|
53
|
+
#ifndef DEFAULT_SHELL
|
54
|
+
#define DEFAULT_SHELL "/bin/bash"
|
55
|
+
#endif
|
56
|
+
|
57
|
+
#ifdef HAVE_ST_SG_NAMP
|
58
|
+
#define SGRP_NAME(s) (s)->sg_namp
|
59
|
+
#else
|
60
|
+
#define SGRP_NAME(s) (s)->sg_name
|
61
|
+
#endif
|
62
|
+
|
63
|
+
#ifndef HAVE_EACCESS
|
64
|
+
extern int eaccess(const char*, int);
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#ifdef HAVE_STRUCT_RB_IO_T_PATHV
|
68
|
+
#define RFILE_PATH(x) (RFILE(x)->fptr)->pathv
|
69
|
+
#else
|
70
|
+
#define RFILE_PATH(x) ( setup_safe_str( (RFILE(x)->fptr)->path ) )
|
71
|
+
#endif
|
72
|
+
|
73
|
+
#ifdef HAVE_RB_IO_STDIO_FILE
|
74
|
+
#define RFILE_FPTR(x) rb_io_stdio_file( RFILE(x)->fptr )
|
75
|
+
#else
|
76
|
+
#define RFILE_FPTR(x) (RFILE(x)->fptr)->f
|
77
|
+
#endif
|
78
|
+
|
79
|
+
#ifndef RSTRING_BLANK_P
|
80
|
+
#define RSTRING_BLANK_P(x) (NIL_P(x) || (RSTRING_LEN(x) <= 0))
|
81
|
+
#endif
|
82
|
+
|
83
|
+
#ifndef UIDT2NUM
|
84
|
+
#define UIDT2NUM(v) LONG2NUM(v)
|
85
|
+
#endif
|
86
|
+
#ifndef NUM2UIDT
|
87
|
+
#define NUM2UIDT(v) NUM2LONG(v)
|
88
|
+
#endif
|
89
|
+
#ifndef GIDT2NUM
|
90
|
+
#define GIDT2NUM(v) LONG2NUM(v)
|
91
|
+
#endif
|
92
|
+
#ifndef NUM2GIDT
|
93
|
+
#define NUM2GIDT(v) NUM2LONG(v)
|
94
|
+
#endif
|
95
|
+
|
96
|
+
#ifndef INT2QFIX
|
97
|
+
#define INT2QFIX(v) (v >= 0 ? INT2FIX(v) : Qnil)
|
98
|
+
#endif
|
99
|
+
#ifndef UINT2QFIX
|
100
|
+
#define UINT2QFIX(v) INT2QFIX( (int)v )
|
101
|
+
#endif
|
102
|
+
|
103
|
+
#ifndef QFIX2INT
|
104
|
+
#define QFIX2INT(v) (RTEST(v) ? FIX2INT(v) : (long)-1 )
|
105
|
+
#endif
|
106
|
+
#ifndef QFIX2ULONG
|
107
|
+
#define QFIX2ULONG(v) (RTEST(v) ? FIX2ULONG(v) : (unsigned long)-1)
|
108
|
+
#endif
|
109
|
+
|
110
|
+
extern ID id_name, id_passwd, id_uid, id_gid;
|
111
|
+
extern VALUE mEtcUtils;
|
112
|
+
|
113
|
+
extern VALUE rb_cPasswd;
|
114
|
+
extern VALUE rb_cShadow;
|
115
|
+
extern VALUE rb_cGroup;
|
116
|
+
extern VALUE rb_cGshadow;
|
117
|
+
|
118
|
+
/* EU helper functions */
|
119
|
+
extern VALUE next_uid( int argc, VALUE *argv, VALUE self);
|
120
|
+
extern VALUE next_gid( int argc, VALUE *argv, VALUE self);
|
121
|
+
extern VALUE iv_get_time(VALUE self, const char *name);
|
122
|
+
extern VALUE iv_set_time(VALUE self, VALUE v, const char *name);
|
123
|
+
extern VALUE rb_current_time();
|
124
|
+
extern void eu_errno(VALUE str);
|
125
|
+
extern void ensure_file(VALUE io);
|
126
|
+
extern void ensure_writes(VALUE io, int t);
|
127
|
+
#define Check_Writes(v,t) ensure_writes((VALUE)(io),(int)(t));
|
128
|
+
extern void ensure_eu_type(VALUE self, VALUE klass);
|
129
|
+
#define Check_EU_Type(v,t) ensure_eu_type((VALUE)(v),(VALUE)(t))
|
130
|
+
|
131
|
+
extern char** setup_char_members(VALUE ary);
|
132
|
+
extern void free_char_members(char ** mem, int c);
|
133
|
+
|
134
|
+
extern VALUE setup_safe_str(const char *str);
|
135
|
+
extern VALUE setup_safe_array(char **arr);
|
136
|
+
|
137
|
+
#ifdef HAVE_SHADOW_H
|
138
|
+
extern VALUE setup_shadow(struct spwd *shadow);
|
139
|
+
#endif
|
140
|
+
extern VALUE setup_passwd(struct passwd *pwd);
|
141
|
+
|
142
|
+
extern VALUE setup_group(struct group *grp);
|
143
|
+
#if defined(HAVE_GSHADOW_H) || defined(HAVE_GSHADOW__H)
|
144
|
+
extern VALUE setup_gshadow(struct sgrp *sgroup);
|
145
|
+
#endif
|
146
|
+
|
147
|
+
extern VALUE eu_to_entry(VALUE self, VALUE(*user_to)(VALUE, VALUE));
|
148
|
+
|
149
|
+
extern VALUE eu_setpwent(VALUE self);
|
150
|
+
extern VALUE eu_setspent(VALUE self);
|
151
|
+
extern VALUE eu_setgrent(VALUE self);
|
152
|
+
extern VALUE eu_setsgent(VALUE self);
|
153
|
+
|
154
|
+
extern VALUE eu_endpwent(VALUE self);
|
155
|
+
extern VALUE eu_endspent(VALUE self);
|
156
|
+
extern VALUE eu_endsgent(VALUE self);
|
157
|
+
extern VALUE eu_endgrent(VALUE self);
|
158
|
+
|
159
|
+
extern VALUE eu_getpwent(VALUE self);
|
160
|
+
extern VALUE eu_getspent(VALUE self);
|
161
|
+
extern VALUE eu_getgrent(VALUE self);
|
162
|
+
extern VALUE eu_getsgent(VALUE self);
|
163
|
+
|
164
|
+
extern VALUE eu_getpwd(VALUE self, VALUE v);
|
165
|
+
extern VALUE eu_getspwd(VALUE self, VALUE v);
|
166
|
+
extern VALUE eu_getgrp(VALUE self, VALUE v);
|
167
|
+
extern VALUE eu_getsgrp(VALUE self, VALUE v);
|
168
|
+
|
169
|
+
extern VALUE eu_sgetpwent(VALUE self, VALUE nam);
|
170
|
+
extern VALUE eu_sgetspent(VALUE self, VALUE nam);
|
171
|
+
extern VALUE eu_sgetgrent(VALUE self, VALUE nam);
|
172
|
+
extern VALUE eu_sgetsgent(VALUE self, VALUE nam);
|
173
|
+
/* END EU helper functions */
|
174
|
+
|
175
|
+
/* EU User functions */
|
176
|
+
extern VALUE user_putpwent(VALUE self, VALUE io);
|
177
|
+
extern VALUE user_putspent(VALUE self, VALUE io);
|
178
|
+
/* END EU User functions */
|
179
|
+
|
180
|
+
/* EU Group functions */
|
181
|
+
extern VALUE group_putgrent(VALUE self, VALUE io);
|
182
|
+
extern VALUE group_putsgent(VALUE self, VALUE io);
|
183
|
+
/* END EU Group functions */
|
184
|
+
|
185
|
+
extern VALUE rb_ary_uniq_bang(VALUE ary);
|
186
|
+
|
187
|
+
extern void Init_etcutils_main();
|
188
|
+
extern void Init_etcutils_user();
|
189
|
+
extern void Init_etcutils_group();
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# extconf.rb
|
3
|
+
#
|
4
|
+
# Modified at: <2013/07/04 16:12:45 by dcampbell>
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'mkmf'
|
8
|
+
|
9
|
+
have_header('ruby/io.h')
|
10
|
+
have_struct_member("struct rb_io_t", "pathv", "ruby/io.h")
|
11
|
+
have_func('rb_io_stdio_file')
|
12
|
+
have_func('eaccess')
|
13
|
+
|
14
|
+
have_header('etcutils.h')
|
15
|
+
|
16
|
+
if (have_header('pwd.h') && have_header('grp.h'))
|
17
|
+
short_v = ['pw','gr']
|
18
|
+
|
19
|
+
if have_header('shadow.h')
|
20
|
+
short_v << 'sp'
|
21
|
+
end
|
22
|
+
|
23
|
+
["gshadow.h","gshadow_.h"].each do |h|
|
24
|
+
short_v << 'sg'
|
25
|
+
if have_header(h)
|
26
|
+
nam = "sg_nam"+ (h =~ /_/ ? 'e' : 'p')
|
27
|
+
[nam, "sg_passwd", "sg_adm", "sg_mem"].each do |m|
|
28
|
+
have_struct_member("struct sgrp", m, h)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
have_func("lckpwdf")
|
34
|
+
have_func("ulckpwdf")
|
35
|
+
|
36
|
+
short_v.each do |h|
|
37
|
+
["get#{h}ent","sget#{h}ent","fget#{h}ent","put#{h}ent","set#{h}ent","end#{h}ent"].each do |func|
|
38
|
+
have_func(func)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
have_struct_member("struct passwd", "pw_change", "pwd.h")
|
42
|
+
have_struct_member("struct passwd", "pw_expire", "pwd.h")
|
43
|
+
have_struct_member("struct passwd", "pw_class", "pwd.h")
|
44
|
+
have_struct_member("struct passwd", "pw_field", "pwd.h")
|
45
|
+
|
46
|
+
|
47
|
+
create_header
|
48
|
+
create_makefile("etcutils")
|
49
|
+
else
|
50
|
+
puts "This system is not managed by passwd/group files.","Exiting"
|
51
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
#include "etcutils.h"
|
2
|
+
VALUE rb_cGroup, rb_cGshadow;
|
3
|
+
|
4
|
+
#ifdef HAVE_PUTGRENT
|
5
|
+
static VALUE group_gr_put(VALUE self, VALUE io)
|
6
|
+
{
|
7
|
+
struct group grp;
|
8
|
+
VALUE path;
|
9
|
+
#ifdef HAVE_FGETGRENT
|
10
|
+
struct group *tmp_grp;
|
11
|
+
long i = 0;
|
12
|
+
#endif
|
13
|
+
|
14
|
+
Check_EU_Type(self, rb_cGroup);
|
15
|
+
Check_Writes(io, FMODE_WRITABLE);
|
16
|
+
|
17
|
+
path = RFILE_PATH(io);
|
18
|
+
|
19
|
+
rewind(RFILE_FPTR(io));
|
20
|
+
grp.gr_name = RSTRING_PTR(rb_ivar_get(self, id_name));
|
21
|
+
|
22
|
+
#ifdef HAVE_FGETGRENT
|
23
|
+
while ( (tmp_grp = fgetgrent(RFILE_FPTR(io))) )
|
24
|
+
if ( !strcmp(tmp_grp->gr_name, grp.gr_name) )
|
25
|
+
rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
|
26
|
+
tmp_grp->gr_name, StringValuePtr(path), ++i );
|
27
|
+
#endif
|
28
|
+
|
29
|
+
grp.gr_passwd = RSTRING_PTR(rb_ivar_get(self, id_passwd));
|
30
|
+
grp.gr_gid = NUM2GIDT( rb_ivar_get(self, id_gid) );
|
31
|
+
grp.gr_mem = setup_char_members( rb_iv_get(self, "@members") );
|
32
|
+
|
33
|
+
if ( putgrent(&grp,RFILE_FPTR(io)) )
|
34
|
+
eu_errno(RFILE_PATH(io));
|
35
|
+
|
36
|
+
free_char_members(grp.gr_mem, (int)RARRAY_LEN( rb_iv_get(self, "@members") ));
|
37
|
+
|
38
|
+
return Qtrue;
|
39
|
+
}
|
40
|
+
#endif
|
41
|
+
|
42
|
+
static VALUE group_gr_sprintf(VALUE self)
|
43
|
+
{
|
44
|
+
VALUE args[5];
|
45
|
+
args[0] = setup_safe_str("%s:%s:%s:%s\n");
|
46
|
+
args[1] = rb_ivar_get(self, id_name);
|
47
|
+
args[2] = rb_ivar_get(self, id_passwd);
|
48
|
+
args[3] = rb_ivar_get(self,id_gid);
|
49
|
+
args[4] = rb_ary_join((VALUE)rb_iv_get(self, "@members"), (VALUE)setup_safe_str(","));
|
50
|
+
return rb_f_sprintf(5, args);
|
51
|
+
}
|
52
|
+
|
53
|
+
VALUE group_putgrent(VALUE self, VALUE io)
|
54
|
+
{
|
55
|
+
#ifdef HAVE_PUTGRENT
|
56
|
+
return group_gr_put(self, io);
|
57
|
+
#else
|
58
|
+
return group_gr_sprintf(self);
|
59
|
+
#endif
|
60
|
+
}
|
61
|
+
|
62
|
+
VALUE group_gr_entry(VALUE self)
|
63
|
+
{
|
64
|
+
return eu_to_entry(self, group_putgrent);
|
65
|
+
}
|
66
|
+
|
67
|
+
VALUE group_putsgent(VALUE self, VALUE io)
|
68
|
+
{
|
69
|
+
#ifdef GSHADOW
|
70
|
+
struct sgrp sgroup, *tmp_sgrp;
|
71
|
+
VALUE path;
|
72
|
+
long i = 0;
|
73
|
+
|
74
|
+
Check_EU_Type(self, rb_cGshadow);
|
75
|
+
Check_Writes(io, FMODE_WRITABLE);
|
76
|
+
|
77
|
+
path = RFILE_PATH(io);
|
78
|
+
|
79
|
+
rewind(RFILE_FPTR(io));
|
80
|
+
SGRP_NAME(&sgroup) = RSTRING_PTR(rb_ivar_get(self, id_name));
|
81
|
+
|
82
|
+
while ( (tmp_sgrp = fgetsgent(RFILE_FPTR(io))) )
|
83
|
+
if ( !strcmp(SGRP_NAME(tmp_sgrp), SGRP_NAME(&sgroup)) )
|
84
|
+
rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
|
85
|
+
RSTRING_PTR(rb_ivar_get(self, id_name)), StringValuePtr(path), ++i );
|
86
|
+
|
87
|
+
sgroup.sg_passwd = RSTRING_PTR(rb_ivar_get(self, id_passwd));
|
88
|
+
sgroup.sg_adm = setup_char_members( rb_iv_get(self,"@admins") );
|
89
|
+
sgroup.sg_mem = setup_char_members( rb_iv_get(self, "@members") );
|
90
|
+
|
91
|
+
if ( putsgent(&sgroup,RFILE_FPTR(io)) )
|
92
|
+
eu_errno(RFILE_PATH(io));
|
93
|
+
|
94
|
+
free_char_members(sgroup.sg_adm, RARRAY_LEN( rb_iv_get(self, "@admins") ));
|
95
|
+
free_char_members(sgroup.sg_mem, RARRAY_LEN( rb_iv_get(self, "@members") ));
|
96
|
+
|
97
|
+
return Qtrue;
|
98
|
+
#else
|
99
|
+
return Qnil;
|
100
|
+
#endif
|
101
|
+
}
|
102
|
+
|
103
|
+
VALUE group_sg_entry(VALUE self)
|
104
|
+
{
|
105
|
+
return eu_to_entry(self, group_putsgent);
|
106
|
+
}
|
107
|
+
|
108
|
+
VALUE setup_group(struct group *grp)
|
109
|
+
{
|
110
|
+
VALUE obj;
|
111
|
+
if (!grp) errno || (errno = 61); // ENODATA
|
112
|
+
eu_errno( setup_safe_str ( "Error setting up Group instance." ) );
|
113
|
+
|
114
|
+
obj = rb_obj_alloc(rb_cGroup);
|
115
|
+
|
116
|
+
rb_ivar_set(obj, id_name, setup_safe_str(grp->gr_name));
|
117
|
+
rb_ivar_set(obj, id_passwd, setup_safe_str(grp->gr_passwd));
|
118
|
+
rb_ivar_set(obj, id_gid, GIDT2NUM(grp->gr_gid));
|
119
|
+
rb_iv_set(obj, "@members", setup_safe_array(grp->gr_mem));
|
120
|
+
|
121
|
+
return obj;
|
122
|
+
}
|
123
|
+
|
124
|
+
#if defined(HAVE_GSHADOW_H) || defined(HAVE_GSHADOW__H)
|
125
|
+
VALUE setup_gshadow(struct sgrp *sgroup)
|
126
|
+
{
|
127
|
+
VALUE obj;
|
128
|
+
if (!sgroup) errno || (errno = 61); // ENODATA
|
129
|
+
eu_errno( setup_safe_str ( "Error setting up GShadow instance." ) );
|
130
|
+
|
131
|
+
obj = rb_obj_alloc(rb_cGshadow);
|
132
|
+
|
133
|
+
rb_ivar_set(obj, id_name, setup_safe_str(SGRP_NAME(sgroup)));
|
134
|
+
rb_ivar_set(obj, id_passwd, setup_safe_str(sgroup->sg_passwd));
|
135
|
+
rb_iv_set(obj, "@admins", setup_safe_array(sgroup->sg_adm));
|
136
|
+
rb_iv_set(obj, "@members", setup_safe_array(sgroup->sg_mem));
|
137
|
+
return obj;
|
138
|
+
}
|
139
|
+
#endif
|
140
|
+
|
141
|
+
void Init_etcutils_group()
|
142
|
+
{
|
143
|
+
/* Define-const: Group
|
144
|
+
*
|
145
|
+
* The struct contains the following members:
|
146
|
+
*
|
147
|
+
* name::
|
148
|
+
* contains the name of the group as a String.
|
149
|
+
* passwd::
|
150
|
+
* contains the encrypted password as a String. An 'x' is
|
151
|
+
* returned if password access to the group is not available; an empty
|
152
|
+
* string is returned if no password is needed to obtain membership of
|
153
|
+
* the group.
|
154
|
+
* gid::
|
155
|
+
* contains the group's numeric ID as an integer.
|
156
|
+
* mem::
|
157
|
+
* is an Array of Strings containing the short login names of the
|
158
|
+
* members of the group.
|
159
|
+
*/
|
160
|
+
#ifdef GROUP
|
161
|
+
rb_define_attr(rb_cGroup, "name", 1, 1);
|
162
|
+
rb_define_attr(rb_cGroup, "passwd", 1, 1);
|
163
|
+
rb_define_attr(rb_cGroup, "gid", 1, 1);
|
164
|
+
rb_define_attr(rb_cGroup, "members", 1, 1);
|
165
|
+
|
166
|
+
rb_define_singleton_method(rb_cGroup,"get",eu_getgrent,0);
|
167
|
+
rb_define_singleton_method(rb_cGroup,"find",eu_getgrp,1);
|
168
|
+
rb_define_singleton_method(rb_cGroup,"parse",eu_sgetgrent,1);
|
169
|
+
rb_define_singleton_method(rb_cGroup,"set",eu_setgrent,0);
|
170
|
+
rb_define_singleton_method(rb_cGroup,"end",eu_endgrent,0);
|
171
|
+
rb_define_singleton_method(rb_cGroup,"each",eu_getgrent,0);
|
172
|
+
|
173
|
+
rb_define_method(rb_cGroup, "fputs", group_putgrent,1);
|
174
|
+
rb_define_method(rb_cGroup, "to_entry", group_gr_entry,0);
|
175
|
+
#endif
|
176
|
+
|
177
|
+
#ifdef GSHADOW
|
178
|
+
rb_define_attr(rb_cGshadow, "name", 1, 1);
|
179
|
+
rb_define_attr(rb_cGshadow, "passwd", 1, 1);
|
180
|
+
rb_define_attr(rb_cGshadow, "admins", 1, 1);
|
181
|
+
rb_define_attr(rb_cGshadow, "members", 1, 1);
|
182
|
+
|
183
|
+
rb_define_singleton_method(rb_cGshadow,"get",eu_getsgent,0);
|
184
|
+
rb_define_singleton_method(rb_cGshadow,"find",eu_getsgrp,1); //getsgent, getsguid
|
185
|
+
rb_define_singleton_method(rb_cGshadow,"parse",eu_sgetsgent,1);
|
186
|
+
rb_define_singleton_method(rb_cGshadow,"set",eu_setsgent,0);
|
187
|
+
rb_define_singleton_method(rb_cGshadow,"end",eu_endsgent,0);
|
188
|
+
rb_define_singleton_method(rb_cGshadow,"each",eu_getsgent,0);
|
189
|
+
rb_define_method(rb_cGshadow, "fputs", group_putsgent, 1);
|
190
|
+
rb_define_method(rb_cGshadow, "to_entry", group_sg_entry,0);
|
191
|
+
#endif
|
192
|
+
}
|
@@ -0,0 +1,297 @@
|
|
1
|
+
#include "etcutils.h"
|
2
|
+
|
3
|
+
VALUE rb_cPasswd, rb_cShadow;
|
4
|
+
int expire_warned = 0;
|
5
|
+
|
6
|
+
static VALUE
|
7
|
+
user_get_pw_change(VALUE self)
|
8
|
+
{
|
9
|
+
return iv_get_time(self, "@last_pw_change");
|
10
|
+
}
|
11
|
+
|
12
|
+
static VALUE
|
13
|
+
user_set_pw_change(VALUE self, VALUE pw)
|
14
|
+
{
|
15
|
+
rb_ivar_set(self, id_passwd, pw);
|
16
|
+
return iv_set_time(self, rb_current_time(), "@last_pw_change");
|
17
|
+
}
|
18
|
+
|
19
|
+
static VALUE
|
20
|
+
user_get_expire(VALUE self)
|
21
|
+
{
|
22
|
+
return iv_get_time(self, "@expire");
|
23
|
+
}
|
24
|
+
|
25
|
+
static VALUE
|
26
|
+
user_set_expire(VALUE self, VALUE v)
|
27
|
+
{
|
28
|
+
if ((rb_equal(v, INT2FIX(0))) && (expire_warned == 0)) {
|
29
|
+
rb_warn("Setting %s#expire to 0 should not be used as it is interpreted as either an account with no expiration, or as an expiration of Jan 1, 1970.", rb_obj_classname(self));
|
30
|
+
expire_warned = 1;
|
31
|
+
}
|
32
|
+
|
33
|
+
return iv_set_time(self, v, "@expire");
|
34
|
+
}
|
35
|
+
|
36
|
+
#ifdef HAVE_PUTPWENT
|
37
|
+
static VALUE user_pw_put(VALUE self, VALUE io)
|
38
|
+
{
|
39
|
+
struct passwd pwd;
|
40
|
+
VALUE path;
|
41
|
+
|
42
|
+
#ifdef HAVE_FGETPWENT
|
43
|
+
struct passwd *tmp_pwd;
|
44
|
+
long i = 0;
|
45
|
+
#endif
|
46
|
+
|
47
|
+
Check_EU_Type(self, rb_cPasswd);
|
48
|
+
Check_Writes(io, FMODE_WRITABLE);
|
49
|
+
|
50
|
+
path = RFILE_PATH(io);
|
51
|
+
|
52
|
+
rewind(RFILE_FPTR(io));
|
53
|
+
pwd.pw_name = RSTRING_PTR(rb_ivar_get(self, id_name));
|
54
|
+
|
55
|
+
#ifdef HAVE_FGETPWENT
|
56
|
+
while ( (tmp_pwd = fgetpwent(RFILE_FPTR(io))) )
|
57
|
+
if ( !strcmp(tmp_pwd->pw_name, pwd.pw_name) )
|
58
|
+
rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
|
59
|
+
tmp_pwd->pw_name, StringValuePtr(path), ++i );
|
60
|
+
#endif
|
61
|
+
|
62
|
+
pwd.pw_passwd = RSTRING_PTR(rb_ivar_get(self, id_passwd));
|
63
|
+
pwd.pw_uid = NUM2UIDT( rb_ivar_get(self,id_uid) );
|
64
|
+
pwd.pw_gid = NUM2GIDT( rb_ivar_get(self,id_gid) );
|
65
|
+
pwd.pw_gecos = RSTRING_PTR(rb_iv_get(self, "@gecos"));
|
66
|
+
pwd.pw_dir = RSTRING_PTR(rb_iv_get(self, "@directory"));
|
67
|
+
pwd.pw_shell = RSTRING_PTR(rb_iv_get(self, "@shell"));
|
68
|
+
|
69
|
+
if ( (putpwent(&pwd, RFILE_FPTR(io))) )
|
70
|
+
eu_errno(path);
|
71
|
+
|
72
|
+
return Qtrue;
|
73
|
+
}
|
74
|
+
#endif
|
75
|
+
|
76
|
+
static VALUE user_pw_sprintf(VALUE self)
|
77
|
+
{
|
78
|
+
VALUE args[11];
|
79
|
+
args[0] = setup_safe_str("%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n");
|
80
|
+
args[1] = rb_ivar_get(self, id_name);
|
81
|
+
args[2] = rb_ivar_get(self, id_passwd);
|
82
|
+
args[3] = rb_ivar_get(self, id_uid);
|
83
|
+
args[4] = rb_ivar_get(self,id_gid);
|
84
|
+
args[5] = rb_iv_get(self, "@access_classs");
|
85
|
+
args[6] = rb_iv_get(self, "@last_pw_change");
|
86
|
+
args[7] = rb_iv_get(self, "@expire");
|
87
|
+
args[8] = rb_iv_get(self, "@gecos");
|
88
|
+
args[9] = rb_iv_get(self, "@directory");
|
89
|
+
args[10] = rb_iv_get(self, "@shell");
|
90
|
+
return rb_f_sprintf(11, args);
|
91
|
+
}
|
92
|
+
|
93
|
+
VALUE user_putpwent(VALUE self, VALUE io)
|
94
|
+
{
|
95
|
+
#ifdef HAVE_PUTPWENT
|
96
|
+
return user_pw_put(self, io);
|
97
|
+
#else
|
98
|
+
return user_pw_sprintf(self);
|
99
|
+
#endif
|
100
|
+
}
|
101
|
+
|
102
|
+
VALUE user_pw_entry(VALUE self)
|
103
|
+
{
|
104
|
+
return eu_to_entry(self, user_putpwent);
|
105
|
+
}
|
106
|
+
|
107
|
+
VALUE user_putspent(VALUE self, VALUE io)
|
108
|
+
{
|
109
|
+
#ifdef SHADOW
|
110
|
+
struct spwd spasswd, *tmp_spwd;
|
111
|
+
VALUE path;
|
112
|
+
long i;
|
113
|
+
errno = 0;
|
114
|
+
i = 0;
|
115
|
+
|
116
|
+
Check_EU_Type(self, rb_cShadow);
|
117
|
+
Check_Writes(io, FMODE_WRITABLE);
|
118
|
+
|
119
|
+
path = RFILE_PATH(io);
|
120
|
+
|
121
|
+
rewind(RFILE_FPTR(io));
|
122
|
+
spasswd.sp_namp = RSTRING_PTR(rb_ivar_get(self, id_name));
|
123
|
+
|
124
|
+
while ( (tmp_spwd = fgetspent(RFILE_FPTR(io))) )
|
125
|
+
if ( !strcmp(tmp_spwd->sp_namp, spasswd.sp_namp) )
|
126
|
+
rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
|
127
|
+
tmp_spwd->sp_namp, StringValuePtr(path), ++i );
|
128
|
+
|
129
|
+
spasswd.sp_pwdp = RSTRING_PTR(rb_ivar_get(self, id_passwd));
|
130
|
+
spasswd.sp_lstchg = FIX2INT( rb_iv_get(self, "@last_pw_change") );
|
131
|
+
spasswd.sp_min = FIX2INT( rb_iv_get(self, "@min_pw_age") );
|
132
|
+
spasswd.sp_max = FIX2INT( rb_iv_get(self, "@max_pw_age") );
|
133
|
+
spasswd.sp_warn = QFIX2INT( rb_iv_get(self, "@warning") );
|
134
|
+
spasswd.sp_inact = QFIX2INT( rb_iv_get(self, "@inactive") );
|
135
|
+
spasswd.sp_expire = QFIX2INT( rb_iv_get(self, "@expire") );
|
136
|
+
spasswd.sp_flag = QFIX2ULONG( rb_iv_get(self, "@flag") );
|
137
|
+
|
138
|
+
if ( (putspent(&spasswd, RFILE_FPTR(io))) )
|
139
|
+
eu_errno(path);
|
140
|
+
|
141
|
+
return Qtrue;
|
142
|
+
#else
|
143
|
+
return Qnil;
|
144
|
+
#endif
|
145
|
+
}
|
146
|
+
|
147
|
+
VALUE user_sp_entry(VALUE self)
|
148
|
+
{
|
149
|
+
return eu_to_entry(self, user_putspent);
|
150
|
+
}
|
151
|
+
|
152
|
+
#ifdef SHADOW
|
153
|
+
VALUE setup_shadow(struct spwd *spasswd)
|
154
|
+
{
|
155
|
+
VALUE obj;
|
156
|
+
if (!spasswd) errno || (errno = 61); // ENODATA
|
157
|
+
eu_errno( setup_safe_str ( "Error setting up Shadow instance." ) );
|
158
|
+
|
159
|
+
obj = rb_obj_alloc(rb_cShadow);
|
160
|
+
|
161
|
+
rb_ivar_set(obj, id_name, setup_safe_str(spasswd->sp_namp));
|
162
|
+
rb_ivar_set(obj, id_passwd, setup_safe_str(spasswd->sp_pwdp));
|
163
|
+
|
164
|
+
rb_iv_set(obj, "@last_pw_change", INT2FIX(spasswd->sp_lstchg));
|
165
|
+
rb_iv_set(obj, "@min_pw_age", INT2FIX(spasswd->sp_min));
|
166
|
+
rb_iv_set(obj, "@max_pw_age", INT2FIX(spasswd->sp_max));
|
167
|
+
rb_iv_set(obj, "@warning", INT2QFIX(spasswd->sp_warn));
|
168
|
+
rb_iv_set(obj, "@inactive", INT2QFIX(spasswd->sp_inact));
|
169
|
+
rb_iv_set(obj, "@expire", INT2QFIX(spasswd->sp_expire));
|
170
|
+
rb_iv_set(obj, "@flag", UINT2QFIX(spasswd->sp_flag));
|
171
|
+
|
172
|
+
return obj;
|
173
|
+
}
|
174
|
+
#endif
|
175
|
+
|
176
|
+
VALUE setup_passwd(struct passwd *pwd)
|
177
|
+
{
|
178
|
+
VALUE obj;
|
179
|
+
if (!pwd) errno || (errno = 61); // ENODATA
|
180
|
+
eu_errno( setup_safe_str ( "Error setting up Password instance." ) );
|
181
|
+
|
182
|
+
obj = rb_obj_alloc(rb_cPasswd);
|
183
|
+
|
184
|
+
rb_ivar_set(obj, id_name, setup_safe_str(pwd->pw_name));
|
185
|
+
rb_ivar_set(obj, id_passwd, setup_safe_str(pwd->pw_passwd));
|
186
|
+
rb_ivar_set(obj, id_uid, UIDT2NUM(pwd->pw_uid));
|
187
|
+
rb_ivar_set(obj, id_gid, GIDT2NUM(pwd->pw_gid));
|
188
|
+
|
189
|
+
rb_iv_set(obj, "@gecos", setup_safe_str(pwd->pw_gecos));
|
190
|
+
rb_iv_set(obj, "@directory", setup_safe_str(pwd->pw_dir));
|
191
|
+
rb_iv_set(obj, "@shell", setup_safe_str(pwd->pw_shell));
|
192
|
+
#ifdef HAVE_ST_PW_CHANGE
|
193
|
+
if (!pwd->pw_change)
|
194
|
+
pwd->pw_change = (time_t)0;
|
195
|
+
rb_iv_set(obj, "@last_pw_change", INT2FIX(pwd->pw_change));
|
196
|
+
#endif
|
197
|
+
#ifdef HAVE_ST_PW_EXPIRE
|
198
|
+
if (!pwd->pw_expire)
|
199
|
+
pwd->pw_expire = (time_t)0;
|
200
|
+
|
201
|
+
rb_iv_set(obj, "@expire", INT2QFIX(pwd->pw_expire));
|
202
|
+
#endif
|
203
|
+
#ifdef HAVE_ST_PW_CLASS
|
204
|
+
if (pwd->pw_class)
|
205
|
+
rb_iv_set(obj, "@access_class", setup_safe_str(pwd->pw_class));
|
206
|
+
#endif
|
207
|
+
|
208
|
+
#ifdef HAVE_ST_PW_FIELD
|
209
|
+
if (pwd->pw_field)
|
210
|
+
rb_iv_set(obj, "@field", setup_safe_str(pwd->pw_field));
|
211
|
+
#endif
|
212
|
+
|
213
|
+
return obj;
|
214
|
+
}
|
215
|
+
|
216
|
+
void Init_etcutils_user()
|
217
|
+
{
|
218
|
+
|
219
|
+
#ifdef HAVE_PWD_H
|
220
|
+
rb_define_attr(rb_cPasswd, "name", 1, 1);
|
221
|
+
rb_define_attr(rb_cPasswd, "uid", 1, 1);
|
222
|
+
rb_define_attr(rb_cPasswd, "gid", 1, 1);
|
223
|
+
rb_define_attr(rb_cPasswd, "gecos", 1, 1);
|
224
|
+
rb_define_attr(rb_cPasswd, "directory", 1, 1);
|
225
|
+
rb_define_attr(rb_cPasswd, "shell", 1, 1);
|
226
|
+
|
227
|
+
#ifdef HAVE_ST_PW_CHANGE
|
228
|
+
rb_define_attr(rb_cPasswd, "last_pw_change", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
|
229
|
+
since the last password change */
|
230
|
+
rb_define_method(rb_cPasswd, "last_pw_change_date", user_get_pw_change, 0);
|
231
|
+
rb_define_attr(rb_cPasswd, "passwd", 1, 0);
|
232
|
+
rb_define_method(rb_cPasswd, "passwd=", user_set_pw_change, 1);
|
233
|
+
#else
|
234
|
+
rb_define_attr(rb_cPasswd, "passwd", 1, 1);
|
235
|
+
#endif
|
236
|
+
#ifdef HAVE_ST_PW_EXPIRE
|
237
|
+
rb_define_attr(rb_cPasswd, "expire", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
|
238
|
+
on which the account will be disabled */
|
239
|
+
rb_define_method(rb_cPasswd, "expire=", user_set_expire, 1);
|
240
|
+
rb_define_method(rb_cPasswd, "expire_date", user_get_expire, 0);
|
241
|
+
rb_define_method(rb_cPasswd, "expire_date=", user_set_expire, 1);
|
242
|
+
#endif
|
243
|
+
|
244
|
+
#ifdef HAVE_ST_PW_CLASS
|
245
|
+
rb_define_attr(rb_cPasswd, "access_class", 1, 1);
|
246
|
+
#endif
|
247
|
+
|
248
|
+
#ifdef HAVE_ST_PW_FIELD
|
249
|
+
rb_define_attr(rb_cPasswd, "field", 1, 0);
|
250
|
+
#endif
|
251
|
+
|
252
|
+
rb_define_method(rb_cPasswd, "to_entry", user_pw_entry,0);
|
253
|
+
rb_define_method(rb_cPasswd, "fputs", user_putpwent, 1);
|
254
|
+
|
255
|
+
rb_define_singleton_method(rb_cPasswd,"get",eu_getpwent,0);
|
256
|
+
rb_define_singleton_method(rb_cPasswd,"each",eu_getpwent,0);
|
257
|
+
rb_define_singleton_method(rb_cPasswd,"find",eu_getpwd,1); // -1 return array
|
258
|
+
rb_define_singleton_method(rb_cPasswd,"parse",eu_sgetpwent,1);
|
259
|
+
|
260
|
+
|
261
|
+
rb_define_singleton_method(rb_cPasswd,"set", eu_setpwent, 0);
|
262
|
+
rb_define_singleton_method(rb_cPasswd,"end", eu_endpwent, 0);
|
263
|
+
#endif
|
264
|
+
|
265
|
+
#ifdef HAVE_SHADOW_H // Shadow specific methods
|
266
|
+
rb_define_attr(rb_cShadow, "name", 1, 1); /* Login name. */
|
267
|
+
rb_define_attr(rb_cShadow, "passwd", 1, 0); /* Encrypted password. */
|
268
|
+
rb_define_attr(rb_cShadow, "min_pw_age", 1, 1); /* Minimum number of days between changes. */
|
269
|
+
rb_define_attr(rb_cShadow, "max_pw_age", 1, 1); /* Maximum number of days between changes. */
|
270
|
+
rb_define_attr(rb_cShadow, "last_pw_change", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
|
271
|
+
since the last password change */
|
272
|
+
rb_define_attr(rb_cShadow, "warning", 1, 1); /* Number of days to warn user to change
|
273
|
+
the password. */
|
274
|
+
rb_define_attr(rb_cShadow, "inactive", 1, 1); /* Number of days after password expires
|
275
|
+
that account is considered inactive and disabled */
|
276
|
+
rb_define_attr(rb_cShadow, "expire", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
|
277
|
+
on which the account will be disabled */
|
278
|
+
rb_define_attr(rb_cShadow, "flag", 1, 0); /* Reserved */
|
279
|
+
|
280
|
+
rb_define_method(rb_cShadow, "passwd=", user_set_pw_change, 1);
|
281
|
+
rb_define_method(rb_cShadow, "expire=", user_set_expire, 1);
|
282
|
+
rb_define_method(rb_cShadow, "last_pw_change_date", user_get_pw_change, 0);
|
283
|
+
rb_define_method(rb_cShadow, "expire_date", user_get_expire, 0);
|
284
|
+
rb_define_method(rb_cShadow, "expire_date=", user_set_expire, 1);
|
285
|
+
|
286
|
+
rb_define_method(rb_cShadow, "to_entry", user_sp_entry,0);
|
287
|
+
rb_define_method(rb_cShadow, "fputs", user_putspent, 1);
|
288
|
+
|
289
|
+
rb_define_singleton_method(rb_cShadow,"get",eu_getspent,0);
|
290
|
+
rb_define_singleton_method(rb_cShadow,"each",eu_getspent,0);
|
291
|
+
rb_define_singleton_method(rb_cShadow,"find",eu_getspwd,1);
|
292
|
+
rb_define_singleton_method(rb_cShadow,"parse",eu_sgetspent,1);
|
293
|
+
|
294
|
+
rb_define_singleton_method(rb_cShadow,"set", eu_setspent, 0);
|
295
|
+
rb_define_singleton_method(rb_cShadow,"end", eu_endspent, 0);
|
296
|
+
#endif
|
297
|
+
}
|