rpam2 3.1.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.rdoc +17 -3
- data/ext/rpam2/extconf.rb +21 -12
- data/ext/rpam2/rpam2.c +98 -15
- data/lib/rpam2.rb +54 -12
- data/rpam2.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e5c4a544a01935abef0fcad198c54eac69eadf13f911ac9d232e12b0febe345a
|
4
|
+
data.tar.gz: 141df1f03c8fc332f68b8c7ef397a9040d2ba91c3ac4c4fd2639e41f3dc9f775
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d629dd561e80ad197493349953319477d7c7fd2d785dfdb2d30adf8b1c2ce4c6e6105b2ac73df18b3fb65dcdcb3087b3ba9464a5b1ae1a91e4aeba3cf402bda
|
7
|
+
data.tar.gz: 8bc5288e360b0e6778f10b719b5d11f12a05a649f08b7ac41225ff29431e60e57193b33c3aa7b0349d5e0ec6cd864d0265f270fc05a6c35e995c3f69d936810f
|
data/README.rdoc
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
else
|
18
18
|
puts "Authentication failed"
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
puts Rpam2.listenv(nil, "user", "password") # uses default (rpam)
|
22
22
|
puts Rpam2.listenv("servicename", "user", "password")
|
23
23
|
puts Rpam2.listenv("servicename", "user", "password", true)
|
@@ -31,12 +31,19 @@
|
|
31
31
|
|
32
32
|
== INSTALL:
|
33
33
|
|
34
|
-
|
34
|
+
gem install rpam2
|
35
|
+
|
36
|
+
or if it should not depend on pam:
|
37
|
+
|
38
|
+
ALLOW_NOPAM=true gem install rpam2
|
39
|
+
|
40
|
+
WARNING: Don't use rpam2 in this case except for test. It isn't safe
|
35
41
|
|
36
42
|
Or manually:
|
37
43
|
|
38
44
|
* gem build rpam2.gemspec
|
39
|
-
* gem install ./rpam2-
|
45
|
+
* gem install ./rpam2-4.0.0.gem
|
46
|
+
|
40
47
|
|
41
48
|
== Usage:
|
42
49
|
|
@@ -49,3 +56,10 @@ Rpam2.account("servicename", "username") => (true/false)
|
|
49
56
|
Rpam2.getenv("servicename", "username", "password", "envvar", [opensession(true/false), ["RUSER", "RHOST"]]) => (string/nil)
|
50
57
|
|
51
58
|
Rpam2.listenv("servicename", "username", "password", [opensession(true/false), ["RUSER", "RHOST"]]) => (hash/nil)
|
59
|
+
|
60
|
+
|
61
|
+
== Testing:
|
62
|
+
For test purposes can Rpam2 be filled with fake data. For this mode pam is not neccessary but then you may should not access not specified services.
|
63
|
+
Only services in fake_data are emulated the rest is redirected to real pam.
|
64
|
+
|
65
|
+
Rpam2.fake_data = { usernames: Set['alex', 'hugo', 'thomas'], servicenames: Set['service1', 'service2'], password: '123456', env: { email: 'me@example.com'} }
|
data/ext/rpam2/extconf.rb
CHANGED
@@ -1,18 +1,27 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
have_func("pam_authenticate")
|
11
|
-
have_func("pam_acct_mgmt")
|
12
|
-
have_func("pam_chauthtok")
|
13
|
-
have_func("pam_set_item")
|
14
|
-
have_func("pam_get_item")
|
3
|
+
pam_installed = have_library("pam","pam_start") and have_header("security/pam_appl.h")
|
4
|
+
#pam_installed = false
|
5
|
+
|
6
|
+
|
7
|
+
abort "missing pam library or header" unless pam_installed || ENV['ALLOW_NOPAM']=='true'
|
8
|
+
|
9
|
+
|
15
10
|
$CFLAGS << " -std=c99 "
|
16
11
|
|
12
|
+
if pam_installed
|
13
|
+
puts "Rpam2 build correctly (without stubs)" if ENV['ALLOW_NOPAM']=='true'
|
14
|
+
have_func("pam_end")
|
15
|
+
have_func("pam_open_session")
|
16
|
+
have_func("pam_close_session")
|
17
|
+
have_func("pam_authenticate")
|
18
|
+
have_func("pam_acct_mgmt")
|
19
|
+
have_func("pam_set_item")
|
20
|
+
have_func("pam_get_item")
|
21
|
+
else
|
22
|
+
warn "Rpam2 build didn't find pam headers/library, use pam stubs.\nONLY FOR TESTS OR IF PAM IS NOT USED. THIS MODE IS NOT SAFE IF PAM IS USED."
|
23
|
+
$CFLAGS << "-DWITHOUT_PAM_HEADER=1 "
|
24
|
+
end
|
25
|
+
|
17
26
|
|
18
27
|
create_makefile("rpam2/rpam2")
|
data/ext/rpam2/rpam2.c
CHANGED
@@ -1,6 +1,90 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
#include <string.h>
|
3
|
+
|
4
|
+
#ifndef WITHOUT_PAM_HEADER
|
3
5
|
#include <security/pam_appl.h>
|
6
|
+
#else
|
7
|
+
/* linux pam */
|
8
|
+
/* status */
|
9
|
+
#define PAM_SUCCESS 0
|
10
|
+
#define PAM_SYMBOL_ERR 2
|
11
|
+
#define PAM_BUF_ERR 5
|
12
|
+
#define PAM_CONV_ERR 19
|
13
|
+
|
14
|
+
/* items */
|
15
|
+
#define PAM_SERVICE 1
|
16
|
+
#define PAM_CONV 5
|
17
|
+
#define PAM_RHOST 4
|
18
|
+
#define PAM_RUSER 8
|
19
|
+
|
20
|
+
/* Messages */
|
21
|
+
#define PAM_PROMPT_ECHO_OFF 1
|
22
|
+
#define PAM_PROMPT_ECHO_ON 2
|
23
|
+
#define PAM_ERROR_MSG 3
|
24
|
+
#define PAM_TEXT_INFO 4
|
25
|
+
|
26
|
+
typedef struct pam_handle pam_handle_t;
|
27
|
+
|
28
|
+
|
29
|
+
struct pam_message {
|
30
|
+
int msg_style;
|
31
|
+
const char *msg;
|
32
|
+
};
|
33
|
+
|
34
|
+
struct pam_response {
|
35
|
+
char *resp;
|
36
|
+
int resp_retcode; /* currently un-used, zero expected */
|
37
|
+
};
|
38
|
+
|
39
|
+
/* The actual conversation structure itself */
|
40
|
+
|
41
|
+
struct pam_conv {
|
42
|
+
int (*conv)(int num_msg, const struct pam_message **msg,
|
43
|
+
struct pam_response **resp, void *appdata_ptr);
|
44
|
+
void *appdata_ptr;
|
45
|
+
};
|
46
|
+
|
47
|
+
// fix implicit function warnings:
|
48
|
+
|
49
|
+
int pam_start(const char *service_name, const char *user, const struct pam_conv *pam_conversation, pam_handle_t **pamh){
|
50
|
+
return PAM_SYMBOL_ERR;
|
51
|
+
};
|
52
|
+
int pam_end(pam_handle_t *pamh, int pam_status){
|
53
|
+
return PAM_SYMBOL_ERR;
|
54
|
+
}
|
55
|
+
|
56
|
+
int pam_authenticate(pam_handle_t *pamh, int flags){
|
57
|
+
return PAM_SYMBOL_ERR;
|
58
|
+
}
|
59
|
+
int pam_acct_mgmt(pam_handle_t *pamh, int flags){
|
60
|
+
return PAM_SYMBOL_ERR;
|
61
|
+
}
|
62
|
+
const char *pam_strerror(pam_handle_t *pamh, int errnum){
|
63
|
+
return "No PAM";
|
64
|
+
}
|
65
|
+
int pam_set_item(pam_handle_t *pamh, int item_type, const void *item){
|
66
|
+
return PAM_SYMBOL_ERR;
|
67
|
+
}
|
68
|
+
int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item){
|
69
|
+
return PAM_SYMBOL_ERR;
|
70
|
+
}
|
71
|
+
char **pam_getenvlist(pam_handle_t *pamh){
|
72
|
+
return PAM_SYMBOL_ERR;
|
73
|
+
}
|
74
|
+
const char *pam_getenv(pam_handle_t *pamh, const char *name){
|
75
|
+
return PAM_SYMBOL_ERR;
|
76
|
+
}
|
77
|
+
|
78
|
+
int pam_open_session(pam_handle_t *pamh, int flags){
|
79
|
+
return PAM_SYMBOL_ERR;
|
80
|
+
}
|
81
|
+
int pam_close_session(pam_handle_t *pamh, int flags){
|
82
|
+
return PAM_SYMBOL_ERR;
|
83
|
+
}
|
84
|
+
|
85
|
+
#endif
|
86
|
+
|
87
|
+
|
4
88
|
|
5
89
|
static const char *const
|
6
90
|
rpam_default_servicename = "rpam";
|
@@ -90,7 +174,7 @@ static unsigned int _start(pam_handle_t* pamh, VALUE* service, char* password, V
|
|
90
174
|
auth_c.conv = rpam_auth_conversation;
|
91
175
|
authw.pw = password;
|
92
176
|
auth_c.appdata_ptr = &authw;
|
93
|
-
|
177
|
+
|
94
178
|
result = pam_set_item(pamh, PAM_CONV, &auth_c);
|
95
179
|
if (result != PAM_SUCCESS) {
|
96
180
|
rb_warn("SET CONV: %s", pam_strerror(pamh, result));
|
@@ -119,7 +203,7 @@ static VALUE method_authpam(VALUE self, VALUE servicename, VALUE username, VALUE
|
|
119
203
|
rb_warn("INIT: %s", pam_strerror(pamh, result));
|
120
204
|
return Qfalse;
|
121
205
|
}
|
122
|
-
|
206
|
+
|
123
207
|
result = _start(pamh, &servicename, StringValueCStr(password), &ruser, &rhost);
|
124
208
|
if(result!=PAM_SUCCESS)
|
125
209
|
return Qfalse;
|
@@ -138,7 +222,7 @@ static VALUE method_accountpam(VALUE self, VALUE servicename, VALUE username) {
|
|
138
222
|
pam_handle_t* pamh = NULL;
|
139
223
|
unsigned int result=0;
|
140
224
|
struct pam_conv auth_c = {0,0};
|
141
|
-
|
225
|
+
|
142
226
|
Check_Type(username, T_STRING);
|
143
227
|
|
144
228
|
result = pam_start(rpam_default_servicename, StringValueCStr(username), &auth_c, &pamh);
|
@@ -162,7 +246,7 @@ static VALUE method_accountpam(VALUE self, VALUE servicename, VALUE username) {
|
|
162
246
|
|
163
247
|
static VALUE method_getenvpam(VALUE self, VALUE servicename, VALUE username, VALUE password, VALUE envname, VALUE opensession, VALUE ruser, VALUE rhost) {
|
164
248
|
pam_handle_t* pamh = NULL;
|
165
|
-
const char *c_ret;
|
249
|
+
const char *c_ret=NULL;
|
166
250
|
VALUE ruby_ret;
|
167
251
|
unsigned int result = 0;
|
168
252
|
struct pam_conv auth_c = {0,0};
|
@@ -176,7 +260,7 @@ static VALUE method_getenvpam(VALUE self, VALUE servicename, VALUE username, VAL
|
|
176
260
|
rb_warn("INIT: %s", pam_strerror(pamh, result));
|
177
261
|
return Qnil;
|
178
262
|
}
|
179
|
-
|
263
|
+
|
180
264
|
result = _start(pamh, &servicename, StringValueCStr(password), &ruser, &rhost);
|
181
265
|
if(result != PAM_SUCCESS)
|
182
266
|
return Qnil;
|
@@ -214,22 +298,22 @@ static VALUE method_getenvpam(VALUE self, VALUE servicename, VALUE username, VAL
|
|
214
298
|
static VALUE method_listenvpam(VALUE self, VALUE servicename, VALUE username, VALUE password, VALUE opensession, VALUE ruser, VALUE rhost){
|
215
299
|
pam_handle_t* pamh = NULL;
|
216
300
|
unsigned int result=0;
|
217
|
-
char *last;
|
218
|
-
char **envlist;
|
219
|
-
char **tmpenvlist;
|
301
|
+
char *last=NULL;
|
302
|
+
char **envlist=NULL;
|
303
|
+
char **tmpenvlist=NULL;
|
220
304
|
VALUE ruby_ret;
|
221
305
|
struct pam_conv auth_c = {0,0};
|
222
306
|
|
223
307
|
Check_Type(username, T_STRING);
|
224
308
|
Check_Type(password, T_STRING);
|
225
309
|
|
226
|
-
|
310
|
+
|
227
311
|
result = pam_start(rpam_default_servicename, StringValueCStr(username), &auth_c, &pamh);
|
228
312
|
if (result != PAM_SUCCESS) {
|
229
313
|
rb_warn("INIT: %s", pam_strerror(pamh, result));
|
230
314
|
return Qnil;
|
231
315
|
}
|
232
|
-
|
316
|
+
|
233
317
|
result = _start(pamh, &servicename, StringValueCStr(password), &ruser, &rhost);
|
234
318
|
if(result != PAM_SUCCESS)
|
235
319
|
return Qnil;
|
@@ -278,9 +362,8 @@ static VALUE method_listenvpam(VALUE self, VALUE servicename, VALUE username, VA
|
|
278
362
|
|
279
363
|
void Init_rpam2(){
|
280
364
|
rpam2 = rb_define_module("Rpam2");
|
281
|
-
rb_define_singleton_method(rpam2, "
|
282
|
-
rb_define_singleton_method(rpam2, "
|
283
|
-
rb_define_singleton_method(rpam2, "
|
284
|
-
rb_define_singleton_method(rpam2, "
|
365
|
+
rb_define_singleton_method(rpam2, "_authc", method_authpam, 5);
|
366
|
+
rb_define_singleton_method(rpam2, "_accountc", method_accountpam, 2);
|
367
|
+
rb_define_singleton_method(rpam2, "_getenvc", method_getenvpam, 7);
|
368
|
+
rb_define_singleton_method(rpam2, "_listenvc", method_listenvpam, 6);
|
285
369
|
}
|
286
|
-
|
data/lib/rpam2.rb
CHANGED
@@ -1,42 +1,84 @@
|
|
1
|
+
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
require 'rpam2/rpam2'
|
5
|
+
|
1
6
|
module Rpam2
|
2
|
-
VERSION =
|
7
|
+
VERSION = 4.0
|
3
8
|
class << self
|
9
|
+
attr_accessor :fake_data
|
10
|
+
@@fake_data = nil
|
11
|
+
|
4
12
|
def auth(*args)
|
5
13
|
case args.size
|
6
14
|
when 3
|
7
|
-
|
15
|
+
_auth(*args, nil, nil)
|
8
16
|
when 5
|
9
|
-
|
17
|
+
_auth(*args)
|
10
18
|
else
|
11
19
|
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 3 or 5)"
|
12
20
|
end
|
13
21
|
end
|
22
|
+
|
23
|
+
def account(servicename, username)
|
24
|
+
_account(servicename, username)
|
25
|
+
end
|
26
|
+
|
14
27
|
def getenv(*args)
|
15
28
|
case args.size
|
16
29
|
when 4
|
17
|
-
|
30
|
+
_getenv(*args, nil, nil, nil)
|
18
31
|
when 5
|
19
|
-
|
32
|
+
_getenv(*args, nil, nil)
|
20
33
|
when 7
|
21
|
-
|
34
|
+
_getenv(*args)
|
22
35
|
else
|
23
36
|
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 4, 5 or 7)"
|
24
37
|
end
|
25
38
|
end
|
26
|
-
|
39
|
+
|
27
40
|
def listenv(*args)
|
28
41
|
case args.size
|
29
42
|
when 3
|
30
|
-
|
43
|
+
_listenv(*args, nil, nil, nil)
|
31
44
|
when 4
|
32
|
-
|
45
|
+
_listenv(*args, nil, nil)
|
33
46
|
when 6
|
34
|
-
|
47
|
+
_listenv(*args)
|
35
48
|
else
|
36
49
|
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 3, 4 or 6)"
|
37
50
|
end
|
38
51
|
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def fake_compare(servicename, username)
|
56
|
+
return false unless self.fake_data
|
57
|
+
self.fake_data.fetch(:servicenames, Set.new).include?(servicename)
|
58
|
+
end
|
59
|
+
|
60
|
+
def _auth(servicename, username, password, ruser, rhost)
|
61
|
+
return _authc(servicename, username, password, ruser, rhost) unless fake_compare(servicename, username)
|
62
|
+
self.fake_data[:password] == password && self.fake_data.fetch(:usernames, Set.new).include?(username)
|
63
|
+
end
|
64
|
+
|
65
|
+
def _account(servicename, username)
|
66
|
+
return _accountc(servicename, username) unless self.fake_data && self.fake_data.fetch(:servicenames, Set.new).include?(servicename)
|
67
|
+
self.fake_data.fetch(:usernames, Set.new).include?(username)
|
68
|
+
end
|
69
|
+
|
70
|
+
def _getenv(servicename, username, password, opensession, varname, ruser, rhost)
|
71
|
+
return _getenvc(servicename, username, password, opensession, varname, ruser, rhost) unless fake_compare(servicename, username)
|
72
|
+
return nil unless self.fake_data.fetch(:usernames, Set.new).include?(username)
|
73
|
+
return nil if self.fake_data[:env].blank? || self.fake_data[:password] != password
|
74
|
+
self.fake_data[:env].fetch(varname, nil)
|
75
|
+
end
|
76
|
+
|
77
|
+
def _listenv(servicename, username, password, opensession, ruser, rhost)
|
78
|
+
return _listenvc(servicename, username, password, opensession, ruser, rhost) unless fake_compare(servicename, username)
|
79
|
+
return nil unless self.fake_data[:password] == password && self.fake_data.fetch(:usernames, Set.new).include?(username)
|
80
|
+
self.fake_data.fetch(:env, {})
|
81
|
+
end
|
39
82
|
end
|
83
|
+
private_class_method :_authc, :_accountc, :_getenvc, :_listenvc
|
40
84
|
end
|
41
|
-
|
42
|
-
require "rpam2/rpam2"
|
data/rpam2.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpam2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Kaftan
|
@@ -44,7 +44,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
44
|
version: '0'
|
45
45
|
requirements: []
|
46
46
|
rubyforge_project:
|
47
|
-
rubygems_version: 2.6
|
47
|
+
rubygems_version: 2.7.6
|
48
48
|
signing_key:
|
49
49
|
specification_version: 4
|
50
50
|
summary: PAM integration with ruby.
|