📄 socks5logichandler.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */package org.apache.mina.proxy.handlers.socks;import java.io.UnsupportedEncodingException;import java.net.Inet4Address;import java.net.Inet6Address;import java.net.InetSocketAddress;import org.apache.mina.core.buffer.IoBuffer;import org.apache.mina.core.filterchain.IoFilter.NextFilter;import org.apache.mina.proxy.session.ProxyIoSession;import org.apache.mina.proxy.utils.ByteUtilities;import org.ietf.jgss.GSSContext;import org.ietf.jgss.GSSException;import org.ietf.jgss.GSSManager;import org.ietf.jgss.GSSName;import org.ietf.jgss.Oid;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Socks5LogicHandler.java - SOCKS5 authentication mechanisms logic handler. * * @author The Apache MINA Project (dev@mina.apache.org) * @version $Rev: 729187 $, $Date: 2008-12-24 02:28:51 +0100 (Wed, 24 Dec 2008) $ * @since MINA 2.0.0-M3 */public class Socks5LogicHandler extends AbstractSocksLogicHandler { private final static Logger logger = LoggerFactory .getLogger(Socks5LogicHandler.class); /** * The selected authentication method attribute key. */ private final static String SELECTED_AUTH_METHOD = Socks5LogicHandler.class .getName() + ".SelectedAuthMethod"; /** * The current step in the handshake attribute key. */ private final static String HANDSHAKE_STEP = Socks5LogicHandler.class .getName() + ".HandshakeStep"; /** * The Java GSS-API context attribute key. */ private final static String GSS_CONTEXT = Socks5LogicHandler.class .getName() + ".GSSContext"; /** * Last GSS token received attribute key. */ private final static String GSS_TOKEN = Socks5LogicHandler.class.getName() + ".GSSToken"; /** * {@inheritDoc} */ public Socks5LogicHandler(final ProxyIoSession proxyIoSession) { super(proxyIoSession); getSession().setAttribute(HANDSHAKE_STEP, SocksProxyConstants.SOCKS5_GREETING_STEP); } /** * Perform the handshake process. */ public synchronized void doHandshake(final NextFilter nextFilter) { logger.debug(" doHandshake()"); // Send request writeRequest(nextFilter, request, ((Integer) getSession().getAttribute( HANDSHAKE_STEP)).intValue()); } /** * Encode the initial greeting packet. * * @param request the socks proxy request data * @return the encoded buffer */ private IoBuffer encodeInitialGreetingPacket(final SocksProxyRequest request) { byte nbMethods = (byte) SocksProxyConstants.SUPPORTED_AUTH_METHODS.length; IoBuffer buf = IoBuffer.allocate(2 + nbMethods); buf.put(request.getProtocolVersion()); buf.put(nbMethods); buf.put(SocksProxyConstants.SUPPORTED_AUTH_METHODS); return buf; } /** * Encode the proxy authorization request packet. * * @param request the socks proxy request data * @return the encoded buffer * @throws UnsupportedEncodingException if request's hostname charset * can't be converted to ASCII. */ private IoBuffer encodeProxyRequestPacket(final SocksProxyRequest request) throws UnsupportedEncodingException { int len = 6; byte[] host = request.getHost() != null ? request.getHost().getBytes( "ASCII") : null; InetSocketAddress adr = request.getEndpointAddress(); byte addressType = 0; if (adr != null && !adr.isUnresolved()) { if (adr.getAddress() instanceof Inet6Address) { len += 16; addressType = SocksProxyConstants.IPV6_ADDRESS_TYPE; } else if (adr.getAddress() instanceof Inet4Address) { len += 4; addressType = SocksProxyConstants.IPV4_ADDRESS_TYPE; } } else { len += 1 + host.length; addressType = SocksProxyConstants.DOMAIN_NAME_ADDRESS_TYPE; } IoBuffer buf = IoBuffer.allocate(len); buf.put(request.getProtocolVersion()); buf.put(request.getCommandCode()); buf.put((byte) 0x00); // Reserved buf.put(addressType); if (addressType == SocksProxyConstants.DOMAIN_NAME_ADDRESS_TYPE) { buf.put((byte) host.length); buf.put(host); } else { buf.put(request.getIpAddress()); } buf.put(request.getPort()); return buf; } /** * Encode the authentication packet for supported authentication methods. * * @param request the socks proxy request data * @return the encoded buffer, if null then authentication step is over * and handshake process can jump immediately to the next step without waiting * for a server reply. * @throws UnsupportedEncodingException * @throws GSSException when something fails while using GSSAPI */ private IoBuffer encodeAuthenticationPacket(final SocksProxyRequest request) throws UnsupportedEncodingException, GSSException { byte method = ((Byte) getSession().getAttribute( Socks5LogicHandler.SELECTED_AUTH_METHOD)).byteValue(); switch (method) { case SocksProxyConstants.NO_AUTH: // In this case authentication is immediately considered as successfull // Next writeRequest() call will send the proxy request getSession().setAttribute(HANDSHAKE_STEP, SocksProxyConstants.SOCKS5_REQUEST_STEP); break; case SocksProxyConstants.GSSAPI_AUTH: return encodeGSSAPIAuthenticationPacket(request); case SocksProxyConstants.BASIC_AUTH: // The basic auth scheme packet is sent byte[] user = request.getUserName().getBytes("ASCII"); byte[] pwd = request.getPassword().getBytes("ASCII"); IoBuffer buf = IoBuffer.allocate(3 + user.length + pwd.length); buf.put(SocksProxyConstants.BASIC_AUTH_SUBNEGOTIATION_VERSION); buf.put((byte) user.length); buf.put(user); buf.put((byte) pwd.length); buf.put(pwd); return buf; } return null; } /** * Encode the authentication packet for supported authentication methods. * * @param request the socks proxy request data * @return the encoded buffer * @throws GSSException when something fails while using GSSAPI */ private IoBuffer encodeGSSAPIAuthenticationPacket( final SocksProxyRequest request) throws GSSException { GSSContext ctx = (GSSContext) getSession().getAttribute(GSS_CONTEXT); if (ctx == null) { GSSManager manager = GSSManager.getInstance(); GSSName serverName = manager.createName(request .getServiceKerberosName(), null); Oid krb5OID = new Oid(SocksProxyConstants.KERBEROS_V5_OID); if (logger.isDebugEnabled()) { logger.debug("Available mechs:"); for (Oid o : manager.getMechs()) { if (o.equals(krb5OID)) { logger.debug("Found Kerberos V OID available"); } logger.debug("{} with oid = {}", manager.getNamesForMech(o), o); } } ctx = manager.createContext(serverName, krb5OID, null, GSSContext.DEFAULT_LIFETIME);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -