3

I'm trying to make a java class in order to authenticate users against local SASL. My saslauthd configuration is like this:

$ cat /etc/sysconfig/saslauthd
# Directory in which to place saslauthd's listening socket, pid file, and so
# on.  This directory must already exist.
SOCKETDIR=/run/saslauthd

# Mechanism to use when checking passwords.  Run "saslauthd -v" to get a list
# of which mechanism your installation was compiled with the ablity to use.
MECH=pam

# Additional flags to pass to saslauthd on the command line.  See saslauthd(8)
# for the list of accepted flags.
FLAGS="-t 1"

Basically it redirects an authentication against PAM. So, if I'm doing for example a test like this.

testsaslauthd -s login -u <user> -p <password>
0: OK "Success."

It is all working correctly.

I now want to manage this mechanism through Java so I compiled something like this:

import java.util.Arrays;
import java.util.List;
import java.io.*;

public class PamAuthenticator {

    public static void main(String args[]) {

        String s = null;

        try {

            Process p = Runtime.getRuntime().exec("testsaslauthd -s "+args[2]+" -u "+args[0]+" -p "+args[1]);

            BufferedReader stdInput = new BufferedReader(new
                InputStreamReader(p.getInputStream()));

            BufferedReader stdError = new BufferedReader(new
                InputStreamReader(p.getErrorStream()));

            while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }

            while ((s = stdError.readLine()) != null) {
                System.out.println(s);
            }

            System.exit(0);
        }
        catch (IOException e) {
            System.out.println("Exception: ");
            e.printStackTrace();
            System.exit(-1);
        }
    }

}

This is correctly working:

$ java -cp .:* PamAuthenticator <user> <password> login
0: OK "Success."

My problem is that I don't want to execute the testsaslauthd command, since this is just a test command. Is there something better and smart I can do in order to try the authentication agains SASL with java?

LucaP
  • 638
  • 1
  • 12
  • 34
  • 1
    there's a sasl api in java: look at the createSaslClient method: https://docs.oracle.com/javase/7/docs/api/javax/security/sasl/Sasl.html – Marc Stroebel Dec 17 '18 at 11:09

1 Answers1

1

You are on the right track, not to use the code above. Besides being a test solution it would introduce a serious security problem: command injection.

From Java 1.6 there is an interface called SaslClient. This does exactly what you need. An example on the JDK8 version of it:

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import java.util.HashMap;

public class Test {
    public static void main(String[] args) throws SaslException {
        String userName = "username";
        String password = "password";
        SaslClient saslClient = Sasl.createSaslClient(new String[]{"PLAIN"},
                null, null, null, new HashMap<>(), callbacks -> {
                    for (final Callback callback : callbacks) {
                        if (callback instanceof NameCallback) {
                            NameCallback.class.cast(callback).setName(userName);
                            continue;
                        }
                        if (callback instanceof PasswordCallback) {
                            PasswordCallback.class.cast(callback).setPassword(password.toCharArray());
                            continue;
                        }
                        throw new UnsupportedCallbackException(callback);
                    }
                });
    }
}

Of course you should alter the source of the username and password.

Hash
  • 4,647
  • 5
  • 21
  • 39
  • Is it possible to specify the pam service on which this saslclient has authenticate against? In the `testsaslauthd` command I use the `-s` option in order to specify the `login` service (for example) which I customized with different modules. Like for example `auth required pam_securid.so` – LucaP Dec 24 '18 at 20:19
  • Yeah, take a look at the `Sasl.createSaslClient`parameters. In the linked JDK8 specification. :) – Hash Dec 25 '18 at 07:09
  • I'm not sure which is the right parameter for set the service. Is it the protocol? Also should at the end of your code perform an evaluateChallenge? – LucaP Mar 06 '19 at 22:00
  • Did the answer fulfill the question? If so could you accept it? :) – Hash Jun 18 '19 at 13:11