Java源码示例:io.undertow.util.FlexBase64

示例1
private static byte[] base64Decode(String sessionId) {
    try {
        ByteBuf sessionIdBuffer = FlexBase64.decode(sessionId);
        byte[] sessionIdData;
        if (sessionIdBuffer.hasArray()) {
            sessionIdData = sessionIdBuffer.array();
        } else {
            sessionIdData = new byte[sessionIdBuffer.readableBytes()];
            sessionIdBuffer.readBytes(sessionIdData);
        }
        return sessionIdData;
    } catch (IOException e) {
        //can happen if the session id is invalid
        return null;
    }
}
 
示例2
private static byte[] base64Decode(String sessionId) {
    try {
        ByteBuffer sessionIdBuffer = FlexBase64.decode(sessionId);
        byte[] sessionIdData;
        if (sessionIdBuffer.hasArray()) {
            sessionIdData = sessionIdBuffer.array();
        } else {
            sessionIdData = new byte[sessionIdBuffer.remaining()];
            sessionIdBuffer.get(sessionIdData);
        }
        return sessionIdData;
    } catch (IOException e) {
        //can happen if the session id is invalid
        return null;
    }
}
 
示例3
@Test
public void testAuthenticatedWebsocket() throws Exception {
    ProgramaticClientEndpoint endpoint = new ProgramaticClientEndpoint();
    ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().configurator(new ClientConfigurator(){
        @Override
        public void beforeRequest(Map<String, List<String>> headers) {
            headers.put(AUTHORIZATION.toString(), Collections.singletonList(BASIC + " " + FlexBase64.encodeString("user1:password1".getBytes(), false)));
        }
    }).build();
    ContainerProvider.getWebSocketContainer().connectToServer(endpoint, clientEndpointConfig, new URI("ws://" + DefaultServer.getHostAddress("default") + ":" + DefaultServer.getHostPort("default") + "/servletContext/secured"));
    Assert.assertEquals("user1", endpoint.getResponses().poll(15, TimeUnit.SECONDS));
    endpoint.session.close();
    endpoint.closeLatch.await(10, TimeUnit.SECONDS);
}
 
示例4
private static String md5(byte[] buffer) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(buffer);
        byte[] digest = md.digest();
        return new String(FlexBase64.encodeBytes(digest, 0, digest.length, false));
    } catch (NoSuchAlgorithmException e) {
        // Should never happen
        throw new InternalError("MD5 not supported on this platform");
    }
}
 
示例5
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);

    String header = NEGOTIATION_PLAIN;

    if (negContext != null) {
        byte[] responseChallenge = negContext.useResponseToken();
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, null);
        if (responseChallenge != null) {
            header = NEGOTIATE_PREFIX + FlexBase64.encodeString(responseChallenge, false);
        }
    } else {
        Subject server = null;
        try {
            server = subjectFactory.getSubjectForHost(getHostName(exchange));
        } catch (GeneralSecurityException e) {
            // Deliberately ignore - no Subject so don't offer GSSAPI is our main concern here.
        }
        if (server == null) {
            return ChallengeResult.NOT_SENT;
        }
    }

    exchange.addResponseHeader(WWW_AUTHENTICATE, header);

    UndertowLogger.SECURITY_LOGGER.debugf("Sending GSSAPI challenge for %s", exchange);
    return new ChallengeResult(true, UNAUTHORIZED);
}
 
示例6
public SimpleNonceManager(final String hashAlg) {
    // Verify it is a valid algorithm (at least for now)
    MessageDigest digest = getDigest(hashAlg);

    this.hashAlg = hashAlg;
    this.hashLength = digest.getDigestLength();

    // Create a new secret only valid within this NonceManager instance.
    Random rand = new SecureRandom();
    byte[] secretBytes = new byte[32];
    rand.nextBytes(secretBytes);
    secret = FlexBase64.encodeString(digest.digest(secretBytes), false);
}
 
示例7
private String createNonce(final byte[] prefix, final byte[] timeStamp) {
    byte[] hashedPart = generateHash(prefix, timeStamp);
    byte[] complete = new byte[9 + timeStamp.length + hashedPart.length];
    System.arraycopy(prefix, 0, complete, 0, 8);
    complete[8] = (byte) timeStamp.length;
    System.arraycopy(timeStamp, 0, complete, 9, timeStamp.length);
    System.arraycopy(hashedPart, 0, complete, 9 + timeStamp.length, hashedPart.length);

    return FlexBase64.encodeString(complete, false);
}
 
示例8
@Override
public String readAttribute(HttpServerExchange exchange) {
    SSLSessionInfo ssl = exchange.getSslSessionInfo();
    if(ssl == null || ssl.getSessionId() == null) {
        return null;
    }
    return FlexBase64.encodeString(ssl.getSessionId(), false);
}
 
示例9
/**
 * Generate the MD5 hash out of the given {@link ByteBuffer}
 */
private static String md5(byte[] buffer) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(buffer);
        byte[] digest = md.digest();
        return new String(FlexBase64.encodeBytes(digest, 0, digest.length, false), StandardCharsets.US_ASCII);
    } catch (NoSuchAlgorithmException e) {
        // Should never happen
        throw new InternalError("MD5 not supported on this platform");
    }
}
 
示例10
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);

    String header = NEGOTIATION_PLAIN;

    if (negContext != null) {
        byte[] responseChallenge = negContext.useResponseToken();
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, null);
        if (responseChallenge != null) {
            header = NEGOTIATE_PREFIX + FlexBase64.encodeString(responseChallenge, false);
        }
    } else {
        Subject server = null;
        try {
            server = subjectFactory.getSubjectForHost(getHostName(exchange));
        } catch (GeneralSecurityException e) {
            // Deliberately ignore - no Subject so don't offer GSSAPI is our main concern here.
        }
        if (server == null) {
            return ChallengeResult.NOT_SENT;
        }
    }

    exchange.getResponseHeaders().add(WWW_AUTHENTICATE, header);

    UndertowLogger.SECURITY_LOGGER.debugf("Sending GSSAPI challenge for %s", exchange);
    return new ChallengeResult(true, UNAUTHORIZED);
}
 
示例11
public SimpleNonceManager(final String hashAlg) {
    // Verify it is a valid algorithm (at least for now)
    MessageDigest digest = getDigest(hashAlg);

    this.hashAlg = hashAlg;
    this.hashLength = digest.getDigestLength();

    // Create a new secret only valid within this NonceManager instance.
    Random rand = new SecureRandom();
    byte[] secretBytes = new byte[32];
    rand.nextBytes(secretBytes);
    secret = FlexBase64.encodeString(digest.digest(secretBytes), false);
}
 
示例12
private String createNonce(final byte[] prefix, final byte[] timeStamp) {
    byte[] hashedPart = generateHash(prefix, timeStamp);
    byte[] complete = new byte[9 + timeStamp.length + hashedPart.length];
    System.arraycopy(prefix, 0, complete, 0, 8);
    complete[8] = (byte) timeStamp.length;
    System.arraycopy(timeStamp, 0, complete, 9, timeStamp.length);
    System.arraycopy(hashedPart, 0, complete, 9 + timeStamp.length, hashedPart.length);

    return FlexBase64.encodeString(complete, false);
}
 
示例13
@Override
public String readAttribute(HttpServerExchange exchange) {
    SSLSessionInfo ssl = exchange.getConnection().getSslSessionInfo();
    if(ssl == null || ssl.getSessionId() == null) {
        return null;
    }
    return FlexBase64.encodeString(ssl.getSessionId(), false);
}
 
示例14
public static String createSettingsFrame(OptionMap options, ByteBufferPool bufferPool) {
    PooledByteBuffer b = bufferPool.allocate();
    try {
        ByteBuffer currentBuffer = b.getBuffer();

        if (options.contains(UndertowOptions.HTTP2_SETTINGS_HEADER_TABLE_SIZE)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_HEADER_TABLE_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_HEADER_TABLE_SIZE));
        }
        if (options.contains(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_ENABLE_PUSH, options.get(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH) ? 1 : 0);
        }

        if (options.contains(UndertowOptions.HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_CONCURRENT_STREAMS, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
        }

        if (options.contains(UndertowOptions.HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_INITIAL_WINDOW_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
        }

        if (options.contains(UndertowOptions.HTTP2_SETTINGS_MAX_FRAME_SIZE)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_FRAME_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_FRAME_SIZE));
        }

        if (options.contains(UndertowOptions.HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_HEADER_LIST_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE));
        } else if(options.contains(UndertowOptions.MAX_HEADER_SIZE)) {
            pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_HEADER_LIST_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE));
        }
        currentBuffer.flip();
        return FlexBase64.encodeStringURL(currentBuffer, false);
    } finally {
        b.close();
    }
}
 
示例15
/**
 * Generate the MD5 hash out of the given {@link ByteBuffer}
 */
private static String md5(byte[] buffer) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(buffer);
        byte[] digest = md.digest();
        return new String(FlexBase64.encodeBytes(digest, 0, digest.length, false), StandardCharsets.US_ASCII);
    } catch (NoSuchAlgorithmException e) {
        // Should never happen
        throw new InternalError("MD5 not supported on this platform");
    }
}
 
示例16
protected String createSecKey() {
    SecureRandom random = new SecureRandom();
    byte[] data = new byte[16];
    for (int i = 0; i < 4; ++i) {
        int val = random.nextInt();
        data[i * 4] = (byte) val;
        data[i * 4 + 1] = (byte) ((val >> 8) & 0xFF);
        data[i * 4 + 2] = (byte) ((val >> 16) & 0xFF);
        data[i * 4 + 3] = (byte) ((val >> 24) & 0xFF);
    }
    return FlexBase64.encodeString(data, false);
}
 
示例17
protected final String solve(final String nonceBase64) {
    try {
        final String concat = nonceBase64 + MAGIC_NUMBER;
        final MessageDigest digest = MessageDigest.getInstance("SHA1");

        digest.update(concat.getBytes(StandardCharsets.UTF_8));
        final byte[] bytes = digest.digest();
        return FlexBase64.encodeString(bytes, false);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}
 
示例18
@Override
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);

    String header = NEGOTIATION_PLAIN;

    if (negContext != null) {
        byte[] responseChallenge = negContext.useResponseToken();
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, null);
        if (responseChallenge != null) {
            header = NEGOTIATE_PREFIX + FlexBase64.encodeString(responseChallenge, false);
        }
    } else {
        Subject server = null;
        try {
            server = subjectFactory.getSubjectForHost(getHostName(exchange));
        } catch (GeneralSecurityException e) {
            // Deliberately ignore - no Subject so don't offer GSSAPI is our main concern here.
        }
        if (server == null) {
            return ChallengeResult.NOT_SENT;
        }
    }

    exchange.getResponseHeaders().add(WWW_AUTHENTICATE, header);

    if(logger.isDebugEnabled()) logger.debug("Sending GSSAPI challenge for %s", exchange);
    return new ChallengeResult(true, UNAUTHORIZED);
}
 
示例19
@SuppressWarnings("unchecked")
private String authenticate(String authHeader) throws ApiException {
    String result = null;
    if (authHeader.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {
        String base64Challenge = authHeader.substring(PREFIX_LENGTH);
        String plainChallenge;
        try {
            ByteBuffer decode = FlexBase64.decode(base64Challenge);
            // assume charset is UTF_8
            Charset charset = StandardCharsets.UTF_8;
            plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
            logger.debug("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, authHeader);
            int colonPos;
            if ((colonPos = plainChallenge.indexOf(COLON)) > -1) {
                String clientId = plainChallenge.substring(0, colonPos);
                String clientSecret = plainChallenge.substring(colonPos + 1);
                // match with db/cached user credentials.
                IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
                Client client = clients.get(clientId);
                if(client == null) {
                    throw new ApiException(new Status(CLIENT_NOT_FOUND, clientId));
                }
                if(!HashUtil.validatePassword(clientSecret.toCharArray(), client.getClientSecret())) {
                    throw new ApiException(new Status(UNAUTHORIZED_CLIENT));
                }
                result = clientId;
            }
        } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
            logger.error("Exception:", e);
            throw new ApiException(new Status(RUNTIME_EXCEPTION));
        }
    }
    return result;
}
 
示例20
@Override
public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange,
                                                   final SecurityContext securityContext) {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
    if (negContext != null) {

        UndertowLogger.SECURITY_LOGGER.debugf("Existing negotiation context found for %s", exchange);
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
        if (negContext.isEstablished()) {
            IdentityManager identityManager = getIdentityManager(securityContext);
            final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
            if (account != null) {
                securityContext.authenticationComplete(account, name, false);
                UndertowLogger.SECURITY_LOGGER.debugf("Authenticated as user %s with existing GSSAPI negotiation context for %s", account.getPrincipal().getName(), exchange);
                return AuthenticationMechanismOutcome.AUTHENTICATED;
            } else {
                UndertowLogger.SECURITY_LOGGER.debugf("Failed to authenticate with existing GSSAPI negotiation context for %s", exchange);
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    List<String> authHeaders = exchange.getRequestHeaders(AUTHORIZATION);
    if (authHeaders != null) {
        for (String current : authHeaders) {
            if (current.startsWith(NEGOTIATE_PREFIX)) {
                String base64Challenge = current.substring(NEGOTIATE_PREFIX.length());
                try {
                    ByteBuf challenge = FlexBase64.decode(base64Challenge);
                    return runGSSAPI(exchange, challenge, securityContext);
                } catch (IOException e) {
                }

                // By this point we had a header we should have been able to verify but for some reason
                // it was not correctly structured.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    // No suitable header was found so authentication was not even attempted.
    return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
 
示例21
public AuthenticationMechanismOutcome run() throws GSSException {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
    if (negContext == null) {
        negContext = new NegotiationContext();
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
    }

    GSSContext gssContext = negContext.getGssContext();
    if (gssContext == null) {
        GSSManager manager = GSSManager.getInstance();

        GSSCredential credential = manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, mechanisms, GSSCredential.ACCEPT_ONLY);

        gssContext = manager.createContext(credential);

        negContext.setGssContext(gssContext);
    }

    byte[] respToken = gssContext.acceptSecContext(challenge.array(), challenge.arrayOffset(), challenge.writerIndex());
    negContext.setResponseToken(respToken);

    if (negContext.isEstablished()) {

        if (respToken != null) {
            // There will be no further challenge but we do have a token so set it here.
            exchange.addResponseHeader(WWW_AUTHENTICATE,
                    NEGOTIATE_PREFIX + FlexBase64.encodeString(respToken, false));
        }
        IdentityManager identityManager = securityContext.getIdentityManager();
        final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
        if (account != null) {
            securityContext.authenticationComplete(account, name, false);
            return AuthenticationMechanismOutcome.AUTHENTICATED;
        } else {
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }
    } else {
        // This isn't a failure but as the context is not established another round trip with the client is needed.
        return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
    }
}
 
示例22
/**
 * Verify a previously unknown nonce and return the {@link NonceKey} representation for the nonce.
 * <p>
 * Later when a nonce is re-used we can match based on the String alone - the information embedded within the nonce will be
 * cached with it.
 * <p>
 * This stage of the verification simply extracts the prefix and the embedded timestamp and recreates a new hashed and
 * Base64 nonce based on the local secret - if the newly generated nonce matches the supplied one we accept it was created
 * by this nonce manager.
 * <p>
 * This verification does not validate that the timestamp is within a valid time period.
 *
 * @param nonce -
 * @return
 */
private Nonce verifyUnknownNonce(final String nonce, final int nonceCount) {
    byte[] complete;
    int offset;
    int length;
    try {
        ByteBuf decode = FlexBase64.decode(nonce);
        complete = decode.array();
        offset = decode.arrayOffset();
        length = decode.writerIndex() - offset;
    } catch (IOException e) {
        throw MESSAGES.invalidBase64Token(e);
    }

    int timeStampLength = complete[offset + 8];
    // A sanity check to try and verify the sizes we expect from the arrays are correct.
    if (hashLength > 0) {
        int expectedLength = 9 + timeStampLength + hashLength;
        if (length != expectedLength) {
            throw MESSAGES.invalidNonceReceived();
        } else if (timeStampLength + 1 >= length)
            throw MESSAGES.invalidNonceReceived();
    }

    byte[] prefix = new byte[8];
    System.arraycopy(complete, offset, prefix, 0, 8);
    byte[] timeStampBytes = new byte[timeStampLength];
    System.arraycopy(complete, offset + 9, timeStampBytes, 0, timeStampBytes.length);

    String expectedNonce = createNonce(prefix, timeStampBytes);

    if (expectedNonce.equals(nonce)) {
        try {
            long timeStamp = Long.parseLong(new String(timeStampBytes, StandardCharsets.UTF_8));

            return new Nonce(expectedNonce, timeStamp, nonceCount);
        } catch (NumberFormatException dropped) {
        }
    }

    return null;
}
 
示例23
/**
 * @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
 */
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {

    List<String> authHeaders = exchange.getRequestHeaders(AUTHORIZATION);
    if (authHeaders != null) {
        for (String current : authHeaders) {
            if (current.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {

                String base64Challenge = current.substring(PREFIX_LENGTH);
                String plainChallenge = null;
                try {
                    ByteBuf decode = FlexBase64.decode(base64Challenge);

                    Charset charset = this.charset;
                    if(!userAgentCharsets.isEmpty()) {
                        String ua = exchange.getRequestHeader(HttpHeaderNames.USER_AGENT);
                        if(ua != null) {
                            for (Map.Entry<Pattern, Charset> entry : userAgentCharsets.entrySet()) {
                                if(entry.getKey().matcher(ua).find()) {
                                    charset = entry.getValue();
                                    break;
                                }
                            }
                        }
                    }

                    plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.writerIndex(), charset);
                    UndertowLogger.SECURITY_LOGGER.debugf("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
                } catch (IOException e) {
                    UndertowLogger.SECURITY_LOGGER.debugf(e, "Failed to decode basic auth header %s in %s", base64Challenge, exchange);
                }
                int colonPos;
                if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
                    String userName = plainChallenge.substring(0, colonPos);
                    char[] password = plainChallenge.substring(colonPos + 1).toCharArray();

                    IdentityManager idm = getIdentityManager(securityContext);
                    PasswordCredential credential = new PasswordCredential(password);
                    try {
                        final AuthenticationMechanismOutcome result;
                        Account account = idm.verify(userName, credential);
                        if (account != null) {
                            securityContext.authenticationComplete(account, name, false);
                            result = AuthenticationMechanismOutcome.AUTHENTICATED;
                        } else {
                            securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), name);
                            result = AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
                        }
                        return result;
                    } finally {
                        clear(password);
                    }
                }

                // By this point we had a header we should have been able to verify but for some reason
                // it was not correctly structured.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    // No suitable header has been found in this request,
    return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
 
示例24
@Override
public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange,
                                                   final SecurityContext securityContext) {
    ServerConnection connection = exchange.getConnection();
    NegotiationContext negContext = connection.getAttachment(NegotiationContext.ATTACHMENT_KEY);
    if (negContext != null) {

        UndertowLogger.SECURITY_LOGGER.debugf("Existing negotiation context found for %s", exchange);
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
        if (negContext.isEstablished()) {
            IdentityManager identityManager = getIdentityManager(securityContext);
            final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
            if (account != null) {
                securityContext.authenticationComplete(account, name, false);
                UndertowLogger.SECURITY_LOGGER.debugf("Authenticated as user %s with existing GSSAPI negotiation context for %s", account.getPrincipal().getName(), exchange);
                return AuthenticationMechanismOutcome.AUTHENTICATED;
            } else {
                UndertowLogger.SECURITY_LOGGER.debugf("Failed to authenticate with existing GSSAPI negotiation context for %s", exchange);
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
    if (authHeaders != null) {
        for (String current : authHeaders) {
            if (current.startsWith(NEGOTIATE_PREFIX)) {
                String base64Challenge = current.substring(NEGOTIATE_PREFIX.length());
                try {
                    ByteBuffer challenge = FlexBase64.decode(base64Challenge);
                    return runGSSAPI(exchange, challenge, securityContext);
                } catch (IOException e) {
                }

                // By this point we had a header we should have been able to verify but for some reason
                // it was not correctly structured.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    // No suitable header was found so authentication was not even attempted.
    return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
 
示例25
public AuthenticationMechanismOutcome run() throws GSSException {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
    if (negContext == null) {
        negContext = new NegotiationContext();
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
        // Also cache it on the connection for future calls.
        exchange.getConnection().putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
    }

    GSSContext gssContext = negContext.getGssContext();
    if (gssContext == null) {
        GSSManager manager = GSSManager.getInstance();

        GSSCredential credential = manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, mechanisms, GSSCredential.ACCEPT_ONLY);

        gssContext = manager.createContext(credential);

        negContext.setGssContext(gssContext);
    }

    byte[] respToken = gssContext.acceptSecContext(challenge.array(), challenge.arrayOffset(), challenge.limit());
    negContext.setResponseToken(respToken);

    if (negContext.isEstablished()) {

        if (respToken != null) {
            // There will be no further challenge but we do have a token so set it here.
            exchange.getResponseHeaders().add(WWW_AUTHENTICATE,
                    NEGOTIATE_PREFIX + FlexBase64.encodeString(respToken, false));
        }
        IdentityManager identityManager = securityContext.getIdentityManager();
        final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
        if (account != null) {
            securityContext.authenticationComplete(account, name, false);
            return AuthenticationMechanismOutcome.AUTHENTICATED;
        } else {
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }
    } else {
        // This isn't a failure but as the context is not established another round trip with the client is needed.
        return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
    }
}
 
示例26
/**
 * Verify a previously unknown nonce and return the {@link NonceKey} representation for the nonce.
 *
 * Later when a nonce is re-used we can match based on the String alone - the information embedded within the nonce will be
 * cached with it.
 *
 * This stage of the verification simply extracts the prefix and the embedded timestamp and recreates a new hashed and
 * Base64 nonce based on the local secret - if the newly generated nonce matches the supplied one we accept it was created
 * by this nonce manager.
 *
 * This verification does not validate that the timestamp is within a valid time period.
 *
 * @param nonce -
 * @return
 */
private Nonce verifyUnknownNonce(final String nonce, final int nonceCount) {
    byte[] complete;
    int offset;
    int length;
    try {
        ByteBuffer decode = FlexBase64.decode(nonce);
        complete = decode.array();
        offset = decode.arrayOffset();
        length = decode.limit() - offset;
    } catch (IOException e) {
        throw MESSAGES.invalidBase64Token(e);
    }

    int timeStampLength = complete[offset + 8];
    // A sanity check to try and verify the sizes we expect from the arrays are correct.
    if (hashLength > 0) {
        int expectedLength = 9 + timeStampLength + hashLength;
        if (length != expectedLength) {
            throw MESSAGES.invalidNonceReceived();
        } else if (timeStampLength + 1 >= length)
            throw MESSAGES.invalidNonceReceived();
    }

    byte[] prefix = new byte[8];
    System.arraycopy(complete, offset, prefix, 0, 8);
    byte[] timeStampBytes = new byte[timeStampLength];
    System.arraycopy(complete, offset + 9, timeStampBytes, 0, timeStampBytes.length);

    String expectedNonce = createNonce(prefix, timeStampBytes);

    if (expectedNonce.equals(nonce)) {
        try {
            long timeStamp = Long.parseLong(new String(timeStampBytes, StandardCharsets.UTF_8));

            return new Nonce(expectedNonce, timeStamp, nonceCount);
        } catch (NumberFormatException dropped) {
        }
    }

    return null;
}
 
示例27
/**
 * @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
 */
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {

    List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
    if (authHeaders != null) {
        for (String current : authHeaders) {
            if (current.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {

                String base64Challenge = current.substring(PREFIX_LENGTH);
                String plainChallenge = null;
                try {
                    ByteBuffer decode = FlexBase64.decode(base64Challenge);

                    Charset charset = this.charset;
                    if(!userAgentCharsets.isEmpty()) {
                        String ua = exchange.getRequestHeaders().getFirst(Headers.USER_AGENT);
                        if(ua != null) {
                            for (Map.Entry<Pattern, Charset> entry : userAgentCharsets.entrySet()) {
                                if(entry.getKey().matcher(ua).find()) {
                                    charset = entry.getValue();
                                    break;
                                }
                            }
                        }
                    }

                    plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
                    UndertowLogger.SECURITY_LOGGER.debugf("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
                } catch (IOException e) {
                    UndertowLogger.SECURITY_LOGGER.debugf(e, "Failed to decode basic auth header %s in %s", base64Challenge, exchange);
                }
                int colonPos;
                if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
                    String userName = plainChallenge.substring(0, colonPos);
                    char[] password = plainChallenge.substring(colonPos + 1).toCharArray();

                    IdentityManager idm = getIdentityManager(securityContext);
                    PasswordCredential credential = new PasswordCredential(password);
                    try {
                        final AuthenticationMechanismOutcome result;
                        Account account = idm.verify(userName, credential);
                        if (account != null) {
                            securityContext.authenticationComplete(account, name, false);
                            result = AuthenticationMechanismOutcome.AUTHENTICATED;
                        } else {
                            securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), name);
                            result = AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
                        }
                        return result;
                    } finally {
                        clear(password);
                    }
                }

                // By this point we had a header we should have been able to verify but for some reason
                // it was not correctly structured.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    // No suitable header has been found in this request,
    return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
 
示例28
@Override
public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange,
                                                   final SecurityContext securityContext) {
    ServerConnection connection = exchange.getConnection();
    NegotiationContext negContext = connection.getAttachment(NegotiationContext.ATTACHMENT_KEY);
    if (negContext != null) {

        if(logger.isDebugEnabled()) logger.debug("Existing negotiation context found for %s", exchange);
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
        if (negContext.isEstablished()) {
            IdentityManager identityManager = getIdentityManager(securityContext);
            // get the client authenticate class and user type from the exchange.
            String clientAuthClass = null;
            String userType = null;
            Map<String, Deque<String>> params = exchange.getQueryParameters();
            Deque<String> clientIdDeque = params.get("client_id");
            if(clientIdDeque != null) {
                String clientId = clientIdDeque.getFirst();
                IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
                Client client = clients.get(clientId);
                if(client != null) {
                    clientAuthClass = client.getAuthenticateClass();
                }
            }
            Deque<String> userTypeDeque = params.get("user_type");
            if(userTypeDeque != null) {
                userType = userTypeDeque.getFirst();
            }

            final Account account = identityManager.verify(new LightGSSContextCredential(negContext.getGssContext(), clientAuthClass, userType));
            if (account != null) {
                securityContext.authenticationComplete(account, name, false);
                if(logger.isDebugEnabled()) logger.debug("Authenticated as user %s with existing GSSAPI negotiation context for %s", account.getPrincipal().getName(), exchange);
                return AuthenticationMechanismOutcome.AUTHENTICATED;
            } else {
                if(logger.isDebugEnabled()) logger.debug("Failed to authenticate with existing GSSAPI negotiation context for %s", exchange);
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
    if (authHeaders != null) {
        for (String current : authHeaders) {
            if (current.startsWith(NEGOTIATE_PREFIX)) {
                String base64Challenge = current.substring(NEGOTIATE_PREFIX.length());
                try {
                    ByteBuffer challenge = FlexBase64.decode(base64Challenge);
                    return runGSSAPI(exchange, challenge, securityContext);
                } catch (IOException e) {
                }

                // By this point we had a header we should have been able to verify but for some reason
                // it was not correctly structured.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    // No suitable header was found so authentication was not even attempted.
    return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
 
示例29
@Override
public AuthenticationMechanismOutcome run() throws GSSException {
    NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
    if (negContext == null) {
        negContext = new NegotiationContext();
        exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
        // Also cache it on the connection for future calls.
        exchange.getConnection().putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
    }

    GSSContext gssContext = negContext.getGssContext();
    if (gssContext == null) {
        GSSManager manager = GSSManager.getInstance();

        GSSCredential credential = manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, mechanisms, GSSCredential.ACCEPT_ONLY);

        gssContext = manager.createContext(credential);

        negContext.setGssContext(gssContext);
    }

    byte[] respToken = gssContext.acceptSecContext(challenge.array(), challenge.arrayOffset(), challenge.limit());
    negContext.setResponseToken(respToken);

    if (negContext.isEstablished()) {

        if (respToken != null) {
            // There will be no further challenge but we do have a token so set it here.
            exchange.getResponseHeaders().add(WWW_AUTHENTICATE,
                    NEGOTIATE_PREFIX + FlexBase64.encodeString(respToken, false));
        }
        IdentityManager identityManager = securityContext.getIdentityManager();
        // get the client authenticate class and user type from the exchange.
        String clientAuthClass = null;
        String userType = null;
        Map<String, Deque<String>> params = exchange.getQueryParameters();
        Deque<String> clientIdDeque = params.get("client_id");
        if(clientIdDeque != null) {
            String clientId = clientIdDeque.getFirst();
            IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
            Client client = clients.get(clientId);
            if(client != null) {
                clientAuthClass = client.getAuthenticateClass();
            }
        }
        Deque<String> userTypeDeque = params.get("user_type");
        if(userTypeDeque != null) {
            userType = userTypeDeque.getFirst();
        }

        final Account account = identityManager.verify(new LightGSSContextCredential(negContext.getGssContext(), clientAuthClass, userType));
        if (account != null) {
            securityContext.authenticationComplete(account, name, false);
            return AuthenticationMechanismOutcome.AUTHENTICATED;
        } else {
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }
    } else {
        // This isn't a failure but as the context is not established another round trip with the client is needed.
        return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
    }
}
 
示例30
/**
 * @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
 */
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {

    List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
    if (authHeaders != null) {
        for (String current : authHeaders) {
            if (current.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {

                String base64Challenge = current.substring(PREFIX_LENGTH);
                String plainChallenge = null;
                try {
                    ByteBuffer decode = FlexBase64.decode(base64Challenge);

                    Charset charset = this.charset;
                    if(!userAgentCharsets.isEmpty()) {
                        String ua = exchange.getRequestHeaders().getFirst(Headers.USER_AGENT);
                        if(ua != null) {
                            for (Map.Entry<Pattern, Charset> entry : userAgentCharsets.entrySet()) {
                                if(entry.getKey().matcher(ua).find()) {
                                    charset = entry.getValue();
                                    break;
                                }
                            }
                        }
                    }

                    plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
                    if(logger.isDebugEnabled()) logger.debug("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
                } catch (IOException e) {
                    logger.error("Failed to decode basic auth header " + base64Challenge + " in " + exchange, e);
                }
                int colonPos;
                if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
                    String userName = plainChallenge.substring(0, colonPos);
                    char[] password = plainChallenge.substring(colonPos + 1).toCharArray();

                    // get clientAuthClass and userType
                    String clientAuthClass = null;
                    String userType = null;
                    Map<String, Deque<String>> params = exchange.getQueryParameters();
                    Deque<String> clientIdDeque = params.get("client_id");
                    if(clientIdDeque != null) {
                        String clientId = clientIdDeque.getFirst();
                        IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
                        Client client = clients.get(clientId);
                        if(client != null) {
                            clientAuthClass = client.getAuthenticateClass();
                        }
                    }
                    Deque<String> userTypeDeque = params.get("user_type");
                    if(userTypeDeque != null) {
                        userType = userTypeDeque.getFirst();
                    }

                    IdentityManager idm = getIdentityManager(securityContext);
                    LightPasswordCredential credential = new LightPasswordCredential(password, clientAuthClass, userType, exchange);
                    try {
                        final AuthenticationMechanismOutcome result;
                        Account account = idm.verify(userName, credential);
                        if (account != null) {
                            securityContext.authenticationComplete(account, name, false);
                            result = AuthenticationMechanismOutcome.AUTHENTICATED;
                        } else {
                            securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), name);
                            result = AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
                        }
                        return result;
                    } finally {
                        clear(password);
                    }
                }

                // By this point we had a header we should have been able to verify but for some reason
                // it was not correctly structured.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }
    }

    // No suitable header has been found in this request,
    return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}