001/* 002 * Copyright 2019-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2019-2020 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-2020 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.ThreadSafety; 045import com.unboundid.util.ThreadSafetyLevel; 046 047 048 049/** 050 * This class provides an implementation of the SCRAM-SHA-512 SASL mechanism, 051 * which is an SCRAM mechanism that uses a SHA-512 digest algorithm and an 052 * HmacSHA512 MAC algorithm. 053 */ 054@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 055public final class SCRAMSHA512BindRequest 056 extends SCRAMBindRequest 057{ 058 /** 059 * The serial version UID for this serializable class. 060 */ 061 private static final long serialVersionUID = -4396660110665214258L; 062 063 064 065 /** 066 * Creates a new SCRAM-SHA-512 bind request with the provided information. 067 * 068 * @param username The username for this bind request. It must not be {@code 069 * null} or empty. 070 * @param password The password for this bind request. It must not be {@code 071 * null} or empty. 072 * @param controls The set of controls to include in the bind request. It may 073 * be {@code null} or empty if no controls are needed. 074 */ 075 public SCRAMSHA512BindRequest(final String username, final String password, 076 final Control... controls) 077 { 078 super(username, new ASN1OctetString(password), controls); 079 } 080 081 082 083 /** 084 * Creates a new SCRAM-SHA-512 bind request with the provided information. 085 * 086 * @param username The username for this bind request. It must not be {@code 087 * null} or empty. 088 * @param password The password for this bind request. It must not be {@code 089 * null} or empty. 090 * @param controls The set of controls to include in the bind request. It may 091 * be {@code null} or empty if no controls are needed. 092 */ 093 public SCRAMSHA512BindRequest(final String username, final byte[] password, 094 final Control... controls) 095 { 096 super(username, new ASN1OctetString(password), controls); 097 } 098 099 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override() 105 public String getSASLMechanismName() 106 { 107 return "SCRAM-SHA-512"; 108 } 109 110 111 112 /** 113 * {@inheritDoc} 114 */ 115 @Override() 116 protected String getDigestAlgorithmName() 117 { 118 return "SHA-512"; 119 } 120 121 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override() 127 protected String getMACAlgorithmName() 128 { 129 return "HmacSHA512"; 130 } 131 132 133 134 /** 135 * {@inheritDoc} 136 */ 137 @Override() 138 public SCRAMSHA512BindRequest getRebindRequest(final String host, 139 final int port) 140 { 141 return duplicate(); 142 } 143 144 145 146 /** 147 * {@inheritDoc} 148 */ 149 @Override() 150 public SCRAMSHA512BindRequest duplicate() 151 { 152 return duplicate(getControls()); 153 } 154 155 156 157 /** 158 * {@inheritDoc} 159 */ 160 @Override() 161 public SCRAMSHA512BindRequest duplicate(final Control[] controls) 162 { 163 return new SCRAMSHA512BindRequest(getUsername(), getPasswordBytes(), 164 controls); 165 } 166 167 168 169 /** 170 * {@inheritDoc} 171 */ 172 @Override() 173 public void toString(final StringBuilder buffer) 174 { 175 buffer.append("SCRAMSHA512BindRequest(username='"); 176 buffer.append(getUsername()); 177 buffer.append('\''); 178 179 final Control[] controls = getControls(); 180 if (controls.length > 0) 181 { 182 buffer.append(", controls={"); 183 for (int i=0; i < controls.length; i++) 184 { 185 if (i > 0) 186 { 187 buffer.append(", "); 188 } 189 190 buffer.append(controls[i]); 191 } 192 buffer.append('}'); 193 } 194 195 buffer.append(')'); 196 } 197 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override() 204 public void toCode(final List<String> lineList, final String requestID, 205 final int indentSpaces, final boolean includeProcessing) 206 { 207 // Create the request variable. 208 final List<ToCodeArgHelper> constructorArgs = new ArrayList<>(4); 209 constructorArgs.add(ToCodeArgHelper.createString(getUsername(), 210 "Username")); 211 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 212 "Password")); 213 214 final Control[] controls = getControls(); 215 if (controls.length > 0) 216 { 217 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 218 "Bind Controls")); 219 } 220 221 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 222 "SCRAMSHA512BindRequest", requestID + "Request", 223 "new SCRAMSHA512BindRequest", constructorArgs); 224 225 226 // Add lines for processing the request and obtaining the result. 227 if (includeProcessing) 228 { 229 // Generate a string with the appropriate indent. 230 final StringBuilder buffer = new StringBuilder(); 231 for (int i=0; i < indentSpaces; i++) 232 { 233 buffer.append(' '); 234 } 235 final String indent = buffer.toString(); 236 237 lineList.add(""); 238 lineList.add(indent + "try"); 239 lineList.add(indent + '{'); 240 lineList.add(indent + " BindResult " + requestID + 241 "Result = connection.bind(" + requestID + "Request);"); 242 lineList.add(indent + " // The bind was processed successfully."); 243 lineList.add(indent + '}'); 244 lineList.add(indent + "catch (LDAPException e)"); 245 lineList.add(indent + '{'); 246 lineList.add(indent + " // The bind failed. Maybe the following will " + 247 "help explain why."); 248 lineList.add(indent + " // Note that the connection is now likely in " + 249 "an unauthenticated state."); 250 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 251 lineList.add(indent + " String message = e.getMessage();"); 252 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 253 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 254 lineList.add(indent + " Control[] responseControls = " + 255 "e.getResponseControls();"); 256 lineList.add(indent + '}'); 257 } 258 } 259}