001/* 002 * Copyright 2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk; 022 023 024 025import java.util.ArrayList; 026import java.util.List; 027 028import com.unboundid.asn1.ASN1OctetString; 029import com.unboundid.util.ThreadSafety; 030import com.unboundid.util.ThreadSafetyLevel; 031 032 033 034/** 035 * This class provides an implementation of the SCRAM-SHA-1 SASL mechanism as 036 * described in <A HREF="http://www.ietf.org/rfc/rfc5802.txt">RFC 5802</A>. 037 */ 038@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 039public final class SCRAMSHA1BindRequest 040 extends SCRAMBindRequest 041{ 042 /** 043 * The serial version UID for this serializable class. 044 */ 045 private static final long serialVersionUID = -1807244826649889525L; 046 047 048 049 /** 050 * Creates a new SCRAM-SHA-1 bind request with the provided information. 051 * 052 * @param username The username for this bind request. It must not be {@code 053 * null} or empty. 054 * @param password The password for this bind request. It must not be {@code 055 * null} or empty. 056 * @param controls The set of controls to include in the bind request. It may 057 * be {@code null} or empty if no controls are needed. 058 */ 059 public SCRAMSHA1BindRequest(final String username, final String password, 060 final Control... controls) 061 { 062 super(username, new ASN1OctetString(password), controls); 063 } 064 065 066 067 /** 068 * Creates a new SCRAM-SHA-1 bind request with the provided information. 069 * 070 * @param username The username for this bind request. It must not be {@code 071 * null} or empty. 072 * @param password The password for this bind request. It must not be {@code 073 * null} or empty. 074 * @param controls The set of controls to include in the bind request. It may 075 * be {@code null} or empty if no controls are needed. 076 */ 077 public SCRAMSHA1BindRequest(final String username, final byte[] password, 078 final Control... controls) 079 { 080 super(username, new ASN1OctetString(password), controls); 081 } 082 083 084 085 /** 086 * {@inheritDoc} 087 */ 088 @Override() 089 public String getSASLMechanismName() 090 { 091 return "SCRAM-SHA-1"; 092 } 093 094 095 096 /** 097 * {@inheritDoc} 098 */ 099 @Override() 100 protected String getDigestAlgorithmName() 101 { 102 return "SHA-1"; 103 } 104 105 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override() 111 protected String getMACAlgorithmName() 112 { 113 return "HmacSHA1"; 114 } 115 116 117 118 /** 119 * {@inheritDoc} 120 */ 121 @Override() 122 public SCRAMSHA1BindRequest getRebindRequest(final String host, 123 final int port) 124 { 125 return duplicate(); 126 } 127 128 129 130 /** 131 * {@inheritDoc} 132 */ 133 @Override() 134 public SCRAMSHA1BindRequest duplicate() 135 { 136 return duplicate(getControls()); 137 } 138 139 140 141 /** 142 * {@inheritDoc} 143 */ 144 @Override() 145 public SCRAMSHA1BindRequest duplicate(final Control[] controls) 146 { 147 return new SCRAMSHA1BindRequest(getUsername(), getPasswordBytes(), 148 controls); 149 } 150 151 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override() 157 public void toString(final StringBuilder buffer) 158 { 159 buffer.append("SCRAMSHA1BindRequest(username='"); 160 buffer.append(getUsername()); 161 buffer.append('\''); 162 163 final Control[] controls = getControls(); 164 if (controls.length > 0) 165 { 166 buffer.append(", controls={"); 167 for (int i=0; i < controls.length; i++) 168 { 169 if (i > 0) 170 { 171 buffer.append(", "); 172 } 173 174 buffer.append(controls[i]); 175 } 176 buffer.append('}'); 177 } 178 179 buffer.append(')'); 180 } 181 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 @Override() 188 public void toCode(final List<String> lineList, final String requestID, 189 final int indentSpaces, final boolean includeProcessing) 190 { 191 // Create the request variable. 192 final List<ToCodeArgHelper> constructorArgs = new ArrayList<>(4); 193 constructorArgs.add(ToCodeArgHelper.createString(getUsername(), 194 "Username")); 195 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 196 "Password")); 197 198 final Control[] controls = getControls(); 199 if (controls.length > 0) 200 { 201 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 202 "Bind Controls")); 203 } 204 205 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 206 "SCRAMSHA1BindRequest", requestID + "Request", 207 "new SCRAMSHA1BindRequest", constructorArgs); 208 209 210 // Add lines for processing the request and obtaining the result. 211 if (includeProcessing) 212 { 213 // Generate a string with the appropriate indent. 214 final StringBuilder buffer = new StringBuilder(); 215 for (int i=0; i < indentSpaces; i++) 216 { 217 buffer.append(' '); 218 } 219 final String indent = buffer.toString(); 220 221 lineList.add(""); 222 lineList.add(indent + "try"); 223 lineList.add(indent + '{'); 224 lineList.add(indent + " BindResult " + requestID + 225 "Result = connection.bind(" + requestID + "Request);"); 226 lineList.add(indent + " // The bind was processed successfully."); 227 lineList.add(indent + '}'); 228 lineList.add(indent + "catch (LDAPException e)"); 229 lineList.add(indent + '{'); 230 lineList.add(indent + " // The bind failed. Maybe the following will " + 231 "help explain why."); 232 lineList.add(indent + " // Note that the connection is now likely in " + 233 "an unauthenticated state."); 234 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 235 lineList.add(indent + " String message = e.getMessage();"); 236 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 237 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 238 lineList.add(indent + " Control[] responseControls = " + 239 "e.getResponseControls();"); 240 lineList.add(indent + '}'); 241 } 242 } 243}