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