Customizing Citrix StoreFront 2.6 including Pre-Login message page

Here are my StoreFront customizations for Citrix StoreFront 2.6.  Many are similar to previous version of SF, however some of the syntax changed.

There are some good improvements/features SF 2.6 brings, one that I like and works best where I currently work is the Web Folder View, which in the past had to be done by running StoreFront in lock down mode.  This new view can certainly help your users feel more comfortable when moving from Web Interface.

Fist take a look at the new features of StoreFront which are listed under this link from Citrix.

Secondly I would like to thank Sam Jacobs which provided some of his code he presented at Citrix Synergy 2014.  You can view the presentation here 

Environment:

  • Windows 2008 R2
  • Citrix XenApp 6.5 Hotfix Rollup Pack 2
  • PVS 6.1.16
  • StoreFront 2.6
  • Citrix NetScaler 10.1 build 122.17

Customizations: (All custom files will need to be created under the contrib folder is located under the SF site in the file system (typical location is C:inetpubwwwrootsitesCitrixStoreWebNamecontrib

The following customizations include the following

  • Pre-Login message page
  • Front Page with custom logo and title header
  • App/Desktop page with custom logo, user client IP (For NetScaler load balancing make sure to use X-Forwarded-For to load balance your StoreFront servers, utilizing CLIENT-IP for your VIP will return the SNIP of your NetScaler as the source IP for the user client IP module :P)
  • Apps/Desktop Tab on top with Disable user multiclick
  • Page footer

03-pre_login_screen

01-front_page_logo

02-apps_page_logo

Back up the original files under C:inetpubwwwrootsitesCitrixStoreWebNamecontrib

Steps:

1. Overwrite the following files

  • custom.wrstrings.en.js
  • custom.script.js
  • custom.style.css

2. Create new files

  • GetServerData.aspx
  • companylogo_whiteTrans.png
  • companylogo_whitetrans_small.png

Code:

custom.wrstrings.en.js

(function ($) {
$.localization.customStringBundle(‘en’, {
Disclaimer: ‘Authorized Use Only’,
DisclaimerStatement: ‘You must be assigned an account to access this system.’
+ ‘ The information on this system and network is the property of this organization and is protected by intellectual property rights.’
+ ‘ By clicking the button below, you are consenting to the monitoring of your activities on the system’,
Continue: ‘Continue’
});
})(jQuery);

custom.script.js (You can certainly change the way I am working with $(document).ready(function() { and clean it up a bit

// StoreFront customizations

// Replace title
document.title = ‘Remote Access’;

// Place Apps/Desktop Tab on top
$(document).ready(function() {
$(“#resources-switcher” ).detach().appendTo(“#resources-header” );
});

// Disable User Multi Click 😛
$(document).ready(function() {
CTXS.Resources.multiClickTimeout = 10;
});

// Display client IP and StoreFront server
$.ajax({
url: ‘contrib/GetServerData.aspx?serverData=clientIPandServerName’,
success: function(data) {
var $markup = $(‘<div id=”server-info”>’ + data + ‘</div>’);
$markup.insertBefore(‘#header-userinfo’);
}
});

// Logon page footer text

// $(document).ready(function() {
// var $footercontent = $(‘<div id=”authentication-footer”><div id=”authentication-copyrightfooter”> <p id=”authentication-copyrightFooterText”></p></div></div>’);
// $footercontent.insertAfter(‘#logonbelt-bottomshadow’);
// });

// $(document).ready(function() {
// $(‘#authentication-copyrightfooter’)[0].innerHTML =
// ‘<p>&copy;2014&nbsp; Access restricted to authorized users.</p>’;
// });

// application page footer text

$(document).ready(function() {
$(‘#copyrightfooter’)[0].innerHTML = ‘<p>&copy;2014&nbsp; Name of your company</p>’;
});

// Prelogin page

$(document).ready(function() {
CTXS.Application.preLoginHook = function () {
var _dialogTitle = ‘<h1’
+ ‘ class=”messagebox-title _ctxstxt_Disclaimer”></h1>’;
var _dialogBody = ‘<div class=”messagebox-body”>’ +
‘<p class=”_ctxstxt_DisclaimerStatement”></p></div>’;
var _dialogButton = ‘<div class=”messagebox-buttons”>’ +
‘<a href=”#” class=”button _ctxstxt_Continue”></a></div>’;
var dialog = _dialogTitle + _dialogBody + _dialogButton;
var $messagePane = CTXS.displayMessagePane(dialog).ctxsLocalize();
var $button = $messagePane.find(‘.button’);
$button.click(function () {
CTXS.Events.publish(CTXS.Events.preLogin.done);
return false;
}).ctxsHandleEscapeKeyInDialog().ctxsPlaceFocusOnFirstElement(
).ctxsBindFocusWithin();
};
});

 

custom.style.css

/*
StoreFront customizations
*/

#credentialupdate-logonimage, #logonbox-logoimage {
background-image: url(“companylogo_whiteTrans.png”);
height: 50px;
width: 283px;
}

#header-logo {
background-image: url(“companylogo_whitetrans_small.png”);
height: 31px;
margin: 8px 0 0 22px;
width: 179px;
}

#resources-header {
height: 84px;
}

#resources-switcher {
padding-top: 48px;
text-align: center;
}

/* Help Desk info */

/* Logon labels */
#logonbox-logonform label{
color:white;
display:table-cell;
font-size:14px;
height:20px;
vertical-align:bottom;
}

/* welcome message and username */
#resources-header #header-userinfo {
float:left;
margin-top:12px;
margin-right:100px;
vertical-align:middle;
color:white;
}

#header-username,
#header-userinfo A {
color:white;
font-size:12px;
}

/* for added server info */
#server-info {
color: white;
font-size:12px;
float: left;
margin-right: 40px;
margin-top: 12px;
position: relative;
vertical-align: middle;
}

/* EOF Help Desk info */

/* Logon page footer text
#copyrightfooter p,
#copyrightfooter a,
#authentication-copyrightfooter p,
#authentication-copyrightfooter a
{color:white;}

*/
/* turn off searchbox
#resources-searcharea {
display: none;
}
*/

GetServerData.aspx

<%@ Page Language=”C#” %>

<script runat=”server” language=”C#”>

private string GetClientIP()
{
string ips = Request.ServerVariables[“HTTP_X_FORWARDED_FOR”];

if (!string.IsNullOrEmpty(ips))
{
return ips.Split(‘,’)[0];
}

return Request.ServerVariables[“REMOTE_ADDR”];
}

private string GetServerName()
{
// for security purposes, only return the last 2 chars
string server = Environment.MachineName;
return server.Substring(server.Length-2);
}
</script>

<%
// what server data are we looking for?
string sData = Request[“serverData”]+””;

switch (sData)
{
case “clientIP”:
Response.Write(GetClientIP());
break;

case “serverName”:
Response.Write(GetServerName());
break;

case “clientIPandServerName”:
Response.Write(“Client IP: ” + GetClientIP() +
“&nbsp;&nbsp;&nbsp;&nbsp; Server: ” + GetServerName());
break;

default:
break;
}
%>

 

Hope this helps you 🙂

How to HA Citrix PVS TFTP services via NetScaler 10.1 using RNAT

I was recently working on a project to migrate a pair of NetScalers from FW 9.3 to a new set of MPX appliances running 10.1: Build 122.17.nc

I was very pleased to know that Citrix deployed a native way to load balance TFTP traffic via NetScaler 10.1, primarely to HA PVS TFTP traffic.  You can read on how to do this on this post by Adam Gamble.

Be cautious! Citrix confirmed this is an issue on 10.1, however it has been fixed in version 10.1 build 123.x or later. Their suggestion is to  upgrade it to the latest 10.1 version(build 128.8) (Did not test with 10.5 yet).  This occurs due to the Packet Process Engine crash when TFTP traffic is triggered through the Netscaler, which will cause your NetScaler to reboot, and in some cases corrupt the NetScaler config file  (ns.conf)

Below is a way to get the darn TFTP process to work via UDP load balancing using an RNAT and utilizing USIP mode

Environment

  • MPX 8200 NetScaler 10.1: Build 122.17.nc

Solution:

In my case I created a new subnet for this.  Reason is because as you may already know, the source IP of traffic is usually your SNIP, however when using an RNAT you will see Source IP coming from the configured RNAT IP and not the SNIP.  So this is up to you.  Where I work now SourceIP is a big deal.

For this example lets use a random 172.16.88.0/24 Subnet

1. Create new NetScaler SNIP for the new Subnet 172.16.88.0/24 under NetScaler> System > Network > IPV4s

Then create your VIP that you will use for your DHCP Option 066 reservation.

SNIP: 172.16.88.99 

VIP: 172.16.88.35

TFTP SNIP

2. Let create a new VLAN 999 (your VLAN TAG) for the 172.16.88.0/24 subnet (Yes you can shrink the subnet size, just using this as an example :))  and in my case TAG the interface 1/1 to save some ports.  You can do this under NetScaler> System > Network > VLAN (Interface 1/1 is set up with full Trunk)

VLAN TFTP

3. To be safe I like to ensure a new DIRECT route is created for the new Subnet to utilize the new SNIP.  This is under  NetScaler> System > Network > Routes > Basic

In this case, it would be Network: 172.16.88.0 Netmask 255.255.255.0 Gateway (Your SNIP): 172.16.88.99

TFTP Route SNIP

 

4. Create RNAT under NetScaler> System > Network > Routes > RNAT

set ns rnat <Host/ Subnet IP> <Host/Subnet Mask> -natip <VIP IP>

In this case Network: 172.16.88.0 Netmask: 255.255.255.0 NatIP (Your VIP that will load balance that TFTP process) 172.16.88.35

TFTP RNAT

 

 

5. Ok the hard part is done.  Lets now create TFTP Servers under NetScaler > Traffic Management > Load Balancing > Servers

TFTP01 = 172.16.88.212

TFTP02 = 172.16.88.213

TFTP Servers

6. Create your Service Groups under NetScaler > Traffic Management > Load Balancing > Service Groups. Under Advanced ensure “User Proxy Port” is set to “No” and “USIP” mode is set.  If this is not set, your TFTP traffic will not function

TFTP Service Group

 

TFTP USIP PROXY NO

7. Create VIP (172.16.88.35) under NetScaler > Traffic Management > Load Balancing > Virtual Servers

Bind Service Group previously created

TFTP Service bind

 

 

 

8. Ok no more NetScaler work, since we are using “Use Source IP” we need to set the default gateway on the TFTP servers (TFTP01/02) to be set to the NetScaler SNIP 172.16.88.99

9. Lastly change your DHCP scope to include the Boot Server Host Name under option 066 to your VIP 172.16.88.35

Your are all set, now to update to 10.5 I guess 😛

TFTP Boot

 

 

 

 

 

Customize AGEE logon page for NetScaler 10.1 via Rewrite policies

While migrating to Access Gateway on the NetScaler 10.1.  I noticed the rewrite policies I implemented on 9.3 did not work.

While this can be done with some HTML customization, etc, and/or creating your own NetScaler theme, I just wanted to change the logon page by NetScaler Rewrite Policies.

Below are the policies that will allow you to do this.

Environment

  • MPX 8200 NetScaler 10.1: Build 122.17.nc
  • Web Interface 5.3 (Can’t deploy StoreFront here due to custom code we use)

Issue:

When two factor authentication is configured on Access Gateway Enterprise Edition, the user is prompted for User name, Password 1, and Password 2

agee_no_active_pol

The issue  seems to be due to change in the ‘ns_showpwd’ function on login.js under /var/netscaler/gui/vpn/ as it has been updated from 9.3

ns_showpwd function

ns_showpwd on Login.js

 

 

Solution:

1. Create the following actions under “Rewrite/Actions” with putty (no need to go under shell mode)

Rewrite Actions:

add rewrite action AD_agee_delete_rewrite_action delete_all “http.RES.BODY(120000).SET_TEXT_MODE(ignorecase)” -pattern “document.write(\’&nbsp;1\’);” -bypassSafetyCheck YES

add rewrite action AD_agee_replace_rewrite_action replace_all “http.RES.BODY(120000).SET_TEXT_MODE(ignorecase)” “\”AD Password\’\”” -pattern “\”Password\”” -bypassSafetyCheck YES -refineSearch q/extend(50,50).REGEX_SELECT(re!e![ ]*\'[ ]*\+[ ]*_\(\”Password\”\)[ ]*!)/

add rewrite action RSA_agee_replace_rewrite_action replace_all “http.RES.BODY(120000).SET_TEXT_MODE(ignorecase)” “\”RSA Code:\’\”” -pattern “\”Password2\”” -bypassSafetyCheck YES -refineSearch q/extend(50,50).REGEX_SELECT(re![ ]*\'[ ]*\+[ ]*_\(\”Password2\”\)[ ]*!)/

Rewrite Policies:

add rewrite policy AD_agee_rewrite_pol “http.req.url.path.endswith(\”vpn/login.js\”)” AD_agee_replace_rewrite_action

add rewrite policy RSA_agee_rewrite_pol “http.req.url.path.endswith(\”vpn/login.js\”)” RSA_agee_replace_rewrite_action

add rewrite policy AD_agee_delete_pol “http.req.url.path.endswith(\”vpn/login.js\”)” AD_agee_delete_rewrite_action

Bind the policies:

bind rewrite global AD_agee_rewrite_pol 100 NEXT -type RES_OVERRIDE

bind rewrite global RSA_agee_rewrite_pol 110 NEXT -type RES_OVERRIDE

bind rewrite global AD_agee_delete_pol 120 NEXT -type RES_OVERRIDE

Result:

Responder Policy AGEE 10.1

Responder Policy AGEE 10.1

XenApp 6.5 session printers not printing

Citrix has collaborated with HP to test select HP printers and their associated HP print drivers in Citrix environments up to and including Citrix XenApp  6.5 with Windows Server 2008 R2 Edition.

These tests were run to determine how HP printers and their associated printer drivers performed using the standard printer and printer-related features tests that Citrix uses to test its XenApp server and client software.

I was recently working in an environment where some local printers which were not showing in the list of “Supported in Citrix environment”, Of course those are the printers we go ahead and buy, and had an entire department calling requesting to get this fixed.

I strongly suggest you head over to http://support.citrix.com/servlet/KbServlet/download/10498-102-649930/HPprinters_CitrixXenApp_1053.pdf and verify ICA ready printers as this could save you a few gray hairs.

Environment:

  • Windows 2008 R2
  • Citrix XenApp 6.5 Hotfix Rollup Pack 2
  • PVS 6.1.16
  • StoreFront 2.1
  • Citrix NetScaler 10.1 build 122.17

Issue:

Users with local printers connect to XenApp Full Desktop and/or seamless applications. The printer maps and successfully shows under the user session(s), however when printing nothing seems to appear in the print job and nothing prints out.

Resolution:

  • Head over to Citrix App Center and click on your User Policies.
  • Under printing, select Drivers, and Edit the Universal driver preference
  • Reconfigured the ‘Universal driver preference’ driver order to PS;XPS;EMF;PCL5c;PCL4

xa65_printing

 

NetScaler 10.1 Unable to load applet

I been working on a NetScaler 10.1 deployment/migration for the last few weeks, and noticed that I was running into issues with the Citrix NetScaler Java applets build in to the GUI.

After thinking it was just me (since I always have Java issues), I noticed other Citrix Admins were experiencing the same.

Environment:
  • Windows 2008 R2
  • Citrix XenApp 6.5 Hotfix Rollup Pack 2
  • PVS 6.1.16
  • StoreFront 2.0
  • Citrix NetScaler 10.1 build 122.17

The Fix:

Open up the Windows Control Panel and start the Java Control panel.

  1. Go to General -> Temporary Internet Files -> Settings and Unselect Keep temporary files on my computer.
  2. Go to General -> Advanced and configure the following options
  3. “Mixed code (sandboxed vs trusted) security verification” = “Disable verification”
  4. “Perform certificate revocation checks on” = “Do not check”

Another solution:

 Open the Java Control Panel

  1. In tab Security click on Edit Site List
  2. Click on Add and type in the file:// or http(s):// URL

On January 14 Oracle released Java Runtime Environment (JRE) 7 update 51. Just like previous updates that raised the security level which could potentially break existing applications.

Also Citrix updated their NetScaler software to meet the requirements of Oracle on December 3rd (downloadrelease notes)

Lastly, the new NetScaler GUI is very slow, however you can still load the old 9.x interface by doing the following

  1. After authenticating to the root page replace “/neo” with “/guia” in the URL after logon.
  2. Login to https://IPADDRESS
  3. After connecting you will be redirected to https://IPADDRESS/menu/neo
  4. Simply update the URL to https://IPADDRESS/menu/guia

And you are back to the old fast interface 🙂

Hopefully Citrix is working on a new HTML5 interface.

XenApp 6.5 User sessions remain active

While working on an SAP 730 implementation, I noticed a customized application was preventing for sessions to log off when the application was terminated.  This was causing for sessions to remain in an active state and for the roaming profiles to not sync.
The issue was caused by an application sub processes that was not closing properly.  By default Citrix XenApp has a hard coded list of processes that are checked for and terminated when the user logs off.
Environment:
  • Windows 2008 R2
  • Citrix XenApp 6.5 Hotfix Rollup Pack 2
  • PVS 6.1.16
  • StoreFront 2.0

Solution:

Modify the following registry key with the additional processes you wish to check.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Citrix\wfshell\TWI

Value Name: LogoffCheckSysModules
Type: REG_SZ
String: myapp.exe,myapp2.exe

processes_screen_reg

XenApp 6.5 Full Desktop – Hide PVS System Tray

While working on a new XenApp 6.5 Deployment with Citrix Provisioning Services, I noticed the Citrix PVS Target Tools icon in the system tray when connecting to a Full Desktop session, this could be confusing or useless information for users.

Environment:

  • Windows 2008 R2
  • Citrix XenApp 6.5 Hotfix Rollup Pack 2
  • PVS 6.1.16
  • StoreFront 2.0

pvs_tray_icon

After researching the web a bit, I came across this HKLM key from Jack Cobben described in his blog Hide Virtual Disk Tray Icon where it simply stated to add the reg hive below.

HKLM\Software\Citrix\ProvisioningServices\Status “ShowIcon” (DWORD) 0

This however will disable to all users, even Admins, and I wanted to be able give administrators the option to see the icon.

Solution:

Apply the HKCU key below to your profile solution  based on Group membership

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\SOFTWARE\Citrix\ProvisioningServices]
“StatusTray”=dword:00000000

Once that is in place the icon will go away.