Наследование: MarshalByRefObject, ISerializable
Пример #1
0
 public AuthCookie(string authToken, Uri identity)
 {
     AuthToken = authToken;
     Identity = identity;
     AuthedRealms = new List<string>();
 }
Пример #2
0
        public static bool SetAuthCookie(OSHttpRequest httpRequest, OSHttpResponse httpResponse, Uri identity, string consumer)
        {
            bool permissionGranted = false;
            HttpCookie cookie = (httpRequest.Cookies != null) ? httpRequest.Cookies["cb_auth"] : null;
            AuthCookie authCookie;
            string cookieKey;

            // Check for an existing cookie pointing to valid server-side cached info
            if (cookie != null && AuthCookies.TryGetValue(cookie.Value, out authCookie))
            {
                cookieKey = cookie.Value;

                // TODO: Linear search could be eliminated with a HashSet<>
                if (authCookie.AuthedRealms.Contains(consumer))
                    permissionGranted = true;
            }
            else
            {
                // Create a new cookie
                cookieKey = UUID.Random().ToString();
                authCookie = new AuthCookie(cookieKey, identity);
            }

            // Cookie will expire in five days
            DateTime cookieExpiration = DateTime.Now + TimeSpan.FromDays(5.0);

            // Set cookie information on the server side and in the client response
            AuthCookies.AddOrUpdate(cookieKey, authCookie, cookieExpiration);

            HttpCookie responseCookie = new HttpCookie("cb_auth", cookieKey);
            responseCookie.Expires = cookieExpiration;
            httpResponse.SetCookie(responseCookie);

            return permissionGranted;
        }
Пример #3
0
 public OAuthRequest(Uri identity, UserAuthorizationRequest request, string[] capabilityNames)
 {
     Identity = identity;
     Request = request;
     CapabilityNames = capabilityNames;
 }
Пример #4
0
        bool IsXmlRpcLogin(Uri requestUrl, out UUID sessionID)
        {
            for (int i = requestUrl.Segments.Length - 1; i >= 0; i--)
            {
                if (UUID.TryParse(requestUrl.Segments[i].Replace("/", String.Empty), out sessionID))
                    return true;
            }

            sessionID = UUID.Zero;
            return false;
        }
Пример #5
0
        /// <summary>
        /// Called when an incoming request_capabilities message is received. Loops through all of the
        /// registered Cable Beach services and gives them a chance to create capabilities for each
        /// request in the dictionary
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="identity"></param>
        /// <param name="capabilities"></param>
        public static void CreateCapabilities(Uri identity, ref Dictionary<CapabilityIdentifier, Uri> capabilities)
        {
            UUID sessionID = UUID.Random();

            lock (m_serviceCallbacks)
            {
                foreach (KeyValuePair<ServiceIdentifier, CreateCapabilitiesCallback> entry in m_serviceCallbacks)
                {
                    try { entry.Value(sessionID, identity, ref capabilities); }
                    catch (Exception ex)
                    {
                        Log.Error("[CABLE BEACH SERVER]: Service " + entry.Key +
                            " threw an exception during capability creation: " + ex.Message, ex);
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Handles all GET and POST requests for OpenID identifier pages and endpoint
        /// server communication
        /// </summary>
        public void Handle(string path, Stream request, Stream response, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
        {
            // Try and lookup this avatar
            UserProfileData profile;
            if (CableBeachState.TryGetProfile(httpRequest.Url, out profile))
            {
                if (httpRequest.Url.AbsolutePath.EndsWith(";xrd"))
                {
                    m_log.Debug("[CABLE BEACH IDP]: Returning XRD document for " + profile.Name);

                    Uri identity = new Uri(httpRequest.Url.ToString().Replace(";xrd", String.Empty));

                    // Create an XRD document from the identity URL and filesystem (inventory) service
                    XrdDocument xrd = new XrdDocument(identity.ToString());
                    xrd.Links.Add(new XrdLink(new Uri("http://specs.openid.net/auth"), null, new XrdUri(identity)));
                    xrd.Links.Add(new XrdLink(new Uri(CableBeachServices.FILESYSTEM), "application/json", new XrdUri(CableBeachState.LoginService.m_config.InventoryUrl)));

                    byte[] data = System.Text.Encoding.UTF8.GetBytes(XrdParser.WriteXrd(xrd));
                    httpResponse.ContentLength = data.Length;
                    httpResponse.ContentType = "application/xrd+xml";
                    httpResponse.OutputStream.Write(data, 0, data.Length);
                }
                else
                {
                    m_log.Debug("[CABLE BEACH IDP]: Returning user identity page for " + profile.Name);
                    Uri openidServerUrl = new Uri(httpRequest.Url, "/openid/server");
                    Uri xrdUrl = new Uri(httpRequest.Url, "/users/" + profile.FirstName + "." + profile.SurName + ";xrd");
                    CableBeachState.SendProviderUserTemplate(httpResponse, profile, openidServerUrl, xrdUrl);
                }
            }
            else
            {
                m_log.Warn("[CABLE BEACH IDP]: Couldn't find an account for identity page " + httpRequest.Url);
                // Couldn't parse an avatar name, or couldn't find the avatar in the user server
                httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                OpenAuthHelper.AddToBody(httpResponse, "OpenID identity not found");
            }
        }
Пример #7
0
        XmlRpcResponse LoginHandler(XmlRpcRequest request, Uri requestUrl)
        {
            XmlRpcResponse response = new XmlRpcResponse();
            Hashtable requestData = (Hashtable)request.Params[0];
            IPEndPoint remoteClient = null;
            if (request.Params.Count > 1)
                remoteClient = request.Params[1] as IPEndPoint;

            UserProfileData userProfile;
            LoginResponse logResponse = new LoginResponse();

            UUID sessionID;
            IsXmlRpcLogin(requestUrl, out sessionID);
            m_log.Info("[CABLE BEACH XMLRPC]: XML-RPC Received login request message with sessionID " + sessionID);

            string startLocationRequest = "last";
            if (requestData.Contains("start"))
                startLocationRequest = (requestData["start"] as string) ?? "last";

            string clientVersion = "Unknown";
            if (requestData.Contains("version"))
                clientVersion = (requestData["version"] as string) ?? "Unknown";

            if (TryAuthenticateXmlRpcLogin(sessionID, out userProfile))
            {
                try
                {
                    UUID agentID = userProfile.ID;
                    LoginService.InventoryData skeleton = null;

                    try { skeleton = CableBeachState.LoginService.GetInventorySkeleton(agentID); }
                    catch (Exception e)
                    {
                        m_log.ErrorFormat("[CABLE BEACH XMLRPC]: Error retrieving inventory skeleton of agent {0} - {1}",
                            agentID, e);

                        // Let's not panic
                        if (!CableBeachState.LoginService.AllowLoginWithoutInventory())
                            return logResponse.CreateLoginInventoryFailedResponse();
                    }

                    #region Inventory Skeletons

                    if (skeleton != null)
                    {
                        ArrayList AgentInventoryArray = skeleton.InventoryArray;

                        Hashtable InventoryRootHash = new Hashtable();
                        InventoryRootHash["folder_id"] = skeleton.RootFolderID.ToString();
                        ArrayList InventoryRoot = new ArrayList();
                        InventoryRoot.Add(InventoryRootHash);

                        logResponse.InventoryRoot = InventoryRoot;
                        logResponse.InventorySkeleton = AgentInventoryArray;
                    }

                    // Inventory Library Section
                    Hashtable InventoryLibRootHash = new Hashtable();
                    InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
                    ArrayList InventoryLibRoot = new ArrayList();
                    InventoryLibRoot.Add(InventoryLibRootHash);

                    logResponse.InventoryLibRoot = InventoryLibRoot;
                    logResponse.InventoryLibraryOwner = CableBeachState.LoginService.GetLibraryOwner();
                    logResponse.InventoryLibrary = CableBeachState.LoginService.GetInventoryLibrary();

                    logResponse.CircuitCode = Util.RandomClass.Next();
                    logResponse.Lastname = userProfile.SurName;
                    logResponse.Firstname = userProfile.FirstName;
                    logResponse.AgentID = agentID;
                    logResponse.SessionID = userProfile.CurrentAgent.SessionID;
                    logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
                    logResponse.Message = CableBeachState.LoginService.GetMessage();
                    logResponse.BuddList = CableBeachState.LoginService.ConvertFriendListItem(CableBeachState.LoginService.UserManager.GetUserFriendList(agentID));
                    logResponse.StartLocation = startLocationRequest;

                    #endregion Inventory Skeletons

                    if (CableBeachState.LoginService.CustomiseResponse(logResponse, userProfile, startLocationRequest, remoteClient))
                    {
                        userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
                        CableBeachState.LoginService.CommitAgent(ref userProfile);

                        // If we reach this point, then the login has successfully logged onto the grid
                        if (StatsManager.UserStats != null)
                            StatsManager.UserStats.AddSuccessfulLogin();

                        m_log.DebugFormat("[CABLE BEACH XMLRPC]: Authentication of user {0} {1} successful. Sending response to client",
                            userProfile.FirstName, userProfile.FirstName);

                        return logResponse.ToXmlRpcResponse();
                    }
                    else
                    {
                        m_log.ErrorFormat("[CABLE BEACH XMLRPC]: Informing user {0} {1} that login failed due to an unavailable region",
                            userProfile.FirstName, userProfile.FirstName);

                        return logResponse.CreateDeadRegionResponse();
                    }
                }
                catch (Exception e)
                {
                    m_log.Error("[CABLE BEACH XMLRPC]: Login failed, returning a blank response. Error: " + e);
                    return response;
                }
            }
            else
            {
                m_log.Warn("[CABLE BEACH XMLRPC]: Authentication failed using sessionID " + sessionID + ", there are " +
                    CableBeachState.PendingLogins.Count + " valid pending logins");
                return logResponse.CreateLoginFailedResponse();
            }
        }
Пример #8
0
        void OpenIDLoginGetHandler(OSHttpRequest httpRequest, OSHttpResponse httpResponse)
        {
            if (httpRequest.Url.AbsolutePath.EndsWith("openid_callback"))
            {
                #region OpenID Callback

                IAuthenticationResponse authResponse = CableBeachState.RelyingParty.GetResponse(OpenAuthHelper.GetRequestInfo(httpRequest));

                if (authResponse != null)
                {
                    if (authResponse.Status == AuthenticationStatus.Authenticated)
                    {
                        // OpenID authentication succeeded
                        Uri identity = new Uri(authResponse.ClaimedIdentifier.ToString());

                        // Check if this identity is authorized for access. This check is done here for the second time
                        // because the ClaimedIdentifier after authentication has finished is not necessarily the original
                        // OpenID URL entered into the login form
                        if (CableBeachState.IsIdentityAuthorized(identity))
                        {
                            string firstName = null, lastName = null, email = null;

                            // Get the Simple Registration attributes the IDP returned, if any
                            ClaimsResponse sreg = authResponse.GetExtension<ClaimsResponse>();
                            if (sreg != null)
                            {
                                if (!String.IsNullOrEmpty(sreg.FullName))
                                {
                                    string[] firstLast = sreg.FullName.Split(' ');
                                    if (firstLast.Length == 2)
                                    {
                                        firstName = firstLast[0];
                                        lastName = firstLast[1];
                                    }
                                }

                                email = sreg.Email;
                            }

                            CableBeachState.StartLogin(httpRequest, httpResponse, identity, firstName, lastName, email, CableBeachAuthMethods.OPENID);
                        }
                        else
                        {
                            CableBeachState.SendLoginTemplate(httpResponse, null, identity + " is not authorized to access this world");
                        }
                    }
                    else
                    {
                        // Parse an error message out of authResponse
                        string errorMsg = (authResponse.Exception != null) ?
                            authResponse.Exception.Message :
                            authResponse.Status.ToString();

                        CableBeachState.SendLoginTemplate(httpResponse, null, errorMsg);
                    }
                }
                else
                {
                    httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
                    OpenAuthHelper.AddToBody(httpResponse, "Invalid or missing OpenID callback data");
                }

                #endregion OpenID Callback
            }
            else if (httpRequest.Url.AbsolutePath.EndsWith("oauth_callback"))
            {
                #region OAuth Callback

                ServiceRequestsData stateData;
                string requestToken = OpenAuthHelper.GetQueryValue(httpRequest.Url.Query, "oauth_token");

                if (!String.IsNullOrEmpty(requestToken) && CableBeachState.CurrentServiceRequests.TryGetValue(requestToken, out stateData))
                {
                    ServiceIdentifier serviceIdentifier = CableBeachState.GetCurrentService(stateData.ServiceRequirements);
                    Service service;
                    CapabilityRequirements capRequirements;

                    if (serviceIdentifier != null)
                    {
                        if (stateData.Services.TryGetValue(serviceIdentifier, out service) &&
                            stateData.ServiceRequirements.TryGetValue(serviceIdentifier, out capRequirements))
                        {
                            try
                            {
                                OAuthConsumer consumer = new OAuthConsumer(OpenAuthHelper.CreateServiceProviderDescription(service), CableBeachState.OAuthTokenManager);
                                AuthorizedTokenResponse tokenResponse = consumer.ProcessUserAuthorization(OpenAuthHelper.GetRequestInfo(httpRequest));

                                // We actually don't need the access token at all since the capabilities should be in this response.
                                // Parse the capabilities out of ExtraData
                                CapabilityRequirements newCaps = new CapabilityRequirements();
                                foreach (KeyValuePair<string, string> capability in tokenResponse.ExtraData)
                                {
                                    Uri capIdentifier, capUri;
                                    if (Uri.TryCreate(capability.Key, UriKind.Absolute, out capIdentifier) &&
                                        Uri.TryCreate(capability.Value, UriKind.Absolute, out capUri))
                                    {
                                        newCaps[capIdentifier] = capUri;
                                    }
                                }

                                m_log.Info("[CABLE BEACH LOGIN]: Fetched " + newCaps.Count + " capabilities through OAuth from " + service.OAuthGetAccessToken);

                                // Update the capabilities for this service
                                stateData.ServiceRequirements[serviceIdentifier] = newCaps;
                            }
                            catch (Exception ex)
                            {
                                m_log.Error("[CABLE BEACH LOGIN]: Failed to exchange request token for capabilities at " + service.OAuthGetAccessToken + ": " + ex.Message);
                                CableBeachState.SendLoginTemplate(httpResponse, null, "OAuth request to " + service.OAuthGetAccessToken + " failed: " + ex.Message);
                                return;
                            }
                        }
                        else
                        {
                            m_log.Error("[CABLE BEACH LOGIN]: OAuth state data corrupted, could not find service or service requirements for " + serviceIdentifier);
                            CableBeachState.SendLoginTemplate(httpResponse, null, "OAuth state data corrupted, please try again");
                            return;
                        }
                    }
                    else
                    {
                        m_log.Warn("[CABLE BEACH LOGIN]: OAuth callback fired but there are no unfulfilled services. Could be a browser refresh");
                    }

                    // Check if we need to continue the cap requesting process
                    CableBeachState.GetCapabilitiesOrCompleteLogin(httpRequest, httpResponse, stateData, requestToken);
                }
                else
                {
                    // A number of different things could lead here (incomplete login sequence, browser refresh of a completed sequence).
                    // Safest thing to do would be to redirect back to the login screen
                    httpResponse.StatusCode = (int)HttpStatusCode.Found;
                    httpResponse.AddHeader("Location", new Uri(CableBeachState.UserServerUrl, "/login/").ToString());
                }

                #endregion OAuth Callback
            }
            else
            {
                // Make sure we are starting from the correct URL
                if (httpRequest.Url.Authority != CableBeachState.UserServerUrl.Authority)
                {
                    m_log.Debug("[CABLE BEACH LOGIN]: Redirecting from " + httpRequest.Url + " to " + CableBeachState.UserServerUrl);
                    httpResponse.StatusCode = (int)HttpStatusCode.Redirect;
                    httpResponse.RedirectLocation = new Uri(CableBeachState.UserServerUrl, "/login/").ToString();
                }
                else if (httpRequest.Query.ContainsKey("openid_identifier"))
                {
                    OpenIDLoginFormHandler(httpRequest, httpResponse, httpRequest.Query["openid_identifier"] as string);
                }
                else
                {
                    // TODO: Check for a client cookie with an authenticated session
                    CableBeachState.SendLoginTemplate(httpResponse, null, null);
                }
            }
        }
Пример #9
0
        void SetCookie(OSHttpResponse httpResponse, Uri identity, UserProfileData profile)
        {
            string cookieKey = UUID.Random().ToString();

            // Cookie will expire in five days
            DateTime cookieExpiration = DateTime.Now + TimeSpan.FromDays(5.0);

            // Cache the server-side data
            CableBeachState.AuthCookies.AddOrUpdate(cookieKey, new AuthCookie(cookieKey, identity, profile), cookieExpiration);

            // Create the cookie
            HttpCookie responseCookie = new HttpCookie("cb_openid_auth", cookieKey);
            responseCookie.Expires = cookieExpiration;
            httpResponse.SetCookie(responseCookie);
        }
Пример #10
0
        bool DoAuthentication(OSHttpResponse httpResponse, DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest authRequest, ClaimsRequest claimsRequest,
            string first, string last, string pass)
        {
            bool authSuccess = false;

            if (!String.IsNullOrEmpty(first) && !String.IsNullOrEmpty(last) && !String.IsNullOrEmpty(pass))
            {
                UserProfileData profile;
                if (CableBeachState.TryGetProfile(first, last, out profile))
                {
                    // Set the claimed identifier to the URL of the given identity
                    Uri identity = new Uri(CableBeachState.UserServerUrl, String.Format("/users/{0}.{1}", profile.FirstName, profile.SurName));
                    authRequest.ClaimedIdentifier = identity;

                    authSuccess = CableBeachState.LoginService.AuthenticateUser(profile, pass);
                    m_log.Info("[CABLE BEACH IDP]: Password match result for " + profile.Name + ": " + authRequest.IsAuthenticated);

                    if (authSuccess)
                    {
                        // Mark the OpenID request as successfully authenticated
                        authRequest.IsAuthenticated = true;

                        // Cache this login
                        SetCookie(httpResponse, identity, profile);

                        if (claimsRequest != null)
                        {
                            // Fill in a few Simple Registration values if there was a request for SREG data
                            ClaimsResponse claimsResponse = claimsRequest.CreateResponse();
                            claimsResponse.Email = profile.Email;
                            claimsResponse.FullName = profile.Name;
                            claimsResponse.BirthDate = Utils.UnixTimeToDateTime(profile.Created);
                            authRequest.AddResponseExtension(claimsResponse);

                            m_log.Debug("[CABLE BEACH IDP]: Appended SREG values to the positive assertion response");
                        }
                    }
                }
                else
                {
                    m_log.Warn("[CABLE BEACH IDP]: Profile for user " + first + " " + last + " not found");
                }
            }
            else
            {
                // Valid POST but missing one or more fields
                m_log.Warn("[CABLE BEACH IDP]: POST is missing first, last, or pass field, sending directed login form");
            }

            return authSuccess;
        }