예제 #1
0
        /// <summary>
        /// Connects this instance to the server.
        /// </summary>
        /// <returns><c>true</c> if the connection was a success; otherwise, <c>false</c>.</returns>
        public bool Connect()
        {
            byte[] encryptedKey = null;

            // TODO: handle other universes?
            byte[] universeKey = KeyDictionary.GetPublicKey(EUniverse.Public);
            using (var rsa = new RSACrypto(universeKey))
            {
                encryptedKey = rsa.Encrypt(sessionKey);
            }

            byte[] encryptedTicket = CryptoHelper.SymmetricEncrypt(appTicket, sessionKey);

            string payload = String.Format("sessionkey={0}&appticket={1}", WebHelpers.UrlEncode(encryptedKey), WebHelpers.UrlEncode(encryptedTicket));

            webClient.Headers.Clear();
            webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

            string response;

            try
            {
                response = webClient.UploadString(BuildCommand(endPoint, "initsession"), payload);
            }
            catch (WebException)
            {
                return(false);
            }

            var responsekv  = KeyValue.LoadFromString(response);
            var sessionidn  = responsekv.Children.Where(c => c.Name == "sessionid").First();
            var reqcountern = responsekv.Children.Where(c => c.Name == "req-counter").First();

            sessionID  = (ulong)(sessionidn.AsLong(0));
            reqcounter = reqcountern.AsLong(0);

            try
            {
                AuthDepot();
            }
            catch (WebException)
            {
                return(false);
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Connects and authenticates to the specified content server.
        /// </summary>
        /// <param name="csServer">The content server to connect to.</param>
        /// <exception cref="System.ArgumentNullException">csServer was null.</exception>
        public void Connect(Server csServer)
        {
            DebugLog.Assert(steamClient.IsConnected, "CDNClient", "CMClient is not connected!");

            if (csServer == null)
            {
                throw new ArgumentNullException("csServer");
            }

            byte[] pubKey = KeyDictionary.GetPublicKey(steamClient.ConnectedUniverse);

            sessionKey = CryptoHelper.GenerateRandomBlock(32);

            byte[] cryptedSessKey = null;
            using (var rsa = new RSACrypto(pubKey))
            {
                cryptedSessKey = rsa.Encrypt(sessionKey);
            }

            string data;

            if (appTicket == null)
            {
                // no appticket, doing anonymous connection
                data = string.Format("sessionkey={0}&anonymoususer=1&steamid={1}", WebHelpers.UrlEncode(cryptedSessKey), steamClient.SteamID.ConvertToUInt64());
            }
            else
            {
                byte[] encryptedAppTicket = CryptoHelper.SymmetricEncrypt(appTicket, sessionKey);
                data = string.Format("sessionkey={0}&appticket={1}", WebHelpers.UrlEncode(cryptedSessKey), WebHelpers.UrlEncode(encryptedAppTicket));
            }

            KeyValue initKv = DoCommand(csServer, "initsession", data, WebRequestMethods.Http.Post);

            sessionId  = ( ulong )initKv["sessionid"].AsLong();
            reqCounter = initKv["req-counter"].AsLong();

            if (appTicket == null)
            {
                data = string.Format("depotid={0}", depotId);
            }
            else
            {
                byte[] encryptedAppTicket = CryptoHelper.SymmetricEncrypt(appTicket, sessionKey);
                data = string.Format("appticket={0}", WebHelpers.UrlEncode(encryptedAppTicket));
            }

            DoCommand(csServer, "authdepot", data, WebRequestMethods.Http.Post, true);

            connectedServer = csServer;
        }
예제 #3
0
파일: WebAPI.cs 프로젝트: sy1989/SteamKit
            /// <summary>
            /// Manually calls the specified Web API function with the provided details.
            /// </summary>
            /// <param name="func">The function name to call.</param>
            /// <param name="version">The version of the function to call.</param>
            /// <param name="args">A dictionary of string key value pairs representing arguments to be passed to the API.</param>
            /// <param name="method">The http request method. Either "POST" or "GET".</param>
            /// <param name="secure">if set to <c>true</c> this method will be called through the secure API.</param>
            /// <returns>A <see cref="Task{T}"/> that contains a <see cref="KeyValue"/> object representing the results of the Web API call.</returns>
            /// <exception cref="ArgumentNullException">The function name or request method provided were <c>null</c>.</exception>
            /// <exception cref="WebException">An network error occurred when performing the request.</exception>
            /// <exception cref="InvalidDataException">An error occured when parsing the response from the WebAPI.</exception>
            public Task <KeyValue> Call(string func, int version = 1, Dictionary <string, string> args = null, string method = WebRequestMethods.Http.Get, bool secure = false)
            {
                if (func == null)
                {
                    throw new ArgumentNullException("func");
                }

                if (args == null)
                {
                    args = new Dictionary <string, string>();
                }

                if (method == null)
                {
                    throw new ArgumentNullException("method");
                }

                StringBuilder urlBuilder   = new StringBuilder();
                StringBuilder paramBuilder = new StringBuilder();

                urlBuilder.Append(secure ? "https://" : "http://");
                urlBuilder.Append(API_ROOT);
                urlBuilder.AppendFormat("/{0}/{1}/v{2}", iface, func, version);

                bool isGet = method.Equals(WebRequestMethods.Http.Get, StringComparison.OrdinalIgnoreCase);

                if (isGet)
                {
                    // if we're doing a GET request, we'll build the params onto the url
                    paramBuilder = urlBuilder;
                    paramBuilder.Append("/?");   // start our GET params
                }

                args.Add("format", "vdf");

                if (!string.IsNullOrEmpty(apiKey))
                {
                    args.Add("key", apiKey);
                }

                // append any args
                paramBuilder.Append(string.Join("&", args.Select(kvp =>
                {
                    // TODO: the WebAPI is a special snowflake that needs to appropriately handle url encoding
                    // this is in contrast to the steam3 content server APIs which use an entirely different scheme of encoding

                    string key   = WebHelpers.UrlEncode(kvp.Key);
                    string value = kvp.Value; // WebHelpers.UrlEncode( kvp.Value );

                    return(string.Format("{0}={1}", key, value));
                })));


                var task = Task.Factory.StartNew <KeyValue>(() =>
                {
                    byte[] data = null;

                    if (isGet)
                    {
                        data = webClient.DownloadData(urlBuilder.ToString());
                    }
                    else
                    {
                        byte[] postData = Encoding.Default.GetBytes(paramBuilder.ToString());

                        webClient.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
                        data = webClient.UploadData(urlBuilder.ToString(), postData);
                    }

                    KeyValue kv = new KeyValue();

                    using (var ms = new MemoryStream(data))
                    {
                        try
                        {
                            kv.ReadAsText(ms);
                        }
                        catch (Exception ex)
                        {
                            throw new InvalidDataException(
                                "An internal error occurred when attempting to parse the response from the WebAPI server. This can indicate a change in the VDF format.",
                                ex
                                );
                        }
                    }

                    return(kv);
                });

                task.ContinueWith(t =>
                {
                    // we need to observe the exception in this OnlyOnFaulted continuation if our task throws an exception but we're not able to observe it
                    // (such as when waiting for the task times out, and an exception is thrown later)
                    // see: http://msdn.microsoft.com/en-us/library/dd997415.aspx

                    DebugLog.WriteLine("WebAPI", "Threw an unobserved exception: {0}", t.Exception);
                }, TaskContinuationOptions.OnlyOnFaulted);

                return(task);
            }
예제 #4
0
        /// <summary>
        /// Connects and initializes a session to the specified content server.
        /// </summary>
        /// <param name="csServer">The content server to connect to.</param>
        /// <exception cref="System.ArgumentNullException">csServer was null.</exception>
        /// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception>
        /// <exception cref="SteamKitWebRequestException">A network error occurred when performing the request.</exception>
        public async Task ConnectAsync(Server csServer)
        {
            DebugLog.Assert(steamClient.IsConnected, "CDNClient", "CMClient is not connected!");

            if (csServer == null)
            {
                throw new ArgumentNullException(nameof(csServer));
            }

            // Nothing needs to be done to initialize a session to a CDN server
            if (csServer.Type == "CDN")
            {
                connectedServer = csServer;
                return;
            }

            byte[] pubKey = KeyDictionary.GetPublicKey(steamClient.Universe);

            sessionKey = CryptoHelper.GenerateRandomBlock(32);

            byte[] cryptedSessKey = null;
            using (var rsa = new RSACrypto(pubKey))
            {
                cryptedSessKey = rsa.Encrypt(sessionKey);
            }

            string data;

            if (appTicket == null)
            {
                // no appticket, doing anonymous connection
                data = string.Format("sessionkey={0}&anonymoususer=1&steamid={1}", WebHelpers.UrlEncode(cryptedSessKey), steamClient.SteamID.ConvertToUInt64());
            }
            else
            {
                byte[] encryptedAppTicket = CryptoHelper.SymmetricEncrypt(appTicket, sessionKey);
                data = string.Format("sessionkey={0}&appticket={1}", WebHelpers.UrlEncode(cryptedSessKey), WebHelpers.UrlEncode(encryptedAppTicket));
            }

            var initKv = await DoCommandAsync(csServer, HttpMethod.Post, "initsession", data).ConfigureAwait(false);

            sessionId       = initKv["sessionid"].AsUnsignedLong();
            reqCounter      = initKv["req-counter"].AsLong();
            connectedServer = csServer;
        }
예제 #5
0
            /// <summary>
            /// Manually calls the specified Web API function with the provided details.
            /// </summary>
            /// <param name="func">The function name to call.</param>
            /// <param name="version">The version of the function to call.</param>
            /// <param name="args">A dictionary of string key value pairs representing arguments to be passed to the API.</param>
            /// <param name="method">The http request method. Either "POST" or "GET".</param>
            /// <param name="secure">if set to <c>true</c> this method will be called through the secure API.</param>
            /// <returns>A <see cref="KeyValue"/> object representing the results of the Web API call.</returns>
            /// <exception cref="ArgumentNullException">The function name or request method provided were <c>null</c>.</exception>
            /// <exception cref="WebException">An network error occurred when performing the request.</exception>
            /// <exception cref="InvalidDataException">An error occured when parsing the response from the WebAPI.</exception>
            public KeyValue Call(string func, int version = 1, Dictionary <string, string> args = null, string method = WebRequestMethods.Http.Get, bool secure = false)
            {
                if (func == null)
                {
                    throw new ArgumentNullException("func");
                }

                if (args == null)
                {
                    args = new Dictionary <string, string>();
                }

                if (method == null)
                {
                    throw new ArgumentNullException("method");
                }

                StringBuilder urlBuilder   = new StringBuilder();
                StringBuilder paramBuilder = new StringBuilder();

                urlBuilder.Append(secure ? "https://" : "http://");
                urlBuilder.Append(API_ROOT);
                urlBuilder.AppendFormat("/{0}/{1}/v{2}", iface, func, version);

                bool isGet = method.Equals(WebRequestMethods.Http.Get, StringComparison.OrdinalIgnoreCase);

                if (isGet)
                {
                    // if we're doing a GET request, we'll build the params onto the url
                    paramBuilder = urlBuilder;
                    paramBuilder.Append("/?");   // start our GET params
                }

                args.Add("format", "vdf");

                if (!string.IsNullOrEmpty(apiKey))
                {
                    args.Add("key", apiKey);
                }

                // append any args
                paramBuilder.Append(string.Join("&", args.Select(kvp =>
                {
                    // TODO: the WebAPI is a special snowflake that needs to appropriately handle url encoding
                    // this is in contrast to the steam3 content server APIs which use an entirely different scheme of encoding

                    string key   = WebHelpers.UrlEncode(kvp.Key);
                    string value = kvp.Value; // WebHelpers.UrlEncode( kvp.Value );

                    return(string.Format("{0}={1}", key, value));
                })));


                byte[] data = null;

                if (isGet)
                {
                    data = webClient.DownloadData(urlBuilder.ToString());
                }
                else
                {
                    byte[] postData = Encoding.Default.GetBytes(paramBuilder.ToString());

                    webClient.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
                    data = webClient.UploadData(urlBuilder.ToString(), postData);
                }

                KeyValue kv = new KeyValue();

                using (var ms = new MemoryStream(data))
                {
                    try
                    {
                        kv.ReadAsText(ms);
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidDataException(
                                  "An internal error occurred when attempting to parse the response from the WebAPI server. This can indicate a change in the VDF format.",
                                  ex
                                  );
                    }
                }

                return(kv);
            }
예제 #6
0
            async Task <KeyValue> CallAsyncCore(HttpMethod method, string func, int version = 1, Dictionary <string, string> args = null)
            {
                if (method == null)
                {
                    throw new ArgumentNullException(nameof(method));
                }

                if (func == null)
                {
                    throw new ArgumentNullException(nameof(func));
                }

                if (args == null)
                {
                    args = new Dictionary <string, string>();
                }


                var urlBuilder   = new StringBuilder();
                var paramBuilder = new StringBuilder();

                urlBuilder.AppendFormat("{0}/{1}/v{2}", iface, func, version);

                var isGet = HttpMethod.Get.Equals(method);

                if (isGet)
                {
                    // if we're doing a GET request, we'll build the params onto the url
                    paramBuilder = urlBuilder;
                    paramBuilder.Append("/?");   // start our GET params
                }

                args.Add("format", "vdf");

                if (!string.IsNullOrEmpty(apiKey))
                {
                    args.Add("key", apiKey);
                }

                // append any args
                paramBuilder.Append(string.Join("&", args.Select(kvp =>
                {
                    // TODO: the WebAPI is a special snowflake that needs to appropriately handle url encoding
                    // this is in contrast to the steam3 content server APIs which use an entirely different scheme of encoding

                    string key   = WebHelpers.UrlEncode(kvp.Key);
                    string value = kvp.Value; // WebHelpers.UrlEncode( kvp.Value );

                    return(string.Format("{0}={1}", key, value));
                })));

                var request = new HttpRequestMessage(method, urlBuilder.ToString());

                if (!isGet)
                {
                    request.Content = new StringContent(paramBuilder.ToString());
                    request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
                }

                var response = await httpClient.SendAsync(request).ConfigureAwait(false);

                var kv = new KeyValue();

                using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                {
                    try
                    {
                        kv.ReadAsText(stream);
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidDataException(
                                  "An internal error occurred when attempting to parse the response from the WebAPI server. This can indicate a change in the VDF format.",
                                  ex
                                  );
                    }
                }

                return(kv);
            }