Beispiel #1
0
        /// <summary>
        /// Handle a full HTTP Request
        /// </summary>
        /// <param name="headers">Headers of the request</param>
        /// <param name="readObject">The client's session data</param>
        /// <param name="method">The method of the request</param>
        /// <param name="resource">The requested function</param>
        /// <param name="requestData">The body of the request</param>
        private void HandleRequest(List <string> headers, ReadObject readObject, string method, string resource, string requestData)
        {
            bool gotTracker = false; //True if client sent tracker in the headers

            //Check if client sent header
            foreach (string header in headers)
            {
                if (header.StartsWith("Client-Tracker"))
                {
                    int    delimiter = header.IndexOf(':') + 2; //The : and the space => 2
                    string value     = header.Substring(delimiter);
                    if (int.TryParse(value, out int tracker))
                    {
                        lock (trackerLockObject)
                        {
                            if (trackers.TryGetValue(tracker, out ReadObject tempReadObject))
                            {
                                readObject = tempReadObject;
                                gotTracker = true;
                            }
                            else
                            {
                                Form1.WriteLine("Client not registered with this ID");
                            }
                        }
                    }
                    else
                    {
                        Form1.WriteLine("Can't parse client tracker");
                    }

                    break;
                }
            }

            if (method == "POST" && gotTracker) //POST Functions
            {
                if (resource == "stor-pw")      //Store password on phone
                {
                    string userName = null;
                    string password = null;

                    int userNameLength = int.Parse(requestData.Substring(0, 10));
                    userName = requestData.Substring(10, userNameLength);
                    int passwordLength = int.Parse(requestData.Substring(10 + userNameLength, 10));
                    password = requestData.Substring(20 + userNameLength, passwordLength);
                    string url = requestData.Substring(20 + userNameLength + passwordLength);

                    if (password != null && userName != null)
                    {
                        Form1.WriteLine($"Requested Password Storage: usr:{userName} ; pwd:{password}; url:{url}");
                        readObject.urlHash  = SessionCrypto.DigestMessage(url);
                        readObject.userName = userName;
                        readObject.password = password;
                        ctx.RequestPasswordStore(url, userName, password);
                        SendMessage(readObject.client, "stor-init");
                    }
                }
                else if (resource == "getpw") //Get password from phone
                {
                    readObject.urlHash = SessionCrypto.DigestMessage(requestData);
                    getPasswordQueue.Add(readObject.urlHash);
                    ctx.RequestPasswordGet(readObject.urlHash);
                    SendMessage(readObject.client, "ok");
                }
                else if (resource == "getkey")
                {
                    readObject.urlHash = SessionCrypto.DigestMessage(requestData);
                    getKeyQueue.Add(readObject.urlHash);
                    ctx.RequestKeyGet(readObject.urlHash);
                    SendMessage(readObject.client, "get-ok");
                }
                else if (resource == "pushkey")
                {
                    int    urlLength   = int.Parse(requestData.Substring(0, 10));
                    string url         = requestData.Substring(10, urlLength);
                    int    tokenLength = int.Parse(requestData.Substring(10 + urlLength, 10));
                    string token       = requestData.Substring(20 + urlLength, tokenLength);
                    readObject.urlHash = SessionCrypto.DigestMessage(url);
                    storeKeyQueue.Add(readObject.urlHash);
                    storeKeyQueue.UpdateExtraData(readObject.urlHash, token);
                    ctx.RequestKeyStore(readObject.urlHash);
                    SendMessage(readObject.client, "push-ok");
                    Form1.WriteLine($"ReadObject url hashed: {readObject.urlHash}");
                }

                readObject.contentLength = 0;
            }
            else if (method == "GET")      //Get functions
            {
                if (resource == "tracker") //Client requested a new tracker ID
                {
                    lock (idLockerObject)
                    {
                        readObject.cTracker = clientTracker;
                        SendMessage(readObject.client, clientTracker.ToString());
                        clientTracker++;
                    }
                }
                else if (!gotTracker) //Drop if not setting tracker and tracker is not set
                {
                    Form1.WriteLine("GET without tracker and not setting tracker");
                }
                else if (resource == "stor-state") //Get the state of storing the password on the phone
                {
                    CredentialTransferState state = (storeQueue.TryGetValue(readObject.urlHash, out CredentialTransferState cts)) ? cts : CredentialTransferState.Pending;
                    string message;
                    switch (state)
                    {
                    case CredentialTransferState.Success:
                        message = "stor-completed";
                        break;

                    case CredentialTransferState.Failed:
                        message = "stor-fail";
                        break;

                    default:
                        message = "stor-pending";
                        break;
                    }

                    SendMessage(readObject.client, message);
                    Form1.WriteLine("Stor get state");
                }
                else if (resource == "get-state") //Get the state of getting hte password from the phone
                {
                    CredentialTransferState qState = getPasswordQueue.GetQueueState(readObject.urlHash);

                    switch (qState)
                    {
                    case CredentialTransferState.Success:
                        object[] extraData = getPasswordQueue.GetQueueData(readObject.urlHash);
                        Tuple <string, string> credentials = new Tuple <string, string>((string)extraData[0], (string)extraData[1]);
                        getPasswordQueue.Remove(readObject.urlHash);
                        SendMessage(readObject.client, $"get-ok{EncodeBodyData(new string[] { credentials.Item1, credentials.Item2 })}");
                        Form1.WriteLine("Password sent to browser");
                        break;

                    case CredentialTransferState.Failed:
                        SendMessage(readObject.client, "get-fail");
                        getPasswordQueue.Remove(readObject.urlHash);
                        Form1.WriteLine("Password fail alert sent to the browser");
                        break;

                    default:
                        SendMessage(readObject.client, "get-pending");
                        break;
                    }
                }
                else if (resource == "kget-state")
                {
                    CredentialTransferState qState = getKeyQueue.GetQueueState(readObject.urlHash);

                    switch (qState)
                    {
                    case CredentialTransferState.Success:
                        object[] extraData = getKeyQueue.GetQueueData(readObject.urlHash);
                        string   keyToken  = (string)extraData[0];
                        getKeyQueue.Remove(readObject.urlHash);
                        SendMessage(readObject.client, $"get-ok{keyToken}");
                        Form1.WriteLine("Key sent to browser");
                        break;

                    case CredentialTransferState.Failed:
                        SendMessage(readObject.client, "get-fail");
                        getKeyQueue.Remove(readObject.urlHash);
                        Form1.WriteLine("Key fail alert sent to the browser");
                        break;

                    default:
                        SendMessage(readObject.client, "get-pending");
                        break;
                    }
                }
                else if (resource == "kpush-state")
                {
                    Form1.WriteLine($"ReadObject url hash: {readObject.urlHash}");
                    Form1.WriteLine($"ReadObject client tracker: {readObject.cTracker}");
                    CredentialTransferState qState = storeKeyQueue.GetQueueState(readObject.urlHash);

                    switch (qState)
                    {
                    case CredentialTransferState.Success:
                        object[] extraData = storeKeyQueue.GetQueueData(readObject.urlHash);
                        storeKeyQueue.Remove(readObject.urlHash);
                        SendMessage(readObject.client, $"push-ok");
                        Form1.WriteLine("Key installed on android");
                        break;

                    case CredentialTransferState.Failed:
                        SendMessage(readObject.client, "push-fail");
                        storeKeyQueue.Remove(readObject.urlHash);
                        Form1.WriteLine("Key install failed in android");
                        break;

                    default:
                        SendMessage(readObject.client, "push-pending");
                        break;
                    }
                }

                readObject.contentLength = 0;
            }
            else if (method == "OPTIONS")
            {
                SendMessage(readObject.client, "", "\r\nAccess-Control-Allow-Headers: Client-Tracker");
                Form1.WriteLine("Options response sent");
                readObject.contentLength = 0;
                return;
            }
            else if (!gotTracker) //POST Request (or other?) without tracker
            {
                Form1.WriteLine("Tracker not sent with!");
                readObject.contentLength = 0;
                return;
            }
            else //Invalid request but tracker is set? wierd
            {
                Form1.WriteLine("Invalid Request Type");
                readObject.contentLength = 0;
                return;
            }

            //Store the session data
            lock (trackerLockObject)
            {
                if (trackers.ContainsKey(readObject.cTracker))
                {
                    trackers[readObject.cTracker] = readObject;
                }
                else
                {
                    trackers.Add(readObject.cTracker, readObject);
                }
            }
        }
        /// <summary>
        /// Read messages from the device
        /// </summary>
        /// <param name="ar">Async Result</param>
        private void ReadCallback(IAsyncResult ar)
        {
            int        bytesRead  = 0;
            bool       noRead     = false;
            ReadObject readObject = (ReadObject)ar.AsyncState;

            try
            {
                bytesRead = readObject.client.EndReceive(ar);
            }
            catch (Exception ex)
            {
                ServerError?.Invoke(ex);
                return;
            }

            if (bytesRead > 0)
            {
                if (readObject.isFirstMessage)
                {
                    string derPublicKey = keyGeneration.GetDerPublicKey();
                    SendString(readObject.client, derPublicKey);
                    Form1.WriteLine("Public Key Sent");
                    readObject.isFirstMessage = false;
                }
                else
                {
                    byte[] dataReceived = new byte[bytesRead];
                    Array.Copy(readObject.buffer, dataReceived, bytesRead);
                    string textData = Encoding.UTF8.GetString(dataReceived);

                    if (textData.StartsWith("set-session-key"))
                    {
                        Form1.WriteLine("Got set session key");
                        string encryptedSessionKey = textData.Substring(15);
                        string sessionKey          = Encoding.UTF8.GetString(keyGeneration.DecryptData(Convert.FromBase64String(encryptedSessionKey)));
                        readObject.session.SetSessionKey(sessionKey);
                    }
                    else
                    {
                        Form1.WriteLine("Got session message");
                        byte[] sessionData     = readObject.session.DecryptData(textData);
                        string sessionTextData = Encoding.UTF8.GetString(sessionData);
                        Form1.WriteLine($"Session Data: {sessionTextData}");
                        if (sessionTextData.StartsWith("res-"))
                        {
                            Form1.WriteLine("Got request setter");
                            readObject.requestString = sessionTextData.Substring(sessionTextData.IndexOf('-') + 1);
                            Form1.WriteLine($"Request string set to: {readObject.requestString}");
                            SendString(readObject.client, Convert.ToBase64String(readObject.session.EncryptData(Encoding.UTF8.GetBytes("no-data"))));
                            Form1.WriteLine("Continue message sent to client");
                        }
                        else if (sessionTextData.StartsWith("no-"))
                        {
                            Form1.WriteLine($"Couldn't find credentials on the device: {sessionTextData}");
                            string parameter = sessionTextData.Substring(sessionTextData.IndexOf('-') + 1);
                            if (parameter == "setup")
                            {
                                LockStateChanged?.Invoke(LockState.Failed);
                            }
                            else if (parameter == "fp")
                            {
                                Form1.WriteLine("User failed to authenticate with fingerprint!");
                                if (readObject.requestString == "getkname-windowsLogon")
                                {
                                    WindowsLocking.CancelRegistration();
                                }
                                else if (readObject.requestString.StartsWith("pw-"))
                                {
                                    Form1.WriteLine("Password get failed");
                                    if (jsSrv != null)
                                    {
                                        jsSrv.getPasswordQueue.UpdateState(readObject.requestString.Substring(3), JavascriptServer.CredentialTransferState.Failed);
                                    }
                                }
                                else if (readObject.requestString.StartsWith("storpw-"))
                                {
                                    Form1.WriteLine("Password storage failed");
                                    if (jsSrv != null)
                                    {
                                        jsSrv.getPasswordQueue.UpdateState(readObject.requestString.Substring(7), JavascriptServer.CredentialTransferState.Failed);
                                    }
                                }
                                else if (readObject.requestString.StartsWith("getkname-"))
                                {
                                    Form1.WriteLine("Get key failed");
                                    if (jsSrv != null)
                                    {
                                        jsSrv.getPasswordQueue.UpdateState(readObject.requestString.Substring(10), JavascriptServer.CredentialTransferState.Failed);
                                    }
                                }
                            }

                            noRead = true;
                        }
                        else if (sessionTextData == "getuser")
                        {
                            if (jsSrv == null)
                            {
                                throw new InvalidOperationException("Can't store password while javascript server is down");
                            }
                            Tuple <string, string> creds = jsSrv.GetCredentials(readObject.requestString.Substring(7));
                            if (creds == null)
                            {
                                throw new NullReferenceException("Can't find credentials for the specified web site hash");
                            }
                            readObject.credentials.username = creds.Item1;
                            readObject.credentials.password = creds.Item2;
                            SendString(readObject.client, Convert.ToBase64String(readObject.session.EncryptData(Encoding.UTF8.GetBytes(readObject.credentials.username))));
                        }
                        else if (sessionTextData == "getpass")
                        {
                            SendString(readObject.client, Convert.ToBase64String(readObject.session.EncryptData(Encoding.UTF8.GetBytes(readObject.credentials.password))));
                            if (jsSrv != null)
                            {
                                jsSrv.getPasswordQueue.UpdateState(readObject.requestString.Substring(7), JavascriptServer.CredentialTransferState.Success);
                            }
                            DismissIfOpen?.Invoke();
                            noRead = true;
                        }
                        else if (sessionTextData.StartsWith("usresp-"))
                        {
                            string parameter = sessionTextData.Substring(sessionTextData.IndexOf('-') + 1);
                            readObject.credentials.username = parameter;
                            Form1.WriteLine($"Got credentials: usr: {readObject.credentials.username} ; pwd: {readObject.credentials.password}");
                            if (jsSrv == null)
                            {
                                throw new NullReferenceException("Javascript Server was down when trying to get credentials data");
                            }
                            jsSrv.getPasswordQueue.UpdateExtraData(readObject.requestString.Substring(3), readObject.credentials.username, readObject.credentials.password);
                            jsSrv.getPasswordQueue.UpdateState(readObject.requestString.Substring(3), JavascriptServer.CredentialTransferState.Success);
                            noRead = true;
                        }
                        else if (sessionTextData.StartsWith("pushkey-"))
                        {
                            string key = sessionTextData.Substring(sessionTextData.IndexOf('-') + 1);

                            if (readObject.requestString == "win")
                            {
                                if (WindowsLocking.IsLogonValid(key))
                                {
                                    LockStateChanged?.Invoke(LockState.Unlocked);
                                }
                                else
                                {
                                    LockStateChanged?.Invoke(LockState.Failed);
                                }
                            }
                            else if (readObject.requestString == "lock")
                            {
                                if (WindowsLocking.IsLogonValid(key))
                                {
                                    LockStateChanged?.Invoke(LockState.Locked);
                                }
                                else
                                {
                                    LockStateChanged?.Invoke(LockState.Failed);
                                }
                            }
                            else
                            {
                                if (jsSrv == null)
                                {
                                    throw new NullReferenceException("Javascript server is down when trying to forward 2fa key");
                                }
                                jsSrv.getKeyQueue.UpdateExtraData(readObject.requestString.Substring(10), key);
                                jsSrv.getKeyQueue.UpdateState(readObject.requestString.Substring(10), JavascriptServer.CredentialTransferState.Success);
                            }

                            noRead = true;
                        }
                        else if (sessionTextData.StartsWith("pwresp-"))
                        {
                            string parameter = sessionTextData.Substring(sessionTextData.IndexOf('-') + 1);
                            readObject.credentials.password = parameter;
                            DismissIfOpen?.Invoke();
                        }
                        else if (sessionTextData == "getkvalue")
                        {
                            string parameter = readObject.requestString.Substring(readObject.requestString.IndexOf('-') + 1);
                            string pushKey;
                            if (parameter == "windowsLogon") //Windows Lock Authentication
                            {
                                string lockingKey = WindowsLocking.RegisterLogon();
                                pushKey = lockingKey;
                            }
                            else
                            {
                                if (jsSrv == null)
                                {
                                    throw new NullReferenceException("Javascript server was down when trying to send key to android device");
                                }
                                if (jsSrv.storeKeyQueue.Contains(readObject.requestString.Substring(9)))
                                {
                                    pushKey = (string)jsSrv.storeKeyQueue.GetQueueData(readObject.requestString.Substring(9))[0];
                                }
                                else
                                {
                                    pushKey = "fail";
                                }
                            }

                            if (pushKey == null)
                            {
                                pushKey = "fail";
                            }

                            SendString(readObject.client, Convert.ToBase64String(readObject.session.EncryptData(Encoding.UTF8.GetBytes(pushKey))));
                            if (pushKey == "fail")
                            {
                                Form1.WriteLine("PushKey set to fail!");
                                jsSrv.storeKeyQueue.UpdateState(readObject.requestString.Substring(9), JavascriptServer.CredentialTransferState.Failed);
                            }
                            else
                            {
                                jsSrv.storeKeyQueue.UpdateState(readObject.requestString.Substring(9), JavascriptServer.CredentialTransferState.Success);
                            }
                            noRead = true;
                        }
                    }
                }
            }

            Array.Clear(readObject.buffer, 0, readObject.buffer.Length);
            if (!noRead)
            {
                readObject.client.BeginReceive(readObject.buffer, 0, readObject.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), readObject);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Read data from the browser request
        /// </summary>
        /// <param name="ar">Async Result Object</param>
        private void ReadCallback(IAsyncResult ar)
        {
            int        bytesRead  = -1;
            ReadObject readObject = (ReadObject)ar.AsyncState;

            try
            {
                bytesRead = readObject.client.EndReceive(ar);
            }
            catch (Exception)
            {
                throw;
            }

            if (bytesRead > 0)
            {
                string textData = Encoding.ASCII.GetString(readObject.buffer, 0, bytesRead);                 //Get the HTTP Request

                if (readObject.http.firstData)                                                               //First request data
                {
                    readObject.http.firstData = false;                                                       //Next request isn't first
                    string[] dataLines   = textData.Split(new String[] { "\r\n" }, StringSplitOptions.None); //Get the lines of the request
                    string   requestLine = "";
                    readObject.http.headers     = new List <string>();
                    readObject.http.requestData = "";
                    bool addRequestData = false; //True if request body should be created
                    foreach (string line in dataLines)
                    {
                        if (requestLine == "")
                        {
                            requestLine = line;                    //First line is always request line
                        }
                        else if (line == "")
                        {
                            addRequestData = true;                  //Empty line means end of headers
                        }
                        else if (!addRequestData)
                        {
                            readObject.http.headers.Add(line);                       //Add headers if not ended
                        }
                        else if (addRequestData)
                        {
                            readObject.http.requestData += line;                      //Append request body if headers ended
                        }
                    }

                    //Parse the content length
                    readObject.http.contentLength = -1;

                    foreach (string header in readObject.http.headers)
                    {
                        if (header.StartsWith("Content-Length: "))
                        {
                            int delimiter = header.IndexOf(':') + 2;
                            readObject.http.contentLength = int.Parse(header.Substring(delimiter));
                        }
                    }

                    string[] reqLineParts = requestLine.Split(' ');
                    readObject.http.method   = reqLineParts[0];              //Set the request method
                    readObject.http.resource = reqLineParts[1].Substring(1); //Set the requested URL
                }
                else //Request fragmented, append the request body
                {
                    readObject.http.requestData += textData;
                }


                if (readObject.http.contentLength != -1 && ((readObject.http.contentLength > 0 && readObject.http.requestData == "") ||
                                                            (readObject.http.contentLength != readObject.http.requestData.Length))) //Browser didn't send the request (full) body in this message
                {
                    Form1.WriteLine("Request fragmented");
                }
                else //The request is fully appended
                {
                    Form1.WriteLine("Request completed");
                    HandleRequest(readObject.http.headers, readObject, readObject.http.method, readObject.http.resource, readObject.http.requestData); //Handle the request
                    readObject.http = new HTTPRequest()
                    {
                        firstData = true
                    };                                                        //Reset the request related data
                    Form1.WriteLine("Request handled");
                }

                Array.Clear(readObject.buffer, 0, readObject.buffer.Length);                                                                                   //Clear receive buffer
                readObject.client.BeginReceive(readObject.buffer, 0, readObject.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), readObject); //Receive again from the stream
            }
        }
Beispiel #4
0
        /// <summary>
        /// Start the Locking UI
        /// </summary>
        internal void StartLockForm()
        {
            lockForm = new Form
            {
                FormBorderStyle = FormBorderStyle.None,
                WindowState     = FormWindowState.Normal,
                Text            = "FP Auth Lock Window",
                StartPosition   = FormStartPosition.Manual,
                BackColor       = Color.White
            };
            qrCodePlaceholder = new PictureBox
            {
                SizeMode = PictureBoxSizeMode.AutoSize,
            };

            lockForm.Controls.Add(qrCodePlaceholder);
#if SafetyButton
            AddSafetyButton(lockForm);
#endif
#if ForceTopDisable
            Form1.WriteLine("Foreground Protection Enable Supressed");
#else
            protectionCancel = new CancellationTokenSource();
            StartForegroundProtection(lockForm);
#endif
            Screen primary = Screen.PrimaryScreen;
            lockForm.SetBounds(primary.Bounds.X, primary.Bounds.Y, primary.Bounds.Width, primary.Bounds.Height);
            Action showForm = new Action(() => lockForm.Show());
            if (Form1.me.InvokeRequired)
            {
                Form1.me.Invoke(showForm);
            }
            else
            {
                showForm();
            }

            screenBlockers.Clear();

            foreach (Screen desktop in Screen.AllScreens)
            {
                if (desktop == primary)
                {
                    continue;
                }
                Form screenLocker = new Form
                {
                    StartPosition   = FormStartPosition.Manual,
                    FormBorderStyle = FormBorderStyle.None,
                    BackColor       = Color.White
                };
                screenLocker.SetBounds(desktop.Bounds.X, desktop.Bounds.Y, desktop.Bounds.Width, desktop.Bounds.Height);
                Label l = new Label
                {
                    Text      = "Computer Is Locked, and this screen is blocked from using it, until not logged in",
                    AutoSize  = false,
                    TextAlign = ContentAlignment.MiddleCenter,
                    Dock      = DockStyle.Fill
                };

                Font f = new Font(FontFamily.GenericSansSerif, 12);
                l.Font = f;

                screenLocker.Controls.Add(l);
                Action showBlocker = new Action(() => screenLocker.Show());
                if (Form1.me.InvokeRequired)
                {
                    Form1.me.Invoke(showBlocker);
                }
                else
                {
                    showBlocker();
                }

#if ForceTopDisable
                Form1.WriteLine("Foreground Protection Enable Supressed");
#else
                StartForegroundProtection(screenLocker);
#endif

                screenBlockers.Add(screenLocker);
            }
        }