gsasl 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gsasl.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # GNU SASL for Ruby
2
+
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
+
5
+ * **EXTERNAL**: Authentication via out of band information.
6
+ * **ANONYMOUS**: Mechanism for anonymous access to resources.
7
+ * **PLAIN**: Clear text username and password.
8
+ * **LOGIN**: Non-standard clear text username and password.
9
+ * **CRAM-MD5**: Challenge-Response Authentication Mechanism.
10
+ * **DIGEST-MD5**: Digest Authentication.
11
+ * **SCRAM-SHA-1**: SCRAM-SHA-1 authentication.
12
+ * **NTLM**: Microsoft NTLM authentication.
13
+ * **SECURID**: Authentication using tokens.
14
+ * **GSSAPI**: GSSAPI (Kerberos 5) authentication.
15
+ * **GS2-KRB5**: Improved GSSAPI (Kerberos 5) authentication.
16
+ * **KERBEROS\_V5**: Experimental KERBEROS\_V5 authentication.
17
+ * **SAML20**: Experimental SAML20 authentication.
18
+ * **OPENID20**: Experimental OPENID20 authentication.
19
+
20
+ # Use in Ruby
21
+
22
+ In the following example the server and the client are on the same machine. If the server is on the remote site, one has to implement a server that will return the next challenge on `server#read` and implements a `server#send` to send the challenge to the server. Also it is possible to not use the `#authenticate` function but to implement the processing individually.
23
+
24
+ session = Gsasl::Context.new
25
+ client = session.create_client("CRAM-MD5")
26
+ server = session.create_server("CRAM-MD5")
27
+
28
+ server.set_callback do |property|
29
+ if property == Gsasl::GSASL_PASSWORD
30
+ if server[Gsasl::GSASL_AUTHID] == "joe"
31
+ server[Gsasl::GSASL_PASSWORD] = "secret"
32
+ end
33
+ Gsasl::GSASL_OK
34
+ end
35
+ end
36
+
37
+ client[Gsasl::GSASL_AUTHID] = "joe"
38
+ client[Gsasl::GSASL_PASSWORD] = "secret"
39
+
40
+ client.authenticate(server).should be_true
41
+
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
data/gsasl.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "gsasl/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "gsasl"
7
+ s.version = Gsasl::VERSION
8
+ s.authors = ["Vincent Landgraf"]
9
+ s.email = ["vilandgr@googlemail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{A lib ffi based wrapper for lib GNU SASL}
12
+ s.description = %q{A library for doing SASL based authentication mechanisms}
13
+
14
+ s.rubyforge_project = "gsasl"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec"
22
+ s.add_development_dependency "rake"
23
+ s.add_runtime_dependency "ffi"
24
+ end
@@ -0,0 +1,97 @@
1
+ module Gsasl
2
+ class Context
3
+ # Access the peers of a given session. This is used to find peers for the
4
+ # global `Gsasl::CALLBACK`.
5
+ # @api private
6
+ attr_accessor :peers
7
+
8
+ # Create a new gsasl authentication context.
9
+ def initialize
10
+ ctx = FFI::MemoryPointer.new :pointer
11
+ result = Gsasl.gsasl_init(ctx)
12
+ @context = ctx.get_pointer(0)
13
+ Gsasl.raise_error!(result)
14
+ @peers = {}
15
+ Gsasl.new_context @context.address, self
16
+ Gsasl.gsasl_callback_set(@context, CALLBACK)
17
+ end
18
+
19
+ # Returns or checks agains the passed version of GNU SASL.
20
+ # @param [String] check the version string to check against.
21
+ # @return [String, nil] the version string if the check was successful, nil
22
+ # otherwise
23
+ def version(check = nil)
24
+ Gsasl.gsasl_check_version check
25
+ end
26
+
27
+ # Checks if the client peer supports the passed mechanism
28
+ # @param [String] mechanism_name the mechnism to check for
29
+ # @return [Boolean] true if it is supported false otherwise
30
+ def client_support_for?(mechanism_name)
31
+ Gsasl.gsasl_client_support_p(@context, mechanism_name) == 1
32
+ end
33
+
34
+ # Checks if the server peer supports the passed mechanism
35
+ # @param [String] mechanism_name the mechnism to check for
36
+ # @return [Boolean] true if it is supported false otherwise
37
+ def server_support_for?(mechanism_name)
38
+ Gsasl.gsasl_server_support_p(@context, mechanism_name) == 1
39
+ end
40
+
41
+ # Closes the sasl peer for the context. Should be called after authenication.
42
+ def close
43
+ Gsasl.gsasl_done(@context)
44
+ end
45
+
46
+ # Returns a list of mechanisms for the server peer
47
+ # @return [Array<String>] the list of possible mechanisms
48
+ def server_mechanisms
49
+ mechanisms :server
50
+ end
51
+
52
+ # Returns a list of mechanisms for the client peer
53
+ # @return [Array<String>] the list of possible mechanisms
54
+ def client_mechanisms
55
+ mechanisms :client
56
+ end
57
+
58
+ # Creates the server peer based on the passed mechanism
59
+ # @param [String] mechanism_name the name of the mechanism
60
+ # @return [Gsasl::Peer] the server peer
61
+ # @example
62
+ # peer = @session.create_server("CRAM-MD5")
63
+ def create_server(mechanism_name)
64
+ peer = Peer.new(@context, mechanism_name, :server)
65
+ @peers[peer.session.address] = peer
66
+ peer
67
+ end
68
+
69
+ # Creates the client peer based on the passed mechanism
70
+ # @param [String] mechanism_name the name of the mechanism
71
+ # @return [Gsasl::Peer] the client peer
72
+ # @example
73
+ # peer = @session.create_client("CRAM-MD5")
74
+ def create_client(mechanism_name)
75
+ peer = Peer.new(@context, mechanism_name, :client)
76
+ @peers[peer.session.address] = peer
77
+ peer
78
+ end
79
+
80
+ private
81
+
82
+ # Returns a list of mechanisms for the passed type (type can be :client or
83
+ # :server)
84
+ # @param [Symbol] type the type to check mechanisms for
85
+ # @return [Array<String>] the list of possible mechanisms
86
+ def mechanisms(type)
87
+ out = FFI::MemoryPointer.new :pointer
88
+ result = Gsasl.send("gsasl_#{type}_mechlist", @context, out)
89
+ Gsasl.raise_error!(result)
90
+ data = out.get_pointer(0)
91
+ list = data.read_string.split(/\s/)
92
+ list
93
+ ensure
94
+ Gsasl.gsasl_free(data)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,177 @@
1
+ require 'ffi'
2
+
3
+ module Gsasl
4
+ extend FFI::Library
5
+ ffi_lib "libgsasl"
6
+
7
+ # RFC 2222: SASL mechanisms are named by strings, from 1 to 20
8
+ # characters in length, consisting of upper-case letters, digits,
9
+ # hyphens, and/or underscores. SASL mechanism names must be
10
+ # registered with the IANA.
11
+ GSASL_MIN_MECHANISM_SIZE = 1,
12
+ GSASL_MAX_MECHANISM_SIZE = 20
13
+
14
+ # Error codes for library functions.
15
+ GSASL_OK = 0
16
+ GSASL_NEEDS_MORE = 1
17
+ GSASL_UNKNOWN_MECHANISM = 2
18
+ GSASL_MECHANISM_CALLED_TOO_MANY_TIMES = 3
19
+ GSASL_MALLOC_ERROR = 7
20
+ GSASL_BASE64_ERROR = 8
21
+ GSASL_CRYPTO_ERROR = 9
22
+ GSASL_SASLPREP_ERROR = 29
23
+ GSASL_MECHANISM_PARSE_ERROR = 30
24
+ GSASL_AUTHENTICATION_ERROR = 31
25
+ GSASL_INTEGRITY_ERROR = 33
26
+ GSASL_NO_CLIENT_CODE = 35
27
+ GSASL_NO_SERVER_CODE = 36
28
+ GSASL_NO_CALLBACK = 51
29
+ GSASL_NO_ANONYMOUS_TOKEN = 52
30
+ GSASL_NO_AUTHID = 53
31
+ GSASL_NO_AUTHZID = 54
32
+ GSASL_NO_PASSWORD = 55
33
+ GSASL_NO_PASSCODE = 56
34
+ GSASL_NO_PIN = 57
35
+ GSASL_NO_SERVICE = 58
36
+ GSASL_NO_HOSTNAME = 59
37
+ GSASL_NO_CB_TLS_UNIQUE = 65
38
+ GSASL_NO_SAML20_IDP_IDENTIFIER = 66
39
+ GSASL_NO_SAML20_REDIRECT_URL = 67
40
+ GSASL_NO_OPENID20_AUTH_IDENTIFIER = 68
41
+
42
+ # Mechanism specific errors.
43
+ GSASL_GSSAPI_RELEASE_BUFFER_ERROR = 37
44
+ GSASL_GSSAPI_IMPORT_NAME_ERROR = 38
45
+ GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR = 39
46
+ GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR = 40
47
+ GSASL_GSSAPI_UNWRAP_ERROR = 41
48
+ GSASL_GSSAPI_WRAP_ERROR = 42
49
+ GSASL_GSSAPI_ACQUIRE_CRED_ERROR = 43
50
+ GSASL_GSSAPI_DISPLAY_NAME_ERROR = 44
51
+ GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR = 45
52
+ GSASL_KERBEROS_V5_INIT_ERROR = 46
53
+ GSASL_KERBEROS_V5_INTERNAL_ERROR = 47
54
+ GSASL_SHISHI_ERROR = GSASL_KERBEROS_V5_INTERNAL_ERROR
55
+ GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE = 48
56
+ GSASL_SECURID_SERVER_NEED_NEW_PIN = 49
57
+ GSASL_GSSAPI_ENCAPSULATE_TOKEN_ERROR = 60
58
+ GSASL_GSSAPI_DECAPSULATE_TOKEN_ERROR = 61
59
+ GSASL_GSSAPI_INQUIRE_MECH_FOR_SASLNAME_ERROR = 62
60
+ GSASL_GSSAPI_TEST_OID_SET_MEMBER_ERROR = 63
61
+ GSASL_GSSAPI_RELEASE_OID_SET_ERROR = 64
62
+
63
+ # Information properties, e.g., username.
64
+ GSASL_AUTHID = 1
65
+ GSASL_AUTHZID = 2
66
+ GSASL_PASSWORD = 3
67
+ GSASL_ANONYMOUS_TOKEN = 4
68
+ GSASL_SERVICE = 5
69
+ GSASL_HOSTNAME = 6
70
+ GSASL_GSSAPI_DISPLAY_NAME = 7
71
+ GSASL_PASSCODE = 8
72
+ GSASL_SUGGESTED_PIN = 9
73
+ GSASL_PIN = 10
74
+ GSASL_REALM = 11
75
+ GSASL_DIGEST_MD5_HASHED_PASSWORD = 12
76
+ GSASL_QOPS = 13
77
+ GSASL_QOP = 14
78
+ GSASL_SCRAM_ITER = 15
79
+ GSASL_SCRAM_SALT = 16
80
+ GSASL_SCRAM_SALTED_PASSWORD = 17
81
+ GSASL_CB_TLS_UNIQUE = 18
82
+ GSASL_SAML20_IDP_IDENTIFIER = 19
83
+ GSASL_SAML20_REDIRECT_URL = 20
84
+ GSASL_OPENID20_AUTH_IDENTIFIER = 21
85
+
86
+ # Client callbacks.
87
+ GSASL_SAML20_AUTHENTICATE_IN_BROWSER = 250
88
+
89
+ # Server validation callback properties.
90
+ GSASL_VALIDATE_SIMPLE = 500
91
+ GSASL_VALIDATE_EXTERNAL = 501
92
+ GSASL_VALIDATE_ANONYMOUS = 502
93
+ GSASL_VALIDATE_GSSAPI = 503
94
+ GSASL_VALIDATE_SECURID = 504
95
+ GSASL_VALIDATE_SAML20 = 505
96
+
97
+ # Gsasl_cipher
98
+ GSASL_CIPHER_DES = 1
99
+ GSASL_CIPHER_3DES = 2
100
+ GSASL_CIPHER_RC4 = 4
101
+ GSASL_CIPHER_RC4_40 = 8
102
+ GSASL_CIPHER_RC4_56 = 16
103
+ GSASL_CIPHER_AES = 32
104
+
105
+ # Quality of Protection types (DIGEST-MD5 and GSSAPI). The
106
+ # integrity and confidentiality values is about application data
107
+ # wrapping. We recommend that you use @GSASL_QOP_AUTH with TLS as
108
+ # that combination is generally more secure and have better chance
109
+ # of working than the integrity/confidentiality layers of SASL.
110
+ GSASL_QOP_AUTH = 1,
111
+ GSASL_QOP_AUTH_INT = 2,
112
+ GSASL_QOP_AUTH_CONF = 4
113
+
114
+ # the callback signature for the global callback
115
+ callback :gsasl_callback, [ :pointer, :pointer, :int], :int
116
+
117
+ # lib ffi mapped functions
118
+ attach_function :gsasl_init, [ :pointer ], :int
119
+ attach_function :gsasl_done, [ :pointer ], :void
120
+ attach_function :gsasl_check_version, [ :string ], :string
121
+ attach_function :gsasl_strerror, [ :int ], :string
122
+ attach_function :gsasl_client_support_p, [ :pointer, :string ], :int
123
+ attach_function :gsasl_server_support_p, [ :pointer, :string ], :int
124
+ attach_function :gsasl_server_start, [ :pointer, :string, :pointer ], :int
125
+ attach_function :gsasl_client_start, [ :pointer, :string, :pointer ], :int
126
+ attach_function :gsasl_finish, [ :pointer ], :void
127
+ attach_function :gsasl_client_mechlist, [ :pointer, :pointer ], :int
128
+ attach_function :gsasl_server_mechlist, [ :pointer, :pointer ], :int
129
+ attach_function :gsasl_free, [ :pointer ], :void
130
+ attach_function :gsasl_property_set, [ :pointer, :int , :string ], :void
131
+ attach_function :gsasl_property_get, [ :pointer, :int ], :string
132
+ attach_function :gsasl_callback_set, [ :pointer, :gsasl_callback ], :void
133
+ attach_function :gsasl_step64, [ :pointer, :string, :pointer], :int
134
+
135
+ # Raises an error if the passed result is not GSASL_OK
136
+ # @param [Fixnum] result that should be checked
137
+ # @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)
141
+ end
142
+ end
143
+
144
+ # Handles at a global level all callbacks that are made by the gsasl library.
145
+ # The context and session (or peer) will be used to proxy the events to the
146
+ # corresponding object.
147
+ CALLBACK = Proc.new do |context, peer, property|
148
+ # find the object...
149
+ if context = find_by_context(context.address)
150
+ if peer = context.peers[peer.address]
151
+ # ...and call the callback with the property
152
+ result = peer.call(property)
153
+ end
154
+ end
155
+
156
+ # if there is no callback handler (nil) return that information
157
+ result || Gsasl::GSASL_NO_CALLBACK
158
+ end
159
+
160
+ # Helper to find an context (or session) by the passed id. Used by `CALLBACK`.
161
+ # @api private
162
+ # @param [Fixnum] id the id of the sesseion (pointer to context struct)
163
+ # @return [Gsasl::Context, nil] the session or nil if nothing was found
164
+ def self.find_by_context(id)
165
+ @contexts ||= {}
166
+ @contexts[id]
167
+ end
168
+
169
+ # Registers the context and the session for later use in the global callback.
170
+ # @api private
171
+ # @param [Fixnum] id the id of the sesseion (pointer to context struct)
172
+ # @param [Gsasl::Context] context the session to save for later use
173
+ def self.new_context(id, context)
174
+ @contexts ||= {}
175
+ @contexts[id] = context
176
+ end
177
+ end
data/lib/gsasl/peer.rb ADDED
@@ -0,0 +1,115 @@
1
+ module Gsasl
2
+ # A peer is a client or server side that processes data to do an
3
+ # authentication.
4
+ class Peer
5
+ # give access to the session object (ffi) that is used by the peer
6
+ # @api private
7
+ attr_accessor :session
8
+
9
+ # Initalize a peer for authentication (either a client or server)
10
+ # @param [FFI::MemoryPointer] context the pointer to the context used
11
+ # @param [String] mechanism_name the name of the mechanism to use
12
+ # @param [Symbol] type either (:server or :client)
13
+ def initialize(context, mechanism_name, type = :server)
14
+ @context = context
15
+ peer = FFI::MemoryPointer.new :pointer
16
+ result = nil
17
+ case type
18
+ when :client
19
+ result = Gsasl.gsasl_client_start @context, mechanism_name, peer
20
+ else
21
+ result = Gsasl.gsasl_server_start @context, mechanism_name, peer
22
+ end
23
+ Gsasl.raise_error!(result)
24
+ ensure
25
+ @session = peer.get_pointer(0)
26
+ end
27
+
28
+ # Sets a property for this peer.
29
+ # @param [Fixnum] property on of the Gsasl API Keys
30
+ # @param [String] value the value tho set for the api key
31
+ # @example
32
+ # peer[Gsasl::GSASL_PASSWORD] = "secret"
33
+ def []=(property, value)
34
+ Gsasl.gsasl_property_set(@session, property, value)
35
+ end
36
+
37
+ # Reads a property from the peer.
38
+ # @param [Fixnum] property on of the Gsasl API Keys
39
+ # @return [String, nil] The value if there is one or nil
40
+ # @example
41
+ # peer[Gsasl::GSASL_AUTHID] #=> "joe"
42
+ def [](property)
43
+ Gsasl.gsasl_property_get(@session, property)
44
+ end
45
+
46
+ # Registers a callback for the peer. In case a variable is not provided.
47
+ # @yield [property] The callback that will be calles during the processing.
48
+ # @yieldparam [Fixnum] property a property for the
49
+ # @yieldreturn [Fixnum, nil] The return code for the callback or nil
50
+ def callback(&block)
51
+ @callback = block
52
+ end
53
+
54
+ # Used as a server hook in the local test environment.
55
+ # @return [Array<Fixnum, String>] Result code and base64 encoded challenge
56
+ def read #b64_str
57
+ process
58
+ end
59
+
60
+ # Used as a server hook in the local test environment.
61
+ # @param [String] b64_str Base64 encoded challenge
62
+ # @return [Array<Fixnum, String>] Result code and base64 encoded challenge
63
+ def send(b64_str)
64
+ process b64_str
65
+ end
66
+
67
+ # Authenticates against a server that implemennts read and send.
68
+ # @param [Gsasl::Peer] server a server peer object
69
+ # @return [Boolean] true if the authentication was successfull,
70
+ # false otherwise
71
+ def authenticate(server)
72
+ result = -1
73
+
74
+ begin
75
+ result, input = server.read
76
+ result, output = process input
77
+
78
+ if (result == GSASL_NEEDS_MORE || result == GSASL_OK)
79
+ result, output = server.send(output)
80
+ end
81
+ end while result == GSASL_NEEDS_MORE
82
+
83
+ Gsasl.raise_error!(result) unless Gsasl::GSASL_AUTHENTICATION_ERROR
84
+ result == Gsasl::GSASL_OK
85
+ end
86
+
87
+ # Close the authentication peer. This should be done after one
88
+ # authenticaion.
89
+ def close
90
+ Gsasl.gsasl_finish(@session)
91
+ end
92
+
93
+ # Process a challenge on the peer. There might be no input at the start.
94
+ # @param [String] input the inital challenge.
95
+ # @return [Array<Fixnum, String>] Result code and base64 encoded challenge
96
+ def process(input = nil)
97
+ output_ptr = FFI::MemoryPointer.new :pointer
98
+ result = Gsasl.gsasl_step64(@session, input, output_ptr)
99
+ if result == GSASL_NEEDS_MORE || result == GSASL_OK
100
+ output = output_ptr.get_pointer(0)
101
+ [result, output.read_string.to_s]
102
+ else
103
+ [result, nil]
104
+ end
105
+ ensure
106
+ Gsasl.gsasl_free(output)
107
+ end
108
+
109
+ # Call the callback of the peer.
110
+ # @param [Fixnum] property the api key.
111
+ def call(property)
112
+ @callback.call(property) if @callback
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module Gsasl
2
+ VERSION = "0.1.0"
3
+ end
data/lib/gsasl.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "gsasl/version"
2
+ require "gsasl/native"
3
+ require "gsasl/context"
4
+ require "gsasl/peer"
5
+
6
+ module Gsasl
7
+ class GsaslError < StandardError; end
8
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Authentications" do
4
+ before(:each) do
5
+ @session = Gsasl::Context.new
6
+ end
7
+
8
+ describe "CRAM-MD5" do
9
+ before(:each) do
10
+ @client = @session.create_client("CRAM-MD5")
11
+ @server = @session.create_server("CRAM-MD5")
12
+ end
13
+
14
+ it "should be able to authenticate correctly" do
15
+ @server.callback do |property|
16
+ if property == Gsasl::GSASL_PASSWORD
17
+ if @server[Gsasl::GSASL_AUTHID] == "joe"
18
+ @server[Gsasl::GSASL_PASSWORD] = "secret"
19
+ end
20
+ Gsasl::GSASL_OK
21
+ end
22
+ end
23
+
24
+ @client[Gsasl::GSASL_AUTHID] = "joe"
25
+ @client[Gsasl::GSASL_PASSWORD] = "secret"
26
+
27
+ @client.authenticate(@server).should be_true
28
+ end
29
+
30
+ it "should be possible to not authenticate correctly" do
31
+ @server.callback do |property|
32
+ if property == Gsasl::GSASL_PASSWORD
33
+ if @server[Gsasl::GSASL_AUTHID] == "joe"
34
+ @server[Gsasl::GSASL_PASSWORD] = "test"
35
+ end
36
+ Gsasl::GSASL_OK
37
+ end
38
+ end
39
+
40
+ @client[Gsasl::GSASL_AUTHID] = "joe"
41
+ @client[Gsasl::GSASL_PASSWORD] = "secret"
42
+
43
+ @client.authenticate(@server).should be_false
44
+ end
45
+
46
+ after(:each) do
47
+ @client.close
48
+ @server.close
49
+ end
50
+ end
51
+
52
+ after(:each) do
53
+ @session.close
54
+ end
55
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gsasl::Context do
4
+ before(:each) do
5
+ @session = Gsasl::Context.new
6
+ end
7
+
8
+ it "should be possible to get the version number of gsasl" do
9
+ @session.version.should =~ /\d.\d.\d/
10
+ end
11
+
12
+ it "should be possible to check the version" do
13
+ @session.version("1.7.0").should == nil
14
+ end
15
+
16
+ it "should be possible to check the support for client authentications" do
17
+ @session.client_support_for?("CRAM-MD5").should be_true
18
+ @session.client_support_for?("NONE").should be_false
19
+ end
20
+
21
+ it "should be possible to check the support for server authentications" do
22
+ @session.server_support_for?("CRAM-MD5").should be_true
23
+ @session.server_support_for?("NONE").should be_false
24
+ end
25
+
26
+ it "should return the supported server mechanisms as list" do
27
+ @session.server_mechanisms.should include("CRAM-MD5")
28
+ @session.server_mechanisms.should include("DIGEST-MD5")
29
+ @session.server_mechanisms.should include("PLAIN")
30
+ end
31
+
32
+ it "should return the supported client mechanisms as list" do
33
+ @session.client_mechanisms.should include("CRAM-MD5")
34
+ @session.client_mechanisms.should include("DIGEST-MD5")
35
+ @session.client_mechanisms.should include("PLAIN")
36
+ end
37
+
38
+ after(:each) do
39
+ @session.close
40
+ end
41
+ end
data/spec/peer_spec.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gsasl::Context do
4
+ before(:each) do
5
+ @session = Gsasl::Context.new
6
+ end
7
+
8
+ it "should be possible to create a client peer" do
9
+ @session.create_client("CRAM-MD5")
10
+ end
11
+
12
+ context "with peer" do
13
+ before(:each) do
14
+ @peer = @session.create_client("CRAM-MD5")
15
+ end
16
+
17
+ it "should return nil on no values" do
18
+ @peer[Gsasl::GSASL_AUTHID].should be_nil
19
+ @peer[Gsasl::GSASL_PASSWORD].should be_nil
20
+ end
21
+
22
+ it "should be possible to set parameter" do
23
+ @peer[Gsasl::GSASL_AUTHID] = "joe"
24
+ @peer[Gsasl::GSASL_PASSWORD] = "secret"
25
+ end
26
+
27
+ it "should be possible to read set parameter" do
28
+ @peer[Gsasl::GSASL_AUTHID] = "joe"
29
+ @peer[Gsasl::GSASL_PASSWORD] = "secret"
30
+ @peer[Gsasl::GSASL_AUTHID].should == "joe"
31
+ @peer[Gsasl::GSASL_PASSWORD].should == "secret"
32
+ end
33
+
34
+ it "should be possible to call a set callback" do
35
+ test_property = 0
36
+ @peer.callback { |property| test_property = property }
37
+ @peer.call(10)
38
+ test_property.should == 10
39
+ end
40
+ end
41
+
42
+ after(:each) do
43
+ @session.close
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ $:.unshift File.expand_path("../../lib", __FILE__)
8
+ require "gsasl"
9
+
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gsasl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vincent Landgraf
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: ffi
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A library for doing SASL based authentication mechanisms
63
+ email:
64
+ - vilandgr@googlemail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - Gemfile
72
+ - README.md
73
+ - Rakefile
74
+ - gsasl.gemspec
75
+ - lib/gsasl.rb
76
+ - lib/gsasl/context.rb
77
+ - lib/gsasl/native.rb
78
+ - lib/gsasl/peer.rb
79
+ - lib/gsasl/version.rb
80
+ - spec/authentication_spec.rb
81
+ - spec/context_spec.rb
82
+ - spec/peer_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: ''
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project: gsasl
104
+ rubygems_version: 1.8.19
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: A lib ffi based wrapper for lib GNU SASL
108
+ test_files:
109
+ - spec/authentication_spec.rb
110
+ - spec/context_spec.rb
111
+ - spec/peer_spec.rb
112
+ - spec/spec_helper.rb