xref: /illumos-gate/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
154925bf6Swillf /*
2*7c64d375Smp153739  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
354925bf6Swillf  * Use is subject to license terms.
454925bf6Swillf  */
554925bf6Swillf 
654925bf6Swillf 
754925bf6Swillf /*
854925bf6Swillf  * lib/kdb/kdb_ldap/kdb_ldap.c
954925bf6Swillf  *
1054925bf6Swillf  * Copyright (c) 2004-2005, Novell, Inc.
1154925bf6Swillf  * All rights reserved.
1254925bf6Swillf  *
1354925bf6Swillf  * Redistribution and use in source and binary forms, with or without
1454925bf6Swillf  * modification, are permitted provided that the following conditions are met:
1554925bf6Swillf  *
1654925bf6Swillf  *   * Redistributions of source code must retain the above copyright notice,
1754925bf6Swillf  *       this list of conditions and the following disclaimer.
1854925bf6Swillf  *   * Redistributions in binary form must reproduce the above copyright
1954925bf6Swillf  *       notice, this list of conditions and the following disclaimer in the
2054925bf6Swillf  *       documentation and/or other materials provided with the distribution.
2154925bf6Swillf  *   * The copyright holder's name is not used to endorse or promote products
2254925bf6Swillf  *       derived from this software without specific prior written permission.
2354925bf6Swillf  *
2454925bf6Swillf  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2554925bf6Swillf  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2654925bf6Swillf  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2754925bf6Swillf  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2854925bf6Swillf  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2954925bf6Swillf  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3054925bf6Swillf  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3154925bf6Swillf  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3254925bf6Swillf  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3354925bf6Swillf  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3454925bf6Swillf  * POSSIBILITY OF SUCH DAMAGE.
3554925bf6Swillf  */
3654925bf6Swillf 
3754925bf6Swillf #include "autoconf.h"
3854925bf6Swillf #if HAVE_UNISTD_H
3954925bf6Swillf #include <unistd.h>
4054925bf6Swillf #endif
4154925bf6Swillf 
4254925bf6Swillf #include <ctype.h>
4354925bf6Swillf #include "kdb_ldap.h"
4454925bf6Swillf #include "ldap_misc.h"
4554925bf6Swillf #include "ldap_main.h"
4654925bf6Swillf #include <kdb5.h>
4754925bf6Swillf #include <kadm5/admin.h>
4854925bf6Swillf /* Solaris Kerberos: needed for MAKE_INIT_FUNCTION() */
4954925bf6Swillf #include <k5-platform.h>
5054925bf6Swillf #include <k5-int.h>
5154925bf6Swillf #include <libintl.h>
5254925bf6Swillf 
5354925bf6Swillf krb5_error_code
krb5_ldap_get_db_opt(char * input,char ** opt,char ** val)5454925bf6Swillf krb5_ldap_get_db_opt(char *input, char **opt, char **val)
5554925bf6Swillf {
5654925bf6Swillf     char *pos = strchr(input, '=');
5754925bf6Swillf 
5854925bf6Swillf     *val = NULL;
5954925bf6Swillf     if (pos == NULL) {
6054925bf6Swillf 	*opt = strdup(input);
6154925bf6Swillf 	if (*opt == NULL) {
6254925bf6Swillf 	    return ENOMEM;
6354925bf6Swillf 	}
6454925bf6Swillf     } else {
6554925bf6Swillf 	int len = pos - input;
6654925bf6Swillf 	*opt = malloc((unsigned) len + 1);
6754925bf6Swillf 	if (!*opt) {
6854925bf6Swillf 	    return ENOMEM;
6954925bf6Swillf 	}
7054925bf6Swillf 	memcpy(*opt, input, (unsigned) len);
7154925bf6Swillf 	/* ignore trailing blanks */
7254925bf6Swillf 	while (isblank((*opt)[len-1]))
7354925bf6Swillf 	    --len;
7454925bf6Swillf 	(*opt)[len] = '\0';
7554925bf6Swillf 
7654925bf6Swillf 	pos += 1; /* move past '=' */
7754925bf6Swillf 	while (isblank(*pos))  /* ignore leading blanks */
7854925bf6Swillf 	    pos += 1;
7954925bf6Swillf 	if (*pos != '\0') {
8054925bf6Swillf 	    *val = strdup (pos);
8154925bf6Swillf 	    if (!*val) {
8254925bf6Swillf 		free (*opt);
8354925bf6Swillf 		return ENOMEM;
8454925bf6Swillf 	    }
8554925bf6Swillf 	}
8654925bf6Swillf     }
8754925bf6Swillf     return (0);
8854925bf6Swillf 
8954925bf6Swillf }
9054925bf6Swillf 
9154925bf6Swillf 
9254925bf6Swillf /*
9354925bf6Swillf  * ldap get age
9454925bf6Swillf  */
9554925bf6Swillf /*ARGSUSED*/
9654925bf6Swillf krb5_error_code
krb5_ldap_db_get_age(context,db_name,age)9754925bf6Swillf krb5_ldap_db_get_age(context, db_name, age)
9854925bf6Swillf     krb5_context context;
9954925bf6Swillf     char *db_name;
10054925bf6Swillf     time_t *age;
10154925bf6Swillf {
10254925bf6Swillf     time (age);
10354925bf6Swillf     return 0;
10454925bf6Swillf }
10554925bf6Swillf 
10654925bf6Swillf /*
10754925bf6Swillf  * read startup information - kerberos and realm container
10854925bf6Swillf  */
10954925bf6Swillf krb5_error_code
krb5_ldap_read_startup_information(krb5_context context)11054925bf6Swillf krb5_ldap_read_startup_information(krb5_context context)
11154925bf6Swillf {
11254925bf6Swillf     krb5_error_code      retval = 0;
11354925bf6Swillf     kdb5_dal_handle      *dal_handle=NULL;
11454925bf6Swillf     krb5_ldap_context    *ldap_context=NULL;
11554925bf6Swillf     int                  mask = 0;
11654925bf6Swillf 
11754925bf6Swillf     SETUP_CONTEXT();
11854925bf6Swillf     if ((retval=krb5_ldap_read_krbcontainer_params(context, &(ldap_context->krbcontainer)))) {
11954925bf6Swillf 	prepend_err_str (context, gettext("Unable to read Kerberos container"), retval, retval);
12054925bf6Swillf 	goto cleanup;
12154925bf6Swillf     }
12254925bf6Swillf 
12354925bf6Swillf     if ((retval=krb5_ldap_read_realm_params(context, context->default_realm, &(ldap_context->lrparams), &mask))) {
12454925bf6Swillf 	prepend_err_str (context, gettext("Unable to read Realm"), retval, retval);
12554925bf6Swillf 	goto cleanup;
12654925bf6Swillf     }
12754925bf6Swillf 
12854925bf6Swillf     if (((mask & LDAP_REALM_MAXTICKETLIFE) == 0) || ((mask & LDAP_REALM_MAXRENEWLIFE) == 0)
12954925bf6Swillf                                                  || ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0)) {
13054925bf6Swillf         kadm5_config_params  params_in, params_out;
13154925bf6Swillf 
13254925bf6Swillf         memset((char *) &params_in, 0, sizeof(params_in));
13354925bf6Swillf         memset((char *) &params_out, 0, sizeof(params_out));
13454925bf6Swillf 
13554925bf6Swillf         retval = kadm5_get_config_params(context, 1, &params_in, &params_out);
13654925bf6Swillf         if (retval) {
13754925bf6Swillf             if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
13854925bf6Swillf                 ldap_context->lrparams->max_life = 24 * 60 * 60; /* 1 day */
13954925bf6Swillf             }
14054925bf6Swillf             if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
14154925bf6Swillf                 ldap_context->lrparams->max_renewable_life = 0;
14254925bf6Swillf             }
14354925bf6Swillf             if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
14454925bf6Swillf                 ldap_context->lrparams->tktflags = KRB5_KDB_DEF_FLAGS;
14554925bf6Swillf             }
14654925bf6Swillf             retval = 0;
14754925bf6Swillf             goto cleanup;
14854925bf6Swillf         }
14954925bf6Swillf 
15054925bf6Swillf         if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
15154925bf6Swillf             if (params_out.mask & KADM5_CONFIG_MAX_LIFE)
15254925bf6Swillf                 ldap_context->lrparams->max_life = params_out.max_life;
15354925bf6Swillf         }
15454925bf6Swillf 
15554925bf6Swillf         if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
15654925bf6Swillf             if (params_out.mask & KADM5_CONFIG_MAX_RLIFE)
15754925bf6Swillf                 ldap_context->lrparams->max_renewable_life = params_out.max_rlife;
15854925bf6Swillf         }
15954925bf6Swillf 
16054925bf6Swillf         if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
16154925bf6Swillf             if (params_out.mask & KADM5_CONFIG_FLAGS)
16254925bf6Swillf                 ldap_context->lrparams->tktflags = params_out.flags;
16354925bf6Swillf         }
16454925bf6Swillf 
16554925bf6Swillf         kadm5_free_config_params(context, &params_out);
16654925bf6Swillf     }
16754925bf6Swillf 
16854925bf6Swillf cleanup:
16954925bf6Swillf     return retval;
17054925bf6Swillf }
17154925bf6Swillf 
17254925bf6Swillf 
17354925bf6Swillf /* Function to check if a LDAP server supports the SASL external mechanism
17454925bf6Swillf  *Return values:
17554925bf6Swillf  *   0 => supports
17654925bf6Swillf  *   1 => does not support
17754925bf6Swillf  *   2 => don't know
17854925bf6Swillf  */
17954925bf6Swillf #define ERR_MSG1 "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. Proceeding anyway ..."
18054925bf6Swillf #define ERR_MSG2 "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform certificate-based bind."
18154925bf6Swillf 
18254925bf6Swillf int
has_sasl_external_mech(context,ldap_server)18354925bf6Swillf has_sasl_external_mech(context, ldap_server)
18454925bf6Swillf     krb5_context     context;
18554925bf6Swillf     char             *ldap_server;
18654925bf6Swillf {
18754925bf6Swillf     int               i=0, flag=0, ret=0, retval=0;
18854925bf6Swillf     char              *attrs[]={"supportedSASLMechanisms", NULL}, **values=NULL;
18954925bf6Swillf     LDAP              *ld=NULL;
19054925bf6Swillf     LDAPMessage       *msg=NULL, *res=NULL;
19154925bf6Swillf 
19254925bf6Swillf     /*
19354925bf6Swillf      * Solaris Kerberos: don't use SSL since we are checking to see if SASL
19454925bf6Swillf      * Externnal mech is supported.
19554925bf6Swillf      */
19654925bf6Swillf     retval = ldap_initialize(&ld, ldap_server, SSL_OFF, NULL);
19754925bf6Swillf     if (retval != LDAP_SUCCESS) {
19854925bf6Swillf 	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
19954925bf6Swillf 	ret = 2; /* Don't know */
20054925bf6Swillf 	goto cleanup;
20154925bf6Swillf     }
20254925bf6Swillf 
20354925bf6Swillf     /* Solaris Kerberos: anon bind not needed */
20454925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
20554925bf6Swillf     /* Anonymous bind */
20654925bf6Swillf     retval = ldap_sasl_bind_s(ld, NULL, NULL, NULL, NULL, NULL, NULL);
20754925bf6Swillf     if (retval != LDAP_SUCCESS) {
20854925bf6Swillf 	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
20954925bf6Swillf 	ret = 2; /* Don't know */
21054925bf6Swillf 	goto cleanup;
21154925bf6Swillf     }
21254925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
21354925bf6Swillf 
21454925bf6Swillf     retval = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, NULL, NULL, NULL, 0, &res);
21554925bf6Swillf     if (retval != LDAP_SUCCESS) {
21654925bf6Swillf 	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
21754925bf6Swillf 	ret = 2; /* Don't know */
21854925bf6Swillf 	goto cleanup;
21954925bf6Swillf     }
22054925bf6Swillf 
22154925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
22254925bf6Swillf     msg = ldap_first_message(ld, res);
22354925bf6Swillf #else
22454925bf6Swillf     /* Solaris Kerberos: more accurate */
22554925bf6Swillf     msg = ldap_first_entry(ld, res);
22654925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
22754925bf6Swillf     if (msg == NULL) {
22854925bf6Swillf 	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
22954925bf6Swillf 	ret = 2; /* Don't know */
23054925bf6Swillf 	goto cleanup;
23154925bf6Swillf     }
23254925bf6Swillf 
23354925bf6Swillf     values = ldap_get_values(ld, msg, "supportedSASLMechanisms");
23454925bf6Swillf     if (values == NULL) {
23554925bf6Swillf 	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
23654925bf6Swillf 	ret = 1; /* Not supported */
23754925bf6Swillf 	goto cleanup;
23854925bf6Swillf     }
23954925bf6Swillf 
24054925bf6Swillf     for (i = 0; values[i] != NULL; i++) {
24154925bf6Swillf 	if (strcmp(values[i], "EXTERNAL"))
24254925bf6Swillf 	    continue;
24354925bf6Swillf 	flag = 1;
24454925bf6Swillf     }
24554925bf6Swillf 
24654925bf6Swillf     if (flag != 1) {
24754925bf6Swillf 	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
24854925bf6Swillf 	ret = 1; /* Not supported */
24954925bf6Swillf 	goto cleanup;
25054925bf6Swillf     }
25154925bf6Swillf 
25254925bf6Swillf cleanup:
25354925bf6Swillf 
25454925bf6Swillf     if (values != NULL)
25554925bf6Swillf 	ldap_value_free(values);
25654925bf6Swillf 
25754925bf6Swillf     if (res != NULL)
25854925bf6Swillf 	ldap_msgfree(res);
25954925bf6Swillf 
26054925bf6Swillf     if (ld != NULL)
26154925bf6Swillf 	ldap_unbind_ext_s(ld, NULL, NULL);
26254925bf6Swillf 
26354925bf6Swillf     return ret;
26454925bf6Swillf }
26554925bf6Swillf 
26654925bf6Swillf /*ARGSUSED*/
krb5_ldap_alloc(krb5_context context,void * ptr,size_t size)26754925bf6Swillf void * krb5_ldap_alloc(krb5_context context, void *ptr, size_t size)
26854925bf6Swillf {
26954925bf6Swillf     return realloc(ptr, size);
27054925bf6Swillf }
27154925bf6Swillf 
27254925bf6Swillf /*ARGSUSED*/
krb5_ldap_free(krb5_context context,void * ptr)27354925bf6Swillf void krb5_ldap_free(krb5_context context, void *ptr)
27454925bf6Swillf 
27554925bf6Swillf {
27654925bf6Swillf     free(ptr);
27754925bf6Swillf }
27854925bf6Swillf 
krb5_ldap_open(krb5_context context,char * conf_section,char ** db_args,int mode)27954925bf6Swillf krb5_error_code krb5_ldap_open(krb5_context context,
28054925bf6Swillf 			       char *conf_section,
28154925bf6Swillf 			       char **db_args,
28254925bf6Swillf 			       int mode)
28354925bf6Swillf {
28454925bf6Swillf     krb5_error_code status  = 0;
28554925bf6Swillf     char **t_ptr = db_args;
28654925bf6Swillf     krb5_ldap_context *ldap_context=NULL;
28754925bf6Swillf     int srv_cnt = 0;
28854925bf6Swillf     kdb5_dal_handle *dal_handle=NULL;
28954925bf6Swillf 
29054925bf6Swillf     /* Clear the global error string */
29154925bf6Swillf     krb5_clear_error_message(context);
29254925bf6Swillf 
29354925bf6Swillf     ldap_context = calloc(1, sizeof(krb5_ldap_context));
29454925bf6Swillf     if (ldap_context == NULL) {
29554925bf6Swillf 	status = ENOMEM;
29654925bf6Swillf 	goto clean_n_exit;
29754925bf6Swillf     }
29854925bf6Swillf 
29954925bf6Swillf     ldap_context->kcontext = context;
30054925bf6Swillf 
30154925bf6Swillf     while (t_ptr && *t_ptr) {
30254925bf6Swillf 	char *opt = NULL, *val = NULL;
30354925bf6Swillf 
30454925bf6Swillf 	if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) {
30554925bf6Swillf 	    goto clean_n_exit;
30654925bf6Swillf 	}
30754925bf6Swillf 	if (opt && !strcmp(opt, "binddn")) {
30854925bf6Swillf 	    if (ldap_context->bind_dn) {
30954925bf6Swillf 		free (opt);
31054925bf6Swillf 		free (val);
31154925bf6Swillf 		status = EINVAL;
31254925bf6Swillf 		krb5_set_error_message (context, status, gettext("'binddn' missing"));
31354925bf6Swillf 		goto clean_n_exit;
31454925bf6Swillf 	    }
31554925bf6Swillf 	    if (val == NULL) {
31654925bf6Swillf 		status = EINVAL;
31754925bf6Swillf 		krb5_set_error_message (context, status, gettext("'binddn' value missing"));
31854925bf6Swillf 		free(opt);
31954925bf6Swillf 		goto clean_n_exit;
32054925bf6Swillf 	    }
32154925bf6Swillf 	    ldap_context->bind_dn = strdup(val);
32254925bf6Swillf 	    if (ldap_context->bind_dn == NULL) {
32354925bf6Swillf 		free (opt);
32454925bf6Swillf 		free (val);
32554925bf6Swillf 		status = ENOMEM;
32654925bf6Swillf 		goto clean_n_exit;
32754925bf6Swillf 	    }
32854925bf6Swillf 	} else if (opt && !strcmp(opt, "nconns")) {
32954925bf6Swillf 	    if (ldap_context->max_server_conns) {
33054925bf6Swillf 		free (opt);
33154925bf6Swillf 		free (val);
33254925bf6Swillf 		status = EINVAL;
33354925bf6Swillf 		krb5_set_error_message (context, status, gettext("'nconns' missing"));
33454925bf6Swillf 		goto clean_n_exit;
33554925bf6Swillf 	    }
33654925bf6Swillf 	    if (val == NULL) {
33754925bf6Swillf 		status = EINVAL;
33854925bf6Swillf 		krb5_set_error_message (context, status, gettext("'nconns' value missing"));
33954925bf6Swillf 		free(opt);
34054925bf6Swillf 		goto clean_n_exit;
34154925bf6Swillf 	    }
34254925bf6Swillf 	    ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
34354925bf6Swillf 	} else if (opt && !strcmp(opt, "bindpwd")) {
34454925bf6Swillf 	    if (ldap_context->bind_pwd) {
34554925bf6Swillf 		free (opt);
34654925bf6Swillf 		free (val);
34754925bf6Swillf 		status = EINVAL;
34854925bf6Swillf 		krb5_set_error_message (context, status, gettext("'bindpwd' missing"));
34954925bf6Swillf 		goto clean_n_exit;
35054925bf6Swillf 	    }
35154925bf6Swillf 	    if (val == NULL) {
35254925bf6Swillf 		status = EINVAL;
35354925bf6Swillf 		krb5_set_error_message (context, status, gettext("'bindpwd' value missing"));
35454925bf6Swillf 		free(opt);
35554925bf6Swillf 		goto clean_n_exit;
35654925bf6Swillf 	    }
35754925bf6Swillf 	    ldap_context->bind_pwd = strdup(val);
35854925bf6Swillf 	    if (ldap_context->bind_pwd == NULL) {
35954925bf6Swillf 		free (opt);
36054925bf6Swillf 		free (val);
36154925bf6Swillf 		status = ENOMEM;
36254925bf6Swillf 		goto clean_n_exit;
36354925bf6Swillf 	    }
36454925bf6Swillf 	} else if (opt && !strcmp(opt, "host")) {
36554925bf6Swillf 	    if (val == NULL) {
36654925bf6Swillf 		status = EINVAL;
36754925bf6Swillf 		krb5_set_error_message (context, status, gettext("'host' value missing"));
36854925bf6Swillf 		free(opt);
36954925bf6Swillf 		goto clean_n_exit;
37054925bf6Swillf 	    }
37154925bf6Swillf 	    if (ldap_context->server_info_list == NULL)
37254925bf6Swillf 		ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (SERV_COUNT+1, sizeof (krb5_ldap_server_info *)) ;
37354925bf6Swillf 
37454925bf6Swillf 	    if (ldap_context->server_info_list == NULL) {
37554925bf6Swillf 		free (opt);
37654925bf6Swillf 		free (val);
37754925bf6Swillf 		status = ENOMEM;
37854925bf6Swillf 		goto clean_n_exit;
37954925bf6Swillf 	    }
38054925bf6Swillf 
38154925bf6Swillf 	    ldap_context->server_info_list[srv_cnt] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
38254925bf6Swillf 	    if (ldap_context->server_info_list[srv_cnt] == NULL) {
38354925bf6Swillf 		free (opt);
38454925bf6Swillf 		free (val);
38554925bf6Swillf 		status = ENOMEM;
38654925bf6Swillf 		goto clean_n_exit;
38754925bf6Swillf 	    }
38854925bf6Swillf 
38954925bf6Swillf 	    ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;
39054925bf6Swillf 
39154925bf6Swillf 	    ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
39254925bf6Swillf 	    if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
39354925bf6Swillf 		free (opt);
39454925bf6Swillf 		free (val);
39554925bf6Swillf 		status = ENOMEM;
39654925bf6Swillf 		goto clean_n_exit;
39754925bf6Swillf 	    }
39854925bf6Swillf 
39954925bf6Swillf 	    srv_cnt++;
40054925bf6Swillf #ifdef HAVE_EDIRECTORY
40154925bf6Swillf 	} else if (opt && !strcmp(opt, "cert")) {
40254925bf6Swillf 	    if (val == NULL) {
40354925bf6Swillf 		status = EINVAL;
40454925bf6Swillf 		krb5_set_error_message (context, status, gettext("'cert' value missing"));
40554925bf6Swillf 		free(opt);
40654925bf6Swillf 		goto clean_n_exit;
40754925bf6Swillf 	    }
40854925bf6Swillf 
40954925bf6Swillf 	    if (ldap_context->root_certificate_file == NULL) {
41054925bf6Swillf 		ldap_context->root_certificate_file = strdup(val);
41154925bf6Swillf 		if (ldap_context->root_certificate_file == NULL) {
41254925bf6Swillf 		    free (opt);
41354925bf6Swillf 		    free (val);
41454925bf6Swillf 		    status = ENOMEM;
41554925bf6Swillf 		    goto clean_n_exit;
41654925bf6Swillf 		}
41754925bf6Swillf 	    } else {
41854925bf6Swillf 		void *tmp=NULL;
41954925bf6Swillf 		char *oldstr = NULL;
42054925bf6Swillf 		unsigned int len=0;
42154925bf6Swillf 
42254925bf6Swillf 		oldstr = strdup(ldap_context->root_certificate_file);
42354925bf6Swillf 		if (oldstr == NULL) {
42454925bf6Swillf 		    free (opt);
42554925bf6Swillf 		    free (val);
42654925bf6Swillf 		    status = ENOMEM;
42754925bf6Swillf 		    goto clean_n_exit;
42854925bf6Swillf 		}
42954925bf6Swillf 
43054925bf6Swillf 		tmp = ldap_context->root_certificate_file;
43154925bf6Swillf 		len = strlen(ldap_context->root_certificate_file) + 2 + strlen(val);
43254925bf6Swillf 		ldap_context->root_certificate_file = realloc(ldap_context->root_certificate_file,
43354925bf6Swillf 							      len);
43454925bf6Swillf 		if (ldap_context->root_certificate_file == NULL) {
43554925bf6Swillf 		    free (tmp);
43654925bf6Swillf 		    free (opt);
43754925bf6Swillf 		    free (val);
43854925bf6Swillf 		    status = ENOMEM;
43954925bf6Swillf 		    goto clean_n_exit;
44054925bf6Swillf 		}
44154925bf6Swillf 		memset(ldap_context->root_certificate_file, 0, len);
44254925bf6Swillf 		sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
44354925bf6Swillf 		free (oldstr);
44454925bf6Swillf 	    }
44554925bf6Swillf #endif
44654925bf6Swillf 	} else {
44754925bf6Swillf 	    /* ignore hash argument. Might have been passed from create */
44854925bf6Swillf 	    status = EINVAL;
44954925bf6Swillf 	    if (opt && !strcmp(opt, "temporary")) {
45054925bf6Swillf 		/*
45154925bf6Swillf 		 * temporary is passed in when kdb5_util load without -update is done.
45254925bf6Swillf 		 * This is unsupported by the LDAP plugin.
45354925bf6Swillf 		 */
45454925bf6Swillf 		krb5_set_error_message (context, status,
45554925bf6Swillf 					gettext("open of LDAP directory aborted, plugin requires -update argument"));
45654925bf6Swillf 	    } else {
45754925bf6Swillf 		krb5_set_error_message (context, status, gettext("unknown option \'%s\'"),
45854925bf6Swillf 					opt?opt:val);
45954925bf6Swillf 	    }
46054925bf6Swillf 	    free(opt);
46154925bf6Swillf 	    free(val);
46254925bf6Swillf 	    goto clean_n_exit;
46354925bf6Swillf 	}
46454925bf6Swillf 
46554925bf6Swillf 	free(opt);
46654925bf6Swillf 	free(val);
46754925bf6Swillf 	t_ptr++;
46854925bf6Swillf     }
46954925bf6Swillf 
47054925bf6Swillf     dal_handle = (kdb5_dal_handle *) context->db_context;
47154925bf6Swillf     dal_handle->db_context = ldap_context;
47254925bf6Swillf     status = krb5_ldap_read_server_params(context, conf_section, mode & 0x0300);
47354925bf6Swillf     if (status) {
47454925bf6Swillf 	if (ldap_context)
47554925bf6Swillf 	    krb5_ldap_free_ldap_context(ldap_context);
47654925bf6Swillf 	ldap_context = NULL;
47754925bf6Swillf 	dal_handle->db_context = NULL;
47854925bf6Swillf 	prepend_err_str (context, gettext("Error reading LDAP server params: "), status, status);
47954925bf6Swillf 	goto clean_n_exit;
48054925bf6Swillf     }
48154925bf6Swillf     if ((status=krb5_ldap_db_init(context, ldap_context)) != 0) {
48254925bf6Swillf 	goto clean_n_exit;
48354925bf6Swillf     }
48454925bf6Swillf 
48554925bf6Swillf     if ((status=krb5_ldap_read_startup_information(context)) != 0) {
48654925bf6Swillf 	goto clean_n_exit;
48754925bf6Swillf     }
48854925bf6Swillf 
48954925bf6Swillf clean_n_exit:
49054925bf6Swillf     /* may be clearing up is not required  db_fini might do it for us, check out */
49154925bf6Swillf     if (status) {
49254925bf6Swillf 	krb5_ldap_close(context);
49354925bf6Swillf     }
49454925bf6Swillf     return status;
49554925bf6Swillf }
49654925bf6Swillf 
49754925bf6Swillf #include "ldap_err.h"
49854925bf6Swillf int
set_ldap_error(krb5_context ctx,int st,int op)49954925bf6Swillf set_ldap_error (krb5_context ctx, int st, int op)
50054925bf6Swillf {
50154925bf6Swillf     int translated_st = translate_ldap_error(st, op);
50254925bf6Swillf     krb5_set_error_message(ctx, translated_st, "%s", ldap_err2string(st));
50354925bf6Swillf     return translated_st;
50454925bf6Swillf }
50554925bf6Swillf 
50654925bf6Swillf void
prepend_err_str(krb5_context ctx,const char * str,krb5_error_code err,krb5_error_code oerr)50754925bf6Swillf prepend_err_str (krb5_context ctx, const char *str, krb5_error_code err,
50854925bf6Swillf 		 krb5_error_code oerr)
50954925bf6Swillf {
51054925bf6Swillf     const char *omsg;
51154925bf6Swillf     if (oerr == 0) oerr = err;
51254925bf6Swillf     omsg = krb5_get_error_message (ctx, err);
51354925bf6Swillf     krb5_set_error_message (ctx, err, "%s %s", str, omsg);
514*7c64d375Smp153739     /* Solaris Kerberos: Memleak */
515*7c64d375Smp153739     krb5_free_error_message(ctx, omsg);
51654925bf6Swillf }
51754925bf6Swillf 
51854925bf6Swillf extern krb5int_access accessor;
51954925bf6Swillf MAKE_INIT_FUNCTION(kldap_init_fn);
52054925bf6Swillf 
kldap_init_fn(void)52154925bf6Swillf int kldap_init_fn(void)
52254925bf6Swillf {
52354925bf6Swillf     /* Global (per-module) initialization.  */
52454925bf6Swillf     return krb5int_accessor (&accessor, KRB5INT_ACCESS_VERSION);
52554925bf6Swillf }
52654925bf6Swillf 
kldap_ensure_initialized(void)52754925bf6Swillf int kldap_ensure_initialized(void)
52854925bf6Swillf {
52954925bf6Swillf     return CALL_INIT_FUNCTION (kldap_init_fn);
53054925bf6Swillf }
531