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