001/* 002 * Copyright 2011-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2011-2017 UnboundID Corp. 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.io.File; 026import java.io.FileInputStream; 027import java.io.Serializable; 028import java.util.Arrays; 029 030import com.unboundid.util.Debug; 031import com.unboundid.util.StaticUtils; 032import com.unboundid.util.ThreadSafety; 033import com.unboundid.util.ThreadSafetyLevel; 034import com.unboundid.util.Validator; 035 036import static com.unboundid.ldap.sdk.LDAPMessages.*; 037 038 039 040/** 041 * This class provides an implementation of a password provider that will obtain 042 * the password from a specified file. All bytes up to (but not including) the 043 * first end-of-line character (or to the end of the file if it does not contain 044 * an end-of-line character) will be considered part of the password. 045 */ 046@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 047public final class ReadFromFilePasswordProvider 048 extends PasswordProvider 049 implements Serializable 050{ 051 /** 052 * The serial version UID for this serializable file. 053 */ 054 private static final long serialVersionUID = -3343425971796985100L; 055 056 057 058 // The password file to use. 059 private final File passwordFile; 060 061 062 063 /** 064 * Creates a new instance of this password provider that will read passwords 065 * from the specified file. 066 * 067 * @param passwordFile The path to the file containing the password to use. 068 * It must not be {@code null}. 069 */ 070 public ReadFromFilePasswordProvider(final String passwordFile) 071 { 072 Validator.ensureNotNull(passwordFile); 073 074 this.passwordFile = new File(passwordFile); 075 } 076 077 078 079 /** 080 * Creates a new instance of this password provider that will read passwords 081 * from the specified file. 082 * 083 * @param passwordFile The file containing the password to use. It must not 084 * be {@code null}. 085 */ 086 public ReadFromFilePasswordProvider(final File passwordFile) 087 { 088 Validator.ensureNotNull(passwordFile); 089 090 this.passwordFile = passwordFile; 091 } 092 093 094 095 /** 096 * Retrieves a password in a newly-created byte array. Once the password is 097 * no longer required, the contents of the array will be overwritten so that 098 * the password is no longer contained in memory. 099 * 100 * @return A byte array containing the password that should be used. 101 * 102 * @throws LDAPException If a problem is encountered while attempting to 103 * obtain the password. 104 */ 105 @Override() 106 public byte[] getPasswordBytes() 107 throws LDAPException 108 { 109 byte[] pwBytes = null; 110 111 try 112 { 113 final int fileLength = (int) passwordFile.length(); 114 pwBytes = new byte[fileLength]; 115 116 final FileInputStream inputStream = new FileInputStream(passwordFile); 117 118 try 119 { 120 int pos = 0; 121 while (pos < fileLength) 122 { 123 final int bytesRead = 124 inputStream.read(pwBytes, pos, pwBytes.length - pos); 125 if (bytesRead < 0) 126 { 127 break; 128 } 129 130 pos += bytesRead; 131 } 132 } 133 finally 134 { 135 inputStream.close(); 136 } 137 138 // If there is an end-of-line marker before the end of the file, then 139 // create a password only up to that point and zero out the current array. 140 for (int i=0; i < pwBytes.length; i++) 141 { 142 if ((pwBytes[i] == '\n') || (pwBytes[i] == '\r')) 143 { 144 final byte[] pwWithoutEOL = new byte[i]; 145 System.arraycopy(pwBytes, 0, pwWithoutEOL, 0, i); 146 Arrays.fill(pwBytes, (byte) 0x00); 147 pwBytes = pwWithoutEOL; 148 break; 149 } 150 } 151 } 152 catch (final Exception e) 153 { 154 Debug.debugException(e); 155 156 if (pwBytes != null) 157 { 158 Arrays.fill(pwBytes, (byte) 0x00); 159 } 160 161 throw new LDAPException(ResultCode.LOCAL_ERROR, 162 ERR_FILE_PW_PROVIDER_ERROR_READING_PW.get( 163 passwordFile.getAbsolutePath(), 164 StaticUtils.getExceptionMessage(e)), 165 e); 166 } 167 168 if (pwBytes.length == 0) 169 { 170 throw new LDAPException(ResultCode.PARAM_ERROR, 171 ERR_FILE_PW_PROVIDER_EMPTY_PW.get(passwordFile.getAbsolutePath())); 172 } 173 174 return pwBytes; 175 } 176}