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