/* * Copyright 2012 aquenos GmbH. * All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html. */ package com.aquenos.scm.ssh.auth; import java.io.IOException; import java.io.StringReader; import java.security.PublicKey; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPublicKey; import java.util.List; import sonia.scm.user.User; import sonia.scm.user.UserManager; import sonia.scm.web.security.AuthenticationResult; import sonia.scm.web.security.AuthenticationState; import com.aquenos.scm.ssh.Constants; import com.aquenos.scm.ssh.server.AuthorizedKeysReader; import com.google.inject.Inject; import com.google.inject.Singleton; /** * Authenticator authenticating public keys against a list of public keys * authorized for a specific user. * * @author Sebastian Marsching */ @Singleton public class PublicKeyAuthenticator { private UserManager userManager; /** * Constructor. Meant to be called by Guice. * * @param userManager * the user manager that is used to get user objects. */ @Inject public PublicKeyAuthenticator(UserManager userManager) { this.userManager = userManager; } /** * Tries to authenticate a user using the supplied public key. * * @param username * the name of the user. * @param publicKey * the public key to look for in the list of authorized keys for * the user. The public key must be an RSA or DSA key. * @return authentication result representing the result of the * authentication operation. */ public AuthenticationResult authenticate(String username, PublicKey publicKey) { User user = userManager.get(username); if (user != null) { if (userManager.getDefaultType().equals(user.getType())) { List<PublicKey> keysForUser = getPublicKeysForUser(user); if (keysForUser == null) { return AuthenticationResult.NOT_FOUND; } if (containsPublicKey(keysForUser, publicKey)) { return new AuthenticationResult(user, AuthenticationState.SUCCESS); } else { return AuthenticationResult.FAILED; } } } return AuthenticationResult.NOT_FOUND; } private List<PublicKey> getPublicKeysForUser(User user) { String authorizedKeysString = user .getProperty(Constants.USER_AUTHORIZED_KEYS_PROPERTY); if (authorizedKeysString != null) { try { return AuthorizedKeysReader .readAuthorizedKeys(new StringReader( authorizedKeysString)); } catch (IOException e) { throw new RuntimeException("Unexpected IOException.", e); } } else { return null; } } private static boolean containsPublicKey(List<PublicKey> keyList, PublicKey key) { RSAPublicKey rsaKey = null; DSAPublicKey dsaKey = null; DSAParams dsaParams = null; if (key instanceof RSAPublicKey) { rsaKey = (RSAPublicKey) key; } else if (key instanceof DSAPublicKey) { dsaKey = (DSAPublicKey) key; dsaParams = dsaKey.getParams(); } else { // Unknown key type. return false; } for (PublicKey keyInList : keyList) { if (rsaKey != null && keyInList instanceof RSAPublicKey) { RSAPublicKey rsaKey2 = (RSAPublicKey) keyInList; if (rsaKey.getModulus().equals(rsaKey2.getModulus()) && rsaKey.getPublicExponent().equals( rsaKey2.getPublicExponent())) { return true; } } else if (dsaKey != null && keyInList instanceof DSAPublicKey) { DSAPublicKey dsaKey2 = (DSAPublicKey) keyInList; DSAParams dsaParams2 = dsaKey2.getParams(); if (dsaKey.getY().equals(dsaKey2.getY()) && dsaParams.getG().equals(dsaParams2.getG()) && dsaParams.getP().equals(dsaParams2.getP()) && dsaParams.getQ().equals(dsaParams2.getQ())) { return true; } } } return false; } }