154925bf6Swillf /*
254925bf6Swillf  * lib/kdb/kdb_ldap/ldap_principal.c
354925bf6Swillf  *
454925bf6Swillf  * Copyright (c) 2004-2005, Novell, Inc.
554925bf6Swillf  * All rights reserved.
654925bf6Swillf  *
754925bf6Swillf  * Redistribution and use in source and binary forms, with or without
854925bf6Swillf  * modification, are permitted provided that the following conditions are met:
954925bf6Swillf  *
1054925bf6Swillf  *   * Redistributions of source code must retain the above copyright notice,
1154925bf6Swillf  *       this list of conditions and the following disclaimer.
1254925bf6Swillf  *   * Redistributions in binary form must reproduce the above copyright
1354925bf6Swillf  *       notice, this list of conditions and the following disclaimer in the
1454925bf6Swillf  *       documentation and/or other materials provided with the distribution.
1554925bf6Swillf  *   * The copyright holder's name is not used to endorse or promote products
1654925bf6Swillf  *       derived from this software without specific prior written permission.
1754925bf6Swillf  *
1854925bf6Swillf  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1954925bf6Swillf  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2054925bf6Swillf  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2154925bf6Swillf  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2254925bf6Swillf  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2354925bf6Swillf  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2454925bf6Swillf  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2554925bf6Swillf  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2654925bf6Swillf  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2754925bf6Swillf  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2854925bf6Swillf  * POSSIBILITY OF SUCH DAMAGE.
2954925bf6Swillf  */
3054925bf6Swillf /*
31159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3254925bf6Swillf  * Use is subject to license terms.
3354925bf6Swillf  */
3454925bf6Swillf 
3554925bf6Swillf #include "ldap_main.h"
3654925bf6Swillf #include "kdb_ldap.h"
3754925bf6Swillf #include "ldap_principal.h"
3854925bf6Swillf #include "princ_xdr.h"
3954925bf6Swillf #include "ldap_err.h"
4054925bf6Swillf #include <libintl.h>
4154925bf6Swillf 
4254925bf6Swillf struct timeval timelimit = {300, 0};  /* 5 minutes */
4354925bf6Swillf char     *principal_attributes[] = { "krbprincipalname",
4454925bf6Swillf 				     "objectclass",
4554925bf6Swillf 				     "krbprincipalkey",
4654925bf6Swillf 				     "krbmaxrenewableage",
4754925bf6Swillf 				     "krbmaxticketlife",
4854925bf6Swillf 				     "krbticketflags",
4954925bf6Swillf 				     "krbprincipalexpiration",
5054925bf6Swillf 				     "krbticketpolicyreference",
5154925bf6Swillf 				     "krbUpEnabled",
5254925bf6Swillf 				     "krbpwdpolicyreference",
5354925bf6Swillf 				     "krbpasswordexpiration",
5454925bf6Swillf                                      "krbLastFailedAuth",
5554925bf6Swillf                                      "krbLoginFailedCount",
5654925bf6Swillf                                      "krbLastSuccessfulAuth",
5754925bf6Swillf #ifdef HAVE_EDIRECTORY
5854925bf6Swillf 				     "loginexpirationtime",
5954925bf6Swillf 				     "logindisabled",
6054925bf6Swillf #endif
6154925bf6Swillf 				     "loginexpirationtime",
6254925bf6Swillf 				     "logindisabled",
6354925bf6Swillf 				     "modifytimestamp",
6454925bf6Swillf 				     "krbLastPwdChange",
6554925bf6Swillf 				     "krbExtraData",
6654925bf6Swillf 				     "krbObjectReferences",
6754925bf6Swillf 				     NULL };
6854925bf6Swillf 
6954925bf6Swillf /* Must match KDB_*_ATTR macros in ldap_principal.h.  */
7054925bf6Swillf static char *attributes_set[] = { "krbmaxticketlife",
7154925bf6Swillf 				  "krbmaxrenewableage",
7254925bf6Swillf 				  "krbticketflags",
7354925bf6Swillf 				  "krbprincipalexpiration",
7454925bf6Swillf 				  "krbticketpolicyreference",
7554925bf6Swillf 				  "krbUpEnabled",
7654925bf6Swillf 				  "krbpwdpolicyreference",
7754925bf6Swillf 				  "krbpasswordexpiration",
7854925bf6Swillf 				  "krbprincipalkey",
7954925bf6Swillf                                   "krblastpwdchange",
8054925bf6Swillf                                   "krbextradata",
8154925bf6Swillf                                   "krbLastSuccessfulAuth",
8254925bf6Swillf                                   "krbLastFailedAuth",
8354925bf6Swillf                                   "krbLoginFailedCount",
8454925bf6Swillf 				  NULL };
8554925bf6Swillf 
8654925bf6Swillf void
krb5_dbe_free_contents(context,entry)8754925bf6Swillf krb5_dbe_free_contents(context, entry)
8854925bf6Swillf     krb5_context 	 context;
8954925bf6Swillf     krb5_db_entry 	*entry;
9054925bf6Swillf {
9154925bf6Swillf     krb5_tl_data 	*tl_data_next=NULL;
9254925bf6Swillf     krb5_tl_data 	*tl_data=NULL;
9354925bf6Swillf     int i, j;
9454925bf6Swillf 
9554925bf6Swillf     if (entry->e_data)
9654925bf6Swillf 	free(entry->e_data);
9754925bf6Swillf     if (entry->princ)
9854925bf6Swillf 	krb5_free_principal(context, entry->princ);
9954925bf6Swillf     for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
10054925bf6Swillf 	tl_data_next = tl_data->tl_data_next;
10154925bf6Swillf 	if (tl_data->tl_data_contents)
10254925bf6Swillf 	    free(tl_data->tl_data_contents);
10354925bf6Swillf 	free(tl_data);
10454925bf6Swillf     }
10554925bf6Swillf     if (entry->key_data) {
10654925bf6Swillf 	for (i = 0; i < entry->n_key_data; i++) {
10754925bf6Swillf 	    for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
10854925bf6Swillf 		if (entry->key_data[i].key_data_length[j]) {
10954925bf6Swillf 		    if (entry->key_data[i].key_data_contents[j]) {
11054925bf6Swillf 			memset(entry->key_data[i].key_data_contents[j],
11154925bf6Swillf 			       0,
11254925bf6Swillf 			       (unsigned) entry->key_data[i].key_data_length[j]);
11354925bf6Swillf 			free (entry->key_data[i].key_data_contents[j]);
11454925bf6Swillf 		    }
11554925bf6Swillf 		}
11654925bf6Swillf 		entry->key_data[i].key_data_contents[j] = NULL;
11754925bf6Swillf 		entry->key_data[i].key_data_length[j] = 0;
11854925bf6Swillf 		entry->key_data[i].key_data_type[j] = 0;
11954925bf6Swillf 	    }
12054925bf6Swillf 	}
12154925bf6Swillf 	free(entry->key_data);
12254925bf6Swillf     }
12354925bf6Swillf     memset(entry, 0, sizeof(*entry));
12454925bf6Swillf     return;
12554925bf6Swillf }
12654925bf6Swillf 
12754925bf6Swillf 
12854925bf6Swillf krb5_error_code
krb5_ldap_free_principal(kcontext,entries,nentries)12954925bf6Swillf krb5_ldap_free_principal(kcontext , entries, nentries)
13054925bf6Swillf     krb5_context  kcontext;
13154925bf6Swillf     krb5_db_entry *entries;
13254925bf6Swillf     int           nentries;
13354925bf6Swillf {
13454925bf6Swillf     register int i;
13554925bf6Swillf     for (i = 0; i < nentries; i++)
13654925bf6Swillf 	krb5_dbe_free_contents(kcontext, &entries[i]);
13754925bf6Swillf     return 0;
13854925bf6Swillf }
13954925bf6Swillf 
14054925bf6Swillf krb5_error_code
krb5_ldap_iterate(context,match_expr,func,func_arg,db_args)141159d09a2SMark Phalan krb5_ldap_iterate(context, match_expr, func, func_arg, db_args)
142159d09a2SMark Phalan     krb5_context           context;
143159d09a2SMark Phalan     char                   *match_expr;
144159d09a2SMark Phalan     krb5_error_code        (*func) (krb5_pointer, krb5_db_entry *);
145159d09a2SMark Phalan     krb5_pointer           func_arg;
1462dd2efa5Swillf     /* Solaris Kerberos: adding support for -rev/recurse flags */
147159d09a2SMark Phalan     char                   **db_args;
14854925bf6Swillf {
14954925bf6Swillf     krb5_db_entry            entry;
15054925bf6Swillf     krb5_principal           principal;
151*55fea89dSDan Cross     char                     **subtree=NULL, *princ_name=NULL, *realm=NULL, **values=NULL, *filter=NULL;
15254925bf6Swillf     unsigned int             filterlen=0, tree=0, ntree=1, i=0;
15354925bf6Swillf     krb5_error_code          st=0, tempst=0;
15454925bf6Swillf     LDAP                     *ld=NULL;
15554925bf6Swillf     LDAPMessage              *result=NULL, *ent=NULL;
15654925bf6Swillf     kdb5_dal_handle          *dal_handle=NULL;
15754925bf6Swillf     krb5_ldap_context        *ldap_context=NULL;
15854925bf6Swillf     krb5_ldap_server_handle  *ldap_server_handle=NULL;
15954925bf6Swillf     char                     *default_match_expr = "*";
16054925bf6Swillf 
16154925bf6Swillf     /* Clear the global error string */
16254925bf6Swillf     krb5_clear_error_message(context);
16354925bf6Swillf 
1642dd2efa5Swillf     /* Solaris Kerberos: adding support for -rev/recurse flags */
1652dd2efa5Swillf     if (db_args) {
1662dd2efa5Swillf 	/* LDAP does not support db_args DB arguments for krb5_ldap_iterate */
1672dd2efa5Swillf 	krb5_set_error_message(context, EINVAL,
1682dd2efa5Swillf 			       gettext("Unsupported argument \"%s\" for ldap"),
1692dd2efa5Swillf 			       db_args[0]);
1702dd2efa5Swillf 	return EINVAL;
1712dd2efa5Swillf     }
1722dd2efa5Swillf 
17354925bf6Swillf     memset(&entry, 0, sizeof(krb5_db_entry));
17454925bf6Swillf     SETUP_CONTEXT();
17554925bf6Swillf 
17654925bf6Swillf     realm = ldap_context->lrparams->realm_name;
17754925bf6Swillf     if (realm == NULL) {
17854925bf6Swillf 	realm = context->default_realm;
17954925bf6Swillf 	if (realm == NULL) {
18054925bf6Swillf 	    st = EINVAL;
18154925bf6Swillf 	    krb5_set_error_message(context, st, gettext("Default realm not set"));
18254925bf6Swillf 	    goto cleanup;
18354925bf6Swillf 	}
18454925bf6Swillf     }
18554925bf6Swillf 
186*55fea89dSDan Cross     /*
18754925bf6Swillf      * If no match_expr then iterate through all krb princs like the db2 plugin
18854925bf6Swillf      */
18954925bf6Swillf     if (match_expr == NULL)
19054925bf6Swillf 	match_expr = default_match_expr;
19154925bf6Swillf 
19254925bf6Swillf     filterlen = strlen(FILTER) + strlen(match_expr) + 2 + 1;  /* 2 for closing brackets */
19354925bf6Swillf     filter = malloc (filterlen);
19454925bf6Swillf     CHECK_NULL(filter);
19554925bf6Swillf     memset(filter, 0, filterlen);
19654925bf6Swillf     /*LINTED*/
19754925bf6Swillf     sprintf(filter, FILTER"%s))", match_expr);
19854925bf6Swillf 
199*55fea89dSDan Cross     if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntree)) != 0)
20054925bf6Swillf 	goto cleanup;
20154925bf6Swillf 
20254925bf6Swillf     GET_HANDLE();
20354925bf6Swillf 
20454925bf6Swillf     for (tree=0; tree < ntree; ++tree) {
20554925bf6Swillf 
20654925bf6Swillf 	LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes);
20754925bf6Swillf 	for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
20854925bf6Swillf 	    if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
20954925bf6Swillf 		for (i=0; values[i] != NULL; ++i) {
21054925bf6Swillf 		    if (values[i])
21154925bf6Swillf 		    if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0)
21254925bf6Swillf 			continue;
21354925bf6Swillf 		    if (krb5_parse_name(context, princ_name, &principal) != 0)
21454925bf6Swillf 			continue;
21554925bf6Swillf 		    if (is_principal_in_realm(ldap_context, principal) == 0) {
21654925bf6Swillf 			if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, principal,
21754925bf6Swillf 				    &entry)) != 0)
21854925bf6Swillf 			    goto cleanup;
21954925bf6Swillf 			(*func)(func_arg, &entry);
22054925bf6Swillf 			krb5_dbe_free_contents(context, &entry);
22154925bf6Swillf 			(void) krb5_free_principal(context, principal);
22254925bf6Swillf 			if (princ_name)
22354925bf6Swillf 			    free(princ_name);
22454925bf6Swillf 			break;
22554925bf6Swillf 		    }
22654925bf6Swillf 		    (void) krb5_free_principal(context, principal);
22754925bf6Swillf 		    if (princ_name)
22854925bf6Swillf 			free(princ_name);
22954925bf6Swillf 		}
23054925bf6Swillf 		ldap_value_free(values);
23154925bf6Swillf 	    }
23254925bf6Swillf 	} /* end of for (ent= ... */
23354925bf6Swillf 	ldap_msgfree(result);
23454925bf6Swillf     } /* end of for (tree= ... */
23554925bf6Swillf 
23654925bf6Swillf cleanup:
23754925bf6Swillf     if (filter)
23854925bf6Swillf 	free (filter);
23954925bf6Swillf 
24054925bf6Swillf     for (;ntree; --ntree)
24154925bf6Swillf 	if (subtree[ntree-1])
24254925bf6Swillf 	    free (subtree[ntree-1]);
24354925bf6Swillf 
24454925bf6Swillf     /* Solaris Kerberos: fix memory leak */
24554925bf6Swillf     if (subtree != NULL) {
24654925bf6Swillf 	free(subtree);
24754925bf6Swillf     }
24854925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
24954925bf6Swillf     return st;
25054925bf6Swillf }
25154925bf6Swillf 
25254925bf6Swillf 
25354925bf6Swillf /*
25454925bf6Swillf  * delete a principal from the directory.
25554925bf6Swillf  */
25654925bf6Swillf krb5_error_code
krb5_ldap_delete_principal(context,searchfor,nentries)25754925bf6Swillf krb5_ldap_delete_principal(context, searchfor, nentries)
25854925bf6Swillf     krb5_context context;
25954925bf6Swillf     krb5_const_principal searchfor;
26054925bf6Swillf     int *nentries;		/* how many found & deleted */
26154925bf6Swillf {
26254925bf6Swillf     char                      *user=NULL, *DN=NULL, *strval[10] = {NULL};
26354925bf6Swillf     LDAPMod                   **mods=NULL;
26454925bf6Swillf     LDAP                      *ld=NULL;
26554925bf6Swillf     int 	              j=0, ptype=0, pcount=0;
26654925bf6Swillf     unsigned int	      attrsetmask=0;
26754925bf6Swillf     krb5_error_code           st=0;
26854925bf6Swillf     krb5_boolean              singleentry=FALSE;
26954925bf6Swillf     KEY                       *secretkey=NULL;
27054925bf6Swillf     kdb5_dal_handle           *dal_handle=NULL;
27154925bf6Swillf     krb5_ldap_context         *ldap_context=NULL;
27254925bf6Swillf     krb5_ldap_server_handle   *ldap_server_handle=NULL;
27354925bf6Swillf     krb5_db_entry             entries;
27454925bf6Swillf     krb5_boolean              more=0;
27554925bf6Swillf 
27654925bf6Swillf     /* Clear the global error string */
27754925bf6Swillf     krb5_clear_error_message(context);
27854925bf6Swillf 
27954925bf6Swillf     SETUP_CONTEXT();
28054925bf6Swillf     /* get the principal info */
28154925bf6Swillf     if ((st=krb5_ldap_get_principal(context, searchfor, &entries, nentries, &more)) != 0 || *nentries == 0)
28254925bf6Swillf 	goto cleanup;
28354925bf6Swillf 
28454925bf6Swillf     if (((st=krb5_get_princ_type(context, &entries, &(ptype))) != 0) ||
28554925bf6Swillf 	((st=krb5_get_attributes_mask(context, &entries, &(attrsetmask))) != 0) ||
28654925bf6Swillf 	((st=krb5_get_princ_count(context, &entries, &(pcount))) != 0) ||
28754925bf6Swillf 	((st=krb5_get_userdn(context, &entries, &(DN))) != 0))
28854925bf6Swillf 	goto cleanup;
28954925bf6Swillf 
29054925bf6Swillf     if (DN == NULL) {
29154925bf6Swillf 	st = EINVAL;
29254925bf6Swillf 	krb5_set_error_message(context, st, gettext("DN information missing"));
29354925bf6Swillf 	goto cleanup;
29454925bf6Swillf     }
29554925bf6Swillf 
29654925bf6Swillf     GET_HANDLE();
29754925bf6Swillf 
29854925bf6Swillf     if (ptype == KDB_STANDALONE_PRINCIPAL_OBJECT) {
29954925bf6Swillf         st = ldap_delete_ext_s(ld, DN, NULL, NULL);
30054925bf6Swillf         if (st != LDAP_SUCCESS) {
30154925bf6Swillf             st = set_ldap_error (context, st, OP_DEL);
30254925bf6Swillf             goto cleanup;
30354925bf6Swillf         }
30454925bf6Swillf     } else {
30554925bf6Swillf 	if (((st=krb5_unparse_name(context, searchfor, &user)) != 0)
30654925bf6Swillf 	    || ((st=krb5_ldap_unparse_principal_name(user)) != 0))
30754925bf6Swillf 	    goto cleanup;
30854925bf6Swillf 
30954925bf6Swillf 	memset(strval, 0, sizeof(strval));
31054925bf6Swillf 	strval[0] = user;
31154925bf6Swillf 	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_DELETE,
31254925bf6Swillf 					  strval)) != 0)
31354925bf6Swillf 	    goto cleanup;
31454925bf6Swillf 
31554925bf6Swillf 	singleentry = (pcount == 1) ? TRUE: FALSE;
31654925bf6Swillf 	if (singleentry == FALSE) {
31754925bf6Swillf 	    if (secretkey != NULL) {
31854925bf6Swillf 		if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", LDAP_MOD_DELETE | LDAP_MOD_BVALUES,
31954925bf6Swillf 						  secretkey->keys)) != 0)
32054925bf6Swillf 		    goto cleanup;
32154925bf6Swillf 	    }
32254925bf6Swillf 	} else {
32354925bf6Swillf 	    /*
32454925bf6Swillf 	     * If the Kerberos user principal to be deleted happens to be the last one associated
32554925bf6Swillf 	     * with the directory user object, then it is time to delete the other kerberos
32654925bf6Swillf 	     * specific attributes like krbmaxticketlife, i.e, unkerberize the directory user.
32754925bf6Swillf 	     * From the attrsetmask value, identify the attributes set on the directory user
32854925bf6Swillf 	     * object and delete them.
32954925bf6Swillf 	     * NOTE: krbsecretkey attribute has per principal entries. There can be chances that the
33054925bf6Swillf 	     * other principals' keys are exisiting/left-over. So delete all the values.
33154925bf6Swillf 	     */
33254925bf6Swillf 	    while (attrsetmask) {
33354925bf6Swillf 		if (attrsetmask & 1) {
33454925bf6Swillf 		    if ((st=krb5_add_str_mem_ldap_mod(&mods, attributes_set[j], LDAP_MOD_DELETE,
33554925bf6Swillf 						      NULL)) != 0)
33654925bf6Swillf 			goto cleanup;
33754925bf6Swillf 		}
33854925bf6Swillf 		attrsetmask >>= 1;
33954925bf6Swillf 		++j;
34054925bf6Swillf 	    }
34154925bf6Swillf 
34254925bf6Swillf 	    /* the same should be done with the objectclass attributes */
34354925bf6Swillf 	    {
34454925bf6Swillf 		char *attrvalues[] = {"krbticketpolicyaux", "krbprincipalaux", NULL};
34554925bf6Swillf /*		char *attrvalues[] = {"krbpwdpolicyrefaux", "krbticketpolicyaux", "krbprincipalaux", NULL};  */
34654925bf6Swillf 		int p, q, r=0, amask=0;
34754925bf6Swillf 
34854925bf6Swillf 		if ((st=checkattributevalue(ld, DN, "objectclass", attrvalues, &amask)) != 0)
34954925bf6Swillf 		    goto cleanup;
35054925bf6Swillf 		memset(strval, 0, sizeof(strval));
35154925bf6Swillf 		for (p=1, q=0; p<=4; p<<=1, ++q)
35254925bf6Swillf 		    if (p & amask)
35354925bf6Swillf 			strval[r++] = attrvalues[q];
35454925bf6Swillf 		strval[r] = NULL;
35554925bf6Swillf 		if (r > 0) {
35654925bf6Swillf 		    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_DELETE,
35754925bf6Swillf 						      strval)) != 0)
35854925bf6Swillf 			goto cleanup;
35954925bf6Swillf 		}
36054925bf6Swillf 	    }
36154925bf6Swillf 	}
36254925bf6Swillf 	st=ldap_modify_ext_s(ld, DN, mods, NULL, NULL);
36354925bf6Swillf 	if (st != LDAP_SUCCESS) {
36454925bf6Swillf 	    st = set_ldap_error(context, st, OP_MOD);
36554925bf6Swillf 	    goto cleanup;
36654925bf6Swillf 	}
36754925bf6Swillf     }
36854925bf6Swillf 
36954925bf6Swillf cleanup:
37054925bf6Swillf     if (user)
37154925bf6Swillf 	free (user);
37254925bf6Swillf 
37354925bf6Swillf     if (DN)
37454925bf6Swillf 	free (DN);
37554925bf6Swillf 
37654925bf6Swillf     if (secretkey != NULL) {
37754925bf6Swillf 	int i=0;
37854925bf6Swillf 	while (i < secretkey->nkey) {
37954925bf6Swillf 	    free (secretkey->keys[i]->bv_val);
38054925bf6Swillf 	    free (secretkey->keys[i]);
38154925bf6Swillf 	    ++i;
38254925bf6Swillf 	}
38354925bf6Swillf 	free (secretkey->keys);
38454925bf6Swillf 	free (secretkey);
38554925bf6Swillf     }
38654925bf6Swillf 
38754925bf6Swillf     if (st == 0)
38854925bf6Swillf 	krb5_ldap_free_principal(context, &entries, *nentries);
38954925bf6Swillf 
39054925bf6Swillf     ldap_mods_free(mods, 1);
39154925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
39254925bf6Swillf     return st;
39354925bf6Swillf }
39454925bf6Swillf 
39554925bf6Swillf 
39654925bf6Swillf /*
39754925bf6Swillf  * Function: krb5_ldap_unparse_principal_name
39854925bf6Swillf  *
39954925bf6Swillf  * Purpose: Removes '\\' that comes before every occurence of '@'
40054925bf6Swillf  *          in the principal name component.
40154925bf6Swillf  *
40254925bf6Swillf  * Arguments:
40354925bf6Swillf  *       user_name     (input/output)      Principal name
40454925bf6Swillf  *
40554925bf6Swillf  */
40654925bf6Swillf 
40754925bf6Swillf krb5_error_code
krb5_ldap_unparse_principal_name(char * user_name)40854925bf6Swillf krb5_ldap_unparse_principal_name(char *user_name)
40954925bf6Swillf {
41054925bf6Swillf     char *tmp_princ_name=NULL, *princ_name=NULL, *tmp=NULL;
41154925bf6Swillf     int l=0;
41254925bf6Swillf     krb5_error_code st=0;
41354925bf6Swillf 
41454925bf6Swillf     if (strstr(user_name, "\\@")) {
41554925bf6Swillf 
41654925bf6Swillf 	tmp_princ_name = strdup(user_name);
41754925bf6Swillf 	if (!tmp_princ_name) {
41854925bf6Swillf 	    st = ENOMEM;
41954925bf6Swillf 	    goto cleanup;
42054925bf6Swillf 	}
42154925bf6Swillf 	tmp = tmp_princ_name;
42254925bf6Swillf 
42354925bf6Swillf 	princ_name = (char *) malloc (strlen(user_name));
42454925bf6Swillf 	if (!princ_name) {
42554925bf6Swillf 	    st = ENOMEM;
42654925bf6Swillf 	    goto cleanup;
42754925bf6Swillf 	}
42854925bf6Swillf 	memset(princ_name, 0, strlen(user_name));
42954925bf6Swillf 
43054925bf6Swillf 	l = 0;
43154925bf6Swillf 	while (*tmp_princ_name) {
43254925bf6Swillf 	    if ((*tmp_princ_name == '\\') && (*(tmp_princ_name+1) == '@')) {
43354925bf6Swillf 		tmp_princ_name += 1;
43454925bf6Swillf 	    } else {
43554925bf6Swillf 		*(princ_name + l) = *tmp_princ_name++;
43654925bf6Swillf 		l++;
43754925bf6Swillf 	    }
43854925bf6Swillf 	}
43954925bf6Swillf 
44054925bf6Swillf 	memset(user_name, 0, strlen(user_name));
44154925bf6Swillf 	/*LINTED*/
44254925bf6Swillf 	sprintf(user_name, "%s", princ_name);
44354925bf6Swillf     }
44454925bf6Swillf 
44554925bf6Swillf cleanup:
44654925bf6Swillf     if (tmp) {
44754925bf6Swillf 	free(tmp);
44854925bf6Swillf 	tmp = NULL;
44954925bf6Swillf     }
45054925bf6Swillf 
45154925bf6Swillf     if (princ_name) {
45254925bf6Swillf 	free(princ_name);
45354925bf6Swillf 	princ_name = NULL;
45454925bf6Swillf     }
45554925bf6Swillf 
45654925bf6Swillf     return st;
45754925bf6Swillf }
45854925bf6Swillf 
45954925bf6Swillf 
46054925bf6Swillf /*
46154925bf6Swillf  * Function: krb5_ldap_parse_principal_name
46254925bf6Swillf  *
46354925bf6Swillf  * Purpose: Inserts '\\' before every occurence of '@'
46454925bf6Swillf  *          in the principal name component.
46554925bf6Swillf  *
46654925bf6Swillf  * Arguments:
46754925bf6Swillf  *       i_princ_name     (input)      Principal name without '\\'
46854925bf6Swillf  *       o_princ_name     (output)     Principal name with '\\'
46954925bf6Swillf  *
47054925bf6Swillf  * Note: The caller has to free the memory allocated for o_princ_name.
47154925bf6Swillf  */
47254925bf6Swillf 
47354925bf6Swillf krb5_error_code
krb5_ldap_parse_principal_name(i_princ_name,o_princ_name)47454925bf6Swillf krb5_ldap_parse_principal_name(i_princ_name, o_princ_name)
47554925bf6Swillf     char              *i_princ_name;
47654925bf6Swillf     char              **o_princ_name;
47754925bf6Swillf {
47854925bf6Swillf     char *tmp_princ_name = NULL, *princ_name = NULL, *at_rlm_name = NULL;
47954925bf6Swillf     int l = 0, m = 0, tmp_princ_name_len = 0, princ_name_len = 0, at_count = 0;
48054925bf6Swillf     krb5_error_code st = 0;
48154925bf6Swillf 
48254925bf6Swillf     at_rlm_name = strrchr(i_princ_name, '@');
48354925bf6Swillf 
48454925bf6Swillf     if (!at_rlm_name) {
48554925bf6Swillf 	*o_princ_name = strdup(i_princ_name);
48654925bf6Swillf 	if (!o_princ_name) {
48754925bf6Swillf 	    st = ENOMEM;
48854925bf6Swillf 	    goto cleanup;
48954925bf6Swillf 	}
49054925bf6Swillf     } else {
49154925bf6Swillf 	tmp_princ_name_len = at_rlm_name - i_princ_name;
49254925bf6Swillf 
49354925bf6Swillf 	tmp_princ_name = (char *) malloc ((unsigned) tmp_princ_name_len + 1);
49454925bf6Swillf 	if (!tmp_princ_name) {
49554925bf6Swillf 	    st = ENOMEM;
49654925bf6Swillf 	    goto cleanup;
49754925bf6Swillf 	}
49854925bf6Swillf 	memset(tmp_princ_name, 0, (unsigned) tmp_princ_name_len + 1);
49954925bf6Swillf 	memcpy(tmp_princ_name, i_princ_name, (unsigned) tmp_princ_name_len);
50054925bf6Swillf 
50154925bf6Swillf 	l = 0;
50254925bf6Swillf 	while (tmp_princ_name[l]) {
50354925bf6Swillf 	    if (tmp_princ_name[l++] == '@')
50454925bf6Swillf 		at_count++;
50554925bf6Swillf 	}
50654925bf6Swillf 
50754925bf6Swillf 	princ_name_len = strlen(i_princ_name) + at_count + 1;
50854925bf6Swillf 	princ_name = (char *) malloc ((unsigned) princ_name_len);
50954925bf6Swillf 	if (!princ_name) {
51054925bf6Swillf 	    st = ENOMEM;
51154925bf6Swillf 	    goto cleanup;
51254925bf6Swillf 	}
51354925bf6Swillf 	memset(princ_name, 0, (unsigned) princ_name_len);
51454925bf6Swillf 
51554925bf6Swillf 	l = 0;
51654925bf6Swillf 	m = 0;
51754925bf6Swillf 	while (tmp_princ_name[l]) {
51854925bf6Swillf 	    if (tmp_princ_name[l] == '@') {
51954925bf6Swillf 		princ_name[m++]='\\';
52054925bf6Swillf 	    }
52154925bf6Swillf 	    princ_name[m++]=tmp_princ_name[l++];
52254925bf6Swillf 	}
52354925bf6Swillf 	/* Solaris Kerberos: using strlcat for safety */
52454925bf6Swillf 	strlcat(princ_name, at_rlm_name, princ_name_len);
52554925bf6Swillf 
52654925bf6Swillf 	*o_princ_name = princ_name;
52754925bf6Swillf     }
52854925bf6Swillf 
52954925bf6Swillf cleanup:
53054925bf6Swillf 
53154925bf6Swillf     if (tmp_princ_name) {
53254925bf6Swillf 	free(tmp_princ_name);
53354925bf6Swillf 	tmp_princ_name = NULL;
53454925bf6Swillf     }
53554925bf6Swillf 
53654925bf6Swillf     return st;
53754925bf6Swillf }
538