Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

apache mina sshd authenticate client signatures

I'm trying to authenticate a signature that clients generate from their private key and send to the server.

The only authenticator I could find in the library that sounded appropriate was the PublickeyAuthenticator. Please correct me if this is the wrong class to do this.

I currently have:

this.sshServer.setPublickeyAuthenticator(new PublickeyAuthenticator() {
                @Override
                public boolean authenticate(String username, PublicKey key, ServerSession session) {
                    if (username.equals("client")) {
                         //if signature == valid??
                         return true;
                    }
                }
            });

Does anyone know if mina supports signature verification and if so, how can it be implemented?

My understanding is that I'd first have to assign/add the user public key to the server. If the client has provided a id_rsa.pub file, how can I go about adding this file to the server as the public key?

like image 999
Hooli Avatar asked Aug 24 '16 12:08

Hooli


1 Answers

Mina SSH has a few implementations of PublickeyAuthenticator.
Look at org.apache.sshd.server.config.keys.AuthorizedKeysAuthenticator and org.apache.sshd.server.auth.pubkey.KeySetPublickeyAuthenticator.
Implementations of PublickeyAuthenticator only check that the given public key is associated with the user.
The actual verification of the signature is handled internally to MINA SSH after the authentication.
The AuthorizedKeysAuthenticator only supports one user(it doesnt check the username), but you could for example just point it at your id_rsa.pub file and it should work.

this.sshServer.setPublickeyAuthenticator(
    new AuthorizedKeysAuthenticator(new File("id_rsa.pub"));

You could write your own PublicKeyAuthenticator that checks the keys against a map of users like so:

public class UserKeySetPublickeyAuthenticator implements PublickeyAuthenticator {
    private final Map<String, Collection<? extends PublicKey>> userToKeySet;

    public UserKeySetPublickeyAuthenticator(Map<String, Collection<? extends PublicKey>> userToKeySet) {
        this.userToKeySet = userToKeySet;
    }

    @Override
    public boolean authenticate(String username, PublicKey key, ServerSession session) {
        return KeyUtils.findMatchingKey(key, userToKeySet.getOrDefault(username, Collections.emptyList())) != null;
    }

}

You need to write some code to populate the map with your key data. AuthorizedKeyEntry has utility methods for doing this from files, inputstreams or strings.
An example of reading from user named authorized key files:

Map<String, List<PublicKey>> userKeysMap = new HashMap<>();
List<String> users = Arrays.asList("Jim", "Sally", "Bob");
for(String user : users){
    List<PublicKey> usersKeys = new ArrayList<>();
    for(AuthorizedKeyEntry ake : AuthorizedKeyEntry.readAuthorizedKeys(new File(user + "_authorized_keys"))){
        PublicKey publicKey = ake.resolvePublicKey(PublicKeyEntryResolver.IGNORING);
        if(publicKey != null){
            usersKeys.add(publicKey);
        }
    }
    userKeysMap.put(user, usersKeys);
}
like image 175
Magnus Avatar answered Sep 19 '22 09:09

Magnus