001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2011-2015 ForgeRock AS. 025 */ 026 027/** 028 * An example client application which performs SASL authentication to a 029 * directory server, displays a result, and closes the connection. 030 * 031 * Set up StartTLS before using this example. 032 */ 033package org.forgerock.opendj.examples; 034 035import java.security.GeneralSecurityException; 036 037import javax.net.ssl.SSLContext; 038 039import org.forgerock.opendj.ldap.Connection; 040import org.forgerock.opendj.ldap.LdapException; 041import org.forgerock.opendj.ldap.LDAPConnectionFactory; 042import org.forgerock.opendj.ldap.LDAPOptions; 043import org.forgerock.opendj.ldap.ResultCode; 044import org.forgerock.opendj.ldap.SSLContextBuilder; 045import org.forgerock.opendj.ldap.TrustManagers; 046import org.forgerock.opendj.ldap.requests.PlainSASLBindRequest; 047import org.forgerock.opendj.ldap.requests.Requests; 048 049/** 050 * An example client application which performs SASL PLAIN authentication to a 051 * directory server over LDAP with StartTLS. This example takes the following 052 * command line parameters: 053 * <ul> 054 * <li>host - host name of the directory server</li> 055 * <li>port - port number of the directory server for StartTLS</li> 056 * <li>authzid - (Optional) Authorization identity</li> 057 * <li>authcid - Authentication identity</li> 058 * <li>passwd - Password of the user to authenticate</li> 059 * </ul> 060 * The host, port, authcid, and passwd are required. SASL PLAIN is described in 061 * <a href="http://www.ietf.org/rfc/rfc4616.txt">RFC 4616</a>. 062 * <p> 063 * The authzid and authcid are prefixed as described in <a 064 * href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513, section 065 * 5.2.1.8</a>, with "dn:" if you pass in a distinguished name, or with "u:" if 066 * you pass in a user ID. 067 * <p> 068 * By default, OpenDJ is set up for SASL PLAIN to use the Exact Match Identity 069 * Mapper to find entries by searching uid values for the user ID. In other 070 * words, the following examples are equivalent. 071 * 072 * <pre> 073 * dn:uid=bjensen,ou=people,dc=example,dc=com 074 * u:bjensen 075 * </pre> 076 */ 077public final class SASLAuth { 078 /** 079 * Authenticate to the directory using SASL PLAIN. 080 * 081 * @param args 082 * The command line arguments 083 */ 084 public static void main(String[] args) { 085 parseArgs(args); 086 Connection connection = null; 087 088 // --- JCite --- 089 try { 090 final LDAPConnectionFactory factory = 091 new LDAPConnectionFactory(host, port, getTrustAllOptions()); 092 connection = factory.getConnection(); 093 PlainSASLBindRequest request = 094 Requests.newPlainSASLBindRequest(authcid, passwd.toCharArray()) 095 .setAuthorizationID(authzid); 096 connection.bind(request); 097 System.out.println("Authenticated as " + authcid + "."); 098 } catch (final LdapException e) { 099 System.err.println(e.getMessage()); 100 System.exit(e.getResult().getResultCode().intValue()); 101 return; 102 } catch (final GeneralSecurityException e) { 103 System.err.println(e.getMessage()); 104 System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue()); 105 } finally { 106 if (connection != null) { 107 connection.close(); 108 } 109 } 110 // --- JCite --- 111 } 112 113 /** 114 * For StartTLS the connection factory needs SSL context options. In the 115 * general case, a trust manager in the SSL context serves to check server 116 * certificates, and a key manager handles client keys when the server 117 * checks certificates from our client. 118 * 119 * OpenDJ directory server lets you install by default with a self-signed 120 * certificate that is not in the system trust store. To simplify this 121 * implementation trusts all server certificates. 122 */ 123 private static LDAPOptions getTrustAllOptions() throws GeneralSecurityException { 124 LDAPOptions lo = new LDAPOptions(); 125 SSLContext sslContext = 126 new SSLContextBuilder().setTrustManager(TrustManagers.trustAll()).getSSLContext(); 127 lo.setSSLContext(sslContext); 128 lo.setUseStartTLS(true); 129 return lo; 130 } 131 132 private static String host; 133 private static int port; 134 private static String authzid; 135 private static String authcid; 136 private static String passwd; 137 138 /** 139 * Parse command line arguments. 140 * 141 * @param args 142 * host port [authzid] authcid passwd 143 */ 144 private static void parseArgs(String[] args) { 145 if (args.length < 4 || args.length > 5) { 146 giveUp(); 147 } 148 149 host = args[0]; 150 port = Integer.parseInt(args[1]); 151 152 if (args.length == 5) { 153 authzid = args[2]; 154 authcid = args[3]; 155 passwd = args[4]; 156 } else { 157 authzid = null; 158 authcid = args[2]; 159 passwd = args[3]; 160 } 161 } 162 163 private static void giveUp() { 164 printUsage(); 165 System.exit(1); 166 } 167 168 private static void printUsage() { 169 System.err.println("Usage: host port [authzid] authcid passwd"); 170 System.err.println("\tThe port must be able to handle LDAP with StartTLS."); 171 System.err.println("\tSee http://www.ietf.org/rfc/rfc4616.txt for more on SASL PLAIN."); 172 } 173 174 private SASLAuth() { 175 // Not used. 176 } 177}