Пример #1
0
        internal static void SignOut(JsonHttpClient jsonHttp)
        {
            var response = jsonHttp.Put("v1/session/signout");

            if (response.IntAt("success") != 1)
            {
                throw new ClientException(ClientException.FailureReason.RespondedWithError,
                                          "Failed to sign out");
            }
        }
Пример #2
0
        internal static Account[] GetVaultAccounts(string id,
                                                   AesKey sessionKey,
                                                   Keychain keychain,
                                                   JsonHttpClient jsonHttp)
        {
            var response = GetEncryptedJson(string.Format("v1/vault/{0}/0/items", id),
                                            sessionKey,
                                            jsonHttp);

            return(response.At("items", new JArray()).Select(i => ParseAccount(i, keychain)).ToArray());
        }
Пример #3
0
        internal static void ReauthorizeDevice(ClientInfo clientInfo, JsonHttpClient jsonHttp)
        {
            var response = jsonHttp.Put(string.Format("v1/device/{0}/reauthorize", clientInfo.Uuid));

            if (response.IntAt("success") != 1)
            {
                throw new ClientException(ClientException.FailureReason.RespondedWithError,
                                          string.Format("Failed to reauthorize the device '{0}'",
                                                        clientInfo.Uuid));
            }
        }
Пример #4
0
        internal static JObject PostEncryptedJson(string endpoint,
                                                  Dictionary <string, string> parameters,
                                                  AesKey sessionKey,
                                                  JsonHttpClient jsonHttp)
        {
            var payload          = JsonConvert.SerializeObject(parameters);
            var encryptedPayload = sessionKey.Encrypt(payload.ToBytes());
            var response         = jsonHttp.Post(endpoint, encryptedPayload.ToDictionary());

            return(Decrypt(response, sessionKey));
        }
Пример #5
0
        //
        // Internal
        //

        internal static byte[] Perform(BigInteger secretA,
                                       ClientInfo clientInfo,
                                       Session session,
                                       JsonHttpClient http)
        {
            var sharedA = ComputeSharedA(secretA);
            var sharedB = ExchangeAForB(sharedA, session, http);

            ValidateB(sharedB);
            return(ComputeKey(secretA, sharedA, sharedB, clientInfo, session));
        }
Пример #6
0
        internal static Vault[] GetVaults(JToken accountInfo,
                                          AesKey sessionKey,
                                          Keychain keychain,
                                          JsonHttpClient jsonHttp)
        {
            var accessibleVaults = new HashSet <string>(BuildListOfAccessibleVaults(accountInfo));

            return(accountInfo.At("vaults")
                   .Where(i => accessibleVaults.Contains(i.StringAt("uuid", "")))
                   .Select(i => GetVault(i, sessionKey, keychain, jsonHttp))
                   .ToArray());
        }
Пример #7
0
        internal static Vault GetVault(JToken json,
                                       AesKey sessionKey,
                                       Keychain keychain,
                                       JsonHttpClient jsonHttp)
        {
            var id         = json.StringAt("uuid");
            var attributes = Decrypt(json.At("encAttrs"), keychain);

            return(new Vault(id: id,
                             name: attributes.StringAt("name", ""),
                             description: attributes.StringAt("desc", ""),
                             accounts: GetVaultAccounts(id, sessionKey, keychain, jsonHttp)));
        }
Пример #8
0
        internal static JsonHttpClient MakeJsonClient(IHttpClient http,
                                                      string baseUrl,
                                                      string sessionId = null)
        {
            var jsonHttp = new JsonHttpClient(http, baseUrl);

            jsonHttp.Headers["X-AgileBits-Client"] = ClientId;

            if (sessionId != null)
            {
                jsonHttp.Headers["X-AgileBits-Session-ID"] = sessionId;
            }

            return(jsonHttp);
        }
Пример #9
0
        internal static void RegisterDevice(ClientInfo clientInfo, JsonHttpClient jsonHttp)
        {
            var response = jsonHttp.Post("v1/device",
                                         new Dictionary <string, object>
            {
                { "uuid", clientInfo.Uuid },
                { "clientName", ClientName },
                { "clientVersion", ClientVersion },
            });

            if (response.IntAt("success") != 1)
            {
                throw new ClientException(ClientException.FailureReason.RespondedWithError,
                                          string.Format("Failed to register the device '{0}'",
                                                        clientInfo.Uuid));
            }
        }
Пример #10
0
        internal static BigInteger ExchangeAForB(BigInteger sharedA,
                                                 Session session,
                                                 JsonHttpClient http)
        {
            var response = http.Post("v1/auth",
                                     new Dictionary <string, object>
            {
                { "sessionID", session.Id },
                { "userA", sharedA.ToHex() }
            });

            if (response.StringAt("sessionID") != session.Id)
            {
                throw ExceptionFactory.MakeInvalidOperation("SRP: session ID doesn't match");
            }

            return(response.StringAt("userB").ToBigInt());
        }
Пример #11
0
        internal static Session StartNewSession(ClientInfo clientInfo, JsonHttpClient jsonHttp)
        {
            var response = jsonHttp.Get(string.Format("v2/auth/{0}/{1}/{2}/{3}",
                                                      clientInfo.Username,
                                                      clientInfo.AccountKey.Format,
                                                      clientInfo.AccountKey.Uuid,
                                                      clientInfo.Uuid));
            var status = response.StringAt("status");

            switch (status)
            {
            case "ok":
                var session = Session.Parse(response);
                if (session.KeyUuid != clientInfo.AccountKey.Uuid)
                {
                    throw new ClientException(ClientException.FailureReason.IncorrectCredentials,
                                              "The account key is incorrect");
                }
                return(session);

            case "device-not-registered":
                RegisterDevice(clientInfo, MakeJsonClient(jsonHttp, response.StringAt("sessionID")));
                break;

            case "device-deleted":
                ReauthorizeDevice(clientInfo, MakeJsonClient(jsonHttp, response.StringAt("sessionID")));
                break;

            default:
                throw new ClientException(
                          ClientException.FailureReason.InvalidResponse,
                          string.Format(
                              "Failed to start a new session, unsupported response status '{0}'",
                              status));
            }

            return(StartNewSession(clientInfo, jsonHttp));
        }
Пример #12
0
        // Returns the session encryption key
        public static AesKey Perform(ClientInfo clientInfo, Session session, JsonHttpClient http)
        {
            var key = Perform(GenerateSecretA(), clientInfo, session, http);

            return(new AesKey(session.Id, key));
        }
Пример #13
0
        //
        // HTTP
        //

        internal static JObject GetEncryptedJson(string endpoint,
                                                 AesKey sessionKey,
                                                 JsonHttpClient jsonHttp)
        {
            return(Decrypt(jsonHttp.Get(endpoint), sessionKey));
        }
Пример #14
0
        internal static void VerifySessionKey(ClientInfo clientInfo,
                                              Session session,
                                              AesKey sessionKey,
                                              JsonHttpClient jsonHttp)
        {
            try
            {
                var response = PostEncryptedJson(
                    "v2/auth/verify",
                    new Dictionary <string, string>
                {
                    { "sessionID", session.Id },
                    { "clientVerifyHash", Crypto.CalculateClientHash(clientInfo, session) },
                    { "client", ClientId },
                },
                    sessionKey,
                    jsonHttp);

                // Just to verify that it's a valid JSON and it has some keys.
                // Technically it should have failed by now either in decrypt or JSON parse
                response.StringAt("userUuid");
            }
            catch (ClientException e)
            {
                // This is a quite ugly attempt at handling a very special case.
                // When this specific request fails with 400, the response contains
                // the error code. It seems 102 means invalid credentials.

                // TODO: Write a test for this case.

                if (e.Reason != ClientException.FailureReason.NetworkError)
                {
                    throw;
                }

                var web = e.InnerException as WebException;
                if (web == null)
                {
                    throw;
                }

                var response = web.Response as HttpWebResponse;
                if (response == null)
                {
                    throw;
                }

                var stream = response.GetResponseStream();
                if (stream == null)
                {
                    throw;
                }

                stream.Position = 0;
                var text = new System.IO.StreamReader(stream).ReadToEnd();

                var json = JObject.Parse(text);
                if (json.IntAt("errorCode", 0) == 102)
                {
                    throw new ClientException(ClientException.FailureReason.IncorrectCredentials,
                                              "Username, password or account key is incorrect",
                                              e);
                }

                throw;
            }
        }
Пример #15
0
 internal static JObject GetAccountInfo(AesKey sessionKey, JsonHttpClient jsonHttp)
 {
     return(GetEncryptedJson("v1/account?attrs=billing,counts,groups,invite,me,settings,tier,user-flags,users,vaults", sessionKey, jsonHttp));
 }
Пример #16
0
 internal static JObject GetKeysets(AesKey sessionKey, JsonHttpClient jsonHttp)
 {
     return(GetEncryptedJson("v1/account/keysets", sessionKey, jsonHttp));
 }
Пример #17
0
 internal static JsonHttpClient MakeJsonClient(JsonHttpClient jsonHttp,
                                               string sessionId = null)
 {
     return(MakeJsonClient(jsonHttp.Http, jsonHttp.BaseUrl, sessionId));
 }