gsasl 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +9 -1
- data/README.md +1 -1
- data/lib/gsasl.rb +7 -4
- data/lib/gsasl/native.rb +11 -5
- data/lib/gsasl/peer.rb +32 -2
- data/lib/gsasl/version.rb +1 -1
- data/spec/peer_spec.rb +88 -0
- metadata +2 -2
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# GNU SASL for Ruby
|
1
|
+
# GNU SASL for Ruby [![Build Status](https://secure.travis-ci.org/threez/gsasl.png)](http://travis-ci.org/threez/gsasl)
|
2
2
|
|
3
3
|
This libaray is a lib ffi based wrapper for the [GNU SASL](http://www.gnu.org/software/gsasl/) library. It supports a variaty of different authentication mechanisms. Those are the mechanisms supported for the current versions:
|
4
4
|
|
data/lib/gsasl.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require "gsasl/version"
|
2
2
|
require "gsasl/native"
|
3
|
-
require "gsasl/context"
|
4
|
-
require "gsasl/remote_authenticator"
|
5
|
-
require "gsasl/peer"
|
6
3
|
|
7
4
|
module Gsasl
|
8
|
-
|
5
|
+
autoload :Context, "gsasl/context"
|
6
|
+
autoload :RemoteAuthenticator, "gsasl/remote_authenticator"
|
7
|
+
autoload :Peer, "gsasl/peer"
|
8
|
+
|
9
|
+
class GsaslError < StandardError;
|
10
|
+
attr_accessor :code
|
11
|
+
end
|
9
12
|
end
|
data/lib/gsasl/native.rb
CHANGED
@@ -2,7 +2,11 @@ require 'ffi'
|
|
2
2
|
|
3
3
|
module Gsasl
|
4
4
|
extend FFI::Library
|
5
|
-
|
5
|
+
begin
|
6
|
+
ffi_lib "libgsasl"
|
7
|
+
rescue LoadError # debain/ubuntu has a different name for the libgsasl library
|
8
|
+
ffi_lib "libgsasl.so.7"
|
9
|
+
end
|
6
10
|
|
7
11
|
# RFC 2222: SASL mechanisms are named by strings, from 1 to 20
|
8
12
|
# characters in length, consisting of upper-case letters, digits,
|
@@ -133,11 +137,13 @@ module Gsasl
|
|
133
137
|
attach_function :gsasl_step64, [ :pointer, :string, :pointer], :int
|
134
138
|
|
135
139
|
# Raises an error if the passed result is not GSASL_OK
|
136
|
-
# @param [Fixnum]
|
140
|
+
# @param [Fixnum] code that should be checked
|
137
141
|
# @raises [GsaslError] if a different result occured
|
138
|
-
def self.raise_error!(
|
139
|
-
if
|
140
|
-
|
142
|
+
def self.raise_error!(code)
|
143
|
+
if code != GSASL_OK
|
144
|
+
error = GsaslError.new(Gsasl.gsasl_strerror(code) + " [#{code}]")
|
145
|
+
error.code = code
|
146
|
+
raise error
|
141
147
|
end
|
142
148
|
end
|
143
149
|
|
data/lib/gsasl/peer.rb
CHANGED
@@ -156,7 +156,9 @@ module Gsasl
|
|
156
156
|
when Gsasl::GSASL_VALIDATE_SECURID
|
157
157
|
handle_secureid_authentication(&block)
|
158
158
|
when Gsasl::GSASL_DIGEST_MD5_HASHED_PASSWORD
|
159
|
-
handle_digest_md5_authentication(&block)
|
159
|
+
handle_digest_md5_authentication(&block) ||
|
160
|
+
# fallback to password if there is no hash digest available
|
161
|
+
handle_password_authentication(&block)
|
160
162
|
when Gsasl::GSASL_VALIDATE_ANONYMOUS
|
161
163
|
handle_anonymous_authentication(&block)
|
162
164
|
when Gsasl::GSASL_VALIDATE_EXTERNAL
|
@@ -260,6 +262,8 @@ module Gsasl
|
|
260
262
|
end
|
261
263
|
|
262
264
|
result == Gsasl::GSASL_OK
|
265
|
+
rescue GsaslError => ex
|
266
|
+
false
|
263
267
|
end
|
264
268
|
|
265
269
|
# Authenticate against a remote peer using a socket like authenication
|
@@ -291,6 +295,32 @@ module Gsasl
|
|
291
295
|
result == Gsasl::GSASL_OK
|
292
296
|
end
|
293
297
|
|
298
|
+
# Handles a client authentication request by the server peer.
|
299
|
+
# @param [String] client_initialization if the client already gives
|
300
|
+
# initialization data before the process starts
|
301
|
+
# @example
|
302
|
+
# auth_result = server.handle do |remote|
|
303
|
+
# remote.recieve { io.gets.strip }
|
304
|
+
# remote.send { |data| io.print "+ #{data}\r\n" }
|
305
|
+
# end
|
306
|
+
def handle(client_initialization = nil, &block)
|
307
|
+
result = GSASL_NEEDS_MORE
|
308
|
+
input = client_initialization
|
309
|
+
|
310
|
+
# create a new authenticator and define its behaviour
|
311
|
+
remote = RemoteAuthenticator.new
|
312
|
+
block.call(remote)
|
313
|
+
|
314
|
+
while result == GSASL_NEEDS_MORE
|
315
|
+
# use the client initialization if given (once) otherwise receive
|
316
|
+
# from the remote client
|
317
|
+
result, response = process input
|
318
|
+
input = remote.send(response) if result == GSASL_NEEDS_MORE
|
319
|
+
end
|
320
|
+
|
321
|
+
result == Gsasl::GSASL_OK
|
322
|
+
end
|
323
|
+
|
294
324
|
# Close the authentication peer. This should be done after one
|
295
325
|
# authenticaion.
|
296
326
|
def close
|
@@ -307,7 +337,7 @@ module Gsasl
|
|
307
337
|
output = output_ptr.get_pointer(0)
|
308
338
|
[result, output.read_string.to_s]
|
309
339
|
else
|
310
|
-
|
340
|
+
Gsasl.raise_error!(result)
|
311
341
|
end
|
312
342
|
ensure
|
313
343
|
Gsasl.gsasl_free(output)
|
data/lib/gsasl/version.rb
CHANGED
data/spec/peer_spec.rb
CHANGED
@@ -79,6 +79,94 @@ describe Gsasl::Context do
|
|
79
79
|
"fb2441a715a5484c6fa16147c4a6b7a8"
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
context "client authenticaten" do
|
84
|
+
before(:each) do
|
85
|
+
@general_handler = lambda do |server, client|
|
86
|
+
server.handle do |remote|
|
87
|
+
remote.send do |data|
|
88
|
+
_, output = client.process data
|
89
|
+
output
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should handle LOGIN" do
|
96
|
+
@client = @session.create_client("LOGIN")
|
97
|
+
@client.credentials!("joe", "secret")
|
98
|
+
@peer = @session.create_server("LOGIN") do |type, authid|
|
99
|
+
"secret" if type == :password && authid == "joe"
|
100
|
+
end
|
101
|
+
@general_handler.call(@peer, @client).should be_true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should handle PLAIN" do
|
105
|
+
@client = @session.create_client("PLAIN")
|
106
|
+
@client.credentials!("joe", "secret")
|
107
|
+
@peer = @session.create_server("PLAIN") do |type, authid|
|
108
|
+
"secret" if type == :password && authid == "joe"
|
109
|
+
end
|
110
|
+
@general_handler.call(@peer, @client).should be_true
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should handle CRAM-MD5" do
|
114
|
+
@client = @session.create_client("CRAM-MD5")
|
115
|
+
@client.credentials!("joe", "secret")
|
116
|
+
@peer = @session.create_server("CRAM-MD5") do |type, authid|
|
117
|
+
"secret" if type == :password && authid == "joe"
|
118
|
+
end
|
119
|
+
@general_handler.call(@peer, @client).should be_true
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should handle SCRAM-SHA-1" do
|
123
|
+
@client = @session.create_client("SCRAM-SHA-1")
|
124
|
+
@client.credentials!("joe", "secret")
|
125
|
+
@peer = @session.create_server("SCRAM-SHA-1") do |type, authid|
|
126
|
+
"secret" if type == :password && authid == "joe"
|
127
|
+
end
|
128
|
+
@general_handler.call(@peer, @client).should be_true
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should handle DIGEST-MD5" do
|
132
|
+
@client = @session.create_client("DIGEST-MD5")
|
133
|
+
@client.credentials!("joe", "secret")
|
134
|
+
@client.service!("smtp", "localhost")
|
135
|
+
@client.realm = "gsasl"
|
136
|
+
@peer = @session.create_server("DIGEST-MD5", "gsasl") do |type, authid|
|
137
|
+
"secret" if type == :password && authid == "joe"
|
138
|
+
end
|
139
|
+
@general_handler.call(@peer, @client).should be_true
|
140
|
+
end
|
141
|
+
|
142
|
+
after(:each) do
|
143
|
+
@peer.close
|
144
|
+
@client.close
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "client initialization" do
|
149
|
+
it "should be possible with PLAIN" do
|
150
|
+
@client = @session.create_client("PLAIN")
|
151
|
+
@client.credentials!("joe", "secret")
|
152
|
+
@peer = @session.create_server("PLAIN") do |type, authid|
|
153
|
+
"secret" if type == :password && authid == "joe"
|
154
|
+
end
|
155
|
+
_, init = @client.process # emulate a client side authentication
|
156
|
+
init.should_not be_empty
|
157
|
+
@peer.handle(init) do |remote|
|
158
|
+
remote.send do |data|
|
159
|
+
_, output = @client.process data
|
160
|
+
output
|
161
|
+
end
|
162
|
+
end.should be_true
|
163
|
+
end
|
164
|
+
|
165
|
+
after(:each) do
|
166
|
+
@peer.close
|
167
|
+
@client.close
|
168
|
+
end
|
169
|
+
end
|
82
170
|
|
83
171
|
after(:each) do
|
84
172
|
@session.close
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gsasl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|