static void pblock_destroy( Slapi_PBlock *pb ) { LDAPControl **controls = NULL; LDAPMod **mods = NULL; char **attrs = NULL; assert( pb != NULL ); pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls ); if ( controls != NULL ) { ldap_controls_free( controls ); } if ( pb->pb_intop ) { slapi_int_connection_done_pb( pb ); } else { pblock_get_default( pb, SLAPI_MODIFY_MODS, (void **)&mods ); ldap_mods_free( mods, 1 ); pblock_get_default( pb, SLAPI_SEARCH_ATTRS, (void **)&attrs ); if ( attrs != NULL ) pb->pb_op->o_tmpfree( attrs, pb->pb_op->o_tmpmemctx ); } ldap_pvt_thread_mutex_destroy( &pb->pb_mutex ); slapi_ch_free( (void **)&pb ); }
krb5_error_code ipadb_simple_delete_val(struct ipadb_context *ipactx, char *dn, char *attr, char *value) { krb5_error_code kerr; LDAPMod *mods[2]; mods[0] = calloc(1, sizeof(LDAPMod)); if (!mods[0]) { return ENOMEM; } mods[1] = NULL; mods[0]->mod_op = LDAP_MOD_DELETE; mods[0]->mod_type = strdup(attr); if (!mods[0]->mod_type) { kerr = ENOMEM; goto done; } mods[0]->mod_values = calloc(2, sizeof(char *)); if (!mods[0]->mod_values) { kerr = ENOMEM; goto done; } mods[0]->mod_values[0] = strdup(value); if (!mods[0]->mod_values[0]) { kerr = ENOMEM; goto done; } kerr = ipadb_simple_modify(ipactx, dn, mods); done: ldap_mods_free(mods, 0); return kerr; }
void LDAPSession::addStringValue ( string dn, const list<LDAPStringValue>& values ) { list<LDAPStringValue>::const_iterator it=values.begin(); list<LDAPStringValue>::const_iterator end=values.end(); int i=0; LDAPMod** mods= ( LDAPMod** ) malloc ( sizeof ( LDAPMod* ) *values.size() +1 ); for ( ;it!=end;++it ) { mods[i]= ( LDAPMod* ) malloc ( sizeof ( LDAPMod ) ); mods[i]->mod_op=LDAP_MOD_ADD; mods[i]->mod_type= ( char* ) malloc ( sizeof ( char ) * ( *it ).attr.length() ); strcpy ( mods[i]->mod_type, ( *it ).attr.c_str() ); list<string>::const_iterator sit= ( *it ).value.begin(); list<string>::const_iterator send= ( *it ).value.end(); int j=0; mods[i]->mod_vals.modv_strvals= ( char** ) malloc ( sizeof ( char* ) * ( *it ).value.size() +1 ); for ( ;sit!=send;++sit ) { mods[i]->mod_vals.modv_strvals[j]= ( char* ) malloc ( sizeof ( char ) * ( *sit ).length() ); strcpy ( mods[i]->mod_vals.modv_strvals[j], ( *sit ).c_str() ); ++j; } mods[i]->mod_vals.modv_strvals[j]=0l; ++i; } mods[i]=0l; int errc= ldap_add_s ( ld,dn.c_str(),mods ); if ( errc != LDAP_SUCCESS ) throw LDAPExeption ( "ldap_add_s",ldap_err2string ( errc ) ); ldap_mods_free ( mods,1 ); }
/* Sets the depot status. */ void set_depot_attr (LDAP *ldap, char *dn, char *attr, char *value) { LDAPMod **mods; mods = (LDAPMod **) malloc (2 * sizeof (LDAPMod *)); mods[0] = (LDAPMod *) malloc (sizeof (LDAPMod)); mods[1] = NULL; mods[0]->mod_op = LDAP_MOD_REPLACE; mods[0]->mod_type = strdup (attr); mods[0]->mod_values = (char **) malloc (2 * sizeof (char *)); mods[0]->mod_values[0] = strdup (value); mods[0]->mod_values[1] = NULL; ldap_modify_s (ldap, dn, mods); ldap_mods_free(mods, 1); }
static NTSTATUS verify_idpool(struct idmap_domain *dom) { NTSTATUS ret; TALLOC_CTX *mem_ctx; LDAPMessage *result = NULL; LDAPMod **mods = NULL; const char **attr_list; char *filter; int count; int rc; struct idmap_ldap_context *ctx; ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); mem_ctx = talloc_new(ctx); if (mem_ctx == NULL) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } filter = talloc_asprintf(mem_ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL); CHECK_ALLOC_DONE(filter); attr_list = get_attr_list(mem_ctx, idpool_attr_list); CHECK_ALLOC_DONE(attr_list); rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); if (rc != LDAP_SUCCESS) { DEBUG(1, ("Unable to verify the idpool, " "cannot continue initialization!\n")); return NT_STATUS_UNSUCCESSFUL; } count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result); ldap_msgfree(result); if ( count > 1 ) { DEBUG(0,("Multiple entries returned from %s (base == %s)\n", filter, ctx->suffix)); ret = NT_STATUS_UNSUCCESSFUL; goto done; } else if (count == 0) { char *uid_str, *gid_str; uid_str = talloc_asprintf(mem_ctx, "%lu", (unsigned long)dom->low_id); gid_str = talloc_asprintf(mem_ctx, "%lu", (unsigned long)dom->low_id); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL); smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER), uid_str); smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str); if (mods) { rc = smbldap_modify(ctx->smbldap_state, ctx->suffix, mods); ldap_mods_free(mods, True); } else { ret = NT_STATUS_UNSUCCESSFUL; goto done; } } ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL; done: talloc_free(mem_ctx); return ret; }
static krb5_error_code LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, LDAPMessage * msg, LDAPMod *** pmods) { krb5_error_code ret; krb5_boolean is_new_entry; char *tmp = NULL; LDAPMod **mods = NULL; hdb_entry_ex orig; unsigned long oflags, nflags; int i; krb5_boolean is_samba_account = FALSE; krb5_boolean is_account = FALSE; krb5_boolean is_heimdal_entry = FALSE; krb5_boolean is_heimdal_principal = FALSE; struct berval **vals; *pmods = NULL; if (msg != NULL) { ret = LDAP_message2entry(context, db, msg, 0, &orig); if (ret) goto out; is_new_entry = FALSE; vals = ldap_get_values_len(HDB2LDAP(db), msg, "objectClass"); if (vals) { int num_objectclasses = ldap_count_values_len(vals); for (i=0; i < num_objectclasses; i++) { if (bervalstrcmp(vals[i], "sambaSamAccount")) is_samba_account = TRUE; else if (bervalstrcmp(vals[i], structural_object)) is_account = TRUE; else if (bervalstrcmp(vals[i], "krb5Principal")) is_heimdal_principal = TRUE; else if (bervalstrcmp(vals[i], "krb5KDCEntry")) is_heimdal_entry = TRUE; } ldap_value_free_len(vals); } /* * If this is just a "account" entry and no other objectclass * is hanging on this entry, it's really a new entry. */ if (is_samba_account == FALSE && is_heimdal_principal == FALSE && is_heimdal_entry == FALSE) { if (is_account == TRUE) { is_new_entry = TRUE; } else { ret = HDB_ERR_NOENTRY; goto out; } } } else is_new_entry = TRUE; if (is_new_entry) { /* to make it perfectly obvious we're depending on * orig being intiialized to zero */ memset(&orig, 0, sizeof(orig)); ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top"); if (ret) goto out; /* account is the structural object class */ if (is_account == FALSE) { ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", structural_object); is_account = TRUE; if (ret) goto out; } ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5Principal"); is_heimdal_principal = TRUE; if (ret) goto out; ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5KDCEntry"); is_heimdal_entry = TRUE; if (ret) goto out; } if (is_new_entry || krb5_principal_compare(context, ent->entry.principal, orig.entry.principal) == FALSE) { if (is_heimdal_principal || is_heimdal_entry) { ret = krb5_unparse_name(context, ent->entry.principal, &tmp); if (ret) goto out; ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "krb5PrincipalName", tmp); if (ret) { free(tmp); goto out; } free(tmp); } if (is_account || is_samba_account) { ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp); if (ret) goto out; ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp); if (ret) { free(tmp); goto out; } free(tmp); } } if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "krb5KeyVersionNumber", ent->entry.kvno); if (ret) goto out; } if (is_heimdal_entry && ent->entry.valid_start) { if (orig.entry.valid_end == NULL || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) { ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, "krb5ValidStart", ent->entry.valid_start); if (ret) goto out; } } if (ent->entry.valid_end) { if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) { if (is_heimdal_entry) { ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, "krb5ValidEnd", ent->entry.valid_end); if (ret) goto out; } if (is_samba_account) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "sambaKickoffTime", *(ent->entry.valid_end)); if (ret) goto out; } } } if (ent->entry.pw_end) { if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) { if (is_heimdal_entry) { ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, "krb5PasswordEnd", ent->entry.pw_end); if (ret) goto out; } if (is_samba_account) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "sambaPwdMustChange", *(ent->entry.pw_end)); if (ret) goto out; } } } #if 0 /* we we have last_pw_change */ if (is_samba_account && ent->entry.last_pw_change) { if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "sambaPwdLastSet", *(ent->entry.last_pw_change)); if (ret) goto out; } } #endif if (is_heimdal_entry && ent->entry.max_life) { if (orig.entry.max_life == NULL || (*(ent->entry.max_life) != *(orig.entry.max_life))) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "krb5MaxLife", *(ent->entry.max_life)); if (ret) goto out; } } if (is_heimdal_entry && ent->entry.max_renew) { if (orig.entry.max_renew == NULL || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "krb5MaxRenew", *(ent->entry.max_renew)); if (ret) goto out; } } oflags = HDBFlags2int(orig.entry.flags); nflags = HDBFlags2int(ent->entry.flags); if (is_heimdal_entry && oflags != nflags) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "krb5KDCFlags", nflags); if (ret) goto out; } /* Remove keys if they exists, and then replace keys. */ if (!is_new_entry && orig.entry.keys.len > 0) { vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); if (vals) { ldap_value_free_len(vals); ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL); if (ret) goto out; } } for (i = 0; i < ent->entry.keys.len; i++) { if (is_samba_account && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { char *ntHexPassword; char *nt; time_t now = time(NULL); /* the key might have been 'sealed', but samba passwords are clear in the directory */ ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]); if (ret) goto out; nt = ent->entry.keys.val[i].key.keyvalue.data; /* store in ntPassword, not krb5key */ ret = hex_encode(nt, 16, &ntHexPassword); if (ret < 0) { ret = ENOMEM; krb5_set_error_message(context, ret, "hdb-ldap: failed to " "hex encode key"); goto out; } ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "sambaNTPassword", ntHexPassword); free(ntHexPassword); if (ret) goto out; ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, "sambaPwdLastSet", now); if (ret) goto out; /* have to kill the LM passwod if it exists */ vals = ldap_get_values_len(HDB2LDAP(db), msg, "sambaLMPassword"); if (vals) { ldap_value_free_len(vals); ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "sambaLMPassword", NULL); if (ret) goto out; } } else if (is_heimdal_entry) { unsigned char *buf; size_t len, buf_size; ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret); if (ret) goto out; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); /* addmod_len _owns_ the key, doesn't need to copy it */ ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len); if (ret) goto out; } } if (ent->entry.etypes) { int add_krb5EncryptionType = 0; /* * Only add/modify krb5EncryptionType if it's a new heimdal * entry or krb5EncryptionType already exists on the entry. */ if (!is_new_entry) { vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType"); if (vals) { ldap_value_free_len(vals); ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType", NULL); if (ret) goto out; add_krb5EncryptionType = 1; } } else if (is_heimdal_entry) add_krb5EncryptionType = 1; if (add_krb5EncryptionType) { for (i = 0; i < ent->entry.etypes->len; i++) { if (is_samba_account && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { ; } else if (is_heimdal_entry) { ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD, "krb5EncryptionType", ent->entry.etypes->val[i]); if (ret) goto out; } } } } /* for clarity */ ret = 0; out: if (ret == 0) *pmods = mods; else if (mods != NULL) { ldap_mods_free(mods, 1); *pmods = NULL; } if (msg) hdb_free_entry(context, &orig); return ret; }
/* * delete a principal from the directory. */ krb5_error_code krb5_ldap_delete_principal(krb5_context context, krb5_const_principal searchfor) { char *user=NULL, *DN=NULL, *strval[10] = {NULL}; LDAPMod **mods=NULL; LDAP *ld=NULL; int j=0, ptype=0, pcount=0, attrsetmask=0; krb5_error_code st=0; krb5_boolean singleentry=FALSE; KEY *secretkey=NULL; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_context *ldap_context=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; krb5_db_entry *entry = NULL; /* Clear the global error string */ krb5_clear_error_message(context); SETUP_CONTEXT(); /* get the principal info */ if ((st=krb5_ldap_get_principal(context, searchfor, 0, &entry))) goto cleanup; if (((st=krb5_get_princ_type(context, entry, &(ptype))) != 0) || ((st=krb5_get_attributes_mask(context, entry, &(attrsetmask))) != 0) || ((st=krb5_get_princ_count(context, entry, &(pcount))) != 0) || ((st=krb5_get_userdn(context, entry, &(DN))) != 0)) goto cleanup; if (DN == NULL) { st = EINVAL; krb5_set_error_message(context, st, "DN information missing"); goto cleanup; } GET_HANDLE(); if (ptype == KDB_STANDALONE_PRINCIPAL_OBJECT) { st = ldap_delete_ext_s(ld, DN, NULL, NULL); if (st != LDAP_SUCCESS) { st = set_ldap_error (context, st, OP_DEL); goto cleanup; } } else { if (((st=krb5_unparse_name(context, searchfor, &user)) != 0) || ((st=krb5_ldap_unparse_principal_name(user)) != 0)) goto cleanup; memset(strval, 0, sizeof(strval)); strval[0] = user; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_DELETE, strval)) != 0) goto cleanup; singleentry = (pcount == 1) ? TRUE: FALSE; if (singleentry == FALSE) { if (secretkey != NULL) { if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", LDAP_MOD_DELETE | LDAP_MOD_BVALUES, secretkey->keys)) != 0) goto cleanup; } } else { /* * If the Kerberos user principal to be deleted happens to be the last one associated * with the directory user object, then it is time to delete the other kerberos * specific attributes like krbmaxticketlife, i.e, unkerberize the directory user. * From the attrsetmask value, identify the attributes set on the directory user * object and delete them. * NOTE: krbsecretkey attribute has per principal entries. There can be chances that the * other principals' keys are exisiting/left-over. So delete all the values. */ while (attrsetmask) { if (attrsetmask & 1) { if ((st=krb5_add_str_mem_ldap_mod(&mods, attributes_set[j], LDAP_MOD_DELETE, NULL)) != 0) goto cleanup; } attrsetmask >>= 1; ++j; } /* the same should be done with the objectclass attributes */ { char *attrvalues[] = {"krbticketpolicyaux", "krbprincipalaux", NULL}; /* char *attrvalues[] = {"krbpwdpolicyrefaux", "krbticketpolicyaux", "krbprincipalaux", NULL}; */ int p, q, r=0, amask=0; if ((st=checkattributevalue(ld, DN, "objectclass", attrvalues, &amask)) != 0) goto cleanup; memset(strval, 0, sizeof(strval)); for (p=1, q=0; p<=4; p<<=1, ++q) if (p & amask) strval[r++] = attrvalues[q]; strval[r] = NULL; if (r > 0) { if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_DELETE, strval)) != 0) goto cleanup; } } } st=ldap_modify_ext_s(ld, DN, mods, NULL, NULL); if (st != LDAP_SUCCESS) { st = set_ldap_error(context, st, OP_MOD); goto cleanup; } } cleanup: if (user) free (user); if (DN) free (DN); if (secretkey != NULL) { int i=0; while (i < secretkey->nkey) { free (secretkey->keys[i]->bv_val); free (secretkey->keys[i]); ++i; } free (secretkey->keys); free (secretkey); } krb5_ldap_free_principal(context, entry); ldap_mods_free(mods, 1); krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return st; }
/* * op_shared_rename() -- common frontend code for modDN operations. * * Beware: this function resets the following pblock elements that were * set by the caller: * * SLAPI_MODRDN_TARGET_SDN * SLAPI_MODRDN_NEWRDN * SLAPI_MODRDN_NEWSUPERIOR_SDN */ static void op_shared_rename(Slapi_PBlock *pb, int passin_args) { char *dn, *newrdn, *newdn = NULL; const char *newsuperior; char **rdns; int deloldrdn; Slapi_Backend *be = NULL; Slapi_DN *origsdn = NULL; Slapi_Mods smods; int internal_op, repl_op, lastmod; Slapi_Operation *operation; Slapi_Entry *referral; char errorbuf[BUFSIZ]; int err; char *proxydn = NULL; char *proxystr = NULL; int proxy_err = LDAP_SUCCESS; char *errtext = NULL; Slapi_DN *sdn = NULL; Slapi_DN *newsuperiorsdn = NULL; slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn); slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn); slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op); slapi_pblock_get (pb, SLAPI_OPERATION, &operation); slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &origsdn); internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL); /* * If ownership has not been passed to this function, we replace the * string input fields within the pblock with strdup'd copies. Why? * Because some pre- and post-op plugins may change them, and the * convention is that plugins should place a malloc'd string in the * pblock. Therefore, we need to be able to retrieve and free them * later. But the callers of the internal modrdn calls are promised * that we will not free these parameters... so if passin_args is * zero, we need to make copies. * * In the case of SLAPI_MODRDN_TARGET_SDN and SLAPI_MODRDN_NEWSUPERIOR_SDN, * we replace the existing values with normalized values (because plugins * expect these DNs to be normalized). */ if (NULL == origsdn) { sdn = slapi_sdn_new_dn_byval(dn); slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn); } if (passin_args) { if (NULL == sdn) { /* origsdn is not NULL, so use it. */ sdn = origsdn; } } else { if (NULL == sdn) { sdn = slapi_sdn_dup(origsdn); } newrdn = slapi_ch_strdup(newrdn); newsuperiorsdn = slapi_sdn_dup(newsuperiorsdn); slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, sdn); slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn); slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, newsuperiorsdn); } /* normdn = slapi_sdn_get_dn(sdn); */ newsuperior = slapi_sdn_get_dn(newsuperiorsdn); /* get the proxy auth dn if the proxy auth control is present */ proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext); /* * first, log the operation to the access log, * then check rdn and newsuperior, * and - if applicable - log reason of any error to the errors log */ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS)) { if (proxydn) { proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn); } if ( !internal_op ) { slapi_log_access(LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, dn, newrdn ? newrdn : "(null)", newsuperior ? newsuperior : "(null)", proxystr ? proxystr : ""); } else { slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d MODRDN dn=\"%s\" newrdn=\"%s\" newsuperior=\"%s\"%s\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, dn, newrdn ? newrdn : "(null)", newsuperior ? newsuperior : "(null)", proxystr ? proxystr : ""); } } /* If we encountered an error parsing the proxy control, return an error * to the client. We do this here to ensure that we log the operation first. */ if (proxy_err != LDAP_SUCCESS) { send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL); goto free_and_return_nolock; } /* check that the rdn is formatted correctly */ if ((rdns = slapi_ldap_explode_rdn(newrdn, 0)) == NULL) { if ( !internal_op ) { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%" NSPRIu64 " op=%d MODRDN invalid new RDN (\"%s\")\n", pb->pb_conn->c_connid, pb->pb_op->o_opid, (NULL == newrdn) ? "(null)" : newrdn); } else { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%s op=%d MODRDN invalid new RDN (\"%s\")\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, (NULL == newrdn) ? "(null)" : newrdn); } send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid RDN", 0, NULL); goto free_and_return_nolock; } else { slapi_ldap_value_free(rdns); } /* check if created attributes are used in the new RDN */ /* check_rdn_for_created_attrs ignores the cases */ if (check_rdn_for_created_attrs((const char *)newrdn)) { send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid attribute in RDN", 0, NULL); goto free_and_return_nolock; } /* check that the dn is formatted correctly */ err = slapi_dn_syntax_check(pb, newsuperior, 1); if (err) { LDAPDebug0Args(LDAP_DEBUG_ARGS, "Syntax check of newSuperior failed\n"); if (!internal_op) { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%" NSPRIu64 " op=%d MODRDN invalid new superior (\"%s\")", pb->pb_conn->c_connid, pb->pb_op->o_opid, newsuperior ? newsuperior : "(null)"); } else { slapi_log_error(SLAPI_LOG_ARGS, NULL, "conn=%s op=%d MODRDN invalid new superior (\"%s\")", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, newsuperior ? newsuperior : "(null)"); } send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "newSuperior does not look like a DN", 0, NULL); goto free_and_return_nolock; } if (newsuperior != NULL) { LDAPDebug(LDAP_DEBUG_ARGS, "do_moddn: newsuperior (%s)\n", newsuperior, 0, 0); } /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (pb->pb_op, sdn); /* * Construct the new DN (code sdn from backend * and modified to handle newsuperior) */ newdn = slapi_moddn_get_newdn(sdn, newrdn, newsuperior); /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ /* slapi_mapping_tree_select_and_check ignores the case of newdn * which is generated using newrdn above. */ if ((err = slapi_mapping_tree_select_and_check(pb, newdn, &be, &referral, errorbuf)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, errorbuf, 0, NULL); goto free_and_return_nolock; } if (referral) { int managedsait; slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait); if (managedsait) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot update referral", 0, NULL); slapi_entry_free(referral); goto free_and_return; } send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto free_and_return; } slapi_pblock_set(pb, SLAPI_BACKEND, be); /* can get lastmod only after backend is selected */ slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod); /* if it is a replicated operation - leave lastmod attributes alone */ slapi_mods_init (&smods, 2); if (!repl_op && lastmod) { modify_update_last_modified_attr(pb, &smods); slapi_pblock_set(pb, SLAPI_MODIFY_MODS, (void*)slapi_mods_get_ldapmods_passout(&smods)); } else { slapi_mods_done (&smods); } /* * call the pre-modrdn plugins. if they succeed, call * the backend modrdn function. then call the * post-modrdn plugins. */ if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN : SLAPI_PLUGIN_PRE_MODRDN_FN) == 0) { int rc= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database); set_db_default_result_handlers(pb); if (be->be_modrdn != NULL) { if ((rc = (*be->be_modrdn)(pb)) == 0) { Slapi_Entry *pse; Slapi_Entry *ecopy; /* we don't perform acl check for internal operations */ /* dont update aci store for remote acis */ if ((!internal_op) && (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA))) plugin_call_acl_mods_update (pb, SLAPI_OPERATION_MODRDN); if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT)) write_audit_log_entry(pb); /* Record the operation in the audit log */ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy); /* GGOODREPL persistent search system needs the changenumber, oops. */ do_ps_service(pse, ecopy, LDAP_CHANGETYPE_MODDN, 0); } } else { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL); } slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc); plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN : SLAPI_PLUGIN_POST_MODRDN_FN); } free_and_return: if (be) slapi_be_Unlock(be); free_and_return_nolock: { /* Free up everything left in the PBlock */ Slapi_Entry *pse; Slapi_Entry *ecopy; LDAPMod **mods; char *s; if (passin_args) { if (NULL == origsdn) { slapi_sdn_free(&sdn); } } else { slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); /* get newrdn to free the string */ slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn); slapi_ch_free_string(&newrdn); slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperiorsdn); slapi_sdn_free(&newsuperiorsdn); } slapi_ch_free_string(&newdn); slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy); slapi_entry_free(ecopy); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_entry_free(pse); slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); ldap_mods_free( mods, 1 ); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &s); slapi_ch_free((void **)&s); } }
static krb5_error_code LDAP_store(krb5_context context, HDB * db, unsigned flags, hdb_entry * entry) { LDAPMod **mods = NULL; krb5_error_code ret; const char *errfn; int rc; LDAPMessage *msg = NULL, *e = NULL; char *dn = NULL, *name = NULL; ret = LDAP_principal2message(context, db, entry->principal, &msg); if (ret == 0) e = ldap_first_entry(HDB2LDAP(db), msg); ret = krb5_unparse_name(context, entry->principal, &name); if (ret) { free(name); return ret; } ret = hdb_seal_keys(context, db, entry); if (ret) goto out; /* turn new entry into LDAPMod array */ ret = LDAP_entry2mods(context, db, entry, e, &mods); if (ret) goto out; if (e == NULL) { ret = asprintf(&dn, "krb5PrincipalName=%s,%s", name, HDB2CREATE(db)); if (ret < 0) { krb5_set_error_string(context, "asprintf: out of memory"); ret = ENOMEM; goto out; } } else if (flags & HDB_F_REPLACE) { /* Entry exists, and we're allowed to replace it. */ dn = ldap_get_dn(HDB2LDAP(db), e); } else { /* Entry exists, but we're not allowed to replace it. Bail. */ ret = HDB_ERR_EXISTS; goto out; } /* write entry into directory */ if (e == NULL) { /* didn't exist before */ rc = ldap_add_s(HDB2LDAP(db), dn, mods); errfn = "ldap_add_s"; } else { /* already existed, send deltas only */ rc = ldap_modify_s(HDB2LDAP(db), dn, mods); errfn = "ldap_modify_s"; } if (check_ldap(context, db, rc)) { char *ld_error = NULL; ldap_get_option(HDB2LDAP(db), LDAP_OPT_ERROR_STRING, &ld_error); krb5_set_error_string(context, "%s: %s (dn=%s) %s: %s", errfn, name, dn, ldap_err2string(rc), ld_error); ret = HDB_ERR_CANT_LOCK_DB; } else ret = 0; out: /* free stuff */ if (dn) free(dn); if (msg) ldap_msgfree(msg); if (mods) ldap_mods_free(mods, 1); if (name) free(name); return ret; }
static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, const char *domain_name) { fstring sid_string; fstring algorithmic_rid_base_string; char *filter = NULL; char *dn = NULL; LDAPMod **mods = NULL; int rc; LDAPMessage *result = NULL; int num_result; const char **attr_list; char *escape_domain_name; /* escape for filter */ escape_domain_name = escape_ldap_string(talloc_tos(), domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } if (asprintf(&filter, "(&(%s=%s)(objectclass=%s))", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name, LDAP_OBJ_DOMINFO) < 0) { TALLOC_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } TALLOC_FREE(escape_domain_name); attr_list = get_attr_list(NULL, dominfo_attr_list ); rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result); TALLOC_FREE( attr_list ); SAFE_FREE(filter); if (rc != LDAP_SUCCESS) { return NT_STATUS_UNSUCCESSFUL; } num_result = ldap_count_entries(ldap_state->ldap_struct, result); if (num_result > 1) { DEBUG (0, ("add_new_domain_info: More than domain with that name exists: bailing " "out!\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } /* Check if we need to add an entry */ DEBUG(3,("add_new_domain_info: Adding new domain\n")); /* this time escape for DN */ escape_domain_name = escape_rdn_val_string_alloc(domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } if (asprintf(&dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name, lp_ldap_suffix(talloc_tos())) < 0) { SAFE_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } SAFE_FREE(escape_domain_name); /* Free original search */ ldap_msgfree(result); /* make the changes - the entry *must* not already have samba * attributes */ smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), domain_name); /* If we don't have an entry, then ask secrets.tdb for what it thinks. It may choose to make it up */ sid_to_fstring(sid_string, get_global_sam_sid()); smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string); slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base()); smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), algorithmic_rid_base_string); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); /* add the sambaNextUserRid attributes. */ { uint32_t rid = BASE_RID; fstring rid_str; fstr_sprintf( rid_str, "%i", rid ); DEBUG(10,("add_new_domain_info: setting next available user rid [%s]\n", rid_str)); smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), rid_str); } rc = smbldap_add(ldap_state, dn, mods); if (rc!=LDAP_SUCCESS) { char *ld_error = NULL; ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(1,("add_new_domain_info: failed to add domain dn= %s with: %s\n\t%s\n", dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); SAFE_FREE(ld_error); SAFE_FREE(dn); ldap_mods_free(mods, True); return NT_STATUS_UNSUCCESSFUL; } DEBUG(2,("add_new_domain_info: added: domain = %s in the LDAP database\n", domain_name)); ldap_mods_free(mods, True); SAFE_FREE(dn); return NT_STATUS_OK; }
krb5_error_code krb5_ldap_modify_realm(krb5_context context, krb5_ldap_realm_params *rparams, int mask) { LDAP *ld=NULL; krb5_error_code st=0; char **strval=NULL, *strvalprc[5]={NULL}; LDAPMod **mods = NULL; int objectmask=0,k=0; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_context *ldap_context=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; if (mask == 0) return 0; if (rparams == NULL) { st = EINVAL; return st; } SETUP_CONTEXT (); /* Check validity of arguments */ if (ldap_context->container_dn == NULL || rparams->tl_data == NULL || rparams->tl_data->tl_data_contents == NULL || ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) || ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || 0) { st = EINVAL; goto cleanup; } /* get ldap handle */ GET_HANDLE (); /* SUBTREE ATTRIBUTE */ if (mask & LDAP_REALM_SUBTREE) { if ( rparams->subtree!=NULL) { /*replace the subtrees with the present if the subtrees are present*/ for(k=0;k<rparams->subtreecount && rparams->subtree[k]!=NULL;k++) { if (strlen(rparams->subtree[k]) != 0) { st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass, &objectmask); CHECK_CLASS_VALIDITY(st, objectmask, _("subtree value: ")); } } strval = rparams->subtree; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE, strval)) != 0) { goto cleanup; } } } /* CONTAINERREF ATTRIBUTE */ if (mask & LDAP_REALM_CONTREF) { if (strlen(rparams->containerref) != 0 ) { st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass, &objectmask); CHECK_CLASS_VALIDITY(st, objectmask, _("container reference value: ")); strvalprc[0] = rparams->containerref; strvalprc[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE, strvalprc)) != 0) goto cleanup; } } /* SEARCHSCOPE ATTRIBUTE */ if (mask & LDAP_REALM_SEARCHSCOPE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE, (rparams->search_scope == LDAP_SCOPE_ONELEVEL || rparams->search_scope == LDAP_SCOPE_SUBTREE) ? rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0) goto cleanup; } if (mask & LDAP_REALM_MAXRENEWLIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE, rparams->max_renewable_life)) != 0) goto cleanup; } /* krbMaxTicketLife ATTRIBUTE */ if (mask & LDAP_REALM_MAXTICKETLIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE, rparams->max_life)) != 0) goto cleanup; } /* krbTicketFlags ATTRIBUTE */ if (mask & LDAP_REALM_KRBTICKETFLAGS) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE, rparams->tktflags)) != 0) goto cleanup; } /* Realm modify opearation */ if (mods != NULL) { if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) { st = set_ldap_error (context, st, OP_MOD); goto cleanup; } } cleanup: ldap_mods_free(mods, 1); krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return st; }
int ldbm_back_modify( Slapi_PBlock *pb ) { backend *be; ldbm_instance *inst = NULL; struct ldbminfo *li; struct backentry *e = NULL, *ec = NULL; struct backentry *original_entry = NULL, *tmpentry = NULL; Slapi_Entry *postentry = NULL; LDAPMod **mods = NULL; LDAPMod **mods_original = NULL; Slapi_Mods smods = {0}; back_txn txn; back_txnid parent_txn; modify_context ruv_c = {0}; int ruv_c_init = 0; int retval = -1; char *msg; char *errbuf = NULL; int retry_count = 0; int disk_full = 0; int ldap_result_code= LDAP_SUCCESS; char *ldap_result_message= NULL; int rc = 0; Slapi_Operation *operation; entry_address *addr; int is_fixup_operation= 0; int is_ruv = 0; /* True if the current entry is RUV */ CSN *opcsn = NULL; int repl_op; int opreturn = 0; int mod_count = 0; int not_an_error = 0; int fixup_tombstone = 0; int ec_locked = 0; int result_sent = 0; slapi_pblock_get( pb, SLAPI_BACKEND, &be); slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li ); slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr ); slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); slapi_pblock_get( pb, SLAPI_TXN, (void**)&parent_txn ); slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op); slapi_pblock_get( pb, SLAPI_OPERATION, &operation ); fixup_tombstone = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_FIXUP); dblayer_txn_init(li,&txn); /* must do this before first goto error_return */ /* the calls to perform searches require the parent txn if any so set txn to the parent_txn until we begin the child transaction */ if (parent_txn) { txn.back_txn_txn = parent_txn; } else { parent_txn = txn.back_txn_txn; slapi_pblock_set( pb, SLAPI_TXN, parent_txn ); } if (NULL == operation) { ldap_result_code = LDAP_OPERATIONS_ERROR; goto error_return; } is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP); is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV); inst = (ldbm_instance *) be->be_instance_info; if (NULL == addr) { goto error_return; } if (inst && inst->inst_ref_count) { slapi_counter_increment(inst->inst_ref_count); } else { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "Instance \"%s\" does not exist.\n", inst ? inst->inst_name : "null instance"); goto error_return; } /* no need to check the dn syntax as this is a replicated op */ if(!repl_op){ ldap_result_code = slapi_dn_syntax_check(pb, slapi_sdn_get_dn(addr->sdn), 1); if (ldap_result_code) { ldap_result_code = LDAP_INVALID_DN_SYNTAX; slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); goto error_return; } } /* The dblock serializes writes to the database, * which reduces deadlocking in the db code, * which means that we run faster. * * But, this lock is re-enterant for the fixup * operations that the URP code in the Replication * plugin generates. * * SERIALLOCK is moved to dblayer_txn_begin along with exposing be * transaction to plugins (see slapi_back_transaction_* APIs). * if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) { dblayer_lock_backend(be); dblock_acquired= 1; } */ if ( MANAGE_ENTRY_BEFORE_DBLOCK(li)) { /* find and lock the entry we are about to modify */ if (fixup_tombstone) { e = find_entry2modify_only_ext( pb, be, addr, TOMBSTONE_INCLUDED, &txn, &result_sent ); } else { e = find_entry2modify( pb, be, addr, &txn, &result_sent ); } if (e == NULL) { ldap_result_code = -1; goto error_return; /* error result sent by find_entry2modify() */ } } txn.back_txn_txn = NULL; /* ready to create the child transaction */ for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) { int cache_rc = 0; int new_mod_count = 0; if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) { /* don't release SERIAL LOCK */ dblayer_txn_abort_ext(li, &txn, PR_FALSE); slapi_pblock_set(pb, SLAPI_TXN, parent_txn); /* * Since be_txn_preop functions could have modified the entry/mods, * We need to grab the current mods, free them, and restore the * originals. Same thing for the entry. */ slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); ldap_mods_free(mods, 1); slapi_pblock_set(pb, SLAPI_MODIFY_MODS, copy_mods(mods_original)); /* reset ec set cache in id2entry_add_ext */ if (ec) { /* must duplicate ec before returning it to cache, * which could free the entry. */ if ((tmpentry = backentry_dup(original_entry?original_entry:ec)) == NULL) { ldap_result_code= LDAP_OPERATIONS_ERROR; goto error_return; } if (cache_is_in_cache(&inst->inst_cache, ec)) { CACHE_REMOVE(&inst->inst_cache, ec); } CACHE_RETURN(&inst->inst_cache, &ec); slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, original_entry->ep_entry ); ec = original_entry; original_entry = tmpentry; tmpentry = NULL; } if (ruv_c_init) { /* reset the ruv txn stuff */ modify_term(&ruv_c, be); ruv_c_init = 0; } slapi_log_err(SLAPI_LOG_BACKLDBM, "ldbm_back_modify", "Modify Retrying Transaction\n"); #ifndef LDBM_NO_BACKOFF_DELAY { PRIntervalTime interval; interval = PR_MillisecondsToInterval(slapi_rand() % 100); DS_Sleep(interval); } #endif } /* Nothing above here modifies persistent store, everything after here is subject to the transaction */ /* dblayer_txn_begin holds SERIAL lock, * which should be outside of locking the entry (find_entry2modify) */ if (0 == retry_count) { /* First time, hold SERIAL LOCK */ retval = dblayer_txn_begin(be, parent_txn, &txn); } else { /* Otherwise, no SERIAL LOCK */ retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE); } if (0 != retval) { if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; ldap_result_code= LDAP_OPERATIONS_ERROR; goto error_return; } /* stash the transaction for plugins */ slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); if (0 == retry_count) { /* just once */ if ( !MANAGE_ENTRY_BEFORE_DBLOCK(li)) { /* find and lock the entry we are about to modify */ if (fixup_tombstone) { e = find_entry2modify_only_ext( pb, be, addr, TOMBSTONE_INCLUDED, &txn, &result_sent ); } else { e = find_entry2modify( pb, be, addr, &txn, &result_sent ); } if (e == NULL) { ldap_result_code = -1; goto error_return; /* error result sent by find_entry2modify() */ } } if ( !is_fixup_operation && !fixup_tombstone) { if (!repl_op && slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE)) { ldap_result_code = LDAP_UNWILLING_TO_PERFORM; ldap_result_message = "Operation not allowed on tombstone entry."; slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "Attempt to modify a tombstone entry %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry ))); goto error_return; } opcsn = operation_get_csn (operation); if (NULL == opcsn && operation->o_csngen_handler) { /* * Current op is a user request. Opcsn will be assigned * if the dn is in an updatable replica. */ opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL ); } if (opcsn) { entry_set_maxcsn (e->ep_entry, opcsn); } } /* Save away a copy of the entry, before modifications */ slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry )); if ( (ldap_result_code = plugin_call_acl_mods_access( pb, e->ep_entry, mods, &errbuf)) != LDAP_SUCCESS ) { ldap_result_message= errbuf; goto error_return; } /* create a copy of the entry and apply the changes to it */ if ( (ec = backentry_dup( e )) == NULL ) { ldap_result_code= LDAP_OPERATIONS_ERROR; goto error_return; } if(!repl_op){ remove_illegal_mods(mods); } /* ec is the entry that our bepreop should get to mess with */ slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, ec->ep_entry ); slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code); opreturn = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN); if (opreturn || (slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code) && ldap_result_code) || (slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn) && opreturn)) { slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code); slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn); if (!ldap_result_code) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "SLAPI_PLUGIN_BE_PRE_MODIFY_FN " "returned error but did not set SLAPI_RESULT_CODE\n"); ldap_result_code = LDAP_OPERATIONS_ERROR; } if (SLAPI_PLUGIN_NOOP == opreturn) { not_an_error = 1; rc = opreturn = LDAP_SUCCESS; } else if (!opreturn) { opreturn = SLAPI_PLUGIN_FAILURE; slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn); } slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); goto error_return; } /* The Plugin may have messed about with some of the PBlock parameters... ie. mods */ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); /* apply the mods, check for syntax, schema problems, etc. */ if (modify_apply_check_expand(pb, operation, mods, e, ec, &postentry, &ldap_result_code, &ldap_result_message)) { goto error_return; } /* the schema check could have added a repl conflict mod * get the mods again */ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); slapi_mods_init_byref(&smods,mods); mod_count = slapi_mods_get_num_mods(&smods); /* * Grab a copy of the mods and the entry in case the be_txn_preop changes * the them. If we have a failure, then we need to reset the mods to their * their original state; */ mods_original = copy_mods(mods); if ( (original_entry = backentry_dup( ec )) == NULL ) { ldap_result_code= LDAP_OPERATIONS_ERROR; goto error_return; } } /* if (0 == retry_count) just once */ /* call the transaction pre modify plugins just after creating the transaction */ retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN); if (retval) { slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_modify", "SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN plugin " "returned error code %d\n", retval ); slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code); slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn); if (SLAPI_PLUGIN_NOOP == retval) { not_an_error = 1; rc = retval = LDAP_SUCCESS; } if (!opreturn) { slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); } slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); goto error_return; } /* the mods might have been changed, so get the latest */ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); /* make sure the betxnpreop did not alter any of the mods that had already previously been applied */ slapi_mods_done(&smods); slapi_mods_init_byref(&smods,mods); new_mod_count = slapi_mods_get_num_mods(&smods); if (new_mod_count < mod_count) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "Error: BE_TXN_PRE_MODIFY plugin has removed " "mods from the original list - mod count was [%d] now [%d] " "mods will not be applied - mods list changes must be done " "in the BE_PRE_MODIFY plugin, not the BE_TXN_PRE_MODIFY\n", mod_count, new_mod_count ); } else if (new_mod_count > mod_count) { /* apply the new betxnpremod mods */ /* apply the mods, check for syntax, schema problems, etc. */ if (modify_apply_check_expand(pb, operation, &mods[mod_count], e, ec, &postentry, &ldap_result_code, &ldap_result_message)) { goto error_return; } } /* else if new_mod_count == mod_count then betxnpremod plugin did nothing */ /* * Update the ID to Entry index. * Note that id2entry_add replaces the entry, so the Entry ID * stays the same. */ retval = id2entry_add_ext( be, ec, &txn, 1, &cache_rc ); if (DB_LOCK_DEADLOCK == retval) { /* Abort and re-try */ continue; } if (0 != retval) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : ""); if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count); goto error_return; } retval = index_add_mods( be, mods, e, ec, &txn ); if (DB_LOCK_DEADLOCK == retval) { /* Abort and re-try */ continue; } if (0 != retval) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "index_add_mods failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : ""); if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count); goto error_return; } /* * Remove the old entry from the Virtual List View indexes. * Add the new entry to the Virtual List View indexes. * If the entry is ruv, no need to update vlv. */ if (!is_ruv) { retval= vlv_update_all_indexes(&txn, be, pb, e, ec); if (DB_LOCK_DEADLOCK == retval) { /* Abort and re-try */ continue; } if (0 != retval) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "vlv_update_index failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : ""); if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count); goto error_return; } } if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) { ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); if (-1 == ruv_c_init) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "ldbm_txn_ruv_modify_context failed to construct RUV modify context\n"); ldap_result_code= LDAP_OPERATIONS_ERROR; retval = 0; goto error_return; } } if (ruv_c_init) { retval = modify_update_all( be, pb, &ruv_c, &txn ); if (DB_LOCK_DEADLOCK == retval) { /* Abort and re-try */ continue; } if (0 != retval) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "modify_update_all failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : ""); if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; ldap_result_code= LDAP_OPERATIONS_ERROR; goto error_return; } } if (0 == retval) { break; } } if (retry_count == RETRY_TIMES) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "Retry count exceeded in modify\n"); ldap_result_code= LDAP_BUSY; goto error_return; } if (ruv_c_init) { if (modify_switch_entries(&ruv_c, be) != 0 ) { ldap_result_code= LDAP_OPERATIONS_ERROR; slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify", "modify_switch_entries failed\n"); goto error_return; } } if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) { MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count); goto error_return; } /* e uncached */ /* we must return both e (which has been deleted) and new entry ec to cache */ /* cache_replace removes e from the cache hash tables */ cache_unlock_entry( &inst->inst_cache, e ); CACHE_RETURN( &inst->inst_cache, &e ); /* lock new entry in cache to prevent usage until we are complete */ cache_lock_entry( &inst->inst_cache, ec ); ec_locked = 1; postentry = slapi_entry_dup( ec->ep_entry ); slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry ); /* invalidate virtual cache */ ec->ep_entry->e_virtual_watermark = 0; /* * LP Fix of crash when the commit will fail: * If the commit fail, the common error path will * try to unlock the entry again and crash (PR_ASSERT * in debug mode. * By just setting e to NULL, we avoid this. It's OK since * we don't use e after that in the normal case. */ e = NULL; /* call the transaction post modify plugins just before the commit */ if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN))) { slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_modify", "SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN plugin " "returned error code %d\n", retval ); if (!ldap_result_code) { slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code); } if (!opreturn) { slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn); } if (!opreturn) { slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); } slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); goto error_return; } /* Release SERIAL LOCK */ retval = dblayer_txn_commit(be, &txn); /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); if (0 != retval) { if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; ldap_result_code= LDAP_OPERATIONS_ERROR; goto error_return; } rc= 0; goto common_return; error_return: if ( postentry != NULL ) { slapi_entry_free( postentry ); postentry = NULL; slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, NULL ); } if (retval == DB_RUNRECOVERY) { dblayer_remember_disk_filled(li); ldbm_nasty("ldbm_back_modify","Modify",81,retval); disk_full = 1; } if (disk_full) { rc= return_on_disk_full(li); } else { if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) { /* make sure SLAPI_RESULT_CODE and SLAPI_PLUGIN_OPRETURN are set */ int val = 0; slapi_pblock_get(pb, SLAPI_RESULT_CODE, &val); if (!val) { if (!ldap_result_code) { ldap_result_code = LDAP_OPERATIONS_ERROR; } slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code); } slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &val ); if (!val) { opreturn = -1; slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &opreturn ); } /* call the transaction post modify plugins just before the abort */ /* plugins called before abort should check for the OPRETURN or RESULT_CODE and skip processing if they don't want do anything - some plugins that keep track of a counter (usn, dna) may want to "rollback" the counter in this case */ if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN))) { slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_modify", "SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN plugin returned error code %d\n", retval ); slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code); slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn); if (!opreturn) { slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); } } /* It is safer not to abort when the transaction is not started. */ /* Release SERIAL LOCK */ dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */ /* txn is no longer valid - reset the txn pointer to the parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); } if (!not_an_error) { rc = SLAPI_FAIL_GENERAL; } } /* if ec is in cache, remove it, then add back e if we still have it */ if (inst && cache_is_in_cache(&inst->inst_cache, ec)) { CACHE_REMOVE( &inst->inst_cache, ec ); /* if ec was in cache, e was not - add back e */ if (e) { if (CACHE_ADD( &inst->inst_cache, e, NULL ) < 0) { slapi_log_err(SLAPI_LOG_CACHE, "ldbm_back_modify", "CACHE_ADD %s failed\n", slapi_entry_get_dn(e->ep_entry)); } } } common_return: slapi_mods_done(&smods); if (inst) { if (ec_locked || cache_is_in_cache(&inst->inst_cache, ec)) { cache_unlock_entry(&inst->inst_cache, ec); } else if (e) { /* if ec was not in cache, cache_replace was not done. * i.e., e was not unlocked. */ cache_unlock_entry(&inst->inst_cache, e); CACHE_RETURN(&inst->inst_cache, &e); } CACHE_RETURN(&inst->inst_cache, &ec); if (inst->inst_ref_count) { slapi_counter_decrement(inst->inst_ref_count); } } /* result code could be used in the bepost plugin functions. */ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code); /* The bepostop is called even if the operation fails. */ if (!disk_full) plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN); if (ruv_c_init) { modify_term(&ruv_c, be); } if (ldap_result_code == -1) { /* Reset to LDAP_NO_SUCH_OBJECT*/ ldap_result_code = LDAP_NO_SUCH_OBJECT; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code); } else { if (not_an_error) { /* This is mainly used by urp. Solved conflict is not an error. * And we don't want the supplier to halt sending the updates. */ ldap_result_code = LDAP_SUCCESS; } if (!result_sent) { /* result is already sent in find_entry. */ slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL ); } } /* free our backups */ ldap_mods_free(mods_original, 1); backentry_free(&original_entry); backentry_free(&tmpentry); slapi_ch_free_string(&errbuf); return rc; }
static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid) { TALLOC_CTX *ctx; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; int rc = LDAP_SERVER_DOWN; int count = 0; LDAPMessage *result = NULL; LDAPMessage *entry = NULL; LDAPMod **mods = NULL; char *new_id_str; char *filter = NULL; const char *dn = NULL; const char **attr_list; const char *type; /* Only do query if we are online */ if (idmap_is_offline()) { return NT_STATUS_FILE_IS_OFFLINE; } if ( ! idmap_alloc_ldap) { return NT_STATUS_UNSUCCESSFUL; } ctx = talloc_new(idmap_alloc_ldap); if ( ! ctx) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } /* get type */ switch (xid->type) { case ID_TYPE_UID: type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER); break; case ID_TYPE_GID: type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER); break; default: DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); return NT_STATUS_INVALID_PARAMETER; } filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL); CHECK_ALLOC_DONE(filter); attr_list = get_attr_list(ctx, idpool_attr_list); CHECK_ALLOC_DONE(attr_list); rc = smbldap_search(idmap_alloc_ldap->smbldap_state, idmap_alloc_ldap->suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); if (rc != LDAP_SUCCESS) { DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL)); goto done; } talloc_autofree_ldapmsg(ctx, result); count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result); if (count != 1) { DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL)); goto done; } entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result); dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry); if ( ! dn) { goto done; } new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id); if ( ! new_id_str) { DEBUG(0,("Out of memory\n")); ret = NT_STATUS_NO_MEMORY; goto done; } smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str); if (mods == NULL) { DEBUG(0,("smbldap_set_mod() failed.\n")); goto done; } rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods); ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { DEBUG(1,("Failed to allocate new %s. " "smbldap_modify() failed.\n", type)); goto done; } ret = NT_STATUS_OK; done: talloc_free(ctx); return ret; }
krb5_error_code krb5_ldap_create_krbcontainer(krb5_context context, const krb5_ldap_krbcontainer_params *krbcontparams) { LDAP *ld=NULL; char *strval[2]={NULL}, *kerberoscontdn=NULL, **rdns=NULL; int pmask=0; LDAPMod **mods = NULL; krb5_error_code st=0; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_context *ldap_context=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; SETUP_CONTEXT (); /* get ldap handle */ GET_HANDLE (); if (krbcontparams != NULL && krbcontparams->DN != NULL) { kerberoscontdn = krbcontparams->DN; } else { st = EINVAL; krb5_set_error_message(context, st, _("Kerberos Container information is missing")); goto cleanup; } strval[0] = "krbContainer"; strval[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) goto cleanup; rdns = ldap_explode_dn(kerberoscontdn, 1); if (rdns == NULL) { st = EINVAL; krb5_set_error_message(context, st, _("Invalid Kerberos container DN")); goto cleanup; } strval[0] = rdns[0]; strval[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) goto cleanup; /* check if the policy reference value exists and is of krbticketpolicyreference object class */ if (krbcontparams && krbcontparams->policyreference) { st = checkattributevalue(ld, krbcontparams->policyreference, "objectclass", policyclass, &pmask); CHECK_CLASS_VALIDITY(st, pmask, _("ticket policy object value: ")); strval[0] = krbcontparams->policyreference; strval[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_ADD, strval)) != 0) goto cleanup; } /* create the kerberos container */ if ((st = ldap_add_ext_s(ld, kerberoscontdn, mods, NULL, NULL)) != LDAP_SUCCESS) { int ost = st; st = translate_ldap_error (st, OP_ADD); krb5_set_error_message(context, st, _("Kerberos Container create FAILED: %s"), ldap_err2string(ost)); goto cleanup; } cleanup: if (rdns) ldap_value_free (rdns); ldap_mods_free(mods, 1); krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return(st); }
static NTSTATUS idmap_ldap_allocate_id_internal(struct idmap_domain *dom, struct unixid *xid) { TALLOC_CTX *mem_ctx; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; int rc = LDAP_SERVER_DOWN; int count = 0; LDAPMessage *result = NULL; LDAPMessage *entry = NULL; LDAPMod **mods = NULL; char *id_str; char *new_id_str; char *filter = NULL; const char *dn = NULL; const char **attr_list; const char *type; struct idmap_ldap_context *ctx; /* Only do query if we are online */ if (idmap_is_offline()) { return NT_STATUS_FILE_IS_OFFLINE; } ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); mem_ctx = talloc_new(ctx); if (!mem_ctx) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } /* get type */ switch (xid->type) { case ID_TYPE_UID: type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER); break; case ID_TYPE_GID: type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER); break; default: DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); return NT_STATUS_INVALID_PARAMETER; } filter = talloc_asprintf(mem_ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL); CHECK_ALLOC_DONE(filter); attr_list = get_attr_list(mem_ctx, idpool_attr_list); CHECK_ALLOC_DONE(attr_list); DEBUG(10, ("Search of the id pool (filter: %s)\n", filter)); rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); if (rc != LDAP_SUCCESS) { DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL)); goto done; } smbldap_talloc_autofree_ldapmsg(mem_ctx, result); count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result); if (count != 1) { DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL)); goto done; } entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result); dn = smbldap_talloc_dn(mem_ctx, ctx->smbldap_state->ldap_struct, entry); if ( ! dn) { goto done; } id_str = smbldap_talloc_single_attribute( ctx->smbldap_state->ldap_struct, entry, type, mem_ctx); if (id_str == NULL) { DEBUG(0,("%s attribute not found\n", type)); ret = NT_STATUS_UNSUCCESSFUL; goto done; } xid->id = strtoul(id_str, NULL, 10); /* make sure we still have room to grow */ switch (xid->type) { case ID_TYPE_UID: if (xid->id > dom->high_id) { DEBUG(0,("Cannot allocate uid above %lu!\n", (unsigned long)dom->high_id)); goto done; } break; case ID_TYPE_GID: if (xid->id > dom->high_id) { DEBUG(0,("Cannot allocate gid above %lu!\n", (unsigned long)dom->high_id)); goto done; } break; default: /* impossible */ goto done; } new_id_str = talloc_asprintf(mem_ctx, "%lu", (unsigned long)xid->id + 1); if ( ! new_id_str) { DEBUG(0,("Out of memory\n")); ret = NT_STATUS_NO_MEMORY; goto done; } smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str); smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str); if (mods == NULL) { DEBUG(0,("smbldap_set_mod() failed.\n")); goto done; } DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", id_str, new_id_str)); rc = smbldap_modify(ctx->smbldap_state, dn, mods); ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { DEBUG(1,("Failed to allocate new %s. " "smbldap_modify() failed.\n", type)); goto done; } ret = NT_STATUS_OK; done: talloc_free(mem_ctx); return ret; }
krb5_error_code krb5_ldap_create_realm(krb5_context context, krb5_ldap_realm_params *rparams, int mask) { LDAP *ld=NULL; krb5_error_code st=0; char *dn=NULL; char *strval[4]={NULL}; char *contref[2]={NULL}; LDAPMod **mods = NULL; int i=0, objectmask=0, subtreecount=0; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_context *ldap_context=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; char *realm_name; SETUP_CONTEXT (); /* Check input validity ... */ if (ldap_context->container_dn == NULL || rparams == NULL || rparams->realm_name == NULL || ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) || ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || 0) { st = EINVAL; return st; } /* get ldap handle */ GET_HANDLE (); realm_name = rparams->realm_name; if (asprintf(&dn, "cn=%s,%s", realm_name, ldap_context->container_dn) < 0) dn = NULL; CHECK_NULL(dn); strval[0] = realm_name; strval[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) goto cleanup; strval[0] = "top"; strval[1] = "krbrealmcontainer"; strval[2] = "krbticketpolicyaux"; strval[3] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) goto cleanup; /* SUBTREE ATTRIBUTE */ if (mask & LDAP_REALM_SUBTREE) { if ( rparams->subtree!=NULL) { subtreecount = rparams->subtreecount; for (i=0; rparams->subtree[i]!=NULL && i<subtreecount; i++) { if (strlen(rparams->subtree[i]) != 0) { st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass, &objectmask); CHECK_CLASS_VALIDITY(st, objectmask, _("realm object value: ")); } } if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD, rparams->subtree)) != 0) { goto cleanup; } } } /* CONTAINER REFERENCE ATTRIBUTE */ if (mask & LDAP_REALM_CONTREF) { if (strlen(rparams->containerref) != 0 ) { st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass, &objectmask); CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: "); contref[0] = rparams->containerref; contref[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD, contref)) != 0) goto cleanup; } } /* SEARCHSCOPE ATTRIBUTE */ if (mask & LDAP_REALM_SEARCHSCOPE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD, (rparams->search_scope == LDAP_SCOPE_ONELEVEL || rparams->search_scope == LDAP_SCOPE_SUBTREE) ? rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0) goto cleanup; } if (mask & LDAP_REALM_MAXRENEWLIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD, rparams->max_renewable_life)) != 0) goto cleanup; } /* krbMaxTicketLife ATTRIBUTE */ if (mask & LDAP_REALM_MAXTICKETLIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD, rparams->max_life)) != 0) goto cleanup; } /* krbTicketFlags ATTRIBUTE */ if (mask & LDAP_REALM_KRBTICKETFLAGS) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD, rparams->tktflags)) != 0) goto cleanup; } /* realm creation operation */ if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) { st = set_ldap_error (context, st, OP_ADD); goto cleanup; } cleanup: if (dn) free(dn); ldap_mods_free(mods, 1); krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return st; }
static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id_map *map) { NTSTATUS ret; TALLOC_CTX *memctx; struct idmap_ldap_context *ctx; LDAPMessage *entry = NULL; LDAPMod **mods = NULL; const char *type; char *id_str; char *sid; char *dn; int rc = -1; /* Only do query if we are online */ if (idmap_is_offline()) { return NT_STATUS_FILE_IS_OFFLINE; } ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context); switch(map->xid.type) { case ID_TYPE_UID: type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_UIDNUMBER); break; case ID_TYPE_GID: type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_GIDNUMBER); break; default: return NT_STATUS_INVALID_PARAMETER; } memctx = talloc_new(ctx); if ( ! memctx) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id); CHECK_ALLOC_DONE(id_str); sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid)); CHECK_ALLOC_DONE(sid); dn = talloc_asprintf(memctx, "%s=%s,%s", get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid, ctx->suffix); CHECK_ALLOC_DONE(dn); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY); smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods, type, id_str); smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods, get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid); if ( ! mods) { DEBUG(2, ("ERROR: No mods?\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; } /* TODO: remove conflicting mappings! */ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY); DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str)); rc = smbldap_add(ctx->smbldap_state, dn, mods); ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; ldap_get_option(ctx->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu " "mapping [%s]\n", sid, (unsigned long)map->xid.id, type)); DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", ld_error ? ld_error : "(NULL)", ldap_err2string (rc))); if (ld_error) { ldap_memfree(ld_error); } ret = NT_STATUS_UNSUCCESSFUL; goto done; } DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to " "%lu [%s]\n", sid, (unsigned long)map->xid.id, type)); ret = NT_STATUS_OK; done: talloc_free(memctx); return ret; }
krb5_error_code krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry, char **db_args) { int l=0, kerberos_principal_object_type=0; krb5_error_code st=0, tempst=0; LDAP *ld=NULL; LDAPMessage *result=NULL, *ent=NULL; char *user=NULL, *subtree=NULL, *principal_dn=NULL; char **values=NULL, *strval[10]= {NULL}, errbuf[1024]; struct berval **bersecretkey=NULL; LDAPMod **mods=NULL; krb5_boolean create_standalone_prinicipal=FALSE; krb5_boolean krb_identity_exists=FALSE, establish_links=FALSE; char *standalone_principal_dn=NULL; krb5_tl_data *tl_data=NULL; krb5_key_data **keys=NULL; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_context *ldap_context=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; osa_princ_ent_rec princ_ent; xargs_t xargs = {0}; char *polname = NULL; OPERATION optype; krb5_boolean found_entry = FALSE; /* Clear the global error string */ krb5_clear_error_message(context); SETUP_CONTEXT(); if (ldap_context->lrparams == NULL || ldap_context->krbcontainer == NULL) return EINVAL; /* get ldap handle */ GET_HANDLE(); if (is_principal_in_realm(ldap_context, entry->princ) != 0) { st = EINVAL; krb5_set_error_message(context, st, _("Principal does not belong to " "the default realm")); goto cleanup; } /* get the principal information to act on */ if (entry->princ) { if (((st=krb5_unparse_name(context, entry->princ, &user)) != 0) || ((st=krb5_ldap_unparse_principal_name(user)) != 0)) goto cleanup; } /* Identity the type of operation, it can be * add principal or modify principal. * hack if the entry->mask has KRB_PRINCIPAL flag set * then it is a add operation */ if (entry->mask & KADM5_PRINCIPAL) optype = ADD_PRINCIPAL; else optype = MODIFY_PRINCIPAL; if (((st=krb5_get_princ_type(context, entry, &kerberos_principal_object_type)) != 0) || ((st=krb5_get_userdn(context, entry, &principal_dn)) != 0)) goto cleanup; if ((st=process_db_args(context, db_args, &xargs, optype)) != 0) goto cleanup; if (entry->mask & KADM5_LOAD) { int tree = 0, ntrees = 0, princlen = 0, numlentries = 0; char **subtreelist = NULL, *filter = NULL; /* A load operation is special, will do a mix-in (add krbprinc * attrs to a non-krb object entry) if an object exists with a * matching krbprincipalname attribute so try to find existing * object and set principal_dn. This assumes that the * krbprincipalname attribute is unique (only one object entry has * a particular krbprincipalname attribute). */ if (user == NULL) { /* must have principal name for search */ st = EINVAL; krb5_set_error_message(context, st, _("operation can not continue, principal " "name not found")); goto cleanup; } princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */ if ((filter = malloc(princlen)) == NULL) { st = ENOMEM; goto cleanup; } snprintf(filter, princlen, FILTER"%s))", user); /* get the current subtree list */ if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) goto cleanup; found_entry = FALSE; /* search for entry with matching krbprincipalname attribute */ for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) { result = NULL; if (principal_dn == NULL) { LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS); } else { /* just look for entry with principal_dn */ LDAP_SEARCH_1(principal_dn, LDAP_SCOPE_BASE, filter, principal_attributes, IGNORE_STATUS); } if (st == LDAP_SUCCESS) { numlentries = ldap_count_entries(ld, result); if (numlentries > 1) { ldap_msgfree(result); free(filter); st = EINVAL; krb5_set_error_message(context, st, _("operation can not continue, " "more than one entry with " "principal name \"%s\" found"), user); goto cleanup; } else if (numlentries == 1) { found_entry = TRUE; if (principal_dn == NULL) { ent = ldap_first_entry(ld, result); if (ent != NULL) { /* setting principal_dn will cause that entry to be modified further down */ if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) { ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); st = set_ldap_error (context, st, 0); ldap_msgfree(result); free(filter); goto cleanup; } } } } if (result) ldap_msgfree(result); } else if (st != LDAP_NO_SUCH_OBJECT) { /* could not perform search, return with failure */ st = set_ldap_error (context, st, 0); free(filter); goto cleanup; } /* * If it isn't found then assume a standalone princ entry is to * be created. */ } /* end for (tree = 0; principal_dn == ... */ free(filter); if (found_entry == FALSE && principal_dn != NULL) { /* * if principal_dn is null then there is code further down to * deal with setting standalone_principal_dn. Also note that * this will set create_standalone_prinicipal true for * non-mix-in entries which is okay if loading from a dump. */ create_standalone_prinicipal = TRUE; standalone_principal_dn = strdup(principal_dn); CHECK_NULL(standalone_principal_dn); } } /* end if (entry->mask & KADM5_LOAD */ /* time to generate the DN information with the help of * containerdn, principalcontainerreference or * realmcontainerdn information */ if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */ /* get the subtree information */ if (entry->princ->length == 2 && entry->princ->data[0].length == strlen("krbtgt") && strncmp(entry->princ->data[0].data, "krbtgt", entry->princ->data[0].length) == 0) { /* if the principal is a inter-realm principal, always created in the realm container */ subtree = strdup(ldap_context->lrparams->realmdn); } else if (xargs.containerdn) { if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) { if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) { int ost = st; st = EINVAL; snprintf(errbuf, sizeof(errbuf), _("'%s' not found: "), xargs.containerdn); prepend_err_str(context, errbuf, st, ost); } goto cleanup; } subtree = strdup(xargs.containerdn); } else if (ldap_context->lrparams->containerref && strlen(ldap_context->lrparams->containerref) != 0) { /* * Here the subtree should be changed with * principalcontainerreference attribute value */ subtree = strdup(ldap_context->lrparams->containerref); } else { subtree = strdup(ldap_context->lrparams->realmdn); } CHECK_NULL(subtree); if (asprintf(&standalone_principal_dn, "krbprincipalname=%s,%s", user, subtree) < 0) standalone_principal_dn = NULL; CHECK_NULL(standalone_principal_dn); /* * free subtree when you are done using the subtree * set the boolean create_standalone_prinicipal to TRUE */ create_standalone_prinicipal = TRUE; free(subtree); subtree = NULL; } /* * If the DN information is presented by the user, time to * validate the input to ensure that the DN falls under * any of the subtrees */ if (xargs.dn_from_kbd == TRUE) { /* make sure the DN falls in the subtree */ int tre=0, dnlen=0, subtreelen=0, ntrees=0; char **subtreelist=NULL; char *dn=NULL; krb5_boolean outofsubtree=TRUE; if (xargs.dn != NULL) { dn = xargs.dn; } else if (xargs.linkdn != NULL) { dn = xargs.linkdn; } else if (standalone_principal_dn != NULL) { /* * Even though the standalone_principal_dn is constructed * within this function, there is the containerdn input * from the user that can become part of the it. */ dn = standalone_principal_dn; } /* get the current subtree list */ if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) goto cleanup; for (tre=0; tre<ntrees; ++tre) { if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) { outofsubtree = FALSE; break; } else { dnlen = strlen (dn); subtreelen = strlen(subtreelist[tre]); if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) { outofsubtree = FALSE; break; } } } for (tre=0; tre < ntrees; ++tre) { free(subtreelist[tre]); } if (outofsubtree == TRUE) { st = EINVAL; krb5_set_error_message(context, st, _("DN is out of the realm subtree")); goto cleanup; } /* * dn value will be set either by dn, linkdn or the standalone_principal_dn * In the first 2 cases, the dn should be existing and in the last case we * are supposed to create the ldap object. so the below should not be * executed for the last case. */ if (standalone_principal_dn == NULL) { /* * If the ldap object is missing, this results in an error. */ /* * Search for krbprincipalname attribute here. * This is to find if a kerberos identity is already present * on the ldap object, in which case adding a kerberos identity * on the ldap object should result in an error. */ char *attributes[]= {"krbticketpolicyreference", "krbprincipalname", NULL}; LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS); if (st == LDAP_SUCCESS) { ent = ldap_first_entry(ld, result); if (ent != NULL) { if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) { ldap_value_free(values); } if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { krb_identity_exists = TRUE; ldap_value_free(values); } } ldap_msgfree(result); } else { st = set_ldap_error(context, st, OP_SEARCH); goto cleanup; } } } /* * If xargs.dn is set then the request is to add a * kerberos principal on a ldap object, but if * there is one already on the ldap object this * should result in an error. */ if (xargs.dn != NULL && krb_identity_exists == TRUE) { st = EINVAL; snprintf(errbuf, sizeof(errbuf), _("ldap object is already kerberized")); krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } if (xargs.linkdn != NULL) { /* * link information can be changed using modprinc. * However, link information can be changed only on the * standalone kerberos principal objects. A standalone * kerberos principal object is of type krbprincipal * structural objectclass. * * NOTE: kerberos principals on an ldap object can't be * linked to other ldap objects. */ if (optype == MODIFY_PRINCIPAL && kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) { st = EINVAL; snprintf(errbuf, sizeof(errbuf), _("link information can not be set/updated as the " "kerberos principal belongs to an ldap object")); krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } /* * Check the link information. If there is already a link * existing then this operation is not allowed. */ { char **linkdns=NULL; int j=0; if ((st=krb5_get_linkdn(context, entry, &linkdns)) != 0) { snprintf(errbuf, sizeof(errbuf), _("Failed getting object references")); krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } if (linkdns != NULL) { st = EINVAL; snprintf(errbuf, sizeof(errbuf), _("kerberos principal is already linked to a ldap " "object")); krb5_set_error_message(context, st, "%s", errbuf); for (j=0; linkdns[j] != NULL; ++j) free (linkdns[j]); free (linkdns); goto cleanup; } } establish_links = TRUE; } if (entry->mask & KADM5_LAST_SUCCESS) { memset(strval, 0, sizeof(strval)); if ((strval[0]=getstringtime(entry->last_success)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastSuccessfulAuth", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free (strval[0]); } if (entry->mask & KADM5_LAST_FAILED) { memset(strval, 0, sizeof(strval)); if ((strval[0]=getstringtime(entry->last_failed)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastFailedAuth", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free(strval[0]); } if (entry->mask & KADM5_FAIL_AUTH_COUNT) { krb5_kvno fail_auth_count; fail_auth_count = entry->fail_auth_count; if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) fail_auth_count++; st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_REPLACE, fail_auth_count); if (st != 0) goto cleanup; } else if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) { int attr_mask = 0; krb5_boolean has_fail_count; /* Check if the krbLoginFailedCount attribute exists. (Through * krb5 1.8.1, it wasn't set in new entries.) */ st = krb5_get_attributes_mask(context, entry, &attr_mask); if (st != 0) goto cleanup; has_fail_count = ((attr_mask & KDB_FAIL_AUTH_COUNT_ATTR) != 0); /* * If the client library and server supports RFC 4525, * then use it to increment by one the value of the * krbLoginFailedCount attribute. Otherwise, assert the * (provided) old value by deleting it before adding. */ #ifdef LDAP_MOD_INCREMENT if (ldap_server_handle->server_info->modify_increment && has_fail_count) { st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_INCREMENT, 1); if (st != 0) goto cleanup; } else { #endif /* LDAP_MOD_INCREMENT */ if (has_fail_count) { st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_DELETE, entry->fail_auth_count); if (st != 0) goto cleanup; } st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_ADD, entry->fail_auth_count + 1); if (st != 0) goto cleanup; #ifdef LDAP_MOD_INCREMENT } #endif } else if (optype == ADD_PRINCIPAL) { /* Initialize krbLoginFailedCount in new entries to help avoid a * race during the first failed login. */ st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_ADD, 0); } if (entry->mask & KADM5_MAX_LIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entry->max_life)) != 0) goto cleanup; } if (entry->mask & KADM5_MAX_RLIFE) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE, entry->max_renewable_life)) != 0) goto cleanup; } if (entry->mask & KADM5_ATTRIBUTES) { if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE, entry->attributes)) != 0) goto cleanup; } if (entry->mask & KADM5_PRINCIPAL) { memset(strval, 0, sizeof(strval)); strval[0] = user; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0) goto cleanup; } if (entry->mask & KADM5_PRINC_EXPIRE_TIME) { memset(strval, 0, sizeof(strval)); if ((strval[0]=getstringtime(entry->expiration)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free (strval[0]); } if (entry->mask & KADM5_PW_EXPIRATION) { memset(strval, 0, sizeof(strval)); if ((strval[0]=getstringtime(entry->pw_expiration)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free (strval[0]); } if (entry->mask & KADM5_POLICY) { memset(&princ_ent, 0, sizeof(princ_ent)); for (tl_data=entry->tl_data; tl_data; tl_data=tl_data->tl_data_next) { if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) { /* FIX ME: I guess the princ_ent should be freed after this call */ if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) { goto cleanup; } } } if (princ_ent.aux_attributes & KADM5_POLICY) { memset(strval, 0, sizeof(strval)); if ((st = krb5_ldap_name_to_policydn (context, princ_ent.policy, &polname)) != 0) goto cleanup; strval[0] = polname; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) goto cleanup; } else { st = EINVAL; krb5_set_error_message(context, st, "Password policy value null"); goto cleanup; } } else if (entry->mask & KADM5_LOAD && found_entry == TRUE) { /* * a load is special in that existing entries must have attrs that * removed. */ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0) goto cleanup; } if (entry->mask & KADM5_POLICY_CLR) { if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) goto cleanup; } if (entry->mask & KADM5_KEY_DATA || entry->mask & KADM5_KVNO) { krb5_kvno mkvno; if ((st=krb5_dbe_lookup_mkvno(context, entry, &mkvno)) != 0) goto cleanup; bersecretkey = krb5_encode_krbsecretkey (entry->key_data, entry->n_key_data, mkvno); if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, bersecretkey)) != 0) goto cleanup; if (!(entry->mask & KADM5_PRINCIPAL)) { memset(strval, 0, sizeof(strval)); if ((strval[0]=getstringtime(entry->pw_expiration)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free (strval[0]); } /* Update last password change whenever a new key is set */ { krb5_timestamp last_pw_changed; if ((st=krb5_dbe_lookup_last_pwd_change(context, entry, &last_pw_changed)) != 0) goto cleanup; memset(strval, 0, sizeof(strval)); if ((strval[0] = getstringtime(last_pw_changed)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastPwdChange", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free (strval[0]); } } /* Modify Key data ends here */ /* Set tl_data */ if (entry->tl_data != NULL) { int count = 0; struct berval **ber_tl_data = NULL; krb5_tl_data *ptr; krb5_timestamp unlock_time; for (ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE #ifdef SECURID || ptr->tl_data_type == KRB5_TL_DB_ARGS #endif || ptr->tl_data_type == KRB5_TL_KADM_DATA || ptr->tl_data_type == KDB_TL_USER_INFO || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL || ptr->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) continue; count++; } if (count != 0) { int j; ber_tl_data = (struct berval **) calloc (count + 1, sizeof (struct berval*)); if (ber_tl_data == NULL) { st = ENOMEM; goto cleanup; } for (j = 0, ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { /* Ignore tl_data that are stored in separate directory * attributes */ if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE #ifdef SECURID || ptr->tl_data_type == KRB5_TL_DB_ARGS #endif || ptr->tl_data_type == KRB5_TL_KADM_DATA || ptr->tl_data_type == KDB_TL_USER_INFO || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL || ptr->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) continue; if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0) break; j++; } if (st == 0) { ber_tl_data[count] = NULL; st=krb5_add_ber_mem_ldap_mod(&mods, "krbExtraData", LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, ber_tl_data); } for (j = 0; ber_tl_data[j] != NULL; j++) { free(ber_tl_data[j]->bv_val); free(ber_tl_data[j]); } free(ber_tl_data); if (st != 0) goto cleanup; } if ((st=krb5_dbe_lookup_last_admin_unlock(context, entry, &unlock_time)) != 0) goto cleanup; if (unlock_time != 0) { /* Update last admin unlock */ memset(strval, 0, sizeof(strval)); if ((strval[0] = getstringtime(unlock_time)) == NULL) goto cleanup; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastAdminUnlock", LDAP_MOD_REPLACE, strval)) != 0) { free (strval[0]); goto cleanup; } free (strval[0]); } } /* Directory specific attribute */ if (xargs.tktpolicydn != NULL) { int tmask=0; if (strlen(xargs.tktpolicydn) != 0) { st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask); CHECK_CLASS_VALIDITY(st, tmask, _("ticket policy object value: ")); strval[0] = xargs.tktpolicydn; strval[1] = NULL; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) goto cleanup; } else { /* if xargs.tktpolicydn is a empty string, then delete * already existing krbticketpolicyreference attr */ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) goto cleanup; } } if (establish_links == TRUE) { memset(strval, 0, sizeof(strval)); strval[0] = xargs.linkdn; if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbObjectReferences", LDAP_MOD_REPLACE, strval)) != 0) goto cleanup; } /* * in case mods is NULL then return * not sure but can happen in a modprinc * so no need to return an error * addprinc will at least have the principal name * and the keys passed in */ if (mods == NULL) goto cleanup; if (create_standalone_prinicipal == TRUE) { memset(strval, 0, sizeof(strval)); strval[0] = "krbprincipal"; strval[1] = "krbprincipalaux"; strval[2] = "krbTicketPolicyAux"; if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) goto cleanup; st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); if (st == LDAP_ALREADY_EXISTS && entry->mask & KADM5_LOAD) { /* a load operation must replace an existing entry */ st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL); if (st != LDAP_SUCCESS) { snprintf(errbuf, sizeof(errbuf), _("Principal delete failed (trying to replace " "entry): %s"), ldap_err2string(st)); st = translate_ldap_error (st, OP_ADD); krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } else { st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); } } if (st != LDAP_SUCCESS) { snprintf(errbuf, sizeof(errbuf), _("Principal add failed: %s"), ldap_err2string(st)); st = translate_ldap_error (st, OP_ADD); krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } } else { /* * Here existing ldap object is modified and can be related * to any attribute, so always ensure that the ldap * object is extended with all the kerberos related * objectclasses so that there are no constraint * violations. */ { char *attrvalues[] = {"krbprincipalaux", "krbTicketPolicyAux", NULL}; int p, q, r=0, amask=0; if ((st=checkattributevalue(ld, (xargs.dn) ? xargs.dn : principal_dn, "objectclass", attrvalues, &amask)) != 0) goto cleanup; memset(strval, 0, sizeof(strval)); for (p=1, q=0; p<=2; p<<=1, ++q) { if ((p & amask) == 0) strval[r++] = attrvalues[q]; } if (r != 0) { if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) goto cleanup; } } if (xargs.dn != NULL) st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL); else st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL); if (st != LDAP_SUCCESS) { snprintf(errbuf, sizeof(errbuf), _("User modification failed: %s"), ldap_err2string(st)); st = translate_ldap_error (st, OP_MOD); krb5_set_error_message(context, st, "%s", errbuf); goto cleanup; } if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) entry->fail_auth_count++; } cleanup: if (user) free(user); free_xargs(xargs); if (standalone_principal_dn) free(standalone_principal_dn); if (principal_dn) free (principal_dn); if (polname != NULL) free(polname); if (subtree) free (subtree); if (bersecretkey) { for (l=0; bersecretkey[l]; ++l) { if (bersecretkey[l]->bv_val) free (bersecretkey[l]->bv_val); free (bersecretkey[l]); } free (bersecretkey); } if (keys) free (keys); ldap_mods_free(mods, 1); krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return(st); }
static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state, const char *domain_name) { NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; int i, rc; uint32_t policy_default; const char *policy_attr = NULL; char *dn = NULL; LDAPMod **mods = NULL; char *escape_domain_name; DEBUG(3,("add_new_domain_account_policies: Adding new account policies for domain\n")); escape_domain_name = escape_rdn_val_string_alloc(domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; } if (asprintf(&dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name, lp_ldap_suffix(talloc_tos())) < 0) { SAFE_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } SAFE_FREE(escape_domain_name); for (i=1; decode_account_policy_name(i) != NULL; i++) { char *val = NULL; policy_attr = get_account_policy_attr(i); if (!policy_attr) { DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n")); continue; } if (!account_policy_get_default(i, &policy_default)) { DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n")); SAFE_FREE(dn); return ntstatus; } DEBUG(10,("add_new_domain_account_policies: adding \"%s\" with value: %d\n", policy_attr, policy_default)); if (asprintf(&val, "%d", policy_default) < 0) { SAFE_FREE(dn); return NT_STATUS_NO_MEMORY; } smbldap_set_mod( &mods, LDAP_MOD_REPLACE, policy_attr, val); rc = smbldap_modify(ldap_state, dn, mods); SAFE_FREE(val); if (rc!=LDAP_SUCCESS) { char *ld_error = NULL; ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(1,("add_new_domain_account_policies: failed to add account policies to dn= %s with: %s\n\t%s\n", dn, ldap_err2string(rc), ld_error ? ld_error : "unknown")); SAFE_FREE(ld_error); SAFE_FREE(dn); ldap_mods_free(mods, True); return ntstatus; } } SAFE_FREE(dn); ldap_mods_free(mods, True); return NT_STATUS_OK; }
/* Creates new LDAP Account */ int db_create(char *bid, char *username, char *first, char *last, char *pass) { /* declares local vars */ LDAP *ld; LDAPMessage *res; LDAPMod **mods; char filter[1024]; int i; int bid_len; char *dn; char *uid; /* checks for connection */ if (db_pointer) { ld = db_pointer; } else { return(1); }; /* Gets size of bid */ bid_len = strlen(bid); /* Creates filter */ strcpy(filter, "(blipsid="); strcpy(filter+9, bid); strcpy(filter+9+bid_len, ")"); if (ldap_search_s(ld, "o=acsalaska.net", LDAP_SCOPE_SUBTREE, filter, NULL, 0, &res)) { ldap_perror(ld, "ldap_search_s"); return(1); }; /* Checks for results */ if (ldap_count_entries(ld, res)) { ldap_msgfree(res); return(2); }; ldap_msgfree(res); res = NULL; /* Generates DN */ dn = (char *) db_dn(username); if (!dn) { return(1); }; /* Searches for existing username */ if (ldap_search_s(ld, dn, LDAP_SCOPE_SUBTREE, "(uid=*)", NULL, 0, &res) != LDAP_NO_SUCH_OBJECT) { ldap_perror(ld, "ldap_search_s"); free(dn); return(1); }; /* Checks for results */ if (ldap_count_entries(ld, res)) { ldap_msgfree(res); return(3); }; ldap_msgfree(res); /* gets UID of account */ uid = strtok(username, "@"); /* Creates mod pointers */ mods = (LDAPMod **) malloc (9*sizeof(LDAPMod *)); if (!mods) { return(1); }; memset(mods, 0, (8*sizeof(LDAPMod *))); for(i = 0; i < 8; i++) { mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); if (!mods[i]) { for(i = i; i >= 0; i--) free(mods[i]); free(mods); return(1); }; }; /* Creates mod entries */ mods[0]->mod_op = 0; mods[0]->mod_type = (char *) strdup("objectclass"); mods[0]->mod_values = (char **) malloc(sizeof(char *)*8); mods[0]->mod_values[0] = (char *) strdup("top"); mods[0]->mod_values[1] = (char *) strdup("person"); mods[0]->mod_values[2] = (char *) strdup("organizationalperson"); mods[0]->mod_values[3] = (char *) strdup("inetorgperson"); mods[0]->mod_values[4] = (char *) strdup("inetuser"); mods[0]->mod_values[5] = (char *) strdup("acsaccount"); mods[0]->mod_values[6] = (char *) strdup("acsblipsaccount"); mods[0]->mod_values[7] = NULL; mods[1]->mod_op = 0; mods[1]->mod_type = (char *) strdup("uid"); mods[1]->mod_values = (char **) malloc(sizeof(char *)*2); mods[1]->mod_values[0] = uid; mods[1]->mod_values[1] = NULL; mods[2]->mod_op = 0; mods[2]->mod_type = (char *) strdup("datasource"); mods[2]->mod_values = (char **) malloc(sizeof(char *)*2); mods[2]->mod_values[0] = (char *) strdup("Backend LDAP Internet Provisioning System Daemon"); mods[2]->mod_values[1] = NULL; mods[3]->mod_op = 0; mods[3]->mod_type = (char *) strdup("givenname"); mods[3]->mod_values = (char **) malloc(sizeof(char *)*2); mods[3]->mod_values[0] = first; mods[3]->mod_values[1] = NULL; mods[4]->mod_op = 0; mods[4]->mod_type = (char *) strdup("sn"); mods[4]->mod_values = (char **) malloc(sizeof(char *)*2); mods[4]->mod_values[0] = last; mods[4]->mod_values[1] = NULL; mods[5]->mod_op = 0; mods[5]->mod_type = (char *) strdup("cn"); mods[5]->mod_values = (char **) malloc(sizeof(char *)*2); mods[5]->mod_values[0] = (char *) strdup("First Last"); mods[5]->mod_values[1] = NULL; mods[6]->mod_op = 0; mods[6]->mod_type = (char *) strdup("clearpassword"); mods[6]->mod_values = (char **) malloc(sizeof(char *)*2); mods[6]->mod_values[0] = pass; mods[6]->mod_values[1] = NULL; mods[7]->mod_op = 0; mods[7]->mod_type = (char *) strdup("userpassword"); mods[7]->mod_values = (char **) malloc(sizeof(char *)*2); mods[7]->mod_values[0] = pass; mods[7]->mod_values[1] = NULL; mods[8] = NULL; /* Creates the account in LDAP */ if (ldap_add_s(ld, dn, mods)) { ldap_perror(ld, "ldap_add_s"); free(dn); ldap_mods_free(mods, 9); return(1); }; ldap_perror(ld, "ldap_add_s"); /* ends function */ fprintf(stderr, "got here 98\n"); free(dn); fprintf(stderr, "got here 99\n"); //ldap_mods_free(mods, 9); fprintf(stderr, "got here 100\n"); return(0); }