All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.yawk.dbus.protocol.auth.mechanism.DbusCookieSha1AuthMechanism Maven / Gradle / Ivy

The newest version!
/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package at.yawk.dbus.protocol.auth.mechanism;

import at.yawk.dbus.protocol.DbusUtil;
import at.yawk.dbus.protocol.auth.AuthChannel;
import at.yawk.dbus.protocol.auth.AuthenticationException;
import at.yawk.dbus.protocol.auth.UnexpectedCommandException;
import at.yawk.dbus.protocol.auth.command.Auth;
import at.yawk.dbus.protocol.auth.command.Begin;
import at.yawk.dbus.protocol.auth.command.Data;
import at.yawk.dbus.protocol.auth.command.Ok;
import io.netty.handler.codec.DecoderException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Optional;
import java.util.concurrent.CompletionStage;

/**
 * @author yawkat
 */
public class DbusCookieSha1AuthMechanism implements AuthMechanism {

    private final SecureRandom rng;

    {
        try {
            rng = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        }
    }

    @Override
    public CompletionStage startAuth(AuthChannel channel) throws Exception {
        String username = System.getProperty("user.name");
        return channel.send(new Auth("DBUS_COOKIE_SHA1", username.getBytes())).thenCompose(cmd -> {
            MechanismException.handleCommand(cmd);
            if (cmd instanceof Data) {
                String s = new String(((Data) cmd).getData());
                try {
                    return channel.send(doAuth(s)).thenAccept(cmd2 -> {
                        MechanismException.handleCommand(cmd2);
                        if ((cmd2 instanceof Ok)) {
                            channel.send(new Begin());
                        } else {
                            throw new UnexpectedCommandException(cmd2);
                        }
                    });
                } catch (IOException | NoSuchAlgorithmException e) {
                    throw new AuthenticationException(e);
                }
            } else {
                throw new UnexpectedCommandException(cmd);
            }
        });
    }

    private Data doAuth(String cookieData) throws IOException, NoSuchAlgorithmException {
        String[] parts = cookieData.split(" ");
        if (parts.length != 3) {
            throw new DecoderException("Expected exactly 3 parts, got " + parts.length);
        }
        String cookieContext = parts[0];
        String cookieId = parts[1];
        String serverChallenge = parts[2];

        String userHome = System.getProperty("user.home");
        Path cookiePath = Paths.get(userHome, ".dbus-keyrings", cookieContext);
        Optional cookieOption = Files.lines(cookiePath)
                .map(line -> line.split(" "))
                .filter(arr -> arr.length == 3)
                .filter(arr -> arr[0].equals(cookieId))
                .map(arr -> arr[2])
                .findAny();
        String cookie = cookieOption.orElseThrow(() -> new DecoderException(
                "Could not find cookie with id " + cookieId + " in " + cookiePath));

        String clientChallenge = DbusUtil.printHex(rng.generateSeed(16));
        String blob = serverChallenge + ':' + clientChallenge + ':' + cookie;
        MessageDigest digest = MessageDigest.getInstance("SHA1");
        byte[] hash = digest.digest(blob.getBytes());

        String response = clientChallenge + " " + DbusUtil.printHex(hash);
        return new Data(response.getBytes());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy