ruby-ldap 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,176 @@
1
+ /*
2
+ * saslconn.c
3
+ * $Id: saslconn.c,v 1.25 2006/02/13 17:20:32 ianmacd Exp $
4
+ */
5
+
6
+ #include "ruby.h"
7
+ #include "rbldap.h"
8
+ #if defined(HAVE_SYS_TIME_H)
9
+ # include <sys/time.h>
10
+ #endif
11
+ #if defined(HAVE_UNISTD_H)
12
+ # include <unistd.h>
13
+ #endif
14
+
15
+ extern VALUE rb_ldap_conn_initialize (int argc, VALUE argv[], VALUE self);
16
+ extern VALUE rb_ldap_conn_rebind (VALUE self);
17
+
18
+ #if defined(HAVE_LDAP_SASL_BIND_S)
19
+ int
20
+ rb_ldap_sasl_interaction (LDAP * ld, unsigned flags, void *defaults, void *in)
21
+ {
22
+ /* not implemented */
23
+ return LDAP_SUCCESS;
24
+ }
25
+
26
+ /*
27
+ * call-seq:
28
+ * conn.sasl_bind(dn=nil, mech=nil, cred=nil, sctrls=nil, cctrls=nil) => self
29
+ * conn.sasl_bind(dn=nil, mech=nil, cred=nil, sctrls=nil, cctrls=nil)
30
+ * { |conn| } => nil
31
+ *
32
+ * Bind an LDAP connection, using the DN, +dn+, the mechanism, +mech+, and the
33
+ * credential, +cred+.
34
+ *
35
+ * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
36
+ * client controls.
37
+ *
38
+ * and the bind method, +method+. If a block is given, +self+ is yielded to
39
+ * the block.
40
+ */
41
+ VALUE
42
+ rb_ldap_conn_sasl_bind (int argc, VALUE argv[], VALUE self)
43
+ {
44
+ RB_LDAP_DATA *ldapdata;
45
+
46
+ VALUE arg1, arg2, arg3, arg4, arg5;
47
+ int version;
48
+ char *dn = NULL;
49
+ char *mechanism = NULL;
50
+ struct berval *cred = ALLOCA_N (struct berval, 1);
51
+ LDAPControl **serverctrls = NULL;
52
+ LDAPControl **clientctrls = NULL;
53
+
54
+ /*
55
+ struct berval *servercred = NULL;
56
+ char *sasl_realm = NULL;
57
+ char *sasl_authc_id = NULL;
58
+ char *sasl_authz_id = NULL;
59
+ char *sasl_secprops = NULL;
60
+ struct berval passwd = { 0, NULL };
61
+ */
62
+
63
+ unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
64
+
65
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
66
+ if (!ldapdata->ldap)
67
+ {
68
+ if (rb_iv_get (self, "@args") != Qnil)
69
+ {
70
+ rb_ldap_conn_rebind (self);
71
+ GET_LDAP_DATA (self, ldapdata);
72
+ }
73
+ else
74
+ {
75
+ rb_raise (rb_eLDAP_InvalidDataError,
76
+ "The LDAP handler has already unbound.");
77
+ }
78
+ }
79
+
80
+ if (ldapdata->bind)
81
+ {
82
+ rb_raise (rb_eLDAP_Error, "already bound.");
83
+ };
84
+ switch (rb_scan_args (argc, argv, "23", &arg1, &arg2, &arg3, &arg4, &arg5))
85
+ {
86
+ case 2: /* don't need the cred for GSSAPI */
87
+ dn = StringValuePtr (arg1);
88
+ mechanism = StringValuePtr (arg2);
89
+ serverctrls = NULL;
90
+ clientctrls = NULL;
91
+ if (rb_iv_get (self, "@sasl_quiet") == Qtrue)
92
+ sasl_flags = LDAP_SASL_QUIET;
93
+ break;
94
+ case 3:
95
+ dn = StringValuePtr (arg1);
96
+ mechanism = StringValuePtr (arg2);
97
+ cred->bv_val = StringValueCStr (arg3);
98
+ cred->bv_len = RSTRING_LEN (arg3);
99
+ break;
100
+ case 4:
101
+ dn = StringValuePtr (arg1);
102
+ mechanism = StringValuePtr (arg2);
103
+ cred->bv_val = StringValueCStr (arg3);
104
+ cred->bv_len = RSTRING_LEN (arg3);
105
+ serverctrls = rb_ldap_get_controls (arg4);
106
+ break;
107
+ case 5:
108
+ dn = StringValuePtr (arg1);
109
+ mechanism = StringValuePtr (arg2);
110
+ cred->bv_val = StringValueCStr (arg3);
111
+ cred->bv_len = RSTRING_LEN (arg3);
112
+ serverctrls = rb_ldap_get_controls (arg4);
113
+ clientctrls = rb_ldap_get_controls (arg5);
114
+ break;
115
+ default:
116
+ rb_bug ("rb_ldap_conn_bind_s");
117
+ }
118
+
119
+ ldap_get_option (ldapdata->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
120
+ if (version < LDAP_VERSION3)
121
+ {
122
+ version = LDAP_VERSION3;
123
+ ldapdata->err =
124
+ ldap_set_option (ldapdata->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
125
+ Check_LDAP_Result (ldapdata->err);
126
+ }
127
+
128
+ /* the following works for GSSAPI, at least */
129
+ ldapdata->err =
130
+ ldap_sasl_interactive_bind_s (ldapdata->ldap, dn, mechanism,
131
+ serverctrls, clientctrls, sasl_flags,
132
+ rb_ldap_sasl_interaction, NULL);
133
+
134
+ if (ldapdata->err == LDAP_SASL_BIND_IN_PROGRESS)
135
+ {
136
+ rb_raise (rb_eNotImpError,
137
+ "SASL authentication is not fully supported.");
138
+ /* How can I implement this with portability? */
139
+ /*
140
+ VALUE scred;
141
+ scred = rb_tainted_str_new(servercred->bv_val,
142
+ servercred->bv_len);
143
+ */
144
+ }
145
+ else
146
+ {
147
+ Check_LDAP_Result (ldapdata->err);
148
+ ldapdata->bind = 1;
149
+ }
150
+
151
+ if (rb_block_given_p ())
152
+ {
153
+ rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
154
+ return Qnil;
155
+ }
156
+ else
157
+ {
158
+ return self;
159
+ };
160
+ }
161
+
162
+ #else /* HAVE_LDAP_SASL_BIND_S */
163
+
164
+ VALUE
165
+ rb_ldap_conn_sasl_bind (int argc, VALUE argv[], VALUE self)
166
+ {
167
+ rb_notimplement ();
168
+ }
169
+
170
+ #endif /* HAVE_LDAP_SASL_BIND_S */
171
+
172
+ void
173
+ Init_ldap_saslconn ()
174
+ {
175
+ rb_define_method (rb_cLDAP_Conn, "sasl_bind", rb_ldap_conn_sasl_bind, -1);
176
+ }
@@ -0,0 +1,377 @@
1
+ /*
2
+ * sslconn.c
3
+ * $Id: sslconn.c,v 1.18 2006/04/19 22:13:26 ianmacd Exp $
4
+ */
5
+
6
+ #include "ruby.h"
7
+ #include "rbldap.h"
8
+ #if defined(HAVE_SYS_TIME_H)
9
+ # include <sys/time.h>
10
+ #endif
11
+ #if defined(HAVE_UNISTD_H)
12
+ # include <unistd.h>
13
+ #endif
14
+
15
+ #if defined(HAVE_LDAP_START_TLS_S)
16
+ # define USE_OPENLDAP_SSLCONN
17
+ #elif defined(HAVE_LDAPSSL_INIT)
18
+ # define USE_NSSLDAP_SSLCONN
19
+ #elif defined(HAVE_LDAP_SSLINIT)
20
+ # define USE_WLDAP32_SSLCONN
21
+ #endif
22
+
23
+ VALUE rb_cLDAP_SSLConn;
24
+
25
+ #ifdef USE_OPENLDAP_SSLCONN
26
+ static VALUE
27
+ rb_openldap_sslconn_initialize (int argc, VALUE argv[], VALUE self)
28
+ {
29
+ RB_LDAP_DATA *ldapdata;
30
+ LDAP *cldap;
31
+ char *chost = NULL;
32
+ int cport = LDAP_PORT;
33
+
34
+ VALUE arg1, arg2, arg3, arg4, arg5;
35
+
36
+ LDAPControl **serverctrls = NULL;
37
+ LDAPControl **clientctrls = NULL;
38
+ int version;
39
+ int start_tls;
40
+
41
+
42
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
43
+ if (ldapdata->ldap)
44
+ return Qnil;
45
+
46
+ switch (rb_scan_args (argc, argv, "05", &arg1, &arg2, &arg3, &arg4, &arg5))
47
+ {
48
+ case 0:
49
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
50
+ strcpy (chost, "localhost");
51
+ cport = LDAP_PORT;
52
+ start_tls = 0;
53
+ break;
54
+ case 1:
55
+ chost = StringValueCStr (arg1);
56
+ cport = LDAP_PORT;
57
+ start_tls = 0;
58
+ break;
59
+ case 2:
60
+ chost = StringValueCStr (arg1);
61
+ cport = NUM2INT (arg2);
62
+ start_tls = 0;
63
+ break;
64
+ case 3:
65
+ chost = StringValueCStr (arg1);
66
+ cport = NUM2INT (arg2);
67
+ start_tls = (arg3 == Qtrue) ? 1 : 0;
68
+ break;
69
+ case 4:
70
+ chost = StringValueCStr (arg1);
71
+ cport = NUM2INT (arg2);
72
+ start_tls = (arg3 == Qtrue) ? 1 : 0;
73
+ serverctrls = rb_ldap_get_controls (arg4);
74
+ break;
75
+ case 5:
76
+ chost = StringValueCStr (arg1);
77
+ cport = NUM2INT (arg2);
78
+ start_tls = (arg3 == Qtrue) ? 1 : 0;
79
+ serverctrls = rb_ldap_get_controls (arg4);
80
+ clientctrls = rb_ldap_get_controls (arg5);
81
+ break;
82
+ default:
83
+ rb_bug ("rb_ldap_conn_new");
84
+ }
85
+
86
+ cldap = ldap_init (chost, cport);
87
+ if (!cldap)
88
+ rb_raise (rb_eLDAP_ResultError, "can't initialise an LDAP session");
89
+
90
+ ldapdata->ldap = cldap;
91
+
92
+ if (rb_block_given_p ())
93
+ {
94
+ rb_yield (self);
95
+ }
96
+
97
+ ldap_get_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version);
98
+ if (version < LDAP_VERSION3)
99
+ {
100
+ version = LDAP_VERSION3;
101
+ ldapdata->err =
102
+ ldap_set_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version);
103
+ Check_LDAP_Result (ldapdata->err);
104
+ }
105
+
106
+ if (start_tls)
107
+ {
108
+ ldapdata->err = ldap_start_tls_s (cldap, serverctrls, clientctrls);
109
+ Check_LDAP_Result (ldapdata->err);
110
+ }
111
+ else
112
+ {
113
+ int opt = LDAP_OPT_X_TLS_HARD;
114
+ ldapdata->err = ldap_set_option (cldap, LDAP_OPT_X_TLS, &opt);
115
+ Check_LDAP_Result (ldapdata->err);
116
+ }
117
+
118
+ rb_iv_set (self, "@args", rb_ary_new4 (argc, argv));
119
+ rb_iv_set (self, "@sasl_quiet", Qfalse);
120
+
121
+ return Qnil;
122
+ }
123
+ #endif /* USE_OPENLDAP_SSLCONN */
124
+
125
+
126
+ #ifdef USE_NSSLDAP_SSLCONN
127
+ static VALUE
128
+ rb_nssldap_sslconn_initialize (int argc, VALUE argv[], VALUE self)
129
+ {
130
+ RB_LDAP_DATA *ldapdata;
131
+ LDAP *cldap;
132
+ char *chost = NULL;
133
+ char *certpath = NULL;
134
+ int cport = LDAP_PORT;
135
+ int csecure = 0;
136
+
137
+ VALUE arg1, arg2, arg3, arg4;
138
+
139
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
140
+ if (ldapdata->ldap)
141
+ return Qnil;
142
+
143
+ switch (rb_scan_args (argc, argv, "04", &arg1, &arg2, &arg3, &arg4))
144
+ {
145
+ case 0:
146
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
147
+ strcpy (chost, "localhost");
148
+ cport = LDAP_PORT;
149
+ csecure = 0;
150
+ certpath = NULL;
151
+ break;
152
+ case 1:
153
+ chost = StringValueCStr (arg1);
154
+ cport = LDAP_PORT;
155
+ csecure = 0;
156
+ certpath = NULL;
157
+ break;
158
+ case 2:
159
+ chost = StringValueCStr (arg1);
160
+ cport = NUM2INT (arg2);
161
+ csecure = 0;
162
+ certpath = NULL;
163
+ break;
164
+ case 3:
165
+ chost = StringValueCStr (arg1);
166
+ cport = NUM2INT (arg2);
167
+ csecure = (arg3 == Qtrue) ? 1 : 0;
168
+ certpath = NULL;
169
+ break;
170
+ case 4:
171
+ chost = StringValueCStr (arg1);
172
+ cport = NUM2INT (arg2);
173
+ csecure = (arg3 == Qtrue) ? 1 : 0;
174
+ certpath = (arg4 == Qnil) ? NULL : StringValueCStr (arg4);
175
+ break;
176
+ default:
177
+ rb_bug ("rb_ldap_conn_new");
178
+ }
179
+
180
+ /***
181
+ ldapssl_client_init():
182
+ http://docs.iplanet.com/docs/manuals/dirsdk/csdk41/html/function.htm#25963
183
+ ldapssl_client_authinit():
184
+ http://docs.iplanet.com/docs/manuals/dirsdk/csdk41/html/function.htm#26024
185
+ ***/
186
+ ldapssl_client_init (certpath, NULL);
187
+ cldap = ldapssl_init (chost, cport, csecure);
188
+ ldapdata->ldap = cldap;
189
+
190
+ rb_iv_set (self, "@args", Qnil);
191
+
192
+ return Qnil;
193
+ }
194
+ #endif /* USE_NSSLDAP_SSLCONN */
195
+
196
+ #if defined(USE_WLDAP32_SSLCONN)
197
+ static VALUE
198
+ rb_wldap32_sslconn_initialize (int argc, VALUE argv[], VALUE self)
199
+ {
200
+ RB_LDAP_DATA *ldapdata;
201
+ LDAP *cldap;
202
+ char *chost;
203
+ int cport;
204
+ int csecure;
205
+ int version;
206
+
207
+ VALUE arg1, arg2, arg3;
208
+
209
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
210
+ if (ldapdata->ldap)
211
+ return Qnil;
212
+
213
+ switch (rb_scan_args (argc, argv, "02", &arg1, &arg2, &arg3))
214
+ {
215
+ case 0:
216
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
217
+ strcpy (chost, "localhost");
218
+ cport = LDAP_PORT;
219
+ csecure = 1;
220
+ break;
221
+ case 1:
222
+ chost = StringValueCStr (arg1);
223
+ cport = LDAP_PORT;
224
+ csecure = 1;
225
+ break;
226
+ case 2:
227
+ chost = StringValueCStr (arg1);
228
+ cport = NUM2INT (arg2);
229
+ csecure = 1;
230
+ break;
231
+ case 3:
232
+ chost = StringValueCStr (arg1);
233
+ cport = NUM2INT (arg2);
234
+ csecure = (arg3 == Qtrue) ? 1 : 0;
235
+ break;
236
+ default:
237
+ rb_bug ("rb_ldap_conn_new");
238
+ }
239
+
240
+ cldap = ldap_sslinit (chost, cport, csecure);
241
+ ldapdata->ldap = cldap;
242
+
243
+ #if defined(HAVE_LDAP_GET_OPTION) && defined(HAVE_LDAP_SET_OPTION)
244
+ ldap_get_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version);
245
+ if (version < LDAP_VERSION3)
246
+ {
247
+ version = LDAP_VERSION3;
248
+ ldapdata->err =
249
+ ldap_set_option (cldap, LDAP_OPT_PROTOCOL_VERSION, &version);
250
+ Check_LDAP_Result (ldapdata->err);
251
+ }
252
+ #endif
253
+
254
+ rb_iv_set (self, "@args", Qnil);
255
+
256
+ return Qnil;
257
+ }
258
+
259
+ VALUE
260
+ rb_ldap_sslconn_bind_f (int argc, VALUE argv[], VALUE self,
261
+ VALUE (*rb_ldap_sslconn_bind_func) (int, VALUE[],
262
+ VALUE))
263
+ {
264
+ RB_LDAP_DATA *ldapdata;
265
+
266
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
267
+ if (!ldapdata->ldap)
268
+ {
269
+ if (rb_iv_get (self, "@args") != Qnil)
270
+ {
271
+ rb_ldap_conn_rebind (self);
272
+ GET_LDAP_DATA (self, ldapdata);
273
+ }
274
+ else
275
+ {
276
+ rb_raise (rb_eLDAP_InvalidDataError,
277
+ "The LDAP handler has already unbound.");
278
+ }
279
+ }
280
+
281
+ ldapdata->err = ldap_connect (ldapdata->ldap, NULL);
282
+ Check_LDAP_Result (ldapdata->err);
283
+
284
+ return rb_ldap_sslconn_bind_func (argc, argv, self);
285
+ }
286
+
287
+ /*
288
+ * call-seq:
289
+ * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE) => self
290
+ * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
291
+ * { |conn| } => self
292
+ *
293
+ * Bind an LDAP connection, using the DN, +dn+, the credential, +password+,
294
+ * and the bind method, +method+. If a block is given, +self+ is yielded to
295
+ * the block.
296
+ */
297
+ VALUE
298
+ rb_ldap_sslconn_bind_s (int argc, VALUE argv[], VALUE self)
299
+ {
300
+ return rb_ldap_sslconn_bind_f (argc, argv, self, rb_ldap_conn_bind_s);
301
+ }
302
+
303
+ /*
304
+ * call-seq:
305
+ * conn.simple_bind(dn=nil, password=nil) => self
306
+ * conn.simple_bind(dn=nil, password=nil) { |conn| } => self
307
+ *
308
+ * Bind an LDAP connection, using the DN, +dn+, and the credential, +password+.
309
+ * If a block is given, +self+ is yielded to the block.
310
+ */
311
+ VALUE
312
+ rb_ldap_sslconn_simple_bind_s (int argc, VALUE argv[], VALUE self)
313
+ {
314
+ return rb_ldap_sslconn_bind_f (argc, argv, self,
315
+ rb_ldap_conn_simple_bind_s);
316
+ }
317
+ #endif /* USE_WLDAP32_SSLCONN */
318
+
319
+ /*
320
+ * call-seq:
321
+ * LDAP::SSLConn.new(host='localhost', port=LDAP_PORT,
322
+ * start_tls=false, sctrls=nil, cctrls=nil)
323
+ * => LDAP::SSLConn
324
+ * LDAP::SSLConn.new(host='localhost', port=LDAP_PORT,
325
+ * start_tls=false, sctrls=nil, cctrls=nil) { |conn| }
326
+ * => LDAP::SSLConn
327
+ *
328
+ * Return a new LDAP::SSLConn connection to the server, +host+, on port +port+.
329
+ * If +start_tls+ is *true*, START_TLS will be used to establish the
330
+ * connection, automatically setting the LDAP protocol version to v3 if it is
331
+ * not already set.
332
+ *
333
+ * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
334
+ * client controls.
335
+ */
336
+ VALUE
337
+ rb_ldap_sslconn_initialize (int argc, VALUE argv[], VALUE self)
338
+ {
339
+ #if defined(USE_OPENLDAP_SSLCONN)
340
+ return rb_openldap_sslconn_initialize (argc, argv, self);
341
+ #elif defined(USE_NSSLDAP_SSLCONN)
342
+ return rb_nssldap_sslconn_initialize (argc, argv, self);
343
+ #elif defined(USE_WLDAP32_SSLCONN)
344
+ return rb_wldap32_sslconn_initialize (argc, argv, self);
345
+ #else
346
+ rb_notimplement ();
347
+ #endif
348
+ }
349
+
350
+ /* :nodoc: */
351
+ VALUE
352
+ rb_ldap_sslconn_s_open (int argc, VALUE argv[], VALUE klass)
353
+ {
354
+ rb_notimplement ();
355
+ }
356
+
357
+ /* Document-class: LDAP::SSLConn
358
+ *
359
+ * Create and manipulate encrypted LDAP connections. LDAP::SSLConn is a
360
+ * subclass of LDAP::Conn and so has access to the same methods, except for
361
+ * LDAP::SSLConn.open, which is not implemented.
362
+ */
363
+ void
364
+ Init_ldap_sslconn ()
365
+ {
366
+ rb_cLDAP_SSLConn =
367
+ rb_define_class_under (rb_mLDAP, "SSLConn", rb_cLDAP_Conn);
368
+ rb_define_singleton_method (rb_cLDAP_SSLConn, "open",
369
+ rb_ldap_sslconn_s_open, -1);
370
+ rb_define_method (rb_cLDAP_SSLConn, "initialize",
371
+ rb_ldap_sslconn_initialize, -1);
372
+ #ifdef USE_WLDAP32_SSLCONN
373
+ rb_define_method (rb_cLDAP_SSLConn, "bind", rb_ldap_sslconn_bind_s, -1);
374
+ rb_define_method (rb_cLDAP_SSLConn, "simple_bind",
375
+ rb_ldap_sslconn_simple_bind_s, -1);
376
+ #endif
377
+ }