2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2012 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 3 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, see <http://www.gnu.org/licenses/>.
21 * Functions necessary to access LDAP servers.
26 #include "claws-features.h"
37 #include "addrcache.h"
39 #include "ldapquery.h"
40 #include "ldapserver.h"
43 #include "adbookbase.h"
46 * Create new LDAP server interface object with no control object.
47 * \return Initialized LDAP server object.
49 LdapServer
*ldapsvr_create_noctl( void ) {
52 server
= g_new0( LdapServer
, 1 );
53 server
->type
= ADBOOKTYPE_LDAP
;
54 server
->addressCache
= addrcache_create();
55 server
->retVal
= MGU_SUCCESS
;
56 server
->control
= NULL
;
57 server
->listQuery
= NULL
;
58 server
->searchFlag
= FALSE
;
63 * Create new LDAP server interface object.
64 * \return Initialized LDAP server object.
66 LdapServer
*ldapsvr_create( void ) {
68 server
= ldapsvr_create_noctl();
69 server
->control
= ldapctl_create();
74 * Return name of server.
75 * \param server Server object.
76 * \return Name for server.
78 gchar
*ldapsvr_get_name( LdapServer
*server
) {
79 cm_return_val_if_fail( server
!= NULL
, NULL
);
80 return addrcache_get_name( server
->addressCache
);
84 * Specify name to be used.
85 * \param server Server object.
86 * \param value Name for server.
88 void ldapsvr_set_name( LdapServer
* server
, const gchar
*value
) {
89 cm_return_if_fail( server
!= NULL
);
90 addrcache_set_name( server
->addressCache
, value
);
91 debug_print("setting name: %s\n", value
?value
:"null");
95 * Refresh internal variables to force a file read.
96 * \param server Server object.
98 void ldapsvr_force_refresh( LdapServer
*server
) {
99 cm_return_if_fail( server
!= NULL
);
100 addrcache_refresh( server
->addressCache
);
104 * Return status/error code.
105 * \param server Server object.
106 * \return Status/error code.
108 gint
ldapsvr_get_status( LdapServer
*server
) {
109 cm_return_val_if_fail( server
!= NULL
, -1 );
110 return server
->retVal
;
114 * Return reference to root level folder.
115 * \param server Server object.
116 * \return Root level folder.
118 ItemFolder
*ldapsvr_get_root_folder( LdapServer
*server
) {
119 cm_return_val_if_fail( server
!= NULL
, NULL
);
121 g_print( "ldapsvr_get_root_folder/start\n" );
122 ldapsvr_print_data( server, stdout );
123 g_print( "ldapsvr_get_root_folder/done\n" );
125 return addrcache_get_root_folder( server
->addressCache
);
129 * Test whether server data has been accessed.
130 * \param server Server object.
131 * \return <i>TRUE</i> if data was accessed.
133 gboolean
ldapsvr_get_accessed( LdapServer
*server
) {
134 cm_return_val_if_fail( server
!= NULL
, FALSE
);
135 return server
->addressCache
->accessFlag
;
139 * Specify that server's data whas beed accessed.
140 * \param server Server object.
141 * \param value Value for flag.
143 void ldapsvr_set_accessed( LdapServer
*server
, const gboolean value
) {
144 cm_return_if_fail( server
!= NULL
);
145 server
->addressCache
->accessFlag
= value
;
146 debug_print("setting accessFlag: %d\n", value
);
150 * Test whether server data has been modified.
151 * \param server Server object.
152 * \return <i>TRUE</i> if data was modified.
154 gboolean
ldapsvr_get_modified( LdapServer
*server
) {
155 cm_return_val_if_fail( server
!= NULL
, FALSE
);
156 return server
->addressCache
->modified
;
160 * Specify modify flag.
161 * \param server Server object.
162 * \param value Value for flag.
164 void ldapsvr_set_modified( LdapServer
*server
, const gboolean value
) {
165 cm_return_if_fail( server
!= NULL
);
166 server
->addressCache
->modified
= value
;
167 debug_print("setting modified: %d\n", value
);
171 * Test whether data was read from server.
172 * \param server Server object.
173 * \return <i>TRUE</i> if data was read.
175 gboolean
ldapsvr_get_read_flag( LdapServer
*server
) {
176 cm_return_val_if_fail( server
!= NULL
, FALSE
);
177 return server
->addressCache
->dataRead
;
181 * Test whether server is to be used for dynamic searches.
182 * \param server Server object.
183 * \return <i>TRUE</i> if server is used for dynamic searches.
185 gboolean
ldapsvr_get_search_flag( LdapServer
*server
) {
186 cm_return_val_if_fail( server
!= NULL
, FALSE
);
187 return server
->searchFlag
;
191 * Specify that server is to be used for dynamic searches.
192 * \param server Server object.
193 * \param value Name for server.
195 void ldapsvr_set_search_flag( LdapServer
*server
, const gboolean value
) {
196 cm_return_if_fail( server
!= NULL
);
197 server
->searchFlag
= value
;
198 debug_print("setting searchFlag: %d\n", value
);
202 * Specify the reference to control data that will be used for the query. The calling
203 * module should be responsible for creating and destroying this control object.
204 * \param server Server object.
205 * \param ctl Control data.
207 void ldapsvr_set_control( LdapServer
*server
, LdapControl
*ctl
) {
208 cm_return_if_fail( server
!= NULL
);
209 addrcache_refresh( server
->addressCache
);
210 server
->control
= ctl
;
215 * \param server Server object.
217 void ldapsvr_free_all_query( LdapServer
*server
) {
219 cm_return_if_fail( server
!= NULL
);
221 node
= server
->listQuery
;
223 LdapQuery
*qry
= node
->data
;
226 node
= g_list_next( node
);
228 g_list_free( server
->listQuery
);
229 server
->listQuery
= NULL
;
233 * Add query to server.
234 * \param server Server object.
235 * \param qry Query object.
237 void ldapsvr_add_query( LdapServer
*server
, LdapQuery
*qry
) {
238 cm_return_if_fail( server
!= NULL
);
239 cm_return_if_fail( qry
!= NULL
);
241 server
->listQuery
= g_list_append( server
->listQuery
, qry
);
242 qry
->server
= server
;
246 * Free up LDAP server interface object by releasing internal memory.
247 * \param server Server object.
249 void ldapsvr_free( LdapServer
*server
) {
250 cm_return_if_fail( server
!= NULL
);
252 /* Stop and cancel any queries that may be active */
253 ldapsvr_stop_all_query( server
);
254 ldapsvr_cancel_all_query( server
);
257 addrcache_clear( server
->addressCache
);
258 addrcache_free( server
->addressCache
);
260 /* Free LDAP control block */
261 ldapctl_free( server
->control
);
262 server
->control
= NULL
;
264 /* Free all queries */
265 ldapsvr_free_all_query( server
);
268 server
->type
= ADBOOKTYPE_NONE
;
269 server
->addressCache
= NULL
;
270 server
->retVal
= MGU_SUCCESS
;
271 server
->listQuery
= NULL
;
272 server
->searchFlag
= FALSE
;
274 /* Now release LDAP object */
279 * Display object to specified stream.
280 * \param server Server object.
281 * \param stream Output stream.
283 void ldapsvr_print_data( LdapServer
*server
, FILE *stream
) {
287 cm_return_if_fail( server
!= NULL
);
289 fprintf( stream
, "LdapServer:\n" );
290 fprintf( stream
, " ret val: %d\n", server
->retVal
);
291 fprintf( stream
, "srch flag: %s\n",
292 server
->searchFlag
? "yes" : "no" );
293 if( server
->control
) {
294 ldapctl_print( server
->control
, stream
);
297 fprintf( stream
, " control: NULL\n" );
299 addrcache_print( server
->addressCache
, stream
);
300 addritem_print_item_folder( server
->addressCache
->rootFolder
, stream
);
304 node
= server
->listQuery
;
306 LdapQuery
*qry
= node
->data
;
307 fprintf( stream
, " query: %2d : %s\n", i
, ADDRQUERY_NAME(qry
) );
309 node
= g_list_next( node
);
314 * Return link list of persons.
315 * \param server Server object.
316 * \return List of persons.
318 GList
*ldapsvr_get_list_person( LdapServer
*server
) {
319 cm_return_val_if_fail( server
!= NULL
, NULL
);
320 return addrcache_get_list_person( server
->addressCache
);
324 * Return link list of folders. There are no "real" folders that are returned
326 * \param server Server object.
327 * \return List of folders.
329 GList
*ldapsvr_get_list_folder( LdapServer
*server
) {
330 cm_return_val_if_fail( server
!= NULL
, NULL
);
331 /* return addrcache_get_list_folder( server->addressCache ); */
336 * Execute specified query.
337 * \param server LDAP server.
338 * \param qry LDAP query.
340 void ldapsvr_execute_query( LdapServer
*server
, LdapQuery
*qry
) {
341 LdapControl
*ctlCopy
;
343 cm_return_if_fail( server
!= NULL
);
344 cm_return_if_fail( qry
!= NULL
);
346 /* Copy server's control data to the query */
347 ctlCopy
= ldapctl_create();
348 ldapctl_copy( server
->control
, ctlCopy
);
349 ldapqry_set_control( qry
, ctlCopy
);
350 ldapqry_initialize();
353 debug_print("ldapsvr_execute_query::checking query...\n");
354 if( ldapqry_check_search( qry
) ) {
355 debug_print("ldapsvr_execute_query::reading with thread...\n");
356 ldapqry_read_data_th( qry
);
357 if(qry
->server
->retVal
== LDAPRC_SUCCESS
) {
358 debug_print("ldapsvr_execute_query::SUCCESS with thread...\n");
361 debug_print("ldapsvr_execute_query... terminated\n");
365 * Stop all queries for specified ID.
366 * \param server Server object.
367 * \param queryID Query ID to stop.
369 void ldapsvr_stop_query_id( LdapServer
*server
, const gint queryID
) {
371 cm_return_if_fail( server
!= NULL
);
373 node
= server
->listQuery
;
375 LdapQuery
*qry
= node
->data
;
376 if( ADDRQUERY_ID(qry
) == queryID
) {
377 /* Notify thread to stop */
378 ldapqry_set_stop_flag( qry
, TRUE
);
380 node
= g_list_next( node
);
385 * Stop all queries by notifying each thread to stop.
386 * \param server Server object.
388 void ldapsvr_stop_all_query( LdapServer
*server
) {
390 cm_return_if_fail( server
!= NULL
);
392 node
= server
->listQuery
;
394 LdapQuery
*qry
= node
->data
;
395 ldapqry_set_stop_flag( qry
, TRUE
);
396 node
= g_list_next( node
);
401 * Cancel all query threads for server.
402 * \param server Server object.
404 void ldapsvr_cancel_all_query( LdapServer
*server
) {
406 cm_return_if_fail( server
!= NULL
);
408 node
= server
->listQuery
;
410 LdapQuery
*qry
= node
->data
;
411 /* Notify thread to stop */
412 ldapqry_set_stop_flag( qry
, TRUE
);
413 /* Now cancel thread */
414 ldapqry_cancel( qry
);
415 node
= g_list_next( node
);
420 * Search most recent query for specified search term. The most recent
421 * completed query is returned. If no completed query is found, the most recent
422 * incomplete is returned.
423 * \param server LdapServer.
424 * \param searchTerm Search term to locate.
425 * \return Query object, or <i>NULL</i> if none found.
427 static LdapQuery
*ldapsvr_locate_query(
428 const LdapServer
*server
, const gchar
*searchTerm
)
430 LdapQuery
*incomplete
= NULL
;
432 cm_return_val_if_fail( server
!= NULL
, NULL
);
434 node
= server
->listQuery
;
435 node
= g_list_last( node
);
436 /* Search backwards for query */
438 LdapQuery
*qry
= node
->data
;
439 if( g_utf8_collate( ADDRQUERY_SEARCHVALUE(qry
), searchTerm
) == 0 ) {
440 if( qry
->agedFlag
) continue;
441 if( qry
->completed
) {
449 node
= g_list_previous( node
);
455 * Retire aged queries. Only the following queries are retired:
457 * a) Dynamic queries.
458 * b) Explicit searches that have a hidden folders.
459 * c) Locate searches that have a hidden folder.
461 * \param server LdapServer.
463 void ldapsvr_retire_query( LdapServer
*server
) {
471 debug_print("ldapsvr_retire_query\n");
472 cm_return_if_fail( server
!= NULL
);
473 ctl
= server
->control
;
474 maxAge
= ctl
->maxQueryAge
;
476 /* Identify queries to age and move to deletion list */
478 node
= server
->listQuery
;
480 LdapQuery
*qry
= node
->data
;
482 node
= g_list_next( node
);
483 folder
= ADDRQUERY_FOLDER(qry
);
484 if( folder
== NULL
) continue;
485 if( ! folder
->isHidden
) {
486 if( ADDRQUERY_SEARCHTYPE(qry
) == ADDRSEARCH_EXPLICIT
) continue;
487 if( ADDRQUERY_SEARCHTYPE(qry
) == ADDRSEARCH_LOCATE
) continue;
490 ldapqry_age( qry
, maxAge
);
491 if( qry
->agedFlag
) {
492 /* Delete folder associated with query */
493 debug_print("deleting folder... ::%s::\n",
494 ADDRQUERY_NAME(qry
)?ADDRQUERY_NAME(qry
):"null");
495 ldapqry_delete_folder( qry
);
496 listDelete
= g_list_append( listDelete
, qry
);
501 listQuery
= server
->listQuery
;
504 LdapQuery
*qry
= node
->data
;
506 listQuery
= g_list_remove( listQuery
, qry
);
509 node
= g_list_next( node
);
511 server
->listQuery
= listQuery
;
513 /* Free up deletion list */
514 g_list_free( listDelete
);
518 * Return results of a previous query by executing callback for each address
519 * contained in specified folder.
521 * \param folder Address book folder to process.
522 * \param req Address query request object.
524 static void ldapsvr_previous_query(
525 const ItemFolder
*folder
, const QueryRequest
*req
, AddrQueryObject
*aqo
)
527 AddrSearchCallbackEntry
*callBack
;
534 callBack
= ( AddrSearchCallbackEntry
* ) req
->callBackEntry
;
537 node
= folder
->listPerson
;
539 AddrItemObject
*aio
= node
->data
;
540 if( aio
&& aio
->type
== ITEMTYPE_PERSON
) {
541 ItemPerson
*person
= node
->data
;
542 nodeEM
= person
->listEMail
;
544 ItemEMail
*email
= nodeEM
->data
;
546 nodeEM
= g_list_next( nodeEM
);
547 listEMail
= g_list_append( listEMail
, email
);
550 node
= g_list_next( node
);
552 ( callBack
) ( sender
, req
->queryID
, listEMail
, NULL
);
553 /* // g_list_free( listEMail ); */
558 * Reuse search results from a previous LDAP query. If there is a query that
559 * has the same search term as specified in the query request, then the query
562 * \param server LDAP server object.
563 * \param req Address query object.
564 * \return <i>TRUE</i> if previous query was used.
566 gboolean
ldapsvr_reuse_previous( const LdapServer
*server
, const QueryRequest
*req
) {
571 cm_return_val_if_fail( server
!= NULL
, FALSE
);
572 cm_return_val_if_fail( req
!= NULL
, FALSE
);
574 searchTerm
= req
->searchTerm
;
576 /* Test whether any queries for the same term exist */
577 qry
= ldapsvr_locate_query( server
, searchTerm
);
579 /* Touch query to ensure it hangs around for a bit longer */
580 ldapqry_touch( qry
);
581 folder
= ADDRQUERY_FOLDER(qry
);
583 ldapsvr_previous_query( folder
, req
, ADDRQUERY_OBJECT(qry
) );
591 * Construct a new LdapQuery object that will be used to perform an dynamic
594 * \param server LdapServer.
595 * \param req Query request.
596 * \return LdapQuery object, or <i>NULL</i> if none created.
598 LdapQuery
*ldapsvr_new_dynamic_search( LdapServer
*server
, QueryRequest
*req
)
605 cm_return_val_if_fail( server
!= NULL
, NULL
);
606 cm_return_val_if_fail( req
!= NULL
, NULL
);
608 /* Retire any aged queries */
609 /* // ldapsvr_retire_query( server ); */
611 /* Name of folder and query */
612 searchTerm
= req
->searchTerm
;
613 name
= g_strdup_printf( "Search '%s'", searchTerm
);
615 /* Create a folder for the search results */
616 folder
= addrcache_add_new_folder( server
->addressCache
, NULL
);
617 addritem_folder_set_name( folder
, name
);
618 addritem_folder_set_remarks( folder
, "" );
620 /* Construct a query */
621 qry
= ldapqry_create();
622 ldapqry_set_query_id( qry
, req
->queryID
);
623 ldapqry_set_search_value( qry
, searchTerm
);
624 ldapqry_set_search_type( qry
, ADDRSEARCH_DYNAMIC
);
625 ldapqry_set_callback_entry( qry
, req
->callBackEntry
);
626 ldapqry_set_callback_end( qry
, req
->callBackEnd
);
628 /* Specify folder type and back reference */
629 ADDRQUERY_FOLDER(qry
) = folder
;
630 folder
->folderType
= ADDRFOLDER_QUERY_RESULTS
;
631 folder
->folderData
= ( gpointer
) qry
;
632 folder
->isHidden
= TRUE
;
635 ldapqry_set_name( qry
, name
);
638 /* Add query to request */
639 qryreq_add_query( req
, ADDRQUERY_OBJECT(qry
) );
641 /* Now start the search */
642 ldapsvr_add_query( server
, qry
);
648 * Construct a new LdapQuery object that will be used to perform an explicit
651 * \param server LdapServer.
652 * \param req Query request.
653 * \param folder Folder that will be used to contain search results.
654 * \return LdapQuery object, or <i>NULL</i> if none created.
656 LdapQuery
*ldapsvr_new_explicit_search(
657 LdapServer
*server
, QueryRequest
*req
, ItemFolder
*folder
)
663 cm_return_val_if_fail( server
!= NULL
, NULL
);
664 cm_return_val_if_fail( req
!= NULL
, NULL
);
665 cm_return_val_if_fail( folder
!= NULL
, NULL
);
667 /* Retire any aged queries */
668 /* // ldapsvr_retire_query( server ); */
671 searchTerm
= req
->searchTerm
;
672 name
= g_strdup_printf( "Explicit search for '%s'", searchTerm
);
674 /* Construct a query */
675 qry
= ldapqry_create();
676 ldapqry_set_query_id( qry
, req
->queryID
);
677 ldapqry_set_name( qry
, name
);
678 ldapqry_set_search_value( qry
, searchTerm
);
679 ldapqry_set_search_type( qry
, ADDRSEARCH_EXPLICIT
);
680 ldapqry_set_callback_end( qry
, req
->callBackEnd
);
681 ldapqry_set_callback_entry( qry
, req
->callBackEntry
);
683 /* Specify folder type and back reference */
684 ADDRQUERY_FOLDER(qry
) = folder
;
685 folder
->folderType
= ADDRFOLDER_QUERY_RESULTS
;
686 folder
->folderData
= ( gpointer
) qry
;
689 ldapsvr_add_query( server
, qry
);
691 /* Set up query request */
692 qryreq_add_query( req
, ADDRQUERY_OBJECT(qry
) );
699 gint
ldapsvr_read_data( LdapServer
*server
)
703 cm_return_val_if_fail( server
!= NULL
, -1 );
705 name
= addrcache_get_name(server
->addressCache
);
706 debug_print("...addrbook_read_data :%s:\n", name
?name
:"null");
708 addrcache_clear(server
->addressCache
);
709 ldapsvr_free_all_query( server
);
710 server
->listQuery
= NULL
;
711 server
->addressCache
->modified
= FALSE
;
712 server
->addressCache
->accessFlag
= FALSE
;
713 server
->addressCache
->dataRead
= TRUE
;
714 addrcache_set_dirty(server
->addressCache
, FALSE
);
718 void ldapsrv_set_options (gint secs
, LDAP
*ld
)
720 static struct timeval timeout
;
723 timeout
.tv_sec
= secs
;
726 i
= LDAP_OPT_X_TLS_ALLOW
;
727 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_REQUIRE_CERT
, &i
);
729 debug_print("cert %s\n", ldaputil_get_error(ld
));
731 debug_print("cert %s\n", ldap_err2string(rc
));
732 /* can crash old libldaps... */
733 rc
= ldap_set_option(NULL
, LDAP_OPT_NETWORK_TIMEOUT
, &timeout
);
735 debug_print("tm %s\n", ldaputil_get_error(ld
));
737 debug_print("tm %s\n", ldap_err2string(rc
));
743 #define LDAP_START_TLS_S "ldap_start_tls_sW"
744 typedef ULONG (* PFldap_start_tls_s
) (LDAP
*, PULONG
, LDAPMessage
**, PLDAPControlW
*, PLDAPControlW
*);
746 #define LDAP_START_TLS_S "ldap_start_tls_sA"
747 typedef ULONG (* PFldap_start_tls_s
) (LDAP
*, PULONG
, LDAPMessage
**, PLDAPControlA
*, PLDAPControlA
*);
748 #endif /* LDAP_UNICODE */
749 PFldap_start_tls_s Win32_ldap_start_tls_s
= NULL
;
753 * Connect to LDAP server.
754 * \param ctl Control object to process.
755 * \return LDAP Resource to LDAP.
757 LDAP
*ldapsvr_connect(LdapControl
*ctl
) {
764 cm_return_val_if_fail(ctl
!= NULL
, NULL
);
766 ldapsrv_set_options (ctl
->timeOut
, NULL
);
767 uri
= g_strdup_printf("ldap%s://%s:%d",
768 ctl
->enableSSL
?"s":"",
769 ctl
->hostName
, ctl
->port
);
771 ldap_initialize(&ld
, uri
);
773 ld
= ldap_sslinit(ctl
->hostName
, ctl
->port
, ctl
->enableSSL
);
774 if (ld
&& ctl
->enableSSL
) {
775 version
= LDAP_VERSION3
;
776 debug_print("Setting version 3\n");
777 rc
= ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
, (void *)&version
);
778 if (rc
== LDAP_SUCCESS
)
779 ctl
->version
= LDAP_VERSION3
;
781 debug_print("Failed: %s\n", ldaputil_get_error(ld
));
783 if (ldap_get_option(ld
,LDAP_OPT_SSL
,(void*)&rc
) != LDAP_SUCCESS
)
784 debug_print("Can't get SSL state\n");
786 if ((void *)rc
!= LDAP_OPT_ON
) {
787 debug_print("Enabling SSL\n");
788 if (ldap_set_option(ld
,LDAP_OPT_SSL
,LDAP_OPT_ON
) != LDAP_SUCCESS
)
789 debug_print("Failed: %s\n", ldaputil_get_error(ld
));
791 ldap_get_option(ld
,LDAP_OPT_SSL
,(void*)&rc
);
792 debug_print("SSL now %d\n", rc
);
796 if (!ld
|| (rc
= ldap_connect(ld
, NULL
)) != LDAP_SUCCESS
)
797 debug_print("ldap_connect failed: %d %s\n", rc
, ldaputil_get_error(ld
));
806 debug_print("Got handle to LDAP host %s on port %d\n", ctl
->hostName
, ctl
->port
);
808 version
= LDAP_VERSION3
;
809 debug_print("Setting version 3\n");
810 rc
= ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
811 if (rc
== LDAP_OPT_SUCCESS
) {
812 ctl
->version
= LDAP_VERSION3
;
814 g_printerr("LDAP: Error %d (%s)\n",
815 rc
, ldaputil_get_error(ld
));
817 #if (defined USE_LDAP_TLS || defined G_OS_WIN32)
819 if (ctl
->version
== LDAP_VERSION3
) {
820 if (ctl
->enableTLS
&& !ctl
->enableSSL
) {
823 if (Win32_ldap_start_tls_s
== NULL
) {
824 void *lib
= LoadLibrary("wldap32.dll");
825 if (!lib
|| (Win32_ldap_start_tls_s
= (PFldap_start_tls_s
) GetProcAddress(lib
, LDAP_START_TLS_S
)) == NULL
) {
826 g_printerr("LDAP Error(tls): ldap_start_tls_s: not supported on this platform");
832 debug_print("Setting TLS\n");
833 rc
= Win32_ldap_start_tls_s(ld
, &serv_rc
, NULL
, NULL
, NULL
);
834 debug_print("ldap_start_tls_s: %d server %d %s\n",
835 rc
, serv_rc
, ldaputil_get_error(ld
));
837 debug_print("Setting TLS\n");
838 rc
= ldap_start_tls_s(ld
, NULL
, NULL
);
840 if (rc
!= LDAP_SUCCESS
) {
841 g_printerr("LDAP Error(tls): ldap_start_tls_s: %d %s\n",
842 rc
, ldaputil_get_error(ld
));
845 debug_print("Done\n");
851 /* Bind to the server, if required */
853 if (* ctl
->bindDN
!= '\0') {
854 pwd
= ldapctl_get_bind_password(ctl
);
855 rc
= claws_ldap_simple_bind_s(ld
, ctl
->bindDN
, pwd
);
856 if (rc
!= LDAP_SUCCESS
) {
857 g_printerr("bindDN: %s, bindPass xxx\n", ctl
->bindDN
);
858 g_printerr("LDAP Error(bind): ldap_simple_bind_s: %s\n",
859 ldaputil_get_error(ld
));
870 * Disconnect to LDAP server.
871 * \param ld Resource to LDAP.
873 void ldapsvr_disconnect(LDAP
*ld
) {
875 cm_return_if_fail(ld
!= NULL
);
876 ldap_unbind_ext(ld
, NULL
, NULL
);
879 #endif /* USE_LDAP */