Search in sources :

Example 1 with StringLimitType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType in project midpoint by Evolveum.

the class ValuePolicyProcessor method validateValue.

public <O extends ObjectType> boolean validateValue(String newValue, ValuePolicyType pp, PrismObject<O> object, StringBuilder message, String shortDesc, Task task, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException {
    Validate.notNull(pp, "Value policy must not be null.");
    OperationResult result = parentResult.createSubresult(OPERATION_STRING_POLICY_VALIDATION);
    result.addParam("policyName", pp.getName());
    normalize(pp);
    if (newValue == null && (pp.getMinOccurs() == null || XsdTypeMapper.multiplicityToInteger(pp.getMinOccurs()) == 0)) {
        // No password is allowed
        result.recordSuccess();
        return true;
    }
    if (newValue == null) {
        newValue = "";
    }
    LimitationsType lims = pp.getStringPolicy().getLimitations();
    testMinimalLength(newValue, lims, result, message);
    testMaximalLength(newValue, lims, result, message);
    testMinimalUniqueCharacters(newValue, lims, result, message);
    if (lims.getLimit() == null || lims.getLimit().isEmpty()) {
        if (message.toString() == null || message.toString().isEmpty()) {
            result.computeStatus();
        } else {
            result.computeStatus(message.toString());
        }
        return result.isAcceptable();
    }
    // check limitation
    HashSet<String> validChars = null;
    HashSet<String> allValidChars = new HashSet<>();
    List<String> passwd = StringPolicyUtils.stringTokenizer(newValue);
    for (StringLimitType stringLimitationType : lims.getLimit()) {
        OperationResult limitResult = new OperationResult("Tested limitation: " + stringLimitationType.getDescription());
        validChars = getValidCharacters(stringLimitationType.getCharacterClass(), pp);
        int count = countValidCharacters(validChars, passwd);
        allValidChars.addAll(validChars);
        testMinimalOccurence(stringLimitationType, count, limitResult, message);
        testMaximalOccurence(stringLimitationType, count, limitResult, message);
        testMustBeFirst(stringLimitationType, count, limitResult, message, newValue, validChars);
        limitResult.computeStatus();
        result.addSubresult(limitResult);
    }
    testInvalidCharacters(passwd, allValidChars, result, message);
    testCheckExpression(newValue, lims, object, shortDesc, task, result, message);
    if (message.toString() == null || message.toString().isEmpty()) {
        result.computeStatus();
    } else {
        result.computeStatus(message.toString());
    }
    return result.isAcceptable();
}
Also used : StringLimitType(com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) LimitationsType(com.evolveum.midpoint.xml.ns._public.common.common_3.LimitationsType) HashSet(java.util.HashSet)

Example 2 with StringLimitType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType in project midpoint by Evolveum.

the class ValuePolicyProcessor method cardinalityCounter.

/**
	 * Count cardinality
	 */
private Map<Integer, List<String>> cardinalityCounter(Map<StringLimitType, List<String>> lims, List<String> password, Boolean skipMatchedLims, boolean uniquenessReached, OperationResult op) {
    HashMap<String, Integer> counter = new HashMap<String, Integer>();
    for (StringLimitType l : lims.keySet()) {
        int counterKey = 1;
        List<String> chars = lims.get(l);
        int i = 0;
        if (null != password) {
            i = charIntersectionCounter(lims.get(l), password);
        }
        // If max is exceed then error unable to continue
        if (l.getMaxOccurs() != null && i > l.getMaxOccurs()) {
            OperationResult o = new OperationResult("Limitation check :" + l.getDescription());
            o.recordFatalError("Exceeded maximal value for this limitation. " + i + ">" + l.getMaxOccurs());
            op.addSubresult(o);
            return null;
        // if max is all ready reached or skip enabled for minimal skip
        // counting
        } else if (l.getMaxOccurs() != null && i == l.getMaxOccurs()) {
            continue;
        // other cases minimum is not reached
        } else if ((l.getMinOccurs() == null || i >= l.getMinOccurs()) && !skipMatchedLims) {
            continue;
        }
        for (String s : chars) {
            if (null == password || !password.contains(s) || uniquenessReached) {
                // if (null == counter.get(s)) {
                counter.put(s, counterKey);
            // } else {
            // counter.put(s, counter.get(s) + 1);
            // }
            }
        }
        counterKey++;
    }
    // If need to remove disabled chars (already reached limitations)
    if (null != password) {
        for (StringLimitType l : lims.keySet()) {
            int i = charIntersectionCounter(lims.get(l), password);
            if (l.getMaxOccurs() != null && i > l.getMaxOccurs()) {
                OperationResult o = new OperationResult("Limitation check :" + l.getDescription());
                o.recordFatalError("Exceeded maximal value for this limitation. " + i + ">" + l.getMaxOccurs());
                op.addSubresult(o);
                return null;
            } else if (l.getMaxOccurs() != null && i == l.getMaxOccurs()) {
                // limitation matched remove all used chars
                LOGGER.trace("Skip " + l.getDescription());
                for (String charToRemove : lims.get(l)) {
                    counter.remove(charToRemove);
                }
            }
        }
    }
    // Transpone to better format
    Map<Integer, List<String>> ret = new HashMap<Integer, List<String>>();
    for (String s : counter.keySet()) {
        // if not there initialize
        if (null == ret.get(counter.get(s))) {
            ret.put(counter.get(s), new ArrayList<String>());
        }
        ret.get(counter.get(s)).add(s);
    }
    return ret;
}
Also used : StringLimitType(com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType) HashMap(java.util.HashMap) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with StringLimitType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType in project midpoint by Evolveum.

the class ValuePolicyProcessor method generateAttempt.

private String generateAttempt(StringPolicyType policy, int defaultLength, boolean generateMinimalSize, OperationResult result) {
    // if (policy.getLimitations() != null &&
    // policy.getLimitations().getMinLength() != null){
    // generateMinimalSize = true;
    // }
    // setup default values where missing
    // PasswordPolicyUtils.normalize(pp);
    // Optimize usage of limits ass hashmap of limitas and key is set of
    // valid chars for each limitation
    Map<StringLimitType, List<String>> lims = new HashMap<StringLimitType, List<String>>();
    int minLen = defaultLength;
    int maxLen = defaultLength;
    int unique = defaultLength / 2;
    if (policy != null) {
        for (StringLimitType l : policy.getLimitations().getLimit()) {
            if (null != l.getCharacterClass().getValue()) {
                lims.put(l, StringPolicyUtils.stringTokenizer(l.getCharacterClass().getValue()));
            } else {
                lims.put(l, StringPolicyUtils.stringTokenizer(StringPolicyUtils.collectCharacterClass(policy.getCharacterClass(), l.getCharacterClass().getRef())));
            }
        }
        // Get global limitations
        minLen = policy.getLimitations().getMinLength() == null ? 0 : policy.getLimitations().getMinLength().intValue();
        if (minLen != 0 && minLen > defaultLength) {
            defaultLength = minLen;
        }
        maxLen = (policy.getLimitations().getMaxLength() == null ? 0 : policy.getLimitations().getMaxLength().intValue());
        unique = policy.getLimitations().getMinUniqueChars() == null ? minLen : policy.getLimitations().getMinUniqueChars().intValue();
    }
    // test correctness of definition
    if (unique > minLen) {
        minLen = unique;
        OperationResult reportBug = new OperationResult("Global limitation check");
        reportBug.recordWarning("There is more required uniq characters then definied minimum. Raise minimum to number of required uniq chars.");
    }
    if (minLen == 0 && maxLen == 0) {
        minLen = defaultLength;
        maxLen = defaultLength;
        generateMinimalSize = true;
    }
    if (maxLen == 0) {
        if (minLen > defaultLength) {
            maxLen = minLen;
        } else {
            maxLen = defaultLength;
        }
    }
    // Initialize generator
    StringBuilder password = new StringBuilder();
    /*
		 * ********************************** Try to find best characters to be
		 * first in password
		 */
    Map<StringLimitType, List<String>> mustBeFirst = new HashMap<StringLimitType, List<String>>();
    for (StringLimitType l : lims.keySet()) {
        if (l.isMustBeFirst() != null && l.isMustBeFirst()) {
            mustBeFirst.put(l, lims.get(l));
        }
    }
    // If any limitation was found to be first
    if (!mustBeFirst.isEmpty()) {
        Map<Integer, List<String>> posibleFirstChars = cardinalityCounter(mustBeFirst, null, false, false, result);
        int intersectionCardinality = mustBeFirst.keySet().size();
        List<String> intersectionCharacters = posibleFirstChars.get(intersectionCardinality);
        // If no intersection was found then raise error
        if (null == intersectionCharacters || intersectionCharacters.size() == 0) {
            result.recordFatalError("No intersection for required first character sets in value policy:" + policy.getDescription());
            // Log error
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("Unable to generate value for " + getPath() + ": No intersection for required first character sets in value policy: [" + policy.getDescription() + "] following character limitation and sets are used:");
                for (StringLimitType l : mustBeFirst.keySet()) {
                    StrBuilder tmp = new StrBuilder();
                    tmp.appendSeparator(", ");
                    tmp.appendAll(mustBeFirst.get(l));
                    LOGGER.error("L:" + l.getDescription() + " -> [" + tmp + "]");
                }
            }
            // EXIT
            return null;
        } else {
            if (LOGGER.isDebugEnabled()) {
                StrBuilder tmp = new StrBuilder();
                tmp.appendSeparator(", ");
                tmp.appendAll(intersectionCharacters);
                LOGGER.trace("Generate first character intersection items [" + tmp + "] into " + getPath() + ".");
            }
            // Generate random char into password from intersection
            password.append(intersectionCharacters.get(RAND.nextInt(intersectionCharacters.size())));
        }
    }
    /*
		 * ************************************** Generate rest to fulfill
		 * minimal criteria
		 */
    boolean uniquenessReached = false;
    // Count cardinality of elements
    Map<Integer, List<String>> chars;
    for (int i = 0; i < minLen; i++) {
        // Check if still unique chars are needed
        if (password.length() >= unique) {
            uniquenessReached = true;
        }
        // Find all usable characters
        chars = cardinalityCounter(lims, StringPolicyUtils.stringTokenizer(password.toString()), false, uniquenessReached, result);
        // If something goes badly then go out
        if (null == chars) {
            return null;
        }
        if (chars.isEmpty()) {
            LOGGER.trace("Minimal criterias was met. No more characters");
            break;
        }
        // Find lowest possible cardinality and then generate char
        for (int card = 1; card < lims.keySet().size(); card++) {
            if (chars.containsKey(card)) {
                List<String> validChars = chars.get(card);
                password.append(validChars.get(RAND.nextInt(validChars.size())));
                break;
            }
        }
    }
    // test if maximum is not exceeded
    if (password.length() > maxLen) {
        result.recordFatalError("Unable to meet minimal criteria and not exceed maximxal size of " + getPath() + ".");
        return null;
    }
    for (int i = 0; i < minLen; i++) {
        // test if max is reached
        if (password.length() == maxLen) {
            // no more characters maximal size is reached
            break;
        }
        if (password.length() >= minLen && generateMinimalSize) {
            // no more characters are needed
            break;
        }
        // Check if still unique chars are needed
        if (password.length() >= unique) {
            uniquenessReached = true;
        }
        // find all usable characters
        chars = cardinalityCounter(lims, StringPolicyUtils.stringTokenizer(password.toString()), true, uniquenessReached, result);
        // If something goes badly then go out
        if (null == chars) {
            // we hope this never happend.
            result.recordFatalError("No valid characters to generate, but no all limitation are reached");
            return null;
        }
        // our work
        if (chars.isEmpty()) {
            if (i == 0) {
                password.append(RandomStringUtils.randomAlphanumeric(minLen));
            }
            break;
        // if (!StringUtils.isBlank(password.toString()) &&
        // password.length() >= minLen) {
        // break;
        // }
        // check uf this is a firs cycle and if we need to user some
        // default (alphanum) character class.
        }
        // Find lowest possible cardinality and then generate char
        for (int card = 1; card <= lims.keySet().size(); card++) {
            if (chars.containsKey(card)) {
                List<String> validChars = chars.get(card);
                password.append(validChars.get(RAND.nextInt(validChars.size())));
                break;
            }
        }
    }
    if (password.length() < minLen) {
        result.recordFatalError("Unable to generate value for " + getPath() + " and meet minimal size of " + getPath() + ". Actual lenght: " + password.length() + ", required: " + minLen);
        LOGGER.trace("Unable to generate value for " + getPath() + " and meet minimal size of " + getPath() + ". Actual lenght: {}, required: {}", password.length(), minLen);
        return null;
    }
    result.recordSuccess();
    // Shuffle output to solve pattern like output
    StrBuilder sb = new StrBuilder(password.substring(0, 1));
    List<String> shuffleBuffer = StringPolicyUtils.stringTokenizer(password.substring(1));
    Collections.shuffle(shuffleBuffer);
    sb.appendAll(shuffleBuffer);
    return sb.toString();
}
Also used : HashMap(java.util.HashMap) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) StringLimitType(com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType) ArrayList(java.util.ArrayList) List(java.util.List) StrBuilder(org.apache.commons.lang.text.StrBuilder)

Example 4 with StringLimitType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType in project midpoint by Evolveum.

the class TestPasswordPolicy method testPasswordGeneratorComplexNegative.

@Test
public void testPasswordGeneratorComplexNegative() throws Exception {
    final String TEST_NAME = "testPasswordGeneratorComplexNegative";
    TestUtil.displayTestTile(TEST_NAME);
    Task task = createTask(TEST_NAME);
    OperationResult result = task.getResult();
    File file = new File(TEST_DIR, "password-policy-complex.xml");
    ValuePolicyType pp = (ValuePolicyType) PrismTestUtil.parseObject(file).asObjectable();
    // Make switch some cosistency
    pp.getStringPolicy().getLimitations().setMinLength(2);
    pp.getStringPolicy().getLimitations().setMinUniqueChars(5);
    // WHEN
    TestUtil.displayWhen(TEST_NAME);
    String psswd = valuePolicyProcessor.generate(SchemaConstants.PATH_PASSWORD_VALUE, pp.getStringPolicy(), 10, null, TEST_NAME, task, result);
    // THEN
    TestUtil.displayThen(TEST_NAME);
    display("Generated password", psswd);
    result.computeStatus();
    AssertJUnit.assertTrue(result.isAcceptable());
    assertNotNull(psswd);
    // Switch to all must be first :-) to test if there is error
    for (StringLimitType l : pp.getStringPolicy().getLimitations().getLimit()) {
        l.setMustBeFirst(true);
    }
    LOGGER.info("Negative testing: passwordGeneratorComplexTest");
    try {
        valuePolicyProcessor.generate(SchemaConstants.PATH_PASSWORD_VALUE, pp.getStringPolicy(), 10, null, TEST_NAME, task, result);
        assertNotReached();
    } catch (ExpressionEvaluationException e) {
        result.computeStatus();
        TestUtil.assertFailure(result);
    }
}
Also used : StringLimitType(com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType) Task(com.evolveum.midpoint.task.api.Task) ExpressionEvaluationException(com.evolveum.midpoint.util.exception.ExpressionEvaluationException) ValuePolicyType(com.evolveum.midpoint.xml.ns._public.common.common_3.ValuePolicyType) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) File(java.io.File) Test(org.testng.annotations.Test) AbstractInternalModelIntegrationTest(com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest)

Aggregations

OperationResult (com.evolveum.midpoint.schema.result.OperationResult)4 StringLimitType (com.evolveum.midpoint.xml.ns._public.common.common_3.StringLimitType)4 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 AbstractInternalModelIntegrationTest (com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest)1 Task (com.evolveum.midpoint.task.api.Task)1 ExpressionEvaluationException (com.evolveum.midpoint.util.exception.ExpressionEvaluationException)1 LimitationsType (com.evolveum.midpoint.xml.ns._public.common.common_3.LimitationsType)1 ValuePolicyType (com.evolveum.midpoint.xml.ns._public.common.common_3.ValuePolicyType)1 File (java.io.File)1 HashSet (java.util.HashSet)1 StrBuilder (org.apache.commons.lang.text.StrBuilder)1 Test (org.testng.annotations.Test)1