Token *oath_token_from_entry(Token *token, Slapi_Entry *e) { if (e != NULL && token != NULL) { Slapi_Attr *seed; token->serial = slapi_entry_attr_get_charptr(e, "tokenSerial"); token->pin = slapi_entry_attr_get_charptr(e, "tokenPIN"); token->counter = slapi_entry_attr_get_long(e, "tokenCounter"); slapi_entry_attr_find(e, "tokenSeed", &seed); if (seed != NULL) { struct berval *bval; Slapi_Value *sval; slapi_attr_first_value(seed, &sval); bval = slapi_value_get_berval(sval); token->seed = ber_bvdup(bval); } } return token; }
/* * hasObjectClass - read an entry and check if it has a * particular object class value * Return: * 1 - the entry contains the object class value * 0 - the entry doesn't contain the object class value */ int entryHasObjectClass(Slapi_PBlock *pb, Slapi_Entry *e, const char *objectClass) { Slapi_Attr *attr; Slapi_Value *v; const struct berval *bv; int vhint; if ( slapi_entry_attr_find(e, "objectclass", &attr) ) { return 0; /* no objectclass values! */ } /* * Check each of the object class values in turn. */ for ( vhint = slapi_attr_first_value( attr, &v ); vhint != -1; vhint = slapi_attr_next_value( attr, vhint, &v )) { bv = slapi_value_get_berval(v); if ( NULL != bv && NULL != bv->bv_val && !strcasecmp(bv->bv_val, objectClass) ) { return 1; } } return 0; }
/* create a new updatedn list - if the entry is given, initialize the list from the replicabinddn values given in the entry */ ReplicaUpdateDNList replica_updatedn_list_new(const Slapi_Entry *entry) { /* allocate table */ PLHashTable *hash = PL_NewHashTable(4, PL_HashString, PL_CompareStrings, updatedn_compare_dns, NULL, NULL); if (hash == NULL) { slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_new_updatedn_list - " "Failed to allocate hash table; NSPR error - %d\n", PR_GetError ()); return NULL; } if (entry) { Slapi_Attr *attr = NULL; if (!slapi_entry_attr_find(entry, attr_replicaBindDn, &attr)) { Slapi_ValueSet *vs = NULL; slapi_attr_get_valueset(attr, &vs); replica_updatedn_list_replace(hash, vs); slapi_valueset_free(vs); } } return (ReplicaUpdateDNList)hash; }
/* Pre-operation plug-in function */ int testpreop_add( Slapi_PBlock *pb ) { Slapi_Entry *e; Slapi_Attr *a; Slapi_Value *v; struct berval **bvals; int i, hint; char *tmp; const char *s; /* Get the entry that is about to be added. */ if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ) != 0 ) { slapi_log_err(SLAPI_LOG_PLUGIN, "testpreop_add", "Could not get entry\n" ); return( -1 ); } /* Prepend the name "BOB" to the value of the cn attribute in the entry. */ if ( slapi_entry_attr_find( e, "cn", &a ) == 0 ) { for ( hint = slapi_attr_first_value( a, &v ); hint != -1; hint = slapi_attr_next_value( a, hint, &v )) { s = slapi_value_get_string( v ); tmp = (char *) malloc( 5 + strlen( s )); strcpy( tmp, "BOB " ); strcat( tmp + 4, s ); slapi_value_set_string( v, tmp ); free( tmp ); } } return( 0 ); /* allow the operation to continue */ }
int ipapwd_setdate(Slapi_Entry *source, Slapi_Mods *smods, const char *attr, time_t date, bool remove) { char timestr[GENERALIZED_TIME_LENGTH+1]; struct tm utctime; Slapi_Attr *t; bool exists; exists = (slapi_entry_attr_find(source, attr, &t) == 0); if (remove) { if (exists) { slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE, attr, NULL); } return LDAP_SUCCESS; } if (!gmtime_r(&date, &utctime)) { LOG_FATAL("failed to convert %s date\n", attr); return LDAP_OPERATIONS_ERROR; } strftime(timestr, GENERALIZED_TIME_LENGTH + 1, "%Y%m%d%H%M%SZ", &utctime); slapi_mods_add_string(smods, exists ? LDAP_MOD_REPLACE : LDAP_MOD_ADD, attr, timestr); return LDAP_SUCCESS; }
/* * Function: ldif_back_compare * * Returns: -1, 0 or 1 * * Description: compares entries in the ldif backend */ int ldif_back_compare( Slapi_PBlock *pb ) { LDIF *db; /*The Database*/ ldif_Entry *e, *prev; /*Used for searching the database*/ char *dn, *type; /*The dn and the type*/ struct berval *bval; Slapi_Attr *attr; int rc; LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_compare\n", 0, 0, 0 ); prev = NULL; if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 || slapi_pblock_get( pb, SLAPI_COMPARE_TARGET, &dn ) < 0 || slapi_pblock_get( pb, SLAPI_COMPARE_TYPE, &type ) < 0 || slapi_pblock_get( pb, SLAPI_COMPARE_VALUE, &bval ) < 0){ slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL ); return(-1); } /*Lock the database*/ PR_Lock( db->ldif_lock ); /*Find the entry for comparison*/ if ( (e = (ldif_Entry*) ldif_find_entry( pb, db, dn, &prev )) == NULL ) { slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL ); PR_Unlock( db->ldif_lock ); return( 1 ); } /*Check the access*/ rc= slapi_access_allowed( pb, e->lde_e, type, bval, SLAPI_ACL_COMPARE ); if ( rc!=LDAP_SUCCESS ) { slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL ); PR_Unlock( db->ldif_lock ); return( 1 ); } /*find the attribute*/ if ( slapi_entry_attr_find( e->lde_e, type, &attr ) != 0 ) { slapi_send_ldap_result( pb, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL, 0, NULL ); PR_Unlock( db->ldif_lock ); return( 1 ); } if ( slapi_attr_value_find( attr, bval ) == 0 ) { slapi_send_ldap_result( pb, LDAP_COMPARE_TRUE, NULL, NULL, 0, NULL ); PR_Unlock( db->ldif_lock ); return( 0 ); } slapi_send_ldap_result( pb, LDAP_COMPARE_FALSE, NULL, NULL, 0, NULL ); PR_Unlock( db->ldif_lock ); LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_compare\n", 0, 0, 0 ); return( 0 ); }
static const char *fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val) { Slapi_Attr *attr; Slapi_Value *val = NULL; if (slapi_entry_attr_find(e, attrname, &attr) != 0) return default_val; slapi_attr_first_value(attr, &val); return slapi_value_get_string(val); }
Slapi_ValueSet * replica_updatedn_group_new(const Slapi_Entry *entry) { Slapi_ValueSet *vs = NULL; if (entry) { Slapi_Attr *attr = NULL; if (!slapi_entry_attr_find(entry, attr_replicaBindDnGroup, &attr)) { slapi_attr_get_valueset(attr, &vs); } } return (vs); }
int ipapwd_get_cur_kvno(Slapi_Entry *target) { Slapi_Attr *krbPrincipalKey = NULL; Slapi_ValueSet *svs; Slapi_Value *sv; BerElement *be = NULL; const struct berval *cbval; ber_tag_t tag, tmp; ber_int_t tkvno; int hint; int kvno; int ret; /* retrieve current kvno and and keys */ ret = slapi_entry_attr_find(target, "krbPrincipalKey", &krbPrincipalKey); if (ret != 0) { return 0; } kvno = 0; slapi_attr_get_valueset(krbPrincipalKey, &svs); hint = slapi_valueset_first_value(svs, &sv); while (hint != -1) { cbval = slapi_value_get_berval(sv); if (!cbval) { LOG_TRACE("Error retrieving berval from Slapi_Value\n"); goto next; } be = ber_init(discard_const(cbval)); if (!be) { LOG_TRACE("ber_init() failed!\n"); goto next; } tag = ber_scanf(be, "{xxt[i]", &tmp, &tkvno); if (tag == LBER_ERROR) { LOG_TRACE("Bad OLD key encoding ?!\n"); ber_free(be, 1); goto next; } if (tkvno > kvno) { kvno = tkvno; } ber_free(be, 1); next: hint = slapi_valueset_next_value(svs, hint, &sv); } return kvno; }
static int ldbm_attrcrypt_parse_entry(ldbm_instance *inst, Slapi_Entry *e, char **attribute_name, int *cipher) { Slapi_Attr *attr; const struct berval *attrValue; Slapi_Value *sval; *cipher = 0; *attribute_name = NULL; /* Get the name of the attribute to index which will be the value * of the cn attribute. */ if (slapi_entry_attr_find(e, "cn", &attr) != 0) { slapi_log_err(SLAPI_LOG_ERR, "ldbm_attrcrypt_parse_entry - Malformed attribute encryption entry %s\n", slapi_entry_get_dn(e), 0, 0); return LDAP_OPERATIONS_ERROR; } slapi_attr_first_value(attr, &sval); attrValue = slapi_value_get_berval(sval); *attribute_name = slapi_ch_strdup(attrValue->bv_val); /* Get the list of index types from the entry. */ if (0 == slapi_entry_attr_find(e, "nsEncryptionAlgorithm", &attr)) { slapi_attr_first_value(attr, &sval); if (sval) { attrValue = slapi_value_get_berval(sval); *cipher = ldbm_attrcrypt_parse_cipher(attrValue->bv_val); if (0 == *cipher) slapi_log_err(SLAPI_LOG_WARNING, "ldbm_attrcrypt_parse_entry - " "Attempt to configure unrecognized cipher %s in encrypted attribute config entry %s\n", attrValue->bv_val, slapi_entry_get_dn(e), 0); } } return LDAP_SUCCESS; }
static int del_replconflict_attr (const Slapi_Entry *entry, CSN *opcsn, int opflags) { Slapi_Attr *attr; int op_result = 0; if (slapi_entry_attr_find (entry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0) { Slapi_Mods smods; const char *uniqueid; const Slapi_DN *entrysdn; uniqueid = slapi_entry_get_uniqueid (entry); entrysdn = slapi_entry_get_sdn_const (entry); slapi_mods_init (&smods, 2); slapi_mods_add (&smods, LDAP_MOD_DELETE, ATTR_NSDS5_REPLCONFLICT, 0, NULL); op_result = urp_fixup_modify_entry (uniqueid, entrysdn, opcsn, &smods, opflags); slapi_mods_done (&smods); } return op_result; }
static char* sync_get_attr_value_from_entry( Slapi_Entry *cl_entry, char *attrtype) { Slapi_Value *sval=NULL; const struct berval *value; char *strvalue = NULL; if ( NULL != cl_entry ) { Slapi_Attr *chattr = NULL; sval = NULL; value = NULL; if ( slapi_entry_attr_find( cl_entry, attrtype, &chattr ) == 0 ) { slapi_attr_first_value( chattr,&sval ); if ( NULL != sval ) { value = slapi_value_get_berval ( sval ); if( NULL != value && NULL != value->bv_val && '\0' != value->bv_val[0]) { strvalue = slapi_ch_strdup( value->bv_val); } } } } return (strvalue); }
static void _usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be) { struct berval usn_berval = {0}; Slapi_Attr* attr = NULL; if (NULL == be->be_usn_counter) { /* USN plugin is not enabled */ return; } slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> _usn_add_next_usn\n"); /* add next USN to the entry; "be" contains the usn counter */ usn_berval.bv_val = slapi_ch_smprintf("%" NSPRIu64, slapi_counter_get_value(be->be_usn_counter)); usn_berval.bv_len = strlen(usn_berval.bv_val); slapi_entry_attr_find(e, SLAPI_ATTR_ENTRYUSN, &attr); if (NULL == attr) { /* ENTRYUSN does not exist; add it */ Slapi_Value *usn_value = slapi_value_new_berval(&usn_berval); slapi_entry_add_value(e, SLAPI_ATTR_ENTRYUSN, usn_value); slapi_value_free(&usn_value); } else { /* ENTRYUSN exists; replace it */ struct berval *new_bvals[2]; new_bvals[0] = &usn_berval; new_bvals[1] = NULL; slapi_entry_attr_replace(e, SLAPI_ATTR_ENTRYUSN, new_bvals); } slapi_ch_free_string(&usn_berval.bv_val); slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- _usn_add_next_usn\n"); return; }
static struct ipapwd_krbcfg *ipapwd_getConfig(void) { krb5_error_code krberr; struct ipapwd_krbcfg *config = NULL; krb5_keyblock *kmkey = NULL; Slapi_Entry *realm_entry = NULL; Slapi_Entry *config_entry = NULL; Slapi_Attr *a; Slapi_Value *v; BerElement *be = NULL; ber_tag_t tag, tvno; ber_int_t ttype; const struct berval *bval; struct berval *mkey = NULL; char **encsalts; char **tmparray; char *tmpstr; int i, ret; config = calloc(1, sizeof(struct ipapwd_krbcfg)); if (!config) { LOG_OOM(); goto free_and_error; } kmkey = calloc(1, sizeof(krb5_keyblock)); if (!kmkey) { LOG_OOM(); goto free_and_error; } config->kmkey = kmkey; krberr = krb5_init_context(&config->krbctx); if (krberr) { LOG_FATAL("krb5_init_context failed\n"); goto free_and_error; } ret = krb5_get_default_realm(config->krbctx, &config->realm); if (ret) { LOG_FATAL("Failed to get default realm?!\n"); goto free_and_error; } /* get the Realm Container entry */ ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL); if (ret != LDAP_SUCCESS) { LOG_FATAL("No realm Entry?\n"); goto free_and_error; } /*** get the Kerberos Master Key ***/ ret = slapi_entry_attr_find(realm_entry, "krbMKey", &a); if (ret == -1) { LOG_FATAL("No master key??\n"); goto free_and_error; } /* there should be only one value here */ ret = slapi_attr_first_value(a, &v); if (ret == -1) { LOG_FATAL("No master key??\n"); goto free_and_error; } bval = slapi_value_get_berval(v); if (!bval) { LOG_FATAL("Error retrieving master key berval\n"); goto free_and_error; } be = ber_init(discard_const(bval)); if (!be) { LOG_FATAL("ber_init() failed!\n"); goto free_and_error; } tag = ber_scanf(be, "{i{iO}}", &tvno, &ttype, &mkey); if (tag == LBER_ERROR) { LOG_FATAL("Bad Master key encoding ?!\n"); goto free_and_error; } config->mkvno = tvno; kmkey->magic = KV5M_KEYBLOCK; kmkey->enctype = ttype; kmkey->length = mkey->bv_len; kmkey->contents = malloc(mkey->bv_len); if (!kmkey->contents) { LOG_OOM(); goto free_and_error; } memcpy(kmkey->contents, mkey->bv_val, mkey->bv_len); ber_bvfree(mkey); ber_free(be, 1); mkey = NULL; be = NULL; /*** get the Supported Enc/Salt types ***/ encsalts = slapi_entry_attr_get_charray(realm_entry, "krbSupportedEncSaltTypes"); if (encsalts) { for (i = 0; encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, (const char * const *)encsalts, i, &config->supp_encsalts, &config->num_supp_encsalts); slapi_ch_array_free(encsalts); } else { LOG("No configured salt types use defaults\n"); for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, ipapwd_def_encsalts, i, &config->supp_encsalts, &config->num_supp_encsalts); } if (ret) { LOG_FATAL("Can't get Supported EncSalt Types\n"); goto free_and_error; } /*** get the Preferred Enc/Salt types ***/ encsalts = slapi_entry_attr_get_charray(realm_entry, "krbDefaultEncSaltTypes"); if (encsalts) { for (i = 0; encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, (const char * const *)encsalts, i, &config->pref_encsalts, &config->num_pref_encsalts); slapi_ch_array_free(encsalts); } else { LOG("No configured salt types use defaults\n"); for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ; ret = parse_bval_key_salt_tuples(config->krbctx, ipapwd_def_encsalts, i, &config->pref_encsalts, &config->num_pref_encsalts); } if (ret) { LOG_FATAL("Can't get Preferred EncSalt Types\n"); goto free_and_error; } slapi_entry_free(realm_entry); /* get the Realm Container entry */ ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL); if (ret != LDAP_SUCCESS) { LOG_FATAL("No config Entry? Impossible!\n"); goto free_and_error; } config->passsync_mgrs = slapi_entry_attr_get_charray(config_entry, "passSyncManagersDNs"); /* now add Directory Manager, it is always added by default */ tmpstr = slapi_ch_strdup("cn=Directory Manager"); slapi_ch_array_add(&config->passsync_mgrs, tmpstr); if (config->passsync_mgrs == NULL) { LOG_OOM(); goto free_and_error; } for (i = 0; config->passsync_mgrs[i]; i++) /* count */ ; config->num_passsync_mgrs = i; slapi_entry_free(config_entry); /* get the ipa etc/ipaConfig entry */ config->allow_nt_hash = false; ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL); if (ret != LDAP_SUCCESS) { LOG_FATAL("No config Entry?\n"); goto free_and_error; } else { tmparray = slapi_entry_attr_get_charray(config_entry, "ipaConfigString"); for (i = 0; tmparray && tmparray[i]; i++) { if (strcasecmp(tmparray[i], "AllowNThash") == 0) { config->allow_nt_hash = true; continue; } } if (tmparray) slapi_ch_array_free(tmparray); } slapi_entry_free(config_entry); return config; free_and_error: if (mkey) ber_bvfree(mkey); if (be) ber_free(be, 1); if (kmkey) { free(kmkey->contents); free(kmkey); } if (config) { if (config->krbctx) { if (config->realm) krb5_free_default_realm(config->krbctx, config->realm); krb5_free_context(config->krbctx); } free(config->pref_encsalts); free(config->supp_encsalts); slapi_ch_array_free(config->passsync_mgrs); free(config); } slapi_entry_free(config_entry); slapi_entry_free(realm_entry); return NULL; }
LDAPWAStatus WindowsAuthentication( struct backentry *e, struct berval *cred ) { Slapi_Attr *a; Slapi_Value *sval = NULL; int iStatus; char szNTDomain[MAX_PATH], szNTUsername[MAX_PATH]; HANDLE hToken = NULL; BOOL bLogonStatus = FALSE; int i= -1; /* Get the NT Domain and username - if the entry has such an attribute */ if( !e || !e->ep_entry || slapi_entry_attr_find( e->ep_entry, "ntuserdomainid", &a ) != 0) { return( LDAPWA_NoDomainAttr ); } i= slapi_attr_first_value( a, &sval ); if(sval==NULL) { return( LDAPWA_NoDomainAttr ); } while(i != -1) { const struct berval *val = slapi_value_get_berval(sval); char * colon = NULL; if (!val->bv_val || (strlen(val->bv_val) > (MAX_PATH<<1))) { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : " "ntuserdomainid attr value too long\n", val->bv_val, 0, 0); i= slapi_attr_next_value(a, i, &sval); continue; } colon = strchr( val->bv_val, ':' ); if (!colon || ((colon - val->bv_val)/sizeof(char) > MAX_PATH)) { if (!colon) { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : " "a colon is missing in ntuserdomainid attr value\n", val->bv_val, 0, 0); } else { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain : " "domain in ntuserdomainid attr value too long\n", val->bv_val, 0, 0); } i= slapi_attr_next_value(a, i, &sval); continue; } if(( iStatus = GetDomainUsername( val->bv_val, szNTDomain, szNTUsername )) != 0) { i= slapi_attr_next_value(a, i, &sval); continue; } #if !defined( LOGON32_LOGON_NETWORK ) /* This is specified in the WIn32 LogonUser() documentation, but not defined in the Visual C++ 4.2 include file winbase.h. A search of the lastest version of this file at www.microsoft.com finds that LOGON32_LOGON_NETWORK == 3. */ #define LOGON32_LOGON_NETWORK 3 #endif /* Now do the Logon attempt */ bLogonStatus = LogonUser( szNTUsername, // string that specifies the user name szNTDomain, // string that specifies the domain or server cred->bv_val, // string that specifies the password LOGON32_LOGON_NETWORK, // the type of logon operation, LOGON32_PROVIDER_DEFAULT, // specifies the logon provider &hToken ); // pointer to variable to receive token handle if( bLogonStatus && hToken ) CloseHandle( hToken ); if( bLogonStatus ) { // Successful validation LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validated \"%s\" on NT Domain \"%s\"\n", szNTUsername, szNTDomain, 0 ); return( LDAPWA_Success ); } else { LDAPDebug( LDAP_DEBUG_TRACE, "WindowsAuthentication => validation FAILED for \"%s\" on NT Domain \"%s\", reason %d\n", szNTUsername, szNTDomain, GetLastError() ); return( LDAPWA_InvalidCredentials ); } i= slapi_attr_next_value(a, i, &sval); } return( LDAPWA_Failure ); }
int ldbm_back_bind( Slapi_PBlock *pb ) { backend *be; ldbm_instance *inst; int method; struct berval *cred; struct ldbminfo *li; struct backentry *e; Slapi_Attr *attr; Slapi_Value **bvals; entry_address *addr; back_txn txn = {NULL}; /* get parameters */ 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_BIND_METHOD, &method ); slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred ); slapi_pblock_get( pb, SLAPI_TXN, &txn.back_txn_txn ); if ( !txn.back_txn_txn ) { dblayer_txn_init( li, &txn ); slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn ); } inst = (ldbm_instance *) be->be_instance_info; /* always allow noauth simple binds (front end will send the result) */ if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) { return( SLAPI_BIND_ANONYMOUS ); } /* * find the target entry. find_entry() takes care of referrals * and sending errors if the entry does not exist. */ if (( e = find_entry( pb, be, addr, &txn )) == NULL ) { return( SLAPI_BIND_FAIL ); } switch ( method ) { case LDAP_AUTH_SIMPLE: { Slapi_Value cv; if ( slapi_entry_attr_find( e->ep_entry, "userpassword", &attr ) != 0 ) { #if defined( XP_WIN32 ) if( WindowsAuthentication( e, cred ) == LDAPWA_Success ) { break; } #endif slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL ); CACHE_RETURN( &inst->inst_cache, &e ); return( SLAPI_BIND_FAIL ); } bvals= attr_get_present_values(attr); slapi_value_init_berval(&cv,cred); if ( slapi_pw_find_sv( bvals, &cv ) != 0 ) { #if defined( XP_WIN32 ) /* One last try - attempt Windows authentication, if the user has a Windows account. */ if( WindowsAuthentication( e, cred ) == LDAPWA_Success ) { break; } #endif slapi_send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL ); CACHE_RETURN( &inst->inst_cache, &e ); value_done(&cv); return( SLAPI_BIND_FAIL ); } value_done(&cv); } break; default: slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL, "auth method not supported", 0, NULL ); CACHE_RETURN( &inst->inst_cache, &e ); return( SLAPI_BIND_FAIL ); } CACHE_RETURN( &inst->inst_cache, &e ); /* success: front end will send result */ return( SLAPI_BIND_SUCCESS ); }
/*************************************************************************** * * __aclinit_handler * * For each entry, finds if there is any ACL in that entry. If there is * then the ACL is processed and stored in the ACL LIST. * * * Input: * * * Returns: * None. * * Error Handling: * If any error found during the ACL generation, the ACL is * logged. Also, set in the callback_data so that caller can act upon it. * **************************************************************************/ static int __aclinit_handler ( Slapi_Entry *e, void *callback_data) { Slapi_Attr *attr; aclinit_handler_callback_data_t *call_back_data = (aclinit_handler_callback_data_t*)callback_data; Slapi_DN *e_sdn; int rv; Slapi_Value *sval=NULL; call_back_data->retCode = 0; /* assume success--if there's an error we overwrite it */ if (e != NULL) { e_sdn = slapi_entry_get_sdn ( e ); /* * Take the write lock around all the mods--so that * other operations will see the acicache either before the whole mod * or after but not, as it was before, during the mod. * This is in line with the LDAP concept of the operation * on the whole entry being the atomic unit. * */ if ( call_back_data->op == ACL_ADD_ACIS ) { slapi_log_err(SLAPI_LOG_ACL, plugin_name, "Adding acis for entry '%s'\n", slapi_sdn_get_dn(e_sdn)); slapi_entry_attr_find ( e, aci_attr_type, &attr ); if ( attr ) { const struct berval *attrValue; int i; if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_LOCK(); } i= slapi_attr_first_value ( attr, &sval ); while(i != -1) { attrValue = slapi_value_get_berval(sval); if ( 0 != (rv=acllist_insert_aci_needsLock (e_sdn, attrValue))) { aclutil_print_err(rv, e_sdn, attrValue, NULL); /* We got an error; Log it and then march along */ slapi_log_err(SLAPI_LOG_ERR, plugin_name, "__aclinit_handler - This (%s) ACL will not be considered for evaluation" " because of syntax errors.\n", attrValue->bv_val ? attrValue->bv_val: "NULL"); call_back_data->retCode = rv; } i= slapi_attr_next_value( attr, i, &sval ); }/* while */ if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_UNLOCK(); } } } else if (call_back_data->op == ACL_REMOVE_ACIS) { /* Here we are deleting the acis. */ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "__aclinit_handler - Removing acis\n"); if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_LOCK(); } if ( 0 != (rv=acllist_remove_aci_needsLock(e_sdn, NULL))) { aclutil_print_err(rv, e_sdn, NULL, NULL); /* We got an error; Log it and then march along */ slapi_log_err(SLAPI_LOG_ERR, plugin_name, "__aclinit_handler - ACLs not deleted from %s\n", slapi_sdn_get_dn(e_sdn)); call_back_data->retCode = rv; } if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) { acllist_acicache_WRITE_UNLOCK(); } } } /* * If we get here it's success. * The call_back_data->error is the error code that counts as it's the * one that the original caller will see--this routine is called off a callbacl. */ return ACL_FALSE; /* "local" error code--it's 0 */ }
/* * preop_add - pre-operation plug-in for add */ static int preop_add(Slapi_PBlock *pb) { int result; char *errtext = NULL; char *attrName = NULL; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD begin\n"); #endif result = LDAP_SUCCESS; /* * Do constraint check on the added entry. Set result. */ BEGIN int err; char *markerObjectClass = NULL; char *requiredObjectClass = NULL; Slapi_DN *sdn = NULL; int isupdatedn; Slapi_Entry *e; Slapi_Attr *attr; int argc; char **argv = NULL; /* * If this is a replication update, just be a noop. */ err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn); if (err) { result = uid_op_error(50); break; } if (isupdatedn) { break; } /* * Get the arguments */ result = getArguments(pb, &attrName, &markerObjectClass, &requiredObjectClass); if (UNTAGGED_PARAMETER == result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD parameter untagged: %s\n", attrName); result = LDAP_SUCCESS; /* Statically defined subtrees to monitor */ err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (err) { result = uid_op_error(53); break; } err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); if (err) { result = uid_op_error(54); break; } argc--; argv++; /* First argument was attribute name */ } else if (0 != result) { break; } /* * Get the target DN for this add operation */ err = slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); if (err) { result = uid_op_error(51); break; } #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD target=%s\n", slapi_sdn_get_dn(sdn)); #endif /* * Get the entry data for this add. Check whether it * contains a value for the unique attribute */ err = slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e); if (err) { result = uid_op_error(52); break; } err = slapi_entry_attr_find(e, attrName, &attr); if (err) break; /* no unique attribute */ /* * Check if it contains the required object class */ if (NULL != requiredObjectClass) { if (!entryHasObjectClass(pb, e, requiredObjectClass)) { /* No, so we don't have to do anything */ break; } } /* * Passed all the requirements - this is an operation we * need to enforce uniqueness on. Now find all parent entries * with the marker object class, and do a search for each one. */ if (NULL != markerObjectClass) { /* Subtree defined by location of marker object class */ result = findSubtreeAndSearch(sdn, attrName, attr, NULL, requiredObjectClass, sdn, markerObjectClass); } else { /* Subtrees listed on invocation line */ result = searchAllSubtrees(argc, argv, attrName, attr, NULL, requiredObjectClass, sdn); } END if (result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD result %d\n", result); if (result == LDAP_CONSTRAINT_VIOLATION) { errtext = slapi_ch_smprintf(moreInfo, attrName); } else { errtext = slapi_ch_strdup("Error checking for attribute uniqueness."); } /* Send failure to the client */ slapi_send_ldap_result(pb, result, 0, errtext, 0, 0); slapi_ch_free_string(&errtext); } return (result==LDAP_SUCCESS)?0:-1; }
static int ipa_winsync_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { PRBool flatten = PR_TRUE; char *realm_filter = NULL; char *realm_attr = NULL; char *new_entry_filter = NULL; char *new_user_oc_attr = NULL; /* don't care about groups for now */ char *homedir_prefix_attr = NULL; char *login_shell_attr = NULL; char *default_group_attr = NULL; char *default_group_filter = NULL; char *acct_disable = NULL; int acct_disable_int; char *inactivated_filter = NULL; char *activated_filter = NULL; char **attrsvals = NULL; int ii; Slapi_Attr *testattr = NULL; PRBool forceSync = PR_FALSE; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* get flatten value */ if (!slapi_entry_attr_find(e, IPA_WINSYNC_USER_FLATTEN, &testattr) && (NULL != testattr)) { flatten = slapi_entry_attr_get_bool(e, IPA_WINSYNC_USER_FLATTEN); } /* get realm filter */ if (!(realm_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_REALM_FILTER_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_FILTER_ATTR); goto done3; } /* get realm attr */ if (!(realm_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_REALM_ATTR_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_ATTR_ATTR); goto done3; } /* get new_entry_filter */ if (!(new_entry_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR); goto done3; } /* get new_user_oc_attr */ if (!(new_user_oc_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_NEW_USER_OC_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_USER_OC_ATTR); goto done3; } /* get homedir_prefix_attr */ if (!(homedir_prefix_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_HOMEDIR_PREFIX_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_HOMEDIR_PREFIX_ATTR); goto done3; } /* get login_shell_attr */ login_shell_attr = slapi_entry_attr_get_charptr(e, IPA_WINSYNC_LOGIN_SHELL_ATTR); if (!login_shell_attr) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Warning: no value given for %s", IPA_WINSYNC_LOGIN_SHELL_ATTR); } /* get default_group_attr */ if (!(default_group_attr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_DEFAULTGROUP_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_ATTR); goto done3; } /* get default_group_filter */ if (!(default_group_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR); goto done3; } /* get the list of attributes & values */ /* get new_user_oc_attr */ if (!(attrsvals = slapi_entry_attr_get_charray( e, IPA_WINSYNC_NEW_USER_ATTRS_VALS))) { LOG("Info: no default attributes and values given in [%s]\n", IPA_WINSYNC_NEW_USER_ATTRS_VALS); } /* get acct disable sync value */ if (!(acct_disable = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_ACCT_DISABLE))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_ACCT_DISABLE); goto done3; } acct_disable_int = parse_acct_disable(acct_disable); if (ACCT_DISABLE_INVALID == acct_disable_int) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid value [%s] given for [%s] - valid " "values are " IPA_WINSYNC_ACCT_DISABLE_NONE ", " IPA_WINSYNC_ACCT_DISABLE_TO_AD ", " IPA_WINSYNC_ACCT_DISABLE_TO_DS ", or " IPA_WINSYNC_ACCT_DISABLE_BOTH, acct_disable, IPA_WINSYNC_ACCT_DISABLE); goto done3; } if (acct_disable_int != ACCT_DISABLE_NONE) { /* get inactivated group filter */ if (!(inactivated_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_INACTIVATED_FILTER))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_INACTIVATED_FILTER); } /* get activated group filter */ if (!(activated_filter = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_ACTIVATED_FILTER))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_ACTIVATED_FILTER); } } /* get forceSync value */ if (!slapi_entry_attr_find(e, IPA_WINSYNC_FORCE_SYNC, &testattr) && (NULL != testattr)) { forceSync = slapi_entry_attr_get_bool(e, IPA_WINSYNC_FORCE_SYNC); } /* if we got here, we have valid values for everything set the config entry */ slapi_lock_mutex(theConfig.lock); slapi_entry_free(theConfig.config_e); theConfig.config_e = slapi_entry_alloc(); slapi_entry_init(theConfig.config_e, slapi_ch_strdup(""), NULL); /* format of *attrsvals is "attrname value" */ /* attrname <space> value */ /* value may contain spaces - attrname is everything up to the first space - value is everything after the first space */ for (ii = 0; attrsvals && attrsvals[ii]; ++ii) { int rc; Slapi_Value *sva[2]; Slapi_Value *sv = NULL; char *val = strchr(attrsvals[ii], ' '); if (!val || !*(val+1)) { /* incorrect format or no value */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value or incorrect value given for [%s] " "value [%s] index [%d] - correct format is attrname SPACE value", IPA_WINSYNC_NEW_USER_ATTRS_VALS, attrsvals[ii], ii); goto done3; } *val++ = '\0'; /* separate attr from val */ sv = slapi_value_new_string(val); sva[0] = sv; sva[1] = NULL; if ((rc = slapi_entry_add_values_sv(theConfig.config_e, attrsvals[ii], sva)) && (rc != LDAP_SUCCESS)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: could not add value [%s] for attribute name " "[%s] - ldap error [%d: %s]", val, attrsvals[ii], rc, ldap_err2string(rc)); slapi_entry_free(theConfig.config_e); theConfig.config_e = NULL; slapi_value_free(&sv); goto done3; } slapi_value_free(&sv); } /* all of the attrs and vals have been set - set the other values */ slapi_ch_free_string(&theConfig.realm_filter); theConfig.realm_filter = realm_filter; realm_filter = NULL; slapi_ch_free_string(&theConfig.realm_attr); theConfig.realm_attr = realm_attr; realm_attr = NULL; slapi_ch_free_string(&theConfig.new_entry_filter); theConfig.new_entry_filter = new_entry_filter; new_entry_filter = NULL; slapi_ch_free_string(&theConfig.new_user_oc_attr); theConfig.new_user_oc_attr = new_user_oc_attr; new_user_oc_attr = NULL; slapi_ch_free_string(&theConfig.homedir_prefix_attr); theConfig.homedir_prefix_attr = homedir_prefix_attr; homedir_prefix_attr = NULL; if (login_shell_attr) { slapi_ch_free_string(&theConfig.login_shell_attr); theConfig.login_shell_attr = login_shell_attr; login_shell_attr = NULL; } slapi_ch_free_string(&theConfig.default_group_attr); theConfig.default_group_attr = default_group_attr; default_group_attr = NULL; slapi_ch_free_string(&theConfig.default_group_filter); theConfig.default_group_filter = default_group_filter; default_group_filter = NULL; theConfig.flatten = flatten; theConfig.acct_disable = parse_acct_disable(acct_disable); slapi_ch_free_string(&theConfig.inactivated_filter); theConfig.inactivated_filter = inactivated_filter; inactivated_filter = NULL; slapi_ch_free_string(&theConfig.activated_filter); theConfig.activated_filter = activated_filter; activated_filter = NULL; theConfig.forceSync = forceSync; /* success */ *returncode = LDAP_SUCCESS; done3: slapi_unlock_mutex(theConfig.lock); slapi_ch_free_string(&realm_filter); slapi_ch_free_string(&realm_attr); slapi_ch_free_string(&new_entry_filter); slapi_ch_free_string(&new_user_oc_attr); slapi_ch_free_string(&homedir_prefix_attr); slapi_ch_free_string(&login_shell_attr); slapi_ch_free_string(&default_group_attr); slapi_ch_free_string(&default_group_filter); slapi_ch_array_free(attrsvals); attrsvals = NULL; slapi_ch_free_string(&acct_disable); slapi_ch_free_string(&inactivated_filter); slapi_ch_free_string(&activated_filter); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
/* Apply the pending changes in the e entry to our config struct. validate must have already been called */ static int pam_passthru_apply_config (Slapi_Entry* e) { int rc = PAM_PASSTHRU_SUCCESS; char **excludes = NULL; char **includes = NULL; char *new_service = NULL; char *pam_ident_attr = NULL; char *map_method = NULL; char *dn = NULL; PRBool fallback; PRBool secure; Pam_PassthruConfig *entry = NULL; PRCList *list; Slapi_Attr *a = NULL; char *filter_str = NULL; int inserted = 0; pam_ident_attr = slapi_entry_attr_get_charptr(e, PAMPT_PAM_IDENT_ATTR); map_method = slapi_entry_attr_get_charptr(e, PAMPT_MAP_METHOD_ATTR); new_service = slapi_entry_attr_get_charptr(e, PAMPT_SERVICE_ATTR); excludes = slapi_entry_attr_get_charray(e, PAMPT_EXCLUDES_ATTR); includes = slapi_entry_attr_get_charray(e, PAMPT_INCLUDES_ATTR); fallback = slapi_entry_attr_get_bool(e, PAMPT_FALLBACK_ATTR); filter_str = slapi_entry_attr_get_charptr(e, PAMPT_FILTER_ATTR); /* Require SSL/TLS if the secure attr is not specified. We * need to check if the attribute is present to make this * determiniation. */ if (slapi_entry_attr_find(e, PAMPT_SECURE_ATTR, &a) == 0) { secure = slapi_entry_attr_get_bool(e, PAMPT_SECURE_ATTR); } else { secure = PR_TRUE; } /* Allocate a config struct. */ entry = (Pam_PassthruConfig *) slapi_ch_calloc(1, sizeof(Pam_PassthruConfig)); if (NULL == entry) { rc = PAM_PASSTHRU_FAILURE; goto bail; } /* use the RDN method to derive the PAM identity by default*/ entry->pamptconfig_map_method1 = PAMPT_MAP_METHOD_RDN; entry->pamptconfig_map_method2 = PAMPT_MAP_METHOD_NONE; entry->pamptconfig_map_method3 = PAMPT_MAP_METHOD_NONE; /* Fill in the struct. */ dn = slapi_entry_get_ndn(e); if (dn) { entry->dn = slapi_ch_strdup(dn); } entry->pamptconfig_fallback = fallback; entry->pamptconfig_secure = secure; if (!entry->pamptconfig_service || (new_service && PL_strcmp(entry->pamptconfig_service, new_service))) { slapi_ch_free_string(&entry->pamptconfig_service); entry->pamptconfig_service = new_service; new_service = NULL; /* config now owns memory */ } /* get the list of excluded suffixes */ pam_ptconfig_free_suffixes(entry->pamptconfig_excludes); entry->pamptconfig_excludes = pam_ptconfig_add_suffixes(excludes); /* get the list of included suffixes */ pam_ptconfig_free_suffixes(entry->pamptconfig_includes); entry->pamptconfig_includes = pam_ptconfig_add_suffixes(includes); if (!entry->pamptconfig_pam_ident_attr || (pam_ident_attr && PL_strcmp(entry->pamptconfig_pam_ident_attr, pam_ident_attr))) { slapi_ch_free_string(&entry->pamptconfig_pam_ident_attr); entry->pamptconfig_pam_ident_attr = pam_ident_attr; pam_ident_attr = NULL; /* config now owns memory */ } if (map_method) { parse_map_method(map_method, &entry->pamptconfig_map_method1, &entry->pamptconfig_map_method2, &entry->pamptconfig_map_method3, NULL); } if (filter_str) { entry->filter_str = filter_str; filter_str = NULL; /* config now owns memory */ entry->slapi_filter = slapi_str2filter(entry->filter_str); } /* Add config to list. We just store at the tail. */ if (!PR_CLIST_IS_EMPTY(pam_passthru_global_config)) { list = PR_LIST_HEAD(pam_passthru_global_config); while (list != pam_passthru_global_config) { list = PR_NEXT_LINK(list); if (pam_passthru_global_config == list) { /* add to tail */ PR_INSERT_BEFORE(&(entry->list), list); slapi_log_err(SLAPI_LOG_CONFIG, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "pam_passthru_apply_config - store [%s] at tail\n", entry->dn); inserted = 1; break; } } } else { /* first entry */ PR_INSERT_LINK(&(entry->list), pam_passthru_global_config); slapi_log_err(SLAPI_LOG_CONFIG, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "pam_passthru_apply_config - store [%s] at head \n", entry->dn); inserted = 1; } bail: if(!inserted){ pam_passthru_free_config_entry(&entry); } slapi_ch_free_string(&new_service); slapi_ch_free_string(&map_method); slapi_ch_free_string(&pam_ident_attr); slapi_ch_free_string(&filter_str); slapi_ch_array_free(excludes); slapi_ch_array_free(includes); return rc; }
/* Validate the pending changes in the e entry. */ static int ipa_winsync_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { char **attrsvals = NULL; int ii; Slapi_Attr *testattr = NULL; char *strattr = NULL; int acct_disable; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* get realm filter */ if (slapi_entry_attr_find(e, IPA_WINSYNC_REALM_FILTER_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_FILTER_ATTR); goto done2; } /* get realm attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_REALM_ATTR_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_REALM_ATTR_ATTR); goto done2; } /* get new_entry_filter */ if (slapi_entry_attr_find(e, IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_ENTRY_FILTER_ATTR); goto done2; } /* get new_user_oc_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_NEW_USER_OC_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_NEW_USER_OC_ATTR); goto done2; } /* get homedir_prefix_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_HOMEDIR_PREFIX_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_HOMEDIR_PREFIX_ATTR); goto done2; } /* get login_shell_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_LOGIN_SHELL_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Warning: no value given for %s", IPA_WINSYNC_LOGIN_SHELL_ATTR); } /* get default_group_attr */ if (slapi_entry_attr_find(e, IPA_WINSYNC_DEFAULTGROUP_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_ATTR); goto done2; } /* get default_group_filter */ if (slapi_entry_attr_find(e, IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_DEFAULTGROUP_FILTER_ATTR); goto done2; } /* get the list of attributes & values */ /* get new_user_oc_attr */ if (!(attrsvals = slapi_entry_attr_get_charray( e, IPA_WINSYNC_NEW_USER_ATTRS_VALS))) { LOG("Info: no default attributes and values given in [%s]\n", IPA_WINSYNC_NEW_USER_ATTRS_VALS); } /* format of *attrsvals is "attrname value" */ /* attrname <space> value */ /* value may contain spaces - attrname is everything up to the first space - value is everything after the first space */ for (ii = 0; attrsvals && attrsvals[ii]; ++ii) { Slapi_Attr *attr = NULL; char *oidp = NULL; char *val = strchr(attrsvals[ii], ' '); if (!val || !*(val+1)) { /* incorrect format or no value */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value or incorrect value given for [%s] " "value [%s] index [%d] - correct format is attrname SPACE value", IPA_WINSYNC_NEW_USER_ATTRS_VALS, attrsvals[ii], ii); goto done2; } *val = '\0'; /* separate attr from val */ /* check to make sure attribute is in the schema */ attr = slapi_attr_new(); slapi_attr_set_type(attr, attrsvals[ii]); slapi_attr_get_oid_copy(attr, &oidp); slapi_attr_free(&attr); if (oidp == NULL) { /* no such attribute */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid attribute name [%s] given for [%s] " "at index [%d] - attribute is not in server schema", attrsvals[ii], IPA_WINSYNC_NEW_USER_ATTRS_VALS, ii); goto done2; } /* attribute is valid - continue */ slapi_ch_free_string(&oidp); } /* get account disable sync direction */ if (!(strattr = slapi_entry_attr_get_charptr( e, IPA_WINSYNC_ACCT_DISABLE))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no value given for %s", IPA_WINSYNC_ACCT_DISABLE); goto done2; } acct_disable = parse_acct_disable(strattr); if (ACCT_DISABLE_INVALID == acct_disable) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid value [%s] given for [%s] - valid " "values are " IPA_WINSYNC_ACCT_DISABLE_NONE ", " IPA_WINSYNC_ACCT_DISABLE_TO_AD ", " IPA_WINSYNC_ACCT_DISABLE_TO_DS ", or " IPA_WINSYNC_ACCT_DISABLE_BOTH, strattr, IPA_WINSYNC_ACCT_DISABLE); goto done2; } /* if using acct disable sync, must have the attributes IPA_WINSYNC_INACTIVATED_FILTER and IPA_WINSYNC_ACTIVATED_FILTER */ if (acct_disable != ACCT_DISABLE_NONE) { if (slapi_entry_attr_find(e, IPA_WINSYNC_INACTIVATED_FILTER, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_INACTIVATED_FILTER); } if (slapi_entry_attr_find(e, IPA_WINSYNC_ACTIVATED_FILTER, &testattr) || (NULL == testattr)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No value given for %s - required for account " "disable sync, ignoring", IPA_WINSYNC_ACTIVATED_FILTER); } } /* success */ *returncode = LDAP_SUCCESS; done2: slapi_ch_free_string(&strattr); slapi_ch_array_free(attrsvals); attrsvals = NULL; if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
/* return the value(s) of the given attribute in the entry that matches the given criteria. The criteria must match one and only one entry. Returns: -1 - problem doing internal search LDAP_UNWILLING_TO_PERFORM - more than one matching entry LDAP_NO_SUCH_OBJECT - no entry found that matched 0 and attrval == NULL - entry found but no attribute other ldap error - error doing search for given basedn */ static int internal_find_entry_get_attr_val(const Slapi_DN *basedn, int scope, const char *filter, const char *attrname, Slapi_ValueSet **svs, char **attrval) { Slapi_Entry **entries = NULL; Slapi_PBlock *pb = NULL; const char *search_basedn = slapi_sdn_get_dn(basedn); int search_scope = scope; int ret = LDAP_SUCCESS; const char *attrs[2] = {attrname, NULL}; if (svs) { *svs = NULL; } if (attrval) { *attrval = NULL; } pb = slapi_pblock_new(); slapi_search_internal_set_pb(pb, search_basedn, search_scope, filter, (char **)attrs, 0, NULL, NULL, ipa_winsync_get_plugin_identity(), 0); slapi_search_internal_pb(pb); /* This search may return no entries, but should never return an error */ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret); if (ret != LDAP_SUCCESS) { LOG_FATAL("Error [%d:%s] searching for base [%s] filter [%s]" " attr [%s]\n", ret, ldap_err2string(ret), search_basedn, filter, attrs[0]); goto out1; } slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); if (entries && entries[0] && entries[1]) { /* error - should never be more than one matching entry */ LOG_FATAL("Error: more than one entry matches search for " "base [%s] filter [%s] attr [%s]\n", search_basedn, filter, attrs[0]); ret = LDAP_UNWILLING_TO_PERFORM; goto out1; } if (entries && entries[0]) { /* found one */ if (svs) { Slapi_Attr *attr = NULL; if (!slapi_entry_attr_find(entries[0], attrname, &attr) && (NULL != attr)) { /* slapi_attr_get_valueset allocates svs - must be freed later */ slapi_attr_get_valueset(attr, svs); } } if (attrval) { if (!strcmp(attrname, "dn")) { /* special - to just get the DN */ *attrval = slapi_ch_strdup(slapi_entry_get_dn_const(entries[0])); } else { *attrval = slapi_entry_attr_get_charptr(entries[0], attrname); } } } else { ret = LDAP_NO_SUCH_OBJECT; LOG("Did not find an entry for search " "base [%s] filter [%s] attr [%s]\n", search_basedn, filter, attrs[0]); } out1: if (pb) { slapi_free_search_results_internal(pb); slapi_pblock_destroy(pb); pb = NULL; } return ret; }
void _ger_get_attrs_rights ( Slapi_PBlock *gerpb, Slapi_Entry *e, const char *subjectndn, char **attrs, char **gerstr, size_t *gerstrsize, size_t *gerstrcap, char **errbuf ) { int isfirstattr = 1; /* gerstr was initially allocated with enough space for one more line */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ", NULL); /* * If it's stated attribute list is given, * the first attr in the list should not be empty. * Otherwise, it's considered the list is not given. */ if (attrs && *attrs && (strlen(*attrs) > 0)) { int i = 0; char **allattrs = NULL; char **opattrs = NULL; char **noexpattrs = NULL; /* attrs not to expose */ char **myattrs = NULL; char **thisattr = NULL; int hasstar = charray_inlist(attrs, "*"); int hasplus = charray_inlist(attrs, "+"); Slapi_Attr *objclasses = NULL; Slapi_ValueSet *objclassvals = NULL; int isextensibleobj = 0; /* get all attrs available for the entry */ slapi_entry_attr_find(e, "objectclass", &objclasses); if (NULL != objclasses) { Slapi_Value *v; slapi_attr_get_valueset(objclasses, &objclassvals); i = slapi_valueset_first_value(objclassvals, &v); if (-1 != i) { const char *ocname = NULL; allattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } /* add "aci" to the allattrs to adjust to do_search */ charray_add(&allattrs, slapi_attr_syntax_normalize("aci")); while (-1 != i) { i = slapi_valueset_next_value(objclassvals, i, &v); if (-1 != i) { myattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/); charray_free(myattrs); } } } slapi_valueset_free(objclassvals); } /* get operational attrs */ opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR); noexpattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_NOEXPOSE); /* subtract no expose attrs from opattrs (e.g., unhashed pw) */ charray_subtract(opattrs, noexpattrs, NULL); if (isextensibleobj) { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } } else { if (hasstar && hasplus) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTS(opattrs); } else if (hasstar) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs); } else if (hasplus) { GER_GET_ATTR_RIGHTS(opattrs); GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs); } else { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } if (charray_inlist(noexpattrs, attrs[i])) { continue; } else if (charray_inlist(allattrs, attrs[i]) || charray_inlist(opattrs, attrs[i]) || (0 == strcasecmp(attrs[i], "dn")) || (0 == strcasecmp(attrs[i], "distinguishedName"))) { _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } else { /* if the attr does not belong to the entry, "<attr>:none" is returned */ if (!isfirstattr) { _append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL); } _append_gerstr(gerstr, gerstrsize, gerstrcap, attrs[i], ":"); _append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL); isfirstattr = 0; } } } } charray_free(allattrs); charray_free(opattrs); } else { Slapi_Attr *prevattr = NULL, *attr; char *type; while ( slapi_entry_next_attr ( e, prevattr, &attr ) == 0 ) { if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) ) { slapi_attr_get_type ( attr, &type ); _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } prevattr = attr; } } if ( isfirstattr ) { /* not a single attribute was retrived or specified */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "*:none", NULL); } return; }
/* * memberof_validate_config() * * Validate the pending changes in the e entry. */ int memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { Slapi_Attr *memberof_attr = NULL; Slapi_Attr *group_attr = NULL; Slapi_DN *config_sdn = NULL; Slapi_DN **include_dn = NULL; Slapi_DN **exclude_dn = NULL; char *syntaxoid = NULL; char *config_dn = NULL; char *skip_nested = NULL; char *auto_add_oc = NULL; char **entry_scopes = NULL; char **entry_exclude_scopes = NULL; int not_dn_syntax = 0; int num_vals = 0; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* Make sure both the group attr and the memberOf attr * config atributes are supplied. We don't care about &attr * here, but slapi_entry_attr_find() requires us to pass it. */ if (!slapi_entry_attr_find(e, MEMBEROF_GROUP_ATTR, &group_attr) && !slapi_entry_attr_find(e, MEMBEROF_ATTR, &memberof_attr)) { Slapi_Attr *test_attr = NULL; Slapi_Value *value = NULL; int hint = 0; /* Loop through each group attribute to see if the syntax is correct. */ hint = slapi_attr_first_value(group_attr, &value); while (value && (not_dn_syntax == 0)) { /* We need to create an attribute to find the syntax. */ test_attr = slapi_attr_new(); slapi_attr_init(test_attr, slapi_value_get_string(value)); /* Get the syntax OID and see if it's the Distinguished Name or * Name and Optional UID syntax. */ slapi_attr_get_syntax_oid_copy(test_attr, &syntaxoid ); not_dn_syntax = strcmp(syntaxoid, DN_SYNTAX_OID) & strcmp(syntaxoid, NAME_OPT_UID_SYNTAX_OID); slapi_ch_free_string(&syntaxoid); /* Print an error if the current attribute is not using the Distinguished * Name syntax, otherwise get the next group attribute. */ if (not_dn_syntax) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "an attribute defined to use either the Distinguished " "Name or Name and Optional UID syntax. (illegal value: %s)", slapi_value_get_string(value), MEMBEROF_GROUP_ATTR); } else { hint = slapi_attr_next_value(group_attr, hint, &value); } /* Free the group attribute. */ slapi_attr_free(&test_attr); } if (not_dn_syntax == 0) { /* Check the syntax of the memberof attribute. */ slapi_attr_first_value(memberof_attr, &value); test_attr = slapi_attr_new(); slapi_attr_init(test_attr, slapi_value_get_string(value)); slapi_attr_get_syntax_oid_copy(test_attr, &syntaxoid ); not_dn_syntax = strcmp(syntaxoid, DN_SYNTAX_OID); slapi_ch_free_string(&syntaxoid); slapi_attr_free(&test_attr); if (not_dn_syntax) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "an attribute defined to use the Distinguished " "Name syntax. (illegal value: %s)", slapi_value_get_string(value), MEMBEROF_ATTR); goto done; } else { *returncode = LDAP_SUCCESS; } } } else { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s and %s configuration attributes must be provided", MEMBEROF_GROUP_ATTR, MEMBEROF_ATTR); goto done; } if ((skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR))){ if(strcasecmp(skip_nested, "on") != 0 && strcasecmp(skip_nested, "off") != 0){ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "\"on\" or \"off\". (illegal value: %s)", MEMBEROF_SKIP_NESTED_ATTR, skip_nested); goto done; } } if ((auto_add_oc = slapi_entry_attr_get_charptr(e, MEMBEROF_AUTO_ADD_OC))){ char *sup = NULL; /* Check if the objectclass exists by looking for its superior oc */ if((sup = slapi_schema_get_superior_name(auto_add_oc)) == NULL){ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "to an existing objectclass (unknown: %s)", MEMBEROF_AUTO_ADD_OC, auto_add_oc); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } else { slapi_ch_free_string(&sup); } } if ((config_dn = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA))){ /* Now check the shared config attribute, validate it now */ Slapi_Entry *e = NULL; int rc = 0; rc = slapi_dn_syntax_check(pb, config_dn, 1); if (rc) { /* syntax check failed */ slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_validate_config - " "%s does not contain a valid DN (%s)\n", SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn); *returncode = LDAP_INVALID_DN_SYNTAX; goto done; } config_sdn = slapi_sdn_new_dn_byval(config_dn); slapi_search_internal_get_entry(config_sdn, NULL, &e, memberof_get_plugin_id()); if(e){ slapi_entry_free(e); *returncode = LDAP_SUCCESS; } else { /* config area does not exist! */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute points to an entry that " "can not be found. (%s)", SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn); *returncode = LDAP_UNWILLING_TO_PERFORM; } } /* * Check the entry scopes */ entry_scopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_ATTR, &num_vals); if(entry_scopes){ int i = 0; /* Validate the syntax before we create our DN array */ for (i = 0;i < num_vals; i++){ if(slapi_dn_syntax_check(pb, entry_scopes[i], 1)){ /* invalid dn syntax */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: Invalid DN (%s) for include suffix.", MEMBEROF_PLUGIN_SUBSYSTEM, entry_scopes[i]); slapi_ch_array_free(entry_scopes); entry_scopes = NULL; theConfig.entryScopeCount = 0; *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } /* Now create our SDN array for conflict checking */ include_dn = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *), num_vals+1); for (i = 0;i < num_vals; i++){ include_dn[i] = slapi_sdn_new_dn_passin(entry_scopes[i]); } } /* * Check and process the entry exclude scopes */ entry_exclude_scopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE, &num_vals); if(entry_exclude_scopes){ int i = 0; /* Validate the syntax before we create our DN array */ for (i = 0;i < num_vals; i++){ if(slapi_dn_syntax_check(pb, entry_exclude_scopes[i], 1)){ /* invalid dn syntax */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: Invalid DN (%s) for exclude suffix.", MEMBEROF_PLUGIN_SUBSYSTEM, entry_exclude_scopes[i]); slapi_ch_array_free(entry_exclude_scopes); entry_exclude_scopes = NULL; *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } /* Now create our SDN array for conflict checking */ exclude_dn = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1); for (i = 0;i < num_vals; i++){ exclude_dn[i] = slapi_sdn_new_dn_passin(entry_exclude_scopes[i]); } } /* * Need to do conflict checking */ if(include_dn && exclude_dn){ /* * Make sure we haven't mixed the same suffix, and there are no * conflicts between the includes and excludes */ int i = 0; while(include_dn[i]){ int x = 0; while(exclude_dn[x]){ if(slapi_sdn_compare(include_dn[i], exclude_dn[x] ) == 0) { /* we have a conflict */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: include suffix (%s) is also listed as an exclude suffix list", MEMBEROF_PLUGIN_SUBSYSTEM, slapi_sdn_get_dn(include_dn[i])); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } x++; } i++; } /* Check for parent/child conflicts */ i = 0; while(include_dn[i]){ int x = 0; while(exclude_dn[x]){ if(slapi_sdn_issuffix(include_dn[i], exclude_dn[x])) { /* we have a conflict */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: include suffix (%s) is a child of the exclude suffix(%s)", MEMBEROF_PLUGIN_SUBSYSTEM, slapi_sdn_get_dn(include_dn[i]), slapi_sdn_get_dn(exclude_dn[i])); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } x++; } i++; } } done: memberof_free_scope(exclude_dn, &num_vals); memberof_free_scope(include_dn, &num_vals); slapi_ch_free((void**)&entry_scopes); slapi_ch_free((void**)&entry_exclude_scopes); slapi_sdn_free(&config_sdn); slapi_ch_free_string(&config_dn); slapi_ch_free_string(&skip_nested); slapi_ch_free_string(&auto_add_oc); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
/* * Config DSE callback for index entry changes. * * this function is huge! */ int ldbm_instance_attrcrypt_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg) { ldbm_instance *inst = (ldbm_instance *)arg; Slapi_Attr *attr; Slapi_Value *sval; const struct berval *attrValue; struct attrinfo *ainfo = NULL; LDAPMod **mods; int i = 0; int j = 0; returntext[0] = '\0'; *returncode = LDAP_SUCCESS; slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); slapi_entry_attr_find(e, "cn", &attr); slapi_attr_first_value(attr, &sval); attrValue = slapi_value_get_berval(sval); ainfo_get(inst->inst_be, attrValue->bv_val, &ainfo); if (NULL == ainfo) { return SLAPI_DSE_CALLBACK_ERROR; } for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) { char *config_attr = (char *)mods[i]->mod_type; /* There are basically three cases in the modify: * 1. The attribute was added * 2. The attribute was deleted * 3. The attribute was modified (deleted and added). * Now, of these three, only #3 is legal. * This is because the attribute is mandatory and single-valued in the schema. * We handle this as follows: an add will always replace what's there (if anything). * a delete will remove what's there as long as it matches what's being deleted. * this is to avoid ordering problems with the adds and deletes. */ if (strcasecmp(config_attr, "nsEncryptionAlgorithm") == 0) { if (SLAPI_IS_MOD_ADD(mods[i]->mod_op)) { for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) { int cipher = ldbm_attrcrypt_parse_cipher(mods[i]->mod_bvalues[j]->bv_val); if (0 == cipher) { /* Tried to configure an invalid cipher */ } ldbm_instance_attrcrypt_enable(ainfo,cipher); } continue; } if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) { if ((mods[i]->mod_bvalues == NULL) || (mods[i]->mod_bvalues[0] == NULL)) { /* Not legal */ return SLAPI_DSE_CALLBACK_ERROR; } else { for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) { /* Code before here should ensure that we only ever delete something that was already here */ ldbm_instance_attrcrypt_disable(ainfo); } } continue; } } } return SLAPI_DSE_CALLBACK_OK; }
/* * preop_modrdn - Pre-operation call for modify RDN * * Check that the new RDN does not include attributes that * cause a constraint violation */ static int preop_modrdn(Slapi_PBlock *pb) { int result = LDAP_SUCCESS; Slapi_Entry *e = NULL; Slapi_Value *sv_requiredObjectClass = NULL; char *errtext = NULL; char *attrName = NULL; #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODRDN begin\n"); #endif BEGIN int err; char *markerObjectClass=NULL; char *requiredObjectClass=NULL; Slapi_DN *sdn = NULL; Slapi_DN *superior; char *rdn; int deloldrdn = 0; int isupdatedn; Slapi_Attr *attr; int argc; char **argv = NULL; /* * If this is a replication update, just be a noop. */ err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn); if (err) { result = uid_op_error(30); break; } if (isupdatedn) { break; } /* * Get the arguments */ result = getArguments(pb, &attrName, &markerObjectClass, &requiredObjectClass); if (UNTAGGED_PARAMETER == result) { result = LDAP_SUCCESS; /* Statically defined subtrees to monitor */ err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (err) { result = uid_op_error(53); break; } err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); if (err) { result = uid_op_error(54); break; } argc--; /* First argument was attribute name */ argv++; } else if (0 != result) { break; } /* Create a Slapi_Value for the requiredObjectClass to use * for checking the entry. */ if (requiredObjectClass) { sv_requiredObjectClass = slapi_value_new_string(requiredObjectClass); } /* Get the DN of the entry being renamed */ err = slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn); if (err) { result = uid_op_error(31); break; } /* Get superior value - unimplemented in 3.0/4.0/5.0 DS */ err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &superior); if (err) { result = uid_op_error(32); break; } /* * No superior means the entry is just renamed at * its current level in the tree. Use the target DN for * determining which managed tree this belongs to */ if (!superior) superior = sdn; /* Get the new RDN - this has the attribute values */ err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &rdn); if (err) { result = uid_op_error(33); break; } #ifdef DEBUG slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODRDN newrdn=%s\n", rdn); #endif /* See if the old RDN value is being deleted. */ err = slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn); if (err) { result = uid_op_error(34); break; } /* Get the entry that is being renamed so we can make a dummy copy * of what it will look like after the rename. */ err = slapi_search_internal_get_entry(sdn, NULL, &e, plugin_identity); if (err != LDAP_SUCCESS) { result = uid_op_error(35); /* We want to return a no such object error if the target doesn't exist. */ if (err == LDAP_NO_SUCH_OBJECT) { result = err; } break; } /* Apply the rename operation to the dummy entry. */ /* slapi_entry_rename does not expect rdn normalized */ err = slapi_entry_rename(e, rdn, deloldrdn, superior); if (err != LDAP_SUCCESS) { result = uid_op_error(36); break; } /* * Find any unique attribute data in the new RDN */ err = slapi_entry_attr_find(e, attrName, &attr); if (err) break; /* no UID attribute */ /* * Check if it has the required object class */ if (requiredObjectClass && !slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sv_requiredObjectClass)) { break; } /* * Passed all the requirements - this is an operation we * need to enforce uniqueness on. Now find all parent entries * with the marker object class, and do a search for each one. */ if (NULL != markerObjectClass) { /* Subtree defined by location of marker object class */ result = findSubtreeAndSearch(slapi_entry_get_sdn(e), attrName, attr, NULL, requiredObjectClass, sdn, markerObjectClass); } else { /* Subtrees listed on invocation line */ result = searchAllSubtrees(argc, argv, attrName, attr, NULL, requiredObjectClass, sdn); } END /* Clean-up */ slapi_value_free(&sv_requiredObjectClass); if (e) slapi_entry_free(e); if (result) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "MODRDN result %d\n", result); if (result == LDAP_CONSTRAINT_VIOLATION) { errtext = slapi_ch_smprintf(moreInfo, attrName); } else { errtext = slapi_ch_strdup("Error checking for attribute uniqueness."); } slapi_send_ldap_result(pb, result, 0, errtext, 0, 0); slapi_ch_free_string(&errtext); } return (result==LDAP_SUCCESS)?0:-1; }
/* Code shared between regular and internal add operation */ static void op_shared_add (Slapi_PBlock *pb) { Slapi_Operation *operation; Slapi_Entry *e, *pse; Slapi_Backend *be = NULL; int err; int internal_op, repl_op, legacy_op, lastmod; char *pwdtype = NULL; Slapi_Attr *attr = NULL; Slapi_Entry *referral; char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE]; struct slapdplugin *p = NULL; char *proxydn = NULL; char *proxystr = NULL; int proxy_err = LDAP_SUCCESS; char *errtext = NULL; Slapi_DN *sdn = NULL; passwdPolicy *pwpolicy; slapi_pblock_get (pb, SLAPI_OPERATION, &operation); slapi_pblock_get (pb, SLAPI_ADD_ENTRY, &e); slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op); slapi_pblock_get (pb, SLAPI_IS_LEGACY_REPLICATED_OPERATION, &legacy_op); internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL); pwpolicy = new_passwdPolicy(pb, slapi_entry_get_dn(e)); /* target spec is used to decide which plugins are applicable for the operation */ operation_set_target_spec (operation, slapi_entry_get_sdn (e)); if ((err = slapi_entry_add_rdn_values(e)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, "failed to add RDN values", 0, NULL); goto done; } /* get the proxy auth dn if the proxy auth control is present */ proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext); 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 ADD dn=\"%s\"%s\n", pb->pb_conn->c_connid, operation->o_opid, slapi_entry_get_dn_const(e), proxystr ? proxystr : ""); } else { slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d ADD dn=\"%s\"\n", LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID, slapi_entry_get_dn_const(e)); } } /* 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 done; } /* * We could be serving multiple database backends. Select the * appropriate one. */ if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf, sizeof(errorbuf))) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, errorbuf, 0, NULL); be = NULL; goto done; } 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 done; } slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void*)operation_get_target_spec (operation)); send_referrals_from_entry(pb,referral); slapi_entry_free(referral); goto done; } if (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)) { Slapi_Value **unhashed_password_vals = NULL; Slapi_Value **present_values = NULL; /* Setting unhashed password to the entry extension. */ if (repl_op) { /* replicated add ==> get unhashed pw from entry, if any. * set it to the extension */ slapi_entry_attr_find(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD, &attr); if (attr) { present_values = attr_get_present_values(attr); valuearray_add_valuearray(&unhashed_password_vals, present_values, 0); #if !defined(USE_OLD_UNHASHED) /* and remove it from the entry. */ slapi_entry_attr_delete(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD); #endif } } else { /* ordinary add ==> * get unhashed pw from userpassword before encrypting it */ /* look for user password attribute */ slapi_entry_attr_find(e, SLAPI_USERPWD_ATTR, &attr); if (attr) { Slapi_Value **vals = NULL; /* Set the backend in the pblock. * The slapi_access_allowed function * needs this set to work properly. */ slapi_pblock_set(pb, SLAPI_BACKEND, slapi_be_select(slapi_entry_get_sdn_const(e))); /* Check ACI before checking password syntax */ if ((err = slapi_access_allowed(pb, e, SLAPI_USERPWD_ATTR, NULL, SLAPI_ACL_ADD)) != LDAP_SUCCESS) { send_ldap_result(pb, err, NULL, "Insufficient 'add' privilege to the " "'userPassword' attribute", 0, NULL); goto done; } /* * Check password syntax, unless this is a pwd admin/rootDN */ present_values = attr_get_present_values(attr); if (!pw_is_pwp_admin(pb, pwpolicy) && check_pw_syntax(pb, slapi_entry_get_sdn_const(e), present_values, NULL, e, 0) != 0) { /* error result is sent from check_pw_syntax */ goto done; } /* pw syntax is valid */ valuearray_add_valuearray(&unhashed_password_vals, present_values, 0); valuearray_add_valuearray(&vals, present_values, 0); pw_encodevals_ext(pb, slapi_entry_get_sdn (e), vals); add_password_attrs(pb, operation, e); slapi_entry_attr_replace_sv(e, SLAPI_USERPWD_ATTR, vals); valuearray_free(&vals); #if defined(USE_OLD_UNHASHED) /* Add the unhashed password pseudo-attribute to the entry */ pwdtype = slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD); slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals); #endif } } if (unhashed_password_vals && (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch())) { /* unhashed_password_vals is consumed if successful. */ err = slapi_pw_set_entry_ext(e, unhashed_password_vals, SLAPI_EXT_SET_ADD); if (err) { valuearray_free(&unhashed_password_vals); } } #if defined(THISISTEST) { /* test code to retrieve an unhashed pw from the entry extention & * PSEUDO_ATTR_UNHASHEDUSERPASSWORD attribute */ char *test_str = slapi_get_first_clear_text_pw(e); if (test_str) { slapi_log_err(SLAPI_LOG_ERR, "Value from extension: %s\n", test_str); slapi_ch_free_string(&test_str); } #if defined(USE_OLD_UNHASHED) test_str = slapi_entry_attr_get_charptr(e, PSEUDO_ATTR_UNHASHEDUSERPASSWORD); if (test_str) { slapi_log_err(SLAPI_LOG_ERR, "Value from attr: %s\n", test_str); slapi_ch_free_string(&test_str); } #endif /* USE_OLD_UNHASHED */ } #endif /* THISISTEST */ /* look for multiple backend local credentials or replication local credentials */ for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL && !repl_op; p = p->plg_next ) { char *L_attr = NULL; int i=0; /* Get the appropriate decoding function */ for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i]) { /* look for multiple backend local credentials or replication local credentials */ char *L_normalized = slapi_attr_syntax_normalize(L_attr); slapi_entry_attr_find(e, L_normalized, &attr); if (attr) { Slapi_Value **present_values = NULL; Slapi_Value **vals = NULL; present_values= attr_get_present_values(attr); valuearray_add_valuearray(&vals, present_values, 0); pw_rever_encode(vals, L_normalized); slapi_entry_attr_replace_sv(e, L_normalized, vals); valuearray_free(&vals); } if (L_normalized) slapi_ch_free ((void**)&L_normalized); } } } slapi_pblock_set(pb, SLAPI_BACKEND, be); if (!repl_op) { /* can get lastmod only after backend is selected */ slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod); if (lastmod && add_created_attrs(pb, e) != 0) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot insert computed attributes", 0, NULL); goto done; } /* expand objectClass values to reflect the inheritance hierarchy */ slapi_schema_expand_objectclasses( e ); } /* uniqueid needs to be generated for entries added during legacy replication */ if (legacy_op){ if (add_uniqueid(e) != UID_SUCCESS) { send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "cannot insert computed attributes", 0, NULL); goto done; } } /* * call the pre-add plugins. if they succeed, call * the backend add function. then call the post-add * plugins. */ sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(e)); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, (void *)sdn); if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN : SLAPI_PLUGIN_PRE_ADD_FN) == SLAPI_PLUGIN_SUCCESS) { int rc; Slapi_Entry *ec; Slapi_DN *add_target_sdn = NULL; Slapi_Entry *save_e = NULL; slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database); set_db_default_result_handlers(pb); /* because be_add frees the entry */ ec = slapi_entry_dup(e); add_target_sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(ec)); slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, add_target_sdn); if (be->be_add != NULL) { rc = (*be->be_add)(pb); /* backend may change this if errors and not consumed */ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &save_e); slapi_pblock_set(pb, SLAPI_ADD_ENTRY, ec); if (rc == 0) { /* acl is not enabled for internal operations */ /* don't 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_ADD); } 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); do_ps_service(pse, NULL, LDAP_CHANGETYPE_ADD, 0); /* * If be_add succeeded, then e is consumed except the resurrect case. * If it is resurrect, the corresponding tombstone entry is resurrected * and put into the cache. * Otherwise, we set e to NULL to prevent freeing it ourselves. */ if (operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY) && save_e) { e = save_e; } else { e = NULL; } } else { /* PR_ASSERT(!save_e); save_e is supposed to be freed in the backend. */ e = save_e; if (rc == SLAPI_FAIL_DISKFULL) { operation_out_of_disk_space(); goto done; } /* If the disk is full we don't want to make it worse ... */ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT)) { write_auditfail_log_entry(pb); /* Record the operation in the audit log */ } } } 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_ADD_FN : SLAPI_PLUGIN_POST_ADD_FN); slapi_entry_free(ec); } slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); done: if (be) slapi_be_Unlock(be); slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse); slapi_entry_free(pse); slapi_ch_free((void **)&operation->o_params.p.p_add.parentuniqueid); slapi_entry_free(e); slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL); slapi_ch_free((void**)&pwdtype); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); }
int parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count ) { int ret = 0; int mod_op = 0; Slapi_Attr *read_attr = NULL; size_t current_sub_count = 0; int already_present = 0; int repl_op = 0; Slapi_Mods *smods = NULL; char value_buffer[20]; /* enough digits for 2^64 children */ if (new_sub_count) *new_sub_count = 0; repl_op = PARENTUPDATE_TOMBSTONE_MASK & op; op &= PARENTUPDATE_MASK; /* Check nobody is trying to use op == 3, it's not implemented yet */ PR_ASSERT( (op == PARENTUPDATE_ADD) || (op == PARENTUPDATE_DEL)); /* We want to invent a mods set to be passed to modify_apply_mods() */ /* For now, we're only interested in subordinatecount. We first examine the present value for the attribute. If it isn't present and we're adding, we assign value 1 to the attribute and add it. If it is present, we increment or decrement depending upon whether we're adding or deleting. If the value after decrementing is zero, we remove it. */ smods = slapi_mods_new(); /* Get the present value of the subcount attr, or 0 if not present */ ret = slapi_entry_attr_find(mc->old_entry->ep_entry,numsubordinates,&read_attr); if (0 == ret) { /* decode the value */ Slapi_Value *sval; slapi_attr_first_value( read_attr, &sval ); if (sval!=NULL) { const struct berval *bval = slapi_value_get_berval(sval); if(NULL != bval) { already_present = 1; current_sub_count = atol(bval->bv_val); } } } if (PARENTUPDATE_DELETE_TOMBSTONE != repl_op) { /* are we adding ? */ if ( (PARENTUPDATE_ADD == op) && !already_present) { /* If so, and the parent entry does not already have a subcount * attribute, we need to add it */ mod_op = LDAP_MOD_ADD; } else if (PARENTUPDATE_DEL == op) { if (!already_present) { /* This means that something is wrong---deleting a child but no subcount present on parent */ LDAPDebug0Args( LDAP_DEBUG_ANY, "numsubordinates assertion failure\n" ); slapi_mods_free(&smods); return -1; } else { if (current_sub_count == 1) { mod_op = LDAP_MOD_DELETE; } else { mod_op = LDAP_MOD_REPLACE; } } } else { /* (PARENTUPDATE_ADD == op) && already_present */ mod_op = LDAP_MOD_REPLACE; } /* Now compute the new value */ if (PARENTUPDATE_ADD == op) { current_sub_count++; } else { current_sub_count--; } if (mod_op == LDAP_MOD_DELETE) { slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, numsubordinates, 0, NULL); } else { sprintf(value_buffer,"%lu", current_sub_count); slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, numsubordinates, strlen(value_buffer), value_buffer); } if (new_sub_count) { *new_sub_count = current_sub_count; } } /* tombstoneNumSubordinates is needed only when this is repl op * and a child is being deleted */ if (repl_op && (PARENTUPDATE_DEL == op)) { current_sub_count = LDAP_MAXINT; ret = slapi_entry_attr_find(mc->old_entry->ep_entry, tombstone_numsubordinates, &read_attr); if (0 == ret) { /* decode the value */ Slapi_Value *sval; slapi_attr_first_value( read_attr, &sval ); if (sval!=NULL) { const struct berval *bval = slapi_value_get_berval(sval); if(NULL != bval) { current_sub_count = atol(bval->bv_val); } } } if (PARENTUPDATE_DELETE_TOMBSTONE == repl_op) { /* deleting a tombstone entry: * reaping or manually deleting it */ if ((current_sub_count != LDAP_MAXINT) && (current_sub_count > 0)) { current_sub_count--; mod_op = LDAP_MOD_REPLACE; sprintf(value_buffer,"%lu", current_sub_count); slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, tombstone_numsubordinates, strlen(value_buffer), value_buffer); } } if (PARENTUPDATE_CREATE_TOMBSTONE == repl_op) { /* creating a tombstone entry */ if (current_sub_count != LDAP_MAXINT) { current_sub_count++; } else { /* tombstonenumsubordinates does not exist */ current_sub_count = 1; } mod_op = LDAP_MOD_REPLACE; sprintf(value_buffer,"%lu", current_sub_count); slapi_mods_add(smods, mod_op | LDAP_MOD_BVALUES, tombstone_numsubordinates, strlen(value_buffer), value_buffer); } } ret = modify_apply_mods(mc, smods); /* smods passed in */ return ret; }
/* See if the given entry has an attribute with the given name and the given value; if value is NULL, just test for the presence of the given attribute; if value is an empty string (i.e. value[0] == 0), the first value in the attribute will be copied into the given buffer and returned */ static int entry_has_attr_and_value(Slapi_Entry *e, const char *attrname, char *value, size_t valuebufsize ) { int retval = 0; Slapi_Attr *attr = 0; if (!e || !attrname) return retval; /* see if the entry has the specified attribute name */ if (!slapi_entry_attr_find(e, attrname, &attr) && attr) { /* if value is not null, see if the attribute has that value */ if (!value) { retval = 1; } else { Slapi_Value *v = 0; int index = 0; for (index = slapi_attr_first_value(attr, &v); v && (index != -1); index = slapi_attr_next_value(attr, index, &v)) { const char *s = slapi_value_get_string(v); if (!s) continue; if (!*value) { size_t len = strlen(s); if ( len < valuebufsize ) { strcpy(value, s); retval = 1; } else { slapi_log_error( SLAPI_LOG_FATAL, "bootstrap config", "Ignoring extremely large value for" " configuration attribute %s" " (length=%ld, value=%40.40s...)\n", attrname, len, s ); retval = 0; /* value is too large: ignore it */ } break; } else if (!strcasecmp(s, value)) { retval = 1; break; } } } } return retval; }
/* * Return 0 for OK, * -1 for Ignore or Error depending on SLAPI_RESULT_CODE, * >0 for action code * Action Code Bit 0: Fetch existing entry. * Action Code Bit 1: Fetch parent entry. * The function is called as a be pre-op on consumers. */ int urp_add_operation( Slapi_PBlock *pb ) { Slapi_Entry *existing_uniqueid_entry; Slapi_Entry *existing_dn_entry; Slapi_Entry *addentry; const char *adduniqueid; CSN *opcsn; const char *basedn; char sessionid[REPL_SESSION_ID_SIZE]; int r; int op_result= 0; int rc= 0; /* OK */ Slapi_DN *sdn = NULL; if ( slapi_op_abandoned(pb) ) { return rc; } get_repl_session_id (pb, sessionid, &opcsn); slapi_pblock_get( pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &existing_uniqueid_entry ); if (existing_uniqueid_entry!=NULL) { /* * An entry with this uniqueid already exists. * - It could be a replay of the same Add, or * - It could be a UUID generation collision, or */ /* * This operation won't be replayed. That is, this CSN won't update * the max csn in RUV. The CSN is left uncommitted in RUV unless an * error is set to op_result. Just to get rid of this CSN from RUV, * setting an error to op_result */ /* op_result = LDAP_SUCCESS; */ slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): an entry with this uniqueid already exists.\n", slapi_entry_get_dn_const(existing_uniqueid_entry)); op_result= LDAP_UNWILLING_TO_PERFORM; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */ PROFILE_POINT; /* Add Conflict; UniqueID Exists; Ignore */ goto bailout; } slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &addentry ); slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &existing_dn_entry ); if (existing_dn_entry==NULL) /* The target DN does not exist */ { /* Check for parent entry... this could be an orphan. */ Slapi_Entry *parententry; slapi_pblock_get( pb, SLAPI_ADD_PARENT_ENTRY, &parententry ); rc = urp_add_resolve_parententry (pb, sessionid, addentry, parententry, opcsn); PROFILE_POINT; /* Add Entry */ goto bailout; } /* * Naming conflict: an entry with the target DN already exists. * Compare the DistinguishedNameCSN of the existing entry * and the OperationCSN. The smaller CSN wins. The loser changes * its RDN to uniqueid+baserdn, and adds operational attribute * ATTR_NSDS5_REPLCONFLIC. */ basedn = slapi_entry_get_ndn (addentry); adduniqueid = slapi_entry_get_uniqueid (addentry); r = csn_compare (entry_get_dncsn(existing_dn_entry), opcsn); if (r<0) { /* Entry to be added is a loser */ char *newdn= get_dn_plus_uniqueid (sessionid, basedn, adduniqueid); if(newdn==NULL) { op_result= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); rc = SLAPI_PLUGIN_NOOP; /* Abort this Operation */ slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): Add conflict; Unique ID (%s) already in RDN\n", basedn, adduniqueid); PROFILE_POINT; /* Add Conflict; Entry Exists; Unique ID already in RDN - Abort this update. */ } else { /* Add the nsds5ReplConflict attribute in the mods */ Slapi_Attr *attr = NULL; Slapi_Value **vals = NULL; Slapi_RDN *rdn; char buf[BUFSIZ]; PR_snprintf(buf, BUFSIZ, "%s %s", REASON_ANNOTATE_DN, basedn); if (slapi_entry_attr_find (addentry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0) { /* ATTR_NSDS5_REPLCONFLICT exists */ slapi_log_error(SLAPI_LOG_FATAL, sessionid, "urp_add: New entry has nsds5ReplConflict already\n"); vals = attr_get_present_values (attr); /* this returns a pointer to the contents */ } if ( vals == NULL || *vals == NULL ) { /* Add new attribute */ slapi_entry_add_string (addentry, ATTR_NSDS5_REPLCONFLICT, buf); } else { /* * Replace old attribute. We don't worry about the index * change here since the entry is yet to be added. */ slapi_value_set_string (*vals, buf); } /* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */ slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn); slapi_sdn_free(&sdn); slapi_entry_set_normdn(addentry, newdn); /* dn: passin */ sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(addentry)); slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn); rdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn_const(addentry) ); slapi_log_error (slapi_log_urp, sessionid, "urp_add: Naming conflict ADD. Add %s instead\n", slapi_rdn_get_rdn(rdn)); slapi_rdn_free(&rdn); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Operation Entry */ } } else if(r>0) { /* Existing entry is a loser */ if (!urp_annotate_dn(sessionid, existing_dn_entry, opcsn, "ADD")) { op_result= LDAP_OPERATIONS_ERROR; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): Entry to be added is a loser; " "urp_annotate_dn failed.\n", basedn); rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */ } else { /* The backend add code should now search for the existing entry again. */ rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY); rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY); } PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Existing Entry */ } else /* r==0 */ { /* The CSN of the Operation and the Entry DN are the same. * This could only happen if: * a) There are two replicas with the same ReplicaID. * b) We've seen the Operation before. * Let's go with (b) and ignore the little bastard. */ /* * This operation won't be replayed. That is, this CSN won't update * the max csn in RUV. The CSN is left uncommitted in RUV unless an * error is set to op_result. Just to get rid of this CSN from RUV, * setting an error to op_result */ /* op_result = LDAP_SUCCESS; */ slapi_log_error(slapi_log_urp, sessionid, "urp_add (%s): The CSN of the Operation and the Entry DN are the same.", slapi_entry_get_dn_const(existing_dn_entry)); op_result= LDAP_UNWILLING_TO_PERFORM; slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result); rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */ PROFILE_POINT; /* Add Conflict; Entry Exists; Same CSN */ } bailout: return rc; }