001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: package com.sshtools.daemon.authentication;
027:
028: import com.sshtools.common.configuration.*;
029:
030: import com.sshtools.daemon.configuration.*;
031: import com.sshtools.daemon.platform.*;
032:
033: import com.sshtools.j2ssh.authentication.*;
034: import com.sshtools.j2ssh.configuration.*;
035: import com.sshtools.j2ssh.io.*;
036: import com.sshtools.j2ssh.transport.publickey.*;
037:
038: import org.apache.commons.logging.*;
039:
040: import java.io.*;
041:
042: import java.util.*;
043:
044: /**
045: *
046: *
047: * @author $author$
048: * @version $Revision: 1.14 $
049: */
050: public class AuthorizationFileVerification implements
051: PublicKeyVerification {
052: private static Log log = LogFactory
053: .getLog(AuthorizationFileVerification.class);
054:
055: /**
056: *
057: *
058: * @param username
059: * @param algorithm
060: * @param encoded
061: * @param service
062: * @param sessionId
063: * @param signature
064: *
065: * @return
066: *
067: * @throws IOException
068: */
069: public boolean verifyKeySignature(String username,
070: String algorithm, byte[] encoded, String service,
071: byte[] sessionId, byte[] signature) throws IOException {
072: try {
073: SshPublicKey key = getAuthorizedKey(username, algorithm,
074: encoded);
075: ByteArrayWriter data = new ByteArrayWriter();
076: data.writeBinaryString(sessionId);
077: data.write(SshMsgUserAuthRequest.SSH_MSG_USERAUTH_REQUEST);
078: data.writeString(username);
079: data.writeString(service);
080: data.writeString("publickey");
081: data.write(1);
082: data.writeString(key.getAlgorithmName());
083: data.writeBinaryString(key.getEncoded());
084:
085: if (key.verifySignature(signature, data.toByteArray())) {
086: return true;
087: }
088: } catch (IOException ex) {
089: }
090:
091: return false;
092: }
093:
094: private SshPublicKey getAuthorizedKey(String username,
095: String algorithm, byte[] encoded) throws IOException {
096: NativeAuthenticationProvider provider = NativeAuthenticationProvider
097: .getInstance();
098: String userHome = provider.getHomeDirectory(username); //, nativeSettings);
099:
100: if (userHome == null) {
101: log.warn("There is no home directory for " + username
102: + " is available");
103: }
104:
105: // Replace '\' with '/' because when we use it in String.replaceAll
106: // for some reason it removes them?
107: if (userHome != null) {
108: userHome = userHome.replace('\\', '/');
109: }
110:
111: ServerConfiguration config = (ServerConfiguration) ConfigurationLoader
112: .getConfiguration(ServerConfiguration.class);
113: String authorizationFile;
114: String userConfigDir = config.getUserConfigDirectory();
115:
116: // First replace any '\' with '/' (Becasue replaceAll removes them!)
117: userConfigDir = userConfigDir.replace('\\', '/');
118:
119: // Replace any home directory tokens
120: if ((userConfigDir.indexOf("%D") > -1) && (userHome == null)) {
121: throw new IOException(
122: "<UserConfigDirectory> requires home directory, but none available for "
123: + username);
124: }
125:
126: int idx = 0;
127:
128: while ((idx = userConfigDir.indexOf("%D", idx + 1)) > -1) {
129: StringBuffer buf = new StringBuffer(userConfigDir);
130: buf = buf.replace(idx, idx + 1, userHome);
131: userConfigDir = buf.toString();
132: }
133:
134: idx = 0;
135:
136: while ((idx = userConfigDir.indexOf("%U", idx + 1)) > -1) {
137: StringBuffer buf = new StringBuffer(userConfigDir);
138: buf = buf.replace(idx, idx + 1, username);
139: userConfigDir = buf.toString();
140: }
141:
142: // Replace the '/' with File.seperator and trim
143: userConfigDir = userConfigDir.replace('/', File.separatorChar)
144: .trim();
145:
146: if (!userConfigDir.endsWith(File.separator)) {
147: userConfigDir += File.separator;
148: }
149:
150: authorizationFile = userConfigDir
151: + config.getAuthorizationFile();
152:
153: // Load the authorization file
154: File file = new File(authorizationFile);
155:
156: if (!file.exists()) {
157: log.info("authorizationFile: " + authorizationFile
158: + " does not exist.");
159: throw new IOException("authorizationFile: "
160: + authorizationFile + " does not exist.");
161: }
162:
163: FileInputStream in = new FileInputStream(file);
164: Authorization keys;
165:
166: try {
167: keys = new Authorization(in);
168: } catch (Exception e) {
169: throw new AuthenticationProtocolException(
170: "Failed to load authorized keys file "
171: + authorizationFile);
172: }
173:
174: // SshPublicKey key = SshPublicKeyFile.parse(encoded);
175: Iterator it = keys.getAuthorizedKeys().iterator();
176: SshKeyPair pair = SshKeyPairFactory.newInstance(algorithm);
177: SshPublicKey authorizedKey = null;
178: SshPublicKey key = pair.decodePublicKey(encoded);
179: boolean valid = false;
180: String keyfile;
181:
182: while (it.hasNext()) {
183: keyfile = (String) it.next();
184:
185: // Look for the file in the user config dir first
186: file = new File(userConfigDir + keyfile);
187:
188: // If it does not exist then look absolute
189: if (!file.exists()) {
190: file = new File(keyfile);
191: }
192:
193: if (file.exists()) {
194: // Try to open the public key in the default file format
195: // otherwise attempt the supported key formats
196: SshPublicKeyFile pkf = SshPublicKeyFile.parse(file);
197: authorizedKey = pkf.toPublicKey();
198:
199: if (authorizedKey.equals(key)) {
200: return authorizedKey;
201: }
202: } else {
203: log.info("Failed attempt to load key file " + keyfile);
204: }
205: }
206:
207: throw new IOException("");
208: }
209:
210: /**
211: *
212: *
213: * @param username
214: * @param algorithm
215: * @param encoded
216: *
217: * @return
218: *
219: * @throws IOException
220: */
221: public boolean acceptKey(String username, String algorithm,
222: byte[] encoded) throws IOException {
223: try {
224: getAuthorizedKey(username, algorithm, encoded);
225:
226: return true;
227: } catch (Exception ex) {
228: return false;
229: }
230: }
231: }
|