logo

The ConnectWise Control forum has moved to ConnectWise University! This forum has been locked and is in read-only mode. Click here for instructions on how to access the new forum.

Welcome Guest! You can not login or register.

Notification

Icon
Error

Options
Go to last post Go to first unread
Scott Wilson  
#1 Posted : Thursday, March 21, 2013 12:35:26 PM(UTC)
Scott Wilson


Rank: Newbie

Medals: Level 1: Random Act of Kindness! Received One Thanks!

Joined: 3/21/2013(UTC)
Posts: 8

Was thanked: 1 time(s) in 1 post(s)
We are looking at integrating ScreenConnect with Phonefactor. We have need to require 2 factor auth when techs are offsite. We don't want to turn ScreenConnect into a remote access solution without 2 factor auth. We already integrate PhoneFactor with Citrix for remote access so by extending to SC we are being consistent.

The sample below supports the PhoneFactor Whitelist.


So the setup is this.

1. Create a PhoneFactor Web Service Proxy using .NET 3.5 SDK to ScreenConnect bin directory
2. PhoneFactor Web Service must be installed somewhere so the ScreenConnect Web server can access it.
3. Add the following appSettings to the web.config file of ScreenConnect

<add key="PfAuth" value="true" />
<add key="PfAuthWsUrl" value="https://<host>/PhoneFactorWebServiceSdk/PfWsSdk.asmx" />
<add key="PfAuthWsID" value="pf_admin" />
<add key="PfAuthWsPwd" value="pf_admin_password" />
4. Modify Login.aspx..see snippets below.

New function in login.aspx
Code:


// Scott Wilson -- Start PhoneFactor Auth Function
	
	protected Boolean PfAuth(string UserID, string IpAddress)
    {
        //Create Web Service Proxy
        PfWsSdk pf = new PfWsSdk();
        //Create Error Handler for Proxy
        Error pfError = new Error();
        //Create Result for Proxy
        CallResult pfResult = new CallResult();
        //Whitelist for bypass
        UserPortalWhitelistIp[] pfWhiteList = new UserPortalWhitelistIp[0];

        //Need credentials for PF Web Service proxy.  Uses Basic Auth.  Credentials need to be member of  PhoneFactor Admin Group
        System.Net.NetworkCredential pfCredentials = new System.Net.NetworkCredential();

        //ID, Password, Whitelist, 
        string pfUser;
        string pfPwd;
        
        bool pfEnabled;

        pfEnabled = false;

        //Get the settings, these could be passed but what the hey
        System.Collections.Specialized.NameValueCollection configuration = System.Web.Configuration.WebConfigurationManager.AppSettings;
        if (configuration.Count > 0)
        {
            
            //Get AppSettings
            pfEnabled = System.Convert.ToBoolean(configuration["PfAuth"]);
            pfUser = configuration["PfAuthWsID"];
            pfPwd = configuration["PfAuthWsPwd"];
                                 
            pfCredentials.UserName = pfUser;
            pfCredentials.Password = pfPwd;
            pf.Credentials = pfCredentials;
            pf.Url = configuration["PfAuthWsUrl"];



            //Check the Whitelist
            try
            {
                //Get the whitelist
                pf.GetUserPortalWhitelistIps(ref pfWhiteList, ref pfError);

                // Check every entry in the whitelist of UserPortal..I only use the range values..subnet, hosts, etc need to use ranage
                foreach (UserPortalWhitelistIp pfWhiteListEntry in pfWhiteList)
                {
                    try
                    {

                        System.Net.IPAddress startIP;
                        System.Net.IPAddress endIP;
                        System.Net.IPAddress testIP;

                        testIP = System.Net.IPAddress.Parse(Request.UserHostAddress);
                        startIP = System.Net.IPAddress.Parse(pfWhiteListEntry.FromIp);
                        endIP = System.Net.IPAddress.Parse(pfWhiteListEntry.ToIp);

                        byte[] testIPbytes = testIP.GetAddressBytes();
                        byte[] startIPbytes = startIP.GetAddressBytes();
                        byte[] endIPbytes = endIP.GetAddressBytes();

                        if (testIPbytes[0] >= startIPbytes[0] && testIPbytes[0] <= endIPbytes[0])
                        {
                            if (testIPbytes[1] >= startIPbytes[1] && testIPbytes[1] <= endIPbytes[1])
                            {
                                if (testIPbytes[2] >= startIPbytes[2] && testIPbytes[2] <= endIPbytes[2])
                                {
                                    if (testIPbytes[3] >= startIPbytes[3] && testIPbytes[3] <= endIPbytes[3])
                                    {
                                        //If all my tests succeed..then set PF to false and bypass below.
                                        pfEnabled = false;
                                    }
                                }
                            }
                        }
                    }
                    catch
                    {

                    }
                                                  
                }
                
                if (pfEnabled == true)
                {
                    pf.PfAuthUser_3(UserID, AuthenticationType.unspecified, Request.UserHostAddress, "ScreenConnect", true, ref pfResult, ref pfError);
                    
                    // Code 21 Cache, code 8 success
                    if ((pfResult.Code != 21) && (pfResult.Code != 8))
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }

                }

            }
            catch
            {
                //something went wrong
                return false;
            }
            
        }
        
        //Bad config so we fail
        return false;
    }
// Scott Wilson -- End PhoneFactor Auth Function





Code:

void OnLoginPanelAuthenticate(object sender, AuthenticateEventArgs e)
	{
		var isUserValid = Membership.ValidateUser(this.loginPanel.UserName, this.loginPanel.Password);
		var oneTimePasswordUserKey = default(string);
		var oneTimePasswordAuthenticationProvider = default(OneTimePasswordAuthenticationProvider);

		if (isUserValid)
		{

		// Scott Wilson - PF Auth Begin
			System.Collections.Specialized.NameValueCollection configuration = System.Web.Configuration.WebConfigurationManager.AppSettings;
			if (System.Convert.ToBoolean(configuration["PfAuth"]))
			{
				if (!PfAuth(this.loginPanel.UserName, Request.UserHostAddress))
				{
					isUserValid = false;					
				}
			}	

		// Scott Wilson - PF Auth End

			this.GetOneTimePasswordAuthenticationInfo(ref oneTimePasswordUserKey, ref oneTimePasswordAuthenticationProvider);

			if (oneTimePasswordUserKey == null)



5. Enjoy.


Please contact me if you have questions.

This is a "beta" setup. It could still be prettier and integrated into the main code branch...
HINT..HINT..

:-)

Another idea would be to configure SC to support Radius Auth since PhoneFactor has a Radius Proxy, then the code wouldn't be required.
Another idea would be to have an IIS version of SC since PhoneFactor has an IIS Plugin to do Form Authentication.

Scott

Scott Wilson  
#2 Posted : Friday, March 22, 2013 4:15:15 PM(UTC)
Scott Wilson


Rank: Newbie

Medals: Level 1: Random Act of Kindness! Received One Thanks!

Joined: 3/21/2013(UTC)
Posts: 8

Was thanked: 1 time(s) in 1 post(s)
Ok..
Have an update.

My original code used the Web Service of PhoneFactor to perform the Auth. You must be a paying PhoneFactor customer to use this Web Services. I created a PF Radius Agent which is available under the free version of PhoneFactor up to 25 people at your company. You might be able to use this with any radius server if you want.

1. Go to http://nradius.nw-network.com/web/index.php. Download source .zip file. Create a new library C# project and compile the class to make a .NET object. Make sure you use the 3.5 framework
2. Copy the resulting .DLL to your BIN directory on ScreenConnect.
3. ScreenConnect Server must have network access to RADIUS server to so make sure all firewall settings are correct.
4. Add the following AppSettings to web.config
Quote:

<add key="PfAuth" value="true" />
<add key="PfRadiusSvr" value="<radius server>" />
<add key="PfRadiusPwd" value="<radius shared secret>" />


5. Add the following code to near top of Login.aspx

Code:


// Scott Wilson -- Start PhoneFactor Radius Auth Function
	protected Boolean PfRadiusAuth(string UserID, string Password)
	{
		int result;
        int wait;
		string pfRadiusSvr;
		string pfRadiusPwd;
		bool pfEnabled;
		
		//Get Settings
		System.Collections.Specialized.NameValueCollection configuration = System.Web.Configuration.WebConfigurationManager.AppSettings;
        if (configuration.Count > 0)
        {
            
            //Get AppSettings
	    pfEnabled = System.Convert.ToBoolean(configuration["PfAuth"]);
            pfRadiusSvr = configuration["PfRadiusSvr"];
            pfRadiusPwd = configuration["PfRadiusPwd"];
                                 
        }
		else
		{
			return false;
		}

		//Radius Timeout to 2 minutes..could be configured with AppSetting
        wait = 120000;
                      
		if (UserID != "" && Password != "" && pfEnabled == true) 
		{
			System.Net.nRadius.nRadius_Client pfRadius = new System.Net.nRadius.nRadius_Client(pfRadiusSvr, pfRadiusPwd, UserID, Password);
			pfRadius.UDPTimeout = wait;
			
			//Attribute 66 needed to do a whitelist lookup on PF Agent
			pfRadius.SetAttribute(66, Request.UserHostAddress);
			result = pfRadius.Authenticate();

			switch (result)
			{
			//Deny
				case -4:
					return false;
					break;                                                
			//Timeout
			   case -2:
					return false;
					break;                                                
			//Access Granted
				case 0:
					return true;
					break;
				default:
					return false;
					break;
			}
									  						  
		}
		else
		return false;
	}

//SW End PF Radius



6. Add the following code further down in login.aspx OnLoginPanelAuthenticate function.


Quote:

if (isUserValid)
{

// Scott Wilson - PF Auth Begin
System.Collections.Specialized.NameValueCollection configuration = System.Web.Configuration.WebConfigurationManager.AppSettings;
if (System.Convert.ToBoolean(configuration["PfAuth"]))
{
if (!PfRadiusAuth(this.loginPanel.UserName, this.loginPanel.Password))
{
isUserValid = false;
this.Response.Redirect("deny.html");
}
}
// Scott Wilson - PF Auth End


Thanks,
Scott
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.