Exemplo n.º 1
0
        private Dictionary <string, string> CheckServiceLicense()
        {
            // check request validity (unless it's for the @config uri, which is a special case)
            Dictionary <string, string> result = null;

            if ((Feature.Service.Self != null) && (Feature.Service is IDreamServiceLicense) && !(Uri.LastSegment ?? string.Empty).EqualsInvariant("@config"))
            {
                string service_license = ((IDreamServiceLicense)Feature.Service).ServiceLicense;
                if (string.IsNullOrEmpty(service_license))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing"));
                }

                // extract public RSA key for validation
                RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(Feature.Service.GetType().Assembly);
                if (public_key == null)
                {
                    throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid"));
                }

                // validate the service-license
                try {
                    // parse service-license
                    result = HttpUtil.ParseNameValuePairs(service_license);
                    if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(result["dsig"], public_key))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license"));
                    }
                } catch (Exception e) {
                    // unexpected error, blame it on the license
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                    else
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license"));
                    }
                }

                // check license
                string text;
                if ((!result.TryGetValue("licensee", out text) || string.IsNullOrEmpty(text)) && !result.ContainsKey("expire"))
                {
                    // unexpected error, blame it on the license
                    throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license"));
                }

                // determine 'now' date-time
                DateTime now          = GlobalClock.UtcNow;
                DateTime?request_date = Request.Headers.Date;
                if (request_date.HasValue)
                {
                    now = (request_date.Value > now) ? request_date.Value : now;
                }

                // check expiration
                DateTime expire;
                if (result.TryGetValue("expire", out text) && (!DateTimeUtil.TryParseInvariant(text, out expire) || (expire.ToUniversalTime() < now)))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired"));
                }
            }
            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Perform startup configuration of a service instance.
        /// </summary>
        /// <remarks>
        /// Should not be manually invoked and should only be overridden if <see cref="Start(MindTouch.Xml.XDoc,Autofac.ILifetimeScope,MindTouch.Tasking.Result)"/> isn't already overriden.
        /// </remarks>
        /// <param name="config">Service configuration.</param>
        /// <param name="result">Synchronization handle for coroutine invocation.</param>
        /// <returns>Iterator used by <see cref="Coroutine"/> execution environment.</returns>
        protected virtual Yield Start(XDoc config, Result result)
        {
            Result <DreamMessage> res;

            // store configuration and uri
            _config = config;
            _self   = Plug.New(config["uri.self"].AsUri);
            if (_self == null)
            {
                throw new ArgumentNullException("config", "Missing element'uri.self'");
            }
            _owner = Plug.New(config["uri.owner"].AsUri);

            // check for service access keys
            var internalAccessKey = config["internal-service-key"].AsText;

            if (!string.IsNullOrEmpty(internalAccessKey))
            {
                _internalAccessKey = internalAccessKey;
            }
            var privateAccessKey = config["private-service-key"].AsText;

            if (!string.IsNullOrEmpty(privateAccessKey))
            {
                _privateAccessKey = privateAccessKey;
            }

            // check for api-key settings
            _apikey = config["apikey"].AsText;

            // process 'set-cookie' entries
            var setCookies = DreamCookie.ParseAllSetCookieNodes(config["set-cookie"]);

            if (setCookies.Count > 0)
            {
                Cookies.Update(setCookies, null);
            }

            // grant private access key to self, host, and owner
            var privateAcccessCookie = DreamCookie.NewSetCookie("service-key", PrivateAccessKey, Self.Uri);

            Cookies.Update(privateAcccessCookie, null);
            yield return(Env.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue)));

            if (Owner != null)
            {
                yield return(res = Owner.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue)));

                if (!res.Value.IsSuccessful)
                {
                    throw new ArgumentException("unexpected failure setting grants on owner service");
                }
            }

            // check if this service requires a service-license to work
            if (this is IDreamServiceLicense)
            {
                string service_license = config["service-license"].AsText;
                if (string.IsNullOrEmpty(service_license))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing"));
                }

                // extract public RSA key for validation
                RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(GetType().Assembly);
                if (public_key == null)
                {
                    throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid"));
                }

                // validate the service-license
                _license = null;
                Dictionary <string, string> values;
                try {
                    // parse service-license
                    values = HttpUtil.ParseNameValuePairs(service_license);
                    if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(values["dsig"], public_key))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (1)"));
                    }

                    // check if the SID matches
                    string sid;
                    if (!values.TryGetValue("sid", out sid) || !SID.HasPrefix(XUri.TryParse(sid), true))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (2)"));
                    }
                    _license = service_license;
                } catch (Exception e) {
                    // unexpected error, blame it on the license
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                    throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (1)"));
                }

                // validate expiration date
                string expirationtext;
                if (values.TryGetValue("expire", out expirationtext))
                {
                    try {
                        DateTime expiration = DateTime.Parse(expirationtext);
                        if (expiration < DateTime.UtcNow)
                        {
                            _license = null;
                        }
                    } catch (Exception e) {
                        _license = null;

                        // unexpected error, blame it on the license
                        if (e is DreamAbortException)
                        {
                            throw;
                        }
                        throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (2)"));
                    }
                }

                // check if a license was assigned
                if (_license == null)
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired"));
                }
            }
            else
            {
                config["service-license"].RemoveAll();
            }

            // create built-in services
            _storage = Plug.New(config["uri.storage"].AsUri);
            _pubsub  = Plug.New(config["uri.pubsub"].AsUri);

            // done
            _log.Debug("Start");
            result.Return();
        }