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"
44 #include "passwordstore.h"
47 * Create new LDAP server interface object with no control object.
48 * \return Initialized LDAP server object.
50 LdapServer
*ldapsvr_create_noctl( void ) {
53 server
= g_new0( LdapServer
, 1 );
54 server
->type
= ADBOOKTYPE_LDAP
;
55 server
->addressCache
= addrcache_create();
56 server
->retVal
= MGU_SUCCESS
;
57 server
->control
= NULL
;
58 server
->listQuery
= NULL
;
59 server
->searchFlag
= FALSE
;
64 * Create new LDAP server interface object.
65 * \return Initialized LDAP server object.
67 LdapServer
*ldapsvr_create( void ) {
69 server
= ldapsvr_create_noctl();
70 server
->control
= ldapctl_create();
75 * Return name of server.
76 * \param server Server object.
77 * \return Name for server.
79 gchar
*ldapsvr_get_name( LdapServer
*server
) {
80 cm_return_val_if_fail( server
!= NULL
, NULL
);
81 return addrcache_get_name( server
->addressCache
);
85 * Specify name to be used.
86 * \param server Server object.
87 * \param value Name for server.
89 void ldapsvr_set_name( LdapServer
* server
, const gchar
*value
) {
90 cm_return_if_fail( server
!= NULL
);
91 addrcache_set_name( server
->addressCache
, value
);
92 debug_print("setting name: %s\n", value
?value
:"null");
96 * Refresh internal variables to force a file read.
97 * \param server Server object.
99 void ldapsvr_force_refresh( LdapServer
*server
) {
100 cm_return_if_fail( server
!= NULL
);
101 addrcache_refresh( server
->addressCache
);
105 * Return status/error code.
106 * \param server Server object.
107 * \return Status/error code.
109 gint
ldapsvr_get_status( LdapServer
*server
) {
110 cm_return_val_if_fail( server
!= NULL
, -1 );
111 return server
->retVal
;
115 * Return reference to root level folder.
116 * \param server Server object.
117 * \return Root level folder.
119 ItemFolder
*ldapsvr_get_root_folder( LdapServer
*server
) {
120 cm_return_val_if_fail( server
!= NULL
, NULL
);
122 g_print( "ldapsvr_get_root_folder/start\n" );
123 ldapsvr_print_data( server, stdout );
124 g_print( "ldapsvr_get_root_folder/done\n" );
126 return addrcache_get_root_folder( server
->addressCache
);
130 * Test whether server data has been accessed.
131 * \param server Server object.
132 * \return <i>TRUE</i> if data was accessed.
134 gboolean
ldapsvr_get_accessed( LdapServer
*server
) {
135 cm_return_val_if_fail( server
!= NULL
, FALSE
);
136 return server
->addressCache
->accessFlag
;
140 * Specify that server's data whas beed accessed.
141 * \param server Server object.
142 * \param value Value for flag.
144 void ldapsvr_set_accessed( LdapServer
*server
, const gboolean value
) {
145 cm_return_if_fail( server
!= NULL
);
146 server
->addressCache
->accessFlag
= value
;
147 debug_print("setting accessFlag: %d\n", value
);
151 * Test whether server data has been modified.
152 * \param server Server object.
153 * \return <i>TRUE</i> if data was modified.
155 gboolean
ldapsvr_get_modified( LdapServer
*server
) {
156 cm_return_val_if_fail( server
!= NULL
, FALSE
);
157 return server
->addressCache
->modified
;
161 * Specify modify flag.
162 * \param server Server object.
163 * \param value Value for flag.
165 void ldapsvr_set_modified( LdapServer
*server
, const gboolean value
) {
166 cm_return_if_fail( server
!= NULL
);
167 server
->addressCache
->modified
= value
;
168 debug_print("setting modified: %d\n", value
);
172 * Test whether data was read from server.
173 * \param server Server object.
174 * \return <i>TRUE</i> if data was read.
176 gboolean
ldapsvr_get_read_flag( LdapServer
*server
) {
177 cm_return_val_if_fail( server
!= NULL
, FALSE
);
178 return server
->addressCache
->dataRead
;
182 * Test whether server is to be used for dynamic searches.
183 * \param server Server object.
184 * \return <i>TRUE</i> if server is used for dynamic searches.
186 gboolean
ldapsvr_get_search_flag( LdapServer
*server
) {
187 cm_return_val_if_fail( server
!= NULL
, FALSE
);
188 return server
->searchFlag
;
192 * Specify that server is to be used for dynamic searches.
193 * \param server Server object.
194 * \param value Name for server.
196 void ldapsvr_set_search_flag( LdapServer
*server
, const gboolean value
) {
197 cm_return_if_fail( server
!= NULL
);
198 server
->searchFlag
= value
;
199 debug_print("setting searchFlag: %d\n", value
);
203 * Specify the reference to control data that will be used for the query. The calling
204 * module should be responsible for creating and destroying this control object.
205 * \param server Server object.
206 * \param ctl Control data.
208 void ldapsvr_set_control( LdapServer
*server
, LdapControl
*ctl
) {
209 cm_return_if_fail( server
!= NULL
);
210 addrcache_refresh( server
->addressCache
);
211 server
->control
= ctl
;
216 * \param server Server object.
218 void ldapsvr_free_all_query( LdapServer
*server
) {
220 cm_return_if_fail( server
!= NULL
);
222 node
= server
->listQuery
;
224 LdapQuery
*qry
= node
->data
;
227 node
= g_list_next( node
);
229 g_list_free( server
->listQuery
);
230 server
->listQuery
= NULL
;
234 * Add query to server.
235 * \param server Server object.
236 * \param qry Query object.
238 void ldapsvr_add_query( LdapServer
*server
, LdapQuery
*qry
) {
239 cm_return_if_fail( server
!= NULL
);
240 cm_return_if_fail( qry
!= NULL
);
242 server
->listQuery
= g_list_append( server
->listQuery
, qry
);
243 qry
->server
= server
;
247 * Free up LDAP server interface object by releasing internal memory.
248 * \param server Server object.
250 void ldapsvr_free( LdapServer
*server
) {
251 cm_return_if_fail( server
!= NULL
);
253 /* Stop and cancel any queries that may be active */
254 ldapsvr_stop_all_query( server
);
255 ldapsvr_cancel_all_query( server
);
258 addrcache_clear( server
->addressCache
);
259 addrcache_free( server
->addressCache
);
261 /* Free LDAP control block */
262 ldapctl_free( server
->control
);
263 server
->control
= NULL
;
265 /* Free all queries */
266 ldapsvr_free_all_query( server
);
269 server
->type
= ADBOOKTYPE_NONE
;
270 server
->addressCache
= NULL
;
271 server
->retVal
= MGU_SUCCESS
;
272 server
->listQuery
= NULL
;
273 server
->searchFlag
= FALSE
;
275 /* Now release LDAP object */
280 * Display object to specified stream.
281 * \param server Server object.
282 * \param stream Output stream.
284 void ldapsvr_print_data( LdapServer
*server
, FILE *stream
) {
288 cm_return_if_fail( server
!= NULL
);
290 fprintf( stream
, "LdapServer:\n" );
291 fprintf( stream
, " ret val: %d\n", server
->retVal
);
292 fprintf( stream
, "srch flag: %s\n",
293 server
->searchFlag
? "yes" : "no" );
294 if( server
->control
) {
295 ldapctl_print( server
->control
, stream
);
298 fprintf( stream
, " control: NULL\n" );
300 addrcache_print( server
->addressCache
, stream
);
301 addritem_print_item_folder( server
->addressCache
->rootFolder
, stream
);
305 node
= server
->listQuery
;
307 LdapQuery
*qry
= node
->data
;
308 fprintf( stream
, " query: %2d : %s\n", i
, ADDRQUERY_NAME(qry
) );
310 node
= g_list_next( node
);
315 * Return link list of persons.
316 * \param server Server object.
317 * \return List of persons.
319 GList
*ldapsvr_get_list_person( LdapServer
*server
) {
320 cm_return_val_if_fail( server
!= NULL
, NULL
);
321 return addrcache_get_list_person( server
->addressCache
);
325 * Return link list of folders. There are no "real" folders that are returned
327 * \param server Server object.
328 * \return List of folders.
330 GList
*ldapsvr_get_list_folder( LdapServer
*server
) {
331 cm_return_val_if_fail( server
!= NULL
, NULL
);
332 /* return addrcache_get_list_folder( server->addressCache ); */
337 * Execute specified query.
338 * \param server LDAP server.
339 * \param qry LDAP query.
341 void ldapsvr_execute_query( LdapServer
*server
, LdapQuery
*qry
) {
342 LdapControl
*ctlCopy
;
344 cm_return_if_fail( server
!= NULL
);
345 cm_return_if_fail( qry
!= NULL
);
347 /* Copy server's control data to the query */
348 ctlCopy
= ldapctl_create();
349 ldapctl_copy( server
->control
, ctlCopy
);
350 ldapqry_set_control( qry
, ctlCopy
);
351 ldapqry_initialize();
354 debug_print("ldapsvr_execute_query::checking query...\n");
355 if( ldapqry_check_search( qry
) ) {
356 debug_print("ldapsvr_execute_query::reading with thread...\n");
357 ldapqry_read_data_th( qry
);
358 if(qry
->server
->retVal
== LDAPRC_SUCCESS
) {
359 debug_print("ldapsvr_execute_query::SUCCESS with thread...\n");
362 debug_print("ldapsvr_execute_query... terminated\n");
366 * Stop all queries for specified ID.
367 * \param server Server object.
368 * \param queryID Query ID to stop.
370 void ldapsvr_stop_query_id( LdapServer
*server
, const gint queryID
) {
372 cm_return_if_fail( server
!= NULL
);
374 node
= server
->listQuery
;
376 LdapQuery
*qry
= node
->data
;
377 if( ADDRQUERY_ID(qry
) == queryID
) {
378 /* Notify thread to stop */
379 ldapqry_set_stop_flag( qry
, TRUE
);
381 node
= g_list_next( node
);
386 * Stop all queries by notifying each thread to stop.
387 * \param server Server object.
389 void ldapsvr_stop_all_query( LdapServer
*server
) {
391 cm_return_if_fail( server
!= NULL
);
393 node
= server
->listQuery
;
395 LdapQuery
*qry
= node
->data
;
396 ldapqry_set_stop_flag( qry
, TRUE
);
397 node
= g_list_next( node
);
402 * Cancel all query threads for server.
403 * \param server Server object.
405 void ldapsvr_cancel_all_query( LdapServer
*server
) {
407 cm_return_if_fail( server
!= NULL
);
409 node
= server
->listQuery
;
411 LdapQuery
*qry
= node
->data
;
412 /* Notify thread to stop */
413 ldapqry_set_stop_flag( qry
, TRUE
);
414 /* Now cancel thread */
415 ldapqry_cancel( qry
);
416 node
= g_list_next( node
);
421 * Search most recent query for specified search term. The most recent
422 * completed query is returned. If no completed query is found, the most recent
423 * incomplete is returned.
424 * \param server LdapServer.
425 * \param searchTerm Search term to locate.
426 * \return Query object, or <i>NULL</i> if none found.
428 static LdapQuery
*ldapsvr_locate_query(
429 const LdapServer
*server
, const gchar
*searchTerm
)
431 LdapQuery
*incomplete
= NULL
;
433 cm_return_val_if_fail( server
!= NULL
, NULL
);
435 node
= server
->listQuery
;
436 node
= g_list_last( node
);
437 /* Search backwards for query */
439 LdapQuery
*qry
= node
->data
;
440 if( g_utf8_collate( ADDRQUERY_SEARCHVALUE(qry
), searchTerm
) == 0 ) {
441 if( qry
->agedFlag
) continue;
442 if( qry
->completed
) {
450 node
= g_list_previous( node
);
456 * Retire aged queries. Only the following queries are retired:
458 * a) Dynamic queries.
459 * b) Explicit searches that have a hidden folders.
460 * c) Locate searches that have a hidden folder.
462 * \param server LdapServer.
464 void ldapsvr_retire_query( LdapServer
*server
) {
472 debug_print("ldapsvr_retire_query\n");
473 cm_return_if_fail( server
!= NULL
);
474 ctl
= server
->control
;
475 maxAge
= ctl
->maxQueryAge
;
477 /* Identify queries to age and move to deletion list */
479 node
= server
->listQuery
;
481 LdapQuery
*qry
= node
->data
;
483 node
= g_list_next( node
);
484 folder
= ADDRQUERY_FOLDER(qry
);
485 if( folder
== NULL
) continue;
486 if( ! folder
->isHidden
) {
487 if( ADDRQUERY_SEARCHTYPE(qry
) == ADDRSEARCH_EXPLICIT
) continue;
488 if( ADDRQUERY_SEARCHTYPE(qry
) == ADDRSEARCH_LOCATE
) continue;
491 ldapqry_age( qry
, maxAge
);
492 if( qry
->agedFlag
) {
493 /* Delete folder associated with query */
494 debug_print("deleting folder... ::%s::\n",
495 ADDRQUERY_NAME(qry
)?ADDRQUERY_NAME(qry
):"null");
496 ldapqry_delete_folder( qry
);
497 listDelete
= g_list_append( listDelete
, qry
);
502 listQuery
= server
->listQuery
;
505 LdapQuery
*qry
= node
->data
;
507 listQuery
= g_list_remove( listQuery
, qry
);
510 node
= g_list_next( node
);
512 server
->listQuery
= listQuery
;
514 /* Free up deletion list */
515 g_list_free( listDelete
);
519 * Return results of a previous query by executing callback for each address
520 * contained in specified folder.
522 * \param folder Address book folder to process.
523 * \param req Address query request object.
525 static void ldapsvr_previous_query(
526 const ItemFolder
*folder
, const QueryRequest
*req
, AddrQueryObject
*aqo
)
528 AddrSearchCallbackEntry
*callBack
;
535 callBack
= ( AddrSearchCallbackEntry
* ) req
->callBackEntry
;
538 node
= folder
->listPerson
;
540 AddrItemObject
*aio
= node
->data
;
541 if( aio
&& aio
->type
== ITEMTYPE_PERSON
) {
542 ItemPerson
*person
= node
->data
;
543 nodeEM
= person
->listEMail
;
545 ItemEMail
*email
= nodeEM
->data
;
547 nodeEM
= g_list_next( nodeEM
);
548 listEMail
= g_list_append( listEMail
, email
);
551 node
= g_list_next( node
);
553 ( callBack
) ( sender
, req
->queryID
, listEMail
, NULL
);
554 /* // g_list_free( listEMail ); */
559 * Reuse search results from a previous LDAP query. If there is a query that
560 * has the same search term as specified in the query request, then the query
563 * \param server LDAP server object.
564 * \param req Address query object.
565 * \return <i>TRUE</i> if previous query was used.
567 gboolean
ldapsvr_reuse_previous( const LdapServer
*server
, const QueryRequest
*req
) {
572 cm_return_val_if_fail( server
!= NULL
, FALSE
);
573 cm_return_val_if_fail( req
!= NULL
, FALSE
);
575 searchTerm
= req
->searchTerm
;
577 /* Test whether any queries for the same term exist */
578 qry
= ldapsvr_locate_query( server
, searchTerm
);
580 /* Touch query to ensure it hangs around for a bit longer */
581 ldapqry_touch( qry
);
582 folder
= ADDRQUERY_FOLDER(qry
);
584 ldapsvr_previous_query( folder
, req
, ADDRQUERY_OBJECT(qry
) );
592 * Construct a new LdapQuery object that will be used to perform an dynamic
595 * \param server LdapServer.
596 * \param req Query request.
597 * \return LdapQuery object, or <i>NULL</i> if none created.
599 LdapQuery
*ldapsvr_new_dynamic_search( LdapServer
*server
, QueryRequest
*req
)
606 cm_return_val_if_fail( server
!= NULL
, NULL
);
607 cm_return_val_if_fail( req
!= NULL
, NULL
);
609 /* Retire any aged queries */
610 /* // ldapsvr_retire_query( server ); */
612 /* Name of folder and query */
613 searchTerm
= req
->searchTerm
;
614 name
= g_strdup_printf( "Search '%s'", searchTerm
);
616 /* Create a folder for the search results */
617 folder
= addrcache_add_new_folder( server
->addressCache
, NULL
);
618 addritem_folder_set_name( folder
, name
);
619 addritem_folder_set_remarks( folder
, "" );
621 /* Construct a query */
622 qry
= ldapqry_create();
623 ldapqry_set_query_id( qry
, req
->queryID
);
624 ldapqry_set_search_value( qry
, searchTerm
);
625 ldapqry_set_search_type( qry
, ADDRSEARCH_DYNAMIC
);
626 ldapqry_set_callback_entry( qry
, req
->callBackEntry
);
627 ldapqry_set_callback_end( qry
, req
->callBackEnd
);
629 /* Specify folder type and back reference */
630 ADDRQUERY_FOLDER(qry
) = folder
;
631 folder
->folderType
= ADDRFOLDER_QUERY_RESULTS
;
632 folder
->folderData
= ( gpointer
) qry
;
633 folder
->isHidden
= TRUE
;
636 ldapqry_set_name( qry
, name
);
639 /* Add query to request */
640 qryreq_add_query( req
, ADDRQUERY_OBJECT(qry
) );
642 /* Now start the search */
643 ldapsvr_add_query( server
, qry
);
649 * Construct a new LdapQuery object that will be used to perform an explicit
652 * \param server LdapServer.
653 * \param req Query request.
654 * \param folder Folder that will be used to contain search results.
655 * \return LdapQuery object, or <i>NULL</i> if none created.
657 LdapQuery
*ldapsvr_new_explicit_search(
658 LdapServer
*server
, QueryRequest
*req
, ItemFolder
*folder
)
664 cm_return_val_if_fail( server
!= NULL
, NULL
);
665 cm_return_val_if_fail( req
!= NULL
, NULL
);
666 cm_return_val_if_fail( folder
!= NULL
, NULL
);
668 /* Retire any aged queries */
669 /* // ldapsvr_retire_query( server ); */
672 searchTerm
= req
->searchTerm
;
673 name
= g_strdup_printf( "Explicit search for '%s'", searchTerm
);
675 /* Construct a query */
676 qry
= ldapqry_create();
677 ldapqry_set_query_id( qry
, req
->queryID
);
678 ldapqry_set_name( qry
, name
);
679 ldapqry_set_search_value( qry
, searchTerm
);
680 ldapqry_set_search_type( qry
, ADDRSEARCH_EXPLICIT
);
681 ldapqry_set_callback_end( qry
, req
->callBackEnd
);
682 ldapqry_set_callback_entry( qry
, req
->callBackEntry
);
684 /* Specify folder type and back reference */
685 ADDRQUERY_FOLDER(qry
) = folder
;
686 folder
->folderType
= ADDRFOLDER_QUERY_RESULTS
;
687 folder
->folderData
= ( gpointer
) qry
;
690 ldapsvr_add_query( server
, qry
);
692 /* Set up query request */
693 qryreq_add_query( req
, ADDRQUERY_OBJECT(qry
) );
700 gint
ldapsvr_read_data( LdapServer
*server
)
704 cm_return_val_if_fail( server
!= NULL
, -1 );
706 name
= addrcache_get_name(server
->addressCache
);
707 debug_print("...addrbook_read_data :%s:\n", name
?name
:"null");
709 addrcache_clear(server
->addressCache
);
710 ldapsvr_free_all_query( server
);
711 server
->listQuery
= NULL
;
712 server
->addressCache
->modified
= FALSE
;
713 server
->addressCache
->accessFlag
= FALSE
;
714 server
->addressCache
->dataRead
= TRUE
;
715 addrcache_set_dirty(server
->addressCache
, FALSE
);
719 void ldapsrv_set_options (gint secs
, LDAP
*ld
)
722 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
|| ctl
->enableTLS
)?"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/TLS state\n");
786 if ((void *)rc
!= LDAP_OPT_ON
) {
787 debug_print("Enabling SSL/TLS\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/TLS 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 STARTTLS\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 STARTTLS\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
= passwd_store_get(PWS_CORE
, "LDAP", ctl
->hostName
);
855 rc
= claws_ldap_simple_bind_s(ld
, ctl
->bindDN
, pwd
);
856 if (pwd
!= NULL
&& strlen(pwd
) > 0)
857 memset(pwd
, 0, strlen(pwd
));
859 if (rc
!= LDAP_SUCCESS
) {
860 g_printerr("bindDN: %s, bindPass xxx\n", ctl
->bindDN
);
861 g_printerr("LDAP Error(bind): ldap_simple_bind_s: %s\n",
862 ldaputil_get_error(ld
));
871 * Disconnect to LDAP server.
872 * \param ld Resource to LDAP.
874 void ldapsvr_disconnect(LDAP
*ld
) {
876 cm_return_if_fail(ld
!= NULL
);
877 ldap_unbind_ext(ld
, NULL
, NULL
);
880 #endif /* USE_LDAP */