29 using System.Collections.Generic;
30 using System.Collections.Specialized;
35 using DotNetOpenId.Provider;
36 using OpenSim.Framework;
37 using OpenSim.Framework.Servers;
38 using OpenSim.Framework.Servers.HttpServer;
39 using OpenSim.Server.Handlers.Base;
40 using OpenSim.Services.Interfaces;
44 namespace OpenSim.Server.Handlers.Authentication
51 private class AssociationItem
53 public AssociationRelyingPartyType DistinguishingFactor;
55 public DateTime Expires;
56 public byte[] PrivateData;
59 Dictionary<string, AssociationItem> m_store =
new Dictionary<string, AssociationItem>();
60 SortedList<DateTime, AssociationItem> m_sortedStore =
new SortedList<DateTime, AssociationItem>();
61 object m_syncRoot =
new object();
63 #region IAssociationStore<AssociationRelyingPartyType> Members
65 public void StoreAssociation(AssociationRelyingPartyType distinguishingFactor, Association assoc)
67 AssociationItem item =
new AssociationItem();
68 item.DistinguishingFactor = distinguishingFactor;
69 item.Handle = assoc.Handle;
70 item.Expires = assoc.Expires.ToLocalTime();
71 item.PrivateData = assoc.SerializePrivateData();
75 m_store[item.Handle] = item;
76 m_sortedStore[item.Expires] = item;
80 public Association
GetAssociation(AssociationRelyingPartyType distinguishingFactor)
84 if (m_sortedStore.Count > 0)
86 AssociationItem item = m_sortedStore.Values[m_sortedStore.Count - 1];
87 return Association.Deserialize(item.Handle, item.Expires.ToUniversalTime(), item.PrivateData);
96 public Association
GetAssociation(AssociationRelyingPartyType distinguishingFactor,
string handle)
101 success = m_store.TryGetValue(handle, out item);
104 return Association.Deserialize(item.Handle, item.Expires.ToUniversalTime(), item.PrivateData);
113 for (
int i = 0; i < m_sortedStore.Values.Count; i++)
115 AssociationItem item = m_sortedStore.Values[i];
116 if (item.Handle == handle)
118 m_sortedStore.RemoveAt(i);
123 return m_store.Remove(handle);
131 List<AssociationItem> itemsCopy =
new List<AssociationItem>(m_sortedStore.Values);
132 DateTime now = DateTime.Now;
134 for (
int i = 0; i < itemsCopy.Count; i++)
136 AssociationItem item = itemsCopy[i];
138 if (item.Expires <= now)
140 m_sortedStore.RemoveAt(i);
141 m_store.Remove(item.Handle);
155 const string LOGIN_PAGE =
157 <head><title>OpenSim OpenID Login</title></head>
159 <h3>OpenSim Login</h3>
160 <form method=""post"">
161 <label for=""first"">First Name:</label> <input readonly type=""text"" name=""first"" id=""first"" value=""{0}""/>
162 <label for=""last"">Last Name:</label> <input readonly type=""text"" name=""last"" id=""last"" value=""{1}""/>
163 <label for=""pass"">Password:</label> <input type=""password"" name=""pass"" id=""pass""/>
164 <input type=""submit"" value=""Login"">
170 const string OPENID_PAGE =
173 <title>{2} {3}</title>
174 <link rel=""openid2.provider openid.server"" href=""{0}://{1}/openid/server/""/>
176 <body>OpenID identifier for {2} {3}</body>
181 const string INVALID_OPENID_PAGE =
182 @"<html><head><title>Identity not found</title></head>
183 <body>Invalid OpenID identity</body></html>";
186 const string ENDPOINT_PAGE =
187 @"<html><head><title>OpenID Endpoint</title></head><body>
188 This is an OpenID server endpoint, not a human-readable resource.
189 For more information, see <a href='http://openid.net/'>http://openid.net/</a>.
198 public override string ContentType {
get {
return "text/html"; } }
205 : base(httpMethod, path,
"OpenId",
"OpenID stream handler")
207 m_authenticationService = authService;
208 m_userAccountService = userService;
218 Uri providerEndpoint =
new Uri(String.Format(
"{0}://{1}{2}", httpRequest.
Url.Scheme, httpRequest.
Url.Authority, httpRequest.
Url.AbsolutePath));
221 httpResponse.ContentType = ContentType;
225 NameValueCollection postQuery = HttpUtility.ParseQueryString(
new StreamReader(httpRequest.
InputStream).ReadToEnd());
226 NameValueCollection getQuery = HttpUtility.ParseQueryString(httpRequest.Url.Query);
227 NameValueCollection openIdQuery = (postQuery.GetValues(
"openid.mode") != null ? postQuery : getQuery);
229 OpenIdProvider provider =
new OpenIdProvider(m_openidStore, providerEndpoint, httpRequest.
Url, openIdQuery);
231 if (provider.Request != null)
233 if (!provider.Request.IsResponseReady && provider.Request is IAuthenticationRequest)
235 IAuthenticationRequest authRequest = (IAuthenticationRequest)provider.Request;
236 string[] passwordValues = postQuery.GetValues(
"pass");
239 if (TryGetAccount(
new Uri(authRequest.ClaimedIdentifier.ToString()), out account))
242 if (passwordValues != null && passwordValues.Length == 1)
244 if (account != null &&
245 (m_authenticationService.Authenticate(account.PrincipalID,Util.Md5Hash(passwordValues[0]), 30) !=
string.Empty))
246 authRequest.IsAuthenticated =
true;
248 authRequest.IsAuthenticated =
false;
253 using (StreamWriter writer =
new StreamWriter(response))
254 writer.Write(String.Format(LOGIN_PAGE, account.FirstName, account.LastName));
261 authRequest.IsAuthenticated =
false;
266 foreach (
string key in provider.Request.Response.Headers.Keys)
267 httpResponse.AddHeader(
key, provider.Request.Response.Headers[
key]);
269 string[] contentTypeValues = provider.Request.Response.Headers.GetValues(
"Content-Type");
270 if (contentTypeValues != null && contentTypeValues.Length == 1)
271 httpResponse.ContentType = contentTypeValues[0];
274 httpResponse.StatusCode = (int)provider.Request.Response.Code;
275 response.Write(provider.Request.Response.Body, 0, provider.Request.Response.Body.Length);
278 else if (httpRequest.
Url.AbsolutePath.Contains(
"/openid/server"))
281 using (StreamWriter writer =
new StreamWriter(response))
282 writer.Write(ENDPOINT_PAGE);
288 if (TryGetAccount(httpRequest.
Url, out account))
290 using (StreamWriter writer =
new StreamWriter(response))
293 writer.Write(String.Format(OPENID_PAGE, httpRequest.Url.Scheme,
294 httpRequest.Url.Authority, account.FirstName, account.LastName));
300 using (StreamWriter writer =
new StreamWriter(response))
301 writer.Write(INVALID_OPENID_PAGE);
307 httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
308 using (StreamWriter writer =
new StreamWriter(response))
309 writer.Write(ex.Message);
320 bool TryGetAccount(Uri requestUrl, out
UserAccount account)
322 if (requestUrl.Segments.Length == 3 && requestUrl.Segments[1] ==
"users/")
325 string username = requestUrl.Segments[requestUrl.Segments.Length - 1];
326 string[] name = username.Split(
'_');
328 if (name.Length == 2)
330 account = m_userAccountService.GetUserAccount(UUID.Zero, name[0], name[1]);
331 return (account != null);
Association GetAssociation(AssociationRelyingPartyType distinguishingFactor, string handle)
OpenIdStreamHandler(string httpMethod, string path, IUserAccountService userService, IAuthenticationService authService)
Constructor
Base handler for writing to an output stream
Association GetAssociation(AssociationRelyingPartyType distinguishingFactor)
void StoreAssociation(AssociationRelyingPartyType distinguishingFactor, Association assoc)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
void ClearExpiredAssociations()
override void ProcessRequest(string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
Handles all GET and POST requests for OpenID identifier pages and endpoint server communication ...
Temporary, in-memory store for OpenID associations
bool RemoveAssociation(AssociationRelyingPartyType distinguishingFactor, string handle)