2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2018 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/>.
20 * Functions necessary to access LDAP servers.
25 #include "claws-features.h"
31 #include <glib/gi18n.h>
37 #include "addrcache.h"
39 #include "ldapquery.h"
40 #include "ldapserver.h"
43 #include "adbookbase.h"
44 #include "passwordstore.h"
48 * Create new LDAP server interface object with no control object.
49 * \return Initialized LDAP server object.
51 LdapServer
*ldapsvr_create_noctl( void ) {
54 server
= g_new0( LdapServer
, 1 );
55 server
->type
= ADBOOKTYPE_LDAP
;
56 server
->addressCache
= addrcache_create();
57 server
->retVal
= MGU_SUCCESS
;
58 server
->control
= NULL
;
59 server
->listQuery
= NULL
;
60 server
->searchFlag
= FALSE
;
65 * Create new LDAP server interface object.
66 * \return Initialized LDAP server object.
68 LdapServer
*ldapsvr_create( void ) {
70 server
= ldapsvr_create_noctl();
71 server
->control
= ldapctl_create();
76 * Return name of server.
77 * \param server Server object.
78 * \return Name for server.
80 gchar
*ldapsvr_get_name( LdapServer
*server
) {
81 cm_return_val_if_fail( server
!= NULL
, NULL
);
82 return addrcache_get_name( server
->addressCache
);
86 * Specify name to be used.
87 * \param server Server object.
88 * \param value Name for server.
90 void ldapsvr_set_name( LdapServer
* server
, const gchar
*value
) {
91 cm_return_if_fail( server
!= NULL
);
92 addrcache_set_name( server
->addressCache
, value
);
93 debug_print("setting name: %s\n", value
?value
:"null");
97 * Refresh internal variables to force a file read.
98 * \param server Server object.
100 void ldapsvr_force_refresh( LdapServer
*server
) {
101 cm_return_if_fail( server
!= NULL
);
102 addrcache_refresh( server
->addressCache
);
106 * Return status/error code.
107 * \param server Server object.
108 * \return Status/error code.
110 gint
ldapsvr_get_status( LdapServer
*server
) {
111 cm_return_val_if_fail( server
!= NULL
, -1 );
112 return server
->retVal
;
116 * Return reference to root level folder.
117 * \param server Server object.
118 * \return Root level folder.
120 ItemFolder
*ldapsvr_get_root_folder( LdapServer
*server
) {
121 cm_return_val_if_fail( server
!= NULL
, NULL
);
123 g_print( "ldapsvr_get_root_folder/start\n" );
124 ldapsvr_print_data( server, stdout );
125 g_print( "ldapsvr_get_root_folder/done\n" );
127 return addrcache_get_root_folder( server
->addressCache
);
131 * Test whether server data has been accessed.
132 * \param server Server object.
133 * \return <i>TRUE</i> if data was accessed.
135 gboolean
ldapsvr_get_accessed( LdapServer
*server
) {
136 cm_return_val_if_fail( server
!= NULL
, FALSE
);
137 return server
->addressCache
->accessFlag
;
141 * Specify that server's data whas beed accessed.
142 * \param server Server object.
143 * \param value Value for flag.
145 void ldapsvr_set_accessed( LdapServer
*server
, const gboolean value
) {
146 cm_return_if_fail( server
!= NULL
);
147 server
->addressCache
->accessFlag
= value
;
148 debug_print("setting accessFlag: %d\n", value
);
152 * Test whether server data has been modified.
153 * \param server Server object.
154 * \return <i>TRUE</i> if data was modified.
156 gboolean
ldapsvr_get_modified( LdapServer
*server
) {
157 cm_return_val_if_fail( server
!= NULL
, FALSE
);
158 return server
->addressCache
->modified
;
162 * Specify modify flag.
163 * \param server Server object.
164 * \param value Value for flag.
166 void ldapsvr_set_modified( LdapServer
*server
, const gboolean value
) {
167 cm_return_if_fail( server
!= NULL
);
168 server
->addressCache
->modified
= value
;
169 debug_print("setting modified: %d\n", value
);
173 * Test whether data was read from server.
174 * \param server Server object.
175 * \return <i>TRUE</i> if data was read.
177 gboolean
ldapsvr_get_read_flag( LdapServer
*server
) {
178 cm_return_val_if_fail( server
!= NULL
, FALSE
);
179 return server
->addressCache
->dataRead
;
183 * Test whether server is to be used for dynamic searches.
184 * \param server Server object.
185 * \return <i>TRUE</i> if server is used for dynamic searches.
187 gboolean
ldapsvr_get_search_flag( LdapServer
*server
) {
188 cm_return_val_if_fail( server
!= NULL
, FALSE
);
189 return server
->searchFlag
;
193 * Specify that server is to be used for dynamic searches.
194 * \param server Server object.
195 * \param value Name for server.
197 void ldapsvr_set_search_flag( LdapServer
*server
, const gboolean value
) {
198 cm_return_if_fail( server
!= NULL
);
199 server
->searchFlag
= value
;
200 debug_print("setting searchFlag: %d\n", value
);
204 * Specify the reference to control data that will be used for the query. The calling
205 * module should be responsible for creating and destroying this control object.
206 * \param server Server object.
207 * \param ctl Control data.
209 void ldapsvr_set_control( LdapServer
*server
, LdapControl
*ctl
) {
210 cm_return_if_fail( server
!= NULL
);
211 addrcache_refresh( server
->addressCache
);
212 server
->control
= ctl
;
217 * \param server Server object.
219 void ldapsvr_free_all_query( LdapServer
*server
) {
221 cm_return_if_fail( server
!= NULL
);
223 node
= server
->listQuery
;
225 LdapQuery
*qry
= node
->data
;
228 node
= g_list_next( node
);
230 g_list_free( server
->listQuery
);
231 server
->listQuery
= NULL
;
235 * Add query to server.
236 * \param server Server object.
237 * \param qry Query object.
239 void ldapsvr_add_query( LdapServer
*server
, LdapQuery
*qry
) {
240 cm_return_if_fail( server
!= NULL
);
241 cm_return_if_fail( qry
!= NULL
);
243 server
->listQuery
= g_list_append( server
->listQuery
, qry
);
244 qry
->server
= server
;
248 * Free up LDAP server interface object by releasing internal memory.
249 * \param server Server object.
251 void ldapsvr_free( LdapServer
*server
) {
252 cm_return_if_fail( server
!= NULL
);
254 /* Stop and cancel any queries that may be active */
255 ldapsvr_stop_all_query( server
);
256 ldapsvr_cancel_all_query( server
);
259 addrcache_clear( server
->addressCache
);
260 addrcache_free( server
->addressCache
);
262 /* Free LDAP control block */
263 ldapctl_free( server
->control
);
264 server
->control
= NULL
;
266 /* Free all queries */
267 ldapsvr_free_all_query( server
);
270 server
->type
= ADBOOKTYPE_NONE
;
271 server
->addressCache
= NULL
;
272 server
->retVal
= MGU_SUCCESS
;
273 server
->listQuery
= NULL
;
274 server
->searchFlag
= FALSE
;
276 /* Now release LDAP object */
281 * Display object to specified stream.
282 * \param server Server object.
283 * \param stream Output stream.
285 void ldapsvr_print_data( LdapServer
*server
, FILE *stream
) {
289 cm_return_if_fail( server
!= NULL
);
291 fprintf( stream
, "LdapServer:\n" );
292 fprintf( stream
, " ret val: %d\n", server
->retVal
);
293 fprintf( stream
, "srch flag: %s\n",
294 server
->searchFlag
? "yes" : "no" );
295 if( server
->control
) {
296 ldapctl_print( server
->control
, stream
);
299 fprintf( stream
, " control: NULL\n" );
301 addrcache_print( server
->addressCache
, stream
);
302 addritem_print_item_folder( server
->addressCache
->rootFolder
, stream
);
306 node
= server
->listQuery
;
308 LdapQuery
*qry
= node
->data
;
309 fprintf( stream
, " query: %2d : %s\n", i
, ADDRQUERY_NAME(qry
) );
311 node
= g_list_next( node
);
316 * Return link list of persons.
317 * \param server Server object.
318 * \return List of persons.
320 GList
*ldapsvr_get_list_person( LdapServer
*server
) {
321 cm_return_val_if_fail( server
!= NULL
, NULL
);
322 return addrcache_get_list_person( server
->addressCache
);
326 * Return link list of folders. There are no "real" folders that are returned
328 * \param server Server object.
329 * \return List of folders.
331 GList
*ldapsvr_get_list_folder( LdapServer
*server
) {
332 cm_return_val_if_fail( server
!= NULL
, NULL
);
333 /* return addrcache_get_list_folder( server->addressCache ); */
338 * Execute specified query.
339 * \param server LDAP server.
340 * \param qry LDAP query.
342 void ldapsvr_execute_query( LdapServer
*server
, LdapQuery
*qry
) {
343 LdapControl
*ctlCopy
;
345 cm_return_if_fail( server
!= NULL
);
346 cm_return_if_fail( qry
!= NULL
);
348 /* Copy server's control data to the query */
349 ctlCopy
= ldapctl_create();
350 ldapctl_copy( server
->control
, ctlCopy
);
351 ldapqry_set_control( qry
, ctlCopy
);
352 ldapqry_initialize();
355 debug_print("ldapsvr_execute_query::checking query...\n");
356 if( ldapqry_check_search( qry
) ) {
357 debug_print("ldapsvr_execute_query::reading with thread...\n");
358 ldapqry_read_data_th( qry
);
359 if(qry
->server
->retVal
== LDAPRC_SUCCESS
) {
360 debug_print("ldapsvr_execute_query::SUCCESS with thread...\n");
363 debug_print("ldapsvr_execute_query... terminated\n");
367 * Stop all queries for specified ID.
368 * \param server Server object.
369 * \param queryID Query ID to stop.
371 void ldapsvr_stop_query_id( LdapServer
*server
, const gint queryID
) {
373 cm_return_if_fail( server
!= NULL
);
375 node
= server
->listQuery
;
377 LdapQuery
*qry
= node
->data
;
378 if( ADDRQUERY_ID(qry
) == queryID
) {
379 /* Notify thread to stop */
380 ldapqry_set_stop_flag( qry
, TRUE
);
382 node
= g_list_next( node
);
387 * Stop all queries by notifying each thread to stop.
388 * \param server Server object.
390 void ldapsvr_stop_all_query( LdapServer
*server
) {
392 cm_return_if_fail( server
!= NULL
);
394 node
= server
->listQuery
;
396 LdapQuery
*qry
= node
->data
;
397 ldapqry_set_stop_flag( qry
, TRUE
);
398 node
= g_list_next( node
);
403 * Cancel all query threads for server.
404 * \param server Server object.
406 void ldapsvr_cancel_all_query( LdapServer
*server
) {
408 cm_return_if_fail( server
!= NULL
);
410 node
= server
->listQuery
;
412 LdapQuery
*qry
= node
->data
;
413 /* Notify thread to stop */
414 ldapqry_set_stop_flag( qry
, TRUE
);
415 /* Now cancel thread */
416 ldapqry_cancel( qry
);
417 node
= g_list_next( node
);
422 * Search most recent query for specified search term. The most recent
423 * completed query is returned. If no completed query is found, the most recent
424 * incomplete is returned.
425 * \param server LdapServer.
426 * \param searchTerm Search term to locate.
427 * \return Query object, or <i>NULL</i> if none found.
429 static LdapQuery
*ldapsvr_locate_query(
430 const LdapServer
*server
, const gchar
*searchTerm
)
432 LdapQuery
*incomplete
= NULL
;
434 cm_return_val_if_fail( server
!= NULL
, NULL
);
436 node
= server
->listQuery
;
437 node
= g_list_last( node
);
438 /* Search backwards for query */
440 LdapQuery
*qry
= node
->data
;
441 if( g_utf8_collate( ADDRQUERY_SEARCHVALUE(qry
), searchTerm
) == 0 ) {
442 if( qry
->agedFlag
) continue;
443 if( qry
->completed
) {
451 node
= g_list_previous( node
);
457 * Retire aged queries. Only the following queries are retired:
459 * a) Dynamic queries.
460 * b) Explicit searches that have a hidden folders.
461 * c) Locate searches that have a hidden folder.
463 * \param server LdapServer.
465 void ldapsvr_retire_query( LdapServer
*server
) {
473 debug_print("ldapsvr_retire_query\n");
474 cm_return_if_fail( server
!= NULL
);
475 ctl
= server
->control
;
476 maxAge
= ctl
->maxQueryAge
;
478 /* Identify queries to age and move to deletion list */
480 node
= server
->listQuery
;
482 LdapQuery
*qry
= node
->data
;
484 node
= g_list_next( node
);
485 folder
= ADDRQUERY_FOLDER(qry
);
486 if( folder
== NULL
) continue;
487 if( ! folder
->isHidden
) {
488 if( ADDRQUERY_SEARCHTYPE(qry
) == ADDRSEARCH_EXPLICIT
) continue;
489 if( ADDRQUERY_SEARCHTYPE(qry
) == ADDRSEARCH_LOCATE
) continue;
492 ldapqry_age( qry
, maxAge
);
493 if( qry
->agedFlag
) {
494 /* Delete folder associated with query */
495 debug_print("deleting folder... ::%s::\n",
496 ADDRQUERY_NAME(qry
)?ADDRQUERY_NAME(qry
):"null");
497 ldapqry_delete_folder( qry
);
498 listDelete
= g_list_append( listDelete
, qry
);
503 listQuery
= server
->listQuery
;
506 LdapQuery
*qry
= node
->data
;
508 listQuery
= g_list_remove( listQuery
, qry
);
511 node
= g_list_next( node
);
513 server
->listQuery
= listQuery
;
515 /* Free up deletion list */
516 g_list_free( listDelete
);
520 * Return results of a previous query by executing callback for each address
521 * contained in specified folder.
523 * \param folder Address book folder to process.
524 * \param req Address query request object.
526 static void ldapsvr_previous_query(
527 const ItemFolder
*folder
, const QueryRequest
*req
, AddrQueryObject
*aqo
)
529 AddrSearchCallbackEntry
*callBack
;
536 callBack
= ( AddrSearchCallbackEntry
* ) req
->callBackEntry
;
539 node
= folder
->listPerson
;
541 AddrItemObject
*aio
= node
->data
;
542 if( aio
&& aio
->type
== ITEMTYPE_PERSON
) {
543 ItemPerson
*person
= node
->data
;
544 nodeEM
= person
->listEMail
;
546 ItemEMail
*email
= nodeEM
->data
;
548 nodeEM
= g_list_next( nodeEM
);
549 listEMail
= g_list_append( listEMail
, email
);
552 node
= g_list_next( node
);
554 ( callBack
) ( sender
, req
->queryID
, listEMail
, NULL
);
555 /* // g_list_free( listEMail ); */
560 * Reuse search results from a previous LDAP query. If there is a query that
561 * has the same search term as specified in the query request, then the query
564 * \param server LDAP server object.
565 * \param req Address query object.
566 * \return <i>TRUE</i> if previous query was used.
568 gboolean
ldapsvr_reuse_previous( const LdapServer
*server
, const QueryRequest
*req
) {
573 cm_return_val_if_fail( server
!= NULL
, FALSE
);
574 cm_return_val_if_fail( req
!= NULL
, FALSE
);
576 searchTerm
= req
->searchTerm
;
578 /* Test whether any queries for the same term exist */
579 qry
= ldapsvr_locate_query( server
, searchTerm
);
581 /* Touch query to ensure it hangs around for a bit longer */
582 ldapqry_touch( qry
);
583 folder
= ADDRQUERY_FOLDER(qry
);
585 ldapsvr_previous_query( folder
, req
, ADDRQUERY_OBJECT(qry
) );
593 * Construct a new LdapQuery object that will be used to perform an dynamic
596 * \param server LdapServer.
597 * \param req Query request.
598 * \return LdapQuery object, or <i>NULL</i> if none created.
600 LdapQuery
*ldapsvr_new_dynamic_search( LdapServer
*server
, QueryRequest
*req
)
607 cm_return_val_if_fail( server
!= NULL
, NULL
);
608 cm_return_val_if_fail( req
!= NULL
, NULL
);
610 /* Retire any aged queries */
611 /* // ldapsvr_retire_query( server ); */
613 /* Name of folder and query */
614 searchTerm
= req
->searchTerm
;
615 name
= g_strdup_printf( "Search '%s'", searchTerm
);
617 /* Create a folder for the search results */
618 folder
= addrcache_add_new_folder( server
->addressCache
, NULL
);
619 addritem_folder_set_name( folder
, name
);
620 addritem_folder_set_remarks( folder
, "" );
622 /* Construct a query */
623 qry
= ldapqry_create();
624 ldapqry_set_query_id( qry
, req
->queryID
);
625 ldapqry_set_search_value( qry
, searchTerm
);
626 ldapqry_set_search_type( qry
, ADDRSEARCH_DYNAMIC
);
627 ldapqry_set_callback_entry( qry
, req
->callBackEntry
);
628 ldapqry_set_callback_end( qry
, req
->callBackEnd
);
630 /* Specify folder type and back reference */
631 ADDRQUERY_FOLDER(qry
) = folder
;
632 folder
->folderType
= ADDRFOLDER_QUERY_RESULTS
;
633 folder
->folderData
= ( gpointer
) qry
;
634 folder
->isHidden
= TRUE
;
637 ldapqry_set_name( qry
, name
);
640 /* Add query to request */
641 qryreq_add_query( req
, ADDRQUERY_OBJECT(qry
) );
643 /* Now start the search */
644 ldapsvr_add_query( server
, qry
);
650 * Construct a new LdapQuery object that will be used to perform an explicit
653 * \param server LdapServer.
654 * \param req Query request.
655 * \param folder Folder that will be used to contain search results.
656 * \return LdapQuery object, or <i>NULL</i> if none created.
658 LdapQuery
*ldapsvr_new_explicit_search(
659 LdapServer
*server
, QueryRequest
*req
, ItemFolder
*folder
)
665 cm_return_val_if_fail( server
!= NULL
, NULL
);
666 cm_return_val_if_fail( req
!= NULL
, NULL
);
667 cm_return_val_if_fail( folder
!= NULL
, NULL
);
669 /* Retire any aged queries */
670 /* // ldapsvr_retire_query( server ); */
673 searchTerm
= req
->searchTerm
;
674 name
= g_strdup_printf( "Explicit search for '%s'", searchTerm
);
676 /* Construct a query */
677 qry
= ldapqry_create();
678 ldapqry_set_query_id( qry
, req
->queryID
);
679 ldapqry_set_name( qry
, name
);
680 ldapqry_set_search_value( qry
, searchTerm
);
681 ldapqry_set_search_type( qry
, ADDRSEARCH_EXPLICIT
);
682 ldapqry_set_callback_end( qry
, req
->callBackEnd
);
683 ldapqry_set_callback_entry( qry
, req
->callBackEntry
);
685 /* Specify folder type and back reference */
686 ADDRQUERY_FOLDER(qry
) = folder
;
687 folder
->folderType
= ADDRFOLDER_QUERY_RESULTS
;
688 folder
->folderData
= ( gpointer
) qry
;
691 ldapsvr_add_query( server
, qry
);
693 /* Set up query request */
694 qryreq_add_query( req
, ADDRQUERY_OBJECT(qry
) );
701 gint
ldapsvr_read_data( LdapServer
*server
)
705 cm_return_val_if_fail( server
!= NULL
, -1 );
707 name
= addrcache_get_name(server
->addressCache
);
708 debug_print("...addrbook_read_data :%s:\n", name
?name
:"null");
710 addrcache_clear(server
->addressCache
);
711 ldapsvr_free_all_query( server
);
712 server
->listQuery
= NULL
;
713 server
->addressCache
->modified
= FALSE
;
714 server
->addressCache
->accessFlag
= FALSE
;
715 server
->addressCache
->dataRead
= TRUE
;
716 addrcache_set_dirty(server
->addressCache
, FALSE
);
720 void ldapsrv_set_options (gint secs
, LDAP
*ld
)
723 static struct timeval timeout
;
724 timeout
.tv_sec
= secs
;
727 i
= LDAP_OPT_X_TLS_ALLOW
;
728 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_REQUIRE_CERT
, &i
);
730 debug_print("cert %s\n", ldaputil_get_error(ld
));
732 debug_print("cert %s\n", ldap_err2string(rc
));
733 /* can crash old libldaps... */
734 rc
= ldap_set_option(NULL
, LDAP_OPT_NETWORK_TIMEOUT
, &timeout
);
736 debug_print("tm %s\n", ldaputil_get_error(ld
));
738 debug_print("tm %s\n", ldap_err2string(rc
));
744 #define LDAP_START_TLS_S "ldap_start_tls_sW"
745 typedef ULONG (* PFldap_start_tls_s
) (LDAP
*, PULONG
, LDAPMessage
**, PLDAPControlW
*, PLDAPControlW
*);
747 #define LDAP_START_TLS_S "ldap_start_tls_sA"
748 typedef ULONG (* PFldap_start_tls_s
) (LDAP
*, PULONG
, LDAPMessage
**, PLDAPControlA
*, PLDAPControlA
*);
749 #endif /* LDAP_UNICODE */
750 PFldap_start_tls_s Win32_ldap_start_tls_s
= NULL
;
754 * Connect to LDAP server.
755 * \param ctl Control object to process.
756 * \return LDAP Resource to LDAP.
758 LDAP
*ldapsvr_connect(LdapControl
*ctl
) {
768 cm_return_val_if_fail(ctl
!= NULL
, NULL
);
770 ldapsrv_set_options (ctl
->timeOut
, NULL
);
772 uri
= g_strdup_printf("ldaps://%s:%d", ctl
->hostName
, ctl
->port
);
774 uri
= g_strdup_printf("ldap://%s:%d", ctl
->hostName
, ctl
->port
);
776 ldap_initialize(&ld
, uri
);
778 ld
= ldap_sslinit(ctl
->hostName
, ctl
->port
, ctl
->enableSSL
);
779 if (ld
&& ctl
->enableSSL
) {
780 version
= LDAP_VERSION3
;
781 debug_print("Setting version 3\n");
782 rc
= ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
, (void *)&version
);
783 if (rc
== LDAP_SUCCESS
) {
784 ctl
->version
= LDAP_VERSION3
;
785 log_print(LOG_PROTOCOL
, "LDAP (options): set version 3\n");
787 log_error(LOG_PROTOCOL
, _("LDAP error (options): %d (%s)\n"),
788 rc
, ldaputil_get_error(ld
));
789 debug_print("Failed: %s\n", ldaputil_get_error(ld
));
792 rc
= ldap_get_option(ld
, LDAP_OPT_SSL
, (void*)&op
);
793 if (rc
!= LDAP_SUCCESS
) {
794 log_warning(LOG_PROTOCOL
, _("LDAP warning (options): can't get SSL/TLS state\n"));
795 debug_print("Can't get SSL/TLS state\n");
798 if ((void *)op
!= LDAP_OPT_ON
) {
799 debug_print("Enabling SSL/TLS\n");
800 rc
= ldap_set_option(ld
, LDAP_OPT_SSL
, LDAP_OPT_ON
);
801 if (rc
!= LDAP_SUCCESS
) {
802 log_error(LOG_PROTOCOL
, _("LDAP error (options): %d (%s)\n"),
803 rc
, ldaputil_get_error(ld
));
804 debug_print("Failed: %s\n", ldaputil_get_error(ld
));
806 rc
= ldap_get_option(ld
, LDAP_OPT_SSL
, (void*)&op
);
807 if (rc
!= LDAP_SUCCESS
) {
808 log_error(LOG_PROTOCOL
, _("LDAP error (options): %d (%s)\n"),
809 rc
, ldaputil_get_error(ld
));
811 log_print(LOG_PROTOCOL
, _("LDAP (options): SSL/TLS enabled (%d)\n"), (gint
)op
);
813 debug_print("SSL/TLS now %d\n", (gint
)op
);
817 if (!ld
|| (rc
= ldap_connect(ld
, NULL
)) != LDAP_SUCCESS
) {
818 log_error(LOG_PROTOCOL
, _("LDAP error (connect): %d (%s)\n"),
819 rc
, ldaputil_get_error(ld
));
820 debug_print("ldap_connect failed: %d %s\n", rc
, ldaputil_get_error(ld
));
822 log_print(LOG_PROTOCOL
, _("LDAP (connect): completed successfully\n"));
831 debug_print("Got handle to LDAP host %s on port %d\n", ctl
->hostName
, ctl
->port
);
833 version
= LDAP_VERSION3
;
834 debug_print("Setting version 3\n");
835 rc
= ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
836 if (rc
== LDAP_OPT_SUCCESS
) {
837 ctl
->version
= LDAP_VERSION3
;
838 log_print(LOG_PROTOCOL
, "LDAP (options): set version 3\n");
840 log_error(LOG_PROTOCOL
, _("LDAP error (options): %d (%s)\n"),
841 rc
, ldaputil_get_error(ld
));
844 #if (defined USE_LDAP_TLS || defined G_OS_WIN32)
846 if (ctl
->version
== LDAP_VERSION3
) {
847 if (ctl
->enableTLS
&& !ctl
->enableSSL
) {
850 if (Win32_ldap_start_tls_s
== NULL
) {
851 void *lib
= LoadLibrary("wldap32.dll");
852 if (!lib
|| (Win32_ldap_start_tls_s
= (PFldap_start_tls_s
) GetProcAddress(lib
, LDAP_START_TLS_S
)) == NULL
) {
853 log_error(LOG_PROTOCOL
, _("LDAP error (TLS): "
854 "ldap_start_tls_s not supported on this platform\n"));
860 debug_print("Setting STARTTLS\n");
861 rc
= Win32_ldap_start_tls_s(ld
, &serv_rc
, NULL
, NULL
, NULL
);
862 debug_print("ldap_start_tls_s: %d server %ld %s\n",
863 rc
, serv_rc
, ldaputil_get_error(ld
));
865 debug_print("Setting STARTTLS\n");
866 rc
= ldap_start_tls_s(ld
, NULL
, NULL
);
868 if (rc
!= LDAP_SUCCESS
) {
869 log_error(LOG_PROTOCOL
, _("LDAP error (TLS): ldap_start_tls_s: %d (%s)\n"),
870 rc
, ldaputil_get_error(ld
));
873 log_print(LOG_PROTOCOL
, _("LDAP (TLS): started successfully\n"));
874 debug_print("Done\n");
880 /* Bind to the server, if required */
882 if (* ctl
->bindDN
!= '\0') {
883 pwd
= passwd_store_get(PWS_CORE
, "LDAP", ctl
->hostName
);
884 rc
= claws_ldap_simple_bind_s(ld
, ctl
->bindDN
, pwd
);
885 if (pwd
!= NULL
&& strlen(pwd
) > 0)
886 memset(pwd
, 0, strlen(pwd
));
888 if (rc
!= LDAP_SUCCESS
) {
889 log_error(LOG_PROTOCOL
, _("LDAP error (bind): binding DN '%s': %d (%s)\n" ),
890 ctl
->bindDN
, rc
, ldaputil_get_error(ld
));
893 log_print(LOG_PROTOCOL
, _("LDAP (bind): successfully for DN '%s'\n"),
901 * Disconnect to LDAP server.
902 * \param ld Resource to LDAP.
904 void ldapsvr_disconnect(LDAP
*ld
) {
907 cm_return_if_fail(ld
!= NULL
);
908 rc
= ldap_unbind_ext(ld
, NULL
, NULL
);
909 if (rc
!= LDAP_SUCCESS
) {
910 log_error(LOG_PROTOCOL
, _("LDAP error (unbind): %d (%s)\n"),
911 rc
, ldaputil_get_error(ld
));
913 log_print(LOG_PROTOCOL
, _("LDAP (unbind): successful\n"));
917 #endif /* USE_LDAP */