Example #1
0
        /// <summary>
        /// Instantiate a sasl client for the first supported auth type in the
        /// given list.
        /// </summary>
        /// <remarks>
        /// Instantiate a sasl client for the first supported auth type in the
        /// given list.  The auth type must be defined, enabled, and the user
        /// must possess the required credentials, else the next auth is tried.
        /// </remarks>
        /// <param name="authTypes">to attempt in the given order</param>
        /// <returns>SaslAuth of instantiated client</returns>
        /// <exception cref="AccessControlException">- client doesn't support any of the auths
        ///     </exception>
        /// <exception cref="System.IO.IOException">- misc errors</exception>
        /// <exception cref="Javax.Security.Sasl.SaslException"/>
        /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/>
        private RpcHeaderProtos.RpcSaslProto.SaslAuth SelectSaslClient(IList <RpcHeaderProtos.RpcSaslProto.SaslAuth
                                                                              > authTypes)
        {
            RpcHeaderProtos.RpcSaslProto.SaslAuth selectedAuthType = null;
            bool switchToSimple = false;

            foreach (RpcHeaderProtos.RpcSaslProto.SaslAuth authType in authTypes)
            {
                if (!IsValidAuthType(authType))
                {
                    continue;
                }
                // don't know what it is, try next
                SaslRpcServer.AuthMethod authMethod = SaslRpcServer.AuthMethod.ValueOf(authType.GetMethod
                                                                                           ());
                if (authMethod == SaslRpcServer.AuthMethod.Simple)
                {
                    switchToSimple = true;
                }
                else
                {
                    saslClient = CreateSaslClient(authType);
                    if (saslClient == null)
                    {
                        // client lacks credentials, try next
                        continue;
                    }
                }
                selectedAuthType = authType;
                break;
            }
            if (saslClient == null && !switchToSimple)
            {
                IList <string> serverAuthMethods = new AList <string>();
                foreach (RpcHeaderProtos.RpcSaslProto.SaslAuth authType_1 in authTypes)
                {
                    serverAuthMethods.AddItem(authType_1.GetMethod());
                }
                throw new AccessControlException("Client cannot authenticate via:" + serverAuthMethods
                                                 );
            }
            if (Log.IsDebugEnabled())
            {
                Log.Debug("Use " + selectedAuthType.GetMethod() + " authentication for protocol "
                          + protocol.Name);
            }
            return(selectedAuthType);
        }
Example #2
0
 private bool IsValidAuthType(RpcHeaderProtos.RpcSaslProto.SaslAuth authType)
 {
     SaslRpcServer.AuthMethod authMethod;
     try
     {
         authMethod = SaslRpcServer.AuthMethod.ValueOf(authType.GetMethod());
     }
     catch (ArgumentException)
     {
         // unknown auth
         authMethod = null;
     }
     // do we know what it is?  is it using our mechanism?
     return(authMethod != null && authMethod.GetMechanismName().Equals(authType.GetMechanism
                                                                           ()));
 }
Example #3
0
        public SaslRpcServer(SaslRpcServer.AuthMethod authMethod)
        {
            this.authMethod = authMethod;
            mechanism       = authMethod.GetMechanismName();
            switch (authMethod)
            {
            case SaslRpcServer.AuthMethod.Simple:
            {
                return;
            }

            case SaslRpcServer.AuthMethod.Token:
            {
                // no sasl for simple
                protocol = string.Empty;
                serverId = SaslRpcServer.SaslDefaultRealm;
                break;
            }

            case SaslRpcServer.AuthMethod.Kerberos:
            {
                string fullName = UserGroupInformation.GetCurrentUser().GetUserName();
                if (Log.IsDebugEnabled())
                {
                    Log.Debug("Kerberos principal name is " + fullName);
                }
                // don't use KerberosName because we don't want auth_to_local
                string[] parts = fullName.Split("[/@]", 3);
                protocol = parts[0];
                // should verify service host is present here rather than in create()
                // but lazy tests are using a UGI that isn't a SPN...
                serverId = (parts.Length < 2) ? string.Empty : parts[1];
                break;
            }

            default:
            {
                // we should never be able to get here
                throw new AccessControlException("Server does not support SASL " + authMethod);
            }
            }
        }
Example #4
0
        /// <summary>
        /// Do client side SASL authentication with server via the given InputStream
        /// and OutputStream
        /// </summary>
        /// <param name="inS">InputStream to use</param>
        /// <param name="outS">OutputStream to use</param>
        /// <returns>AuthMethod used to negotiate the connection</returns>
        /// <exception cref="System.IO.IOException"/>
        public virtual SaslRpcServer.AuthMethod SaslConnect(InputStream inS, OutputStream
                                                            outS)
        {
            DataInputStream  inStream  = new DataInputStream(new BufferedInputStream(inS));
            DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(outS));

            // redefined if/when a SASL negotiation starts, can be queried if the
            // negotiation fails
            authMethod = SaslRpcServer.AuthMethod.Simple;
            SendSaslMessage(outStream, negotiateRequest);
            // loop until sasl is complete or a rpc error occurs
            bool done = false;

            do
            {
                int totalLen = inStream.ReadInt();
                ProtobufRpcEngine.RpcResponseMessageWrapper responseWrapper = new ProtobufRpcEngine.RpcResponseMessageWrapper
                                                                                  ();
                responseWrapper.ReadFields(inStream);
                RpcHeaderProtos.RpcResponseHeaderProto header = responseWrapper.GetMessageHeader(
                    );
                switch (header.GetStatus())
                {
                case RpcHeaderProtos.RpcResponseHeaderProto.RpcStatusProto.Error:
                case RpcHeaderProtos.RpcResponseHeaderProto.RpcStatusProto.Fatal:
                {
                    // might get a RPC error during
                    throw new RemoteException(header.GetExceptionClassName(), header.GetErrorMsg());
                }

                default:
                {
                    break;
                }
                }
                if (totalLen != responseWrapper.GetLength())
                {
                    throw new SaslException("Received malformed response length");
                }
                if (header.GetCallId() != Server.AuthProtocol.Sasl.callId)
                {
                    throw new SaslException("Non-SASL response during negotiation");
                }
                RpcHeaderProtos.RpcSaslProto saslMessage = RpcHeaderProtos.RpcSaslProto.ParseFrom
                                                               (responseWrapper.GetMessageBytes());
                if (Log.IsDebugEnabled())
                {
                    Log.Debug("Received SASL message " + saslMessage);
                }
                // handle sasl negotiation process
                RpcHeaderProtos.RpcSaslProto.Builder response = null;
                switch (saslMessage.GetState())
                {
                case RpcHeaderProtos.RpcSaslProto.SaslState.Negotiate:
                {
                    // create a compatible SASL client, throws if no supported auths
                    RpcHeaderProtos.RpcSaslProto.SaslAuth saslAuthType = SelectSaslClient(saslMessage
                                                                                          .GetAuthsList());
                    // define auth being attempted, caller can query if connect fails
                    authMethod = SaslRpcServer.AuthMethod.ValueOf(saslAuthType.GetMethod());
                    byte[] responseToken = null;
                    if (authMethod == SaslRpcServer.AuthMethod.Simple)
                    {
                        // switching to SIMPLE
                        done = true;
                    }
                    else
                    {
                        // not going to wait for success ack
                        byte[] challengeToken = null;
                        if (saslAuthType.HasChallenge())
                        {
                            // server provided the first challenge
                            challengeToken = saslAuthType.GetChallenge().ToByteArray();
                            saslAuthType   = ((RpcHeaderProtos.RpcSaslProto.SaslAuth)RpcHeaderProtos.RpcSaslProto.SaslAuth
                                              .NewBuilder(saslAuthType).ClearChallenge().Build());
                        }
                        else
                        {
                            if (saslClient.HasInitialResponse())
                            {
                                challengeToken = new byte[0];
                            }
                        }
                        responseToken = (challengeToken != null) ? saslClient.EvaluateChallenge(challengeToken
                                                                                                ) : new byte[0];
                    }
                    response = CreateSaslReply(RpcHeaderProtos.RpcSaslProto.SaslState.Initiate, responseToken
                                               );
                    response.AddAuths(saslAuthType);
                    break;
                }

                case RpcHeaderProtos.RpcSaslProto.SaslState.Challenge:
                {
                    if (saslClient == null)
                    {
                        // should probably instantiate a client to allow a server to
                        // demand a specific negotiation
                        throw new SaslException("Server sent unsolicited challenge");
                    }
                    byte[] responseToken = SaslEvaluateToken(saslMessage, false);
                    response = CreateSaslReply(RpcHeaderProtos.RpcSaslProto.SaslState.Response, responseToken
                                               );
                    break;
                }

                case RpcHeaderProtos.RpcSaslProto.SaslState.Success:
                {
                    // simple server sends immediate success to a SASL client for
                    // switch to simple
                    if (saslClient == null)
                    {
                        authMethod = SaslRpcServer.AuthMethod.Simple;
                    }
                    else
                    {
                        SaslEvaluateToken(saslMessage, true);
                    }
                    done = true;
                    break;
                }

                default:
                {
                    throw new SaslException("RPC client doesn't support SASL " + saslMessage.GetState
                                                ());
                }
                }
                if (response != null)
                {
                    SendSaslMessage(outStream, ((RpcHeaderProtos.RpcSaslProto)response.Build()));
                }
            }while (!done);
            return(authMethod);
        }
Example #5
0
        /// <summary>Try to create a SaslClient for an authentication type.</summary>
        /// <remarks>
        /// Try to create a SaslClient for an authentication type.  May return
        /// null if the type isn't supported or the client lacks the required
        /// credentials.
        /// </remarks>
        /// <param name="authType">- the requested authentication method</param>
        /// <returns>SaslClient for the authType or null</returns>
        /// <exception cref="Javax.Security.Sasl.SaslException">- error instantiating client</exception>
        /// <exception cref="System.IO.IOException">- misc errors</exception>
        private SaslClient CreateSaslClient(RpcHeaderProtos.RpcSaslProto.SaslAuth authType
                                            )
        {
            string saslUser = null;
            // SASL requires the client and server to use the same proto and serverId
            // if necessary, auth types below will verify they are valid
            string saslProtocol   = authType.GetProtocol();
            string saslServerName = authType.GetServerId();
            IDictionary <string, string> saslProperties = saslPropsResolver.GetClientProperties
                                                              (serverAddr.Address);
            CallbackHandler saslCallback = null;

            SaslRpcServer.AuthMethod method = SaslRpcServer.AuthMethod.ValueOf(authType.GetMethod
                                                                                   ());
            switch (method)
            {
            case SaslRpcServer.AuthMethod.Token:
            {
                Org.Apache.Hadoop.Security.Token.Token <object> token = GetServerToken(authType);
                if (token == null)
                {
                    return(null);
                }
                // tokens aren't supported or user doesn't have one
                saslCallback = new SaslRpcClient.SaslClientCallbackHandler(token);
                break;
            }

            case SaslRpcServer.AuthMethod.Kerberos:
            {
                if (ugi.GetRealAuthenticationMethod().GetAuthMethod() != SaslRpcServer.AuthMethod
                    .Kerberos)
                {
                    return(null);
                }
                // client isn't using kerberos
                string serverPrincipal = GetServerPrincipal(authType);
                if (serverPrincipal == null)
                {
                    return(null);
                }
                // protocol doesn't use kerberos
                if (Log.IsDebugEnabled())
                {
                    Log.Debug("RPC Server's Kerberos principal name for protocol=" + protocol.GetCanonicalName
                                  () + " is " + serverPrincipal);
                }
                break;
            }

            default:
            {
                throw new IOException("Unknown authentication method " + method);
            }
            }
            string mechanism = method.GetMechanismName();

            if (Log.IsDebugEnabled())
            {
                Log.Debug("Creating SASL " + mechanism + "(" + method + ") " + " client to authenticate to service at "
                          + saslServerName);
            }
            return(Javax.Security.Sasl.Sasl.CreateSaslClient(new string[] { mechanism }, saslUser
                                                             , saslProtocol, saslServerName, saslProperties, saslCallback));
        }