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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8180810fbc2a5e9a9ac2eeac16e0a62bff594e6c
4
- data.tar.gz: d43a52c9d4e266a1a91bebceb057f29d955da4f3
2
+ SHA256:
3
+ metadata.gz: e5c4a544a01935abef0fcad198c54eac69eadf13f911ac9d232e12b0febe345a
4
+ data.tar.gz: 141df1f03c8fc332f68b8c7ef397a9040d2ba91c3ac4c4fd2639e41f3dc9f775
5
5
  SHA512:
6
- metadata.gz: f7172cb9bc9cb1a78c052d75f3663d430b222c5bd70c33bcb762e5a171899fb250eff5e0bb8a4404bb2647cb0dbfb0da24cc8d9d6739f7c8985e1511d3260588
7
- data.tar.gz: d14f701064970ddea61f52ab036fbfc86a7a030aa3a614d2b8a27c4e3c7e66d822b8a3985f11fe5dedd1a066f20c09dea81f71a5bb730f858d541d733551dcae
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
- * gem install rpam2
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-2.0.0.gem
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
- abort "missing pam library" unless have_library("pam","pam_start")
4
- abort "missing pam library headers" unless have_header("security/pam_appl.h")
5
- abort "missing pam library headers" unless have_header("security/pam_modules.h")
6
-
7
- have_func("pam_end")
8
- have_func("pam_open_session")
9
- have_func("pam_close_session")
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, "_auth", method_authpam, 5);
282
- rb_define_singleton_method(rpam2, "account", method_accountpam, 2);
283
- rb_define_singleton_method(rpam2, "_getenv", method_getenvpam, 7);
284
- rb_define_singleton_method(rpam2, "_listenv", method_listenvpam, 6);
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 = 2.0
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
- self._auth(*args, nil, nil)
15
+ _auth(*args, nil, nil)
8
16
  when 5
9
- self._auth(*args)
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
- self._getenv(*args, nil, nil, nil)
30
+ _getenv(*args, nil, nil, nil)
18
31
  when 5
19
- self._getenv(*args, nil, nil)
32
+ _getenv(*args, nil, nil)
20
33
  when 7
21
- self._getenv(*args)
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
- self._listenv(*args, nil, nil, nil)
43
+ _listenv(*args, nil, nil, nil)
31
44
  when 4
32
- self._listenv(*args, nil, nil)
45
+ _listenv(*args, nil, nil)
33
46
  when 6
34
- self._listenv(*args)
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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rpam2"
3
- s.version = "3.1.0"
3
+ s.version = "4.0.0"
4
4
  s.date = "2017-10-10"
5
5
  s.summary = "PAM integration with ruby."
6
6
  s.email = "devkral@web.de"
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: 3.1.0
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.13
47
+ rubygems_version: 2.7.6
48
48
  signing_key:
49
49
  specification_version: 4
50
50
  summary: PAM integration with ruby.