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 static org.forgerock.opendj.ldap.LDAPConnectionFactory.SSL_USE_STARTTLS; 036import static org.forgerock.opendj.ldap.LDAPConnectionFactory.SSL_CONTEXT; 037 038 039import java.security.GeneralSecurityException; 040 041import javax.net.ssl.SSLContext; 042 043import org.forgerock.opendj.ldap.Connection; 044import org.forgerock.opendj.ldap.LdapException; 045import org.forgerock.opendj.ldap.LDAPConnectionFactory; 046import org.forgerock.opendj.ldap.ResultCode; 047import org.forgerock.opendj.ldap.SSLContextBuilder; 048import org.forgerock.opendj.ldap.TrustManagers; 049import org.forgerock.opendj.ldap.requests.PlainSASLBindRequest; 050import org.forgerock.opendj.ldap.requests.Requests; 051import org.forgerock.util.Options; 052 053/** 054 * An example client application which performs SASL PLAIN authentication to a 055 * directory server over LDAP with StartTLS. This example takes the following 056 * command line parameters: 057 * <ul> 058 * <li>host - host name of the directory server</li> 059 * <li>port - port number of the directory server for StartTLS</li> 060 * <li>authzid - (Optional) Authorization identity</li> 061 * <li>authcid - Authentication identity</li> 062 * <li>passwd - Password of the user to authenticate</li> 063 * </ul> 064 * The host, port, authcid, and passwd are required. SASL PLAIN is described in 065 * <a href="http://www.ietf.org/rfc/rfc4616.txt">RFC 4616</a>. 066 * <p> 067 * The authzid and authcid are prefixed as described in <a 068 * href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513, section 069 * 5.2.1.8</a>, with "dn:" if you pass in a distinguished name, or with "u:" if 070 * you pass in a user ID. 071 * <p> 072 * By default, OpenDJ is set up for SASL PLAIN to use the Exact Match Identity 073 * Mapper to find entries by searching uid values for the user ID. In other 074 * words, the following examples are equivalent. 075 * 076 * <pre> 077 * dn:uid=bjensen,ou=people,dc=example,dc=com 078 * u:bjensen 079 * </pre> 080 */ 081public final class SASLAuth { 082 /** 083 * Authenticate to the directory using SASL PLAIN. 084 * 085 * @param args 086 * The command line arguments 087 */ 088 public static void main(String[] args) { 089 parseArgs(args); 090 Connection connection = null; 091 092 // --- JCite --- 093 try { 094 final LDAPConnectionFactory factory = 095 new LDAPConnectionFactory(host, port, getTrustAllOptions()); 096 connection = factory.getConnection(); 097 PlainSASLBindRequest request = 098 Requests.newPlainSASLBindRequest(authcid, passwd.toCharArray()) 099 .setAuthorizationID(authzid); 100 connection.bind(request); 101 System.out.println("Authenticated as " + authcid + "."); 102 } catch (final LdapException e) { 103 System.err.println(e.getMessage()); 104 System.exit(e.getResult().getResultCode().intValue()); 105 return; 106 } catch (final GeneralSecurityException e) { 107 System.err.println(e.getMessage()); 108 System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue()); 109 } finally { 110 if (connection != null) { 111 connection.close(); 112 } 113 } 114 // --- JCite --- 115 } 116 117 /** 118 * For StartTLS the connection factory needs SSL context options. In the 119 * general case, a trust manager in the SSL context serves to check server 120 * certificates, and a key manager handles client keys when the server 121 * checks certificates from our client. 122 * 123 * OpenDJ directory server lets you install by default with a self-signed 124 * certificate that is not in the system trust store. To simplify this 125 * implementation trusts all server certificates. 126 */ 127 private static Options getTrustAllOptions() throws GeneralSecurityException { 128 Options options = Options.defaultOptions(); 129 SSLContext sslContext = 130 new SSLContextBuilder().setTrustManager(TrustManagers.trustAll()).getSSLContext(); 131 options.set(SSL_CONTEXT, sslContext); 132 options.set(SSL_USE_STARTTLS, true); 133 return options; 134 } 135 136 private static String host; 137 private static int port; 138 private static String authzid; 139 private static String authcid; 140 private static String passwd; 141 142 /** 143 * Parse command line arguments. 144 * 145 * @param args 146 * host port [authzid] authcid passwd 147 */ 148 private static void parseArgs(String[] args) { 149 if (args.length < 4 || args.length > 5) { 150 giveUp(); 151 } 152 153 host = args[0]; 154 port = Integer.parseInt(args[1]); 155 156 if (args.length == 5) { 157 authzid = args[2]; 158 authcid = args[3]; 159 passwd = args[4]; 160 } else { 161 authzid = null; 162 authcid = args[2]; 163 passwd = args[3]; 164 } 165 } 166 167 private static void giveUp() { 168 printUsage(); 169 System.exit(1); 170 } 171 172 private static void printUsage() { 173 System.err.println("Usage: host port [authzid] authcid passwd"); 174 System.err.println("\tThe port must be able to handle LDAP with StartTLS."); 175 System.err.println("\tSee http://www.ietf.org/rfc/rfc4616.txt for more on SASL PLAIN."); 176 } 177 178 private SASLAuth() { 179 // Not used. 180 } 181}