openldap 0.0.1pre11

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -0,0 +1,4 @@
1
+ ## 0.0.1 [2011-02-11] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Initial release.
4
+
@@ -0,0 +1,20 @@
1
+ .gemtest
2
+ History.md
3
+ Manifest.txt
4
+ README.md
5
+ Rakefile
6
+ Roadmap.md
7
+ ext/connection.c
8
+ ext/openldap.c
9
+ ext/openldap.h
10
+ lib/openldap.rb
11
+ lib/openldap/connection.rb
12
+ lib/openldap/exceptions.rb
13
+ lib/openldap/mixins.rb
14
+ lib/openldap/utils.rb
15
+ spec/lib/constants.rb
16
+ spec/lib/helpers.rb
17
+ spec/openldap/connection_spec.rb
18
+ spec/openldap/exceptions_spec.rb
19
+ spec/openldap_spec.rb
20
+ test.conf-example
@@ -0,0 +1,100 @@
1
+ # openldap
2
+
3
+ * http://bitbucket.org/ged/ruby-openldap
4
+
5
+
6
+ ## Description
7
+
8
+ A simple, but feature-complete Ruby binding for OpenLDAP's libldap.
9
+
10
+ This binding is intended as an alternative for [ruby-ldap][] for libraries or applications which require a more complete implementation of the LDAP protocol (according to [RFC4511][]) than it provides.
11
+
12
+ Additions or changes:
13
+
14
+ * Referrals for add, modify, delete, modrdn, compare
15
+ * Controls for add, modify, delete, modrdn, compare
16
+ * Asynchronous and synchronous APIs
17
+ * Detailed exception class hierarchy for results instead of just one
18
+ class for all non-success results.
19
+ * Complete [RFC4511][] support:
20
+ - extended operations and results
21
+ - unsolicited notifications
22
+ - continuation references
23
+ - intermediate responses
24
+ - alias deferencing
25
+ - etc.
26
+ * Cleanly abandon terminated operations where supported
27
+ * Memory-handling cleanup to avoid leaks, corruption, and other
28
+ problems experienced in the wild.
29
+ * Drop deprecated non-_ext variants of operations which have a
30
+ modern equivalent.
31
+ * M17n for Ruby 1.9.x.
32
+ * Improved test coverage
33
+
34
+ **NOTE:** This library is still under development, and should not be considered to be feature-complete or production-ready.
35
+
36
+ This project's versions follow the [Semantic Versioning Specification][semver].
37
+
38
+
39
+ ## Installation
40
+
41
+ gem install openldap
42
+
43
+ You may have to specify the path to `libldap` like so:
44
+
45
+ gem install openldap -- --with-ldap-dir=/usr/local
46
+
47
+ and/or override your Ruby implementation's architecture flags if your Ruby and OpenLDAP installations don't match, particularly under MacOS X:
48
+
49
+ ARCHFLAGS="-arch x86_64" gem install openldap
50
+
51
+
52
+ ## Contributing
53
+
54
+ You can check out the current development source with Mercurial via its [Bitbucket project][bitbucket]. Or if you prefer Git, via [its Github mirror][github].
55
+
56
+ After checking out the source, run:
57
+
58
+ $ rake newb
59
+
60
+ This task will install any missing dependencies, run the tests/specs,
61
+ and generate the API documentation.
62
+
63
+
64
+ ## License
65
+
66
+ Copyright (c) 2011, Michael Granger
67
+ All rights reserved.
68
+
69
+ Redistribution and use in source and binary forms, with or without
70
+ modification, are permitted provided that the following conditions are met:
71
+
72
+ * Redistributions of source code must retain the above copyright notice,
73
+ this list of conditions and the following disclaimer.
74
+
75
+ * Redistributions in binary form must reproduce the above copyright notice,
76
+ this list of conditions and the following disclaimer in the documentation
77
+ and/or other materials provided with the distribution.
78
+
79
+ * Neither the name of the author/s, nor the names of the project's
80
+ contributors may be used to endorse or promote products derived from this
81
+ software without specific prior written permission.
82
+
83
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
84
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
85
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
86
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
87
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
88
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
89
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
90
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
91
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
92
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
93
+
94
+
95
+ [RFC4511]: http://tools.ietf.org/html/rfc4511
96
+ [ruby-ldap]: http://ruby-ldap.sourceforge.net/
97
+ [semver]: http://semver.org/
98
+ [bitbucket]: https://bitbucket.org/ged/ruby-openldap
99
+ [github]: https://github.com/ged/ruby-openldap
100
+
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'pp'
4
+ require 'rbconfig'
5
+ require 'pathname'
6
+
7
+ begin
8
+ require 'rake/extensiontask'
9
+ rescue LoadError
10
+ abort "This Rakefile requires rake-compiler (gem install rake-compiler)"
11
+ end
12
+
13
+ begin
14
+ require 'hoe'
15
+ rescue LoadError
16
+ abort "This Rakefile requires hoe (gem install hoe)"
17
+ end
18
+
19
+ # Build constants
20
+ BASEDIR = Pathname( __FILE__ ).dirname.relative_path_from( Pathname.pwd )
21
+ SPECDIR = BASEDIR + 'spec'
22
+ LIBDIR = BASEDIR + 'lib'
23
+ EXTDIR = BASEDIR + 'ext'
24
+
25
+ EXTCONF = EXTDIR + 'extconf.rb'
26
+
27
+ DLEXT = Config::CONFIG['DLEXT']
28
+ EXT = LIBDIR + "bluecloth_ext.#{DLEXT}"
29
+
30
+ VALGRIND_OPTIONS = [
31
+ "--num-callers=50",
32
+ "--error-limit=no",
33
+ "--partial-loads-ok=yes",
34
+ "--undef-value-errors=no",
35
+ ]
36
+ VALGRIND_MEMORYFILL_OPTIONS = [
37
+ "--freelist-vol=100000000",
38
+ "--malloc-fill=6D",
39
+ "--free-fill=66 ",
40
+ ]
41
+
42
+ GDB_OPTIONS = []
43
+
44
+
45
+ # Load Hoe plugins
46
+ Hoe.plugin :mercurial
47
+ Hoe.plugin :yard
48
+ Hoe.plugin :signing
49
+
50
+ Hoe.plugins.delete :rubyforge
51
+ Hoe.plugins.delete :compiler
52
+
53
+ # Configure Hoe
54
+ hoespec = Hoe.spec 'openldap' do
55
+ self.readme_file = 'README.md'
56
+ self.history_file = 'History.md'
57
+
58
+ self.developer 'Michael Granger', 'ged@FaerieMUD.org'
59
+
60
+ self.dependency 'rake-compiler', '~> 0.7', :developer
61
+ self.dependency 'rspec', '~> 2.6', :developer
62
+
63
+ self.spec_extras[:licenses] = ["BSD"]
64
+ self.spec_extras[:signing_key] = '/Volumes/Keys/ged-private_gem_key.pem'
65
+ self.spec_extras[:extensions] = [ EXTCONF.to_s ]
66
+ self.extra_rdoc_files += ['ext/connection.c', 'ext/openldap.c']
67
+
68
+ self.require_ruby_version( '>= 1.9.2' )
69
+
70
+ self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
71
+ self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
72
+ end
73
+
74
+ ENV['VERSION'] ||= hoespec.spec.version.to_s
75
+
76
+ # Ensure the specs pass before checking in
77
+ task 'hg:precheckin' => :spec
78
+
79
+ # Ensure the extension is compiled before testing
80
+ task :spec => :compile
81
+
82
+ # gem-testers support
83
+ task :test do
84
+ # rake-compiler always wants to copy the compiled extension into lib/, but
85
+ # we don't want testers to have to re-compile, especially since that
86
+ # often fails because they can't (and shouldn't have to) write to tmp/ in
87
+ # the installed gem dir. So we clear the task rake-compiler set up
88
+ # to break the dependency between :spec and :compile when running under
89
+ # rubygems-test, and then run :spec.
90
+ Rake::Task[ EXT.to_s ].clear
91
+ Rake::Task[ :spec ].execute
92
+ end
93
+
94
+ desc "Turn on warnings and debugging in the build."
95
+ task :maint do
96
+ ENV['MAINTAINER_MODE'] = 'yes'
97
+ end
98
+
99
+ ENV['RUBY_CC_VERSION'] = '1.8.7:1.9.2'
100
+
101
+ # Rake-compiler task
102
+ Rake::ExtensionTask.new do |ext|
103
+ ext.name = 'openldap_ext'
104
+ ext.gem_spec = hoespec.spec
105
+ ext.ext_dir = 'ext'
106
+ ext.source_pattern = "*.{c,h}"
107
+ ext.cross_compile = true
108
+ ext.cross_platform = %w[i386-mswin32 i386-mingw32]
109
+ end
110
+
111
+
112
+ namespace :spec do
113
+
114
+ RSPEC_CMD = [ RUBY, '-S', 'rspec', '-Ilib:ext', SPECDIR.to_s ]
115
+
116
+ desc "Run the specs under GDB."
117
+ task :gdb => [ :compile ] do |task|
118
+ cmd = [ 'gdb' ] + GDB_OPTIONS
119
+ cmd += [ '--args' ]
120
+ cmd += RSPEC_CMD
121
+ system( *cmd )
122
+ end
123
+
124
+ desc "Run the specs under Valgrind."
125
+ task :valgrind do
126
+ cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
127
+ cmd += RSPEC_CMD
128
+ system( *cmd )
129
+ end
130
+
131
+ end
132
+
133
+ ### Make the ChangeLog update if the repo has changed since it was last built
134
+ file '.hg/branch'
135
+ file 'ChangeLog' => '.hg/branch' do |task|
136
+ $stderr.puts "Updating the changelog..."
137
+ content = nil
138
+
139
+ begin
140
+ content = make_changelog()
141
+ rescue NoMethodError
142
+ abort "Releasing requires the hoe-mercurial plugin (gem install hoe-mercurial)"
143
+ end
144
+
145
+ File.open( task.name, 'w', 0644 ) do |fh|
146
+ fh.print( content )
147
+ end
148
+ end
149
+
150
+ # Rebuild the ChangeLog immediately before release
151
+ task :prerelease => 'ChangeLog'
152
+
@@ -0,0 +1,55 @@
1
+ # ruby-openldap Function Roadmap
2
+
3
+
4
+ ldap_initialize(3) initialize the LDAP library without opening a connection to a server
5
+ ldap_result(3) wait for the result from an asynchronous operation
6
+ ldap_abandon_ext(3) abandon (abort) an asynchronous operation
7
+ ldap_add_ext(3) asynchronously add an entry
8
+ ldap_add_ext_s(3) synchronously add an entry
9
+ ldap_sasl_bind(3) asynchronously bind to the directory
10
+ ldap_sasl_bind_s(3) synchronously bind to the directory
11
+ ldap_unbind_ext(3) synchronously unbind from the LDAP server and close the connection
12
+ ldap_unbind(3)
13
+ ldap_unbind_s(3) equivalent to ldap_unbind_ext(3)
14
+ ldap_memfree(3) dispose of memory allocated by LDAP routines.
15
+ ldap_compare_ext(3) asynchronously compare to a directory entry
16
+ ldap_compare_ext_s(3) synchronously compare to a directory entry
17
+ ldap_delete_ext(3) asynchronously delete an entry
18
+ ldap_delete_ext_s(3) synchronously delete an entry
19
+ ld_errno(3) LDAP error indication
20
+ ldap_errlist(3) list of LDAP errors and their meanings
21
+ ldap_err2string(3) convert LDAP error indication to a string
22
+ ldap_extended_operation(3) asynchronously perform an arbitrary extended operation
23
+ ldap_extended_operation_s(3) synchronously perform an arbitrary extended operation
24
+ ldap_first_attribute(3) return first attribute name in an entry
25
+ ldap_next_attribute(3) return next attribute name in an entry
26
+ ldap_first_entry(3) return first entry in a chain of search results
27
+ ldap_next_entry(3) return next entry in a chain of search results
28
+ ldap_count_entries(3) return number of entries in a search result
29
+ ldap_get_dn(3) extract the DN from an entry
30
+ ldap_get_values_len(3) return an attribute's values with lengths
31
+ ldap_value_free_len(3) free memory allocated by ldap_get_values_len(3)
32
+ ldap_count_values_len(3) return number of values
33
+ ldap_modify_ext(3) asynchronously modify an entry
34
+ ldap_modify_ext_s(3) synchronously modify an entry
35
+ ldap_mods_free(3) free array of pointers to mod structures used by ldap_modify_ext(3)
36
+ ldap_rename(3) asynchronously rename an entry
37
+ ldap_rename_s(3) synchronously rename an entry
38
+ ldap_msgfree(3) free results allocated by ldap_result(3)
39
+ ldap_msgtype(3) return the message type of a message from ldap_result(3)
40
+ ldap_msgid(3) return the message id of a message from ldap_result(3)
41
+ ldap_search_ext(3) asynchronously search the directory
42
+ ldap_search_ext_s(3) synchronously search the directory
43
+ ldap_is_ldap_url(3) check a URL string to see if it is an LDAP URL
44
+ ldap_url_parse(3) break up an LDAP URL string into its components
45
+ ldap_sort_entries(3) sort a list of search results
46
+ ldap_sort_values(3) sort a list of attribute values
47
+ ldap_sort_strcasecmp(3) case insensitive string comparison
48
+
49
+
50
+ OpenLDAP::Connection
51
+
52
+ OpenLDAP::Entry
53
+
54
+ OpenLDAP::Result
55
+
@@ -0,0 +1,1125 @@
1
+ /*
2
+ * Ruby-OpenLDAP -- a Ruby binding to OpenLDAP's libldap
3
+ * $Id: connection.c,v 2568fe5f94bd 2011/08/11 23:01:24 ged $
4
+ *
5
+ * Authors
6
+ *
7
+ * - Michael Granger <ged@FaerieMUD.org>
8
+ *
9
+ * Copyright (c) 2011 Michael Granger
10
+ *
11
+ * All rights reserved.
12
+ *
13
+ * Redistribution and use in source and binary forms, with or without modification, are
14
+ * permitted provided that the following conditions are met:
15
+ *
16
+ * * Redistributions of source code must retain the above copyright notice, this
17
+ * list of conditions and the following disclaimer.
18
+ *
19
+ * * Redistributions in binary form must reproduce the above copyright notice, this
20
+ * list of conditions and the following disclaimer in the documentation and/or
21
+ * other materials provided with the distribution.
22
+ *
23
+ * * Neither the name of the authors, nor the names of its contributors may be used to
24
+ * endorse or promote products derived from this software without specific prior
25
+ * written permission.
26
+ *
27
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+ *
39
+ *
40
+ */
41
+
42
+ #include "openldap.h"
43
+
44
+
45
+ #define MILLION_F 1000000.0
46
+
47
+
48
+ /* --------------------------------------------------------------
49
+ * Declarations
50
+ * -------------------------------------------------------------- */
51
+ VALUE ropenldap_cOpenLDAPConnection;
52
+
53
+
54
+ /* --------------------------------------------------
55
+ * Memory-management functions
56
+ * -------------------------------------------------- */
57
+
58
+ /*
59
+ * Allocation function
60
+ */
61
+ static struct ropenldap_connection *
62
+ ropenldap_conn_alloc( LDAP *ldp )
63
+ {
64
+ struct ropenldap_connection *ptr = ALLOC( struct ropenldap_connection );
65
+
66
+ ptr->ldap = ldp;
67
+
68
+ return ptr;
69
+ }
70
+
71
+
72
+ /*
73
+ * GC Mark function
74
+ */
75
+ static void
76
+ ropenldap_conn_gc_mark( struct ropenldap_connection *ptr )
77
+ {
78
+ /* No-op */
79
+ }
80
+
81
+
82
+
83
+ /*
84
+ * GC Free function
85
+ */
86
+ static void
87
+ ropenldap_conn_gc_free( struct ropenldap_connection *ptr )
88
+ {
89
+ if ( ptr ) {
90
+ ptr->ldap = NULL;
91
+
92
+ xfree( ptr );
93
+ ptr = NULL;
94
+ }
95
+ }
96
+
97
+
98
+ /*
99
+ * Object validity checker. Returns the data pointer.
100
+ */
101
+ static struct ropenldap_connection *
102
+ check_conn( VALUE self )
103
+ {
104
+ Check_Type( self, T_DATA );
105
+
106
+ if ( !IsConnection(self) ) {
107
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected an OpenLDAP::Connection)",
108
+ rb_obj_classname( self ) );
109
+ }
110
+
111
+ return DATA_PTR( self );
112
+ }
113
+
114
+
115
+ /*
116
+ * Fetch the data pointer and check it for sanity.
117
+ */
118
+ static struct ropenldap_connection *
119
+ ropenldap_get_conn( VALUE self )
120
+ {
121
+ struct ropenldap_connection *conn = check_conn( self );
122
+
123
+ if ( !conn ) rb_fatal( "Use of uninitialized OpenLDAP::Connection" );
124
+
125
+ return conn;
126
+ }
127
+
128
+
129
+
130
+ /* --------------------------------------------------------------
131
+ * Class methods
132
+ * -------------------------------------------------------------- */
133
+
134
+ /*
135
+ * call-seq:
136
+ * OpenLDAP::Connection.allocate -> store
137
+ *
138
+ * Allocate a new OpenLDAP::Connection object.
139
+ *
140
+ */
141
+ static VALUE
142
+ ropenldap_conn_s_allocate( VALUE klass )
143
+ {
144
+ return Data_Wrap_Struct( klass, ropenldap_conn_gc_mark, ropenldap_conn_gc_free, 0 );
145
+ }
146
+
147
+
148
+ /* --------------------------------------------------------------
149
+ * Instance methods
150
+ * -------------------------------------------------------------- */
151
+
152
+ /*
153
+ * call-seq:
154
+ * OpenLDAP::Connection.new( *uris ) -> conn
155
+ *
156
+ * Create a new OpenLDAP::Connection object using the given +uris+.
157
+ *
158
+ */
159
+ static VALUE
160
+ ropenldap_conn_initialize( VALUE self, VALUE urls )
161
+ {
162
+ ropenldap_log_obj( self, "debug", "Initializing 0x%x", self );
163
+
164
+ if ( !check_conn(self) ) {
165
+ VALUE urlstring;
166
+ LDAP *ldp = NULL;
167
+ char *url = NULL;
168
+ struct ropenldap_connection *conn;
169
+ int result = 0;
170
+ int proto_ver = 3;
171
+
172
+ urlstring = rb_funcall( urls, rb_intern("join"), 1, rb_str_new(" ", 1) );
173
+ url = RSTRING_PTR( rb_obj_as_string(urlstring) );
174
+
175
+ if ( !ldap_is_ldap_url(url) )
176
+ rb_raise( rb_eArgError, "'%s' is not an LDAP url", url );
177
+
178
+ ropenldap_log_obj( self, "info", "Creating a new %s (%s)", rb_obj_classname(self), url );
179
+ result = ldap_initialize( &ldp, url );
180
+ ropenldap_check_result( result, "ldap_initialize( \"%s\" )", url );
181
+
182
+ conn = DATA_PTR( self ) = ropenldap_conn_alloc( ldp );
183
+
184
+ } else {
185
+ rb_raise( ropenldap_eOpenLDAPError,
186
+ "Cannot re-initialize a store once it's been created." );
187
+ }
188
+
189
+ return Qnil;
190
+ }
191
+
192
+
193
+ /*
194
+ * call-seq:
195
+ * conn.protocol_version -> fixnum
196
+ *
197
+ * Get the protocol version use by the connection.
198
+ *
199
+ * conn.protocol_version
200
+ * # => 3
201
+ */
202
+ static VALUE
203
+ ropenldap_conn_protocol_version( VALUE self )
204
+ {
205
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
206
+ int version = 0;
207
+
208
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS )
209
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_PROTOCOL_VERSION" );
210
+
211
+ return INT2FIX( version );
212
+ }
213
+
214
+
215
+ /*
216
+ * call-seq:
217
+ * conn.protocol_version = version
218
+ *
219
+ * Set the protocol version use by the connection to +version+.
220
+ *
221
+ * conn.protocol_version = 3
222
+ * # => 3
223
+ */
224
+ static VALUE
225
+ ropenldap_conn_protocol_version_eq( VALUE self, VALUE version )
226
+ {
227
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
228
+ int v = NUM2INT( version );
229
+
230
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_PROTOCOL_VERSION, &v) != LDAP_OPT_SUCCESS )
231
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_PROTOCOL_VERSION" );
232
+
233
+ return version;
234
+ }
235
+
236
+
237
+ /*
238
+ * call-seq:
239
+ * conn.async_connect? -> boolean
240
+ *
241
+ * Returns +true+ if the connect(2) call made by the library will be made asynchronously.
242
+ *
243
+ * conn.async_connect?
244
+ * # => true
245
+ */
246
+ static VALUE
247
+ ropenldap_conn_async_connect_p( VALUE self )
248
+ {
249
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
250
+ int enabled;
251
+
252
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_CONNECT_ASYNC, &enabled) != LDAP_OPT_SUCCESS )
253
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_CONNECT_ASYNC" );
254
+
255
+ return enabled ? Qtrue : Qfalse;
256
+ }
257
+
258
+
259
+ /*
260
+ * call-seq:
261
+ * conn.async_connect = boolean
262
+ *
263
+ * If set to a +true+ value, the library will call connect(2) and return without waiting for
264
+ * a response.
265
+ *
266
+ * conn.async_connect = true
267
+ */
268
+ static VALUE
269
+ ropenldap_conn_async_connect_eq( VALUE self, VALUE boolean )
270
+ {
271
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
272
+ int rv = 0;
273
+
274
+ if ( RTEST(boolean) ) {
275
+ ropenldap_log_obj( self, "debug", "Enabling async connect." );
276
+ rv = ldap_set_option( ptr->ldap, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON );
277
+ } else {
278
+ ropenldap_log_obj( self, "debug", "Disabling async connect." );
279
+ rv = ldap_set_option( ptr->ldap, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_OFF );
280
+ }
281
+
282
+ if ( rv != LDAP_OPT_SUCCESS )
283
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_CONNECT_ASYNC" );
284
+
285
+ return RTEST( boolean ) ? Qtrue : Qfalse;
286
+ }
287
+
288
+
289
+ /*
290
+ * call-seq:
291
+ * conn.network_timeout -> float or nil
292
+ *
293
+ * Returns the network timeout value (if it is set).
294
+ *
295
+ * conn.network_timeout
296
+ * # => 2.5
297
+ */
298
+ static VALUE
299
+ ropenldap_conn_network_timeout( VALUE self )
300
+ {
301
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
302
+ struct timeval *timeout;
303
+ double seconds = 0;
304
+
305
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout) != LDAP_OPT_SUCCESS )
306
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_NETWORK_TIMEOUT" );
307
+
308
+ if ( timeout ) {
309
+ ropenldap_log_obj( self, "debug", "Got network timeout: %d/%d",
310
+ timeout->tv_sec, timeout->tv_usec );
311
+ seconds = ((double) timeout->tv_sec) + timeout->tv_usec / MILLION_F;
312
+ ldap_memfree( timeout );
313
+ return rb_float_new( seconds );
314
+ } else {
315
+ ropenldap_log_obj( self, "debug", "No network timeout." );
316
+ return Qnil;
317
+ }
318
+ }
319
+
320
+
321
+ /*
322
+ * call-seq:
323
+ * conn.network_timeout = float or nil
324
+ *
325
+ * Set the network timeout value; the network timeout value is the number of seconds after which
326
+ * poll(2)/select(2) following a connect(2) returns in case of no activity. Setting this to nil
327
+ * or -1 disables it.
328
+ *
329
+ * conn.network_timeout = 1.0
330
+ */
331
+ static VALUE
332
+ ropenldap_conn_network_timeout_eq( VALUE self, VALUE arg )
333
+ {
334
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
335
+ double seconds;
336
+ struct timeval timeout;
337
+
338
+ if ( NIL_P(arg) ) {
339
+ seconds = -1.0;
340
+ } else {
341
+ seconds = NUM2DBL( arg );
342
+ }
343
+
344
+ ropenldap_log_obj( self, "debug", "Setting network timeout to %0.5f seconds", seconds );
345
+ timeout.tv_sec = (time_t)floor( seconds );
346
+ timeout.tv_usec = (suseconds_t)( fmod(seconds, 1.0) * MILLION_F );
347
+
348
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_NETWORK_TIMEOUT, (const void *)&timeout) != LDAP_OPT_SUCCESS )
349
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_NETWORK_TIMEOUT" );
350
+
351
+ return arg;
352
+ }
353
+
354
+
355
+ /*
356
+ * call-seq:
357
+ * conn.simple_bind( bind_dn, password ) -> result
358
+ * conn.simple_bind( bind_dn, password ) {|result| ... }
359
+ *
360
+ * Bind to the directory using a simple +bind_dn+ and a +password+.
361
+ *
362
+ */
363
+ static VALUE
364
+ ropenldap_conn_simple_bind( VALUE self, VALUE bind_dn, VALUE password )
365
+ {
366
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
367
+ return Qnil;
368
+ }
369
+
370
+
371
+ /*
372
+ * Start TLS synchronously; called from ropenldap_conn__start_tls after
373
+ * the GIL is released.
374
+ */
375
+ static VALUE
376
+ ropenldap_conn__start_tls_body( void *ptr )
377
+ {
378
+ LDAP *ld = ptr;
379
+ return (VALUE)ldap_start_tls_s( ld, NULL, NULL );
380
+ }
381
+
382
+
383
+ /*
384
+ * #_start_ls: backend of the #start_tls method.
385
+ */
386
+ static VALUE
387
+ ropenldap_conn__start_tls( VALUE self )
388
+ {
389
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
390
+
391
+ int result;
392
+
393
+ ropenldap_log_obj( self, "debug", "Starting TLS..." );
394
+ result = (int)rb_thread_blocking_region( ropenldap_conn__start_tls_body, (void *)ptr->ldap,
395
+ RUBY_UBF_IO, NULL );
396
+ ropenldap_check_result( result, "ldap_start_tls_s" );
397
+ ropenldap_log_obj( self, "debug", " TLS started." );
398
+
399
+ return Qtrue;
400
+ }
401
+
402
+
403
+ /*
404
+ * call-seq:
405
+ * conn.tls_inplace? -> true or false
406
+ *
407
+ * Returns +true+ if TLS handlers have been installed on the session.
408
+ *
409
+ */
410
+ static VALUE
411
+ ropenldap_conn_tls_inplace_p( VALUE self )
412
+ {
413
+ #ifdef HAVE_LDAP_TLS_INPLACE
414
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
415
+
416
+ if ( ldap_tls_inplace(ptr->ldap) ) {
417
+ return Qtrue;
418
+ } else {
419
+ return Qfalse;
420
+ }
421
+ #else
422
+ rb_raise( rb_eNotImpError, "not implemented in your version of libldap" );
423
+ #endif /* HAVE_LDAP_TLS_INPLACE */
424
+ }
425
+
426
+
427
+ /*
428
+ * call-seq:
429
+ * conn.tls_cacertfile -> string
430
+ *
431
+ * Get the full path of the CA certificate file as a String.
432
+ */
433
+ static VALUE
434
+ ropenldap_conn_tls_cacertfile( VALUE self )
435
+ {
436
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
437
+ char *path;
438
+ VALUE pathstring = Qnil;
439
+
440
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_CACERTFILE, &path) != LDAP_OPT_SUCCESS )
441
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_CACERTFILE" );
442
+ if ( !path )
443
+ return Qnil;
444
+
445
+ pathstring = rb_str_new2( path );
446
+ ldap_memfree( path );
447
+
448
+ return pathstring;
449
+ }
450
+
451
+ /*
452
+ * call-seq:
453
+ * conn.tls_cacertfile = string
454
+ *
455
+ * Set the full path of the CA certificate file as a String.
456
+ */
457
+ static VALUE
458
+ ropenldap_conn_tls_cacertfile_eq( VALUE self, VALUE path )
459
+ {
460
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
461
+ VALUE pathstring = rb_obj_as_string( path );
462
+ const char *pathopt = StringValuePtr( pathstring );
463
+
464
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_CACERTFILE, pathopt) != LDAP_OPT_SUCCESS )
465
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_CACERTFILE" );
466
+
467
+ return path;
468
+ }
469
+
470
+
471
+ /*
472
+ * call-seq:
473
+ * conn.tls_cacertdir -> string
474
+ *
475
+ * Get the full path of the directory containing CA certificates as a String.
476
+ */
477
+ static VALUE
478
+ ropenldap_conn_tls_cacertdir( VALUE self )
479
+ {
480
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
481
+ char *path;
482
+ VALUE pathstring = Qnil;
483
+
484
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_CACERTDIR, &path) != LDAP_OPT_SUCCESS )
485
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_CACERTDIR" );
486
+ if ( !path )
487
+ return Qnil;
488
+
489
+ pathstring = rb_str_new2( path );
490
+ ldap_memfree( path );
491
+
492
+ return pathstring;
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * conn.tls_cacertdir = string
498
+ *
499
+ * Set the path of the directory containing CA certificates as a String.
500
+ */
501
+ static VALUE
502
+ ropenldap_conn_tls_cacertdir_eq( VALUE self, VALUE path )
503
+ {
504
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
505
+ VALUE pathstring = rb_obj_as_string( path );
506
+ const char *pathopt = StringValuePtr( pathstring );
507
+
508
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_CACERTDIR, pathopt) != LDAP_OPT_SUCCESS )
509
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_CACERTDIR" );
510
+
511
+ return path;
512
+ }
513
+
514
+
515
+ /*
516
+ * call-seq:
517
+ * conn.tls_cacertfile -> string
518
+ *
519
+ * Get the full path of the certificate file as a String.
520
+ */
521
+ static VALUE
522
+ ropenldap_conn_tls_certfile( VALUE self )
523
+ {
524
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
525
+ char *path;
526
+ VALUE pathstring = Qnil;
527
+
528
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_CERTFILE, &path) != LDAP_OPT_SUCCESS )
529
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_CERTFILE" );
530
+ if ( !path )
531
+ return Qnil;
532
+
533
+ pathstring = rb_str_new2( path );
534
+ ldap_memfree( path );
535
+
536
+ return pathstring;
537
+ }
538
+
539
+ /*
540
+ * call-seq:
541
+ * conn.tls_certfile = string
542
+ *
543
+ * Set the full path of the certificate file as a String.
544
+ */
545
+ static VALUE
546
+ ropenldap_conn_tls_certfile_eq( VALUE self, VALUE path )
547
+ {
548
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
549
+ VALUE pathstring = rb_obj_as_string( path );
550
+ const char *pathopt = StringValuePtr( pathstring );
551
+
552
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_CERTFILE, pathopt) != LDAP_OPT_SUCCESS )
553
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_CERTFILE" );
554
+
555
+ return path;
556
+ }
557
+
558
+
559
+ /*
560
+ * call-seq:
561
+ * conn.tls_keyfile -> string
562
+ *
563
+ * Get the full path of the file that contains the private key that matches the certificate stored
564
+ * in the #tls_certfile.
565
+ */
566
+ static VALUE
567
+ ropenldap_conn_tls_keyfile( VALUE self )
568
+ {
569
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
570
+ char *path;
571
+ VALUE pathstring = Qnil;
572
+
573
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_KEYFILE, &path) != LDAP_OPT_SUCCESS )
574
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_KEYFILE" );
575
+ if ( !path )
576
+ return Qnil;
577
+
578
+ pathstring = rb_str_new2( path );
579
+ ldap_memfree( path );
580
+
581
+ return pathstring;
582
+ }
583
+
584
+ /*
585
+ * call-seq:
586
+ * conn.tls_keyfile = newvalue
587
+ *
588
+ * Set the full path to the file that contains the private key that matches the certificate stored
589
+ * in the #tls_certfile.
590
+ */
591
+ static VALUE
592
+ ropenldap_conn_tls_keyfile_eq( VALUE self, VALUE path )
593
+ {
594
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
595
+ VALUE pathstring = rb_obj_as_string( path );
596
+ const char *pathopt = StringValuePtr( pathstring );
597
+
598
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_KEYFILE, pathopt) != LDAP_OPT_SUCCESS )
599
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_KEYFILE" );
600
+
601
+ return path;
602
+ }
603
+
604
+
605
+ /*
606
+ * call-seq:
607
+ * conn.tls_cipher_suite -> cipherstring
608
+ *
609
+ * Get the allowed cipher suite. See http://www.openssl.org/docs/apps/ciphers.html for the
610
+ * allowed format of the +cipherstring+.
611
+ */
612
+ static VALUE
613
+ ropenldap_conn_tls_cipher_suite( VALUE self )
614
+ {
615
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
616
+ char *path;
617
+ VALUE pathstring = Qnil;
618
+
619
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_CIPHER_SUITE, &path) != LDAP_OPT_SUCCESS )
620
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_CIPHER_SUITE" );
621
+ if ( !path )
622
+ return Qnil;
623
+
624
+ pathstring = rb_str_new2( path );
625
+ ldap_memfree( path );
626
+
627
+ return pathstring;
628
+ }
629
+
630
+ /*
631
+ * call-seq:
632
+ * conn.tls_cipher_suite = cipherstring
633
+ *
634
+ * Set the allowed cipher suite to +cipherstring+; see http://www.openssl.org/docs/apps/ciphers.html
635
+ * for more about the format of this string.
636
+ */
637
+ static VALUE
638
+ ropenldap_conn_tls_cipher_suite_eq( VALUE self, VALUE cipherstring )
639
+ {
640
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
641
+ VALUE string = rb_obj_as_string( cipherstring );
642
+ const char *cipheropt = StringValuePtr( string );
643
+
644
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_CIPHER_SUITE, cipheropt) != LDAP_OPT_SUCCESS )
645
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_CIPHER_SUITE" );
646
+
647
+ return string;
648
+ }
649
+
650
+
651
+ /*
652
+ * call-seq:
653
+ * conn.tls_random_file -> true or false
654
+ *
655
+ * Get the path to the random file that will be used when /dev/random and /dev/urandom are
656
+ * not available.
657
+ */
658
+ static VALUE
659
+ ropenldap_conn_tls_random_file( VALUE self )
660
+ {
661
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
662
+ char *path;
663
+ VALUE pathstring = Qnil;
664
+
665
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_RANDOM_FILE, &path) != LDAP_OPT_SUCCESS )
666
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_RANDOM_FILE" );
667
+ if ( !path )
668
+ return Qnil;
669
+
670
+ pathstring = rb_str_new2( path );
671
+ ldap_memfree( path );
672
+
673
+ return pathstring;
674
+ }
675
+
676
+ /*
677
+ * call-seq:
678
+ * conn.tls_random_file = newvalue
679
+ *
680
+ * Set the path to the random file that will be used when /dev/random and /dev/urandom are
681
+ * not available.
682
+ */
683
+ static VALUE
684
+ ropenldap_conn_tls_random_file_eq( VALUE self, VALUE path )
685
+ {
686
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
687
+ VALUE pathstring = rb_obj_as_string( path );
688
+ const char *pathopt = StringValuePtr( pathstring );
689
+
690
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_RANDOM_FILE, pathopt) != LDAP_OPT_SUCCESS )
691
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_RANDOM_FILE" );
692
+
693
+ return path;
694
+ }
695
+
696
+
697
+ /*
698
+ * call-seq:
699
+ * conn.tls_dhfile -> string
700
+ *
701
+ * Path to PEM encoded Diffie-Hellman parameter file.
702
+ */
703
+ static VALUE
704
+ ropenldap_conn_tls_dhfile( VALUE self )
705
+ {
706
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
707
+ char *path;
708
+ VALUE pathstring = Qnil;
709
+
710
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_DHFILE, &path) != LDAP_OPT_SUCCESS )
711
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_DHFILE" );
712
+ if ( !path )
713
+ return Qnil;
714
+
715
+ pathstring = rb_str_new2( path );
716
+ ldap_memfree( path );
717
+
718
+ return pathstring;
719
+ }
720
+
721
+ /*
722
+ * call-seq:
723
+ * conn.tls_dhfile = newvalue
724
+ *
725
+ * Set the path to a PEM-encoded Diffie-Hellman parameter file. If this is specified, DH key
726
+ * exchange will be used for the ephemeral keying.
727
+ *
728
+ * You can use the 'openssl' command-line tool to generate the file like so:
729
+ *
730
+ * openssl dhparam -outform PEM -out dh1024.pem -5 1024
731
+ */
732
+ static VALUE
733
+ ropenldap_conn_tls_dhfile_eq( VALUE self, VALUE path )
734
+ {
735
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
736
+ VALUE pathstring = rb_obj_as_string( path );
737
+ const char *pathopt = StringValuePtr( pathstring );
738
+
739
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_DHFILE, pathopt) != LDAP_OPT_SUCCESS )
740
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_DHFILE" );
741
+
742
+ return path;
743
+ }
744
+
745
+
746
+ /*
747
+ * call-seq:
748
+ * conn.tls_crlfile -> string
749
+ *
750
+ * Get the current path to the file containing a Certificate Revocation List used for verifying that
751
+ * certificates have not been revoked.
752
+ */
753
+ static VALUE
754
+ ropenldap_conn_tls_crlfile( VALUE self )
755
+ {
756
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
757
+ char *path;
758
+ VALUE pathstring = Qnil;
759
+
760
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_CRLFILE, &path) != LDAP_OPT_SUCCESS )
761
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_CRLFILE" );
762
+ if ( !path )
763
+ return Qnil;
764
+
765
+ pathstring = rb_str_new2( path );
766
+ ldap_memfree( path );
767
+
768
+ return pathstring;
769
+ }
770
+
771
+ /*
772
+ * call-seq:
773
+ * conn.tls_crlfile = path
774
+ *
775
+ * Set the path to the file containing a Certificate Revocation List used for verifying that
776
+ * certificates have not been revoked. This value is only used when LDAP has been compiled
777
+ * to use GnuTLS.
778
+ */
779
+ static VALUE
780
+ ropenldap_conn_tls_crlfile_eq( VALUE self, VALUE path )
781
+ {
782
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
783
+ VALUE pathstring = rb_obj_as_string( path );
784
+ const char *pathopt = StringValuePtr( pathstring );
785
+
786
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_CRLFILE, pathopt) != LDAP_OPT_SUCCESS )
787
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_CRLFILE" );
788
+
789
+ return path;
790
+ }
791
+
792
+
793
+ /*
794
+ * call-seq:
795
+ * conn._tls_require_cert -> fixnum
796
+ *
797
+ * Backend method for #tls_require_cert
798
+ */
799
+ static VALUE
800
+ ropenldap_conn__tls_require_cert( VALUE self )
801
+ {
802
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
803
+ int opt;
804
+
805
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_REQUIRE_CERT, &opt) != LDAP_OPT_SUCCESS )
806
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_REQUIRE_CERT" );
807
+
808
+ return INT2FIX( opt );
809
+ }
810
+
811
+ /*
812
+ * call-seq:
813
+ * conn._tls_require_cert = fixnum
814
+ *
815
+ * Backend method for #tls_require_cert=.
816
+ */
817
+ static VALUE
818
+ ropenldap_conn__tls_require_cert_eq( VALUE self, VALUE opt )
819
+ {
820
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
821
+ const int optval = NUM2INT( opt );
822
+
823
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_REQUIRE_CERT, &optval) != LDAP_OPT_SUCCESS )
824
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_REQUIRE_CERT" );
825
+
826
+ return opt;
827
+ }
828
+
829
+
830
+ /*
831
+ * call-seq:
832
+ * conn._tls_crlcheck -> fixnum
833
+ *
834
+ * Backend method for #tls_crlcheck.
835
+ */
836
+ static VALUE
837
+ ropenldap_conn__tls_crlcheck( VALUE self )
838
+ {
839
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
840
+ int opt;
841
+
842
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_CRLCHECK, &opt) != LDAP_OPT_SUCCESS )
843
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_CRLCHECK" );
844
+
845
+ return INT2FIX( opt );
846
+ }
847
+
848
+ /*
849
+ * call-seq:
850
+ * conn._tls_crlcheck = fixnum
851
+ *
852
+ * Backend method for #tls_crlcheck=.
853
+ */
854
+ static VALUE
855
+ ropenldap_conn__tls_crlcheck_eq( VALUE self, VALUE opt )
856
+ {
857
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
858
+ const int optval = NUM2INT( opt );
859
+
860
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_CRLCHECK, &optval) != LDAP_OPT_SUCCESS )
861
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_CRLCHECK" );
862
+
863
+ return opt;
864
+ }
865
+
866
+
867
+ /*
868
+ * call-seq:
869
+ * conn.tls_protocol_min -> fixnum
870
+ *
871
+ * Gets the current minimum protocol version.
872
+ */
873
+ static VALUE
874
+ ropenldap_conn_tls_protocol_min( VALUE self )
875
+ {
876
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
877
+ int version;
878
+
879
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_PROTOCOL_MIN, &version) != LDAP_OPT_SUCCESS )
880
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_PROTOCOL_MIN" );
881
+
882
+ return INT2FIX( version );
883
+ }
884
+
885
+
886
+ /*
887
+ * call-seq:
888
+ * conn.tls_protocol_min = fixnum
889
+ *
890
+ * Set the minimum protocol version.
891
+ */
892
+ static VALUE
893
+ ropenldap_conn_tls_protocol_min_eq( VALUE self, VALUE opt )
894
+ {
895
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
896
+ const int optval = NUM2INT( opt );
897
+
898
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_PROTOCOL_MIN, &optval) != LDAP_OPT_SUCCESS )
899
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_PROTOCOL_MIN" );
900
+
901
+ return opt;
902
+ }
903
+
904
+
905
+ /*
906
+ * call-seq:
907
+ * conn.tls_package -> string
908
+ *
909
+ * :FIXME: I can't find any docs on what this does.
910
+ */
911
+ static VALUE
912
+ ropenldap_conn_tls_package( VALUE self )
913
+ {
914
+ #ifdef LDAP_OPT_X_TLS_PACKAGE
915
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
916
+ char *package;
917
+ VALUE pkgstring = Qnil;
918
+
919
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_X_TLS_PACKAGE, &package) != LDAP_OPT_SUCCESS )
920
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_X_TLS_PACKAGE" );
921
+ if ( !package )
922
+ return Qnil;
923
+
924
+ pkgstring = rb_str_new2( package );
925
+ ldap_memfree( package );
926
+
927
+ return pkgstring;
928
+ #else
929
+ rb_raise( rb_eNotImpError, "not implemented in your version of libldap." );
930
+ #endif /* LDAP_OPT_X_TLS_PACKAGE */
931
+ }
932
+
933
+
934
+ /*
935
+ * call-seq:
936
+ * conn.create_new_tls_context -> true or false
937
+ *
938
+ * Instructs the library to create a new TLS library context.
939
+ */
940
+ static VALUE
941
+ ropenldap_conn_create_new_tls_context( VALUE self )
942
+ {
943
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
944
+ const int flag = 1;
945
+
946
+ if ( ldap_set_option(ptr->ldap, LDAP_OPT_X_TLS_NEWCTX, &flag) != LDAP_OPT_SUCCESS )
947
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't set option: LDAP_OPT_X_TLS_NEWCTX" );
948
+
949
+ return Qtrue;
950
+ }
951
+
952
+
953
+ /*
954
+ * Turn a STRING_T into a URI object via URI::parse.
955
+ */
956
+ static VALUE
957
+ ropenldap_parse_uri( VALUE string )
958
+ {
959
+ StringValue( string );
960
+ return rb_funcall( ropenldap_rbmURI, rb_intern("parse"), 1, string );
961
+ }
962
+
963
+
964
+ /*
965
+ * call-seq:
966
+ * connection.uris -> array
967
+ *
968
+ * Gets an Array of URIs to be contacted by the library when trying to establish
969
+ * a connection.
970
+ *
971
+ */
972
+ static VALUE
973
+ ropenldap_conn_uris( VALUE self )
974
+ {
975
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
976
+ char *uris;
977
+ VALUE uristring, uriarray;
978
+
979
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_URI, &uris) != LDAP_OPT_SUCCESS )
980
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_URI" );
981
+
982
+ /* Convert to strings first, then collect them into URI objects */
983
+ uristring = rb_str_new2( uris );
984
+ ldap_memfree( uris );
985
+
986
+ uriarray = rb_funcall( uristring, rb_intern("split"), 0 );
987
+ rb_block_call( uriarray, rb_intern("collect!"), 0, NULL,
988
+ ropenldap_parse_uri, Qnil );
989
+
990
+ return uriarray;
991
+ }
992
+
993
+
994
+ /*
995
+ * call-seq:
996
+ * connection.fdno -> fixnum
997
+ *
998
+ * Return the file descriptor of the underlying socket. If the socket isn't connected yet,
999
+ * this method returns +nil+.
1000
+ *
1001
+ * ldapsock = IO.for_fd( conn.fdno, "w+" )
1002
+ */
1003
+ static VALUE
1004
+ ropenldap_conn_fdno( VALUE self )
1005
+ {
1006
+ struct ropenldap_connection *ptr = ropenldap_get_conn( self );
1007
+ int fdno = 0;
1008
+
1009
+ if ( ldap_get_option(ptr->ldap, LDAP_OPT_DESC, &fdno) != LDAP_OPT_SUCCESS )
1010
+ rb_raise( ropenldap_eOpenLDAPError, "couldn't get option: LDAP_OPT_DESC" );
1011
+
1012
+ /* If the socket isn't set up yet, return nil */
1013
+ if ( fdno < 0 ) return Qnil;
1014
+
1015
+ return INT2FIX( fdno );
1016
+ }
1017
+
1018
+
1019
+
1020
+
1021
+ /*
1022
+ * document-class: OpenLDAP::Connection
1023
+ */
1024
+ void
1025
+ ropenldap_init_connection( void )
1026
+ {
1027
+ ropenldap_log( "debug", "Initializing OpenLDAP::Connection" );
1028
+
1029
+ #ifdef FOR_RDOC
1030
+ ropenldap_mOpenLDAP = rb_define_module( "OpenLDAP" );
1031
+ #endif
1032
+
1033
+ /* OpenLDAP::Connection */
1034
+ ropenldap_cOpenLDAPConnection =
1035
+ rb_define_class_under( ropenldap_mOpenLDAP, "Connection", rb_cObject );
1036
+ rb_include_module( ropenldap_cOpenLDAPConnection, ropenldap_mOpenLDAPLoggable );
1037
+
1038
+ rb_define_alloc_func( ropenldap_cOpenLDAPConnection, ropenldap_conn_s_allocate );
1039
+
1040
+ rb_define_protected_method( ropenldap_cOpenLDAPConnection, "_initialize",
1041
+ ropenldap_conn_initialize, -2 );
1042
+
1043
+ rb_define_method( ropenldap_cOpenLDAPConnection, "uris", ropenldap_conn_uris, 0 );
1044
+ rb_define_method( ropenldap_cOpenLDAPConnection, "fdno", ropenldap_conn_fdno, 0 );
1045
+ rb_define_alias( ropenldap_cOpenLDAPConnection, "fileno", "fdno" );
1046
+ rb_define_method( ropenldap_cOpenLDAPConnection, "simple_bind", ropenldap_conn_simple_bind, 2 );
1047
+
1048
+ rb_define_method( ropenldap_cOpenLDAPConnection, "protocol_version",
1049
+ ropenldap_conn_protocol_version, 0 );
1050
+ rb_define_method( ropenldap_cOpenLDAPConnection, "protocol_version=",
1051
+ ropenldap_conn_protocol_version_eq, 1 );
1052
+ rb_define_method( ropenldap_cOpenLDAPConnection, "async_connect?",
1053
+ ropenldap_conn_async_connect_p, 0 );
1054
+ rb_define_method( ropenldap_cOpenLDAPConnection, "async_connect=",
1055
+ ropenldap_conn_async_connect_eq, 1 );
1056
+ rb_define_method( ropenldap_cOpenLDAPConnection, "network_timeout",
1057
+ ropenldap_conn_network_timeout, 0 );
1058
+ rb_define_method( ropenldap_cOpenLDAPConnection, "network_timeout=",
1059
+ ropenldap_conn_network_timeout_eq, 1 );
1060
+
1061
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_inplace?",
1062
+ ropenldap_conn_tls_inplace_p, 0 );
1063
+
1064
+ /* Options */
1065
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_cacertfile",
1066
+ ropenldap_conn_tls_cacertfile, 0 );
1067
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_cacertfile=",
1068
+ ropenldap_conn_tls_cacertfile_eq, 1 );
1069
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_cacertdir",
1070
+ ropenldap_conn_tls_cacertdir, 0 );
1071
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_cacertdir=",
1072
+ ropenldap_conn_tls_cacertdir_eq, 1 );
1073
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_certfile",
1074
+ ropenldap_conn_tls_certfile, 0 );
1075
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_certfile=",
1076
+ ropenldap_conn_tls_certfile_eq, 1 );
1077
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_keyfile",
1078
+ ropenldap_conn_tls_keyfile, 0 );
1079
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_keyfile=",
1080
+ ropenldap_conn_tls_keyfile_eq, 1 );
1081
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_cipher_suite",
1082
+ ropenldap_conn_tls_cipher_suite, 0 );
1083
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_cipher_suite=",
1084
+ ropenldap_conn_tls_cipher_suite_eq, 1 );
1085
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_random_file",
1086
+ ropenldap_conn_tls_random_file, 0 );
1087
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_random_file=",
1088
+ ropenldap_conn_tls_random_file_eq, 1 );
1089
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_dhfile",
1090
+ ropenldap_conn_tls_dhfile, 0 );
1091
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_dhfile=",
1092
+ ropenldap_conn_tls_dhfile_eq, 1 );
1093
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_crlfile",
1094
+ ropenldap_conn_tls_crlfile, 0 );
1095
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_crlfile=",
1096
+ ropenldap_conn_tls_crlfile_eq, 1 );
1097
+
1098
+ /* Integer options */
1099
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_protocol_min",
1100
+ ropenldap_conn_tls_protocol_min, 0 );
1101
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_protocol_min=",
1102
+ ropenldap_conn_tls_protocol_min_eq, 1 );
1103
+
1104
+ /* Read-only options */
1105
+ rb_define_method( ropenldap_cOpenLDAPConnection, "tls_package",
1106
+ ropenldap_conn_tls_package, 0 );
1107
+
1108
+ rb_define_method( ropenldap_cOpenLDAPConnection, "create_new_tls_context",
1109
+ ropenldap_conn_create_new_tls_context, 0 );
1110
+
1111
+ /* Methods with Ruby front-ends */
1112
+ rb_define_protected_method( ropenldap_cOpenLDAPConnection, "_start_tls",
1113
+ ropenldap_conn__start_tls, 0 );
1114
+ rb_define_protected_method( ropenldap_cOpenLDAPConnection, "_tls_require_cert",
1115
+ ropenldap_conn__tls_require_cert, 0 );
1116
+ rb_define_protected_method( ropenldap_cOpenLDAPConnection, "_tls_require_cert=",
1117
+ ropenldap_conn__tls_require_cert_eq, 1 );
1118
+ rb_define_protected_method( ropenldap_cOpenLDAPConnection, "_tls_crlcheck",
1119
+ ropenldap_conn__tls_crlcheck, 0 );
1120
+ rb_define_protected_method( ropenldap_cOpenLDAPConnection, "_tls_crlcheck=",
1121
+ ropenldap_conn__tls_crlcheck_eq, 1 );
1122
+
1123
+ rb_require( "openldap/connection" );
1124
+ }
1125
+