1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* plugins/kdb/ldap/libkdb_ldap/ldap_handle.c */
3 /*
4 * Copyright (c) 2004-2005, Novell, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * The copyright holder's name is not used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "ldap_main.h"
32
33 /*
34 * Return ldap server handle from the pool. If the pool is exhausted return NULL.
35 * Do not lock the mutex, caller should lock it
36 */
37
38 static krb5_ldap_server_handle *
krb5_get_ldap_handle(krb5_ldap_context * ldap_context)39 krb5_get_ldap_handle(krb5_ldap_context *ldap_context)
40 {
41 krb5_ldap_server_handle *ldap_server_handle=NULL;
42 krb5_ldap_server_info *ldap_server_info=NULL;
43 int cnt=0;
44
45 while (ldap_context->server_info_list[cnt] != NULL) {
46 ldap_server_info = ldap_context->server_info_list[cnt];
47 if (ldap_server_info->server_status != OFF) {
48 if (ldap_server_info->ldap_server_handles != NULL) {
49 ldap_server_handle = ldap_server_info->ldap_server_handles;
50 ldap_server_info->ldap_server_handles = ldap_server_handle->next;
51 break;
52 }
53 }
54 ++cnt;
55 }
56 return ldap_server_handle;
57 }
58
59 /*
60 * This is called in case krb5_get_ldap_handle returns NULL.
61 * Try getting a single connection (handle) and return the same by
62 * calling krb5_get_ldap_handle function.
63 * Do not lock the mutex here. The caller should lock it
64 */
65
66 static krb5_ldap_server_handle *
krb5_retry_get_ldap_handle(krb5_ldap_context * ldap_context,krb5_error_code * st)67 krb5_retry_get_ldap_handle(krb5_ldap_context *ldap_context,
68 krb5_error_code *st)
69 {
70 krb5_ldap_server_handle *ldap_server_handle=NULL;
71
72 if ((*st=krb5_ldap_db_single_init(ldap_context)) != 0)
73 return NULL;
74
75 ldap_server_handle = krb5_get_ldap_handle(ldap_context);
76 return ldap_server_handle;
77 }
78
79 /*
80 * Put back the ldap server handle to the front of the list of handles of the
81 * ldap server info structure.
82 * Do not lock the mutex here. The caller should lock it.
83 */
84
85 static krb5_error_code
krb5_put_ldap_handle(krb5_ldap_server_handle * ldap_server_handle)86 krb5_put_ldap_handle(krb5_ldap_server_handle *ldap_server_handle)
87 {
88
89 if (ldap_server_handle == NULL)
90 return 0;
91
92 ldap_server_handle->next = ldap_server_handle->server_info->ldap_server_handles;
93 ldap_server_handle->server_info->ldap_server_handles = ldap_server_handle;
94 return 0;
95 }
96
97 /*
98 * Free up all the ldap server handles of the server info.
99 * This function is called when the ldap server returns LDAP_SERVER_DOWN.
100 */
101
102 static krb5_error_code
krb5_ldap_cleanup_handles(krb5_ldap_server_info * ldap_server_info)103 krb5_ldap_cleanup_handles(krb5_ldap_server_info *ldap_server_info)
104 {
105 krb5_ldap_server_handle *ldap_server_handle = NULL;
106
107 while (ldap_server_info->ldap_server_handles != NULL) {
108 ldap_server_handle = ldap_server_info->ldap_server_handles;
109 ldap_server_info->ldap_server_handles = ldap_server_handle->next;
110 /* ldap_unbind_s(ldap_server_handle); */
111 free (ldap_server_handle);
112 ldap_server_handle = NULL;
113 }
114 return 0;
115 }
116
117 /*
118 * wrapper function called from outside to get a handle.
119 */
120
121 krb5_error_code
krb5_ldap_request_handle_from_pool(krb5_ldap_context * ldap_context,krb5_ldap_server_handle ** ldap_server_handle)122 krb5_ldap_request_handle_from_pool(krb5_ldap_context *ldap_context,
123 krb5_ldap_server_handle **
124 ldap_server_handle)
125 {
126 krb5_error_code st=0;
127
128 *ldap_server_handle = NULL;
129
130 HNDL_LOCK(ldap_context);
131 if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
132 (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
133 HNDL_UNLOCK(ldap_context);
134 return st;
135 }
136
137 /*
138 * wrapper function wrapper called to get the next ldap server handle, when the current
139 * ldap server handle returns LDAP_SERVER_DOWN.
140 */
141
142 krb5_error_code
krb5_ldap_request_next_handle_from_pool(krb5_ldap_context * ldap_context,krb5_ldap_server_handle ** ldap_server_handle)143 krb5_ldap_request_next_handle_from_pool(krb5_ldap_context *ldap_context,
144 krb5_ldap_server_handle **
145 ldap_server_handle)
146 {
147 krb5_error_code st=0;
148
149 HNDL_LOCK(ldap_context);
150 (*ldap_server_handle)->server_info->server_status = OFF;
151 time(&(*ldap_server_handle)->server_info->downtime);
152 krb5_put_ldap_handle(*ldap_server_handle);
153 krb5_ldap_cleanup_handles((*ldap_server_handle)->server_info);
154
155 if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
156 (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
157 HNDL_UNLOCK(ldap_context);
158 return st;
159 }
160
161 /*
162 * wrapper function to call krb5_put_ldap_handle.
163 */
164
165 void
krb5_ldap_put_handle_to_pool(krb5_ldap_context * ldap_context,krb5_ldap_server_handle * ldap_server_handle)166 krb5_ldap_put_handle_to_pool(krb5_ldap_context *ldap_context,
167 krb5_ldap_server_handle *ldap_server_handle)
168 {
169 if (ldap_server_handle != NULL) {
170 HNDL_LOCK(ldap_context);
171 krb5_put_ldap_handle(ldap_server_handle);
172 HNDL_UNLOCK(ldap_context);
173 }
174 return;
175 }
176