gsasl 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,2 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ - jruby-18mode # JRuby in 1.8 mode
6
+ - jruby-19mode # JRuby in 1.9 mode
7
+ # - rbx-18mode
8
+ # - rbx-19mode
1
9
  before_script:
2
- - sudo apt-get install libgsasl
10
+ - sudo apt-get install libgsasl7
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
 
@@ -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
- class GsaslError < StandardError; end
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
@@ -2,7 +2,11 @@ require 'ffi'
2
2
 
3
3
  module Gsasl
4
4
  extend FFI::Library
5
- ffi_lib "libgsasl"
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] result that should be checked
140
+ # @param [Fixnum] code that should be checked
137
141
  # @raises [GsaslError] if a different result occured
138
- def self.raise_error!(result)
139
- if result != GSASL_OK
140
- raise GsaslError, Gsasl.gsasl_strerror(result)
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
 
@@ -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
- [result, nil]
340
+ Gsasl.raise_error!(result)
311
341
  end
312
342
  ensure
313
343
  Gsasl.gsasl_free(output)
@@ -1,3 +1,3 @@
1
1
  module Gsasl
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -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.2.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-01 00:00:00.000000000 Z
12
+ date: 2012-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec