ruby-ldap 0.9.11 → 0.9.12
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +18 -0
- data/FAQ +5 -9
- data/NOTES +29 -0
- data/README +22 -18
- data/TODO +10 -0
- data/clientauth.c +605 -0
- data/conn.c +24 -1
- data/entry.c +9 -9
- data/extconf.rb +70 -29
- data/ldap.c +67 -0
- data/lib/ldap/control.rb +3 -3
- data/lib/ldap/ldif.rb +264 -269
- data/lib/ldap/schema.rb +39 -33
- data/mod.c +7 -3
- data/rbldap.h +8 -6
- data/test/cookbooks/apt/metadata.rb +13 -0
- data/test/cookbooks/apt/providers/repository.rb +73 -0
- data/test/cookbooks/apt/recipes/cacher-client.rb +44 -0
- data/test/cookbooks/apt/recipes/cacher.rb +45 -0
- data/test/cookbooks/apt/recipes/default.rb +50 -0
- data/test/cookbooks/apt/resources/repository.rb +30 -0
- data/test/cookbooks/nginx/attributes/default.rb +35 -0
- data/test/cookbooks/nginx/definitions/nginx_site.rb +35 -0
- data/test/cookbooks/nginx/metadata.rb +86 -0
- data/test/cookbooks/nginx/recipes/default.rb +56 -0
- data/test/cookbooks/nginx/recipes/source.rb +143 -0
- data/test/cookbooks/openldap/attributes/default.rb +61 -0
- data/test/cookbooks/openldap/metadata.rb +99 -0
- data/test/cookbooks/openldap/recipes/auth.rb +70 -0
- data/test/cookbooks/openldap/recipes/client.rb +28 -0
- data/test/cookbooks/openldap/recipes/default.rb +18 -0
- data/test/cookbooks/openldap/recipes/server.rb +110 -0
- data/test/cookbooks/postgresql/attributes/default.rb +68 -0
- data/test/cookbooks/postgresql/metadata.rb +15 -0
- data/test/cookbooks/postgresql/recipes/client.rb +27 -0
- data/test/cookbooks/postgresql/recipes/default.rb +20 -0
- data/test/cookbooks/postgresql/recipes/server.rb +36 -0
- data/test/cookbooks/postgresql/recipes/server_debian.rb +51 -0
- data/test/cookbooks/postgresql/recipes/server_redhat.rb +84 -0
- data/test/cookbooks/sqlite/metadata.rb +11 -0
- data/test/cookbooks/sqlite/recipes/default.rb +26 -0
- data/test/cookbooks/vagrant_main/recipes/default.rb +12 -0
- data/test/moz_cert.rb +105 -0
- data/test/setup.rb +2 -2
- data/win/wldap32.def +257 -0
- metadata +78 -55
data/ChangeLog
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
Tue Dec 27 15:17:03 UTC 2011 Alexey Chebotar <alexey.chebotar@gmail.com>
|
2
|
+
* Version 0.9.12
|
3
|
+
|
4
|
+
* Enable client certificate authentication for mozilla ldap 6.0 only.
|
5
|
+
Thank to Yuri Arabadji.
|
6
|
+
* New patch for LDAP::Mod data corruption. Thanks to Aprotim Sanyal.
|
7
|
+
* Modify mod_type dangling pointer corruption. Thank you, anon!
|
8
|
+
* Fixed bug in ldap/ldif.rb (GH-6). Thanks to bbense.
|
9
|
+
* Added functions:
|
10
|
+
LDAP::Conn.open_uri(uri);
|
11
|
+
LDAP::explode_dn(dn, notypes);
|
12
|
+
LDAP::explode_rdn(rdn, notypes)
|
13
|
+
Thanks to Marek Veber and Antonio Terceiro.
|
14
|
+
* Fixed many memory leaks. Thanks to Marek Veber and Antonio Terceiro.
|
15
|
+
* Fixed compile with ruby 1.9.2. Thanks to Hiroki Najima.
|
16
|
+
* On windows, the default ldap library became wldap32.
|
17
|
+
Thanks to Hiroki Najima.
|
18
|
+
|
1
19
|
Mon Mar 15 19:15:49 UTC 2010 Alexey Chebotar <alexey.chebotar@gmail.com>
|
2
20
|
* Version 0.9.11
|
3
21
|
* Allow passing SASL interaction options.
|
data/FAQ
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
$Id: FAQ,v 1.6 2006/04/25 08:43:12 ianmacd Exp $
|
2
|
-
|
3
|
-
|
4
1
|
FAQ
|
5
2
|
---
|
6
3
|
|
@@ -10,21 +7,19 @@ A. Create a LDAP::Mod object with the flag LDAP::LDAP_MOD_BVALUES as follows:
|
|
10
7
|
|
11
8
|
entry = [
|
12
9
|
LDAP::mod(LDAP::LDAP_MOD_ADD|LDAP_MOD_BVALUES, 'jpegPhoto', [jpeg_img]),
|
13
|
-
LDAP::mod(LDAP::LDAP_MOD_ADD, 'cn', ['Takaaki Tateishi'])
|
14
|
-
...
|
10
|
+
LDAP::mod(LDAP::LDAP_MOD_ADD, 'cn', ['Takaaki Tateishi']) #, ...
|
15
11
|
]
|
16
12
|
conn.add("dc=localhost, dc=localdomain", entry)
|
17
13
|
|
18
14
|
|
19
15
|
|
20
|
-
Q. Is there shortcut method for adding/modifying entries
|
16
|
+
Q. Is there shortcut method for adding/modifying entries?
|
21
17
|
|
22
18
|
A. Yes, there is. You can directly give LDAP::Conn#add/modify hash data as
|
23
19
|
follows:
|
24
20
|
|
25
21
|
entry = {
|
26
|
-
'objectclass' => [ 'top', 'person' ]
|
27
|
-
...
|
22
|
+
'objectclass' => [ 'top', 'person' ] #, ...
|
28
23
|
}
|
29
24
|
conn.add( "cn=foobar, dc=localhost, dc=localdomain", entry )
|
30
25
|
|
@@ -49,7 +44,7 @@ A. Yes, as of version 0.9.4, you can. Set the size limit using
|
|
49
44
|
conn.set_option( LDAP::LDAP_OPT_SIZELIMIT, 10 )
|
50
45
|
|
51
46
|
conn.search2( 'dc=localhost,dc=localdomain',
|
52
|
-
|
47
|
+
LDAP::LDAP_SCOPE_SUBTREE, '(objectClass=*)' )
|
53
48
|
|
54
49
|
if conn.err == LDAP::LDAP_SIZELIMIT_EXCEEDED
|
55
50
|
# Results set was truncated by server.
|
@@ -60,3 +55,4 @@ A. Yes, as of version 0.9.4, you can. Set the size limit using
|
|
60
55
|
will likely have its own maximum configured, so it can be important to
|
61
56
|
check for this condition on all of your calls to LDAP::Conn#search and
|
62
57
|
LDAP::Conn#search2.
|
58
|
+
|
data/NOTES
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
0.9.12
|
2
|
+
-----
|
3
|
+
|
4
|
+
* On windows, the default ldap library became wldap32;
|
5
|
+
* Fixed compile with ruby 1.9.2.
|
6
|
+
|
7
|
+
Thank to Hiroki Najima!
|
8
|
+
|
9
|
+
* Fixed many memory leaks;
|
10
|
+
* Added functions:
|
11
|
+
LDAP::Conn.open_uri(uri);
|
12
|
+
LDAP::explode_dn(dn, notypes);
|
13
|
+
LDAP::explode_rdn(rdn, notypes).
|
14
|
+
|
15
|
+
Thanks to Marek Veber and Antonio Terceiro!
|
16
|
+
|
17
|
+
* Fixed bug in ldap/ldif.rb (GH-6).
|
18
|
+
|
19
|
+
Thanks to bbense.
|
20
|
+
|
21
|
+
* Fixed LDAP::Mod data corruption.
|
22
|
+
|
23
|
+
Thanks to Aprotim Sanyal!
|
24
|
+
|
25
|
+
* Enable client certificate authentication for mozilla ldap 6.0 only.
|
26
|
+
|
27
|
+
Thanks to Yuri Arabadji!
|
28
|
+
|
29
|
+
|
1
30
|
0.9.11
|
2
31
|
-----
|
3
32
|
|
data/README
CHANGED
@@ -7,22 +7,20 @@ Copyright (C) 2009 Alexey Chebotar <alexey.chebotar@gmail.com>
|
|
7
7
|
|
8
8
|
DESCRIPTION
|
9
9
|
|
10
|
-
|
10
|
+
Ruby/LDAP is a Ruby extension library that provides an interface to the LDAP
|
11
11
|
API as described in RFC1823.
|
12
12
|
-------------------------------------------------------------------------------
|
13
13
|
|
14
14
|
REQUIREMENT
|
15
15
|
|
16
|
-
* Ruby 1.8.x
|
16
|
+
* Ruby 1.8.x or 1.9.x
|
17
17
|
* OpenLDAP, Netscape SDK, Windows 2003 or Windows XP
|
18
|
-
|
19
18
|
-------------------------------------------------------------------------------
|
20
19
|
|
21
20
|
PORTS
|
22
21
|
|
23
22
|
* FreeBSD ("Akinori -Aki- MUSHA" <knu@idaemons.org>)
|
24
23
|
* Debian (Akira Yamada <akira@ruby-lang.org>)
|
25
|
-
|
26
24
|
-------------------------------------------------------------------------------
|
27
25
|
|
28
26
|
BUILDING
|
@@ -41,7 +39,6 @@ install with:
|
|
41
39
|
|
42
40
|
If you're building the software on Windows, you may need to use nmake instead
|
43
41
|
of make.
|
44
|
-
|
45
42
|
-------------------------------------------------------------------------------
|
46
43
|
|
47
44
|
LICENSE
|
@@ -240,27 +237,34 @@ Here are some URLs that contain useful information about LDAP:
|
|
240
237
|
http://ldap.hklc.com/
|
241
238
|
* Object Identifiers Registry
|
242
239
|
http://www.alvestrand.no/harald/objectid/
|
240
|
+
-------------------------------------------------------------------------------
|
243
241
|
|
244
242
|
THANKS
|
245
243
|
|
246
244
|
This list maybe not correct. If you notice mistakes of this list, please point out.
|
247
245
|
|
248
|
-
*
|
246
|
+
* Adam Doligalski
|
249
247
|
* Akinori MUSHA
|
250
248
|
* Akira Yamada
|
249
|
+
* Anthony M. Martinez
|
250
|
+
* Antonio Terceiro
|
251
|
+
* Aprotim Sanyal
|
252
|
+
* Chris Scharf
|
253
|
+
* Hadmut Danisch
|
254
|
+
* Hiroki Najima
|
255
|
+
* Jan Mikkelsen
|
256
|
+
* Kouhei Sutou
|
257
|
+
* Marek Veber
|
258
|
+
* Mark Kittisopikul
|
259
|
+
* Michael Granger
|
260
|
+
* Milos Jakubicek
|
251
261
|
* Pirmin Kalberer
|
252
262
|
* Radek Hnilica
|
253
|
-
*
|
254
|
-
* Yuuzou Gotou
|
263
|
+
* S. Potter
|
255
264
|
* Tilo Sloboda
|
256
265
|
* Usa Nakamura
|
257
|
-
*
|
258
|
-
*
|
259
|
-
*
|
260
|
-
*
|
261
|
-
* bidon
|
262
|
-
* Milos Jakubicek: Patch.
|
263
|
-
* S. Potter [mbbx6spp]: Gem Packaging Support
|
264
|
-
* Kouhei Sutou
|
265
|
-
* Michael Granger: Patch.
|
266
|
-
* Anthony M. Martinez: Patch.
|
266
|
+
* Yuri Arabadji
|
267
|
+
* Yuuzou Gotou
|
268
|
+
* atsu@@metallic.co.jp
|
269
|
+
* bbense
|
270
|
+
* bidon
|
data/TODO
CHANGED
@@ -3,6 +3,16 @@
|
|
3
3
|
To-do list
|
4
4
|
----------
|
5
5
|
|
6
|
+
- Setup a vagrant boxes for tests:
|
7
|
+
* 32/64 Ubuntu Lucid ( ruby-ldap http://packages.ubuntu.com/lucid/libldap-ruby1.8 )
|
8
|
+
* 32/64 Debian 6.0.3 ( ruby-ldap http://packages.debian.org/sid/ruby/libldap-ruby1.8 )
|
9
|
+
* 32/64 Arch 2011.08.19 ( ruby-ldap https://aur.archlinux.org/packages.php?ID=13471 )
|
10
|
+
* 32/64 FreeBSD 8.2 (9.0-RC1, 7.4) ( ruby-ldap http://www.freebsd.org/cgi/cvsweb.cgi/ports/net/ruby-ldap/ )
|
11
|
+
|
12
|
+
|
13
|
+
Ian's Td-do list
|
14
|
+
----------
|
15
|
+
|
6
16
|
- Support for more LDAPv3 controls and extensions.
|
7
17
|
|
8
18
|
- DSML support.
|
data/clientauth.c
ADDED
@@ -0,0 +1,605 @@
|
|
1
|
+
/*
|
2
|
+
* clientauth.c
|
3
|
+
* Composed by Yuri Arabadji @ Fused Network
|
4
|
+
*
|
5
|
+
* bugs only: yuri[.@.]deepunix.net
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include "ruby.h"
|
9
|
+
#include "rbldap.h"
|
10
|
+
#ifdef HAVE_SYS_TIME_H
|
11
|
+
#include <sys/time.h>
|
12
|
+
#endif
|
13
|
+
#ifdef HAVE_UNISTD_H
|
14
|
+
#include <unistd.h>
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#include <stdarg.h>
|
18
|
+
#include <errno.h>
|
19
|
+
|
20
|
+
#ifdef USE_SSL_CLIENTAUTH
|
21
|
+
#warning ########################################################
|
22
|
+
#warning
|
23
|
+
#warning " Enabling highly experimental code. "
|
24
|
+
#warning "Expect breakage, ice melting, floods and world terror."
|
25
|
+
#warning
|
26
|
+
#warning ########################################################
|
27
|
+
|
28
|
+
#include <nspr/nspr.h>
|
29
|
+
#include <ldap_ssl.h>
|
30
|
+
#include <ldappr.h>
|
31
|
+
#include <signal.h>
|
32
|
+
|
33
|
+
// helpful macros
|
34
|
+
#define LDAPTOOL_RESULT_IS_AN_ERROR( rc ) \
|
35
|
+
( (rc) != LDAP_SUCCESS && (rc) != LDAP_COMPARE_TRUE \
|
36
|
+
&& (rc) != LDAP_COMPARE_FALSE )
|
37
|
+
|
38
|
+
/* copied from ldaprot.h - required to parse the pwpolicy ctrl */
|
39
|
+
#define LDAP_TAG_PWP_WARNING 0xA0L /* context specific + constructed */
|
40
|
+
#define LDAP_TAG_PWP_SECSLEFT 0x80L /* context specific + primitive */
|
41
|
+
#define LDAP_TAG_PWP_GRCLOGINS 0x81L /* context specific + primitive + 1 */
|
42
|
+
#define LDAP_TAG_PWP_ERROR 0x81L /* context specific + primitive + 1 */
|
43
|
+
|
44
|
+
|
45
|
+
// checks for *SSL* error
|
46
|
+
#define Check_LDAP_Error_MSG(retval, errmsg) { \
|
47
|
+
if( (long)(retval) == LDAP_OPT_ERROR ){ \
|
48
|
+
rb_raise(rb_eLDAP_ResultError, "%s. Lower layer reported: %s.", errmsg, ldapssl_err2string(PORT_GetError())); \
|
49
|
+
} \
|
50
|
+
}
|
51
|
+
|
52
|
+
////////////////////////////////////////////////////////////////////////////////
|
53
|
+
|
54
|
+
VALUE rb_cLDAP_SSLAuthConn;
|
55
|
+
|
56
|
+
// forward declare 'em
|
57
|
+
VALUE rb_ldap_sslauthconn_initialize(int, VALUE[], VALUE);
|
58
|
+
void ldaptool_print_referrals(char**);
|
59
|
+
void print_to_stdout(char*, ...);
|
60
|
+
void handle_sigint(int, siginfo_t*, void*);
|
61
|
+
|
62
|
+
////////////////////////////////////////////////////////////////////////////////
|
63
|
+
//
|
64
|
+
// Thank you, ldaptool / common.c!
|
65
|
+
//
|
66
|
+
////////////////////////////////////////////////////////////////////////////////
|
67
|
+
|
68
|
+
/*
|
69
|
+
* Wait for a result, check for and display errors and referrals.
|
70
|
+
* Also recognize and display "Unsolicited notification" messages.
|
71
|
+
* Returns an LDAP error code.
|
72
|
+
*/
|
73
|
+
int
|
74
|
+
wait4result(LDAP *ld, int msgid, struct berval **servercredp, char *msg) {
|
75
|
+
LDAPMessage *res;
|
76
|
+
int rc, received_only_unsolicited = 1;
|
77
|
+
|
78
|
+
while (received_only_unsolicited) {
|
79
|
+
res = NULL;
|
80
|
+
if ((rc = ldap_result(ld, msgid, 1, (struct timeval *) NULL, &res))
|
81
|
+
== LDAP_OPT_ERROR) {
|
82
|
+
return ldaptool_print_lderror(ld, msg);
|
83
|
+
}
|
84
|
+
|
85
|
+
/*
|
86
|
+
* Special handling for unsolicited notifications:
|
87
|
+
* 1. Parse and display contents.
|
88
|
+
* 2. go back and wait for another (real) result.
|
89
|
+
*/
|
90
|
+
if (rc == LDAP_RES_EXTENDED
|
91
|
+
&& ldap_msgid(res) == LDAP_RES_UNSOLICITED) {
|
92
|
+
rc = ldaptool_print_extended_response(ld, res,
|
93
|
+
"Unsolicited response");
|
94
|
+
} else {
|
95
|
+
rc = parse_result(ld, res, servercredp, msg, 1);
|
96
|
+
received_only_unsolicited = 0; /* we're done */
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
return ( rc);
|
101
|
+
}
|
102
|
+
|
103
|
+
/*
|
104
|
+
* print contents of an extended response to stderr
|
105
|
+
* this is mainly to support unsolicited notifications
|
106
|
+
* Returns an LDAP error code (from the extended result).
|
107
|
+
*/
|
108
|
+
int
|
109
|
+
ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg )
|
110
|
+
{
|
111
|
+
char *oid;
|
112
|
+
struct berval *data;
|
113
|
+
|
114
|
+
if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 )
|
115
|
+
!= LDAP_SUCCESS ) {
|
116
|
+
ldaptool_print_lderror( ld, msg);
|
117
|
+
} else {
|
118
|
+
if ( oid != NULL ) {
|
119
|
+
if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) {
|
120
|
+
print_to_stdout("%s: Notice of Disconnection\n", msg);
|
121
|
+
} else {
|
122
|
+
print_to_stdout("%s: OID %s\n", msg, oid);
|
123
|
+
}
|
124
|
+
ldap_memfree( oid );
|
125
|
+
} else {
|
126
|
+
print_to_stdout("%s: missing OID\n", msg);
|
127
|
+
}
|
128
|
+
|
129
|
+
if ( data != NULL ) {
|
130
|
+
print_to_stdout("%s: Data (length %d):\n", msg, data->bv_len );
|
131
|
+
#if 0
|
132
|
+
/* XXXmcs: maybe we should display the actual data? */
|
133
|
+
lber_bprint( data->bv_val, data->bv_len );
|
134
|
+
#endif
|
135
|
+
ber_bvfree( data );
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
return parse_result( ld, res, NULL, msg, 1 );
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
int
|
144
|
+
parse_result(LDAP *ld, LDAPMessage *res, struct berval **servercredp,
|
145
|
+
char *msg, int freeit) {
|
146
|
+
int rc, lderr, errno;
|
147
|
+
char **refs = NULL;
|
148
|
+
LDAPControl **ctrls;
|
149
|
+
|
150
|
+
if ((rc = ldap_parse_result(ld, res, &lderr, NULL, NULL, &refs,
|
151
|
+
&ctrls, 0)) != LDAP_SUCCESS) {
|
152
|
+
(void) ldaptool_print_lderror(ld, msg);
|
153
|
+
ldap_msgfree(res);
|
154
|
+
return ( rc);
|
155
|
+
}
|
156
|
+
|
157
|
+
if ((rc = check_response_controls(ld, msg, ctrls, 1)) != LDAP_SUCCESS) {
|
158
|
+
ldap_msgfree(res);
|
159
|
+
return ( rc);
|
160
|
+
}
|
161
|
+
|
162
|
+
if (servercredp != NULL && (rc = ldap_parse_sasl_bind_result(ld, res,
|
163
|
+
servercredp, 0)) != LDAP_SUCCESS) {
|
164
|
+
(void) ldaptool_print_lderror(ld, msg);
|
165
|
+
ldap_msgfree(res);
|
166
|
+
return ( rc);
|
167
|
+
}
|
168
|
+
|
169
|
+
if (freeit) {
|
170
|
+
ldap_msgfree(res);
|
171
|
+
}
|
172
|
+
|
173
|
+
if (LDAPTOOL_RESULT_IS_AN_ERROR(lderr)) {
|
174
|
+
(void) ldaptool_print_lderror(ld, msg);
|
175
|
+
}
|
176
|
+
|
177
|
+
if (refs != NULL) {
|
178
|
+
ldaptool_print_referrals(refs);
|
179
|
+
ldap_value_free(refs);
|
180
|
+
}
|
181
|
+
|
182
|
+
return ( lderr);
|
183
|
+
}
|
184
|
+
|
185
|
+
/*
|
186
|
+
* check for response controls. authentication response control
|
187
|
+
* and PW POLICY control are the ones we care about right now.
|
188
|
+
*/
|
189
|
+
int
|
190
|
+
check_response_controls(LDAP *ld, char *msg, LDAPControl **ctrls, int freeit) {
|
191
|
+
int i;
|
192
|
+
int errno;
|
193
|
+
int pw_days = 0, pw_hrs = 0, pw_mins = 0, pw_secs = 0; /* for pwpolicy */
|
194
|
+
char *s = NULL;
|
195
|
+
BerElement *ber = NULL;
|
196
|
+
static const char *pwpolicy_err2str[] = {
|
197
|
+
"Password has expired.",
|
198
|
+
"Account is locked.",
|
199
|
+
"Password has been reset by an administrator; you must change it.",
|
200
|
+
"Password change not allowed.",
|
201
|
+
"Must supply old password.",
|
202
|
+
"Invalid password syntax.",
|
203
|
+
"Password too short.",
|
204
|
+
"Password too young.",
|
205
|
+
"Password in history."
|
206
|
+
};
|
207
|
+
|
208
|
+
if (NULL != ctrls) {
|
209
|
+
for (i = 0; NULL != ctrls[i]; ++i) {
|
210
|
+
|
211
|
+
if (0 == strcmp(ctrls[i]->ldctl_oid,
|
212
|
+
LDAP_CONTROL_AUTH_RESPONSE)) {
|
213
|
+
s = ctrls[i]->ldctl_value.bv_val;
|
214
|
+
if (NULL == s) {
|
215
|
+
s = "Null";
|
216
|
+
} else if (*s == '\0') {
|
217
|
+
s = "Anonymous";
|
218
|
+
}
|
219
|
+
print_to_stdout("%s: bound as %s\n", msg, s);
|
220
|
+
} /* end of LDAP_CONTROL_AUTH_RESPONSE */
|
221
|
+
|
222
|
+
if (0 == strcmp(ctrls[i]->ldctl_oid,
|
223
|
+
LDAP_CONTROL_PWEXPIRING)) {
|
224
|
+
|
225
|
+
/* Warn the user his passwd is to expire */
|
226
|
+
errno = 0;
|
227
|
+
pw_secs = atoi(ctrls[i]->ldctl_value.bv_val);
|
228
|
+
if (pw_secs > 0 && errno != ERANGE) {
|
229
|
+
if (pw_secs > 86400) {
|
230
|
+
pw_days = (pw_secs / 86400);
|
231
|
+
pw_secs = (pw_secs % 86400);
|
232
|
+
}
|
233
|
+
if (pw_secs > 3600) {
|
234
|
+
pw_hrs = (pw_secs / 3600);
|
235
|
+
pw_secs = (pw_secs % 3600);
|
236
|
+
}
|
237
|
+
if (pw_secs > 60) {
|
238
|
+
pw_mins = (pw_secs / 60);
|
239
|
+
pw_secs = (pw_secs % 60);
|
240
|
+
}
|
241
|
+
|
242
|
+
printf("%s: Warning ! Your password will expire after ", msg);
|
243
|
+
if (pw_days) {
|
244
|
+
printf("%d days, ", pw_days);
|
245
|
+
}
|
246
|
+
if (pw_hrs) {
|
247
|
+
printf("%d hrs, ", pw_hrs);
|
248
|
+
}
|
249
|
+
if (pw_mins) {
|
250
|
+
printf("%d mins, ", pw_mins);
|
251
|
+
}
|
252
|
+
printf("%d seconds.\n", pw_secs);
|
253
|
+
}
|
254
|
+
} /* end of LDAP_CONTROL_PWEXPIRING */
|
255
|
+
|
256
|
+
if (0 == strcmp(ctrls[i]->ldctl_oid,
|
257
|
+
LDAP_X_CONTROL_PWPOLICY_RESPONSE)) {
|
258
|
+
ber_tag_t tag1 = 0, tag2 = 0, tag3 = 0;
|
259
|
+
ber_int_t warnvalue = 0;
|
260
|
+
int grclogins = -1, secsleft = -1;
|
261
|
+
ber_int_t errvalue = -1;
|
262
|
+
static int err2str_size = sizeof (pwpolicy_err2str) / sizeof (pwpolicy_err2str[0]);
|
263
|
+
|
264
|
+
if ((ber = ber_init(&(ctrls[i]->ldctl_value))) == NULL) {
|
265
|
+
fprintf(stderr, "%s: not enough memory\n", msg);
|
266
|
+
return ( LDAP_NO_MEMORY);
|
267
|
+
}
|
268
|
+
if (ber_scanf(ber, "{t", &tag1) == LBER_ERROR) {
|
269
|
+
/* error */
|
270
|
+
ber_free(ber, 1);
|
271
|
+
return (ldaptool_print_lderror(ld, msg));
|
272
|
+
}
|
273
|
+
switch (tag1) {
|
274
|
+
case LDAP_TAG_PWP_WARNING:
|
275
|
+
if (ber_scanf(ber, "{ti}", &tag2, &warnvalue)
|
276
|
+
== LBER_ERROR) {
|
277
|
+
/* error */
|
278
|
+
ber_free(ber, 1);
|
279
|
+
return (ldaptool_print_lderror(ld, msg));
|
280
|
+
}
|
281
|
+
switch (tag2) {
|
282
|
+
case LDAP_TAG_PWP_SECSLEFT:
|
283
|
+
secsleft = (int) warnvalue;
|
284
|
+
break;
|
285
|
+
case LDAP_TAG_PWP_GRCLOGINS:
|
286
|
+
grclogins = (int) warnvalue;
|
287
|
+
break;
|
288
|
+
default:
|
289
|
+
/* error */
|
290
|
+
ber_free(ber, 1);
|
291
|
+
return (ldaptool_print_lderror(ld, msg));
|
292
|
+
}
|
293
|
+
/* Now check for the error value if it's present */
|
294
|
+
if (ber_scanf(ber, "te", &tag3, &errvalue) != LBER_ERROR) {
|
295
|
+
if (tag3 != LDAP_TAG_PWP_ERROR) {
|
296
|
+
errvalue = -1;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
break;
|
300
|
+
case LDAP_TAG_PWP_ERROR:
|
301
|
+
if (ber_scanf(ber, "e}", &errvalue)
|
302
|
+
== LBER_ERROR) {
|
303
|
+
/* error */
|
304
|
+
ber_free(ber, 1);
|
305
|
+
return (ldaptool_print_lderror(ld, msg));
|
306
|
+
}
|
307
|
+
break;
|
308
|
+
default: /* error */
|
309
|
+
ber_free(ber, 1);
|
310
|
+
return (ldaptool_print_lderror(ld, msg));
|
311
|
+
}
|
312
|
+
|
313
|
+
/* Now we have all the values */
|
314
|
+
if (secsleft >= 0) {
|
315
|
+
fprintf(stderr, "%s: Password will expire in %d seconds\n",
|
316
|
+
msg, secsleft);
|
317
|
+
}
|
318
|
+
if (grclogins >= 0) {
|
319
|
+
fprintf(stderr, "%s: %d grace login(s) remain\n",
|
320
|
+
msg, grclogins);
|
321
|
+
}
|
322
|
+
if (errvalue >= 0 && errvalue < err2str_size) {
|
323
|
+
fprintf(stderr, "%s: %s\n",
|
324
|
+
msg, pwpolicy_err2str[errvalue]);
|
325
|
+
} else if (errvalue != -1) {
|
326
|
+
fprintf(stderr, "%s: %s\n",
|
327
|
+
msg,
|
328
|
+
"Invalid error value in password policy response control");
|
329
|
+
}
|
330
|
+
} /* end of LDAP_X_CONTROL_PWPOLICY_RESPONSE */
|
331
|
+
|
332
|
+
}
|
333
|
+
|
334
|
+
if (freeit) {
|
335
|
+
ldap_controls_free(ctrls);
|
336
|
+
ber_free(ber, 1);
|
337
|
+
}
|
338
|
+
}
|
339
|
+
return LDAP_SUCCESS;
|
340
|
+
}
|
341
|
+
|
342
|
+
|
343
|
+
/*
|
344
|
+
* Like ldap_sasl_bind_s() but calls wait4result() to display
|
345
|
+
* any referrals returned and report errors in a consistent way.
|
346
|
+
*/
|
347
|
+
int
|
348
|
+
ldaptool_sasl_bind_s(LDAP *ld, const char *dn, const char *mechanism,
|
349
|
+
const struct berval *cred, LDAPControl **serverctrls,
|
350
|
+
LDAPControl **clientctrls, struct berval **servercredp, char *msg) {
|
351
|
+
int rc, msgid;
|
352
|
+
|
353
|
+
if (servercredp != NULL) {
|
354
|
+
*servercredp = NULL;
|
355
|
+
}
|
356
|
+
|
357
|
+
if ((rc = ldap_sasl_bind(ld, dn, mechanism, cred, serverctrls,
|
358
|
+
clientctrls, &msgid)) == LDAP_SUCCESS) {
|
359
|
+
rc = wait4result(ld, msgid, servercredp, msg);
|
360
|
+
}
|
361
|
+
|
362
|
+
return ( rc);
|
363
|
+
}
|
364
|
+
|
365
|
+
// Rebind in case we were unbound
|
366
|
+
VALUE
|
367
|
+
rb_ldap_sslauthconn_rebind(VALUE self)
|
368
|
+
{
|
369
|
+
VALUE ary = rb_iv_get (self, "@args");
|
370
|
+
|
371
|
+
return rb_ldap_sslauthconn_initialize(RARRAY_LEN(ary), RARRAY_PTR(ary), self);
|
372
|
+
}
|
373
|
+
|
374
|
+
////////////////////////////////////////////////////////////////////////////////
|
375
|
+
//
|
376
|
+
// .bind
|
377
|
+
//
|
378
|
+
////////////////////////////////////////////////////////////////////////////////
|
379
|
+
|
380
|
+
/*
|
381
|
+
* call-seq:
|
382
|
+
* conn.bind(serverctrls = nil) {|conn| # optional block }
|
383
|
+
* => self
|
384
|
+
*
|
385
|
+
* Bind a LDAP connection with SASL EXTERNAL method,
|
386
|
+
* with optional +serverctls+.
|
387
|
+
* If a block is given, +self+ is yielded to the block.
|
388
|
+
*/
|
389
|
+
VALUE
|
390
|
+
rb_ldap_sslauthconn_s_bind(int argc, VALUE argv[], VALUE self) {
|
391
|
+
RB_LDAP_DATA *ldapdata;
|
392
|
+
|
393
|
+
VALUE arg1;
|
394
|
+
|
395
|
+
LDAPControl **bindctrls = NULL;
|
396
|
+
|
397
|
+
Data_Get_Struct(self, RB_LDAP_DATA, ldapdata);
|
398
|
+
|
399
|
+
if (ldapdata->bind == 0) {
|
400
|
+
if (rb_iv_get(self, "@args") != Qnil) {
|
401
|
+
rb_ldap_sslauthconn_rebind(self);
|
402
|
+
GET_LDAP_DATA(self, ldapdata);
|
403
|
+
} else {
|
404
|
+
rb_raise(rb_eLDAP_InvalidDataError,
|
405
|
+
"The LDAP handler has already unbound.");
|
406
|
+
}
|
407
|
+
} else {
|
408
|
+
rb_raise(rb_eLDAP_Error, "already bound.");
|
409
|
+
};
|
410
|
+
|
411
|
+
switch (rb_scan_args(argc, argv, "01", &arg1)) {
|
412
|
+
case 1:
|
413
|
+
bindctrls = rb_ldap_get_controls(arg1);
|
414
|
+
case 0:
|
415
|
+
break;
|
416
|
+
default:
|
417
|
+
rb_bug("rb_ldap_sslauthconn_bind_s");
|
418
|
+
}
|
419
|
+
|
420
|
+
ldapdata->err = ldaptool_sasl_bind_s(ldapdata->ldap, NULL, LDAP_SASL_EXTERNAL, NULL,
|
421
|
+
bindctrls, NULL, NULL, "clientauth_ldap_sasl_bind");
|
422
|
+
|
423
|
+
Check_LDAP_Result(ldapdata->err);
|
424
|
+
ldapdata->bind = 1;
|
425
|
+
|
426
|
+
if (rb_block_given_p()) {
|
427
|
+
rb_ensure(rb_yield, self, rb_ldap_conn_unbind, self);
|
428
|
+
return Qnil;
|
429
|
+
} else {
|
430
|
+
return self;
|
431
|
+
};
|
432
|
+
};
|
433
|
+
|
434
|
+
////////////////////////////////////////////////////////////////////////////////
|
435
|
+
//
|
436
|
+
// .new
|
437
|
+
//
|
438
|
+
////////////////////////////////////////////////////////////////////////////////
|
439
|
+
VALUE
|
440
|
+
rb_ldap_sslauthconn_initialize(int argc, VALUE argv[], VALUE self)
|
441
|
+
{
|
442
|
+
RB_LDAP_DATA *ldapdata;
|
443
|
+
LDAP *cldap;
|
444
|
+
char *chost = NULL;
|
445
|
+
char *certpath = NULL;
|
446
|
+
char *certname = NULL;
|
447
|
+
char *keypass = NULL;
|
448
|
+
int cport = LDAP_PORT;
|
449
|
+
int ctls = 0;
|
450
|
+
|
451
|
+
VALUE host, port, tls, cp, cn, key_pw, sctrls, cctrls;
|
452
|
+
|
453
|
+
Data_Get_Struct(self, RB_LDAP_DATA, ldapdata);
|
454
|
+
if (ldapdata->ldap)
|
455
|
+
return Qnil;
|
456
|
+
|
457
|
+
int anum = rb_scan_args(argc, argv, "62", &host, &port, &tls, &cp, &cn, &key_pw, &sctrls, &cctrls);
|
458
|
+
|
459
|
+
if (anum < 6) {
|
460
|
+
rb_bug("rb_ldap_auth_conn_new");
|
461
|
+
} else if (anum >= 6) {
|
462
|
+
chost = StringValueCStr(host);
|
463
|
+
cport = NUM2INT(port);
|
464
|
+
ctls = (tls == Qtrue) ? 1 : 0;
|
465
|
+
certpath = (cp == Qnil) ? NULL : StringValueCStr(cp);
|
466
|
+
certname = (cn == Qnil) ? NULL : StringValueCStr(cn);
|
467
|
+
keypass = (key_pw == Qnil) ? NULL : StringValueCStr(key_pw);
|
468
|
+
}
|
469
|
+
|
470
|
+
// Here we go
|
471
|
+
Check_LDAP_Error_MSG(ldapssl_clientauth_init(certpath, NULL, (keypass == NULL) ? 0 : 1, NULL, NULL),
|
472
|
+
"SSLAuthConn: Failed to initialize NSS certificate storeage. -- ldapssl_clientauth_init");
|
473
|
+
|
474
|
+
// Make sure we can SIGINT
|
475
|
+
struct sigaction act = {
|
476
|
+
.sa_sigaction = handle_sigint,
|
477
|
+
.sa_flags = SA_RESTART | SA_SIGINFO
|
478
|
+
};
|
479
|
+
|
480
|
+
if (sigaction(SIGINT, &act, NULL) < 0) {
|
481
|
+
print_to_stdout("error setting sigint");
|
482
|
+
};
|
483
|
+
|
484
|
+
cldap = tls ? (LDAP*)prldap_init(chost, cport, 0) : ldapssl_init(chost, cport, 1);
|
485
|
+
|
486
|
+
Check_LDAP_Error_MSG((long) cldap,
|
487
|
+
"SSLAuthConn: Init failure");
|
488
|
+
|
489
|
+
Check_LDAP_Error_MSG(ldapssl_enable_clientauth(cldap, "", keypass, certname),
|
490
|
+
"SSLAuthConn: Couldn't enable client auth");
|
491
|
+
|
492
|
+
if (tls) {
|
493
|
+
Check_LDAP_Error_MSG(ldap_start_tls_s(cldap, NULL, NULL),
|
494
|
+
"SSLAuthConn: TLS failure");
|
495
|
+
}
|
496
|
+
|
497
|
+
// protect key
|
498
|
+
char* ptr_orig = StringValuePtr(key_pw);
|
499
|
+
char* iptr = ptr_orig;
|
500
|
+
while ((iptr - ptr_orig <= 16) && ((char)*iptr != '\0')) {
|
501
|
+
*iptr++ = 'X';
|
502
|
+
}
|
503
|
+
|
504
|
+
// set ruby stuff
|
505
|
+
ldapdata->ldap = cldap;
|
506
|
+
rb_iv_set(self, "@args", rb_ary_new4(argc, argv));
|
507
|
+
|
508
|
+
return Qnil;
|
509
|
+
}
|
510
|
+
|
511
|
+
////////////////////////////////////////////////////////////////////////////////
|
512
|
+
//
|
513
|
+
// Fancy printing stuff goes here
|
514
|
+
//
|
515
|
+
////////////////////////////////////////////////////////////////////////////////
|
516
|
+
|
517
|
+
/*
|
518
|
+
* Print referrals to stdout
|
519
|
+
*/
|
520
|
+
void
|
521
|
+
ldaptool_print_referrals(char **refs)
|
522
|
+
{
|
523
|
+
int i;
|
524
|
+
|
525
|
+
if (refs != NULL) {
|
526
|
+
for (i = 0; refs[ i ] != NULL; ++i) {
|
527
|
+
print_to_stdout("Referral: %s\n", refs[i]);
|
528
|
+
}
|
529
|
+
}
|
530
|
+
}
|
531
|
+
|
532
|
+
/*
|
533
|
+
* Retrieve and print an LDAP error message. Returns the LDAP error code.
|
534
|
+
*/
|
535
|
+
int
|
536
|
+
ldaptool_print_lderror( LDAP *ld, char *msg)
|
537
|
+
{
|
538
|
+
int lderr = ldap_get_lderrno( ld, NULL, NULL );
|
539
|
+
|
540
|
+
ldap_perror(ld, msg);
|
541
|
+
|
542
|
+
int sslerr = PORT_GetError();
|
543
|
+
|
544
|
+
rb_warn("%s SSL sublayer reported error: ", msg, ldapssl_err2string(sslerr));
|
545
|
+
|
546
|
+
return(lderr);
|
547
|
+
}
|
548
|
+
|
549
|
+
void
|
550
|
+
print_to_stdout(char* format, ...) {
|
551
|
+
static char buf[512] = "";
|
552
|
+
va_list ap;
|
553
|
+
|
554
|
+
va_start(ap, format);
|
555
|
+
vsnprintf(buf, sizeof(buf) - 1, format, ap);
|
556
|
+
rb_io_write(rb_stdout, rb_str_new2(buf));
|
557
|
+
va_end(ap);
|
558
|
+
}
|
559
|
+
|
560
|
+
void handle_sigint(int sig, siginfo_t *siginfo, void *context) {
|
561
|
+
print_to_stdout("Requested to terminate [%d].\n", sig);
|
562
|
+
exit(0);
|
563
|
+
}
|
564
|
+
|
565
|
+
VALUE
|
566
|
+
rb_ldap_sslauthconn_s_open(int argc, VALUE argv[], VALUE klass)
|
567
|
+
{
|
568
|
+
rb_notimplement();
|
569
|
+
}
|
570
|
+
|
571
|
+
/*
|
572
|
+
* call-seq:
|
573
|
+
* LDAP::SSLAuthConn.new(host='localhost', port=LDAP_PORT,
|
574
|
+
* start_tls=false, cert_path, cert_nickname,
|
575
|
+
* key_password, sctrls=nil, cctrls=nil)
|
576
|
+
*
|
577
|
+
* => LDAP::SSLAuthConn
|
578
|
+
*
|
579
|
+
* Return a new LDAP::SSLConn connection to the server, +host+, on port +port+.
|
580
|
+
* If +start_tls+ is *true*, START_TLS will be used to establish the
|
581
|
+
* connection, automatically setting the LDAP protocol version to v3 if it is
|
582
|
+
* not already set.
|
583
|
+
*
|
584
|
+
* +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
|
585
|
+
* client controls.
|
586
|
+
*
|
587
|
+
* Method accepts at least 6 parameters and an optional block.
|
588
|
+
*
|
589
|
+
*/
|
590
|
+
void
|
591
|
+
Init_ldap_clientauth()
|
592
|
+
{
|
593
|
+
rb_cLDAP_SSLAuthConn =
|
594
|
+
rb_define_class_under(rb_mLDAP, "SSLAuthConn", rb_cLDAP_SSLConn);
|
595
|
+
rb_define_singleton_method(rb_cLDAP_SSLAuthConn, "open",
|
596
|
+
rb_ldap_sslauthconn_s_open, -1);
|
597
|
+
rb_define_method(rb_cLDAP_SSLAuthConn, "initialize",
|
598
|
+
rb_ldap_sslauthconn_initialize, -1);
|
599
|
+
|
600
|
+
rb_define_method(rb_cLDAP_SSLAuthConn, "bind",
|
601
|
+
rb_ldap_sslauthconn_s_bind, -1);
|
602
|
+
|
603
|
+
}
|
604
|
+
|
605
|
+
#endif
|