2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2007 Match Grun and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * Some utility functions to access LDAP servers.
37 #define SYLDAP_TEST_FILTER "(objectclass=*)"
38 #define SYLDAP_SEARCHBASE_V2 "cn=config"
39 #define SYLDAP_SEARCHBASE_V3 ""
40 #define SYLDAP_V2_TEST_ATTR "database"
41 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
44 * Attempt to discover the base DN for a server using LDAP version 3.
45 * \param ld LDAP handle for a connected server.
46 * \param tov Timeout value (seconds), or 0 for none, default 30 secs.
47 * \return List of Base DN's, or NULL if could not read. List should be
50 static GList
*ldaputil_test_v3( LDAP
*ld
, gint tov
, gint
*errcode
) {
53 LDAPMessage
*result
= NULL
, *e
;
58 struct timeval timeout
;
69 /* Test for LDAP version 3 */
70 attribs
[0] = SYLDAP_V3_TEST_ATTR
;
72 rc
= ldap_search_ext_s(
73 ld
, SYLDAP_SEARCHBASE_V3
, LDAP_SCOPE_BASE
, SYLDAP_TEST_FILTER
,
74 attribs
, 0, NULL
, NULL
, &timeout
, 0, &result
);
76 if( rc
== LDAP_SUCCESS
) {
78 for( e
= ldap_first_entry( ld
, result
);
80 e
= ldap_next_entry( ld
, e
) )
82 /* Process attributes */
83 for( attribute
= ldap_first_attribute( ld
, e
, &ber
);
85 attribute
= ldap_next_attribute( ld
, e
, ber
) )
88 attribute
, SYLDAP_V3_TEST_ATTR
) == 0 )
90 vals
= ldap_get_values_len( ld
, e
, attribute
);
92 for( i
= 0; vals
[i
] != NULL
; i
++ ) {
93 baseDN
= g_list_append(
94 baseDN
, g_strndup( vals
[i
]->bv_val
, vals
[i
]->bv_len
) );
97 ldap_value_free_len( vals
);
99 ldap_memfree( attribute
);
110 ldap_msgfree( result
);
115 * Attempt to discover the base DN for a server using LDAP version 2.
116 * \param ld LDAP handle for a connected server.
117 * \param tov Timeout value (seconds), or 0 for none, default 30 secs.
118 * \return List of Base DN's, or NULL if could not read. List should be
119 * g_free() when done.
121 static GList
*ldaputil_test_v2( LDAP
*ld
, gint tov
) {
122 GList
*baseDN
= NULL
;
124 LDAPMessage
*result
= NULL
, *e
;
128 struct berval
**vals
;
129 struct timeval timeout
;
132 timeout
.tv_usec
= 0L;
134 timeout
.tv_sec
= tov
;
137 timeout
.tv_sec
= 30L;
141 rc
= ldap_search_ext_s(
142 ld
, SYLDAP_SEARCHBASE_V2
, LDAP_SCOPE_BASE
, SYLDAP_TEST_FILTER
,
143 attribs
, 0, NULL
, NULL
, &timeout
, 0, &result
);
145 if( rc
== LDAP_SUCCESS
) {
146 /* Process entries */
147 for( e
= ldap_first_entry( ld
, result
);
149 e
= ldap_next_entry( ld
, e
) )
151 /* Process attributes */
152 for( attribute
= ldap_first_attribute( ld
, e
, &ber
);
154 attribute
= ldap_next_attribute( ld
, e
, ber
) )
158 SYLDAP_V2_TEST_ATTR
) == 0 ) {
159 vals
= ldap_get_values_len( ld
, e
, attribute
);
161 for( i
= 0; vals
[i
] != NULL
; i
++ ) {
164 * Strip the 'ldb:' from the
165 * front of the value.
167 tmp
= g_strndup( vals
[i
]->bv_val
, vals
[i
]->bv_len
);
168 ch
= ( char * ) strchr( tmp
, ':' );
170 gchar
*bn
= g_strdup( ++ch
);
173 baseDN
= g_list_append(
174 baseDN
, g_strdup( bn
) );
180 ldap_value_free_len( vals
);
182 ldap_memfree( attribute
);
191 ldap_msgfree( result
);
195 int claws_ldap_simple_bind_s( LDAP
*ld
, LDAP_CONST
char *dn
, LDAP_CONST
char *passwd
)
199 if ( passwd
!= NULL
) {
200 cred
.bv_val
= (char *) passwd
;
201 cred
.bv_len
= strlen( passwd
);
207 return ldap_sasl_bind_s( ld
, dn
, LDAP_SASL_SIMPLE
, &cred
,
212 * Attempt to discover the base DN for the server.
213 * \param host Host name.
214 * \param port Port number.
215 * \param bindDN Bind DN (optional).
216 * \param bindPW Bind PW (optional).
217 * \param tov Timeout value (seconds), or 0 for none, default 30 secs.
218 * \return List of Base DN's, or NULL if could not read. This list should be
219 * g_free() when done.
221 GList
*ldaputil_read_basedn(
222 const gchar
*host
, const gint port
, const gchar
*bindDN
,
223 const gchar
*bindPW
, const gint tov
, int ssl
, int tls
)
225 GList
*baseDN
= NULL
;
233 if( host
== NULL
) return baseDN
;
234 if( port
< 1 ) return baseDN
;
236 /* Connect to server. */
238 uri
= g_strdup_printf("ldap%s://%s:%d",
241 rc
= ldap_initialize(&ld
, uri
);
250 version
= LDAP_VERSION3
;
251 rc
= ldap_set_option( ld
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
252 if( rc
!= LDAP_OPT_SUCCESS
) {
253 ldap_unbind_ext( ld
, NULL
, NULL
);
256 rc
= ldap_start_tls_s( ld
, NULL
, NULL
);
258 ldap_unbind_ext( ld
, NULL
, NULL
);
264 /* Bind to the server, if required */
266 if( *bindDN
!= '\0' ) {
267 rc
= claws_ldap_simple_bind_s( ld
, bindDN
, bindPW
);
268 if( rc
!= LDAP_SUCCESS
) {
269 ldap_unbind_ext( ld
, NULL
, NULL
);
275 /* Test for LDAP version 3 */
276 baseDN
= ldaputil_test_v3( ld
, tov
, &rc
);
278 if( baseDN
== NULL
&& !LDAP_API_ERROR(rc
) ) {
279 baseDN
= ldaputil_test_v2( ld
, tov
);
281 if (ld
&& !LDAP_API_ERROR(rc
))
282 ldap_unbind_ext( ld
, NULL
, NULL
);
288 * Attempt to connect to the server.
290 * \param host Host name.
291 * \param port Port number.
292 * \return <i>TRUE</i> if connected successfully.
294 gboolean
ldaputil_test_connect( const gchar
*host
, const gint port
, int ssl
, int tls
) {
295 gboolean retVal
= FALSE
;
303 if( host
== NULL
) return retVal
;
304 if( port
< 1 ) return retVal
;
306 uri
= g_strdup_printf("ldap%s://%s:%d",
309 ldap_initialize(&ld
, uri
);
316 GList
*dummy
= ldaputil_test_v3( ld
, 10, &rc
);
319 if (LDAP_API_ERROR(rc
))
325 version
= LDAP_VERSION3
;
326 rc
= ldap_set_option( ld
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
327 if( rc
!= LDAP_OPT_SUCCESS
) {
328 ldap_unbind_ext( ld
, NULL
, NULL
);
332 rc
= ldap_start_tls_s( ld
, NULL
, NULL
);
334 ldap_unbind_ext( ld
, NULL
, NULL
);
340 ldap_unbind_ext( ld
, NULL
, NULL
);
347 * Test whether LDAP libraries installed.
348 * Return: TRUE if library available.
350 gboolean
ldaputil_test_ldap_lib( void ) {
354 #endif /* USE_LDAP */