1*54925bf6Swillf #pragma ident "%Z%%M% %I% %E% SMI" 2*54925bf6Swillf 3*54925bf6Swillf /* 4*54925bf6Swillf * lib/kdb/kdb_ldap/ldap_principal2.c 5*54925bf6Swillf * 6*54925bf6Swillf * Copyright (c) 2004-2005, Novell, Inc. 7*54925bf6Swillf * All rights reserved. 8*54925bf6Swillf * 9*54925bf6Swillf * Redistribution and use in source and binary forms, with or without 10*54925bf6Swillf * modification, are permitted provided that the following conditions are met: 11*54925bf6Swillf * 12*54925bf6Swillf * * Redistributions of source code must retain the above copyright notice, 13*54925bf6Swillf * this list of conditions and the following disclaimer. 14*54925bf6Swillf * * Redistributions in binary form must reproduce the above copyright 15*54925bf6Swillf * notice, this list of conditions and the following disclaimer in the 16*54925bf6Swillf * documentation and/or other materials provided with the distribution. 17*54925bf6Swillf * * The copyright holder's name is not used to endorse or promote products 18*54925bf6Swillf * derived from this software without specific prior written permission. 19*54925bf6Swillf * 20*54925bf6Swillf * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21*54925bf6Swillf * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*54925bf6Swillf * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*54925bf6Swillf * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24*54925bf6Swillf * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25*54925bf6Swillf * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26*54925bf6Swillf * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27*54925bf6Swillf * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28*54925bf6Swillf * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29*54925bf6Swillf * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30*54925bf6Swillf * POSSIBILITY OF SUCH DAMAGE. 31*54925bf6Swillf */ 32*54925bf6Swillf /* 33*54925bf6Swillf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 34*54925bf6Swillf * Use is subject to license terms. 35*54925bf6Swillf */ 36*54925bf6Swillf 37*54925bf6Swillf #include <time.h> 38*54925bf6Swillf #include "ldap_main.h" 39*54925bf6Swillf #include "kdb_ldap.h" 40*54925bf6Swillf #include "ldap_principal.h" 41*54925bf6Swillf #include "princ_xdr.h" 42*54925bf6Swillf #include "ldap_tkt_policy.h" 43*54925bf6Swillf #include "ldap_pwd_policy.h" 44*54925bf6Swillf #include "ldap_err.h" 45*54925bf6Swillf #include <kadm5/admin.h> 46*54925bf6Swillf #include <libintl.h> 47*54925bf6Swillf 48*54925bf6Swillf extern char* principal_attributes[]; 49*54925bf6Swillf extern char* max_pwd_life_attr[]; 50*54925bf6Swillf 51*54925bf6Swillf static char * 52*54925bf6Swillf getstringtime(krb5_timestamp); 53*54925bf6Swillf 54*54925bf6Swillf krb5_error_code 55*54925bf6Swillf berval2tl_data(struct berval *in, krb5_tl_data **out) 56*54925bf6Swillf { 57*54925bf6Swillf *out = (krb5_tl_data *) malloc (sizeof (krb5_tl_data)); 58*54925bf6Swillf if (*out == NULL) 59*54925bf6Swillf return ENOMEM; 60*54925bf6Swillf 61*54925bf6Swillf (*out)->tl_data_length = in->bv_len - 2; 62*54925bf6Swillf (*out)->tl_data_contents = (krb5_octet *) malloc 63*54925bf6Swillf ((*out)->tl_data_length * sizeof (krb5_octet)); 64*54925bf6Swillf if ((*out)->tl_data_contents == NULL) { 65*54925bf6Swillf free (*out); 66*54925bf6Swillf return ENOMEM; 67*54925bf6Swillf } 68*54925bf6Swillf 69*54925bf6Swillf /* Solaris Kerberos: need cast */ 70*54925bf6Swillf UNSTORE16_INT ((unsigned char *)in->bv_val, (*out)->tl_data_type); 71*54925bf6Swillf memcpy ((*out)->tl_data_contents, in->bv_val + 2, (*out)->tl_data_length); 72*54925bf6Swillf 73*54925bf6Swillf return 0; 74*54925bf6Swillf } 75*54925bf6Swillf 76*54925bf6Swillf /* 77*54925bf6Swillf * look up a principal in the directory. 78*54925bf6Swillf */ 79*54925bf6Swillf 80*54925bf6Swillf krb5_error_code 81*54925bf6Swillf krb5_ldap_get_principal(context, searchfor, entries, nentries, more) 82*54925bf6Swillf krb5_context context; 83*54925bf6Swillf krb5_const_principal searchfor; 84*54925bf6Swillf krb5_db_entry *entries; /* filled in */ 85*54925bf6Swillf int *nentries; /* how much room/how many found */ 86*54925bf6Swillf krb5_boolean *more; /* are there more? */ 87*54925bf6Swillf { 88*54925bf6Swillf char *user=NULL, *filter=NULL, **subtree=NULL; 89*54925bf6Swillf unsigned int tree=0, ntrees=1, princlen=0; 90*54925bf6Swillf krb5_error_code tempst=0, st=0; 91*54925bf6Swillf char **values=NULL; 92*54925bf6Swillf LDAP *ld=NULL; 93*54925bf6Swillf LDAPMessage *result=NULL, *ent=NULL; 94*54925bf6Swillf krb5_ldap_context *ldap_context=NULL; 95*54925bf6Swillf kdb5_dal_handle *dal_handle=NULL; 96*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle=NULL; 97*54925bf6Swillf 98*54925bf6Swillf /* Clear the global error string */ 99*54925bf6Swillf krb5_clear_error_message(context); 100*54925bf6Swillf 101*54925bf6Swillf /* set initial values */ 102*54925bf6Swillf *nentries = 0; 103*54925bf6Swillf *more = 0; 104*54925bf6Swillf memset(entries, 0, sizeof(*entries)); 105*54925bf6Swillf 106*54925bf6Swillf if (searchfor == NULL) 107*54925bf6Swillf return EINVAL; 108*54925bf6Swillf 109*54925bf6Swillf dal_handle = (kdb5_dal_handle *) context->db_context; 110*54925bf6Swillf ldap_context = (krb5_ldap_context *) dal_handle->db_context; 111*54925bf6Swillf 112*54925bf6Swillf CHECK_LDAP_HANDLE(ldap_context); 113*54925bf6Swillf 114*54925bf6Swillf if (is_principal_in_realm(ldap_context, searchfor) != 0) { 115*54925bf6Swillf *more = 0; 116*54925bf6Swillf krb5_set_error_message (context, st, gettext("Principal does not belong to realm")); 117*54925bf6Swillf goto cleanup; 118*54925bf6Swillf } 119*54925bf6Swillf 120*54925bf6Swillf if ((st=krb5_unparse_name(context, searchfor, &user)) != 0) 121*54925bf6Swillf goto cleanup; 122*54925bf6Swillf 123*54925bf6Swillf if ((st=krb5_ldap_unparse_principal_name(user)) != 0) 124*54925bf6Swillf goto cleanup; 125*54925bf6Swillf 126*54925bf6Swillf princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */ 127*54925bf6Swillf if ((filter = malloc(princlen)) == NULL) { 128*54925bf6Swillf st = ENOMEM; 129*54925bf6Swillf goto cleanup; 130*54925bf6Swillf } 131*54925bf6Swillf snprintf(filter, princlen, FILTER"%s))", user); 132*54925bf6Swillf 133*54925bf6Swillf if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0) 134*54925bf6Swillf goto cleanup; 135*54925bf6Swillf 136*54925bf6Swillf GET_HANDLE(); 137*54925bf6Swillf for (tree=0; tree < ntrees && *nentries == 0; ++tree) { 138*54925bf6Swillf 139*54925bf6Swillf LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes); 140*54925bf6Swillf for (ent=ldap_first_entry(ld, result); ent != NULL && *nentries == 0; ent=ldap_next_entry(ld, ent)) { 141*54925bf6Swillf 142*54925bf6Swillf /* get the associated directory user information */ 143*54925bf6Swillf if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { 144*54925bf6Swillf int i; 145*54925bf6Swillf 146*54925bf6Swillf /* a wild-card in a principal name can return a list of kerberos principals. 147*54925bf6Swillf * Make sure that the correct principal is returned. 148*54925bf6Swillf * NOTE: a principalname k* in ldap server will return all the principals starting with a k 149*54925bf6Swillf */ 150*54925bf6Swillf for (i=0; values[i] != NULL; ++i) { 151*54925bf6Swillf if (strcasecmp(values[i], user) == 0) { 152*54925bf6Swillf *nentries = 1; 153*54925bf6Swillf break; 154*54925bf6Swillf } 155*54925bf6Swillf } 156*54925bf6Swillf ldap_value_free(values); 157*54925bf6Swillf 158*54925bf6Swillf if (*nentries == 0) /* no matching principal found */ 159*54925bf6Swillf continue; 160*54925bf6Swillf } 161*54925bf6Swillf 162*54925bf6Swillf if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, searchfor, 163*54925bf6Swillf entries)) != 0) 164*54925bf6Swillf goto cleanup; 165*54925bf6Swillf } 166*54925bf6Swillf ldap_msgfree(result); 167*54925bf6Swillf result = NULL; 168*54925bf6Swillf } /* for (tree=0 ... */ 169*54925bf6Swillf 170*54925bf6Swillf /* once done, put back the ldap handle */ 171*54925bf6Swillf krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 172*54925bf6Swillf ldap_server_handle = NULL; 173*54925bf6Swillf 174*54925bf6Swillf cleanup: 175*54925bf6Swillf ldap_msgfree(result); 176*54925bf6Swillf 177*54925bf6Swillf if (*nentries == 0 || st != 0) 178*54925bf6Swillf krb5_dbe_free_contents(context, entries); 179*54925bf6Swillf 180*54925bf6Swillf if (filter) 181*54925bf6Swillf free (filter); 182*54925bf6Swillf 183*54925bf6Swillf if (subtree) { 184*54925bf6Swillf for (; ntrees; --ntrees) 185*54925bf6Swillf if (subtree[ntrees-1]) 186*54925bf6Swillf free (subtree[ntrees-1]); 187*54925bf6Swillf free (subtree); 188*54925bf6Swillf } 189*54925bf6Swillf 190*54925bf6Swillf if (ldap_server_handle) 191*54925bf6Swillf krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 192*54925bf6Swillf 193*54925bf6Swillf if (user) 194*54925bf6Swillf free(user); 195*54925bf6Swillf 196*54925bf6Swillf return st; 197*54925bf6Swillf } 198*54925bf6Swillf 199*54925bf6Swillf typedef enum{ ADD_PRINCIPAL, MODIFY_PRINCIPAL } OPERATION; 200*54925bf6Swillf /* 201*54925bf6Swillf * ptype is creating confusions. Additionally the logic 202*54925bf6Swillf * surronding ptype is redundunt and can be achevied 203*54925bf6Swillf * with the help of dn and containerdn members. 204*54925bf6Swillf * so dropping the ptype member 205*54925bf6Swillf */ 206*54925bf6Swillf 207*54925bf6Swillf typedef struct _xargs_t { 208*54925bf6Swillf char *dn; 209*54925bf6Swillf char *linkdn; 210*54925bf6Swillf krb5_boolean dn_from_kbd; 211*54925bf6Swillf char *containerdn; 212*54925bf6Swillf char *tktpolicydn; 213*54925bf6Swillf }xargs_t; 214*54925bf6Swillf 215*54925bf6Swillf static void 216*54925bf6Swillf free_xargs(xargs) 217*54925bf6Swillf xargs_t xargs; 218*54925bf6Swillf { 219*54925bf6Swillf if (xargs.dn) 220*54925bf6Swillf free (xargs.dn); 221*54925bf6Swillf if (xargs.linkdn) 222*54925bf6Swillf free(xargs.linkdn); 223*54925bf6Swillf if (xargs.containerdn) 224*54925bf6Swillf free (xargs.containerdn); 225*54925bf6Swillf if (xargs.tktpolicydn) 226*54925bf6Swillf free (xargs.tktpolicydn); 227*54925bf6Swillf } 228*54925bf6Swillf 229*54925bf6Swillf static krb5_error_code 230*54925bf6Swillf process_db_args(context, db_args, xargs, optype) 231*54925bf6Swillf krb5_context context; 232*54925bf6Swillf char **db_args; 233*54925bf6Swillf xargs_t *xargs; 234*54925bf6Swillf OPERATION optype; 235*54925bf6Swillf { 236*54925bf6Swillf int i=0; 237*54925bf6Swillf krb5_error_code st=0; 238*54925bf6Swillf char errbuf[1024]; 239*54925bf6Swillf char *arg=NULL, *arg_val=NULL; 240*54925bf6Swillf char **dptr=NULL; 241*54925bf6Swillf unsigned int arg_val_len=0; 242*54925bf6Swillf 243*54925bf6Swillf if (db_args) { 244*54925bf6Swillf for (i=0; db_args[i]; ++i) { 245*54925bf6Swillf arg = strtok_r(db_args[i], "=", &arg_val); 246*54925bf6Swillf if (strcmp(arg, TKTPOLICY_ARG) == 0) { 247*54925bf6Swillf dptr = &xargs->tktpolicydn; 248*54925bf6Swillf } else { 249*54925bf6Swillf if (strcmp(arg, USERDN_ARG) == 0) { 250*54925bf6Swillf if (optype == MODIFY_PRINCIPAL || 251*54925bf6Swillf xargs->dn != NULL || xargs->containerdn != NULL || 252*54925bf6Swillf xargs->linkdn != NULL) { 253*54925bf6Swillf st = EINVAL; 254*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 255*54925bf6Swillf gettext("%s option not supported"), arg); 256*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 257*54925bf6Swillf goto cleanup; 258*54925bf6Swillf } 259*54925bf6Swillf dptr = &xargs->dn; 260*54925bf6Swillf } else if (strcmp(arg, CONTAINERDN_ARG) == 0) { 261*54925bf6Swillf if (optype == MODIFY_PRINCIPAL || 262*54925bf6Swillf xargs->dn != NULL || xargs->containerdn != NULL) { 263*54925bf6Swillf st = EINVAL; 264*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 265*54925bf6Swillf gettext("%s option not supported"), arg); 266*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 267*54925bf6Swillf goto cleanup; 268*54925bf6Swillf } 269*54925bf6Swillf dptr = &xargs->containerdn; 270*54925bf6Swillf } else if (strcmp(arg, LINKDN_ARG) == 0) { 271*54925bf6Swillf if (xargs->dn != NULL || xargs->linkdn != NULL) { 272*54925bf6Swillf st = EINVAL; 273*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 274*54925bf6Swillf gettext("%s option not supported"), arg); 275*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 276*54925bf6Swillf goto cleanup; 277*54925bf6Swillf } 278*54925bf6Swillf dptr = &xargs->linkdn; 279*54925bf6Swillf } else { 280*54925bf6Swillf st = EINVAL; 281*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), gettext("unknown option: %s"), arg); 282*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 283*54925bf6Swillf goto cleanup; 284*54925bf6Swillf } 285*54925bf6Swillf 286*54925bf6Swillf xargs->dn_from_kbd = TRUE; 287*54925bf6Swillf if (arg_val == NULL || strlen(arg_val) == 0) { 288*54925bf6Swillf st = EINVAL; 289*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 290*54925bf6Swillf gettext("%s option value missing"), arg); 291*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 292*54925bf6Swillf goto cleanup; 293*54925bf6Swillf } 294*54925bf6Swillf } 295*54925bf6Swillf 296*54925bf6Swillf if (arg_val == NULL) { 297*54925bf6Swillf st = EINVAL; 298*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 299*54925bf6Swillf gettext("%s option value missing"), arg); 300*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 301*54925bf6Swillf goto cleanup; 302*54925bf6Swillf } 303*54925bf6Swillf arg_val_len = strlen(arg_val) + 1; 304*54925bf6Swillf 305*54925bf6Swillf if (strcmp(arg, TKTPOLICY_ARG) == 0) { 306*54925bf6Swillf if ((st = krb5_ldap_name_to_policydn (context, 307*54925bf6Swillf arg_val, 308*54925bf6Swillf dptr)) != 0) 309*54925bf6Swillf goto cleanup; 310*54925bf6Swillf } else { 311*54925bf6Swillf *dptr = calloc (1, arg_val_len); 312*54925bf6Swillf if (*dptr == NULL) { 313*54925bf6Swillf st = ENOMEM; 314*54925bf6Swillf goto cleanup; 315*54925bf6Swillf } 316*54925bf6Swillf memcpy(*dptr, arg_val, arg_val_len); 317*54925bf6Swillf } 318*54925bf6Swillf } 319*54925bf6Swillf } 320*54925bf6Swillf 321*54925bf6Swillf cleanup: 322*54925bf6Swillf return st; 323*54925bf6Swillf } 324*54925bf6Swillf 325*54925bf6Swillf krb5int_access accessor; 326*54925bf6Swillf extern int kldap_ensure_initialized (void); 327*54925bf6Swillf 328*54925bf6Swillf static krb5_error_code 329*54925bf6Swillf asn1_encode_sequence_of_keys (krb5_key_data *key_data, krb5_int16 n_key_data, 330*54925bf6Swillf krb5_int32 mkvno, krb5_data **code) 331*54925bf6Swillf { 332*54925bf6Swillf krb5_error_code err; 333*54925bf6Swillf 334*54925bf6Swillf /* 335*54925bf6Swillf * This should be pushed back into other library initialization 336*54925bf6Swillf * code. 337*54925bf6Swillf */ 338*54925bf6Swillf err = kldap_ensure_initialized (); 339*54925bf6Swillf if (err) 340*54925bf6Swillf return err; 341*54925bf6Swillf 342*54925bf6Swillf return accessor.asn1_ldap_encode_sequence_of_keys(key_data, n_key_data, 343*54925bf6Swillf mkvno, code); 344*54925bf6Swillf } 345*54925bf6Swillf 346*54925bf6Swillf static krb5_error_code 347*54925bf6Swillf asn1_decode_sequence_of_keys (krb5_data *in, krb5_key_data **out, 348*54925bf6Swillf krb5_int16 *n_key_data, int *mkvno) 349*54925bf6Swillf { 350*54925bf6Swillf krb5_error_code err; 351*54925bf6Swillf 352*54925bf6Swillf /* 353*54925bf6Swillf * This should be pushed back into other library initialization 354*54925bf6Swillf * code. 355*54925bf6Swillf */ 356*54925bf6Swillf err = kldap_ensure_initialized (); 357*54925bf6Swillf if (err) 358*54925bf6Swillf return err; 359*54925bf6Swillf 360*54925bf6Swillf return accessor.asn1_ldap_decode_sequence_of_keys(in, out, n_key_data, 361*54925bf6Swillf mkvno); 362*54925bf6Swillf } 363*54925bf6Swillf 364*54925bf6Swillf 365*54925bf6Swillf /* Decoding ASN.1 encoded key */ 366*54925bf6Swillf static struct berval ** 367*54925bf6Swillf krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data) { 368*54925bf6Swillf struct berval **ret = NULL; 369*54925bf6Swillf int currkvno; 370*54925bf6Swillf int num_versions = 1; 371*54925bf6Swillf int i, j, last; 372*54925bf6Swillf krb5_error_code err = 0; 373*54925bf6Swillf 374*54925bf6Swillf if (n_key_data <= 0) 375*54925bf6Swillf return NULL; 376*54925bf6Swillf 377*54925bf6Swillf /* Find the number of key versions */ 378*54925bf6Swillf for (i = 0; i < n_key_data - 1; i++) 379*54925bf6Swillf if (key_data[i].key_data_kvno != key_data[i + 1].key_data_kvno) 380*54925bf6Swillf num_versions++; 381*54925bf6Swillf 382*54925bf6Swillf ret = (struct berval **) calloc (num_versions + 1, sizeof (struct berval *)); 383*54925bf6Swillf if (ret == NULL) { 384*54925bf6Swillf err = ENOMEM; 385*54925bf6Swillf goto cleanup; 386*54925bf6Swillf } 387*54925bf6Swillf for (i = 0, last = 0, j = 0, currkvno = key_data[0].key_data_kvno; i < n_key_data; i++) { 388*54925bf6Swillf krb5_data *code; 389*54925bf6Swillf if (i == n_key_data - 1 || key_data[i + 1].key_data_kvno != currkvno) { 390*54925bf6Swillf code = NULL; 391*54925bf6Swillf asn1_encode_sequence_of_keys (key_data+last, 392*54925bf6Swillf (krb5_int16) i - last + 1, 393*54925bf6Swillf 0, /* For now, mkvno == 0*/ 394*54925bf6Swillf &code); 395*54925bf6Swillf if (code == NULL) { 396*54925bf6Swillf err = ENOMEM; 397*54925bf6Swillf goto cleanup; 398*54925bf6Swillf } 399*54925bf6Swillf ret[j] = malloc (sizeof (struct berval)); 400*54925bf6Swillf if (ret[j] == NULL) { 401*54925bf6Swillf err = ENOMEM; 402*54925bf6Swillf goto cleanup; 403*54925bf6Swillf } 404*54925bf6Swillf /*CHECK_NULL(ret[j]); */ 405*54925bf6Swillf ret[j]->bv_len = code->length; 406*54925bf6Swillf ret[j]->bv_val = code->data; 407*54925bf6Swillf j++; 408*54925bf6Swillf last = i + 1; 409*54925bf6Swillf 410*54925bf6Swillf currkvno = key_data[i].key_data_kvno; 411*54925bf6Swillf /* Solaris Kerberos: fix memleak */ 412*54925bf6Swillf free(code); 413*54925bf6Swillf } 414*54925bf6Swillf } 415*54925bf6Swillf ret[num_versions] = NULL; 416*54925bf6Swillf 417*54925bf6Swillf cleanup: 418*54925bf6Swillf 419*54925bf6Swillf if (err != 0) { 420*54925bf6Swillf if (ret != NULL) { 421*54925bf6Swillf for (i = 0; i <= num_versions; i++) 422*54925bf6Swillf if (ret[i] != NULL) 423*54925bf6Swillf free (ret[i]); 424*54925bf6Swillf free (ret); 425*54925bf6Swillf ret = NULL; 426*54925bf6Swillf } 427*54925bf6Swillf } 428*54925bf6Swillf 429*54925bf6Swillf return ret; 430*54925bf6Swillf } 431*54925bf6Swillf 432*54925bf6Swillf static krb5_error_code tl_data2berval (krb5_tl_data *in, struct berval **out) { 433*54925bf6Swillf *out = (struct berval *) malloc (sizeof (struct berval)); 434*54925bf6Swillf if (*out == NULL) 435*54925bf6Swillf return ENOMEM; 436*54925bf6Swillf 437*54925bf6Swillf (*out)->bv_len = in->tl_data_length + 2; 438*54925bf6Swillf (*out)->bv_val = (char *) malloc ((*out)->bv_len); 439*54925bf6Swillf if ((*out)->bv_val == NULL) { 440*54925bf6Swillf free (*out); 441*54925bf6Swillf return ENOMEM; 442*54925bf6Swillf } 443*54925bf6Swillf 444*54925bf6Swillf /* Solaris Kerberos: need cast */ 445*54925bf6Swillf STORE16_INT((unsigned char *)(*out)->bv_val, in->tl_data_type); 446*54925bf6Swillf memcpy ((*out)->bv_val + 2, in->tl_data_contents, in->tl_data_length); 447*54925bf6Swillf 448*54925bf6Swillf return 0; 449*54925bf6Swillf } 450*54925bf6Swillf 451*54925bf6Swillf krb5_error_code 452*54925bf6Swillf krb5_ldap_put_principal(context, entries, nentries, db_args) 453*54925bf6Swillf krb5_context context; 454*54925bf6Swillf krb5_db_entry *entries; 455*54925bf6Swillf register int *nentries; /* number of entry structs to update */ 456*54925bf6Swillf char **db_args; 457*54925bf6Swillf { 458*54925bf6Swillf int i=0, l=0, kerberos_principal_object_type=0; 459*54925bf6Swillf krb5_error_code st=0, tempst=0; 460*54925bf6Swillf LDAP *ld=NULL; 461*54925bf6Swillf LDAPMessage *result=NULL, *ent=NULL; 462*54925bf6Swillf char *user=NULL, *subtree=NULL, *principal_dn=NULL; 463*54925bf6Swillf char **values=NULL, *strval[10]={NULL}, errbuf[1024]; 464*54925bf6Swillf struct berval **bersecretkey=NULL; 465*54925bf6Swillf LDAPMod **mods=NULL; 466*54925bf6Swillf krb5_boolean create_standalone_prinicipal=FALSE; 467*54925bf6Swillf krb5_boolean krb_identity_exists=FALSE, establish_links=FALSE; 468*54925bf6Swillf char *standalone_principal_dn=NULL; 469*54925bf6Swillf krb5_tl_data *tl_data=NULL; 470*54925bf6Swillf kdb5_dal_handle *dal_handle=NULL; 471*54925bf6Swillf krb5_ldap_context *ldap_context=NULL; 472*54925bf6Swillf krb5_ldap_server_handle *ldap_server_handle=NULL; 473*54925bf6Swillf osa_princ_ent_rec princ_ent; 474*54925bf6Swillf xargs_t xargs = {0}; 475*54925bf6Swillf char *polname = NULL; 476*54925bf6Swillf OPERATION optype; 477*54925bf6Swillf krb5_boolean found_entry = FALSE; 478*54925bf6Swillf struct berval **ber_tl_data = NULL; 479*54925bf6Swillf 480*54925bf6Swillf /* Clear the global error string */ 481*54925bf6Swillf krb5_clear_error_message(context); 482*54925bf6Swillf 483*54925bf6Swillf SETUP_CONTEXT(); 484*54925bf6Swillf if (ldap_context->lrparams == NULL || ldap_context->krbcontainer == NULL) 485*54925bf6Swillf return EINVAL; 486*54925bf6Swillf 487*54925bf6Swillf /* get ldap handle */ 488*54925bf6Swillf GET_HANDLE(); 489*54925bf6Swillf 490*54925bf6Swillf for (i=0; i < *nentries; ++i, ++entries) { 491*54925bf6Swillf if (is_principal_in_realm(ldap_context, entries->princ) != 0) { 492*54925bf6Swillf st = EINVAL; 493*54925bf6Swillf krb5_set_error_message(context, st, gettext("Principal does not belong to the default realm")); 494*54925bf6Swillf goto cleanup; 495*54925bf6Swillf } 496*54925bf6Swillf 497*54925bf6Swillf /* get the principal information to act on */ 498*54925bf6Swillf if (entries->princ) { 499*54925bf6Swillf if (((st=krb5_unparse_name(context, entries->princ, &user)) != 0) || 500*54925bf6Swillf ((st=krb5_ldap_unparse_principal_name(user)) != 0)) 501*54925bf6Swillf goto cleanup; 502*54925bf6Swillf } 503*54925bf6Swillf 504*54925bf6Swillf /* Identity the type of operation, it can be 505*54925bf6Swillf * add principal or modify principal. 506*54925bf6Swillf * hack if the entries->mask has KRB_PRINCIPAL flag set 507*54925bf6Swillf * then it is a add operation 508*54925bf6Swillf */ 509*54925bf6Swillf if (entries->mask & KADM5_PRINCIPAL) 510*54925bf6Swillf optype = ADD_PRINCIPAL; 511*54925bf6Swillf else 512*54925bf6Swillf optype = MODIFY_PRINCIPAL; 513*54925bf6Swillf 514*54925bf6Swillf if (((st=krb5_get_princ_type(context, entries, &kerberos_principal_object_type)) != 0) || 515*54925bf6Swillf ((st=krb5_get_userdn(context, entries, &principal_dn)) != 0)) 516*54925bf6Swillf goto cleanup; 517*54925bf6Swillf 518*54925bf6Swillf if ((st=process_db_args(context, db_args, &xargs, optype)) != 0) 519*54925bf6Swillf goto cleanup; 520*54925bf6Swillf 521*54925bf6Swillf if (entries->mask & KADM5_LOAD) { 522*54925bf6Swillf int tree = 0, princlen = 0, numlentries = 0; 523*54925bf6Swillf unsigned int ntrees = 0; 524*54925bf6Swillf char **subtreelist = NULL, *filter = NULL; 525*54925bf6Swillf 526*54925bf6Swillf /* A load operation is special, will do a mix-in (add krbprinc 527*54925bf6Swillf * attrs to a non-krb object entry) if an object exists with a 528*54925bf6Swillf * matching krbprincipalname attribute so try to find existing 529*54925bf6Swillf * object and set principal_dn. This assumes that the 530*54925bf6Swillf * krbprincipalname attribute is unique (only one object entry has 531*54925bf6Swillf * a particular krbprincipalname attribute). 532*54925bf6Swillf */ 533*54925bf6Swillf if (user == NULL) { 534*54925bf6Swillf /* must have principal name for search */ 535*54925bf6Swillf st = EINVAL; 536*54925bf6Swillf krb5_set_error_message(context, st, gettext("operation can not continue, principal name not found")); 537*54925bf6Swillf goto cleanup; 538*54925bf6Swillf } 539*54925bf6Swillf princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */ 540*54925bf6Swillf if ((filter = malloc(princlen)) == NULL) { 541*54925bf6Swillf st = ENOMEM; 542*54925bf6Swillf goto cleanup; 543*54925bf6Swillf } 544*54925bf6Swillf snprintf(filter, princlen, FILTER"%s))", user); 545*54925bf6Swillf 546*54925bf6Swillf /* get the current subtree list */ 547*54925bf6Swillf if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) 548*54925bf6Swillf goto cleanup; 549*54925bf6Swillf 550*54925bf6Swillf found_entry = FALSE; 551*54925bf6Swillf /* search for entry with matching krbprincipalname attribute */ 552*54925bf6Swillf for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) { 553*54925bf6Swillf result = NULL; 554*54925bf6Swillf if (principal_dn == NULL) { 555*54925bf6Swillf LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS); 556*54925bf6Swillf } else { 557*54925bf6Swillf /* just look for entry with principal_dn */ 558*54925bf6Swillf LDAP_SEARCH_1(principal_dn, LDAP_SCOPE_BASE, filter, principal_attributes, IGNORE_STATUS); 559*54925bf6Swillf } 560*54925bf6Swillf if (st == LDAP_SUCCESS) { 561*54925bf6Swillf numlentries = ldap_count_entries(ld, result); 562*54925bf6Swillf if (numlentries > 1) { 563*54925bf6Swillf ldap_msgfree(result); 564*54925bf6Swillf free(filter); 565*54925bf6Swillf st = EINVAL; 566*54925bf6Swillf krb5_set_error_message(context, st, 567*54925bf6Swillf gettext("operation can not continue, more than one entry with principal name \"%s\" found"), 568*54925bf6Swillf user); 569*54925bf6Swillf goto cleanup; 570*54925bf6Swillf } else if (numlentries == 1) { 571*54925bf6Swillf found_entry = TRUE; 572*54925bf6Swillf if (principal_dn == NULL) { 573*54925bf6Swillf ent = ldap_first_entry(ld, result); 574*54925bf6Swillf if (ent != NULL) { 575*54925bf6Swillf /* setting principal_dn will cause that entry to be modified further down */ 576*54925bf6Swillf if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) { 577*54925bf6Swillf ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); 578*54925bf6Swillf st = set_ldap_error (context, st, 0); 579*54925bf6Swillf ldap_msgfree(result); 580*54925bf6Swillf free(filter); 581*54925bf6Swillf goto cleanup; 582*54925bf6Swillf } 583*54925bf6Swillf } 584*54925bf6Swillf } 585*54925bf6Swillf } 586*54925bf6Swillf if (result) 587*54925bf6Swillf ldap_msgfree(result); 588*54925bf6Swillf } else if (st != LDAP_NO_SUCH_OBJECT) { 589*54925bf6Swillf /* could not perform search, return with failure */ 590*54925bf6Swillf st = set_ldap_error (context, st, 0); 591*54925bf6Swillf free(filter); 592*54925bf6Swillf goto cleanup; 593*54925bf6Swillf } 594*54925bf6Swillf /* 595*54925bf6Swillf * If it isn't found then assume a standalone princ entry is to 596*54925bf6Swillf * be created. 597*54925bf6Swillf */ 598*54925bf6Swillf } /* end for (tree = 0; principal_dn == ... */ 599*54925bf6Swillf 600*54925bf6Swillf free(filter); 601*54925bf6Swillf 602*54925bf6Swillf if (found_entry == FALSE && principal_dn != NULL) { 603*54925bf6Swillf /* 604*54925bf6Swillf * if principal_dn is null then there is code further down to 605*54925bf6Swillf * deal with setting standalone_principal_dn. Also note that 606*54925bf6Swillf * this will set create_standalone_prinicipal true for 607*54925bf6Swillf * non-mix-in entries which is okay if loading from a dump. 608*54925bf6Swillf */ 609*54925bf6Swillf create_standalone_prinicipal = TRUE; 610*54925bf6Swillf standalone_principal_dn = strdup(principal_dn); 611*54925bf6Swillf CHECK_NULL(standalone_principal_dn); 612*54925bf6Swillf } 613*54925bf6Swillf } /* end if (entries->mask & KADM5_LOAD */ 614*54925bf6Swillf 615*54925bf6Swillf /* time to generate the DN information with the help of 616*54925bf6Swillf * containerdn, principalcontainerreference or 617*54925bf6Swillf * realmcontainerdn information 618*54925bf6Swillf */ 619*54925bf6Swillf if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */ 620*54925bf6Swillf /* get the subtree information */ 621*54925bf6Swillf if (entries->princ->length == 2 && entries->princ->data[0].length == strlen("krbtgt") && 622*54925bf6Swillf strncmp(entries->princ->data[0].data, "krbtgt", entries->princ->data[0].length) == 0) { 623*54925bf6Swillf /* if the principal is a inter-realm principal, always created in the realm container */ 624*54925bf6Swillf subtree = strdup(ldap_context->lrparams->realmdn); 625*54925bf6Swillf } else if (xargs.containerdn) { 626*54925bf6Swillf if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) { 627*54925bf6Swillf if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) { 628*54925bf6Swillf int ost = st; 629*54925bf6Swillf st = EINVAL; 630*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), gettext("'%s' not found: "), xargs.containerdn); 631*54925bf6Swillf prepend_err_str(context, errbuf, st, ost); 632*54925bf6Swillf } 633*54925bf6Swillf goto cleanup; 634*54925bf6Swillf } 635*54925bf6Swillf subtree = strdup(xargs.containerdn); 636*54925bf6Swillf } else if (ldap_context->lrparams->containerref && strlen(ldap_context->lrparams->containerref) != 0) { 637*54925bf6Swillf /* 638*54925bf6Swillf * Here the subtree should be changed with 639*54925bf6Swillf * principalcontainerreference attribute value 640*54925bf6Swillf */ 641*54925bf6Swillf subtree = strdup(ldap_context->lrparams->containerref); 642*54925bf6Swillf } else { 643*54925bf6Swillf subtree = strdup(ldap_context->lrparams->realmdn); 644*54925bf6Swillf } 645*54925bf6Swillf CHECK_NULL(subtree); 646*54925bf6Swillf 647*54925bf6Swillf standalone_principal_dn = malloc(strlen("krbprincipalname=") + strlen(user) + strlen(",") + 648*54925bf6Swillf strlen(subtree) + 1); 649*54925bf6Swillf CHECK_NULL(standalone_principal_dn); 650*54925bf6Swillf /*LINTED*/ 651*54925bf6Swillf sprintf(standalone_principal_dn, "krbprincipalname=%s,%s", user, subtree); 652*54925bf6Swillf /* 653*54925bf6Swillf * free subtree when you are done using the subtree 654*54925bf6Swillf * set the boolean create_standalone_prinicipal to TRUE 655*54925bf6Swillf */ 656*54925bf6Swillf create_standalone_prinicipal = TRUE; 657*54925bf6Swillf free(subtree); 658*54925bf6Swillf subtree = NULL; 659*54925bf6Swillf } 660*54925bf6Swillf 661*54925bf6Swillf /* 662*54925bf6Swillf * If the DN information is presented by the user, time to 663*54925bf6Swillf * validate the input to ensure that the DN falls under 664*54925bf6Swillf * any of the subtrees 665*54925bf6Swillf */ 666*54925bf6Swillf if (xargs.dn_from_kbd == TRUE) { 667*54925bf6Swillf /* make sure the DN falls in the subtree */ 668*54925bf6Swillf int tre=0, dnlen=0, subtreelen=0; 669*54925bf6Swillf unsigned int ntrees = 0; 670*54925bf6Swillf char **subtreelist=NULL; 671*54925bf6Swillf char *dn=NULL; 672*54925bf6Swillf krb5_boolean outofsubtree=TRUE; 673*54925bf6Swillf 674*54925bf6Swillf if (xargs.dn != NULL) { 675*54925bf6Swillf dn = xargs.dn; 676*54925bf6Swillf } else if (xargs.linkdn != NULL) { 677*54925bf6Swillf dn = xargs.linkdn; 678*54925bf6Swillf } else if (standalone_principal_dn != NULL) { 679*54925bf6Swillf /* 680*54925bf6Swillf * Even though the standalone_principal_dn is constructed 681*54925bf6Swillf * within this function, there is the containerdn input 682*54925bf6Swillf * from the user that can become part of the it. 683*54925bf6Swillf */ 684*54925bf6Swillf dn = standalone_principal_dn; 685*54925bf6Swillf } 686*54925bf6Swillf 687*54925bf6Swillf /* get the current subtree list */ 688*54925bf6Swillf if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) 689*54925bf6Swillf goto cleanup; 690*54925bf6Swillf 691*54925bf6Swillf for (tre=0; tre<ntrees; ++tre) { 692*54925bf6Swillf if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) { 693*54925bf6Swillf outofsubtree = FALSE; 694*54925bf6Swillf break; 695*54925bf6Swillf } else { 696*54925bf6Swillf dnlen = strlen (dn); 697*54925bf6Swillf subtreelen = strlen(subtreelist[tre]); 698*54925bf6Swillf if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) { 699*54925bf6Swillf outofsubtree = FALSE; 700*54925bf6Swillf break; 701*54925bf6Swillf } 702*54925bf6Swillf } 703*54925bf6Swillf } 704*54925bf6Swillf 705*54925bf6Swillf for (tre=0; tre < ntrees; ++tre) { 706*54925bf6Swillf free(subtreelist[tre]); 707*54925bf6Swillf } 708*54925bf6Swillf 709*54925bf6Swillf if (outofsubtree == TRUE) { 710*54925bf6Swillf st = EINVAL; 711*54925bf6Swillf krb5_set_error_message(context, st, gettext("DN is out of the realm subtree")); 712*54925bf6Swillf goto cleanup; 713*54925bf6Swillf } 714*54925bf6Swillf 715*54925bf6Swillf /* 716*54925bf6Swillf * dn value will be set either by dn, linkdn or the standalone_principal_dn 717*54925bf6Swillf * In the first 2 cases, the dn should be existing and in the last case we 718*54925bf6Swillf * are supposed to create the ldap object. so the below should not be 719*54925bf6Swillf * executed for the last case. 720*54925bf6Swillf */ 721*54925bf6Swillf 722*54925bf6Swillf if (standalone_principal_dn == NULL) { 723*54925bf6Swillf /* 724*54925bf6Swillf * If the ldap object is missing, this results in an error. 725*54925bf6Swillf */ 726*54925bf6Swillf 727*54925bf6Swillf /* 728*54925bf6Swillf * Search for krbprincipalname attribute here. 729*54925bf6Swillf * This is to find if a kerberos identity is already present 730*54925bf6Swillf * on the ldap object, in which case adding a kerberos identity 731*54925bf6Swillf * on the ldap object should result in an error. 732*54925bf6Swillf */ 733*54925bf6Swillf char *attributes[]={"krbticketpolicyreference", "krbprincipalname", NULL}; 734*54925bf6Swillf 735*54925bf6Swillf LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS); 736*54925bf6Swillf if (st == LDAP_SUCCESS) { 737*54925bf6Swillf ent = ldap_first_entry(ld, result); 738*54925bf6Swillf if (ent != NULL) { 739*54925bf6Swillf if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) { 740*54925bf6Swillf ldap_value_free(values); 741*54925bf6Swillf } 742*54925bf6Swillf 743*54925bf6Swillf if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { 744*54925bf6Swillf krb_identity_exists = TRUE; 745*54925bf6Swillf ldap_value_free(values); 746*54925bf6Swillf } 747*54925bf6Swillf } 748*54925bf6Swillf ldap_msgfree(result); 749*54925bf6Swillf } else { 750*54925bf6Swillf st = set_ldap_error(context, st, OP_SEARCH); 751*54925bf6Swillf goto cleanup; 752*54925bf6Swillf } 753*54925bf6Swillf } 754*54925bf6Swillf } 755*54925bf6Swillf 756*54925bf6Swillf /* 757*54925bf6Swillf * If xargs.dn is set then the request is to add a 758*54925bf6Swillf * kerberos principal on a ldap object, but if 759*54925bf6Swillf * there is one already on the ldap object this 760*54925bf6Swillf * should result in an error. 761*54925bf6Swillf */ 762*54925bf6Swillf 763*54925bf6Swillf if (xargs.dn != NULL && krb_identity_exists == TRUE) { 764*54925bf6Swillf st = EINVAL; 765*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), gettext("ldap object is already kerberized")); 766*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 767*54925bf6Swillf goto cleanup; 768*54925bf6Swillf } 769*54925bf6Swillf 770*54925bf6Swillf if (xargs.linkdn != NULL) { 771*54925bf6Swillf /* 772*54925bf6Swillf * link information can be changed using modprinc. 773*54925bf6Swillf * However, link information can be changed only on the 774*54925bf6Swillf * standalone kerberos principal objects. A standalone 775*54925bf6Swillf * kerberos principal object is of type krbprincipal 776*54925bf6Swillf * structural objectclass. 777*54925bf6Swillf * 778*54925bf6Swillf * NOTE: kerberos principals on an ldap object can't be 779*54925bf6Swillf * linked to other ldap objects. 780*54925bf6Swillf */ 781*54925bf6Swillf if (optype == MODIFY_PRINCIPAL && 782*54925bf6Swillf kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) { 783*54925bf6Swillf st = EINVAL; 784*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 785*54925bf6Swillf gettext("link information can not be set/updated as the kerberos principal belongs to an ldap object")); 786*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 787*54925bf6Swillf goto cleanup; 788*54925bf6Swillf } 789*54925bf6Swillf /* 790*54925bf6Swillf * Check the link information. If there is already a link 791*54925bf6Swillf * existing then this operation is not allowed. 792*54925bf6Swillf */ 793*54925bf6Swillf { 794*54925bf6Swillf char **linkdns=NULL; 795*54925bf6Swillf int j=0; 796*54925bf6Swillf 797*54925bf6Swillf if ((st=krb5_get_linkdn(context, entries, &linkdns)) != 0) { 798*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 799*54925bf6Swillf gettext("Failed getting object references")); 800*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 801*54925bf6Swillf goto cleanup; 802*54925bf6Swillf } 803*54925bf6Swillf if (linkdns != NULL) { 804*54925bf6Swillf st = EINVAL; 805*54925bf6Swillf snprintf(errbuf, sizeof(errbuf), 806*54925bf6Swillf gettext("kerberos principal is already linked " 807*54925bf6Swillf "to a ldap object")); 808*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 809*54925bf6Swillf for (j=0; linkdns[j] != NULL; ++j) 810*54925bf6Swillf free (linkdns[j]); 811*54925bf6Swillf free (linkdns); 812*54925bf6Swillf goto cleanup; 813*54925bf6Swillf } 814*54925bf6Swillf } 815*54925bf6Swillf 816*54925bf6Swillf establish_links = TRUE; 817*54925bf6Swillf } 818*54925bf6Swillf 819*54925bf6Swillf if ((entries->last_success)!=0) { 820*54925bf6Swillf memset(strval, 0, sizeof(strval)); 821*54925bf6Swillf if ((strval[0]=getstringtime(entries->last_success)) == NULL) 822*54925bf6Swillf goto cleanup; 823*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastSuccessfulAuth", LDAP_MOD_REPLACE, strval)) != 0) { 824*54925bf6Swillf free (strval[0]); 825*54925bf6Swillf goto cleanup; 826*54925bf6Swillf } 827*54925bf6Swillf free (strval[0]); 828*54925bf6Swillf } 829*54925bf6Swillf 830*54925bf6Swillf if (entries->last_failed!=0) { 831*54925bf6Swillf memset(strval, 0, sizeof(strval)); 832*54925bf6Swillf if ((strval[0]=getstringtime(entries->last_failed)) == NULL) 833*54925bf6Swillf goto cleanup; 834*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastFailedAuth", LDAP_MOD_REPLACE, strval)) != 0) { 835*54925bf6Swillf free (strval[0]); 836*54925bf6Swillf goto cleanup; 837*54925bf6Swillf } 838*54925bf6Swillf free(strval[0]); 839*54925bf6Swillf } 840*54925bf6Swillf 841*54925bf6Swillf if (entries->fail_auth_count!=0) { 842*54925bf6Swillf if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_REPLACE, entries->fail_auth_count)) !=0) 843*54925bf6Swillf goto cleanup; 844*54925bf6Swillf } 845*54925bf6Swillf 846*54925bf6Swillf if (entries->mask & KADM5_MAX_LIFE) { 847*54925bf6Swillf if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entries->max_life)) != 0) 848*54925bf6Swillf goto cleanup; 849*54925bf6Swillf } 850*54925bf6Swillf 851*54925bf6Swillf if (entries->mask & KADM5_MAX_RLIFE) { 852*54925bf6Swillf if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE, 853*54925bf6Swillf entries->max_renewable_life)) != 0) 854*54925bf6Swillf goto cleanup; 855*54925bf6Swillf } 856*54925bf6Swillf 857*54925bf6Swillf if (entries->mask & KADM5_ATTRIBUTES) { 858*54925bf6Swillf if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE, 859*54925bf6Swillf entries->attributes)) != 0) 860*54925bf6Swillf goto cleanup; 861*54925bf6Swillf } 862*54925bf6Swillf 863*54925bf6Swillf if (entries->mask & KADM5_PRINCIPAL) { 864*54925bf6Swillf memset(strval, 0, sizeof(strval)); 865*54925bf6Swillf strval[0] = user; 866*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0) 867*54925bf6Swillf goto cleanup; 868*54925bf6Swillf } 869*54925bf6Swillf 870*54925bf6Swillf /* 871*54925bf6Swillf * Solaris Kerberos: this logic was not working properly when 872*54925bf6Swillf * default_principal_expiration set. 873*54925bf6Swillf */ 874*54925bf6Swillf if (entries->mask & KADM5_PRINC_EXPIRE_TIME || entries->expiration != 0) { 875*54925bf6Swillf memset(strval, 0, sizeof(strval)); 876*54925bf6Swillf if ((strval[0]=getstringtime(entries->expiration)) == NULL) 877*54925bf6Swillf goto cleanup; 878*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) { 879*54925bf6Swillf free (strval[0]); 880*54925bf6Swillf goto cleanup; 881*54925bf6Swillf } 882*54925bf6Swillf free (strval[0]); 883*54925bf6Swillf } 884*54925bf6Swillf 885*54925bf6Swillf /* 886*54925bf6Swillf * Solaris Kerberos: in case KADM5_PW_EXPIRATION isn't set, check 887*54925bf6Swillf * pw_expiration 888*54925bf6Swillf */ 889*54925bf6Swillf if (entries->mask & KADM5_PW_EXPIRATION || entries->pw_expiration != 0) { 890*54925bf6Swillf memset(strval, 0, sizeof(strval)); 891*54925bf6Swillf if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL) 892*54925bf6Swillf goto cleanup; 893*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration", 894*54925bf6Swillf LDAP_MOD_REPLACE, 895*54925bf6Swillf strval)) != 0) { 896*54925bf6Swillf free (strval[0]); 897*54925bf6Swillf goto cleanup; 898*54925bf6Swillf } 899*54925bf6Swillf free (strval[0]); 900*54925bf6Swillf } 901*54925bf6Swillf 902*54925bf6Swillf if (entries->mask & KADM5_POLICY) { 903*54925bf6Swillf memset(&princ_ent, 0, sizeof(princ_ent)); 904*54925bf6Swillf for (tl_data=entries->tl_data; tl_data; tl_data=tl_data->tl_data_next) { 905*54925bf6Swillf if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) { 906*54925bf6Swillf /* FIX ME: I guess the princ_ent should be freed after this call */ 907*54925bf6Swillf if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) { 908*54925bf6Swillf goto cleanup; 909*54925bf6Swillf } 910*54925bf6Swillf } 911*54925bf6Swillf } 912*54925bf6Swillf 913*54925bf6Swillf if (princ_ent.aux_attributes & KADM5_POLICY) { 914*54925bf6Swillf memset(strval, 0, sizeof(strval)); 915*54925bf6Swillf if ((st = krb5_ldap_name_to_policydn (context, princ_ent.policy, &polname)) != 0) 916*54925bf6Swillf goto cleanup; 917*54925bf6Swillf strval[0] = polname; 918*54925bf6Swillf /* Solaris Kerberos: fix memleak */ 919*54925bf6Swillf free(princ_ent.policy); 920*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) 921*54925bf6Swillf goto cleanup; 922*54925bf6Swillf } else { 923*54925bf6Swillf st = EINVAL; 924*54925bf6Swillf krb5_set_error_message(context, st, gettext("Password policy value null")); 925*54925bf6Swillf goto cleanup; 926*54925bf6Swillf } 927*54925bf6Swillf } else if (entries->mask & KADM5_LOAD && found_entry == TRUE) { 928*54925bf6Swillf /* 929*54925bf6Swillf * a load is special in that existing entries must have attrs that 930*54925bf6Swillf * removed. 931*54925bf6Swillf */ 932*54925bf6Swillf 933*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0) 934*54925bf6Swillf goto cleanup; 935*54925bf6Swillf } 936*54925bf6Swillf 937*54925bf6Swillf if (entries->mask & KADM5_POLICY_CLR) { 938*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) 939*54925bf6Swillf goto cleanup; 940*54925bf6Swillf } 941*54925bf6Swillf 942*54925bf6Swillf if (entries->mask & KADM5_KEY_DATA || entries->mask & KADM5_KVNO) { 943*54925bf6Swillf bersecretkey = krb5_encode_krbsecretkey (entries->key_data, 944*54925bf6Swillf entries->n_key_data); 945*54925bf6Swillf 946*54925bf6Swillf if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", 947*54925bf6Swillf LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, bersecretkey)) != 0) 948*54925bf6Swillf goto cleanup; 949*54925bf6Swillf 950*54925bf6Swillf if (!(entries->mask & KADM5_PRINCIPAL)) { 951*54925bf6Swillf memset(strval, 0, sizeof(strval)); 952*54925bf6Swillf if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL) 953*54925bf6Swillf goto cleanup; 954*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, 955*54925bf6Swillf "krbpasswordexpiration", 956*54925bf6Swillf LDAP_MOD_REPLACE, strval)) != 0) { 957*54925bf6Swillf free (strval[0]); 958*54925bf6Swillf goto cleanup; 959*54925bf6Swillf } 960*54925bf6Swillf free (strval[0]); 961*54925bf6Swillf } 962*54925bf6Swillf 963*54925bf6Swillf /* Update last password change whenever a new key is set */ 964*54925bf6Swillf { 965*54925bf6Swillf krb5_timestamp last_pw_changed; 966*54925bf6Swillf if ((st=krb5_dbe_lookup_last_pwd_change(context, entries, 967*54925bf6Swillf &last_pw_changed)) != 0) 968*54925bf6Swillf goto cleanup; 969*54925bf6Swillf 970*54925bf6Swillf memset(strval, 0, sizeof(strval)); 971*54925bf6Swillf if ((strval[0] = getstringtime(last_pw_changed)) == NULL) 972*54925bf6Swillf goto cleanup; 973*54925bf6Swillf 974*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastPwdChange", 975*54925bf6Swillf LDAP_MOD_REPLACE, strval)) != 0) { 976*54925bf6Swillf free (strval[0]); 977*54925bf6Swillf goto cleanup; 978*54925bf6Swillf } 979*54925bf6Swillf free (strval[0]); 980*54925bf6Swillf } 981*54925bf6Swillf 982*54925bf6Swillf } /* Modify Key data ends here */ 983*54925bf6Swillf 984*54925bf6Swillf /* Set tl_data */ 985*54925bf6Swillf if (entries->tl_data != NULL) { 986*54925bf6Swillf int count = 0; 987*54925bf6Swillf /* struct berval **ber_tl_data = NULL; */ 988*54925bf6Swillf krb5_tl_data *ptr; 989*54925bf6Swillf for (ptr = entries->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { 990*54925bf6Swillf if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE 991*54925bf6Swillf #ifdef SECURID 992*54925bf6Swillf || ptr->tl_data_type == KRB5_TL_DB_ARGS 993*54925bf6Swillf #endif 994*54925bf6Swillf || ptr->tl_data_type == KRB5_TL_KADM_DATA 995*54925bf6Swillf || ptr->tl_data_type == KDB_TL_USER_INFO) 996*54925bf6Swillf continue; 997*54925bf6Swillf count++; 998*54925bf6Swillf } 999*54925bf6Swillf if (count != 0) { 1000*54925bf6Swillf int j; 1001*54925bf6Swillf ber_tl_data = (struct berval **) calloc (count + 1, 1002*54925bf6Swillf sizeof (struct berval*)); 1003*54925bf6Swillf if (ber_tl_data == NULL) { 1004*54925bf6Swillf st = ENOMEM; 1005*54925bf6Swillf goto cleanup; 1006*54925bf6Swillf } 1007*54925bf6Swillf for (j = 0, ptr = entries->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { 1008*54925bf6Swillf /* Ignore tl_data that are stored in separate directory 1009*54925bf6Swillf * attributes */ 1010*54925bf6Swillf if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE 1011*54925bf6Swillf #ifdef SECURID 1012*54925bf6Swillf || ptr->tl_data_type == KRB5_TL_DB_ARGS 1013*54925bf6Swillf #endif 1014*54925bf6Swillf || ptr->tl_data_type == KRB5_TL_KADM_DATA 1015*54925bf6Swillf || ptr->tl_data_type == KDB_TL_USER_INFO) 1016*54925bf6Swillf continue; 1017*54925bf6Swillf if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0) 1018*54925bf6Swillf break; 1019*54925bf6Swillf j++; 1020*54925bf6Swillf } 1021*54925bf6Swillf if (st != 0) { 1022*54925bf6Swillf /* Solaris Kerberos: don't free here, do it at cleanup */ 1023*54925bf6Swillf goto cleanup; 1024*54925bf6Swillf } 1025*54925bf6Swillf ber_tl_data[count] = NULL; 1026*54925bf6Swillf if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbExtraData", 1027*54925bf6Swillf LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, 1028*54925bf6Swillf ber_tl_data)) != 0) 1029*54925bf6Swillf goto cleanup; 1030*54925bf6Swillf } 1031*54925bf6Swillf } 1032*54925bf6Swillf 1033*54925bf6Swillf /* Directory specific attribute */ 1034*54925bf6Swillf if (xargs.tktpolicydn != NULL) { 1035*54925bf6Swillf int tmask=0; 1036*54925bf6Swillf 1037*54925bf6Swillf if (strlen(xargs.tktpolicydn) != 0) { 1038*54925bf6Swillf st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask); 1039*54925bf6Swillf CHECK_CLASS_VALIDITY(st, tmask, "ticket policy object value: "); 1040*54925bf6Swillf 1041*54925bf6Swillf strval[0] = xargs.tktpolicydn; 1042*54925bf6Swillf strval[1] = NULL; 1043*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) 1044*54925bf6Swillf goto cleanup; 1045*54925bf6Swillf 1046*54925bf6Swillf } else { 1047*54925bf6Swillf /* if xargs.tktpolicydn is a empty string, then delete 1048*54925bf6Swillf * already existing krbticketpolicyreference attr */ 1049*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) 1050*54925bf6Swillf goto cleanup; 1051*54925bf6Swillf } 1052*54925bf6Swillf 1053*54925bf6Swillf } 1054*54925bf6Swillf 1055*54925bf6Swillf if (establish_links == TRUE) { 1056*54925bf6Swillf memset(strval, 0, sizeof(strval)); 1057*54925bf6Swillf strval[0] = xargs.linkdn; 1058*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbObjectReferences", LDAP_MOD_REPLACE, strval)) != 0) 1059*54925bf6Swillf goto cleanup; 1060*54925bf6Swillf } 1061*54925bf6Swillf 1062*54925bf6Swillf /* 1063*54925bf6Swillf * in case mods is NULL then return 1064*54925bf6Swillf * not sure but can happen in a modprinc 1065*54925bf6Swillf * so no need to return an error 1066*54925bf6Swillf * addprinc will at least have the principal name 1067*54925bf6Swillf * and the keys passed in 1068*54925bf6Swillf */ 1069*54925bf6Swillf if (mods == NULL) 1070*54925bf6Swillf goto cleanup; 1071*54925bf6Swillf 1072*54925bf6Swillf if (create_standalone_prinicipal == TRUE) { 1073*54925bf6Swillf memset(strval, 0, sizeof(strval)); 1074*54925bf6Swillf strval[0] = "krbprincipal"; 1075*54925bf6Swillf strval[1] = "krbprincipalaux"; 1076*54925bf6Swillf strval[2] = "krbTicketPolicyAux"; 1077*54925bf6Swillf 1078*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 1079*54925bf6Swillf goto cleanup; 1080*54925bf6Swillf 1081*54925bf6Swillf st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); 1082*54925bf6Swillf if (st == LDAP_ALREADY_EXISTS && entries->mask & KADM5_LOAD) { 1083*54925bf6Swillf /* a load operation must replace an existing entry */ 1084*54925bf6Swillf st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL); 1085*54925bf6Swillf if (st != LDAP_SUCCESS) { 1086*54925bf6Swillf snprintf(errbuf, sizeof (errbuf), gettext("Principal delete failed (trying to replace entry): %s"), 1087*54925bf6Swillf ldap_err2string(st)); 1088*54925bf6Swillf st = translate_ldap_error (st, OP_ADD); 1089*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 1090*54925bf6Swillf goto cleanup; 1091*54925bf6Swillf } else { 1092*54925bf6Swillf st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); 1093*54925bf6Swillf } 1094*54925bf6Swillf } 1095*54925bf6Swillf if (st != LDAP_SUCCESS) { 1096*54925bf6Swillf snprintf(errbuf, sizeof (errbuf), gettext("Principal add failed: %s"), ldap_err2string(st)); 1097*54925bf6Swillf st = translate_ldap_error (st, OP_ADD); 1098*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 1099*54925bf6Swillf goto cleanup; 1100*54925bf6Swillf } 1101*54925bf6Swillf } else { 1102*54925bf6Swillf /* 1103*54925bf6Swillf * Here existing ldap object is modified and can be related 1104*54925bf6Swillf * to any attribute, so always ensure that the ldap 1105*54925bf6Swillf * object is extended with all the kerberos related 1106*54925bf6Swillf * objectclasses so that there are no constraint 1107*54925bf6Swillf * violations. 1108*54925bf6Swillf */ 1109*54925bf6Swillf { 1110*54925bf6Swillf char *attrvalues[] = {"krbprincipalaux", "krbTicketPolicyAux", NULL}; 1111*54925bf6Swillf int p, q, r=0, amask=0; 1112*54925bf6Swillf 1113*54925bf6Swillf if ((st=checkattributevalue(ld, (xargs.dn) ? xargs.dn : principal_dn, 1114*54925bf6Swillf "objectclass", attrvalues, &amask)) != 0) 1115*54925bf6Swillf goto cleanup; 1116*54925bf6Swillf 1117*54925bf6Swillf memset(strval, 0, sizeof(strval)); 1118*54925bf6Swillf for (p=1, q=0; p<=2; p<<=1, ++q) { 1119*54925bf6Swillf if ((p & amask) == 0) 1120*54925bf6Swillf strval[r++] = attrvalues[q]; 1121*54925bf6Swillf } 1122*54925bf6Swillf if (r != 0) { 1123*54925bf6Swillf if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 1124*54925bf6Swillf goto cleanup; 1125*54925bf6Swillf } 1126*54925bf6Swillf } 1127*54925bf6Swillf if (xargs.dn != NULL) 1128*54925bf6Swillf st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL); 1129*54925bf6Swillf else 1130*54925bf6Swillf st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL); 1131*54925bf6Swillf 1132*54925bf6Swillf if (st != LDAP_SUCCESS) { 1133*54925bf6Swillf snprintf(errbuf, sizeof (errbuf), gettext("User modification failed: %s"), ldap_err2string(st)); 1134*54925bf6Swillf st = translate_ldap_error (st, OP_MOD); 1135*54925bf6Swillf krb5_set_error_message(context, st, "%s", errbuf); 1136*54925bf6Swillf goto cleanup; 1137*54925bf6Swillf } 1138*54925bf6Swillf } 1139*54925bf6Swillf } 1140*54925bf6Swillf 1141*54925bf6Swillf cleanup: 1142*54925bf6Swillf if (user) 1143*54925bf6Swillf free(user); 1144*54925bf6Swillf 1145*54925bf6Swillf free_xargs(xargs); 1146*54925bf6Swillf 1147*54925bf6Swillf if (standalone_principal_dn) 1148*54925bf6Swillf free(standalone_principal_dn); 1149*54925bf6Swillf 1150*54925bf6Swillf if (principal_dn) 1151*54925bf6Swillf free (principal_dn); 1152*54925bf6Swillf 1153*54925bf6Swillf /* Solaris Kerberos: fix memleak */ 1154*54925bf6Swillf if (ber_tl_data) { 1155*54925bf6Swillf int j; 1156*54925bf6Swillf 1157*54925bf6Swillf for (j = 0; ber_tl_data[j] != NULL; j++) { 1158*54925bf6Swillf free (ber_tl_data[j]->bv_val); 1159*54925bf6Swillf free (ber_tl_data[j]); 1160*54925bf6Swillf } 1161*54925bf6Swillf free(ber_tl_data); 1162*54925bf6Swillf } 1163*54925bf6Swillf 1164*54925bf6Swillf if (polname != NULL) 1165*54925bf6Swillf free(polname); 1166*54925bf6Swillf 1167*54925bf6Swillf if (subtree) 1168*54925bf6Swillf free (subtree); 1169*54925bf6Swillf 1170*54925bf6Swillf if (bersecretkey) { 1171*54925bf6Swillf for (l=0; bersecretkey[l]; ++l) { 1172*54925bf6Swillf if (bersecretkey[l]->bv_val) 1173*54925bf6Swillf free (bersecretkey[l]->bv_val); 1174*54925bf6Swillf free (bersecretkey[l]); 1175*54925bf6Swillf } 1176*54925bf6Swillf free (bersecretkey); 1177*54925bf6Swillf } 1178*54925bf6Swillf 1179*54925bf6Swillf ldap_mods_free(mods, 1); 1180*54925bf6Swillf krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 1181*54925bf6Swillf *nentries = i; 1182*54925bf6Swillf return(st); 1183*54925bf6Swillf } 1184*54925bf6Swillf 1185*54925bf6Swillf krb5_error_code 1186*54925bf6Swillf krb5_read_tkt_policy (context, ldap_context, entries, policy) 1187*54925bf6Swillf krb5_context context; 1188*54925bf6Swillf krb5_ldap_context *ldap_context; 1189*54925bf6Swillf krb5_db_entry *entries; 1190*54925bf6Swillf char *policy; 1191*54925bf6Swillf { 1192*54925bf6Swillf krb5_error_code st=0; 1193*54925bf6Swillf unsigned int mask=0, omask=0; 1194*54925bf6Swillf int tkt_mask=(KDB_MAX_LIFE_ATTR | KDB_MAX_RLIFE_ATTR | KDB_TKT_FLAGS_ATTR); 1195*54925bf6Swillf krb5_ldap_policy_params *tktpoldnparam=NULL; 1196*54925bf6Swillf 1197*54925bf6Swillf if ((st=krb5_get_attributes_mask(context, entries, &mask)) != 0) 1198*54925bf6Swillf goto cleanup; 1199*54925bf6Swillf 1200*54925bf6Swillf if ((mask & tkt_mask) == tkt_mask) 1201*54925bf6Swillf goto cleanup; 1202*54925bf6Swillf 1203*54925bf6Swillf if (policy != NULL) { 1204*54925bf6Swillf st = krb5_ldap_read_policy(context, policy, &tktpoldnparam, &omask); 1205*54925bf6Swillf if (st && st != KRB5_KDB_NOENTRY) { 1206*54925bf6Swillf prepend_err_str(context, gettext("Error reading ticket policy. "), st, st); 1207*54925bf6Swillf goto cleanup; 1208*54925bf6Swillf } 1209*54925bf6Swillf 1210*54925bf6Swillf st = 0; /* reset the return status */ 1211*54925bf6Swillf } 1212*54925bf6Swillf 1213*54925bf6Swillf if ((mask & KDB_MAX_LIFE_ATTR) == 0) { 1214*54925bf6Swillf if ((omask & KDB_MAX_LIFE_ATTR) == KDB_MAX_LIFE_ATTR) 1215*54925bf6Swillf entries->max_life = tktpoldnparam->maxtktlife; 1216*54925bf6Swillf else if (ldap_context->lrparams->max_life) 1217*54925bf6Swillf entries->max_life = ldap_context->lrparams->max_life; 1218*54925bf6Swillf } 1219*54925bf6Swillf 1220*54925bf6Swillf if ((mask & KDB_MAX_RLIFE_ATTR) == 0) { 1221*54925bf6Swillf if ((omask & KDB_MAX_RLIFE_ATTR) == KDB_MAX_RLIFE_ATTR) 1222*54925bf6Swillf entries->max_renewable_life = tktpoldnparam->maxrenewlife; 1223*54925bf6Swillf else if (ldap_context->lrparams->max_renewable_life) 1224*54925bf6Swillf entries->max_renewable_life = ldap_context->lrparams->max_renewable_life; 1225*54925bf6Swillf } 1226*54925bf6Swillf 1227*54925bf6Swillf if ((mask & KDB_TKT_FLAGS_ATTR) == 0) { 1228*54925bf6Swillf if ((omask & KDB_TKT_FLAGS_ATTR) == KDB_TKT_FLAGS_ATTR) 1229*54925bf6Swillf entries->attributes = tktpoldnparam->tktflags; 1230*54925bf6Swillf else if (ldap_context->lrparams->tktflags) 1231*54925bf6Swillf entries->attributes |= ldap_context->lrparams->tktflags; 1232*54925bf6Swillf } 1233*54925bf6Swillf krb5_ldap_free_policy(context, tktpoldnparam); 1234*54925bf6Swillf 1235*54925bf6Swillf cleanup: 1236*54925bf6Swillf return st; 1237*54925bf6Swillf } 1238*54925bf6Swillf 1239*54925bf6Swillf krb5_error_code 1240*54925bf6Swillf krb5_decode_krbsecretkey(context, entries, bvalues) 1241*54925bf6Swillf krb5_context context; 1242*54925bf6Swillf krb5_db_entry *entries; 1243*54925bf6Swillf struct berval **bvalues; 1244*54925bf6Swillf { 1245*54925bf6Swillf char *user=NULL; 1246*54925bf6Swillf int i=0, j=0, noofkeys=0; 1247*54925bf6Swillf krb5_key_data *key_data=NULL, *tmp; 1248*54925bf6Swillf krb5_error_code st=0; 1249*54925bf6Swillf 1250*54925bf6Swillf if ((st=krb5_unparse_name(context, entries->princ, &user)) != 0) 1251*54925bf6Swillf goto cleanup; 1252*54925bf6Swillf 1253*54925bf6Swillf for (i=0; bvalues[i] != NULL; ++i) { 1254*54925bf6Swillf int mkvno; /* Not used currently */ 1255*54925bf6Swillf krb5_int16 n_kd; 1256*54925bf6Swillf krb5_key_data *kd; 1257*54925bf6Swillf krb5_data in; 1258*54925bf6Swillf 1259*54925bf6Swillf if (bvalues[i]->bv_len == 0) 1260*54925bf6Swillf continue; 1261*54925bf6Swillf in.length = bvalues[i]->bv_len; 1262*54925bf6Swillf in.data = bvalues[i]->bv_val; 1263*54925bf6Swillf 1264*54925bf6Swillf st = asn1_decode_sequence_of_keys (&in, 1265*54925bf6Swillf &kd, 1266*54925bf6Swillf &n_kd, 1267*54925bf6Swillf &mkvno); 1268*54925bf6Swillf 1269*54925bf6Swillf if (st != 0) { 1270*54925bf6Swillf const char *msg = error_message(st); 1271*54925bf6Swillf st = -1; /* Something more appropriate ? */ 1272*54925bf6Swillf krb5_set_error_message (context, st, 1273*54925bf6Swillf gettext("unable to decode stored principal key data (%s)"), msg); 1274*54925bf6Swillf goto cleanup; 1275*54925bf6Swillf } 1276*54925bf6Swillf noofkeys += n_kd; 1277*54925bf6Swillf tmp = key_data; 1278*54925bf6Swillf key_data = realloc (key_data, noofkeys * sizeof (krb5_key_data)); 1279*54925bf6Swillf if (key_data == NULL) { 1280*54925bf6Swillf key_data = tmp; 1281*54925bf6Swillf st = ENOMEM; 1282*54925bf6Swillf goto cleanup; 1283*54925bf6Swillf } 1284*54925bf6Swillf for (j = 0; j < n_kd; j++) 1285*54925bf6Swillf key_data[noofkeys - n_kd + j] = kd[j]; 1286*54925bf6Swillf free (kd); 1287*54925bf6Swillf } 1288*54925bf6Swillf 1289*54925bf6Swillf entries->n_key_data = noofkeys; 1290*54925bf6Swillf entries->key_data = key_data; 1291*54925bf6Swillf 1292*54925bf6Swillf cleanup: 1293*54925bf6Swillf ldap_value_free_len(bvalues); 1294*54925bf6Swillf free (user); 1295*54925bf6Swillf return st; 1296*54925bf6Swillf } 1297*54925bf6Swillf 1298*54925bf6Swillf static char * 1299*54925bf6Swillf getstringtime(epochtime) 1300*54925bf6Swillf krb5_timestamp epochtime; 1301*54925bf6Swillf { 1302*54925bf6Swillf struct tm tme; 1303*54925bf6Swillf char *strtime=NULL; 1304*54925bf6Swillf time_t posixtime = epochtime; 1305*54925bf6Swillf 1306*54925bf6Swillf strtime = calloc (50, 1); 1307*54925bf6Swillf if (strtime == NULL) 1308*54925bf6Swillf return NULL; 1309*54925bf6Swillf 1310*54925bf6Swillf if (gmtime_r(&posixtime, &tme) == NULL) 1311*54925bf6Swillf return NULL; 1312*54925bf6Swillf 1313*54925bf6Swillf strftime(strtime, 50, DATE_FORMAT, &tme); 1314*54925bf6Swillf return strtime; 1315*54925bf6Swillf } 1316*54925bf6Swillf 1317