rpam2 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|