gsasl 0.2.0 → 1.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.
@@ -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