示例#1
0
        // ReSharper disable once InconsistentNaming
        public static string TestCredentials(string credentialsLogin, string credentialsPass, string credentials2FA,
                                             string logonUriEncoded)
        {
            if (!string.IsNullOrEmpty(credentialsLogin.Trim()) && !string.IsNullOrEmpty(credentialsPass.Trim()))
            {
                string logonUri = HttpUtility.UrlDecode(logonUriEncoded);

                try
                {
                    Person authenticatedPerson = Authentication.Authenticate(credentialsLogin,
                                                                             credentialsPass);

                    int lastOrgId = authenticatedPerson.LastLogonOrganizationId;

                    if (PilotInstallationIds.IsPilot(PilotInstallationIds.PiratePartySE) && (lastOrgId == 3 || lastOrgId == 0))
                    {
                        lastOrgId = 1;                                   // legacy: log on to Piratpartiet SE if indeterminate; prevent sandbox for this pilot
                        authenticatedPerson.LastLogonOrganizationId = 1; // avoid future legacy problems
                    }
                    else if (lastOrgId == 0)
                    {
                        lastOrgId = Organization.SandboxIdentity;
                    }

                    Authority testAuthority = Authority.FromLogin(authenticatedPerson,
                                                                  Organization.FromIdentity(lastOrgId));

                    if (!authenticatedPerson.MemberOfWithInherited(lastOrgId) && !testAuthority.HasSystemAccess(AccessType.Read))
                    {
                        // If the person doesn't have access to the last organization (anymore), log on to Sandbox
                        // unless first pilot, in which case throw (deny login)

                        if (PilotInstallationIds.IsPilot(PilotInstallationIds.PiratePartySE))
                        {
                            throw new UnauthorizedAccessException();
                        }

                        lastOrgId = Organization.SandboxIdentity;
                    }

                    GuidCache.Set(logonUri + "-LoggedOn",
                                  Authority.FromLogin(authenticatedPerson, Organization.FromIdentity(lastOrgId)).ToEncryptedXml());

                    return("Success");  // Prepare here for "2FARequired" return code
                }
                catch (UnauthorizedAccessException)
                {
                    return("Fail");
                }
            }

            return("Fail");
        }
示例#2
0
        protected void ButtonCheat_Click(object sender, EventArgs e)
        {
            // If we're debugging, enable the auto- / impersonation login. This MUST NEVER fire outside of development environment.

            if (Debugger.IsAttached && Path.DirectorySeparatorChar == '\\')
            // on Windows, with a debugger attached, so this is not a production environment
            {
                // but check that we're running against Localhost on non-SSL on a nonstandard port as well

                if (Request.Url.ToString().StartsWith("http://localhost:"))
                {
                    Authority cheatLogon = Authority.FromLogin(Person.FromIdentity(1), Organization.Sandbox);
                    FormsAuthentication.RedirectFromLoginPage(cheatLogon.ToEncryptedXml(), true);
                }
            }
        }
        public static AjaxCallResult Commence(int personId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            if (!authData.Authority.HasSystemAccess())
            {
                // Restrict impersonation to system-level access for now: it's a debugging tool

                return(new AjaxCallResult
                {
                    Success = false,
                    DisplayMessage = CommonV5.JavascriptEscape(Resources.Pages.Admin.CommenceImpersonation_Failed)
                });
            }

            // BEGIN IMPERSONATION

            Person impersonatedPerson = Person.FromIdentity(personId);

            SwarmopsLogEntry newEntry = SwarmopsLog.CreateEntry(impersonatedPerson,
                                                                new ImpersonationLogEntry {
                ImpersonatorPersonId = authData.CurrentUser.PersonId, Started = true
            });

            newEntry.CreateAffectedObject(authData.CurrentUser); // link impersonator to log entry for searchability

            // Someone who has system level access can always impersonate => no further access control at this time

            // SECURITY CONSIDERATIONS: If somebody replaces/fires a superior? Trivially undoable at the database level

            DateTime  utcNow = DateTime.UtcNow;
            Authority impersonatingAuthority = Authority.FromLogin(impersonatedPerson, authData.CurrentOrganization);

            impersonatingAuthority.Impersonation = new Impersonation
            {
                ImpersonatedByPersonId = authData.CurrentUser.PersonId,
                ImpersonationStarted   = utcNow
            };

            FormsAuthentication.SetAuthCookie(impersonatingAuthority.ToEncryptedXml(), false);
            HttpContext.Current.Response.AppendCookie(new HttpCookie("DashboardMessage", CommonV5.JavascriptEscape(String.Format(Resources.Pages.Admin.CommenceImpersonation_Success, utcNow))));
            return(new AjaxCallResult {
                Success = true
            });
        }
示例#4
0
        public static AjaxCallResult TerminateImpersonation()
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            if (!authData.Authority.ImpersonationActive)
            {
                return(new AjaxCallResult {
                    Success = false
                });                                          // no impersonation active. Race condition?
            }

            int    realUserPersonId = authData.Authority.Impersonation.ImpersonatedByPersonId;
            Person impersonator     = Person.FromIdentity(realUserPersonId);

            // Terminate impersonation and set new authority cookie from the impersonator data.
            // VERY SECURITY SENSITIVE: The identity as impersonator will be the new user.

            // TODO: LOG LOG LOG LOG

            SwarmopsLogEntry logEntry = SwarmopsLog.CreateEntry(authData.CurrentUser,
                                                                new ImpersonationLogEntry
            {
                ImpersonatorPersonId = impersonator.Identity,
                Started = false
            });

            logEntry.CreateAffectedObject(impersonator); // link impersonator to log entry for searchability

            DateTime utcNow = DateTime.UtcNow;

            Authority authority =
                Authority.FromLogin(impersonator, authData.CurrentOrganization);

            FormsAuthentication.SetAuthCookie(authority.ToEncryptedXml(), false);
            HttpContext.Current.Response.AppendCookie(new HttpCookie("DashboardMessage", CommonV5.JavascriptEscape(String.Format(Resources.Pages.Admin.CommenceImpersonation_Ended, utcNow))));

            // returning Success will force a reload, resetting dashboard to original user

            return(new AjaxCallResult {
                Success = true
            });
        }
示例#5
0
        protected void ButtonLogin_Click(object sender, EventArgs args)
        {
            // Check the host names and addresses again as a security measure - after all, we can be called from outside our intended script

            if (!(VerifyHostName(this.TextServerName.Text) && VerifyHostAddress(this.TextServerAddress.Text)))
            {
                if (!Debugger.IsAttached)
                {
                    return; // Probable hack attempt - fail silently
                }
            }

            // Protect against race condition on a really really slow server: wait until there is a first person or 15 seconds have expired

            DateTime utcTimeout = DateTime.UtcNow.AddSeconds(15);
            People   people     = People.GetAll();

            while (people.Count < 1 && DateTime.UtcNow < utcTimeout)
            {
                Thread.Sleep(500);
                people = People.GetAll();
            }

            if (people.Count < 1)
            {
                throw new InvalidOperationException("First person has not been created despite 15-second timeout; cannot login");
            }

            // Get authenticated person

            Person expectedPersonOne = Authentication.Authenticate("1",
                                                                   this.TextFirstUserPassword1.Text);

            if (expectedPersonOne != null)
            {
                Authority firstAuthority = Authority.FromLogin(expectedPersonOne, Organization.Sandbox);
                FormsAuthentication.RedirectFromLoginPage(firstAuthority.ToEncryptedXml(), true);
                Response.Redirect("/", true);
            }
        }
示例#6
0
        protected void Page_Load(object sender, EventArgs e)
        {
            // Check if this is the first run ever. If so, redirect to Init.

            if (!SupportFunctions.DatabaseConfigured)
            {
                // ReSharper disable once Html.PathError   <-- this line is required for Resharper to not flag the next line as invalid
                Response.Redirect("/Initialize", true);
                return;
            }

            // Persistence.Key["Debug_RawData"] = Request.ToRaw();

            // Check for POST data - for BitId via Webform

            if (Request.HttpMethod == "POST")
            {
                // We should ONLY get here if we're getting a BitId by Webform submission.

                // Persistence.Key["BitId_RawData"] = Request.ToRaw();

                if (Request.Params["address"] != null)
                {
                    // yes, indeed looks like it

                    BitIdCredentials credentials = new BitIdCredentials
                    {
                        address   = Request.Params["address"],
                        uri       = Request.Params["uri"],
                        signature = Request.Params["signature"]
                    };

                    ProcessRespondBitId(credentials, Response);
                    return;
                }
                if (Request.ContentType == "application/json")
                {
                    BitIdCredentials credentials =
                        new JavaScriptSerializer().Deserialize <BitIdCredentials> (
                            new StreamReader(Request.InputStream).ReadToEnd());
                    // TODO: untested but seems to work. Throws?

                    ProcessRespondBitId(credentials, Response);
                    return;
                }
            }

            string requestHost = Request.Url.Host;

            // If this is the Dev Sandbox, autologin

            if ((requestHost == "sandbox.swarmops.com" || requestHost == "dev.swarmops.com") &&
                PilotInstallationIds.IsPilot(PilotInstallationIds.DevelopmentSandbox) &&
                Request.QueryString["SuppressAutologin"] != "true")
            {
                DashboardMessage.Set("<p>You have been logged on as <strong>Sandbox Administrator</strong> to the Swarmops Development Sandbox.</p><br/><p>This machine runs the latest development build, so you may run into diagnostic code and half-finished features. All data here is bogus test data and is reset every night.</p><br/><p><strong>In other words, welcome, and play away!</strong></p>");
                FormsAuthentication.SetAuthCookie(Authority.FromLogin(Person.FromIdentity(1), Organization.Sandbox).ToEncryptedXml(), true);
                Response.Redirect(HttpContext.Current.Request ["ReturnUrl"]);   // Returns to the requested URL with auth cookie set
            }

            // If we're on an Open Ledgers domain, autologin as Open Ledgers

            Organization organizationOpenLedgers = Organization.FromOpenLedgersDomain(requestHost); // returns null if doesn't exist

            if (organizationOpenLedgers != null)
            {
                DashboardMessage.Set(String.Format(Resources.Pages.Security.Login_AsOpenLedgers, organizationOpenLedgers.Name));
                FormsAuthentication.SetAuthCookie(Authority.FromLogin(Person.FromIdentity(Person.OpenLedgersIdentity), organizationOpenLedgers).ToEncryptedXml(), true);
                if (HttpContext.Current.Request["ReturnUrl"] == "/")
                {
                    Response.Redirect(@"/Ledgers/Balance");
                }
                else
                {
                    Response.Redirect(HttpContext.Current.Request["ReturnUrl"]);  // Returns to the requested URL with auth cookie set
                }
            }

            // Check for SSL and force it

            // Special case for CloudFlare deployments - there is a case where somebody will get their connections de-SSLed at the server

            string cloudFlareVisitorScheme = Request.Headers["CF-Visitor"];
            bool   cloudFlareSsl           = false;

            if (!string.IsNullOrEmpty(cloudFlareVisitorScheme))
            {
                if (cloudFlareVisitorScheme.Contains("\"scheme\":\"https\""))
                {
                    cloudFlareSsl = true;
                }
            }

            // TODO: Same thing for Pound/HAProxy deployments

            // Rewrite if applicable

            if (Request.Url.ToString().StartsWith("http://") && !cloudFlareSsl)
            // only check client-side as many server sites de-SSL the connection before reaching the web server
            {
                if (!Request.Url.ToString().StartsWith("http://dev.swarmops.com/") &&
                    !(Request.Url.ToString().StartsWith("http://*****:*****@"//" + vanityOrganization.VanityDomain + @"/Signup";
                // this.LabelSelfSignup.Text = String.Format (Resources.Pages.Security.Login_SelfSignup, vanityOrganization.Name);
                // this.LabelSelfSignupHeader.Text = Resources.Pages.Security.Login_SelfSignupHeader;
                // this.PanelJoin.Visible = true;
            }


            // If we're debugging, enable the auto- / impersonation login. This MUST NEVER fire outside of development environment.

            if (Debugger.IsAttached && Path.DirectorySeparatorChar == '\\')
            // on Windows, with a debugger attached, so this is not a production environment
            {
                // but check that we're running against Localhost as well

                if (Request.Url.ToString().StartsWith("http://localhost:"))
                {
                    this.PanelCheat.Visible = true;
                }
            }


            // this.ImageCultureIndicator.Style[HtmlTextWriterStyle.MarginTop] = "-3px";
            // this.ImageCultureIndicator.Style[HtmlTextWriterStyle.MarginRight] = "3px";
            // this.ImageCultureIndicator.Style[HtmlTextWriterStyle.Cursor] = "pointer";

            _cacheVersionMark = Logic.Support.Formatting.SwarmopsVersion;
            if (_cacheVersionMark.StartsWith("Debug"))
            {
                _cacheVersionMark = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.ffff");
            }
            _cacheVersionMark = SHA1.Hash(_cacheVersionMark).Replace(" ", "").Substring(0, 8);

            Localize();

            // Generate BitID tokens

            Guid   guid       = Guid.NewGuid();
            string guidString = guid.ToString().Replace("-", "");

            string nonce = guidString + DateTime.UtcNow.Ticks.ToString("x8");

            string hostName = Request.Url.Host;

            string bitIdUri = "bitid://" + hostName + "/Security/Login.aspx/BitIdLogin?x=" + nonce;

            /*   -- commented out: NEVER permit BitId over non-SSL
             * if (Request.Url.ToString().StartsWith ("http://") && !cloudFlareSsl)
             * {
             *  bitIdUri += "&u=1";
             * }*/

            this.LiteralUri.Text   = HttpUtility.UrlEncode(bitIdUri);
            this.LiteralNonce.Text = nonce;

            GuidCache.Set(bitIdUri + "-Logon", "Unauth");

            // TODO: need to NOT USE GOOGLE CHARTS for this but bring home a free QR package

            this.ImageBitIdQr.ImageUrl =
                "https://chart.googleapis.com/chart?cht=qr&chs=400x400&chl=" + HttpUtility.UrlEncode(bitIdUri);
        }
示例#7
0
        protected string _cacheVersionMark; // CSS cache buster

        protected static void ProcessRespondBitId(BitIdCredentials credentials, HttpResponse response)
        {
            BitcoinPubKeyAddress testAddress = new BitcoinPubKeyAddress(credentials.address);

            if (testAddress.VerifyMessage(credentials.uri, credentials.signature))
            {
                // woooooo

                try
                {
                    // Test for registration

                    string intent = GuidCache.Get(credentials.uri + "-Intent") as string;

                    if (!string.IsNullOrEmpty(intent))
                    {
                        if (intent.StartsWith("Register"))
                        {
                            int    personId = Int32.Parse(intent.Substring("Register-".Length));
                            Person person   = Person.FromIdentity(personId);
                            person.BitIdAddress = credentials.address;
                            GuidCache.Set(credentials.uri + "-Intent", "Complete");
                        }
                    }

                    // Otherwise, test for logon

                    if (GuidCache.Get(credentials.uri + "-Logon") as string == "Unauth")
                    {
                        Person person = Person.FromBitIdAddress(credentials.address);

                        // TODO: If above throws, show friendly "unknown wallet" message

                        int lastOrgId = person.LastLogonOrganizationId;

                        if (lastOrgId == 0)
                        {
                            lastOrgId = Organization.SandboxIdentity;
                            person.LastLogonOrganizationId = lastOrgId;
                        }

                        GuidCache.Set(credentials.uri + "-LoggedOn",
                                      Authority.FromLogin(person, Organization.FromIdentity(person.LastLogonOrganizationId)).ToEncryptedXml());
                    }
                }
                catch (Exception e)
                {
                    Persistence.Key["BitIdLogin_Debug_Exception"] = e.ToString();
                }

                // TODO: Error codes

                response.StatusCode = 200;
                response.SetJson();
                response.Write("{\"address\":\"" + credentials.address + "\",\"signature\":\"" + credentials.signature +
                               "\"}");
                response.End();
            }
            else
            {
                response.StatusCode = 401; // Be a bit more friendly in your return codes
            }
        }
示例#8
0
        public static AjaxCallResult SignupParticipant(string name, int organizationId, string mail, string password, string phone,
                                                       string street1, string street2, string postalCode, string city, string countryCode, string dateOfBirth,
                                                       int geographyId, bool activist, PersonGender gender, int[] positionIdsVolunteer)
        {
            CommonV5.CulturePreInit(HttpContext.Current.Request);  // Set culture, for date parsing

            if (geographyId == 0)
            {
                geographyId = Geography.RootIdentity; // if geo was undetermined, set it to "Global"
            }

            Organization organization      = Organization.FromIdentity(organizationId);
            DateTime     parsedDateOfBirth = new DateTime(1800, 1, 1); // Default if unspecified

            if (dateOfBirth.Length > 0)
            {
                parsedDateOfBirth = DateTime.Parse(dateOfBirth);
            }

            Person newPerson = Person.Create(name, mail, password, phone, street1 + "\n" + street2.Trim(), postalCode,
                                             city, countryCode, parsedDateOfBirth, gender);
            Participation participation = newPerson.AddParticipation(organization, DateTime.UtcNow.AddYears(1));    // TODO: set duration from organization settings of Participantship

            // TODO: SEND NOTIFICATIONS

            // Log the signup

            SwarmopsLog.CreateEntry(newPerson, new PersonAddedLogEntry(participation, newPerson));

            // Create notification

            OutboundComm.CreateParticipantNotification(newPerson, newPerson, organization,
                                                       NotificationResource.Participant_Signup);

            // Add the bells and whistles

            if (activist)
            {
                newPerson.CreateActivist(false, false);
            }

            if (positionIdsVolunteer.Length > 0)
            {
                Volunteer volunteer = newPerson.CreateVolunteer();
                foreach (int positionId in positionIdsVolunteer)
                {
                    Position position = Position.FromIdentity(positionId);
                    volunteer.AddPosition(position);
                    SwarmopsLog.CreateEntry(newPerson, new VolunteerForPositionLogEntry(newPerson, position));
                }
            }

            newPerson.LastLogonOrganizationId = organizationId;

            // Create a welcome message to the Dashboard

            HttpContext.Current.Response.AppendCookie(new HttpCookie("DashboardMessage", CommonV5.JavascriptEscape(String.Format(Resources.Pages.Public.Signup_DashboardMessage, organization.Name))));

            // Set authentication cookie, which will log the new person in using the credentials just given

            FormsAuthentication.SetAuthCookie(Authority.FromLogin(newPerson).ToEncryptedXml(), true);

            AjaxCallResult result = new AjaxCallResult {
                Success = true
            };

            return(result);
        }
示例#9
0
        public static bool PerformReset(string mailAddress, string ticket, string newPassword)
        {
            People people = People.FromMail(mailAddress.Trim());

            if (people.Count != 1)
            {
                return(false);
            }

            Person resetPerson = people[0];

            string[] resetData = resetPerson.ResetPasswordTicket.Split(',');

            if (resetData.Length != 2)
            {
                return(false); // invalid data or no ticket
            }

            // This may throw on invalid data, which will give a slightly different error but that's fine too for now.
            DateTime ticketExpiresUtc = DateTime.Parse(resetData[0]);

            if (DateTime.UtcNow > ticketExpiresUtc)
            {
                // Ticket expired.
                return(false);
            }

            if (ticket != resetData[1])
            {
                // Bad ticket.
                return(false);
            }

            // When we get here, all checks to reset the password have completed. Change the password, log the change,
            // notify the user that the password was changed, set a new authentication cookie, and have the web page
            // redirect to Dashboard (by returning true).

            // Clear password reset ticket

            resetPerson.ResetPasswordTicket = string.Empty;

            // Create lockdown code, notify

            string lockdownTicket = SupportFunctions.GenerateSecureRandomKey(16);

            OutboundComm.CreateSecurityNotification(resetPerson, null, null, lockdownTicket,
                                                    NotificationResource.Password_Changed);
            resetPerson.AccountLockdownTicket = DateTime.UtcNow.AddDays(1).ToString(CultureInfo.InvariantCulture) + "," +
                                                lockdownTicket;

            // Set new password

            resetPerson.SetPassword(newPassword);

            // Log the password reset

            SwarmopsLog.CreateEntry(resetPerson,
                                    new PasswordResetLogEntry(resetPerson, SupportFunctions.GetRemoteIPAddressChain()));

            // Set authentication cookies

            int lastOrgId = resetPerson.LastLogonOrganizationId;

            if (lastOrgId == 0)
            {
                lastOrgId = Organization.SandboxIdentity;
            }

            if (!resetPerson.ParticipatesInOrganizationOrParent(lastOrgId))
            {
                // If the person doesn't have access to the last organization (anymore), log on to Sandbox

                lastOrgId = 1;
            }

            // Set cookies

            FormsAuthentication.SetAuthCookie(Authority.FromLogin(resetPerson).ToEncryptedXml(), true);
            DashboardMessage.Set(Resources.Pages.Security.ResetPassword_Success);

            return(true); // temp

            // do NOT NOT NOT trim password - this is deliberate. Passwords starting/ending in whitespace must be possible
        }