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