using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Security.Principal;
using System.Web.Security;
using System.Data.OleDb;
using System.Xml;
using System.Web.Configuration;
using Sage.Platform.Application;
using Sage.SalesLogix;
using System.Web.Caching;
using log4net;
using SSSWorld.Common;
using System.Data;
using Sage.Platform.Data;
namespace SSSWorld.Slx72.Web.Utility
{
///
/// Replacement for the Saleslogix MixedModeSecurityModule.
/// It uses the connection string from the legacy site for the authentication.
/// This avoids having to set up the delegation (which implies running the service as a trusted user).
/// To use it, replace the configured MixedModeSecurityModule in web.config.
/// The "legacy" connection string must be set up properly in the registry (using the legacy web manager).
///
public class MixedModeSecurityModuleHelper : IHttpModule
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(MixedModeSecurityModuleHelper));
public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(this.context_EndRequest);
context.PostAcquireRequestState += new EventHandler(this.context_PostAcquireRequestState);
(context.Modules["FormsAuthentication"] as FormsAuthenticationModule).Authenticate += new FormsAuthenticationEventHandler(this.MixedModeSecurityModule_Authenticate);
}
private void context_EndRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
if (context.Items["_hid401Status"] != null)
{
context.Response.StatusCode = 0x191;
context.Items["_hid401Status"] = null;
LOG.Debug("Restored 401 status");
}
}
///
/// Retrieve the info that has been stored in the cache during the Authenticate
/// event, and if available initializes the user's context with it.
///
///
///
private void context_PostAcquireRequestState(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
string str = context.Request.ServerVariables["LOGON_USER"];
object obj2 = context.Cache.Get(str + "WinAuth");
if (obj2 != null)
{
AuthUserInfo info = (AuthUserInfo)obj2;
if (!string.IsNullOrEmpty(info._UserCode) && (ApplicationContext.Current != null))
{
if (!ApplicationContext.Current.Services.Get().IsAuthenticated)
{
Membership.ValidateUser(info._UserCode, SLXEncryption.Decrypt(info._Password, info._UserId).Trim());
}
if (ApplicationContext.Current != null)
{
IContextService service = ApplicationContext.Current.Services.Get(true);
if (((service != null) && (service["TimeZone"] == null)) && (string.IsNullOrEmpty(context.Request.Params["loadtz"]) && !string.IsNullOrEmpty(info._UserCode)))
{
string absolutePath = context.Request.Url.AbsolutePath;
context.Response.Redirect(string.Format("~/WinAuthLoad.aspx?next_url={0}&loadtz=true", absolutePath));
}
context.Cache.Remove(str + "WinAuth");
}
}
}
}
private IPrincipal CreateUser(string user, WindowsIdentity wi, HttpContext context)
{
string str = WebConfigurationManager.AppSettings["UseWindowsPrincipal"];
if (!string.IsNullOrEmpty(str) && (str != "false"))
{
return new WindowsPrincipal(wi);
}
AuthenticationSection section = (AuthenticationSection)WebConfigurationManager.GetSection("system.web/authentication");
int totalMinutes = (int)section.Forms.Timeout.TotalMinutes;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user, DateTime.Now, DateTime.Now.AddMinutes((double)totalMinutes), false, "", FormsAuthentication.FormsCookiePath);
SetAuthenticationCookie(context, ticket);
return new GenericPrincipal(new FormsIdentity(ticket), null);
}
private static void GetUserNamePass(WindowsIdentity identity, AuthUserInfo aui)
{
// don't use this - trying to access dataservice will cause NullRef
//IDataService dataService = ApplicationContext.Current.Services.Get();
string connectionString = GetConnectionString();
String sid = identity.User.ToString();
//LOG.Debug("Retrieving user info for " + identity.Name + " (SID: " + sid + ")");
try
{
//LOG.Debug("Using connection string " + connectionString);
using (DBConnectionWrapper con = new DBConnectionWrapper(connectionString))
{
//LOG.Debug("Connected");
if (String.Equals(con.GetField("USEWINDOWSAUTH", "SYSTEMINFO", "SYSTEMINFOID='PRIMARY'"),
"T"))
{
using (IDataReader reader =
con.OpenDataReader("SELECT USERCODE,USERPW, US.USERID, UI.USEWINDOWSAUTH FROM USERSECURITY US JOIN USERINFO UI ON US.USERID=UI.USERID WHERE UI.WINDOWSSID = ?", sid))
{
//LOG.Debug("Got user info");
if (reader.Read())
{
aui._UserCode = reader.GetString(0);
aui._Password = reader.GetString(1);
aui._UserId = reader.GetString(2);
}
else
{
LOG.Info("Could not locate usersecurity record for sid " + sid);
}
}
}
LOG.Debug("Windows Authentication: Returning [" + aui._UserCode + "],[" + aui._UserId + "]");
}
}
catch (OleDbException x)
{
LOG.Debug("Unable to create connection for Windows authentication - Make sure connection is setup in legacy web settings", x);
return;
}
catch (Exception x)
{
LOG.Warn("Uncaught exception in GetUserPass", x);
throw;
}
}
///
/// Retrieve connection string from the registry
/// (this relies on the legacy web settings being configured correctly)
///
///
private static String GetConnectionString()
{
return SSSWorld.Common.Saleslogix.SLXConnectionInfo.GetWebConnection(
HttpContext.Current.Server.MachineName,
HttpContext.Current.Request.Url.Port).BuildConnectionString();
/*
XmlReader reader = XmlReader.Create(HttpContext.Current.Server.MapPath("~/connection.config"));
if (!reader.ReadToDescendant("ConString"))
throw new InvalidOperationException("Can't locate ConString node");
reader.Read();
OleDbConnectionStringBuilder bldr = new OleDbConnectionStringBuilder(reader.Value);
bldr["User Id"] = "ADMIN";
bldr["Password"] = "sssworld231";
return bldr.ConnectionString;
*/
}
private void MixedModeSecurityModule_Authenticate(object sender, FormsAuthenticationEventArgs e)
{
HttpContext context = e.Context;
if (context.Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(context.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
e.User = new GenericPrincipal(new FormsIdentity(ticket), new string[0]);
string str = context.Request.ServerVariables["LOGON_USER"];
if (!string.IsNullOrEmpty(str))
{
context.Response.Cookies.Remove("." + str);
}
}
else if (context.Request.RawUrl.ToUpper().Contains("WINDOWS.ASPX"))
{
string str2 = context.Request.ServerVariables["LOGON_USER"];
if (string.IsNullOrEmpty(str2))
{
WindowsIdentity anonymous = WindowsIdentity.GetAnonymous();
e.User = new WindowsPrincipal(anonymous);
}
else if ((context.Request.Cookies["." + str2] == null) && ((!string.IsNullOrEmpty(str2) && (context.Request.LogonUserIdentity.GetType() == typeof(WindowsIdentity))) && context.Request.LogonUserIdentity.IsAuthenticated))
{
AuthUserInfo aui = new AuthUserInfo();
lock (aui)
{
GetUserNamePass(context.Request.LogonUserIdentity, aui);
if (context.Cache[str2 + "WinAuth"] != null)
{
context.Cache[str2 + "WinAuth"] = aui;
}
if (!string.IsNullOrEmpty(aui._UserCode))
{
context.Cache.Add(str2 + "WinAuth", aui, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5.0), CacheItemPriority.NotRemovable, null);
e.User = this.CreateUser(aui._UserCode, context.Request.LogonUserIdentity, context);
}
else
{
HttpCookie cookie = new HttpCookie("." + str2);
cookie.Expires = DateTime.Now.AddSeconds(30.0);
cookie.HttpOnly = true;
context.Response.SetCookie(cookie);
}
}
}
}
}
private static void SetAuthenticationCookie(HttpContext context, FormsAuthenticationTicket ticket)
{
string str = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(".SLXAUTH");
cookie.Value = str;
cookie.Secure = FormsAuthentication.RequireSSL;
cookie.Domain = FormsAuthentication.CookieDomain;
cookie.HttpOnly = false;
context.Response.Cookies.Add(cookie);
}
private class AuthUserInfo
{
// Fields
public string _Password;
public string _UserCode;
public string _UserId;
// Methods
public AuthUserInfo()
{
this._UserCode = "";
this._Password = "";
this._UserId = "";
}
public AuthUserInfo(string uc, string pw, string id)
{
this._UserCode = uc;
this._Password = pw;
this._UserId = id;
}
}
public void Dispose()
{
}
}
}