openldap 0.0.1pre11

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.
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
+