NationalSecurityAgency/ghidra · error · GeneralSecurityException

Distinguished name required (dn="..")

Error message

Distinguished name required (dn="..")

What it means

Thrown by addUserCommand() when host authentication is PKI but either distinguishedName or commonName is null. Adding a user to a PKI-secured server requires a DN (and its extracted CN) so the certificate identity can be mapped to the new role in pg_ident.conf.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java:1144

			true);
		FileUtilities.copyFile(copyFile, identFile, false, null);
	}

	/**
	 * Add a new user to the currently running server on the local host.
	 * A connection is established, using the local interface, and the "CREATE ROLE" command
	 * is executed. If the server is configured to require certificate authentication on
	 * remote connections, the user must have provided a distinguished name associated with
	 * the certificate, which is then mapped to the new username. 
	 * @throws GeneralSecurityException if using PKI and no Distinguished Name is found
	 * @throws Exception if there's a problem initializing the Application of discovering the Postgres installation
	 */
	private void addUserCommand() throws GeneralSecurityException, Exception {
		discoverPostgresInstall();
		initializeDataDirectory();			// Needed to pick up authentication settings
		if (hostAuthentication == AUTHENTICATION_PKI) {
			if (distinguishedName == null || commonName == null) {
				throw new GeneralSecurityException("Distinguished name required (dn=\"..\")");
			}
		}
		StringBuilder resultMessage = new StringBuilder();
		resultMessage.append("Added user: ");
		resultMessage.append(specifiedUserName);
		boolean resetPassword = (hostAuthentication == AUTHENTICATION_PASSWORD);

		adminPasswordData = null;

		localConnection = getOrCreateLocalConnection();

		StringBuilder buffer = new StringBuilder();
		buffer.append("CREATE ROLE ");
		Utils.escapeIdentifier(buffer, specifiedUserName);
		buffer.append(" WITH LOGIN");

		try (Statement st = localConnection.createStatement()) {
			st.executeUpdate(buffer.toString());

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Pass `--dn "CN=<common name>"` on the adduser command.
  2. Ensure the DN includes a CN RDN that matches the client certificate.
  3. Confirm the CN maps to the new role via the mymap identity map.
  4. If PKI is not in use, verify the server's actual auth mode with `bsim_ctl status`.

Example fix

// before
bsim_ctl adduser alice admin
// after
bsim_ctl adduser --dn "CN=alice" alice admin
Defensive patterns

Strategy: validation

Validate before calling

if (hostAuthIsPki && (dn == null || !dn.contains("CN="))) {
    throw new IllegalArgumentException(
        "--dn \"CN=...\" is required when adding a user to a PKI-secured server");
}

Type guard

public boolean dnReadyForPkiAdduser(String dn) {
    if (dn == null) return false;
    try { return new LdapName(dn).getRdns().stream()
            .anyMatch(r -> "CN".equalsIgnoreCase(r.getType())); }
    catch (Exception e) { return false; }
}

Try / catch

try {
    bsimControl.adduser(args);
} catch (GeneralSecurityException e) {
    if ("Distinguished name required (dn=\"..\")".equals(e.getMessage())) {
        throw new UserFacingException("Add --dn \"CN=<name>\" for PKI adduser", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Running `bsim_ctl adduser <name> <priv>` against a server configured with `--auth cert`, without supplying `--dn "CN=..."`, or supplying a DN with no CN RDN so commonName extraction failed.

Common situations: Forgetting --dn on adduser; malformed DN string; CN component missing from the DN; assuming the DN from server init carries over to the adduser invocation (each invocation parses its own args).

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/b7873e4caca7b9be. Report an issue: GitHub.