Modifying IIS 6 to allow subdomains using a wildcard ssl certificate to use port 443

History: By default, IIS websites cannot use the same SSL port (443) for a site using the same IP address. Websites with different IPs can all use port 443. This situation is typical of a standard SSL certificate which is issued to a single host header (ie: secure.website.com). Any other attempt to connect to a site via https through a different host header (ie: http://www.website.com) causes a certificate error (this is by design).

This becomes an issue when trying to install a wildcard SSL certificate. Wildcard certificates provide the ability to secure all subdomains on the root domain using a single certificate. (*.website.com) examples:

root domain – website.com

subdomains -admin.website.com, shop.website.com,etc

However, after you’ve installed a wildcard certificate and try to set up the subdomain to use SSL port 443, you will receive a Port In Use error. You will not be able to start the subdomain websites with the port set to 443. The IIS MMC (inetmgr.mmc) does not provide a method of resolving this so you must use the command line. (Start -> Run -> cmd)

You need to determine the site identifier of the subdomain you wish to modify. To determine <site identifier> Open IIS MMC, click on Web Sites and view the Identifier number next to the subdomain website. In the following script, replace <site identifier> with the number shown in the IIS MMC and change subdomain.website.com to the subdomain you wish to modify. Run the script with the modifications and you should now be able to browse to https://subdomain.website.com with no error.

cscript.exe c:\inetpub\adminscripts\adsutil.vbs set /w3svc/<site identifer>/SecureBindings ":443:subdomain.website.com"

if you have multiple subdomains, you could create a batch file to run the scripts.

A Coldfusion Who’s Online Widget

Last week I set up Ray Camden’s Lighthouse Pro , a open source issue/bug tracking Coldfusion application. We are going to use this internally for project and bug tracking. One bit of functionality I wanted that wasn’t included was a Who’s Online function so everyone could see who was using the site at any given time. This gives me to opportunity to “gently” prod folks who are resistant to using the new program that “it’s the way we now do things”.  Change is hard you know.

This code is not specifically tied to any app and can be dropped in any system using application.cfc.  It would be good for forums, intranets or any other “social web” app where knowing who’s online may be a benefit.

The first bit is to define the struct we are going to use to store the information and to populate it with the newly logged in user.

On thing to note here is that I’m using a combination of CFID and Username to give me my user_cfid which is the key we are looking for. The reason for this is that we want to be able to allow multiple users with the same name to use the application. If we just keyed on username, the system couldn’t tell there were more than one and we could see name overlap problems. Because CFID is set with the session, it’s “reasonably” unique, especially when combined with username. For greater overlap prevention or for systems which only use jsessionid’s, you could use createuuid() intead of CFID.

Application.cfc onRequest in your successful login section
—————————————-

<!— begin Who’s Online section —>
<cfparam name=”session.whosOnFirst” default=””>
<!— Test for existence of UserInfo and create if necessary  —>
<cflock timeout=”15″ scope=”APPLICATION” type=”EXCLUSIVE”>
<cfif NOT isDefined(“Application.UsersInfo”)>
<cfset Application.UsersInfo = StructNew()>
</cfif>
</cflock>
<cfif isDefined(‘form.userName’)>
<!— create new user info for the struct —>
<cflock name=”#CreateUUID()#” timeout=”15″ type=”EXCLUSIVE”>
<cfset user_cfid = Evaluate(CFID) & “,” & form.userName>
<cfset user_time = Now()>
</cflock>
<!— set a session id so we can use it to verify that this session is still active in application.cfm —>
<cfset session.whosOnFirst = user_cfid>
<cflock scope=”APPLICATION” type=”EXCLUSIVE” timeout=”15″>
<!— If the user does not exist in the struct, insert it —>
<cfif NOT StructKeyExists(Application.UsersInfo, user_cfid)>
<cfset temp = StructInsert(Application.UsersInfo, user_cfid, user_time)>
</cfif>
</cflock>
</cfif>
<!— end Who’s Online section —>
the second bit does the updating and checking of user activity and either updates or deletes the user from the tracking struct

Application.cfc onRequest
—————————————-
<!— Begin Who’s Online section —>
<!— determines timeout to heck if user still is active.
set to 0 will check on each page load and will cause list to change a lot as people “timeout”
while viewing or working on pages
set to 10 minutes will give a more general idea of activity.
remember that activity timeout and session timeout may be different.
—>

<!— handle application timeout —>
<cflock timeout=”15″ scope=”APPLICATION” type=”EXCLUSIVE”>
<cfif NOT isDefined(“Application.UsersInfo”)>
<cfset Application.UsersInfo = StructNew()>
</cfif>
</cflock>

<cfset ActivityTimeout = 0>
<!— if we still have a session id but have been cleared from the struct reset the struct
this would be due to having an activity online timeout which is shorter than
your session timeout. —>

<!– check if session exists –>
<cfif structKeyExists(session,”whosOnFirst”)>
<!– check if key in who’s online exists –>
<cfif NOT StructKeyExists(Application.UsersInfo, session.whosOnFirst)>
<cfset temp = StructInsert(Application.UsersInfo, session.whosOnFirst, now())>
</cfif>
</cfif>

<cfloop collection=”#Application.UsersInfo#” item=”uName”>
<!— if the struct matches the session id then it’s us so update our activity time —>
<cfif structKeyExists(session,”whosOnFirst”)>
<cfif uName eq session.whosOnFirst>
<cfset user_cfid = uName>
<cfset user_time = Now()>
<cfset temp = StructUpdate(Application.UsersInfo, user_cfid, user_time)>
</cfif>
</cfif>
<!— look for values in the struct which are larger than ActivityTimeout
and delete them as their timeout period will have expired.   —>
<cfif Evaluate(DateDiff(“n”, StructFind(Application.UsersInfo, uName), Now())) GT ActivityTimeout>
<cfset StructDelete(Application.UsersInfo, uName)>
</cfif>
</cfloop>
<!— end Who’s Online section —>

This last bit is the display section which you can place on any page you want the widget to appear.

whosOnFirst.cfm
———————————————-
<div style=”padding:5px;”>
<cflock scope=”APPLICATION” type=”EXCLUSIVE” timeout=”10″>
<cfoutput>
Users Online : #StructCount(Application.UsersInfo)#<br>
<cfloop collection=”#Application.UsersInfo#” item=”uName”>
<cfif Uname eq session.whosOnFirst>
<div style=”font-weight:bold;border-top:1px dashed;border-bottom:1px dashed;”>#listlast(UCASE(Uname))#</div><!— this is me —>
<cfelse>
<div>#listlast(UCASE(Uname))# <br>
<span style=”font-size:.7em;”>
Last Activity : #timeformat(structfind(Application.UsersInfo,uname), “hh:mm:ss”)#
</span></div>
</cfif>
</cfloop>
</cfoutput>
</cflock>
</div>

For apps that allow both registered users and guests, you could add an additional logic section to onRequestStart which determines if a user is browser as a guest and then set user_cfid as

<cfset user_cfid = Evaluate(CFID) & “,” & “Guest”>

Since CFID is “unique-ish” we can combine it with multiple Guests and not have overlap. For larger volume sites which could have many guests, I’d recommend using the createUUID() as recommend above.

Word of warning: I’m not sure what performance implications there would be on a heavily visited forum site.  You would also want to either limit the number of users displayed by the collection cfloop, or add some css to allow for scrolling of the div so you didn’t have a list that had 300-400 visible users.

Have Fun.