예제 #1
0
        private static void DoCallHome(object state)
        {
            HttpWebClient client = new HttpWebClient();

            log.Info("Calling home to " + FileHandlerFactoryLocator.CallHomeEndpoint);

            client.BeginPost(
                FileHandlerFactoryLocator.CallHomeEndpoint,
                delegate(HttpResponseHandler response)
                {
                    log.Info("Successfully called home to " + FileHandlerFactoryLocator.CallHomeEndpoint);
                },
                delegate(Exception e)
                {
                    log.Error("Exception when calling home to " + FileHandlerFactoryLocator.CallHomeEndpoint, e);

                    // no-op for strict compiler
                    if (null == Timer)
                    {}
                },
                new KeyValuePair<string, string>("host", FileHandlerFactoryLocator.Hostname));
        }
        /// <summary>
        /// Establishes trust between a user and another server
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="receiveNotificationEndpoint"></param>
        /// <param name="callback"></param>
        private void BeginEstablishTrust(
            IUserOrGroup sender,
            string receiveNotificationEndpoint,
            string establishTrustEndpoint,
            Action<string> callback,
            Action<Exception> errorCallback)
        {
            // Make sure the timer is created
            if (null == EstablishTrustDataTimer)
            {
                Timer timer = new Timer(EstablishTrustDataCleanup, null, 600000, 600000);
                if (null != Interlocked.CompareExchange<Timer>(ref EstablishTrustDataTimer, timer, null))
                    timer.Dispose();
            }

            // Get the avatar
            byte[] avatar;
            ISession session = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession();

            try
            {
                IWebConnection webConnection = new BlockingShellWebConnection(
                    FileHandlerFactoryLocator.WebServer,
                    session,
                    "/Users/" + sender.Name + ".user?Method=GetAvatar",
                    null,
                    null,
                    null,
                    CallingFrom.Web,
                    WebMethod.GET);

                IWebResults webResults = webConnection.ShellTo("/Users/" + sender.Name + ".user?Method=GetAvatar");

                using (Stream stream = webResults.ResultsAsStream)
                {
                    avatar = new byte[stream.Length];
                    stream.Read(avatar, 0, avatar.Length);
                }
            }
            finally
            {
                FileHandlerFactoryLocator.SessionManagerHandler.EndSession(session.SessionId);
            }

            // Hold on to callback information for use after trust is established
            string token;
            using (TimedLock.Lock(EstablishTrustDatasByToken))
            {
                do
                    token = Convert.ToBase64String(SRandom.NextBytes(100));
                while (EstablishTrustDatasByToken.ContainsKey(token));

                EstablishTrustDatasByToken[token] = new EstablishTrustData();
            }

            HttpWebClient httpWebClient = new HttpWebClient();
            httpWebClient.BeginPost(
                establishTrustEndpoint,
                delegate(HttpResponseHandler httpResponseHandler)
                {
                    if (httpResponseHandler.StatusCode == System.Net.HttpStatusCode.Created)
                    {
                        string senderToken;

                        using (TimedLock.Lock(EstablishTrustDatasByToken))
                        {
                            senderToken = EstablishTrustDatasByToken[token].SenderToken;
                            EstablishTrustDatasByToken.Remove(token);
                        }

                        this.persistedUserManagerData.Write(userManagerData =>
                        {
                            var user = userManagerData.GetUser(sender.Id);

                            string oldSenderToken;
                            if (user.receiveNotificationSenderTokensByEndpoint.TryGetValue(receiveNotificationEndpoint, out oldSenderToken))
                                user.receiveNotificationEndpointsBySenderToken.Remove(oldSenderToken);

                            user.receiveNotificationEndpointsBySenderToken[senderToken] = receiveNotificationEndpoint;
                            user.receiveNotificationSenderTokensByEndpoint[receiveNotificationEndpoint] = senderToken;
                        });

                        callback(senderToken);
                    }
                    else
                        errorCallback(new ParticleException.CouldNotEstablishTrust("Couldn't establish trust: " + httpResponseHandler.AsString()));
                },
                errorCallback,
                new KeyValuePair<string, string>("senderIdentity", sender.Identity),
                new KeyValuePair<string, string>("token", token),
                new KeyValuePair<string, string>("avatar", Convert.ToBase64String(avatar)),
                new KeyValuePair<string, string>("loginURL", string.Format("http://{0}/Users/UserDB?Method=OpenIDLogin", FileHandlerFactoryLocator.HostnameAndPort)),
                new KeyValuePair<string, string>("loginURLOpenID", "openid_url"),
                new KeyValuePair<string, string>("loginURLWebFinger", "openid_url"),
                new KeyValuePair<string, string>("loginURLRedirect", "redirect"),
                GenerateSecurityTimestamp());
        }
        public IWebResults UserConfirmLink(
            IWebConnection webConnection,
            string objectUrl,
            string ownerIdentity,
            string linkSummaryView,
            string linkUrl,
            string linkDocumentType,
            string[] recipients,
            string redirectUrl,
            string linkID,
            string password,
            string remember)
        {
            IUser user;
            if (ownerIdentity != webConnection.Session.User.Identity)
            {
                string name = GetLocalUserNameFromOpenID(ownerIdentity);

                // Load the user and verify the password
                user = LoadUserAndVerifyPassword(webConnection, name, password);
            }
            else
                user = webConnection.Session.User;

            Uri domainUri = new Uri(objectUrl);

            webConnection.Session.User.UserHandler.SetRememberOpenIDLink(domainUri.Host, remember != null);

            FileHandler.GetEndpointInfos(
                user,
                false,
                recipients,
                ParticleEndpoint.ConfirmLink,
                delegate(EndpointInfo endpointInfo)
                {
                    HttpWebClient httpWebClient = new HttpWebClient();

                    httpWebClient.BeginPost(
                        endpointInfo.Endpoint,
                        delegate(HttpResponseHandler httpResponseHandler)
                        {
                        },
                        delegate(Exception e)
                        {
                            log.Warn("Exception calling particle.confirmLink for " + StringGenerator.GenerateCommaSeperatedList(endpointInfo.RecipientIdentities), e);
                        },
                        new KeyValuePair<string, string>("objectUrl", objectUrl),
                        new KeyValuePair<string, string>("senderToken", endpointInfo.SenderToken),
                        new KeyValuePair<string, string>("linkSummaryView", linkSummaryView),
                        new KeyValuePair<string, string>("linkUrl", linkUrl),
                        new KeyValuePair<string, string>("linkDocumentType", linkDocumentType),
                        new KeyValuePair<string, string>("linkID", linkID),
                        new KeyValuePair<string, string>("recipients", JsonWriter.Serialize(endpointInfo.RecipientIdentities)),
                        GenerateSecurityTimestamp());
                },
                delegate(IEnumerable<string> recipientsInError)
                {
                    log.Warn("Could not get particle.confirmLink for the following recipients: " + StringGenerator.GenerateCommaSeperatedList(recipientsInError));
                },
                delegate(Exception e)
                {
                    log.Error("Exception getting recipient information for particle.confirmLink", e);
                });

            return WebResults.Redirect(redirectUrl);
        }
        public void SendNotification(
            IUser sender,
            EndpointInfo recipientInfo,
            string objectUrl,
            string summaryView,
            string documentType,
            string verb,
            string changeData,
            int maxRetries,
            TimeSpan transportErrorDelay)
        {
            HttpWebClient webClient = new HttpWebClient();

            Action retry = delegate()
            {
                if (maxRetries > 0)
                    ThreadPool.QueueUserWorkItem(delegate(object state)
                    {
                        Thread.Sleep(transportErrorDelay);

                        SendNotification(
                            sender,
                            recipientInfo,
                            objectUrl,
                            summaryView,
                            documentType,
                            verb,
                            changeData,
                            maxRetries - 1,
                            transportErrorDelay);
                    });
            };

            webClient.BeginPost(
                recipientInfo.Endpoint,
                delegate(HttpResponseHandler response)
                {
                    string responseString = response.AsString();

                    if (response.StatusCode == System.Net.HttpStatusCode.OK)
                    // success!
                    { }

                    else if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
                        // errors
                        log.Warn("Errors occured when sending a notification: " + responseString);

                    else if (response.StatusCode == System.Net.HttpStatusCode.PreconditionFailed && "senderToken" == responseString)
                    {
                        SendNotification(
                            sender,
                            true,
                            recipientInfo.RecipientIdentities,
                            objectUrl,
                            summaryView,
                            documentType,
                            verb,
                            changeData,
                            maxRetries,
                            transportErrorDelay);
                    }
                    else
                        retry();
                },
                delegate(Exception e)
                {
                },
                new KeyValuePair<string, string>("senderToken", recipientInfo.SenderToken),
                new KeyValuePair<string, string>("recipients", JsonWriter.Serialize(recipientInfo.RecipientIdentities)),
                new KeyValuePair<string, string>("objectUrl", objectUrl),
                new KeyValuePair<string, string>("summaryView", summaryView),
                new KeyValuePair<string, string>("documentType", documentType),
                new KeyValuePair<string, string>("verb", verb),
                new KeyValuePair<string, string>("changeData", changeData),
                GenerateSecurityTimestamp());
        }
        public IWebResults EstablishTrust(
            IWebConnection webConnection,
            string senderIdentity,
            string avatar,
            string token,
            string loginURL,
            string loginURLOpenID,
            string loginURLWebFinger,
            string loginURLRedirect)
        {
            VerifySecurityTimestamp(webConnection);

            // Decode the avatar, verifying that it's legitimate base64 encoded
            byte[] avatarBytes;
            try
            {
                avatarBytes = Convert.FromBase64String(avatar);
            }
            catch (Exception e)
            {
                throw new WebResultsOverrideException(WebResults.From(Status._400_Bad_Request, "Malformed avatar"), e);
            }

            // Note:  The avatar should be a valid JPEG under 250kb.
            // For the sake of keeping the network running, this is not verified

            // Generate a sender token, with a sanity check for duplicates
            // TODO for the OCD:  It's statisically difficult, but this sender token isn't inserted in the database, thus
            // there's no check against duplicate in-RAM sender tokens
            string senderToken;
            bool senderTokenInMemory;
            string conflictingSenderIdentity;

            do
            {
                // First check the database for a duplicate
                do
                    senderToken = Convert.ToBase64String(SRandom.NextBytes(100));
                while (FileHandler.TryGetSenderIdentity(senderToken, out conflictingSenderIdentity));

                // Next check for a duplicate sender token that hasn't yet been written to the DB
                lock (PendingSenderTokens)
                {
                    senderTokenInMemory = PendingSenderTokens.Contains(senderToken);

                    if (!senderTokenInMemory)
                        PendingSenderTokens.Add(senderToken);
                }

            } while (senderTokenInMemory);

            Action<HttpResponseHandler> callback = delegate(HttpResponseHandler response)
            {
                if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
                {
                    FileHandler.EstablishTrust(senderIdentity, senderToken, loginURL, loginURLOpenID, loginURLWebFinger, loginURLRedirect);

                    webConnection.SendResults(WebResults.From(Status._201_Created, "created"));

                    IUser senderUser = FileHandlerFactoryLocator.IdentityProviders[1].GetOrCreateUser(senderIdentity);

                    string avatarFilename = senderUser.Id.ToString() + ".jpg";

                    IBinaryHandler avatarHandler;
                    if (ParticleAvatarsDirectory.IsFilePresent(avatarFilename))
                        avatarHandler = ParticleAvatarsDirectory.OpenFile(avatarFilename).CastFileHandler<IBinaryHandler>();
                    else
                        avatarHandler = (IBinaryHandler)ParticleAvatarsDirectory.CreateFile(avatarFilename, "image", null);

                    avatarHandler.WriteAll(avatarBytes);

                    // Remove the sender token from the list of pending sender tokens
                    lock (PendingSenderTokens)
                        PendingSenderTokens.Remove(senderToken);
                }
                else
                    webConnection.SendResults(WebResults.From(Status._400_Bad_Request, "Error from RespondTrust"));
            };

            Action<Exception> errorCallback = delegate(Exception e)
            {
                webConnection.SendResults(WebResults.From(Status._401_Unauthorized, "Could not establish trust"));
            };

            FileHandler.GetEndpoints(
                senderIdentity,
                delegate(IEndpoints endpoints)
                {
                    HttpWebClient httpWebClient = new HttpWebClient();
                    httpWebClient.BeginPost(
                        endpoints[ParticleEndpoint.RespondTrust],
                        callback,
                        errorCallback,
                        new KeyValuePair<string, string>("token", token),
                        new KeyValuePair<string, string>("senderToken", senderToken),
                        GenerateSecurityTimestamp());
                },
                delegate(Exception e)
                {
                    log.Error("Can not get the endpoint to respond establishing trust from within a call to EstablishTrust", e);
                });

            return null;
        }