示例#1
0
 /// <summary>Evaluate the server provided challenge.</summary>
 /// <remarks>
 /// Evaluate the server provided challenge.  The server must send a token
 /// if it's not done.  If the server is done, the challenge token is
 /// optional because not all mechanisms send a final token for the client to
 /// update its internal state.  The client must also be done after
 /// evaluating the optional token to ensure a malicious server doesn't
 /// prematurely end the negotiation with a phony success.
 /// </remarks>
 /// <param name="saslResponse">- client response to challenge</param>
 /// <param name="serverIsDone">- server negotiation state</param>
 /// <exception cref="Javax.Security.Sasl.SaslException">- any problems with negotiation
 ///     </exception>
 private byte[] SaslEvaluateToken(RpcHeaderProtos.RpcSaslProto saslResponse, bool
                                  serverIsDone)
 {
     byte[] saslToken = null;
     if (saslResponse.HasToken())
     {
         saslToken = saslResponse.GetToken().ToByteArray();
         saslToken = saslClient.EvaluateChallenge(saslToken);
     }
     else
     {
         if (!serverIsDone)
         {
             // the server may only omit a token when it's done
             throw new SaslException("Server challenge contains no token");
         }
     }
     if (serverIsDone)
     {
         // server tried to report success before our client completed
         if (!saslClient.IsComplete())
         {
             throw new SaslException("Client is out of sync with server");
         }
         // a client cannot generate a response to a success message
         if (saslToken != null)
         {
             throw new SaslException("Client generated spurious response");
         }
     }
     return(saslToken);
 }
示例#2
0
 /// <exception cref="System.IO.IOException"/>
 private void SendSaslMessage(DataOutputStream @out, RpcHeaderProtos.RpcSaslProto
                              message)
 {
     if (Log.IsDebugEnabled())
     {
         Log.Debug("Sending sasl message " + message);
     }
     ProtobufRpcEngine.RpcRequestMessageWrapper request = new ProtobufRpcEngine.RpcRequestMessageWrapper
                                                              (saslHeader, message);
     @out.WriteInt(request.GetLength());
     request.Write(@out);
     @out.Flush();
 }
示例#3
0
            /// <exception cref="System.IO.IOException"/>
            public override void Write(byte[] buf, int off, int len)
            {
                if (SaslRpcClient.Log.IsDebugEnabled())
                {
                    SaslRpcClient.Log.Debug("wrapping token of length:" + len);
                }
                buf = this._enclosing.saslClient.Wrap(buf, off, len);
                RpcHeaderProtos.RpcSaslProto saslMessage = ((RpcHeaderProtos.RpcSaslProto)RpcHeaderProtos.RpcSaslProto
                                                            .NewBuilder().SetState(RpcHeaderProtos.RpcSaslProto.SaslState.Wrap).SetToken(ByteString
                                                                                                                                         .CopyFrom(buf, 0, buf.Length)).Build());
                ProtobufRpcEngine.RpcRequestMessageWrapper request = new ProtobufRpcEngine.RpcRequestMessageWrapper
                                                                         (SaslRpcClient.saslHeader, saslMessage);
                DataOutputStream dob = new DataOutputStream(this.@out);

                dob.WriteInt(request.GetLength());
                request.Write(dob);
            }
示例#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);
        }