xref: /freebsd/crypto/krb5/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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