mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
2 days ago 458f009de6ccb989ac565da62ac407f20755303e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions copyright [year] [name of copyright owner]".
 *
 * Copyright 2026 3A Systems, LLC.
 */
package com.forgerock.opendj.ldap.tools;
 
import static com.forgerock.opendj.ldap.tools.ToolsMessages.ERR_TOOL_INVALID_CONTROL_STRING;
import static com.forgerock.opendj.util.OperatingSystem.isWindows;
import static org.fest.assertions.Assertions.assertThat;
import static org.testng.Assert.fail;
 
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
 
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.controls.Control;
import org.forgerock.testng.ForgeRockTestCase;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
 
import com.forgerock.opendj.cli.CommonArguments;
import com.forgerock.opendj.cli.StringArgument;
 
/** Tests the parsing of the {@code -J/--control} argument by {@link Utils#readControls(StringArgument)}. */
@Test
public final class ControlArgumentTestCase extends ForgeRockTestCase {
 
    @DataProvider
    public Object[][] validControls() {
        return new Object[][] {
            { "1.2.3.4", "1.2.3.4", false, null },
            { "1.2.3.4:true", "1.2.3.4", true, null },
            { "1.2.3.4:FALSE:value", "1.2.3.4", false, "value" },
            { "1.2.3.4:true:", "1.2.3.4", true, "" },
            { "pwpolicy:true", "1.3.6.1.4.1.42.2.27.8.5.1", true, null },
            // Everything after the second colon is the value, colons included.
            { "2.16.840.1.113730.3.4.18:true:dn:uid=bjensen,ou=People,dc=example,dc=com",
              "2.16.840.1.113730.3.4.18", true, "dn:uid=bjensen,ou=People,dc=example,dc=com" },
            { "2.16.840.1.113730.3.4.18:true:u:bjensen", "2.16.840.1.113730.3.4.18", true, "u:bjensen" },
            { "1.2.3.4:false:urn:example:value", "1.2.3.4", false, "urn:example:value" },
            { "1.2.3.4:false:ldap://host:1389/dc=example", "1.2.3.4", false, "ldap://host:1389/dc=example" },
            // The base64 form decodes to a value that can itself hold colons.
            { "1.2.3.4:true::" + base64("dn:uid=bjensen"), "1.2.3.4", true, "dn:uid=bjensen" },
            { "1.2.3.4:true::", "1.2.3.4", true, "" },
        };
    }
 
    @Test(dataProvider = "validControls")
    public void testValidControl(final String argument, final String oid, final boolean critical,
            final String value) throws Exception {
        final Control control = readSingleControl(argument);
        assertThat(control.getOID()).isEqualTo(oid);
        assertThat(control.isCritical()).isEqualTo(critical);
        if (value == null) {
            assertThat(control.hasValue()).isFalse();
        } else {
            assertThat(control.hasValue()).isTrue();
            assertThat(control.getValue().toString()).isEqualTo(value);
        }
    }
 
    @Test
    public void testValueReadFromFileWhosePathHoldsAColon() throws Exception {
        // On Windows the drive letter puts a colon in every absolute path; elsewhere the file name carries one.
        final File dir = Files.createTempDirectory("control-value").toFile();
        final File file = new File(dir, isWindows() ? "control-value.ber" : "control:value.ber");
        try {
            final byte[] bytes = { 0x04, 0x03, 'a', ':', 'b' };
            Files.write(file.toPath(), bytes);
 
            final Control control = readSingleControl("1.2.3.4:true:<" + file.getAbsolutePath());
            assertThat(control.getOID()).isEqualTo("1.2.3.4");
            assertThat(control.isCritical()).isTrue();
            assertThat(control.getValue()).isEqualTo(ByteString.wrap(bytes));
        } finally {
            file.delete();
            dir.delete();
        }
    }
 
    @DataProvider
    public Object[][] invalidControls() {
        final String missingFile = new File(System.getProperty("java.io.tmpdir"), "no-such-dir-1156/value.ber")
                .getAbsolutePath();
        return new Object[][] {
            { "1.2.3.4:invalidcriticality" },
            { "1.2.3.4:invalidcriticality:value" },
            { "1.2.3.4:true:<" + missingFile },
            { "1.2.3.4:true::not*base64" },
        };
    }
 
    @Test(dataProvider = "invalidControls")
    public void testInvalidControlIsReportedAsAnInvalidControlString(final String argument) throws Exception {
        try {
            readControls(argument);
            fail("Expected the control '" + argument + "' to be rejected");
        } catch (final LDAPToolException e) {
            assertThat(e.getResultCode()).isEqualTo(ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue());
            assertThat(e.getMessage()).isEqualTo(ERR_TOOL_INVALID_CONTROL_STRING.get(argument).toString());
        }
    }
 
    private static Control readSingleControl(final String argument) throws Exception {
        final List<Control> controls = readControls(argument);
        assertThat(controls).hasSize(1);
        return controls.get(0);
    }
 
    private static List<Control> readControls(final String argument) throws Exception {
        final StringArgument controlArg = CommonArguments.controlArgument();
        controlArg.addValue(argument);
        controlArg.setPresent(true);
        return Utils.readControls(controlArg);
    }
 
    private static String base64(final String value) {
        return ByteString.valueOfBytes(value.getBytes(StandardCharsets.UTF_8)).toBase64String();
    }
}