CSharpRTMP.Core.Protocols.Rtmp.BaseRTMPAppProtocolHandler.AuthenticateInboundAdobe C# (CSharp) Method

AuthenticateInboundAdobe() private method

private AuthenticateInboundAdobe ( BaseRTMPProtocol pFrom, AmfMessage request, Variant authState ) : bool
pFrom BaseRTMPProtocol
request AmfMessage
authState Variant
return bool
        private bool AuthenticateInboundAdobe(BaseRTMPProtocol pFrom,  AmfMessage request, Variant authState)
        {
            if (authState["stage"] == null) authState["stage"] = "inProgress";
            else if (authState["stage"] == "authenticated") return true;
            if (authState["stage"] != "inProgress")
            {
                Logger.FATAL("This protocol in not in the authenticating mode");
                return false;
            }
            //1. Validate the type of request
            if (request.MessageType != Defines.RM_HEADER_MESSAGETYPE_INVOKE)
            {
                this.Log().Info("This is not an invoke. Wait for it...");
                return true;
            }

            //2. Validate the invoke function name
            if (request.InvokeFunction != Defines.RM_INVOKE_FUNCTION_CONNECT)
            {
                Logger.FATAL("This is not a connect invoke");
                return false;
            }

            //3. Pick up the first param in the invoke
            Variant connectParams = request.InvokeParam[0];
            if (connectParams != VariantType.Map)
            {
                Logger.FATAL("first invoke param must be a map");
                return false;
            }
            //4. pick up the agent name
            if ((connectParams[Defines.RM_INVOKE_PARAMS_CONNECT_FLASHVER] == null)
                    || (connectParams[Defines.RM_INVOKE_PARAMS_CONNECT_FLASHVER] != VariantType.String))
            {
                Logger.WARN("Incorrect user agent");
                authState["stage"] = "authenticated";
                authState["canPublish"] = false;
                authState["canOverrideStreamName"] = false;
                return true;
            }
            string flashVer = connectParams[Defines.RM_INVOKE_PARAMS_CONNECT_FLASHVER];

            //6. test the flash ver against the allowed encoder agents
            if (_adobeAuthSettings[Defines.CONF_APPLICATION_AUTH_ENCODER_AGENTS, flashVer] == null)
            {
                Logger.WARN("This agent is not on the list of allowed encoders: `{0}`", flashVer);
                authState["stage"] = "authenticated";
                authState["canPublish"] = false;
                authState["canOverrideStreamName"] = false;
                return true;
            }

            //7. pick up the tcUrl from the first param
            if ((connectParams[Defines.RM_INVOKE_PARAMS_CONNECT_APP] == null)
                    || (connectParams[Defines.RM_INVOKE_PARAMS_CONNECT_APP] != VariantType.String))
            {
                Logger.WARN("Incorrect app url");
                authState["stage"] = "authenticated";
                authState["canPublish"] = (bool)false;
                authState["canOverrideStreamName"] = (bool)false;
                return true;
            }
            string appUrl = connectParams[Defines.RM_INVOKE_PARAMS_CONNECT_APP];

            //8. Split the URI into parts
            var appUrlParts = appUrl.Split('?');
            if (appUrlParts.Length == 1)
            {
                //bare request. We need to tell him that he needs auth
                if (!pFrom.SendMessage( ConnectionMessageFactory.GetInvokeConnectError(request,
                        "[ AccessManager.Reject ] : [ code=403 need auth; authmod=adobe ] : ")))
                {
                    Logger.FATAL("Unable to send message");
                    return false;
                }

                if (!pFrom.SendMessage( ConnectionMessageFactory.GetInvokeClose()))
                {
                    Logger.FATAL("Unable to send message");
                    return false;
                }
                //pFrom.SendMessagesBlock.TriggerBatch();
                pFrom.EnqueueForOutbound(pFrom.OutputBuffer);
                pFrom.GracefullyEnqueueForDelete();
                return true;
            }
            else if (appUrlParts.Length == 2)
            {
                var _params = appUrlParts[1].GetURLParam();
                if ((!_params.ContainsKey("authmod")) || (!_params.ContainsKey("user")))
                {
                    Logger.WARN("Invalid appUrl: {0}", appUrl);
                    authState["stage"] = "authenticated";
                    authState["canPublish"] = false;
                    authState["canOverrideStreamName"] = false;
                    return true;
                }

                string user = _params["user"];

                if (_params.ContainsKey("challenge")
                    && _params.ContainsKey("response")
                    && _params.ContainsKey("opaque"))
                {
                    string challenge = _params["challenge"];
                    string response = _params["response"];
                    string opaque = _params["opaque"];
                    string password = GetAuthPassword(user);
                    if (password == "")
                    {
                        Logger.WARN("No such user: `{0}`", user);

                        if (!pFrom.SendMessage( ConnectionMessageFactory.GetInvokeConnectError(request,
                            "[ AccessManager.Reject ] : [ authmod=adobe ] : ?reason=authfailed&opaque=vgoAAA==")))
                        {
                            Logger.FATAL("Unable to send message");
                            return false;
                        }

                        if (!pFrom.SendMessage( ConnectionMessageFactory.GetInvokeClose()))
                        {
                            Logger.FATAL("Unable to send message");
                            return false;
                        }
                        //pFrom.SendMessagesBlock.TriggerBatch();
                        pFrom.EnqueueForOutbound(pFrom.OutputBuffer);
                        pFrom.GracefullyEnqueueForDelete();
                        return true;
                    }
                    var md5 = MD5.Create();
                    string str1 = user + _adobeAuthSalt + password;
                    string hash1 = Convert.ToBase64String(md5.ComputeHash(Encoding.ASCII.GetBytes(str1)));
                    string str2 = hash1 + opaque + challenge;
                    string wanted = Convert.ToBase64String(md5.ComputeHash(Encoding.ASCII.GetBytes(str2)));

                    if (response == wanted)
                    {
                        authState["stage"] = "authenticated";
                        authState["canPublish"] = true;
                        authState["canOverrideStreamName"] = true;
                        Logger.WARN("User `{0}` authenticated", user);
                        return true;
                    }
                    else
                    {
                        Logger.WARN("Invalid password for user `{0}`", user);
                        if (!pFrom.SendMessage( ConnectionMessageFactory.GetInvokeConnectError(request,
                            "[ AccessManager.Reject ] : [ authmod=adobe ] : ?reason=authfailed&opaque=vgoAAA==")))
                        {
                            Logger.FATAL("Unable to send message");
                            return false;
                        }
                        if (!pFrom.SendMessage( ConnectionMessageFactory.GetInvokeClose()))
                        {
                            Logger.FATAL("Unable to send message");
                            return false;
                        }
                        //pFrom.SendMessagesBlock.TriggerBatch();
                        pFrom.EnqueueForOutbound(pFrom.OutputBuffer);
                        pFrom.GracefullyEnqueueForDelete();
                        return true;
                    }
                }
                else
                {
                    string challenge = Utils.GenerateRandomString(6) + "==";
                    string opaque = challenge;
                    string description =
                        "[ AccessManager.Reject ] : [ authmod=adobe ] : ?reason=needauth&user={0}&salt={1}&challenge={2}&opaque={3}";

                    description = string.Format(description, user, _adobeAuthSalt, challenge, opaque);

                    if (!pFrom.SendMessage(ConnectionMessageFactory.GetInvokeConnectError(request, description)))
                    {
                        Logger.FATAL("Unable to send message");
                        return false;
                    }


                    if (!pFrom.SendMessage(ConnectionMessageFactory.GetInvokeClose()))
                    {
                        Logger.FATAL("Unable to send message");
                        return false;
                    }
                    //pFrom.SendMessagesBlock.TriggerBatch();
                    pFrom.EnqueueForOutbound(pFrom.OutputBuffer);
                    pFrom.GracefullyEnqueueForDelete();
                    return true;
                }
            }
            else
            {
                Logger.FATAL("Invalid appUrl: {0}", appUrl);
                return false;
            }
        }