1*54925bf6Swillf /*
2*54925bf6Swillf * lib/kdb/kdb_ldap/ldap_handle.c
3*54925bf6Swillf *
4*54925bf6Swillf * Copyright (c) 2004-2005, Novell, Inc.
5*54925bf6Swillf * All rights reserved.
6*54925bf6Swillf *
7*54925bf6Swillf * Redistribution and use in source and binary forms, with or without
8*54925bf6Swillf * modification, are permitted provided that the following conditions are met:
9*54925bf6Swillf *
10*54925bf6Swillf * * Redistributions of source code must retain the above copyright notice,
11*54925bf6Swillf * this list of conditions and the following disclaimer.
12*54925bf6Swillf * * Redistributions in binary form must reproduce the above copyright
13*54925bf6Swillf * notice, this list of conditions and the following disclaimer in the
14*54925bf6Swillf * documentation and/or other materials provided with the distribution.
15*54925bf6Swillf * * The copyright holder's name is not used to endorse or promote products
16*54925bf6Swillf * derived from this software without specific prior written permission.
17*54925bf6Swillf *
18*54925bf6Swillf * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*54925bf6Swillf * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*54925bf6Swillf * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*54925bf6Swillf * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22*54925bf6Swillf * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*54925bf6Swillf * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*54925bf6Swillf * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*54925bf6Swillf * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*54925bf6Swillf * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*54925bf6Swillf * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*54925bf6Swillf * POSSIBILITY OF SUCH DAMAGE.
29*54925bf6Swillf */
30*54925bf6Swillf
31*54925bf6Swillf #include "ldap_main.h"
32*54925bf6Swillf
33*54925bf6Swillf
34*54925bf6Swillf #ifdef ASYNC_BIND
35*54925bf6Swillf
36*54925bf6Swillf /*
37*54925bf6Swillf * Update the server info structure. In case of an asynchronous bind,
38*54925bf6Swillf * this function is called to check the bind status. A flag
39*54925bf6Swillf * server_info_upate_pending is refered before calling this function.
40*54925bf6Swillf * This function sets the server_status to either ON or OFF and
41*54925bf6Swillf * sets the server_info_udpate_pending to OFF.
42*54925bf6Swillf * Do not lock the mutex here. The caller should lock it
43*54925bf6Swillf */
44*54925bf6Swillf
45*54925bf6Swillf static krb5_error_code
krb5_update_server_info(ldap_server_handle,server_info)46*54925bf6Swillf krb5_update_server_info(ldap_server_handle, server_info)
47*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle;
48*54925bf6Swillf krb5_ldap_server_info *server_info;
49*54925bf6Swillf {
50*54925bf6Swillf krb5_error_code st=0;
51*54925bf6Swillf struct timeval ztime={0, 0};
52*54925bf6Swillf LDAPMessage *result=NULL;
53*54925bf6Swillf
54*54925bf6Swillf if (ldap_server_handle == NULL || server_info == NULL)
55*54925bf6Swillf return -1;
56*54925bf6Swillf
57*54925bf6Swillf while (st == 0) {
58*54925bf6Swillf st = ldap_result(ldap_server_handle->ldap_handle, ldap_server_handle->msgid,
59*54925bf6Swillf LDAP_MSG_ALL, &ztime, &result);
60*54925bf6Swillf switch (st) {
61*54925bf6Swillf case -1:
62*54925bf6Swillf server_info->server_status = OFF;
63*54925bf6Swillf time(&server_info->downtime);
64*54925bf6Swillf break;
65*54925bf6Swillf
66*54925bf6Swillf case 0:
67*54925bf6Swillf continue;
68*54925bf6Swillf break;
69*54925bf6Swillf
70*54925bf6Swillf case LDAP_RES_BIND:
71*54925bf6Swillf if ((st=ldap_result2error(ldap_server_handle->ldap_handle, result, 1)) == LDAP_SUCCESS) {
72*54925bf6Swillf server_info->server_status = ON;
73*54925bf6Swillf } else {
74*54925bf6Swillf /* ?? */ krb5_set_error_message(0, 0, "%s", ldap_err2string(st));
75*54925bf6Swillf server_info->server_status = OFF;
76*54925bf6Swillf time(&server_info->downtime);
77*54925bf6Swillf }
78*54925bf6Swillf ldap_msgfree(result);
79*54925bf6Swillf break;
80*54925bf6Swillf default:
81*54925bf6Swillf ldap_msgfree(result);
82*54925bf6Swillf continue;
83*54925bf6Swillf break;
84*54925bf6Swillf }
85*54925bf6Swillf }
86*54925bf6Swillf ldap_server_handle->server_info_update_pending = FALSE;
87*54925bf6Swillf return 0;
88*54925bf6Swillf }
89*54925bf6Swillf #endif
90*54925bf6Swillf
91*54925bf6Swillf /*
92*54925bf6Swillf * Return ldap server handle from the pool. If the pool is exhausted return NULL.
93*54925bf6Swillf * Do not lock the mutex, caller should lock it
94*54925bf6Swillf */
95*54925bf6Swillf
96*54925bf6Swillf static krb5_ldap_server_handle *
krb5_get_ldap_handle(ldap_context)97*54925bf6Swillf krb5_get_ldap_handle(ldap_context)
98*54925bf6Swillf krb5_ldap_context *ldap_context;
99*54925bf6Swillf {
100*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle=NULL;
101*54925bf6Swillf krb5_ldap_server_info *ldap_server_info=NULL;
102*54925bf6Swillf int cnt=0;
103*54925bf6Swillf
104*54925bf6Swillf while (ldap_context->server_info_list[cnt] != NULL) {
105*54925bf6Swillf ldap_server_info = ldap_context->server_info_list[cnt];
106*54925bf6Swillf if (ldap_server_info->server_status != OFF) {
107*54925bf6Swillf if (ldap_server_info->ldap_server_handles != NULL) {
108*54925bf6Swillf ldap_server_handle = ldap_server_info->ldap_server_handles;
109*54925bf6Swillf ldap_server_info->ldap_server_handles = ldap_server_handle->next;
110*54925bf6Swillf break;
111*54925bf6Swillf #ifdef ASYNC_BIND
112*54925bf6Swillf if (ldap_server_handle->server_info_update_pending == TRUE) {
113*54925bf6Swillf krb5_update_server_info(context, ldap_server_handle,
114*54925bf6Swillf ldap_server_info);
115*54925bf6Swillf }
116*54925bf6Swillf
117*54925bf6Swillf if (ldap_server_info->server_status == ON) {
118*54925bf6Swillf ldap_server_info->ldap_server_handles = ldap_server_handle->next;
119*54925bf6Swillf break;
120*54925bf6Swillf } else
121*54925bf6Swillf ldap_server_handle = NULL;
122*54925bf6Swillf #endif
123*54925bf6Swillf }
124*54925bf6Swillf }
125*54925bf6Swillf ++cnt;
126*54925bf6Swillf }
127*54925bf6Swillf return ldap_server_handle;
128*54925bf6Swillf }
129*54925bf6Swillf
130*54925bf6Swillf /*
131*54925bf6Swillf * This is called incase krb5_get_ldap_handle returns NULL.
132*54925bf6Swillf * Try getting a single connection (handle) and return the same by
133*54925bf6Swillf * calling krb5_get_ldap_handle function.
134*54925bf6Swillf * Do not lock the mutex here. The caller should lock it
135*54925bf6Swillf */
136*54925bf6Swillf
137*54925bf6Swillf static krb5_ldap_server_handle *
krb5_retry_get_ldap_handle(ldap_context,st)138*54925bf6Swillf krb5_retry_get_ldap_handle(ldap_context, st)
139*54925bf6Swillf krb5_ldap_context *ldap_context;
140*54925bf6Swillf krb5_error_code *st;
141*54925bf6Swillf {
142*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle=NULL;
143*54925bf6Swillf
144*54925bf6Swillf if ((*st=krb5_ldap_db_single_init(ldap_context)) != 0)
145*54925bf6Swillf return NULL;
146*54925bf6Swillf
147*54925bf6Swillf ldap_server_handle = krb5_get_ldap_handle(ldap_context);
148*54925bf6Swillf return ldap_server_handle;
149*54925bf6Swillf }
150*54925bf6Swillf
151*54925bf6Swillf /*
152*54925bf6Swillf * Put back the ldap server handle to the front of the list of handles of the
153*54925bf6Swillf * ldap server info structure.
154*54925bf6Swillf * Do not lock the mutex here. The caller should lock it.
155*54925bf6Swillf */
156*54925bf6Swillf
157*54925bf6Swillf static krb5_error_code
krb5_put_ldap_handle(ldap_server_handle)158*54925bf6Swillf krb5_put_ldap_handle(ldap_server_handle)
159*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle;
160*54925bf6Swillf {
161*54925bf6Swillf
162*54925bf6Swillf if (ldap_server_handle == NULL)
163*54925bf6Swillf return 0;
164*54925bf6Swillf
165*54925bf6Swillf ldap_server_handle->next = ldap_server_handle->server_info->ldap_server_handles;
166*54925bf6Swillf ldap_server_handle->server_info->ldap_server_handles = ldap_server_handle;
167*54925bf6Swillf return 0;
168*54925bf6Swillf }
169*54925bf6Swillf
170*54925bf6Swillf /*
171*54925bf6Swillf * Add a new ldap server handle structure to the server info structure.
172*54925bf6Swillf * This function name can be changed to krb5_insert_ldap_handle.
173*54925bf6Swillf * Do not lock the mutex here. The caller should lock it
174*54925bf6Swillf */
175*54925bf6Swillf
176*54925bf6Swillf krb5_error_code
krb5_update_ldap_handle(ldap_server_handle,server_info)177*54925bf6Swillf krb5_update_ldap_handle(ldap_server_handle, server_info)
178*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle;
179*54925bf6Swillf krb5_ldap_server_info *server_info;
180*54925bf6Swillf {
181*54925bf6Swillf
182*54925bf6Swillf if (ldap_server_handle == NULL || server_info == NULL)
183*54925bf6Swillf return 0;
184*54925bf6Swillf
185*54925bf6Swillf ldap_server_handle->next = server_info->ldap_server_handles;
186*54925bf6Swillf server_info->ldap_server_handles = ldap_server_handle;
187*54925bf6Swillf server_info->num_conns++;
188*54925bf6Swillf ldap_server_handle->server_info = server_info;
189*54925bf6Swillf return 0;
190*54925bf6Swillf }
191*54925bf6Swillf
192*54925bf6Swillf /*
193*54925bf6Swillf * Free up all the ldap server handles of the server info.
194*54925bf6Swillf * This function is called when the ldap server returns LDAP_SERVER_DOWN.
195*54925bf6Swillf */
196*54925bf6Swillf
197*54925bf6Swillf static krb5_error_code
krb5_ldap_cleanup_handles(ldap_server_info)198*54925bf6Swillf krb5_ldap_cleanup_handles(ldap_server_info)
199*54925bf6Swillf krb5_ldap_server_info *ldap_server_info;
200*54925bf6Swillf {
201*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle = NULL;
202*54925bf6Swillf
203*54925bf6Swillf while (ldap_server_info->ldap_server_handles != NULL) {
204*54925bf6Swillf ldap_server_handle = ldap_server_info->ldap_server_handles;
205*54925bf6Swillf ldap_server_info->ldap_server_handles = ldap_server_handle->next;
206*54925bf6Swillf /* Solaris kerberos: don't leak ldap handles */
207*54925bf6Swillf ldap_unbind_s(ldap_server_handle->ldap_handle);
208*54925bf6Swillf free (ldap_server_handle);
209*54925bf6Swillf ldap_server_handle = NULL;
210*54925bf6Swillf }
211*54925bf6Swillf return 0;
212*54925bf6Swillf }
213*54925bf6Swillf
214*54925bf6Swillf /*
215*54925bf6Swillf * wrapper function called from outside to get a handle.
216*54925bf6Swillf */
217*54925bf6Swillf
218*54925bf6Swillf krb5_error_code
krb5_ldap_request_handle_from_pool(ldap_context,ldap_server_handle)219*54925bf6Swillf krb5_ldap_request_handle_from_pool(ldap_context, ldap_server_handle)
220*54925bf6Swillf krb5_ldap_context *ldap_context;
221*54925bf6Swillf krb5_ldap_server_handle **ldap_server_handle;
222*54925bf6Swillf {
223*54925bf6Swillf krb5_error_code st=0;
224*54925bf6Swillf
225*54925bf6Swillf *ldap_server_handle = NULL;
226*54925bf6Swillf
227*54925bf6Swillf HNDL_LOCK(ldap_context);
228*54925bf6Swillf if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
229*54925bf6Swillf (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
230*54925bf6Swillf HNDL_UNLOCK(ldap_context);
231*54925bf6Swillf return st;
232*54925bf6Swillf }
233*54925bf6Swillf
234*54925bf6Swillf /*
235*54925bf6Swillf * wrapper function wrapper called to get the next ldap server handle, when the current
236*54925bf6Swillf * ldap server handle returns LDAP_SERVER_DOWN.
237*54925bf6Swillf */
238*54925bf6Swillf
239*54925bf6Swillf krb5_error_code
krb5_ldap_request_next_handle_from_pool(ldap_context,ldap_server_handle)240*54925bf6Swillf krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle)
241*54925bf6Swillf krb5_ldap_context *ldap_context;
242*54925bf6Swillf krb5_ldap_server_handle **ldap_server_handle;
243*54925bf6Swillf {
244*54925bf6Swillf krb5_error_code st=0;
245*54925bf6Swillf
246*54925bf6Swillf HNDL_LOCK(ldap_context);
247*54925bf6Swillf (*ldap_server_handle)->server_info->server_status = OFF;
248*54925bf6Swillf time(&(*ldap_server_handle)->server_info->downtime);
249*54925bf6Swillf krb5_put_ldap_handle(*ldap_server_handle);
250*54925bf6Swillf krb5_ldap_cleanup_handles((*ldap_server_handle)->server_info);
251*54925bf6Swillf
252*54925bf6Swillf if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
253*54925bf6Swillf (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
254*54925bf6Swillf HNDL_UNLOCK(ldap_context);
255*54925bf6Swillf return st;
256*54925bf6Swillf }
257*54925bf6Swillf
258*54925bf6Swillf /*
259*54925bf6Swillf * wrapper function to call krb5_put_ldap_handle.
260*54925bf6Swillf */
261*54925bf6Swillf
262*54925bf6Swillf void
krb5_ldap_put_handle_to_pool(ldap_context,ldap_server_handle)263*54925bf6Swillf krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle)
264*54925bf6Swillf krb5_ldap_context *ldap_context;
265*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle;
266*54925bf6Swillf {
267*54925bf6Swillf
268*54925bf6Swillf if (ldap_server_handle != NULL) {
269*54925bf6Swillf HNDL_LOCK(ldap_context);
270*54925bf6Swillf krb5_put_ldap_handle(ldap_server_handle);
271*54925bf6Swillf HNDL_UNLOCK(ldap_context);
272*54925bf6Swillf }
273*54925bf6Swillf return;
274*54925bf6Swillf }
275*54925bf6Swillf
276