001/* 002 * Copyright 2019-2022 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2019-2022 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-2022 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 return new SCRAMSHA512BindRequest(getUsername(), getPasswordBytes(), 182 controls); 183 } 184 185 186 187 /** 188 * {@inheritDoc} 189 */ 190 @Override() 191 public void toString(@NotNull final StringBuilder buffer) 192 { 193 buffer.append("SCRAMSHA512BindRequest(username='"); 194 buffer.append(getUsername()); 195 buffer.append('\''); 196 197 final Control[] controls = getControls(); 198 if (controls.length > 0) 199 { 200 buffer.append(", controls={"); 201 for (int i=0; i < controls.length; i++) 202 { 203 if (i > 0) 204 { 205 buffer.append(", "); 206 } 207 208 buffer.append(controls[i]); 209 } 210 buffer.append('}'); 211 } 212 213 buffer.append(')'); 214 } 215 216 217 218 /** 219 * {@inheritDoc} 220 */ 221 @Override() 222 public void toCode(@NotNull final List<String> lineList, 223 @NotNull final String requestID, 224 final int indentSpaces, final boolean includeProcessing) 225 { 226 // Create the request variable. 227 final List<ToCodeArgHelper> constructorArgs = new ArrayList<>(4); 228 constructorArgs.add(ToCodeArgHelper.createString(getUsername(), 229 "Username")); 230 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 231 "Password")); 232 233 final Control[] controls = getControls(); 234 if (controls.length > 0) 235 { 236 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 237 "Bind Controls")); 238 } 239 240 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 241 "SCRAMSHA512BindRequest", requestID + "Request", 242 "new SCRAMSHA512BindRequest", constructorArgs); 243 244 245 // Add lines for processing the request and obtaining the result. 246 if (includeProcessing) 247 { 248 // Generate a string with the appropriate indent. 249 final StringBuilder buffer = new StringBuilder(); 250 for (int i=0; i < indentSpaces; i++) 251 { 252 buffer.append(' '); 253 } 254 final String indent = buffer.toString(); 255 256 lineList.add(""); 257 lineList.add(indent + "try"); 258 lineList.add(indent + '{'); 259 lineList.add(indent + " BindResult " + requestID + 260 "Result = connection.bind(" + requestID + "Request);"); 261 lineList.add(indent + " // The bind was processed successfully."); 262 lineList.add(indent + '}'); 263 lineList.add(indent + "catch (LDAPException e)"); 264 lineList.add(indent + '{'); 265 lineList.add(indent + " // The bind failed. Maybe the following will " + 266 "help explain why."); 267 lineList.add(indent + " // Note that the connection is now likely in " + 268 "an unauthenticated state."); 269 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 270 lineList.add(indent + " String message = e.getMessage();"); 271 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 272 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 273 lineList.add(indent + " Control[] responseControls = " + 274 "e.getResponseControls();"); 275 lineList.add(indent + '}'); 276 } 277 } 278}