1 /*
2  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * lib/kdb/kdb_ldap/kdb_ldap.h
8  *
9  * Copyright (c) 2004-2005, Novell, Inc.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  *   * Redistributions of source code must retain the above copyright notice,
16  *       this list of conditions and the following disclaimer.
17  *   * Redistributions in binary form must reproduce the above copyright
18  *       notice, this list of conditions and the following disclaimer in the
19  *       documentation and/or other materials provided with the distribution.
20  *   * The copyright holder's name is not used to endorse or promote products
21  *       derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /* */
37 #ifndef _KDB_LDAP_H
38 #define _KDB_LDAP_H 1
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /* We want the interfaces marked "deprecated" in OpenLDAP.  */
43 #define LDAP_DEPRECATED 1
44 #include <ldap.h>
45 
46 /* Check for acceptable versions.
47 
48    OpenLDAP version 2.2.6 is known to have some kind of problem that
49    is tickled by the use of multiple handles in this code.  Version
50    2.2.19 in Mac OS 10.4.7 seems to be buggy as well.  Version 2.2.24
51    doesn't have this problem.  Other in-between versions have not been
52    tested.  */
53 #ifndef BUILD_WITH_BROKEN_LDAP
54 # if defined(LDAP_API_FEATURE_X_OPENLDAP)
55 #  if LDAP_VENDOR_VERSION < 20224
56 #   error This code triggers bugs in old OpenLDAP implementations.  Please update to 2.2.24 or later.
57 #  endif
58 # endif
59 #endif /* BUILD_WITH_BROKEN_LDAP */
60 
61 #include <k5-thread.h>
62 #include <k5-platform.h> /* Solaris Kerberos */
63 #include <kdb5.h>
64 #include "k5-int.h"
65 #include "ldap_krbcontainer.h"
66 #include "ldap_realm.h"
67 
68 extern struct timeval timelimit;
69 
70 /* Solaris Kerberos: need this define to get around sccs keyword expansion */
71 #define  DATE_FORMAT "%Y" "%m" "%d" "%H" "%M" "%SZ"
72 
73 #define  SERV_COUNT                  100
74 #define  DEFAULT_CONNS_PER_SERVER    5
75 #define  REALM_READ_REFRESH_INTERVAL (5 * 60)
76 
77 #ifdef HAVE_EDIRECTORY
78 #define  SECURITY_CONTAINER "cn=Security"
79 #define  KERBEROS_CONTAINER "cn=Kerberos,cn=Security"
80 #endif
81 
82 #if !defined(LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER)
83 #define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER
84 #endif
85 
86 #define NEG(val)   (val <0) ? abs(val) : -val ;
87 #define MAXINTLEN  10
88 
89 #define IGNORE_STATUS              0
90 #define CHECK_STATUS               1
91 
92 #define SETUP_CONTEXT() if (context == NULL || context->db_context == NULL \
93             || ((kdb5_dal_handle *)context->db_context)->db_context == NULL) { \
94         return EINVAL; \
95     } \
96     dal_handle = (kdb5_dal_handle *)context->db_context; \
97     ldap_context = (krb5_ldap_context *) dal_handle->db_context; \
98     if (ldap_context == NULL || ldap_context->server_info_list == NULL) \
99         return KRB5_KDB_DBNOTINITED;
100 
101 #define GET_HANDLE()  ld = NULL; \
102     st = krb5_ldap_request_handle_from_pool(ldap_context, &ldap_server_handle); \
103     if (st != 0) { \
104         prepend_err_str(context, "LDAP handle unavailable: ", KRB5_KDB_ACCESS_ERROR, st); \
105         st = KRB5_KDB_ACCESS_ERROR; \
106         goto cleanup; \
107     } \
108     ld = ldap_server_handle->ldap_handle;
109 
110 extern int set_ldap_error (krb5_context ctx, int st, int op);
111 extern void prepend_err_str (krb5_context ctx, const char *s, krb5_error_code err, krb5_error_code oerr);
112 
113 #define LDAP_SEARCH(base, scope, filter, attrs)   LDAP_SEARCH_1(base, scope, filter, attrs, CHECK_STATUS)
114 
115 #define LDAP_SEARCH_1(base, scope, filter, attrs, status_check)        \
116       do { \
117 	  st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, NULL, &timelimit, LDAP_NO_LIMIT, &result); \
118 	  if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
119               tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
120 	      if (ldap_server_handle) \
121 		  ld = ldap_server_handle->ldap_handle; \
122 	  } \
123       }while (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR && tempst == 0); \
124       \
125       if (status_check != IGNORE_STATUS) { \
126         if (tempst != 0) { \
127             prepend_err_str(context, "LDAP handle unavailable: ", KRB5_KDB_ACCESS_ERROR, st); \
128             st = KRB5_KDB_ACCESS_ERROR; \
129             goto cleanup; \
130         } \
131         if (st != LDAP_SUCCESS) { \
132 	     st = set_ldap_error(context, st, OP_SEARCH); \
133 	     goto cleanup; \
134         } \
135       }
136 
137 
138 #define CHECK_CLASS_VALIDITY(st, mask, str) \
139 	if (st != 0 || mask == 0) { \
140 	    if (st == 0 && mask == 0) { \
141 	       st = set_ldap_error(context, LDAP_OBJECT_CLASS_VIOLATION, OP_SEARCH); \
142 	    } \
143 	    prepend_err_str(context, str, st, st); \
144 	    goto cleanup; \
145 	 }
146 
147 #define CHECK_NULL(ptr) if (ptr == NULL) { \
148                             st = ENOMEM; \
149                             goto cleanup; \
150                         }
151 
152 #define  STORE16_INT(ptr, val)	store_16_be(val, ptr)
153 #define  STORE32_INT(ptr, val)  store_32_be(val, ptr)
154 #define UNSTORE16_INT(ptr, val) (val = load_16_be(ptr))
155 #define UNSTORE32_INT(ptr, val) (val = load_32_be(ptr))
156 
157 #define KRB5_CONF_KDC_BIND_DN "ldap_kdc_dn"
158 #define KRB5_CONF_ADMIN_BIND_DN "ldap_kadmind_dn"
159 #define KRB5_CONF_PWD_BIND_DN "ldap_passwd_dn"
160 
161 #define  KDB_TL_USER_INFO      0x7ffe
162 
163 #define KDB_TL_PRINCTYPE          0x01
164 #define KDB_TL_PRINCCOUNT         0x02
165 #define KDB_TL_USERDN             0x03
166 #define KDB_TL_KEYINFO            0x04
167 #define KDB_TL_MASK               0x05
168 #define KDB_TL_CONTAINERDN        0x06
169 #define KDB_TL_LINKDN             0x07
170 
171 
172 #define CHECK_LDAP_HANDLE(lcontext)     if (!(ldap_context \
173 					      && ldap_context->server_info_list)) { \
174 					  return KRB5_KDB_DBNOTINITED; \
175 					}
176 
177 #define HNDL_LOCK(lcontext) k5_mutex_lock(&lcontext->hndl_lock)
178 #define HNDL_UNLOCK(lcontext) k5_mutex_unlock(&lcontext->hndl_lock)
179 
180 /* To be used later */
181 typedef struct _krb5_ldap_certificates{
182     char *certificate;
183     int  certtype;
184 }krb5_ldap_certificates;
185 
186 /* ldap server info structure */
187 
188 typedef enum _server_type {PRIMARY, SECONDARY} krb5_ldap_server_type;
189 
190 typedef enum _server_status {OFF, ON, NOTSET} krb5_ldap_server_status;
191 
192 typedef struct _krb5_ldap_server_info krb5_ldap_server_info;
193 
194 typedef struct  _krb5_ldap_server_handle {
195     int                              msgid;
196     LDAP                             *ldap_handle;
197     krb5_boolean                     server_info_update_pending;
198     krb5_ldap_server_info            *server_info;
199     struct _krb5_ldap_server_handle  *next;
200 } krb5_ldap_server_handle;
201 
202 struct _krb5_ldap_server_info {
203     krb5_ldap_server_type	 server_type;
204     krb5_ldap_server_status      server_status;
205     krb5_ui_4                    num_conns;
206     krb5_ldap_server_handle      *ldap_server_handles;
207     time_t                       downtime;
208     char			*server_name;
209 #ifdef HAVE_EDIRECTORY
210     char			*root_certificate_file;
211 #endif
212     struct _krb5_ldap_server_info *next;
213 };
214 
215 
216 /* ldap server structure */
217 
218 typedef enum {SERVICE_DN_TYPE_SERVER, SERVICE_DN_TYPE_CLIENT} krb5_ldap_servicetype;
219 
220 typedef struct _krb5_ldap_context {
221   krb5_ldap_servicetype         service_type;
222   krb5_ldap_server_info         **server_info_list;
223   krb5_ui_4                     max_server_conns;
224   char                          *conf_section;
225   char 		                *bind_dn;
226   char                          *bind_pwd;
227   char 		                *service_password_file;
228   char 		                *root_certificate_file;
229   char                          *service_cert_path;
230   char                          *service_cert_pass;
231   krb5_ldap_certificates        **certificates;
232   krb5_ui_4                     cert_count; /* certificate count */
233   k5_mutex_t                    hndl_lock;
234   krb5_ldap_krbcontainer_params *krbcontainer;
235   krb5_ldap_realm_params        *lrparams;
236   krb5_context                  kcontext;   /* to set the error code and message */
237 } krb5_ldap_context;
238 
239 
240 typedef struct {
241   int           nkey;
242   struct berval **keys;
243 }KEY;
244 
245 #define k5ldap_inited(c) (c && c->db_context \
246                          && ((kdb5_dal_handle*)c->db_context)->db_context \
247                          && ((krb5_ldap_context *) ((kdb5_dal_handle*)c->db_context)->db_context))
248 
249 
250 /* misc functions */
251 
252 krb5_error_code
253 krb5_ldap_db_init(krb5_context, krb5_ldap_context *);
254 
255 krb5_error_code
256 krb5_ldap_db_single_init(krb5_ldap_context *);
257 
258 krb5_error_code
259 krb5_ldap_rebind(krb5_ldap_context *, krb5_ldap_server_handle **);
260 
261 krb5_error_code
262 krb5_ldap_db_get_age(krb5_context, char *, time_t *);
263 
264 krb5_error_code
265 krb5_ldap_lib_init(void);
266 
267 krb5_error_code
268 krb5_ldap_lib_cleanup(void);
269 
270 void *
271 krb5_ldap_alloc( krb5_context kcontext,  void *ptr, size_t size );
272 
273 void
274 krb5_ldap_free( krb5_context kcontext, void *ptr );
275 krb5_error_code
276 krb5_ldap_get_mkey(krb5_context, krb5_keyblock **);
277 
278 krb5_error_code
279 krb5_ldap_set_mkey(krb5_context, char *, krb5_keyblock *);
280 
281 krb5_error_code
282 krb5_ldap_create(krb5_context , char *, char **);
283 
284 krb5_error_code
285 krb5_ldap_open( krb5_context , char *,
286 		char **db_args,
287 		int mode );
288 krb5_error_code
289 krb5_ldap_close( krb5_context );
290 
291 krb5_error_code
292 krb5_ldap_free_ldap_context(krb5_ldap_context *);
293 
294 krb5_error_code
295 krb5_ldap_read_startup_information(krb5_context );
296 
297 int
298 has_sasl_external_mech(krb5_context, char *);
299 
300 /* DAL functions */
301 
302 
303 krb5_error_code
304 krb5_ldap_set_option( krb5_context, int, void * );
305 
306 krb5_error_code
307 krb5_ldap_lock( krb5_context, int );
308 
309 krb5_error_code
310 krb5_ldap_unlock( krb5_context );
311 
312 krb5_error_code
313 krb5_ldap_supported_realms( krb5_context, char ** );
314 
315 krb5_error_code
316 krb5_ldap_free_supported_realms( krb5_context, char ** );
317 
318 const char *
319 krb5_ldap_errcode_2_string( krb5_context, long );
320 
321 void
322 krb5_ldap_release_errcode_string (krb5_context, const char *);
323 
324 #ifndef HAVE_LDAP_INITIALIZE
325 /* Solaris Kerberos: added a use_SSL parameter */
326 int
327 ldap_initialize(LDAP **, char *, int, char **);
328 #endif
329 #ifndef HAVE_LDAP_UNBIND_EXT_S
330 int
331 ldap_unbind_ext_s(LDAP *, LDAPControl **, LDAPControl **);
332 #endif
333 
334 #endif
335