/** * Encodes this entry using the V3 encoding. * * @param buffer The buffer to encode into. * @throws DirectoryException If a problem occurs while attempting to encode the entry. */ private void encodeV1(Entry entry, ByteStringBuilder buffer) throws DirectoryException { // The version number will be one byte. buffer.append((byte) 0x01); // TODO: Can we encode the DN directly into buffer? byte[] dnBytes = getBytes(entry.getDN().toString()); buffer.appendBERLength(dnBytes.length); buffer.append(dnBytes); // Encode number of OCs and 0 terminated names. int i = 1; ByteStringBuilder bsb = new ByteStringBuilder(); for (String ocName : entry.getObjectClasses().values()) { bsb.append(ocName); if (i < entry.getObjectClasses().values().size()) { bsb.append((byte) 0x00); } i++; } buffer.appendBERLength(bsb.length()); buffer.append(bsb); // Encode the user attributes in the appropriate manner. encodeV1Attributes(buffer, entry.getUserAttributes()); // The operational attributes will be encoded in the same way as // the user attributes. encodeV1Attributes(buffer, entry.getOperationalAttributes()); }
/** Test for escaped characters in templates, check LDIF output. */ @Test( dataProvider = "templatesToTestLDIFOutput", dependsOnMethods = {"testParsingEscapeCharInTemplate"}) public void testLDIFOutputFromTemplate( String testName, String[] lines, String attrName, String expectedValue) throws Exception { File tmpFile = File.createTempFile(testName, "out.ldif"); tmpFile.deleteOnExit(); String outLdifFilePath = tmpFile.getAbsolutePath(); LdifFileWriter.makeLdif(outLdifFilePath, resourcePath, lines); LDIFImportConfig ldifConfig = new LDIFImportConfig(outLdifFilePath); ldifConfig.setValidateSchema(false); LDIFReader reader = new LDIFReader(ldifConfig); Entry top = reader.readEntry(); Entry e = reader.readEntry(); reader.close(); assertNotNull(top); assertNotNull(e); List<Attribute> attrs = e.getAttribute(attrName); assertFalse(attrs.isEmpty()); Attribute a = attrs.get(0); Attribute expectedRes = Attributes.create(attrName, expectedValue); assertEquals(a, expectedRes); }
/** * Evaluate an entry to be added to see if it has any "aci" attribute type. If it does, examines * each "aci" attribute type value for syntax errors. All of the "aci" attribute type values must * pass syntax check for the add operation to proceed. Any entry with an "aci" attribute type must * have "modify-acl" privileges. * * @param entry The entry to be examined. * @param operation The operation to to check privileges on. * @param clientDN The authorization DN. * @return True if the entry has no ACI attributes or if all of the "aci" attributes values pass * ACI syntax checking. * @throws DirectoryException If a modified ACI could not be decoded. */ private boolean verifySyntax(Entry entry, Operation operation, DN clientDN) throws DirectoryException { if (entry.hasOperationalAttribute(aciType)) { /* * Check that the operation has "modify-acl" privileges since the * entry to be added has an "aci" attribute type. */ if (!operation.getClientConnection().hasPrivilege(Privilege.MODIFY_ACL, operation)) { Message message = INFO_ACI_ADD_FAILED_PRIVILEGE.get( String.valueOf(entry.getDN()), String.valueOf(clientDN)); logError(message); return false; } List<Attribute> attributeList = entry.getOperationalAttribute(aciType, null); for (Attribute attribute : attributeList) { for (AttributeValue value : attribute) { try { DN dn = entry.getDN(); Aci.decode(value.getValue(), dn); } catch (AciException ex) { Message message = WARN_ACI_ADD_FAILED_DECODE.get(String.valueOf(entry.getDN()), ex.getMessage()); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } } } } return true; }
/** {@inheritDoc} */ @Override() public DynamicGroup newInstance(Entry groupEntry) throws DirectoryException { ensureNotNull(groupEntry); // Get the memberURL attribute from the entry, if there is one, and parse // out the LDAP URLs that it contains. LinkedHashSet<LDAPURL> memberURLs = new LinkedHashSet<LDAPURL>(); AttributeType memberURLType = DirectoryConfig.getAttributeType(ATTR_MEMBER_URL_LC, true); List<Attribute> attrList = groupEntry.getAttribute(memberURLType); if (attrList != null) { for (Attribute a : attrList) { for (AttributeValue v : a) { try { memberURLs.add(LDAPURL.decode(v.getValue().toString(), true)); } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } Message message = ERR_DYNAMICGROUP_CANNOT_DECODE_MEMBERURL.get( v.getValue().toString(), String.valueOf(groupEntry.getDN()), de.getMessageObject()); ErrorLogger.logError(message); } } } } return new DynamicGroup(groupEntry.getDN(), memberURLs); }
/** * Generates an entry for a backup directory based on the provided DN. The DN must contain an RDN * component that specifies the path to the backup directory, and that directory must exist and be * a valid backup directory. * * @param entryDN The DN of the backup directory entry to retrieve. * @return The requested backup directory entry. * @throws DirectoryException If the specified directory does not exist or is not a valid backup * directory, or if the DN does not specify any backup directory. */ private Entry getBackupDirectoryEntry(DN entryDN) throws DirectoryException { // Make sure that the DN specifies a backup directory. AttributeType t = DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true); AttributeValue v = entryDN.getRDN().getAttributeValue(t); if (v == null) { Message message = ERR_BACKUP_DN_DOES_NOT_SPECIFY_DIRECTORY.get(String.valueOf(entryDN)); throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message, backupBaseDN, null); } // Get a handle to the backup directory and the information that it // contains. BackupDirectory backupDirectory; try { backupDirectory = BackupDirectory.readBackupDirectoryDescriptor(v.getValue().toString()); } catch (ConfigException ce) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ce); } Message message = ERR_BACKUP_INVALID_BACKUP_DIRECTORY.get(String.valueOf(entryDN), ce.getMessage()); throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } Message message = ERR_BACKUP_ERROR_GETTING_BACKUP_DIRECTORY.get(getExceptionMessage(e)); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } // Construct the backup directory entry to return. LinkedHashMap<ObjectClass, String> ocMap = new LinkedHashMap<ObjectClass, String>(2); ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP); ObjectClass backupDirOC = DirectoryServer.getObjectClass(OC_BACKUP_DIRECTORY, true); ocMap.put(backupDirOC, OC_BACKUP_DIRECTORY); LinkedHashMap<AttributeType, List<Attribute>> opAttrs = new LinkedHashMap<AttributeType, List<Attribute>>(0); LinkedHashMap<AttributeType, List<Attribute>> userAttrs = new LinkedHashMap<AttributeType, List<Attribute>>(3); ArrayList<Attribute> attrList = new ArrayList<Attribute>(1); attrList.add(Attributes.create(t, v)); userAttrs.put(t, attrList); t = DirectoryServer.getAttributeType(ATTR_BACKUP_BACKEND_DN, true); attrList = new ArrayList<Attribute>(1); attrList.add( Attributes.create( t, AttributeValues.create(t, backupDirectory.getConfigEntryDN().toString()))); userAttrs.put(t, attrList); Entry e = new Entry(entryDN, ocMap, userAttrs, opAttrs); e.processVirtualAttributes(); return e; }
private Entry get0(ByteString value) throws Exception { if (value == null) { return null; } final Entry entry = entryFromDatabase(value, dataConfig.getEntryEncodeConfig().getCompressedSchema()); entry.processVirtualAttributes(); return entry; }
/** * Tests the use of the StartTLS extended operation to communicate with the server in conjunction * with SASL EXTERNAL authentication and using a client trust store to validate the server * certificate. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testStartTLSExternalAuthTrustStore() throws Exception { TestCaseUtils.initializeTestBackend(true); Entry e = TestCaseUtils.makeEntry( "dn: cn=Test User,o=test", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "cn: Test User", "givenName: Test", "sn: User"); InternalClientConnection conn = InternalClientConnection.getRootConnection(); AddOperation addOperation = conn.processAdd( e.getDN(), e.getObjectClasses(), e.getUserAttributes(), e.getOperationalAttributes()); assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); String keyStorePath = DirectoryServer.getInstanceRoot() + File.separator + "config" + File.separator + "client.keystore"; String trustStorePath = DirectoryServer.getInstanceRoot() + File.separator + "config" + File.separator + "client.truststore"; String[] args = { "--noPropertiesFile", "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-q", "-K", keyStorePath, "-W", "password", "-P", trustStorePath, "-r", "-b", "", "-s", "base", "(objectClass=*)" }; assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); }
/** * Ensures that password policy creation will fail when given an invalid configuration. * * @param e The entry containing an invalid password policy configuration. * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "invalidConfigs") public void testInvalidConfigurations(Entry e) throws Exception { InternalClientConnection connection = InternalClientConnection.getRootConnection(); AddOperation addOperation = connection.processAdd( e.getDN(), e.getObjectClasses(), e.getUserAttributes(), e.getOperationalAttributes()); assertTrue(addOperation.getResultCode() != ResultCode.SUCCESS); assertNull(DirectoryServer.getEntry(e.getDN())); }
/** * A utility method which may be used by implementations in order to obtain the value of the * specified attribute from the provided entry as a time in generalized time format. * * @param entry The entry whose attribute is to be parsed as a boolean. * @param attributeType The attribute type whose value should be parsed as a generalized time * value. * @return The requested time, or -1 if it could not be determined. * @throws DirectoryException If a problem occurs while attempting to decode the value as a * generalized time. */ protected static final long getGeneralizedTime( final Entry entry, final AttributeType attributeType) throws DirectoryException { long timeValue = -1; final List<Attribute> attrList = entry.getAttribute(attributeType); if (attrList != null) { for (final Attribute a : attrList) { if (a.isEmpty()) { continue; } final AttributeValue v = a.iterator().next(); try { timeValue = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(v.getNormalizedValue()); } catch (final Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); TRACER.debugWarning( "Unable to decode value %s for attribute %s " + "in user entry %s: %s", v.getValue().toString(), attributeType.getNameOrOID(), entry.getDN().toString(), stackTraceToSingleLineString(e)); } final Message message = ERR_PWPSTATE_CANNOT_DECODE_GENERALIZED_TIME.get( v.getValue().toString(), attributeType.getNameOrOID(), entry.getDN().toString(), String.valueOf(e)); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message, e); } break; } } if (timeValue == -1) { if (debugEnabled()) { TRACER.debugInfo( "Returning -1 because attribute %s does not " + "exist in user entry %s", attributeType.getNameOrOID(), entry.getDN().toString()); } } // FIXME: else to be consistent... return timeValue; }
/** {@inheritDoc} */ @Override() public boolean hasValue(Entry entry, VirtualAttributeRule rule) { Backend backend = DirectoryServer.getBackend(entry.getDN()); try { ConditionResult ret = backend.hasSubordinates(entry.getDN()); return ret != null && ret != ConditionResult.UNDEFINED; } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } return false; } }
/** * Performs a successful LDAP bind using CRAM-MD5 using the dn: form of the authentication ID * using a long password (longer than 64 bytes). * * @throws Exception If an unexpected problem occurs. */ @Test() public void testLDAPBindSuccessWithDNAndLongPassword() throws Exception { TestCaseUtils.initializeTestBackend(true); String password = "******"; Entry e = TestCaseUtils.makeEntry( "dn: uid=test.user,o=test", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "userPassword: "******"ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," + "cn=Password Policies,cn=config"); InternalClientConnection conn = InternalClientConnection.getRootConnection(); AddOperation addOperation = conn.processAdd( e.getDN(), e.getObjectClasses(), e.getUserAttributes(), e.getOperationalAttributes()); assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); String[] args = { "--noPropertiesFile", "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-o", "mech=CRAM-MD5", "-o", "authid=dn:uid=test.user,o=test", "-w", password, "-b", "", "-s", "base", "(objectClass=*)" }; assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0); }
/** {@inheritDoc} */ @Override public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation) throws DirectoryException { throw new DirectoryException( ResultCode.UNWILLING_TO_PERFORM, ERR_BACKEND_MODIFY_NOT_SUPPORTED.get(String.valueOf(oldEntry.getDN()), getBackendID())); }
/** {@inheritDoc} */ @Override public Entry getEntry(DN entryDN) throws DirectoryException { // If the requested entry was null, then throw an exception. if (entryDN == null) { throw new DirectoryException( DirectoryServer.getServerErrorResultCode(), ERR_BACKEND_GET_ENTRY_NULL.get(getBackendID())); } // If the requested entry was the backend base entry, then retrieve it. if (entryDN.equals(backupBaseDN)) { return backupBaseEntry.duplicate(true); } // See if the requested entry was one level below the backend base entry. // If so, then it must point to a backup directory. Otherwise, it must be // two levels below the backup base entry and must point to a specific // backup. DN parentDN = entryDN.getParentDNInSuffix(); if (parentDN == null) { Message message = ERR_BACKUP_INVALID_BASE.get(String.valueOf(entryDN)); throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); } else if (parentDN.equals(backupBaseDN)) { return getBackupDirectoryEntry(entryDN); } else if (backupBaseDN.equals(parentDN.getParentDNInSuffix())) { return getBackupEntry(entryDN); } else { Message message = ERR_BACKUP_INVALID_BASE.get(String.valueOf(entryDN)); throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, backupBaseDN, null); } }
private void encodeVolatile(Entry entry, DataConfig dataConfig) throws DirectoryException { // Encode the entry for later use. entry.encode(entryBuffer, dataConfig.getEntryEncodeConfig()); // First write the DB format version byte. encodedBuffer.appendByte(DnKeyFormat.FORMAT_VERSION); try { // Then start the ASN1 sequence. writer.writeStartSequence(TAG_TREE_ENTRY); if (dataConfig.isCompressed()) { OutputStream compressor = null; try { compressor = new DeflaterOutputStream(compressedEntryBuffer.asOutputStream()); entryBuffer.copyTo(compressor); } finally { closeSilently(compressor); } // Compression needed and successful. writer.writeInteger(entryBuffer.length()); writer.writeOctetString(compressedEntryBuffer); } else { writer.writeInteger(0); writer.writeOctetString(entryBuffer); } writer.writeEndSequence(); } catch (IOException ioe) { // TODO: This should never happen with byte buffer. logger.traceException(ioe); } }
/** {@inheritDoc} */ @Override() public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation) throws DirectoryException, CanceledOperationException { checkDiskSpace(modifyOperation); writerBegin(); DN entryDN = newEntry.getDN(); EntryContainer ec; if (rootContainer != null) { ec = rootContainer.getEntryContainer(entryDN); } else { Message message = ERR_ROOT_CONTAINER_NOT_INITIALIZED.get(getBackendID()); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } ec.sharedLock.lock(); try { ec.replaceEntry(oldEntry, newEntry, modifyOperation); } catch (DatabaseException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } throw createDirectoryException(e); } finally { ec.sharedLock.unlock(); writerEnd(); } }
/** * Test that various backup and restore task definitions complete with the expected state. * * @param taskEntry The task entry. * @param expectedState The expected completion state of the task. */ @Test(dataProvider = "backups") public void testBackups(Entry taskEntry, TaskState expectedState) throws Exception { final int backupBeginCountStart = backupBeginCount.get(); final int backupEndCountStart = backupEndCount.get(); final int restoreBeginCountStart = restoreBeginCount.get(); final int restoreEndCountStart = restoreEndCount.get(); ObjectClass backupClass = DirectoryServer.getObjectClass("ds-task-backup", true); testTask(taskEntry, expectedState, 30); if (expectedState == TaskState.COMPLETED_SUCCESSFULLY || expectedState == TaskState.COMPLETED_WITH_ERRORS) { if (taskEntry.hasObjectClass(backupClass)) { // The backup task can back up multiple backends at the same time, so // we the count may be incremented by more than one in those cases. assertThat(backupBeginCount.get()).isGreaterThan(backupBeginCountStart); assertThat(backupEndCount.get()).isGreaterThan(backupEndCountStart); assertEquals(backupBeginCount.get(), backupEndCount.get()); } else { assertEquals(restoreBeginCount.get(), restoreBeginCountStart + 1); assertEquals(restoreEndCount.get(), restoreEndCountStart + 1); assertEquals(restoreBeginCount.get(), restoreEndCount.get()); } } }
/** * Gathers all of the attribute types in an entry along with the "objectclass" attribute type in a * List. The "objectclass" attribute is added to the list first so it is evaluated first. * * @param e Entry to gather the attributes for. * @return List containing the attribute types. */ private List<AttributeType> getAllAttrs(Entry e) { Map<AttributeType, List<Attribute>> attrMap = e.getUserAttributes(); Map<AttributeType, List<Attribute>> opAttrMap = e.getOperationalAttributes(); List<AttributeType> typeList = new LinkedList<AttributeType>(); Attribute attr = e.getObjectClassAttribute(); /* * When a search is not all attributes returned, the "objectclass" * attribute type is missing from the entry. */ if (attr != null) { AttributeType ocType = attr.getAttributeType(); typeList.add(ocType); } typeList.addAll(attrMap.keySet()); typeList.addAll(opAttrMap.keySet()); return typeList; }
/** {@inheritDoc} */ @Override() public boolean isGroupDefinition(Entry entry) { ensureNotNull(entry); // FIXME -- This needs to exclude enhanced groups once we have support for // them. ObjectClass groupOfURLsClass = DirectoryConfig.getObjectClass(OC_GROUP_OF_URLS_LC, true); return entry.hasObjectClass(groupOfURLsClass); }
/** * Performs a failed LDAP bind using CRAM-MD5 using the dn: form of the authentication ID with the * DN of a user that doesn't exist. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testLDAPBindFailNoSuchUser() throws Exception { TestCaseUtils.initializeTestBackend(true); Entry e = TestCaseUtils.makeEntry( "dn: uid=test.user,o=test", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: test.user", "givenName: Test", "sn: User", "cn: Test User", "userPassword: password"); InternalClientConnection conn = InternalClientConnection.getRootConnection(); AddOperation addOperation = conn.processAdd( e.getDN(), e.getObjectClasses(), e.getUserAttributes(), e.getOperationalAttributes()); assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); String[] args = { "--noPropertiesFile", "-h", "127.0.0.1", "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), "-o", "mech=CRAM-MD5", "-o", "authid=dn:uid=doesntexist,o=test", "-w", "password", "-b", "", "-s", "base", "(objectClass=*)" }; assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0); }
/** {@inheritDoc} */ @Override public boolean isGroupDefinition(Entry entry) { ifNull(entry); // FIXME -- This needs to exclude enhanced groups once we have support for // them. ObjectClass virtualStaticGroupClass = DirectoryServer.getObjectClass(OC_VIRTUAL_STATIC_GROUP, true); return entry.hasObjectClass(virtualStaticGroupClass); }
private LocalizableMessage getDisconnectMessage(Entry taskEntry) { AttributeType attrType = DirectoryServer.getAttributeTypeOrDefault(ATTR_TASK_DISCONNECT_MESSAGE); for (Attribute a : taskEntry.getAttribute(attrType)) { for (ByteString v : a) { return LocalizableMessage.raw(v.toString()); } } return INFO_TASK_DISCONNECT_GENERIC_MESSAGE.get(); }
/** {@inheritDoc} */ @Override() public Set<AttributeValue> getValues(Entry entry, VirtualAttributeRule rule) { Backend backend = DirectoryServer.getBackend(entry.getDN()); try { ConditionResult ret = backend.hasSubordinates(entry.getDN()); if (ret != null && ret != ConditionResult.UNDEFINED) { AttributeValue value = AttributeValues.create( ByteString.valueOf(ret.toString()), ByteString.valueOf(ret.toString())); return Collections.singleton(value); } } catch (DirectoryException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } } return Collections.emptySet(); }
/** * Validates a number of password policy state constraints for the user. This will be called * before the offered credentials are checked. * * @param userEntry The entry for the user that is authenticating. * @param saslHandler The SASL mechanism handler if this is a SASL bind, or {@code null} for a * simple bind. * @throws DirectoryException If a problem occurs that should cause the bind to fail. */ protected void checkUnverifiedPasswordPolicyState( Entry userEntry, SASLMechanismHandler<?> saslHandler) throws DirectoryException { PasswordPolicyState pwPolicyState = (PasswordPolicyState) authPolicyState; PasswordPolicy policy = pwPolicyState.getAuthenticationPolicy(); boolean isSASLBind = saslHandler != null; // If the password policy is configured to track authentication failures or // keep the last login time and the associated backend is disabled, then we // may need to reject the bind immediately. if ((policy.getStateUpdateFailurePolicy() == PasswordPolicyCfgDefn.StateUpdateFailurePolicy.PROACTIVE) && ((policy.getLockoutFailureCount() > 0) || ((policy.getLastLoginTimeAttribute() != null) && (policy.getLastLoginTimeFormat() != null))) && ((DirectoryServer.getWritabilityMode() == WritabilityMode.DISABLED) || (backend.getWritabilityMode() == WritabilityMode.DISABLED))) { // This policy isn't applicable to root users, so if it's a root // user then ignore it. if (!DirectoryServer.isRootDN(userEntry.getName())) { throw new DirectoryException( ResultCode.INVALID_CREDENTIALS, ERR_BIND_OPERATION_WRITABILITY_DISABLED.get(userEntry.getName())); } } // Check to see if the authentication must be done in a secure // manner. If so, then the client connection must be secure. if (policy.isRequireSecureAuthentication() && !clientConnection.isSecure()) { if (isSASLBind) { if (!saslHandler.isSecure(saslMechanism)) { throw new DirectoryException( ResultCode.INVALID_CREDENTIALS, ERR_BIND_OPERATION_INSECURE_SASL_BIND.get(saslMechanism, userEntry.getName())); } } else { throw new DirectoryException( ResultCode.INVALID_CREDENTIALS, ERR_BIND_OPERATION_INSECURE_SIMPLE_BIND.get()); } } }
/** * Tests the entry encoding and decoding process the version 1 encoding. * * @throws Exception If the test failed unexpectedly. */ @Test(dataProvider = "encodeConfigs") public void testEntryToAndFromDatabaseV2(EntryEncodeConfig config) throws Exception { ensureServerIsUpAndRunning(); // Convert the test LDIF string to a byte array byte[] originalLDIFBytes = StaticUtils.getBytes(ldifString); try (final LDIFReader reader = new LDIFReader(new LDIFImportConfig(new ByteArrayInputStream(originalLDIFBytes)))) { Entry entryBefore, entryAfterV2; while ((entryBefore = reader.readEntry(false)) != null) { ByteStringBuilder bsb = new ByteStringBuilder(); encodeV2(entryBefore, bsb, config); entryAfterV2 = Entry.decode(bsb.asReader()); if (config.excludeDN()) { entryAfterV2.setDN(entryBefore.getName()); } assertEquals(entryBefore, entryAfterV2); } } }
/** {@inheritDoc} */ @Override public boolean mayProxy(Entry proxyUser, Entry proxiedUser, Operation op) { boolean ret; if (!(ret = skipAccessCheck(proxyUser))) { AuthenticationInfo authInfo = new AuthenticationInfo(proxyUser, DirectoryServer.isRootDN(proxyUser.getDN())); AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(op, proxiedUser, authInfo, ACI_PROXY); ret = accessAllowedEntry(operationContainer); } return ret; }
/** * Returns {@code true} if this authentication policy state is associated with a user whose * account has been administratively disabled. * * <p>The default implementation is use the value of the "ds-pwp-account-disable" attribute in the * user's entry. * * @return {@code true} if this authentication policy state is associated with a user whose * account has been administratively disabled. */ public boolean isDisabled() { final AttributeType type = DirectoryServer.getAttributeType(OP_ATTR_ACCOUNT_DISABLED, true); try { isDisabled = getBoolean(userEntry, type); } catch (final Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } isDisabled = ConditionResult.TRUE; if (debugEnabled()) { TRACER.debugWarning( "User %s is considered administratively " + "disabled because an error occurred while " + "attempting to make the determination: %s.", userEntry.getDN().toString(), stackTraceToSingleLineString(e)); } return true; } if (isDisabled == ConditionResult.UNDEFINED) { isDisabled = ConditionResult.FALSE; if (debugEnabled()) { TRACER.debugInfo( "User %s is not administratively disabled since " + "the attribute \"%s\" is not present in the entry.", userEntry.getDN().toString(), OP_ATTR_ACCOUNT_DISABLED); } return false; } if (debugEnabled()) { TRACER.debugInfo( "User %s %s administratively disabled.", userEntry.getDN().toString(), ((isDisabled == ConditionResult.TRUE) ? " is" : " is not")); } return isDisabled == ConditionResult.TRUE; }
/** * A utility method which may be used by implementations in order to obtain the value of the * specified attribute from the provided entry as a boolean. * * @param entry The entry whose attribute is to be parsed as a boolean. * @param attributeType The attribute type whose value should be parsed as a boolean. * @return The attribute's value represented as a ConditionResult value, or * ConditionResult.UNDEFINED if the specified attribute does not exist in the entry. * @throws DirectoryException If the value cannot be decoded as a boolean. */ protected static final ConditionResult getBoolean( final Entry entry, final AttributeType attributeType) throws DirectoryException { final List<Attribute> attrList = entry.getAttribute(attributeType); if (attrList != null) { for (final Attribute a : attrList) { if (a.isEmpty()) { continue; } final String valueString = toLowerCase(a.iterator().next().getValue().toString()); if (valueString.equals("true") || valueString.equals("yes") || valueString.equals("on") || valueString.equals("1")) { if (debugEnabled()) { TRACER.debugInfo( "Attribute %s resolves to true for user entry " + "%s", attributeType.getNameOrOID(), entry.getDN().toString()); } return ConditionResult.TRUE; } if (valueString.equals("false") || valueString.equals("no") || valueString.equals("off") || valueString.equals("0")) { if (debugEnabled()) { TRACER.debugInfo( "Attribute %s resolves to false for user " + "entry %s", attributeType.getNameOrOID(), entry.getDN().toString()); } return ConditionResult.FALSE; } if (debugEnabled()) { TRACER.debugError( "Unable to resolve value %s for attribute %s " + "in user entry %s as a Boolean.", valueString, attributeType.getNameOrOID(), entry.getDN().toString()); } final Message message = ERR_PWPSTATE_CANNOT_DECODE_BOOLEAN.get( valueString, attributeType.getNameOrOID(), entry.getDN().toString()); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } } if (debugEnabled()) { TRACER.debugInfo( "Returning %s because attribute %s does not exist " + "in user entry %s", ConditionResult.UNDEFINED.toString(), attributeType.getNameOrOID(), entry.getDN().toString()); } return ConditionResult.UNDEFINED; }
/** * Attempt to read a single entry. * * @throws Exception If the test failed unexpectedly. */ @Test(dependsOnMethods = {"testReadEntryEmptyStream"}) public void testReadEntrySingle() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n"; LDIFReader reader = createLDIFReader(ldifString); try { Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertEquals(entry.getDN(), DN.decode("cn=john, dc=foo, dc=com")); Assert.assertTrue(entry.hasObjectClass(OC_TOP)); Assert.assertTrue(entry.hasObjectClass(OC_PERSON)); Assert.assertTrue(entry.hasValue(AT_CN, null, AttributeValues.create(AT_CN, "john"))); Assert.assertTrue(entry.hasValue(AT_SN, null, AttributeValues.create(AT_SN, "smith"))); Assert.assertNull(reader.readEntry()); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 1); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), 1); } finally { reader.close(); } }
/** * Test for escaped characters in templates, check LDIF output when the templates combines escaped * characters and variables. */ @Test(dependsOnMethods = {"testParsingEscapeCharInTemplate"}) public void testOutputCombineEscapeCharInTemplate() throws Exception { String[] lines = { "branch: dc=test", "subordinateTemplate: templateWithEscape:1", "", "template: templateWithEscape", "rdnAttr: uid", "objectclass: inetOrgPerson", "uid: testEntry", "sn: Bar", // The value below combines variable, randoms and escaped chars. // The resulting value is "Foo <?>{1}Bar" where ? is a letter from [A-Z]. "cn: Foo \\<<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>\\>\\{1\\}{sn}", "", }; File tmpFile = File.createTempFile("combineEscapeChar", "out.ldif"); tmpFile.deleteOnExit(); String outLdifFilePath = tmpFile.getAbsolutePath(); LdifFileWriter.makeLdif(outLdifFilePath, resourcePath, lines); LDIFImportConfig ldifConfig = new LDIFImportConfig(outLdifFilePath); ldifConfig.setValidateSchema(false); LDIFReader reader = new LDIFReader(ldifConfig); Entry top = reader.readEntry(); Entry e = reader.readEntry(); reader.close(); assertNotNull(top); assertNotNull(e); List<Attribute> attrs = e.getAttribute("cn"); assertFalse(attrs.isEmpty()); Attribute a = attrs.get(0); assertTrue( a.iterator().next().toString().matches("Foo <[A-Z]>\\{1\\}Bar"), "cn value doesn't match the expected value"); }
/** {@inheritDoc} */ @Override public boolean maySend(DN dn, Operation operation, SearchResultReference reference) { boolean ret; if (!(ret = skipAccessCheck(operation))) { Entry e = new Entry(dn, null, null, null); AttributeBuilder builder = new AttributeBuilder(refAttrType, ATTR_REFERRAL_URL); List<String> URLStrings = reference.getReferralURLs(); // Load the values, a bind rule might want to evaluate them. for (String URLString : URLStrings) { builder.add(AttributeValues.create(refAttrType, URLString)); } e.addAttribute(builder.toAttribute(), null); SearchResultEntry se = new SearchResultEntry(e); AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, (ACI_READ), se); operationContainer.setCurrentAttributeType(refAttrType); ret = accessAllowed(operationContainer); } return ret; }