public boolean auth()

in dbus-java/src/main/java/org/freedesktop/dbus/connections/SASL.java [406:702]


    public boolean auth(SaslMode mode, int types, String guid, OutputStream out, InputStream in, Socket us) throws IOException {
        String luid = null;
        String kernelUid = null;

        long uid = POSIXFactory.getJavaPOSIX().getuid();
        luid = stupidlyEncode("" + uid);

        SASL.Command c;
        int failed = 0;
        int current = 0;
        SaslAuthState state = SaslAuthState.INITIAL_STATE;
        
        while (state != SaslAuthState.FINISHED && state != SaslAuthState.FAILED) {

            logger.trace("Mode: {} AUTH state: {}", mode, state);

            switch (mode) {
            case CLIENT:
                switch (state) {
                case INITIAL_STATE:
                    if (FreeBSDHelper.isFreeBSD()) {
                        FreeBSDHelper.send_cred(us);
                    } else {
                        out.write(new byte[] {
                                0
                        });
                    }
                    send(out, AUTH);
                    state = SaslAuthState.WAIT_DATA;
                    break;
                case WAIT_DATA:
                    c = receive(in);
                    switch (c.getCommand()) {
                        case DATA:
                            switch (doChallenge(current, c)) {
                                case CONTINUE:
                                    send(out, DATA, c.getResponse());
                                    break;
                                case OK:
                                    send(out, DATA, c.getResponse());
                                    state = SaslAuthState.WAIT_OK;
                                    break;
                                case ERROR:
                                default:
                                    send(out, ERROR, c.getResponse());
                                    break;
                            }
                        break;
                        case REJECTED:
                            failed |= current;
                            int available = c.getMechs() & (~failed);
                            if (0 != (available & AUTH_EXTERNAL)) {
                                send(out, AUTH, "EXTERNAL", luid);
                                current = AUTH_EXTERNAL;
                            } else if (0 != (available & AUTH_SHA)) {
                                send(out, AUTH, "DBUS_COOKIE_SHA1", luid);
                                current = AUTH_SHA;
                            } else if (0 != (available & AUTH_ANON)) {
                                send(out, AUTH, "ANONYMOUS");
                                current = AUTH_ANON;
                            } else {
                                state = SaslAuthState.FAILED;
                            }
                            break;
                        case ERROR:
                            // when asking for file descriptor support, ERROR means FD support is not supported
                            if (state == SaslAuthState.NEGOTIATE_UNIX_FD) { 
                                state = SaslAuthState.FINISHED;
                                logger.trace("File descriptors NOT supported by server");
                                fileDescriptorSupported = false;
                                send(out, BEGIN);                            
                            } else {
                                send(out, CANCEL);
                                state = SaslAuthState.WAIT_REJECT;
                            }
                            break;
                        case OK:
                            logger.trace("Authenticated");
                            state = SaslAuthState.AUTHENTICATED;

                            if (hasFileDescriptorSupport) {
                                state = SaslAuthState.WAIT_DATA;
                                logger.trace("Asking for file descriptor support");
                                // if authentication was successful, ask remote end for file descriptor support
                                send(out, SaslCommand.NEGOTIATE_UNIX_FD);
                            }else{
                                state = SaslAuthState.FINISHED;
                                send(out, BEGIN);                     
                            }
                            break;
                        case AGREE_UNIX_FD:
                            if (hasFileDescriptorSupport) {
                                state = SaslAuthState.FINISHED;
                                logger.trace("File descriptors supported by server");
                                fileDescriptorSupported = true;
                                send(out, BEGIN);
                            }
                            break;
                        default:
                            send(out, ERROR, "Got invalid command");
                            break;
                        }
                    break;
                case WAIT_OK:
                    c = receive(in);
                    switch (c.getCommand()) {
                    case OK:
                        send(out, BEGIN);
                        state = SaslAuthState.AUTHENTICATED;
                        break;
                    case ERROR:
                    case DATA:
                        send(out, CANCEL);
                        state = SaslAuthState.WAIT_REJECT;
                        break;
                    case REJECTED:
                        failed |= current;
                        int available = c.getMechs() & (~failed);
                        state = SaslAuthState.WAIT_DATA;
                        if (0 != (available & AUTH_EXTERNAL)) {
                            send(out, AUTH, "EXTERNAL", luid);
                            current = AUTH_EXTERNAL;
                        } else if (0 != (available & AUTH_SHA)) {
                            send(out, AUTH, "DBUS_COOKIE_SHA1", luid);
                            current = AUTH_SHA;
                        } else if (0 != (available & AUTH_ANON)) {
                            send(out, AUTH, "ANONYMOUS");
                            current = AUTH_ANON;
                        } else {
                            state = SaslAuthState.FAILED;
                        }
                        break;
                    default:
                        send(out, ERROR, "Got invalid command");
                        break;
                    }
                    break;
                case WAIT_REJECT:
                    c = receive(in);
                    switch (c.getCommand()) {
                        case REJECTED:
                            failed |= current;
                            int available = c.getMechs() & (~failed);
                            if (0 != (available & AUTH_EXTERNAL)) {
                                send(out, AUTH, "EXTERNAL", luid);
                                current = AUTH_EXTERNAL;
                            } else if (0 != (available & AUTH_SHA)) {
                                send(out, AUTH, "DBUS_COOKIE_SHA1", luid);
                                current = AUTH_SHA;
                            } else if (0 != (available & AUTH_ANON)) {
                                send(out, AUTH, "ANONYMOUS");
                                current = AUTH_ANON;
                            } else {
                                state = SaslAuthState.FAILED;
                            }
                        break;
                        default:
                            state = SaslAuthState.FAILED;
                            break;
                    }
                    break;
                default:
                    state = SaslAuthState.FAILED;
                }
                break;
            case SERVER:
                switch (state) {
                    case INITIAL_STATE:
                        byte[] buf = new byte[1];
                        if (null == us) {
                            in.read(buf); // 0
                            state = SaslAuthState.WAIT_AUTH;
                        } else {
                            Credentials credentials;
                            try {
                                if (FreeBSDHelper.isFreeBSD()) {
                                    long euid = FreeBSDHelper.recv_cred(us);
                                    if (euid >= 0) {
                                        kernelUid = stupidlyEncode("" + euid);
                                    }
                                } else {
                                    credentials = ((UnixSocket) us).getCredentials();
                                    int kuid = credentials.getUid();
                                    if (kuid >= 0) {
                                        kernelUid = stupidlyEncode("" + kuid);
                                    }
                                }
                                state = SaslAuthState.WAIT_AUTH;
    
                            } catch (SocketException _ex) {
                                state = SaslAuthState.FAILED;
                            }
                        }
                    break;
                    case WAIT_AUTH:
                        c = receive(in);
                        switch (c.getCommand()) {
                            case AUTH:
                                switch (doResponse(current, luid, kernelUid, c)) {
                                    case CONTINUE:
                                        send(out, DATA, c.getResponse());
                                        current = c.getMechs();
                                        state = SaslAuthState.WAIT_DATA;
                                        break;
                                    case OK:
                                        send(out, SaslCommand.OK, guid);
                                        state = SaslAuthState.WAIT_BEGIN;
                                        current = 0;
                                        break;
                                    case REJECT:
                                    default:
                                        send(out, REJECTED, getTypes(types));
                                        current = 0;
                                        break;
                                }
                                break;
                            case ERROR:
                                send(out, REJECTED, getTypes(types));
                                break;
                            case BEGIN:
                                state = SaslAuthState.FAILED;
                                break;
                            default:
                                send(out, ERROR, "Got invalid command");
                                break;
                            }
                    break;
                    case WAIT_DATA:
                        c = receive(in);
                    switch (c.getCommand()) {
                    case DATA:
                        switch (doResponse(current, luid, kernelUid, c)) {
                            case CONTINUE:
                                send(out, DATA, c.getResponse());
                                state = SaslAuthState.WAIT_DATA;
                                break;
                            case OK:
                                send(out, SaslCommand.OK, guid);
                                state = SaslAuthState.WAIT_BEGIN;
                                current = 0;
                                break;
                            case REJECT:
                            default:
                                send(out, REJECTED, getTypes(types));
                                current = 0;
                                break;
                            }
                        break;
                        case ERROR:
                        case CANCEL:
                            send(out, REJECTED, getTypes(types));
                            state = SaslAuthState.WAIT_AUTH;
                        break;
                        case BEGIN:
                            state = SaslAuthState.FAILED;
                        break;
                        default:
                            send(out, ERROR, "Got invalid command");
                        break;
                    }
                    break;
                    case WAIT_BEGIN:
                        c = receive(in);
                        switch (c.getCommand()) {
                            case ERROR:
                            case CANCEL:
                                send(out, REJECTED, getTypes(types));
                                state = SaslAuthState.WAIT_AUTH;
                            break;
                            case BEGIN:
                                    state = SaslAuthState.FINISHED;
                            break;
                            case NEGOTIATE_UNIX_FD:
                                logger.debug("File descriptor negotiation requested");
                                if (!hasFileDescriptorSupport) {
                                    send(out, ERROR);
                                } else {
                                    send(out, AGREE_UNIX_FD);
                                }
                                
                            break;
                            default:
                                send(out, ERROR, "Got invalid command");
                            break;
                        }
                    break;
                    default:
                        state = SaslAuthState.FAILED;
                    }
                break;
            default:
                return false;
            }
        }

        return state == SaslAuthState.FINISHED;
    }