en-US
search-icon

SonicOS 6.2 Admin Guide

Appendices
* 
NOTE: Not supported on the SuperMassive 9800.

Configuring Open Authentication, Social Login, and LHM

* 
NOTE: Configuring Open Authorization, social Login, and LHM is not supported on the SuperMassive 9800.

About OAuth and Social Login

Social Login is a form of single sign-on authentication that utilizes existing user credentials from social networking services such as Facebook, Twitter, or Google+ to then sign in to a third-party website instead of creating a new login account specifically for that website. The Open Authentication (OAuth) Social Login feature can be used with guest service on wireless zones, LAN zones, or DMZ zones using pass-through authentication; see External Authentication Server Login Topology. Pass-though authentication is a method of performing authentication to a domain controller that resides within a trusted domain. Wireless guest services are widely used in public WiFi hot spots and corporate WiFi services set up for guests.

External Authentication Server Login Topology

Topics:  

What are OAuth and Social Login?

OAuth is an open standard for authorization. OAuth provides client applications “secure delegated access” to server resources on behalf of a resource owner, and specifies a process for owners to authorize third-party access to their server resources without sharing their credentials.

Social Login, also known as social sign-in, is a form of single sign-on (SSO) using existing login information from a social networking service such as Facebook, Twitter, or Google+ to sign into a third-party website instead of creating a new login account specifically for that website.

Benefits of OAuth and Social Login

Topics:  

OAuth

OAuth is a popular mechanism that assists users in sharing data between applications. You can take advantage of OAuth by using it as a login provider for your web application.

Other advantages
Limiting customer profiles on the net
Fewer passwords to track
Not required to submit a password where trust might be an issue
You can still prevent access from the OAuth provider
Lower risk of ID theft. Authentication is assumed by the provider
Lower risk of bug failure with authentication using previously proven APIs
Less storage requirement on your data servers
Disadvantages
You cannot tailor user profiles for your own applications
User confusion in creating accounts with OAuth providers when they do not have existing accounts

Social Login

Social login is designed to simplify the login process and to realize a higher conversion rate for registrations.

Other Advantages
Quick registration
Remember fewer logins
Target-rich content
Use of multiple identities
Collection of visitor data
Detailed or personalized user experience
Familiar login environments
Fewer failed logins
Ease of use for mobile
Disadvantages
Low trust level
Non-Social users excluded
Data accuracy can be falsified
Blocked content from Social networks
Security issues

How Do OAuth and Social Login Work?

The Open Authentication (OAuth) and Social Login features can both be used with internal wireless services and SonicPoints as a wireless zone guest service. Guests can log in to the Internet using your company’s corporate WiFi. Wireless guest services are widely used in public WiFi hot spots and corporate WiFi services set up for guests.

Both OAuth and Social Login use wireless guest services that include Internet access and can be configured to use either or both of these methods of connection:

No Redirect

No Redirect provides open Internet access to guests with no required encryption, so guests are allowed to connect to the provided WiFi freely.

No redirect can also provide WPA/WEP passphrase or password access where guests would need a passcode to use the available WiFi. The passcode could be provided through other means, such as on a receipt.

Redirect to a Landing Page

A landing web page provides the most widely used hot spot access. While the layer 2 WiFi access is open, guests are directed to a landing web page when accessing the first layer; see Oauth flow. Some other redirect access options include:

No authentication on the landing page
Guests can create a new login account and then sign in with it
Guests can sign up using a code sent to them by SMS to a mobile phone, email, or other method
Scanning a QR code with a mobile app
Using a social login

Oauth flow

Supported Platforms

Open Authentication and Social Login is supported on SonicWall firewalls:

Running SonicOS 6.2.7 and higher
Under GMS Management running GMS 8.3

Requirements for Development and Production

A Facebook account
Enable Facebook For Developers
External server
Public accessible
Has a domain name
PHP support
SSL Certificate
Sonicwall firewall
Can be reached by the external server (by IP or FQDN)
Wireless (internal or SonicPoint)

About Lightweight Hotspot Messaging (LHM)

Lightweight Hotspot Messaging (LHM) leverages the SonicWall Guest Service model, wherein users can be classified and authorized for differentiated network access through a SonicWall security appliance. For example, the SonicWall can be configured such that any user connecting through an interface belonging to a guest-services-enabled WLAN (wireless LAN) Zone only has access to the Internet (Untrusted network), but does not have access to the LAN (Trusted network). This allows a single firewall to offer simultaneous access to trusted and guest users.

LHM extends the Guest Services model by breaking apart the authentication and authorization processes, thereby allowing the authentication to occur external to the SonicWall. This allows for extensive customization of the authentication interface, and also allows for any kind of imaginable authentication scheme to be used.

A side by side view of the original Guest Services authorization flow and the LHM authorization flow is shown in Comparison of authorization flows:

 

Comparison of authorization flows

Original Guest Services Authorization Flow

LHM Authorization Flow

LHM defines the method and syntax for communications between a SonicWall wireless access device (such as a SOHO W firewall, a TZ Wireless series firewall, or a SonicPoint with a governing SonicWall security appliance) and an Authentication Back-End (ABE) for authenticating Hotspot users and providing them parametrically bound network access. LHM configuration example depicts a generic configuration.

LHM configuration example

LHM allows network operators to provide centralized management of multiple Hotspot locations by providing an interface between SonicWall’s Wireless Guest Services and any existing ABE. LHM is an adaptation of the generalized WISPr and GIS specifications.

LHM was designed to satisfy the requirements of a particularly common operational environment rather than a broad set of environments. Specifically, LHM allows for Hotspot user-management and authentication to occur entirely on the network operator’s ABE, supporting any method of account creation and management, and any extent of site customization and branding. This approach enables integration into any existing environment without dependencies upon particular billing, accounting or database systems, and also provides the network operator with unrestricted control of the site’s design, from look-and-feel to redirection.

Configuring Facebook for Social Login

Topics:  

Facebook Settings

To login to Facebook for Developers:
1
Open a Web browser
2
Log in to your Facebook for Developers account at https://developers.facebook.com/.

3
Complete the login process or sign up for a new developer’s account.
4
Click Settings in the left column.

See Example of settings for Facebook for developers to fill the form, but adjust the Facebook Settings to work with your LHM server.

Example of settings for Facebook for developers

Client OAuth Settings

You should adjust your Client OAuth settings at Facebook for Developers, https://developers.facebook.com/ (Products > Facebook Login > Settings), similar to those shown in Example of OAuth Facebook settings.

Example of OAuth Facebook settings

Guest Status (demo)

When a wireless client is allowed access to the SonicWall WiFi, the owner’s account name and information is sent to SonicOS. You can collect and store this information in your own databases.

Configuring Open Authentication and Social Login

Topics:  

About Configuring Guest Services

Although SonicOS provides its own guest account management, you can use your own IT infrastructure to better accommodate your business requirements. This configuration can be done by setting up external guest authentication or a social login. The Guest Services tab (see Current Guest Services settings on Edit Zone dialog) is provided in the Add/Edit Zone dialogs of the SonicOS wireless zone, LAN zone, or DMZ zone (Network > Zones).

Current Guest Services settings on Edit Zone dialog

About Configuring Social Login

This feature simplifies cumbersome logins for end users as well as provides reliable demographic information to web developers.

To prepare for configuring Social Login:
1
Create a wireless zone, LAN zone, or DMZ zone as described Network > Zones and set up or edit a network zone with security capabilities. For more information on adding the network zone, see Adding a New Zone.
2
In SonicOS, the external server can also be created or selected as a Lightweight Hotspot Messaging (LHM) server IP or FQDN address object.

Configuring Social Login in SonicOS

Setting up your firewall properly requires some configuration. The firewall blocks most Internet applications, but a few should be allowed for this feature to function correctly.

* 
IMPORTANT: An LHM server should be in service before configuring Social Login.
To configure your firewall for Social Login:
1
Go to Network > Zones to set up or edit a network zone with wireless security capabilities. For more information on adding the network zone, Adding a New Zone.
* 
NOTE: The external server can also be created or selected as an Lightweight Hotspot Messaging (LHM) server IP or FQDN address object.
2
Click the WLAN Edit icon to access the WLAN network zone. The Edit Zone dialog displays.

3
Click the Guest Services tab.

4
Select the Enable Guest Services checkbox. The other options activate.
5
Select Enable External Guest Authentication checkbox. The Configure button activates.
6
Click Configure. The External Guest Authentication dialog displays.

7
For the External Web Server Settings, you should have an LHM server already in service. Select an Address Object associated with that server from the Host Server Host drop-down menu.
8
Configure the rest of the page as described in Configuring a Zone for Guest Access.
9
In the Social Network Login section, select the Enable Social Network Login checkbox. The social networks activate.
10
Select one or more social network to enable for open authentication:
Facebook
Google
Twitter

SonicOS automatically creates the necessary pass-through authentication network domains for allowing authentication process traffic between the authentication server and the user. The automatically added address object groups are named Default Social Login Pass Group. This address object group is appended to the currently configured pass networks, if any, or it is added into a new group called Social Login Pass Group.

11
Click the Auth Pages tab.

12
Enter a Login Page location, such as login.php, but based on your developer’s input pages. These scripts are hosted by your own LHM server, so you should be able to make sure they function correctly.
13
Complete the remaining fields.
14
Click OK.

Verifying the Social Login Configuration

You can verify the correct configuration of Open Authentication and Social Login by viewing the Network > Address Objects page.

To verify settings:
1
Navigate to Network > Address Objects.
2
Select the Address Groups tab.

The page should show:

Domains have been added automatically.
Facebook, Google, and/or Twitter login traffic can pass through successfully.

Using Social Login, LHM, and ABE

Topics:  

About ABE

The ABE consists of a Web Server (WS) to host content for user interaction and an (optional) Authentication Server (AS) to provide directory services authentication. The AS can be any kind of user authentication mechanism, including, but not limited to RADIUS, LDAP, or AD; the only requirement is that the WS can communicate with the AS for authentication purposes. The WS and AS can be administered on a single server or on separate servers.

LHM also provides the ability for the AS to use the SonicWall security appliance’s internal user database for user authentication. For details on messaging, see Message Format, Local Authentication Request, and Local Authentication Reply.

The ABE needs to communicate with the Hotspot SonicWall to exchange result codes and session information. All communications are HTTPS and can occur either directly (such as to the LAN, WAN, X0 interface of the SonicWall security appliance) or over a VPN tunnel to one of the SonicWall security appliance’s management interface addresses. The LHM management interface is automatically derived through a route (path) lookup, and only the management interface(s) accepts LHM management messaging through automatically added Access Rules.

LHM communications occur on a specific LHM management port that must be defined on the SonicWall security appliance, and the LHM management port must be different from the standard HTTPS Management port.

To allow the ABE to communicate with the SonicWall, and to redirect clients to the appropriate interface on the SonicWall, two parameters are constructed by the SonicWall and passed (among others) through the client redirect to the ABE. The following communication parameters must be used for all communications between the ABE and the SonicWall.

mgmtBaseUrl - The IP address and the port that the ABE uses to communicate with the SonicWall. It is composed of the HTTPS protocol designator, the IP of the selected LHM management interface, and the LHM port (such as https://10.1.2.3:4043).
clientRedirectUrl - The IP address (and optionally the port) on the SonicWall to which clients are redirected during various phases of the session, namely the LAN management IP on the TZW, or the WLAN IP on a SonicOS device (such as http://172.16.31.1).

The parameter values are passed to the ABE by the SonicWall during Session Creation (see Session Creation) and during the Session State Sync (see Message Format), and should be used by the ABE as the base in the construction of all relevant URLs. The following are the pages on the SonicWall that is referenced by the ABE:

wirelessServicesUnavailable.html – ABE is unavailable message. This redirect is typically sent by the SonicWall, but can also be referenced by the ABE. Text is configurable (see the Web Content tab in SonicWall LHM Configuration Pages).
externalGuestRedirect.html – Initial redirect message provided by the SonicWall on session creation. Text is configurable (see the Web Content tab in SonicWall LHM Configuration Pages).
externalGuestLogin.cgi – The page to which the ABE posts session creation data.
externalGuestLogoff.cgi – The page to which the ABE posts session termination data.
localGuestLogin.cgi – The page to which the ABE posts for authenticating user credentials against the SonicWall’s internal user database.
createGuestAccount.cgi – The page to which the ABE posts to create a guest account in the SonicWall’s internal user database.
externalGuestUpdateSession.cgi – The page to which the ABE posts to update the sessionLifetime and idleTimeout parameters of an existing session (see Session Update).

For communications from the SonicWall to the ABE, URLs (including host, port, and page/resource) hosted on the ABE is fully configurable at the SonicWall (see the General and Auth Pages tabs in SonicWall LHM Configuration Pages). The host can be specified using either an IP address or fully qualified domain name (FQDN). When using FQDN, the name is resolved upon first use and is stored by the SonicWall as an IP address.

SonicWall LHM Configuration Pages

Topics:  
General

Auth Pages

Web Content

Advanced

Session Life Cycle

The following sections describe the phases of a session life cycle, as well as the Session Popup Window and Web Server (WS) Status Check components:

Session Creation

Session creation occurs when a wireless client attempts access, and the SonicWall has no active session information for that client based upon MAC address.

Session Creation Flow

1
Wireless client associates with SonicWall. Obtains IP Address from internal DHCP server, or uses static addressing with Dynamic Address Translation (DAT) feature.
2
Client requests web-resource, http://www.website.com.
SonicWall determines that this is a new session.
3
SonicWall redirects client to internally hosted externalGuestRedirect.html page. The externalGuestRedirect.html page provides administrator-configurable text explaining that the session is being redirected for authentication.
4
During this redirect, the SonicWall checks the availability of the ABE through a JavaScript redirect attempt to the configured target redirect page.
If the redirect to the WS fails to occur within a specified period (the value is configurable on the SonicWall, between 1 and 30 seconds) the SonicWall redirects the session to the internal wirelessServicesUnavailable.html page.
5
In addition to the JavaScript availability check, an optional full Web Server Status Check is available from the SonicWall (see Web Server Status Check). This option can be configured to run at a configurable interval between 1 and 60 minutes. If an error response code of 1, 2, or 255occurs, the SonicWall logs the response and redirects the browser to the internal wirelessServicesUnavailable.html page. This page provides administrator-configurable text explaining recourse.
6
If available, the SonicWall redirects client to authentication portal hosted on AS at: https://172.20.0.1/auth.html?ssid=mySSID&sessionId=11aa::00ff&ip=172.16.31.10&mac=0002ABCDEF&ufi=0006010203&mgmtBaseUrl=https://10.1.2.3:4043&clientRedirectUrl=http://172.16.31.1&req=http%3A//www.website.com
ssid – The ESSID (wireless network name) of the wireless network to which the redirected client was associated.
sessionId — A 32 byte hex representation of a 16 byte MD5 hash value generated by the SonicWall, which is used by the SonicWall and the WS for indexing clients (such as “11aa3e2f5da3e12ef978ba120d2300ff”).
ip — The client IP address.
mac — The client MAC address.
req — The originally requested web-site is passed as an argument to the authentication server)
ufi — The SonicWall Unique Firewall Identifier. To be used for site identification, if desired.
mgmtBaseUrl — The protocol, IP address, and port on the SonicWall with which the IP subsequently communicates.
clientRedirectUrl — The protocol, IP address (and optionally port) on the SonicWall that the ABE uses for client redirection.
req – The client’s originally requested URL, if any, URL encoded.
7
Client provides authentication information (such as username, password, token, and so on).
* 
NOTE: The WS must be able to reach the Client, for example, by VPN, NAT or route.
8
WS validates user against AS.
AS provides session specific information, namely, Session Timeout and Idle Timeout values.
Session specific values can optionally be applied globally by the WS rather than obtained from the AS; some value simply needs to be passed to the SonicWall.
Timeout values are presented in seconds and can range from 1 to 863,913,600 (equal to 9999 days).
9
If authentication fails, the WS should redirect the client to a page explaining the failure. A link should be provided back to http(s)://172.16.31.1/externalGuestRedirect.html to restart the process.
10
If successful, the WS connects to the SonicWall either through HTTPS or through VPN and POSTs https://10.1.2.3:4043/externalGuestLogin.cgi?sessId=11aa::00ff&userName=Name&sessionLifetime=1800&idleTimeout=600.
The SonicWall attempts to create the session and sends a result to the WS in the same connection. Results are described in Message Format.
11
If a failure response is received (such as code 51, 100, or 255), WS should redirect client to a page explaining the failure. A link can be provided back to: http(s)://172.16.31.1/externalGuestRedirect.html to start process over.
12
If successful (code 50), WS can redirect user to the originally requested site (req) or to any site (such as a portal or start page). WS should also instruct on how to logoff from session (such as bookmark a page, popup window, URL).

Session Popup Window

It is recommended that sessions be managed through a Session Popup window. This should be a browser window instantiated at the time of Session Creation providing session time information (such as lifetime, idle timeout value, timer countdowns) and a Logout button. Sample code is provided.

Clicking Logout ends the session and triggers a User Logout event.
Attempting to close the window should provide a warning message that closing the window ends the session.
Closing the window ends the session and triggers a User Logout event.

Idle Timeout

Idle timeout occurs when the idle timeout (specified in Session Creation, Step 8) is exceeded.

Idle Timeout Flow

1
Idle timer (as set during Session Creation) expires.
2
Because the client’s browser might not be open at this time, we do not initiate this process with a redirect. Instead, SonicWall sends a POST to the WS at: https://172.20.0.1/autoLogout.asp?ssid=mySSID&sessId=11aa::00ff&eventId=4 (see Message Format for Logoff event IDs).
The resource to which the POST is sent is configurable on the SonicWall from: Network > Zones > Edit Zone – WLAN > Guest Services > External Guest Authentication > Advanced > Auto-Session Logout > Logout CGI.
The WS hosted page must expect and interpret the sessId and eventId values.
3
The WS sends an XML result to the WS in the same connection. Results are described in Logoff Reply.
4
If the client returns from the idle state and attempts to reach a web resource, the SonicWall redirects the user to the internal externalGuestRedirect.html page, starting the session creation process over (see Session Creation).
* 
NOTE: To conserve resources, it is recommended that the idle timeout be set to a maximum of 10 minutes.

Session Timeout

The event occurs when the Session lifetime expires. The exchange is the same as the Idle Timeout above, except the Session Timeout eventId value is 3 instead of 4 for an Idle Timeout.

User Logout

Event occurs when the user actively ends the session by closing their Session Popup window or by using the Logout button provided on the Session Popup window. The Session Popup window is the preferred method for user logout; however, the same result can be achieved without this method by allowing the session’s lifetime to expire. The latter removes the dependency on the Session Popup window, but manages resources less efficiently.

User Logout Flow

1
Client logs out using the Logout button, or closes the session popup window.
2
The WS sends a POST to: https://10.1.2.3:4043/externalGuestLogoff.cgi?sessId=11aa::00ff&eventId=1 (for Logoff event IDs, see Message Format).
sessId — The value generated during Session Creation (see Session Creation) by the SonicWall, which is used by the SonicWall and the WS for indexing clients.
eventId — Describes the logoff request event.
3
SonicWall responds with a result to the WS in the same connection. Results are described in Logoff Reply.
4
If the client attempts to reach a web resource, the SonicWall redirects the user to the internal http://172.16.31.1/externalGuestRedirect.html page, starting the Session Creation process over (see Session Creation).

Administrator Logout (Optional)

The event occurs when the ABE administrator logs out from a Guest session from the management interface. It is not possible at this time to terminate ABE-established Guest Sessions from the SonicWall interface itself. ABE-established Guest Sessions are represented as such (or distinctly from internal WGS Guest Sessions) on the SonicWall management UI and are not editable.

Administrator Logout Flow

1
The ABE administrator terminates the Guest session from the management UI.
2
The WS sends a POST to the SonicWall: https://10.1.2.3:4043/externalGuestLogoff.cgi?sessId=11aa::00ff&eventId=2. (for Logoff event IDs, see Message Format).
sessId — The value generated during Session Creation by the SonicWall, which is used by the SonicWall and the WS for indexing clients.
eventId — Describes the logoff request event.
3
The SonicWall sends a result to the WS in the same connection. Results are described in Logoff Reply.
4
If the client returns from the idle state and attempts to reach a web resource, the SonicWall redirects the user to the internal http://172.16.31.1/externalGuestRedirect.html page, starting the Session Creation process over (see Session Creation).

Web Server Status Check

To provide more granular ABE status than simple Web Server (WS) availability (as is provided by the mandatory Step 4 of Session Creation Flow, the JavaScript redirect), the SonicWall can optionally send a secure HTTP GET operation to the WS in order to determine server operational status. The target URL is configurable, as is the interval of the query (between 1 and 60 minutes). The WS responds back in an XML format listing the server’s current state. For details. see Message Format.

If an error response code (1, 2, or 255) is received (indicating that the WS itself is available, but that some other ABE error condition has occurred), the SonicWall logs the response and redirects all subsequent authentication requests to an internal wirelessServicesUnavailable.html page. This page provides administrator-configurable text explaining recourse.

The SonicWall continues to attempt to query the ABE at the configured interval and resumes redirection to the WS (rather than to the wirelessServicesUnavailable.html page) when a response code of 0 (Server Up) is received.

Session State Sync

At a configurable interval (between 1 and 60 minutes), the SonicWall optionally sends a secure HTTP POST operation to the WS containing an XML list of all currently active guest sessions. The CGI post provides the sessionList as an XML list of all active guest sessions. For details, see Message Format.

The feature itself is enabled through a checkbox on the SonicWall, but is disabled by default. The target URL is configurable.

Message Authentication

This feature ensures that the CGI data exchanged between both the SonicWall and ABE originated from the SonicWall/ABE device, and that it has not been tampered with. If enabled, an additional CGI parameter, named hmac, is added to all CGI data exchanged. The following is an example of what the redirect URL now looks like with message authentication enabled:

https://10.1.2.3/login.asp?sessionId=faad7f12ac26d5c2fe3236de2c149a22&ip=172.16.31.2&mac=00:90:4b:6a:37:32&ufi=0006B1020148&mgmtBaseUrl=https://10.0.61.222:4043/&clientRedirectUrl=http://192.168.168.168:80/&req=http%3A//www.google.com/&hmac=cd2399aeff26d5c2fe3236d211549acc
* 
NOTE: The SonicWall URL encodes the following characters within the value of the req (and only the req) variable:
% = %25
: = %3A
= %20 (space)
? = %3F
+ = %2B
& = %26
= = %3D

In the preceding example, the HMAC signature was generated using the following data:

HMAC(
faad7f12ac26d5c2fe3236de2c149a22 +
172.16.31.2 +
00:90:4b:6a:37:32 +
0006B1020148 +
https://10.0.61.222:4043/ +
https://10.0.61.222:4043/ +
http%3A//www.google.com/
)

If message authentication is enabled, then the SonicWall device expects an HMAC signature as part of the CGI post data originating from the ABE. If the SonicWall detects that the HMAC is missing or incorrect, then an error code of 251 is returned, and the requested operation (such as guest login, account creation) is aborted.

Session Update

Session update allows for the ABE to update the Session Lifetime and Idle Timeout values of existing session on the SonicWall. This allows, for example, for additional time to be purchased by guest users and added to an existing session.

The Session Update can be sent from the ABE to the SonicWall at any time during a session’s lifetime.
The userName and sessionLifetime values must be specified in the message
The sessID value may be specified. If included, the update pertains to the specified session. If omitted, the update pertains to all sessions matching the specified userName.

For details, see Message Format.

Message Format

Topics:  
* 
NOTE: The XML Schema location is subject to change.

The SonicWall IP address and port is defined in the mgmtBaseUrl variable.

External Authentication Request

The WS sends a secure HTTP POST operation to: https://sonicwall.ip.add.ress:port/externalGuestLogin.cgi. The post parameters include these arguments:

sessId: Session ID
userName: The full user ID
sessionLifetime: The session lifetime of the user (in seconds)
idleTimeout: The maximum idle timeout (in seconds)

External Authentication Reply

The SonicWall returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<AuthenticationReply>
<ResponseCode>{response code}</ResponseCode>
<ReplyMessage>{reply message}</ReplyMessage>
</AuthenticationReply>
</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in External authentication response codes.

External authentication response codes

Response Code

Response Meaning

50

Login succeeded

51

Session limit exceeded

100

Login failed -- access reject

251

Msg. Auth failed -- Invalid HMAC

253

Invalid session ID

254

Invalid or missing CGI parameter

255

Internal error

Local Authentication Request

The WS sends a secure HTTP POST operation to: https://sonicwall.ip.add.ress:port/localGuestLogin.cgi. The post parameters includes these arguments:

sessId: Session ID
userName: The full user ID
passwd: The guest’s clear-text password

Local Authentication Reply

The SonicWall returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<AuthenticationReply>
<ResponseCode>{response code}</ResponseCode>
<ReplyMessage>{reply message}</ReplyMessage>
</AuthenticationReply>
</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in Local authentication response codes.

 

Local authentication response codes

Response Code

Response Meaning

50

Login succeeded

51

Session limit exceeded

52

Invalid username/password

100

Login failed -- access reject

251

Msg. Auth failed -- Invalid HMAC

253

Invalid session ID

254

Invalid or missing CGI parameter

255

Internal error

Logoff Request

The WS sends a secure HTTP POST operation to: https://sonicwall.ip.add.ress:port/externalGuestLogoff.cgi. The post parameters includes the following arguments:

sessId: GW Session ID
eventId: Logoff event ID. Must be one of the following:
 

Logoff Event ID

Event Meaning

1

Guest logged out manually

2

Admin logged off the specified guest

3

Guest session expired

4

Guest idle timeout expired

Logoff Reply

The SonicWall returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">

<SonicWallAccessGatewayParam

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/

SonicWallAccessGatewayParam.xsd">

<LogoffReply>

<ResponseCode>{response code}</ResponseCode>

<ReplyMessage>{reply message}</ReplyMessage>

</LogoffReply>

</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in Logoff response codes:

 

Logoff response codes

Response Code

Response Meaning

150

Logoff succeeded

251

Msg. Auth failed -- Invalid HMAC

253

Invalid session ID

254

Invalid or missing CGI parameter

255

Internal error

Web Server Status Check

The WS returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<ServerStatus >{status code}</ ServerStatus >
</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in Web server status check response codes.

 

Web server status check response codes

Response Code

Response Meaning

0

Server Up

1

DB down

2

Configuration error

255

Internal error

Session State Sync

Periodically, the GW sends a secure HTTP POST operation to the AS containing an XML list of all currently active guest sessions. Both the target URL and time period are configurable by the GW administrator.

The CGI post parameters include this argument:

sessionList: XML list of all active GW guest sessions.

The session list returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<SessionSync>
<SessionCount>{Session Count}</SessionCount>
<SessionList>
<Session>
<Ssid>{ESSID}</Ssid>8
<ID>{Session ID}</ID>
<UserName>{User Name}</UserName>
<IP>{IP Address}</IP>
<MAC>{MAC Address}</MAC>
<Idle>
{Time Idle (expressed in seconds)}
</Idle>
<SessionRemaining>
{Session Remaining (expressed in seconds)}
<SessionRemaining>
<BaseMgmtUrl>
{https://ip.add.re.ss:port}
</BaseMgmtUrl>
<RxBytes>
{total bytes received}
</RxBytes>
<TxBytes>
{total bytes transmitted}
</TxBytes>
</Session>
</SessionList>
</SessionSync>
</SonicWallAccessGatewayParam>

Session State Sync Reply

The WS returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<SessionSync>
<ResponseCode>{response code}</ResponseCode>
</SessionSync>
</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in Session state sync reply response codes.

 

Session state sync reply response codes

Response Code

Response Meaning

200

Sync successful

201

Sync failed

255

Internal error

Local Account Creation Request

The WS sends a secure HTTP POST operation to: https://sonicwall.ip.add.ress:port/createGuestAccount.cgi. The post parameters include these arguments:

userName: The full user ID (maximum length: 32)
passwd: The guest’s clear-text password (maximum length: 64)
comment: Optional (maximum length: 16). Default=NULL
enforceUniqueLogin: Optional: 1=true, 0=false. Default=1
activateNow: Optional: 1=true, 0=false. Default=0
autoPrune: Optional: 1=true, 0=false. Default=1
accountLifetime: The account lifetime of the user (expressed in seconds)
sessionLifetime: The session lifetime of the user (expressed in seconds)
idleTimeout: The max idle timeout (expressed in seconds)

Local Account Creation Reply

The SonicWall returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<AccountCreationReply>
<ResponseCode>{response code}</ResponseCode>
<ReplyMessage>{reply message}</ReplyMessage>
</AccountCreationReply>
</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in Local account creation reply response codes.

 

Local account creation reply response codes

Response Code

Response Meaning

10

Account creation succeeded

11

Max account limit

12

Account Exists

251

Msg. Auth failed -- Invalid HMAC

254

Invalid or missing CGI parameter

255

Internal error

Update Session Request

The POST from the ABE may be made to the SonicWall at externalGuestUpdateSession.cgi in this format:

https://10.1.2.3:4043/externalGuestUpdateSession.cgi?sessId=11aa::00ff&userName=guest&sessionLifetime=600&idleTimeout=180

The post parameters include these arguments:

sessID: The value may be specified. If the value is not specified, then all guest sessions matching the specified username are updated.
userName: The value must be specified as it defines the name of the user session (or potentially sessions if no session ID is provided) that is updated.
sessionLifetime: The value must be specified as it defines the number of seconds to assign to the session. It can be any number from 1 to 863,913,600.
idleTimeout: The value may be specified. It:
Defines the number of seconds to assign to the session.
Can be any number from 1 to 863,913,600.
Must be less than or equal to the sessionLifetime.

If an idleTimeout is not provided, the session’s existing idleTimeout value is maintained.

Update Session Reply

The SonicWall returns an XML response in this format:

<?xml version="1.0" encoding="UTF-8">
<SonicWallAccessGatewayParam
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.sonicwall.com/
SonicWallAccessGatewayParam.xsd">
<UpdateSessionReply>
<ResponseCode>{response code}</ResponseCode>
<ReplyMessage>{reply message}</ReplyMessage>
</ UpdateSessionReply >
</SonicWallAccessGatewayParam>

The {response code} includes one of the values listed in Update session reply response codes.

 

Update session reply response codes

Response Code

Response Meaning

210

Session Update succeeded

211

Session Update failed

251

Msg. Auth failed -- Invalid HMAC

254

Invalid or missing CGI parameter

255

Internal error

Frequently Asked Questions (FAQs)

Topics:  

Do the LHM server scripts have to be written in ASP?

No. The LHM server scripts can be written using any platform capable of handling web requests and XML, the two core components of LHM. This includes Perl, PHP, ASP, ASP.NET, and J2EE.

Why were these new scripts written in ASP.NET?

ASP.NET was chosen for the new scripts because of its prevalence, and because it does lots of things well, not the least of which being the ease with which it handles XML.

How can I use LHM to provide Guest Services access to wired users?

Although Guest Services (previously known as WGS, or Wireless Guest Services) were designed for wireless (hotspot) users, Guest Services can also be employed for wired users on SonicOS 6.2.7 and later by placing the wired interface (or interfaces, as the case may be on the PRO 1260 with PortShield) into a Wireless Zone with SonicPoint Enforcement disabled. All Guest Services options then apply to wired users, including among others, LHM, Dynamic Address Translations, Allow/Deny Networks.

What is the difference between “authentication” and “authorization”?

Authentication describes the process of a user providing a response to some kind of challenge. The challenge can be just about anything, although traditionally it is a username:password. LHM breaks this dependence of the traditional model by abstracting the authentication. The role of authenticator is fulfilled by the LHM server, and the methods of authentication are bound only by imagination. Consider the following methods of authentication:

Provide a valid username and password
Guess the number the computer generated
Complete this questionnaire
Pass a quiz with a score of at least 80%
Click the I Accept button

After authentication, the client can then be authorized to do something.

Authorization is the process of granting access to something. For authorization to be useful, the authorizer must have a means of stopping the client from getting to guarded resources. In the case of LHM, the SonicWall is the client's gateway (either wired or wireless), so it can very effectively act as authorizer. After the SonicWall receives the OK from the authenticator for a client, it creates the Guest Services session and allows the client access to the Internet.

Can I use LHM to provide access using LDAP, RADIUS, a button, the time of day, tasseography, a survey, relative barometric pressure, a pass code, and so on as the authenticator?

Yes.

Can SonicWall write the script for me that does that?

We have provided a series of sample scripts as examples and for you to freely modify, but we do not provide custom scripts. We can, however, put you in touch with someone who can provide custom scripts. There are many SonicWall partners who have web development teams on staff who can provide these services.

I want to use the sample scripts SonicWall provided. What do I need to do to use them?

You need:

Microsoft Windows 2000, XP, 2003 platform running IIS 5.0 or higher, running the latest service packs and Hotfixes.
To use the scripts:
1
Copy the LHM script (or scripts) you wish to use to the wwwroot directory (usually in C:\inetpub\wwwroot).
2
Configure Guest Services on your SonicWall to use External Guest Authentication, as described in the What do all the LHM settings mean? How do I configure them?.

Some scripts need write privileges, particularly those that use databases. Depending on your configuration, two or three separate “users” need to have write access to the script directories that require writing.

The first account (all platforms) is IUSR_MACHINENAME (where machinename = the name of the local machine).
The second account on:
Windows XP is ASPNET (ASP.NET machine account).
Other platforms is IWAM_MACHINENAME (where machinename = the name of the local machine).
If database read/write access continues to fail even after assigning these permissions, it might be necessary to add read/write privileges for the NETWORK SERVICE account.
* 
NOTE: Versions on .NET Framework prior to 1.1 had user permission problems on domain controllers (http://support.microsoft.com/default.aspx?scid=kb;en-us;Q315158). It is strongly recommended that 1.1 (or higher) be installed.
3
After your environment is set up, you need to customize the scripts. We have tried to make this as simple as possible by placing all the interesting configurable bits in the myvars.aspx file. All entries are well commented, and their purposes and syntax should be evident. Further customization to the scripts themselves can be performed, but is generally not necessary.

Where can the LHM server reside?

The LHM Server can be virtually anywhere in the network, as long as it is reachable by the Guest Clients. It can be located at a centralized network operations center where it can administer LHM for multiple hotspots, or it can be co-located with a single SonicWall security appliance.

Why are my Guest Clients unable to reach the LHM Server, or why are the pages on the LHM server not loading?

Guest clients communicate directly with the LHM server; the communication is not proxied by the SonicWall security appliance. In other words:

The Guest Client's subnet must be able to reach the LHM server.
The LHM server must know how to reach the Guest Client's subnet (by route, NAT, or VPN).
Firewall Access Rules must be configured to allow the Guest Client subnet to reach the LHM server.

How does the LHM exchange between the SonicWall and the LHM server work (concise version, typical environment)?

1
The Guest Client associates, gets a DHCP lease, and launches a web browser.
2
DNS is allowed through the SonicWall security appliance. The URL FQDN resolves to its IP address.
3
The SonicWall security appliance checks if the Guest Client has an authenticated session.
If it's new, SonicWall redirects the client to the internal redirect (Please wait while you are being redirected) page.
4
The internal redirect page attempts to redirect the Guest Client to the LHM server.
If it fails, it redirects the client to the internal server-down (Wireless internet access is temporarily unavailable. Please click here to try again) page.
5
The Guest Client is redirected to the LHM server. In the redirect URL, the SonicWall embeds querystring information describing the embryonic session (such as the sessionID, the client's MAC and IP address, the SonicWall's LHM management IP and port, the UFI, the originally requested URL).
The LHM server script grabs the querystring information.
The client directly retrieves the LHM landing page from the LHM server.
6
Depending on the authorization model used (such as username:password, passcode, I Accept button), the LHM server decides that the Guest Client is worthy of access.
7
The LHM server initiates a web-request to the SonicWall security appliance at the configured management port (such as TCP 4043) to the externalGuestLogin.cgi page.
The LHM server POSTs the sessionID (which it obtained in Step 5) along with the username (which it either got from the user or made up) and the session-lifetime and idle-timeout (both of which it determines).
8
The SonicWall security appliance validates the sessionID, tries to create the session, and then responds to the POST with a result code describing whether or not it was able to authorize (create) the Guest session.
9
The LHM Server interprets the result code and reports the results (such as Session Authorized - You may now start browsing, Session creation failed - Rats, Max sessions) to the Guest Client.

What do all the LHM settings mean? How do I configure them?

Rather than going into the full detail provided in About Lightweight Hotspot Messaging (LHM), let's just explain what the settings mean and how you might configure them:

The LHM configuration on a wireless SonicOS is done on the Edit Zone — WLAN dialog.

Topics:  
General Tab
Local Web Server Settings
 

Client Redirect Protocol

The protocol (HTTP or HTTPS) used by the SonicWall security appliance when performing the initial internal client redirect via the Please wait while you are being redirected page. (This message is configurable from the Redirect Message area on the Web Content tab.) This step is prior to redirection to the LHM server.

External Web Server Settings
 

Web Server Protocol

The protocol (HTTP or HTTPS) running on the LHM server.

Web Server Host

The IP or resolvable FQDN of the LHM server.

Web Server Port

The TCP port of operations for the selected protocol on the LHM server.

Connection Timeout

The duration of time, in seconds, before the LMH server is considered unavailable on a redirect attempt. On timeout, the client is presented with the Server Down message configured on the Web Content tab.

Message Authentication

Enable Message Authentication

Use HMAC digest and embedded querystring in communication with the LHM server. This is useful if you are concerned about message tampering when HTTP is used to communicate with the LHM server. Optional.

Authentication Method

Select MD5 or SHA1.

Shared Secret

The shared secret for the hashed MAC. If used, it also needs to be configured on the LHM server scripts.

Auth Pages Tab
External Authentication Pages
* 
NOTE: These pages may each be a unique page on the LHM server, or they may all be the same page with a separate event handler for each status message. Examples are provided as follows to work with the newly developed scripts.
 

Login Page

The first page to which the client is redirected (such as lhm/accept/default.aspx).

Session Expiration Page

The page to which the client is redirected when the session expires (such as lhm/accept/default.aspx?cc=2). After a session expires, the user must create a new LHM session.

Idle Timeout Page -

The page to which the client is redirected when the idle timer is exceeded (such as lhm/accept/default.aspx?cc=3). After the idle timer is exceeded, the user can log in again with the same credentials as long as there is time left for the session.

Max Session Page

The page to which the client is redirected when the maximum number of sessions has been reached (such as lhm/accept/default.aspx?cc=4).

Web Content Tab
Redirect Message

The default or customized message that is presented to the client (usually for no more than one second) explaining that the session is being redirected to the LHM server. This interstitial page is used (rather than going directly to the LHM server) so that the SonicWall security appliance can verify the availability of the LHM server.

Server Down Message

The default or customized message that is presented to the client when the Redirector determines that the LHM server in unavailable.

Advanced Tab

The parameters on this tab are optional.

 

Auto Session Logout

The time increment and the page to which the SonicWall security appliance POSTs when a session is logged out (either automatically or manually).

Server Status Check

The time increment and the page to which the SonicWall POSTs to determine the availability of components on or behind the LHM server (such as a back-end database).

Session Synchronization

The time increment and the page to which the SonicWall POSTs the entire Guest Services session table. This allows the LHM server to synchronize the state of Guest Users for accounting, billing, or heuristics.

Can I change the LHM Management port from its default of TCP 4043?

Yes. This is easily done in SonicOS by modifying the port values of the External Guest Authentication Service Object.

Do I need to use the HMAC option? If I do want to use it, how do I use it?

The HMAC function is optional. It ensures that messages sent by the SonicWall to the LHM server and the LHM server to the SonicWall security appliance have not been tampered with. HMAC achieves this by calculating a keyed (password-aided) message authentication code on the information being passed between the two peers, and by adding that calculated digest to the data. Upon receiving the data, the other side calculates the digest itself, and compares it to the transmitted MAC; if the two match, the data was delivered intact. You should consider using the HMAC option if you are in an insecure environment or if you are concerned with security.

If you choose to use HMAC, you may implement your own HMAC routines, but the simplest method is to use the SonicWall-written SonicSSL.dll library, along with the libeay32.dll, which is freely available as part of OpenSSL; both are available from SonicWall by request.

To use HMAC:
1
Copy the libeay32.dll file to the path on the LHM (IIS) server (for example, into the C:\Windows\system32 folder).
2
Copy the SonicSSL.dll file to any location on the same server.
3
Register the SonicSSL.dll file with the command regsvr32 SonicSSL.dll.

After this is done, the LHM scripts are able to use the Server.CreateObject(SonicSSL.Crypto) object for HMAC calculations. The HMAC functions are included in the scripts described in LHM Script Library.

* 
IMPORTANT: The SonicWall security appliance URL Encodes (converts certain characters from their ASCII notation to hex notation) the req (originally requested URL) portion of the querystring, but the SonicWall method of URL encoding is slightly different from the Microsoft method (as employed by Request.QueryString, for example). Because of this difference in methods, it is possible for the string upon which the HMAC is being performed to be different between the SonicWall and the LHM server. The provided scripts compensate for this by manually encoding the req portion of the querystring in a fashion consistent with the SonicWall method.

Does SonicWall provide any support for these scripts?

The scripts are provided as examples, and they are not supported by SonicWall Technical Support, nor can SonicWall support assist with the configuration of your LHM back-end environment. Future consultative support services might address this.

I've written a new script, I've made some great enhancements to your scripts, or I've just made your scripts work a whole lot better than you did; is SonicWall interested?

Yes! We are always looking for new ways to use LHM, and for people to contribute to the library of available scripts. We consider LHM scripts written on any platform, using any authentication method. Send an email to products@sonicwall.com describing your script, and we will consider it for addition to our library. Submitting a script gives SonicWall permission to freely modify and/or redistribute the submitted script.

LHM Script Library

The SonicWall LHM Script library was established to serve as a resource for people using or wishing to use LHM for Guest Services. The goal is to attract multiple contributors and consumers, helping the library to grow to house a large, varied, and useful collection of scripts that anyone can modify or use as-is.

The first contribution to the library comprises six scripts: some in response to common user requests (accept, guestbook, and adauth), and some more uncommon (lhmquiz, random, and paypal). They were written outside of a Visual Studio .NET development environment, so their styles can be diverse. Common to all the scripts, however, are:

Modularization of the configurable variables, such as the paths to files, server IP addresses, use of a popup logout window, salt values, and timer settings. These configurable values are gathered into the myvars.aspx file so per-environment editing can be done in one place rather than having to search for configurable elements.
Extensive commentary explaining step-by-step what is being done.

A chooser.aspx landing page has been provided at the top-level of the scripts directory. This script was designed for demonstration environments to allow for the selection of a lower-level (specific) script without having to reconfigure the LHM settings on the SonicWall to point to a specific script. In other words, LHM on the SonicWall can be configured to point to the top-level chooser.aspx script, which then enumerate all the sub-directories (lower-level scripts such as random, accept, adauth). The top-level chooser.aspx script opens the target lower-level default.aspx script in a new window, and passes the original querystring in its entirety.

All of the scripts begin with the default.aspx page, and client redirection is performed automatically as needed. The LHM configuration on the SonicWall should, therefore, point to the default.aspx page at the appropriate path (such as lhm/accept/default.aspx or lhm/adauth/default.aspx). Some scripts have separate administrative function page; these are noted in the script descriptions.

A logout.aspx page is also provided with each script. The use of this page is controllable with the logoutPopup variable in myvars. Setting a value of 1 enables the use of the popup logout window. The window is invoked by the LHM authentication process after a successful response code (50) is received from the SonicWall. The script passes the sessID, mgmtBaseUrl, and sessTimer variables to the logout.aspx window so that the window can track the session time, and can POST a logout event back to the SonicWall (at the mgmtBaseUrl) for the correct session (sessID) when/if the user wants to manually terminate the session.

About the Use of the Logout Popup Window

The use of the logout popup is not necessary. Sessions timeout by themselves after their configured lifetime expires. The popup window simply provides users a mechanism to manually terminate their own sessions.
The window launches with a javascript popup, so popup blockers block the window.
Closing the window does not interrupt the session. Only the Logout button can end a session.
Because the countdown timer runs client-side, steps have been taken to prevent refreshing the page. Refreshing the page resets the client-side countdown timer, but it does not affect the actual session timer. The F5 key and right-click mouse event are captured and suppressed, which does not work on all browsers.
The use of the logout popup should agree with the nature of the scripts authentication scheme:
Some scripts have non-exclusive login processes, meaning that the user can login repeatedly (such as the Accept and ADAuth scripts). The use of the logout popup on these non-exclusive scripts is encouraged.
Some scripts are non-exclusive, but gather data that should be kept unique (such as the Guestbook and LHMQuiz scripts). The use of the logout popup on these scripts is acceptable, but can lead to redundant data being gathered.
Some scripts are exclusive, meaning that after the user authenticates, it is not possible to repeat the authentication process without some kind of cost (such as the PayPal script or the Random script where useDB is enabled). The use of the logout popup is discouraged on these scripts because the user has no simple means of logging back in.

The scripts also provide hidden output for a .NET procedure error, where the text is hidden by matching it to the color of the background. In the event of some kind of failure or error condition, error output may be provided and made visible by hitting CTRL-A on the web-page to select all of the text.

The following is a description of each of the scripts, what they do, and how they do it. As new scripts are added to the library, similar descriptions accompany them to help with understanding, customization, and integration.

Topics:  

Accept Script

 

Authentication Model

The Guest Client clicks the I Accept button.

Purpose

Present an acceptable use policy, terms of service, or welcome screen to the client.

myvars Variables

logoutPopup

Controls the use of the logout popup window. Set to:

0 to disable the popup window.
1 to enable the popup window.

 

sessTimer

The session timer in seconds.

 

idleTimer

The idle timer in seconds.

 

username

The username applied to the guest sessions. Because the script does not obtain a username from the client, it can be:

Explicitly set here for all clients.
Set to useMAC to set the username to the MAC address.

 

strHmac

The shared secret for the optional HMAC function.

 

hmacType

The digest type to use if HMAC is in use: MD5 or SHA1.

 

logo

The names of the logo (image) file to use on page headers.

Session Flow

1
The Guest Client clicks the I Accept button.
2
The LHM post string is assembled with the sessionID, the username (either default of MAC), the default session lifetime, and idle lifetime.
3
The script performs the LHM post to the SonicWall to authorize the session.

Additional Considerations

Only the basic LHM configuration is required.

Topics:  
default.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
   As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/accept/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim customCode as String
 
Sub Page_Load(src as Object, e as EventArgs)
 
LHMResult.Text=""
catchError.Text=""
 
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Set the userName to the grabbed client MAC address if so configured in myvars
If userName = "useMAC" Then
userName = mac
End If
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & Server.URLEncode(userName) & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/AuthenticationReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 50 - Login Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "50"
 
'Do we want to provide a logout popup window?
If logoutPopup = "1" Then
'Popup hack using Javascript for logout window
Dim sb As New System.Text.StringBuilder()
sb.Append("<script language='javascript'>")
sb.Append("window.open('logout.aspx?sessId=")
sb.Append(Server.URLEncode(CStr(sessionId)))
sb.Append("&mgmtBaseUrl=")
sb.Append(Server.URLEncode(CStr(mgmtBaseUrl)))
sb.Append("&sessTimer=")
sb.Append(Server.URLEncode(CStr(sessTimer)))
sb.Append("','logOut','toolbar=no,")
sb.Append("addressbar=no,menubar=no,")
sb.Append("width=400,height=250');")
sb.Append("<")
sb.Append("/")
sb.Append("script>")
RegisterStartupScript("stp", sb.ToString)
End If
 
LHMResult.Text = "<br><b><font color=""green"">Session Authorized:</font></b> You may now go to the URL you originally requested: <a target=""_blank"" href=""" & req & """>" & req & "</a>"
 
'Response code 51 - Session Limit Exceeded
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "51"
LHMResult.Text = "<br><b><font color=""red"">Session Limit Reached:</font></b> The maximum number of guest session has been reached. Sorry for the inconvenience. Please close and relaunch your browser to try again."
'Response code 100 - Login Failed.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "100"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> Your session cannot be created at this time. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
 
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Accept Script</TITLE>
</HEAD>
 
<BODY>
<form id="frmValidator" runat="server">
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>Welcome <%= ip%></b></font></td>
<td><center><img width="216" height="51" src="<%= logo%>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
 
<tr>
<td><br></td>
</tr>
<tr>
<td align=left>
By clicking the <b>Accept</b> button below, you accept the following terms of service:<br><br><b>
1. You will not try to download bad things.<br>
2. You will not try to upload bad things.<br>
3. You will not try to use all the bandwidth so that others have none.<br>
4. You will be happy when the SonicWALL blocks bad things from reaching you.</b><br><br>
</td>
<td>
</tr>
<tr>
<td><br><asp:button id="btnSubmit" class="button" text=" Accept " onClick="btnSubmit_Click" runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=catchError runat="server" /></td>
</tr>
</table>
</form>
</BODY>
</HTML>
logout.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
Dim sessionId as String
Dim mgmtBaseUrl as String
Dim eventId as String = "&eventId=1"
 
'Grab the code and the session lifetime from the generator page
Sub Page_Load(src as Object, e as EventArgs)
sessionId=Request.QueryString("sessId")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
sessTimer=Request.QueryString("sessTimer")
 
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'When the page loads, make the loggedIn span visible
loggedIn.Visible=True
loggedOut.Visible=False
 
Me.Button1.Attributes.Add("OnClick", "self.close()")
 
End Sub
 
'The Logout button
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogoff.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & eventId
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Make the loggedOut span visible
loggedIn.Visible=False
loggedOut.Visible=True
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/LogoffReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 150 - Logout Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "150"
LHMResult.Text = "<br><b><font color=""green"">Your session has been logged out.<br><br>Thank you for using LHM Guest Services.</font></b>"
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
</script>
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
font-size: 10pt;
background-color:#006699;
}
 
tr.smalltext {
font-size: 8pt;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
font-size: 8pt;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Logout Page</TITLE>
 
<SCRIPT LANGUAGE="Javascript">
 
//'Javascript Seconds Countdown Timer
var SecondsToCountDown = <%= sessTimer%>;
var originalTime=" ";
 
function CountDown()
{
clockStr="";
 
dayStr=Math.floor(SecondsToCountDown/86400)%100000
if(dayStr>0){
if(dayStr>1){
dayStr+=" days ";
} else dayStr+=" day ";
clockStr=dayStr;
}
hourStr=Math.floor(SecondsToCountDown/3600)%24
if(hourStr>0){
if(hourStr>1){
hourStr+=" hours ";
} else hourStr+=" hour ";
clockStr+=hourStr;
}
minuteStr=Math.floor(SecondsToCountDown/60)%60
if(minuteStr>0){
if(minuteStr>1){
minuteStr+=" minutes ";
} else minuteStr+=" minute ";
clockStr+=minuteStr;
}
secondStr=Math.floor(SecondsToCountDown/1)%60
if(secondStr>0){
if(secondStr>1){
secondStr+=" seconds ";
} else secondStr+=" second ";
clockStr+=secondStr;
}
 
if(SecondsToCountDown > 0)
{
--SecondsToCountDown;
}
 
if(originalTime.length < 2)
{
originalTime = clockStr;
}
 
// Make sure the form is still there before trying to set a value
if(document.frmValidator){
document.frmValidator.originalTime.value = originalTime;
document.frmValidator.countdown.value = clockStr;
}
setTimeout("CountDown()", 1000);
if(SecondsToCountDown == 0)
{
document.frmValidator.countdown.value = "Session Expired";
}
}
 
//'Disable right-click so that the window doesn't get refreshed since the countdown is clientside.
document.oncontextmenu = disableRightClick;
function disableRightClick()
{
return false;
}
 
//'Disable F5 key, too, on IE at least.
function noF5()
{
var key_f5 = 116;
if (key_f5==event.keyCode)
{
event.keyCode=0;
return false;
}
return false;
}
 
document.onkeydown=noF5
document.onmousedown=disableRightClick
 
</SCRIPT>
 
</HEAD>
 
<BODY onload='CountDown()'>
<span id="loggedIn" runat="server">
<form id="frmValidator" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="smalltext"><td><br></td></tr>
<tr class="smalltext">
<td>Original Session Time:</td>
<td><asp:textbox width=250 id="originalTime" runat="server" /></td>
</tr>
<tr class="smalltext">
<td>Remaining Session Time:</td>
<td><asp:textbox width=250 id="countdown" runat="server" /></td>
</tr>
<tr class="smalltext">
<td colspan=2><br>You may use this window to manually logout your session at any time, or you may safely close this window if you prefer to let your session timeout automatically.</font></td>
</td>
<tr>
<td colspan=2><center><asp:button id="btnSubmit" class="button" text=" Logout " onClick="btnSubmit_Click" runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
<span id="loggedOut" runat="server">
<form id="logout" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=catchError runat="server" /></td>
</tr>
<tr><td><br></td></tr>
<tr>
<td><center><asp:button id="Button1" class="button" text=" Close " runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
</BODY>
</HTML>
myvars.aspx
<script language="VB" runat="server">
 
'Set the logoutPopup window flag - 0 = no popup, 1 = popup
'The use of the logoutPopup in this script is encouraged because the login event is non-exclusive.
Dim logoutPopup as String = "1"
 
'Set the LHM Session Timeout
Dim sessTimer as String = "3600"
 
'Set the LHM Idle Timeout
Dim idleTimer as String = "300"
 
'Set the username to record for LHM session since this does not gather one. Set to userName="useMAC" to use the MAC addess.
Dim userName="useMAC"
'Dim userName = "LHM Guest User"
 
'Set the secret for use with optional HMAC auth, as configured in the Extern Guest Auth config on the SonicWALL
Dim strHmac as String = "password"
 
'Set the digest method for the HMAC, either MD5 or SHA1
Dim hmacType as String = "MD5"
'Dim hmacType as String = "SHA1"
 
'Set the logo image to use
Dim logo as String = "sonicwall.gif"
 
'------------------------End of Configurable Settings-------------------------
 
</script>

ADAuth Script

 

Authentication Model

The Guest Client provides their username and password. These credentials are then authenticated against an Active Directory or LDAP database.

Purpose

Classical authorization model using Active Directory via LDAP. Support for per-user session-timer and idle-timer setting provided by optionally grabbing LDAP attributes from the database during authorization.

myvars Variables

logoutPopup

Controls the use of the logout popup window. Set to:

0 to disable the popup window.
1 to enable the popup window.

 

myLdapServer

The IP address or resolvable FQDN of the LDAP/AD server providing authentication.

 

myLdapDomain

The LDAP/AD domain name

 

retrAttr

Specifies whether to retrieve session and idle timer values from the authenticating user's LDAP attributes (defined later). Set to:

0 to disable retrieval.
1 to attempt retrieval.

 

useCN

If reAttr=1, then this flag sets whether to use the common name (cn) to retrieve attributes, or the AD default login name (sAMAccountName).

Set to 1 to use cn. When authenticating against AD, this flag should be set to 0.

 

sessAttr

The LDAP attribute from which to retrieve the session timer (in seconds). If no value can be retrieved, or if the retrieved value is not numeric, the default session timer (sessTimer, defined below) are used.

 

idleAttr

The LDAP attribute from which to retrieve the idle timer (in seconds). If no value can be retrieved, or if the retrieved value is not numeric, the default idle timer (idleTimer, defined below) are used.

 

sessTimer

The default session timer in seconds.

 

idleTimer

The default idle timer in seconds.

 

strHmac

The shared secret for the optional HMAC function.

 

hmacType

The digest type to use if HMAC is in use: MD5 or SHA1.

 

logo

The names of the logo (image) file to use on page headers.

Session Flow

1
The Guest Client enters their LDAP/AD username and password.
2
The provided credentials are used to bind with the configured LDAP server.
3
If the bind attempt succeeds, the user is authenticated.
4
If the reAttr flag is set, an attempt is made to retrieve the defined sessAttr and idleAttr attributes (such as pager and mobile) from the LDAP DB. If valid results are retrieved, they are used; otherwise the default values are used.
5
The script performs the LHM post to the SonicWall to authorize the session.

Additional Considerations

Requires that the LHM server be able to communicate with the configured LDAP/AD server, either by route, NAT, or VPN. If the reAttr option is used, it requires that the LDAP attributes be defined for user-specific values to take effect.

NOTE: The pager and mobile attributes were selected because they are not frequently used, and because they can be set directly through Microsoft's Users and Computers MMC.)
Topics:  
default.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Math" %>
<%@ Import Namespace="System.DirectoryServices" %>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
<%@ Assembly name="System.DirectoryServices, Version=1.0.3300.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/adauth/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim customCode as String
 
Sub Page_Load(src as Object, e as EventArgs)
 
LHMResult.Text=""
catchError.Text=""
authResult.Text=""
 
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
sub OnBtnClearClicked (Sender As Object, e As EventArgs)
txtName.Text = ""
txtPassword.Text = ""
authResult.Text=""
LHMResult.Text=""
catchError.Text=""
end sub
 
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'Try to connect to LDAP with the user supplied attributes
Try
Dim ldapPath as String = "LDAP://" & myLdapServer
Dim ldapUser as String = myLdapDomain & "\" & txtName.Text
Dim validateUser as New DirectoryEntry(ldapPath,ldapUser,txtPassword.Text)
 
'This is the actual authentication piece
Dim nativeCheck as Object = validateUser.NativeObject
 
'If retrAttr is set in the myvars file, attempt to retrieve the session and idle values from LDAP
If retrAttr = "1" Then
Dim mySearch as New DirectorySearcher(validateUser)
'Check the myvars for selecting either sAMAccountName or cn
If useCN = "0" Then
mySearch.Filter = "(sAMAccountName=" & Server.URLEncode(txtName.Text) & ")"
Else
mySearch.Filter = "(cn=" & Server.URLEncode(txtName.Text) & ")"
End If
mySearch.PageSize="1"
mySearch.PropertiesToLoad.Add(sessAttr)
mySearch.PropertiesToLoad.Add(idleAttr)
Dim adResult as SearchResult
 
'If we get results on the attribute query, set timer values
adResult = mySearch.FindOne
If Not (adResult is Nothing) Then
If (adResult.Properties.Contains(sessAttr)) Then
'Check to see if the LDAP value returned is a number
Dim isNumber as New RegEx("^\d+$")
If (isNumber.IsMatch(adResult.Properties(sessAttr)(0).ToString())) Then
sessTimer=adResult.Properties(sessAttr)(0).ToString()
End If
End If 'End If sessAttr
If (adResult.Properties.Contains(idleAttr)) Then
'Check to see if the LDAP value returned is a number
Dim isNumber as New RegEx("^\d+$")
If (isNumber.IsMatch(adResult.Properties(idleAttr)(0).ToString())) Then
idleTimer=adResult.Properties(idleAttr)(0).ToString()
End If
End If 'End if idleAttr
End If 'End if adResult is present
End If 'End if retrAttr is in use
 
authResult.Text="<font color=""green""><b>Credentials Accepted.</b></font><br>Session Lifetime: " & round(sessTimer/60) & " minutes.<br>Idle Timer: " & round(idleTimer/60) & " minutes."
'Auth succeeded - move on to LHM Auth
LHM()
 
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
authResult.Text="<font color=""Red""><b>Credentials Rejected.</b></font><br>Please enter a valid username and password. "
End Try
 
End Sub
Sub LHM()
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & Server.URLEncode(txtName.Text) & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/AuthenticationReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 50 - Login Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "50"
 
'Do we want to provide a logout popup window?
If logoutPopup = "1" Then
'Popup hack using Javascript for logout window
Dim sb As New System.Text.StringBuilder()
sb.Append("<script language='javascript'>")
sb.Append("window.open('logout.aspx?sessId=")
sb.Append(Server.URLEncode(CStr(sessionId)))
sb.Append("&mgmtBaseUrl=")
sb.Append(Server.URLEncode(CStr(mgmtBaseUrl)))
sb.Append("&sessTimer=")
sb.Append(Server.URLEncode(CStr(sessTimer)))
sb.Append("','logOut','toolbar=no,")
sb.Append("addressbar=no,menubar=no,")
sb.Append("width=400,height=250');")
sb.Append("<")
sb.Append("/")
sb.Append("script>")
RegisterStartupScript("stp", sb.ToString)
End If
LHMResult.Text = "<br><b><font color=""green"">Session authorized:</font></b> You may now go to the URL you originally requested: <a target=""_blank"" href=""" & req & """>" & req & "</a>"
 
'Response code 51 - Session Limit Exceeded
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "51"
LHMResult.Text = "<br><b><font color=""red"">Session Limit Reached:</font></b> The maximum number of guest session has been reached. Sorry for the inconvenience. Please close and relaunch your browser to try again."
'Response code 100 - Login Failed.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "100"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> Your session cannot be created at this time. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM ADAuth Script</TITLE>
</HEAD>
 
<BODY>
<form id="frmValidator" runat="server">
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>LDAP/AD LHM Authentication</b></font></td>
<td><center><img width="216" height="51" src="<%= logo %>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
 
<table width="90%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td><b>Wecome <%= ip%> to SonicWALL's LHM AD/LDAP Authenticator.</b><br><br>Enter your LDAP or Active Directory username and password to obtain secure guest internet access.<br><br>If your domain account specifies session timeout values, those values will be applied to your account, otherwise you will receive the default one hour (60 minutes) of access with a five minute idle timeout.<br>
</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">Authentication domain: <%=myLdapDomain%></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td width="30%"><br>Enter your login name:</td>
<td width="30%"><asp:TextBox id="txtName" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtName" ControlToValidate="txtName" ErrorMessage="Please enter your name." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your password:</td>
<td width="30%"><asp:TextBox id="txtPassword" textmode="password" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtPassword" ControlToValidate="txtPassword" ErrorMessage="Please enter your password." runat="server" /></td>
</tr>
<tr>
<td></td><td><asp:Label id=authResult runat="server" />&nbsp</td>
</tr>
<tr>
<td></td>
<td><asp:button id="btnSubmit" class="button" text=" Submit " onClick="btnSubmit_Click" runat="server" />
&nbsp&nbsp
<asp:button id="btnClear" class="button" text=" Clear All " CausesValidation="False" onClick="OnBtnClearClicked" runat="server" />
</td>
</tr>
<tr>
<td colspan=2><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td colspan=2><asp:Label id=catchError runat="server" /></td>
</tr>
</table>
</form>
</BODY>
</HTML>
logout.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
Dim sessionId as String
Dim mgmtBaseUrl as String
Dim eventId as String = "&eventId=1"
 
'Grab the code and the session lifetime from the generator page
Sub Page_Load(src as Object, e as EventArgs)
sessionId=Request.QueryString("sessId")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
sessTimer=Request.QueryString("sessTimer")
 
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'When the page loads, make the loggedIn span visible
loggedIn.Visible=True
loggedOut.Visible=False
 
Me.Button1.Attributes.Add("OnClick", "self.close()")
 
End Sub
 
'The Logout button
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogoff.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & eventId
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Make the loggedOut span visible
loggedIn.Visible=False
loggedOut.Visible=True
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/LogoffReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 150 - Logout Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "150"
LHMResult.Text = "<br><b><font color=""green"">Your session has been logged out.<br><br>Thank you for using LHM Guest Services.</font></b>"
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
</script>
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
font-size: 10pt;
background-color:#006699;
}
 
tr.smalltext {
font-size: 8pt;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
font-size: 8pt;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Logout Page</TITLE>
 
<SCRIPT LANGUAGE="Javascript">
 
//'Javascript Seconds Countdown Timer
var SecondsToCountDown = <%= sessTimer%>;
var originalTime=" ";
 
function CountDown()
{
clockStr="";
 
dayStr=Math.floor(SecondsToCountDown/86400)%100000
if(dayStr>0){
if(dayStr>1){
dayStr+=" days ";
} else dayStr+=" day ";
clockStr=dayStr;
}
hourStr=Math.floor(SecondsToCountDown/3600)%24
if(hourStr>0){
if(hourStr>1){
hourStr+=" hours ";
} else hourStr+=" hour ";
clockStr+=hourStr;
}
minuteStr=Math.floor(SecondsToCountDown/60)%60
if(minuteStr>0){
if(minuteStr>1){
minuteStr+=" minutes ";
} else minuteStr+=" minute ";
clockStr+=minuteStr;
}
secondStr=Math.floor(SecondsToCountDown/1)%60
if(secondStr>0){
if(secondStr>1){
secondStr+=" seconds ";
} else secondStr+=" second ";
clockStr+=secondStr;
}
 
if(SecondsToCountDown > 0)
{
--SecondsToCountDown;
}
 
if(originalTime.length < 2)
{
originalTime = clockStr;
}
 
// Make sure the form is still there before trying to set a value
if(document.frmValidator){
document.frmValidator.originalTime.value = originalTime;
document.frmValidator.countdown.value = clockStr;
}
setTimeout("CountDown()", 1000);
if(SecondsToCountDown == 0)
{
document.frmValidator.countdown.value = "Session Expired";
}
}
 
//'Disable right-click so that the window doesn't get refreshed since the countdown is clientside.
document.oncontextmenu = disableRightClick;
function disableRightClick()
{
return false;
}
 
//'Disable F5 key, too, on IE at least.
function noF5()
{
var key_f5 = 116;
if (key_f5==event.keyCode)
{
event.keyCode=0;
return false;
}
return false;
}
 
document.onkeydown=noF5
document.onmousedown=disableRightClick
 
</SCRIPT>
 
</HEAD>
 
<BODY onload='CountDown()'>
<span id="loggedIn" runat="server">
<form id="frmValidator" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="smalltext"><td><br></td></tr>
<tr class="smalltext">
<td>Original Session Time:</td>
<td><asp:textbox width=250 id="originalTime" runat="server" /></td>
</tr>
<tr class="smalltext">
<td>Remaining Session Time:</td>
<td><asp:textbox width=250 id="countdown" runat="server" /></td>
</tr>
<tr class="smalltext">
<td colspan=2><br>You may use this window to manually logout your session at any time, or you may safely close this window if you prefer to let your session timeout automatically.</font></td>
</td>
<tr>
<td colspan=2><center><asp:button id="btnSubmit" class="button" text=" Logout " onClick="btnSubmit_Click" runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
<span id="loggedOut" runat="server">
<form id="logout" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=catchError runat="server" /></td>
</tr>
<tr><td><br></td></tr>
<tr>
<td><center><asp:button id="Button1" class="button" text=" Close " runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
</BODY>
</HTML>
myvars.aspx
<script language="VB" runat="server">
 
'Set the logoutPopup window flag - 0 = no popup, 1 = popup
'The use of the logoutPopup in this script is encouraged because the login event is non-exclusive.
Dim logoutPopup as String = "1"
 
'Set the LDAP server IP or Name
Dim myLdapServer as String = "10.50.128.40"
 
'Set the LDAP domain
Dim myLdapDomain as String = "sv.us.sonicwall.com"
 
'Set the retrAttr to 0 to use default session and idle timeouts
'Set the retrAttr to 1 to try to retrieve the session and idle timeouts from LDAP attributes.
Dim retrAttr as String ="1"
 
'Set useCN=1 to use common name (e.g. "joe levy", non-Active Directory LDAP) for attribute retrieval (retrAttr).
'Set useCN=0 to use saMACcountName (e.g. "jlevy", Active Directory / Windows) for attribute retrieval.
Dim useCN as String = "0"
 
'If using retrAttr=1, you must define the ldap attributes from which to retrieve the values
'Set the ldap attribute from which to retrieve the session timeout value (use is optional)
Dim sessAttr as String = "pager"
 
'Set the ldap attribute from which to retrieve the idle timeout value (use is optional)
Dim idleAttr as String = "mobile"
 
'If retrAttr=0, of if no attributes value can be retrieved, use the following timeout values
'Set the default LHM Session Timeout (for when no attributes is retrieved)
Dim sessTimer as String = "3600"
 
'Set the default LHM Idle Timeout (for when no attributes is retrieved)
Dim idleTimer as String = "300"
 
'Set the secret for use with optional HMAC auth, as configured in the Extern Guest Auth config on the SonicWALL
Dim strHmac as String = "password"
 
'Set the digest method for the HMAC, either MD5 or SHA1
Dim hmacType as String = "MD5"
'Dim hmacType as String = "SHA1"
 
'Set the logo image to use
Dim logo as String = "sonicwall.gif"
 
'------------------------End of Configurable Settings-------------------------
</script>

Guestbook Script

 

Authentication Model

The Guest Client provides their name, address, phone, email, URL (optional), and comment (optional) information.

Purpose

Gather market information; write the information to a database for later use.

myvars Variables

logoutPopup

Controls the use of the logout popup window. Set to:

0 to disable the popup window.
1 to enable the popup window.

 

sessTimer

The session timer in seconds.

 

idleTimer

The idle timer in seconds.

 

strHmac

The shared secret for the optional HMAC function.

 

hmacType

The digest type to use if HMAC is in use: MD5 or SHA1.

 

logo

The names of the logo (image) file to use on page headers.

Session Flow

1
The Guest Client enters their personal information and clicks Submit.
2
The entered information is written to a local .mdb database file for later use.
3
The LHM post string is assembled with the sessionID, the username (as provided in the web-form), the default session lifetime and idle lifetime.
4
The script performs the LHM post to the SonicWall to authorize the session.

Additional Considerations

Because the script is writing to the database, it is necessary to configure write privileges for the IUSR_MACHINENAME and IWAM_MACHINENAME (or ASPNET) accounts, as described in I want to use the sample scripts SonicWall provided. What do I need to do to use them?.

Topics:  
default.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDB" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/guestbook/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim customCode as String
 
Sub Page_Load(src as Object, e as EventArgs)
 
LHMResult.Text=""
catchError.Text=""
 
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
sub OnBtnClearClicked (Sender As Object, e As EventArgs)
txtName.Text = ""
txtAddress.Text = ""
txtCity.Text = ""
txtState.Text = ""
txtZip.Text = ""
txtPhone.Text = ""
txtEMail.Text = ""
txtURL.Text = ""
txtComment.Text = ""
LHMResult.Text=""
catchError.Text=""
end sub
 
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
Try
'Try to write the submitted info to the database file
Dim strConn as string = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("guestbook.mdb") & ";"
Dim MySQL as string = "INSERT INTO Guestbook (Name, Address, City, State, Zip, Phone, EMail, URL, Comment) VALUES ('" & txtName.Text & "','" & txtAddress.Text & "','" & txtCity.Text & "','" & txtState.Text & "','" & txtZip.Text & "','" & txtPhone.Text & "','" & txtEMail.Text & "','" & txtURL.Text & "','" & txtComment.Text & "')"
Dim MyConn as New OleDBConnection (strConn)
Dim cmd as New OleDBCommand (MySQL, MyConn)
MyConn.Open ()
cmd.ExecuteNonQuery ()
MyConn.Close ()
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
End Try
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & Server.URLEncode(txtName.Text) & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/AuthenticationReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 50 - Login Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "50"
 
'Do we want to provide a logout popup window?
If logoutPopup = "1" Then
'Popup hack using Javascript for logout window
Dim sb As New System.Text.StringBuilder()
sb.Append("<script language='javascript'>")
sb.Append("window.open('logout.aspx?sessId=")
sb.Append(Server.URLEncode(CStr(sessionId)))
sb.Append("&mgmtBaseUrl=")
sb.Append(Server.URLEncode(CStr(mgmtBaseUrl)))
sb.Append("&sessTimer=")
sb.Append(Server.URLEncode(CStr(sessTimer)))
sb.Append("','logOut','toolbar=no,")
sb.Append("addressbar=no,menubar=no,")
sb.Append("width=400,height=250');")
sb.Append("<")
sb.Append("/")
sb.Append("script>")
RegisterStartupScript("stp", sb.ToString)
End If
LHMResult.Text = "<br><b><font color=""green"">Session authorized:</font></b> You may now go to the URL you originally requested: <a target=""_blank"" href=""" & req & """>" & req & "</a>"
 
'Response code 51 - Session Limit Exceeded
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "51"
LHMResult.Text = "<br><b><font color=""red"">Session Limit Reached:</font></b> The maximum number of guest session has been reached. Sorry for the inconvenience. Please close and relaunch your browser to try again."
'Response code 100 - Login Failed.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "100"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> Your session cannot be created at this time. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Guestbook Script</TITLE>
</HEAD>
 
<BODY>
<form id="frmValidator" runat="server">
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>LHM Guestbook</b></font></td>
<td><center><img width="216" height="51" src="<%= logo %>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
 
<table width="90%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td>Wecome <%= ip%> to SonicWALL's LHM Guestbook. In exchange for providing us with your contact information,
along with your permission to occassionally contact you while you are in the middle of dinner, we will
provide you with <b>one complimentary hour of secure internet access.</b><br>
</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3><font color="white"><center><b>Thank you for your participation.</b></center></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="30%"><br>Enter your full name:</td>
<td width="30%"><asp:TextBox id="txtName" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtName" ControlToValidate="txtName" ErrorMessage="Please enter your name." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your address:</td>
<td width="30%"><asp:TextBox id="txtAddress" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtAddress" ControlToValidate="txtAddress" ErrorMessage="Please enter your address." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your city:</td>
<td width="30%"><asp:TextBox id="txtCity" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtCity" ControlToValidate="txtCity" ErrorMessage="Please enter your city." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your State:</td>
<td width="30%"><asp:TextBox id="txtState" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtState" ControlToValidate="txtState" ErrorMessage="Please enter your State." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your zip code:</td>
<td width="30%"><asp:TextBox id="txtZip" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtZip" ControlToValidate="txtZip" ErrorMessage="Please enter your zip code." Display="Dynamic" runat="server" />
<asp:RegularExpressionValidator id=regEx1 runat="server" Display="Dynamic" ControlToValidate="txtZip" ErrorMessage="Please enter in the format #####" ValidationExpression="^\d{5}"></asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td width="30%"><br>Enter your phone number:</td>
<td width="30%"><asp:TextBox id="txtPhone" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtPhone" ControlToValidate="txtPhone" ErrorMessage="Please enter your phone number." Display="Dynamic" runat="server" />
<asp:RegularExpressionValidator id=regEx2 runat="server" Display="Dynamic" ControlToValidate="txtPhone" ErrorMessage="Please enter in the format ###-###-####" ValidationExpression="((\(\d{3}\)?)|(\d{3}-))?\d{3}-\d{4}"></asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td width="30%"><br>Enter your email address:</td>
<td width="30%"><asp:TextBox id="txtEmail" runat="server" /></td>
<td width="40%"><asp:RegularExpressionValidator id=regEx3 runat="server" ControlToValidate="txtEmail" ValidationExpression=".*@.*\..*" ErrorMessage="Please enter a valid email address." Display="Dynamic" />
</asp:RegularExpressionValidator>
<asp:RequiredFieldValidator id="valTxtEnail" runat="server" ControlToValidate="txtEmail" ErrorMessage="Please enter you email address." Display="Dynamic" />
</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td width="30%"><br>Enter your web site URL (optional):</td>
<td width="30%"><asp:TextBox id="txtURL" runat="server" /></td>
</tr>
<tr>
<td valign="top" width="30%"><br>Enter a comment (optional):</td>
<td width="30%"><asp:TextBox id="txtComment" width="300px" height="100px" textmode="MultiLine" tabindex="4" runat="server" /></td>
</tr>
<tr>
<td></td>
<td><br><asp:button id="btnSubmit" class="button" text=" Submit " onClick="btnSubmit_Click" runat="server" />
&nbsp&nbsp
<asp:button id="btnClear" class="button" text=" Clear All " CausesValidation="False" onClick="OnBtnClearClicked" runat="server" />
</td>
</tr>
<tr>
<td colspan=2><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td colspan=2><asp:Label id=catchError runat="server" /></td>
</tr>
</table>
</form>
</BODY>
</HTML>
logout.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDB" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/guestbook/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim customCode as String
 
Sub Page_Load(src as Object, e as EventArgs)
 
LHMResult.Text=""
catchError.Text=""
 
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
sub OnBtnClearClicked (Sender As Object, e As EventArgs)
txtName.Text = ""
txtAddress.Text = ""
txtCity.Text = ""
txtState.Text = ""
txtZip.Text = ""
txtPhone.Text = ""
txtEMail.Text = ""
txtURL.Text = ""
txtComment.Text = ""
LHMResult.Text=""
catchError.Text=""
end sub
 
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
Try
'Try to write the submitted info to the database file
Dim strConn as string = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("guestbook.mdb") & ";"
Dim MySQL as string = "INSERT INTO Guestbook (Name, Address, City, State, Zip, Phone, EMail, URL, Comment) VALUES ('" & txtName.Text & "','" & txtAddress.Text & "','" & txtCity.Text & "','" & txtState.Text & "','" & txtZip.Text & "','" & txtPhone.Text & "','" & txtEMail.Text & "','" & txtURL.Text & "','" & txtComment.Text & "')"
Dim MyConn as New OleDBConnection (strConn)
Dim cmd as New OleDBCommand (MySQL, MyConn)
MyConn.Open ()
cmd.ExecuteNonQuery ()
MyConn.Close ()
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
End Try
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & Server.URLEncode(txtName.Text) & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/AuthenticationReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 50 - Login Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "50"
 
'Do we want to provide a logout popup window?
If logoutPopup = "1" Then
'Popup hack using Javascript for logout window
Dim sb As New System.Text.StringBuilder()
sb.Append("<script language='javascript'>")
sb.Append("window.open('logout.aspx?sessId=")
sb.Append(Server.URLEncode(CStr(sessionId)))
sb.Append("&mgmtBaseUrl=")
sb.Append(Server.URLEncode(CStr(mgmtBaseUrl)))
sb.Append("&sessTimer=")
sb.Append(Server.URLEncode(CStr(sessTimer)))
sb.Append("','logOut','toolbar=no,")
sb.Append("addressbar=no,menubar=no,")
sb.Append("width=400,height=250');")
sb.Append("<")
sb.Append("/")
sb.Append("script>")
RegisterStartupScript("stp", sb.ToString)
End If
LHMResult.Text = "<br><b><font color=""green"">Session authorized:</font></b> You may now go to the URL you originally requested: <a target=""_blank"" href=""" & req & """>" & req & "</a>"
 
'Response code 51 - Session Limit Exceeded
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "51"
LHMResult.Text = "<br><b><font color=""red"">Session Limit Reached:</font></b> The maximum number of guest session has been reached. Sorry for the inconvenience. Please close and relaunch your browser to try again."
'Response code 100 - Login Failed.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "100"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> Your session cannot be created at this time. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Guestbook Script</TITLE>
</HEAD>
 
<BODY>
<form id="frmValidator" runat="server">
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>LHM Guestbook</b></font></td>
<td><center><img width="216" height="51" src="<%= logo %>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
 
<table width="90%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td>Wecome <%= ip%> to SonicWALL's LHM Guestbook. In exchange for providing us with your contact information,
along with your permission to occassionally contact you while you are in the middle of dinner, we will
provide you with <b>one complimentary hour of secure internet access.</b><br>
</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3><font color="white"><center><b>Thank you for your participation.</b></center></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="30%"><br>Enter your full name:</td>
<td width="30%"><asp:TextBox id="txtName" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtName" ControlToValidate="txtName" ErrorMessage="Please enter your name." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your address:</td>
<td width="30%"><asp:TextBox id="txtAddress" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtAddress" ControlToValidate="txtAddress" ErrorMessage="Please enter your address." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your city:</td>
<td width="30%"><asp:TextBox id="txtCity" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtCity" ControlToValidate="txtCity" ErrorMessage="Please enter your city." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your State:</td>
<td width="30%"><asp:TextBox id="txtState" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtState" ControlToValidate="txtState" ErrorMessage="Please enter your State." runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your zip code:</td>
<td width="30%"><asp:TextBox id="txtZip" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtZip" ControlToValidate="txtZip" ErrorMessage="Please enter your zip code." Display="Dynamic" runat="server" />
<asp:RegularExpressionValidator id=regEx1 runat="server" Display="Dynamic" ControlToValidate="txtZip" ErrorMessage="Please enter in the format #####" ValidationExpression="^\d{5}"></asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td width="30%"><br>Enter your phone number:</td>
<td width="30%"><asp:TextBox id="txtPhone" runat="server" /></td>
<td width="40%"><asp:RequiredFieldValidator id="valTxtPhone" ControlToValidate="txtPhone" ErrorMessage="Please enter your phone number." Display="Dynamic" runat="server" />
<asp:RegularExpressionValidator id=regEx2 runat="server" Display="Dynamic" ControlToValidate="txtPhone" ErrorMessage="Please enter in the format ###-###-####" ValidationExpression="((\(\d{3}\)?)|(\d{3}-))?\d{3}-\d{4}"></asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td width="30%"><br>Enter your email address:</td>
<td width="30%"><asp:TextBox id="txtEmail" runat="server" /></td>
<td width="40%"><asp:RegularExpressionValidator id=regEx3 runat="server" ControlToValidate="txtEmail" ValidationExpression=".*@.*\..*" ErrorMessage="Please enter a valid email address." Display="Dynamic" />
</asp:RegularExpressionValidator>
<asp:RequiredFieldValidator id="valTxtEnail" runat="server" ControlToValidate="txtEmail" ErrorMessage="Please enter you email address." Display="Dynamic" />
</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td width="30%"><br>Enter your web site URL (optional):</td>
<td width="30%"><asp:TextBox id="txtURL" runat="server" /></td>
</tr>
<tr>
<td valign="top" width="30%"><br>Enter a comment (optional):</td>
<td width="30%"><asp:TextBox id="txtComment" width="300px" height="100px" textmode="MultiLine" tabindex="4" runat="server" /></td>
</tr>
<tr>
<td></td>
<td><br><asp:button id="btnSubmit" class="button" text=" Submit " onClick="btnSubmit_Click" runat="server" />
&nbsp&nbsp
<asp:button id="btnClear" class="button" text=" Clear All " CausesValidation="False" onClick="OnBtnClearClicked" runat="server" />
</td>
</tr>
<tr>
<td colspan=2><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td colspan=2><asp:Label id=catchError runat="server" /></td>
</tr>
</table>
</form>
</BODY>
</HTML>
myvars.aspx
<script language="VB" runat="server">
 
'Set the logoutPopup window flag - 0 = no popup, 1 = popup
'The use of the logoutPopup in this script is discouraged because although the login event
'is non-exclusive, the login event produces data where redundancy is undesirable.
Dim logoutPopup as String = "0"
 
'Set the LHM Session Timeout
Dim sessTimer as String = "3600"
 
'Set the LHM Idle Timeout
Dim idleTimer as String = "300"
 
'Set the secret for use with optional HMAC auth, as configured in the Extern Guest Auth config on the SonicWALL
Dim strHmac as String = "password"
 
'Set the digest method for the HMAC, either MD5 or SHA1
Dim hmacType as String = "MD5"
'Dim hmacType as String = "SHA1"
 
'Set the logo image to use
Dim logo as String = "sonicwall.gif"
 
'------------------------End of Configurable Settings-------------------------
 
</script>

LHMQuiz Script

 

Authentication Model

The Guest Client takes a quiz. A passing score serves as the authentication credentials

Purpose

It is common for network access to be provided in a classroom environment. By using a passing score on a test of the material being taught as the method for authentication, an instructor can ensure that the course material has been mastered before the irresistible temptation of the Internet diverts attention. The script also emails the completed passing test to the test-taker, and mails failing tests to the proctor/instructor.

myvars Variables

logoutPopup

Controls the use of the logout popup window. Set to:

0 to disable the popup window.
1 to enable the popup window.

 

passingScore

The score (an integer representing a percentage) required to pass the quiz.

 

quizFile

The filename for the XML source for the quiz (such as quiz.xml, shortquiz.xml).

 

quizName

The name of the quiz, used throughout the script.

 

quizFrom

The From: email address used when emailing the quiz.

 

quizTo

The To: email address where failing quizzes are to be sent (such as the test proctor or instructor).

 

imagePath

The email includes an attachment for the correct and incorrect answers. This sets the path for those image files. This is generally set to the same path of the script files themselves.

 

smtpServer

The IP address or resolvable FQDN of the SMTP server to be used for quiz result delivery. This can be set to 127.0.0.1 if the local IIS SMTP server instances is to be used.

 

sessTimer

The session timer in seconds.

 

idleTimer

The idle timer in seconds.

 

strHmac

The shared secret for the optional HMAC function.

 

hmacType

The digest type to use if HMAC is in use: MD5 or SHA1.

 

logo

The names of the logo (image) file to use on page headers.

Session Flow

1
The Guest Client is prompted to enter their full name and email address. A correct/valid email address is required for delivery of the completed passing quiz.
2
After entering name and email, the Guest Client is redirected to the quiz.aspx page. This is where the multiple choice test is administered.
3
The test questions themselves are contained in the quiz.xml file, defined by the quiz.xsd (XML Schema Definition) file. The quiz.xml file can and should be edited to customize the quiz, but the quiz.xsd document should not be edited unless absolutely necessary.

Two versions of the quiz are included: quiz.xml (containing 10 questions) and shortquiz.xml (containing 2 questions, for testing that the script works). The quiz supports any number of questions, and each question supports any number of answers, one of which must be marked the correct answer, with correct=yes. It should be fairly straightforward to modify the provided quiz.xml file as needed.

 

4
At the end of the quiz, the results are shown. If it is a:
Failing score, the test results are emailed to the instructor (email address defined in myvars), and the Guest Client is prompted to take the test again. The LHM session is not authorized.
Passing score, the test results are emailed to the test-taker, and the LHM session is authorized.

The emailed test is sent in an HTML format, and includes the checkmark.gif and block.gif (right and wrong) graphics as an attachment so that they can be displayed in the email.

5
If the test was passed, the LHM post string is assembled with the sessionID, the username (as provided in the web-form), the default session lifetime and idle lifetime.
6
The script performs the LHM post to the SonicWall to authorize the session.

Additional Considerations

Access to an SMTP server is required to deliver the test results. Because the script is relaying the mail through the server, the SMTP server needs to be configured to allow relaying from the LHM server. This is best accomplished by configuring the SMTP server to allow relaying from the IP address of the LHM server.

Most IIS installations include a local SMTP server, so it is convenient to use this local SMTP server for mail delivery by configuring the smtpServer variable in myvars as 127.0.0.1.

 

Even when using the local SMTP server for mail delivery, it is necessary to allow relaying. In most configurations, this is performed by:

1
Going into the IIS MMC configurator.
2
Right clicking on Default SMTP Virtual Server.
3
Selecting Properties.
4
Selecting the Access tab.
5
Clicking the Relay button.
6
Adding 127.0.0.1 to the access granted list.

When using a non-local SMTP server, that SMTP server should be configured to allow the LHM server to relay by its actual IP address.

Topics:  
default.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script runat="server">
 
'Sample LHM redirect querystring:
'http://10.50.165.231/xmlquiz/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim emailAddr as String
Dim userName as String
Dim customCode as String
 
Sub Page_Load(src as Object, e as EventArgs)
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
'When the submit button is clicked, pass the variables we need and load the quiz
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
Context.Items.Add("req", req)
Context.Items.Add("sessionId", sessionId)
Context.Items.Add("emailAddr",clientEmail.Text)
Context.Items.Add("userName",clientName.Text)
Context.Items.Add("mgmtBaseUrl",mgmtBaseUrl)
Server.Transfer("quiz.aspx",true)
 
End Sub
 
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Quiz Script</TITLE>
</HEAD>
 
<BODY>
<form id="frmValidator" runat="server">
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>LHM Quiz Authorization</b></font></td>
<td><center><img width="216" height="51" src="sonicwall.gif"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td width="30%"><br>Enter your full name:</td>
<td width="20%"><asp:TextBox id="clientName" runat="server" /></td>
<td ><asp:RequiredFieldValidator id="valTxtName" ControlToValidate="clientName" ErrorMessage="Please enter your name." Display="Dynamic" runat="server" /></td>
</tr>
<tr>
<td width="30%"><br>Enter your real email address:</td>
<td width="20%"><asp:TextBox id="clientEmail" runat="server" /></td>
<td ><asp:RegularExpressionValidator id="fromEmail" runat="server" ControlToValidate="clientEmail" ValidationExpression=".*@.*\..*" ErrorMessage="Please enter a valid email address." Display="Dynamic" />
</asp:RegularExpressionValidator>
<asp:RequiredFieldValidator id="fromRequired" runat="server" ControlToValidate="clientEmail" ErrorMessage="Please enter your email address." Display="Dynamic" />
</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td></td>
<td><asp:button id="btnSubmit" class="button" text=" Submit " onClick="btnSubmit_Click" runat="server" /><br></td>
</tr>
 
<tr class="heading">
<td colspan=3 align="left"><font color="white"><b>Welcome Quiztaker <%= ip%></b></font></td>
</tr>
</table>
<table width="70%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td>
<br>You have been redirected here by Lightweight Hotspot Messaging.
This environment has been setup to demonstrate the flexibility of LHM, including
support for both wired and wireless clients, and also the ability for LHM to use
more than just username and password authentication for providing access.<br><br>
The page that you are about to continue on to is a <%= quizName %> written in ASP.net.
A passing score of <%= passingScore%>% will serve as the authentication for LHM, and will grant
you network access. You must pass the test to continue, and will be prompted to retake
the entire quiz if you you do not pass. <br><br>
When you are done, the completed test will be emailed to you at the address you
specify above.<br><br>
So it's not just a good way to prove your understanding of some
key SonicOS concepts, but also a practical example of the versatility of LHM.
</td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td colspan=2><asp:Label id=catchError runat="server" /></td>
</tr>
</table>
</form>
</BODY>
</HTML>
logout.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
Dim sessionId as String
Dim mgmtBaseUrl as String
Dim eventId as String = "&eventId=1"
 
'Grab the code and the session lifetime from the generator page
Sub Page_Load(src as Object, e as EventArgs)
sessionId=Request.QueryString("sessId")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
sessTimer=Request.QueryString("sessTimer")
 
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'When the page loads, make the loggedIn span visible
loggedIn.Visible=True
loggedOut.Visible=False
 
Me.Button1.Attributes.Add("OnClick", "self.close()")
 
End Sub
 
'The Logout button
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogoff.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & eventId
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Make the loggedOut span visible
loggedIn.Visible=False
loggedOut.Visible=True
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/LogoffReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 150 - Logout Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "150"
LHMResult.Text = "<br><b><font color=""green"">Your session has been logged out.<br><br>Thank you for using LHM Guest Services.</font></b>"
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
</script>
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
font-size: 10pt;
background-color:#006699;
}
 
tr.smalltext {
font-size: 8pt;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
font-size: 8pt;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Logout Page</TITLE>
 
<SCRIPT LANGUAGE="Javascript">
 
//'Javascript Seconds Countdown Timer
var SecondsToCountDown = <%= sessTimer%>;
var originalTime=" ";
 
function CountDown()
{
clockStr="";
 
dayStr=Math.floor(SecondsToCountDown/86400)%100000
if(dayStr>0){
if(dayStr>1){
dayStr+=" days ";
} else dayStr+=" day ";
clockStr=dayStr;
}
hourStr=Math.floor(SecondsToCountDown/3600)%24
if(hourStr>0){
if(hourStr>1){
hourStr+=" hours ";
} else hourStr+=" hour ";
clockStr+=hourStr;
}
minuteStr=Math.floor(SecondsToCountDown/60)%60
if(minuteStr>0){
if(minuteStr>1){
minuteStr+=" minutes ";
} else minuteStr+=" minute ";
clockStr+=minuteStr;
}
secondStr=Math.floor(SecondsToCountDown/1)%60
if(secondStr>0){
if(secondStr>1){
secondStr+=" seconds ";
} else secondStr+=" second ";
clockStr+=secondStr;
}
 
if(SecondsToCountDown > 0)
{
--SecondsToCountDown;
}
 
if(originalTime.length < 2)
{
originalTime = clockStr;
}
 
// Make sure the form is still there before trying to set a value
if(document.frmValidator){
document.frmValidator.originalTime.value = originalTime;
document.frmValidator.countdown.value = clockStr;
}
setTimeout("CountDown()", 1000);
if(SecondsToCountDown == 0)
{
document.frmValidator.countdown.value = "Session Expired";
}
}
 
//'Disable right-click so that the window doesn't get refreshed since the countdown is clientside.
document.oncontextmenu = disableRightClick;
function disableRightClick()
{
return false;
}
 
//'Disable F5 key, too, on IE at least.
function noF5()
{
var key_f5 = 116;
if (key_f5==event.keyCode)
{
event.keyCode=0;
return false;
}
return false;
}
 
document.onkeydown=noF5
document.onmousedown=disableRightClick
 
</SCRIPT>
 
</HEAD>
 
<BODY onload='CountDown()'>
<span id="loggedIn" runat="server">
<form id="frmValidator" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="smalltext"><td><br></td></tr>
<tr class="smalltext">
<td>Original Session Time:</td>
<td><asp:textbox width=250 id="originalTime" runat="server" /></td>
</tr>
<tr class="smalltext">
<td>Remaining Session Time:</td>
<td><asp:textbox width=250 id="countdown" runat="server" /></td>
</tr>
<tr class="smalltext">
<td colspan=2><br>You may use this window to manually logout your session at any time, or you may safely close this window if you prefer to let your session timeout automatically.</font></td>
</td>
<tr>
<td colspan=2><center><asp:button id="btnSubmit" class="button" text=" Logout " onClick="btnSubmit_Click" runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
<span id="loggedOut" runat="server">
<form id="logout" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=catchError runat="server" /></td>
</tr>
<tr><td><br></td></tr>
<tr>
<td><center><asp:button id="Button1" class="button" text=" Close " runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
</BODY>
</HTML>
 
myvars.aspx
<script language="VB" runat="server">
 
'Set the logoutPopup window flag - 0 = no popup, 1 = popup
'The use of the logoutPopup in this script is discouraged because although the login event
'is non-exclusive, the login event produces data where redundancy is undesirable.
Dim logoutPopup as String = "0"
 
'Set the passing score
Dim passingScore as Integer = 80
 
'Set the filename of the quiz XML source
Dim quizFile as String = "quiz.xml"
'Dim quizFile as String = "shortquiz.xml"
 
'Set the name of the Quiz
Dim quizName as String = "SonicOS Quiz"
 
'Set the emailed quiz results "from" email address
Dim quizFrom as String = "joelevy@sonicwall.com"
 
'Set the email address to send failed test results to (the proctor/instructor)
Dim quizTo as String = "joelevy@sonicwall.com"
 
'Set the path for check and block embedded images - usually the same path as the quiz
Dim imagePath as String = "C:\inetpub\wwwroot\lhm\lhmquiz\"
 
'Set the IP or resolvable FQDN for the SMTP Server
'Make sure the server is configured to relay from the IP address of this server
'If setting to 127.0.0.1 (local IIS SMTP), you need to allow IIS SMTP to relay from 127.0.0.1
Dim smtpServer as String = "127.0.0.1"
 
'Set the LHM Session Timeout
Dim sessTimer as String = "86400"
 
'Set the LHM Idle Timeout
Dim idleTimer as String = "3600"
 
'Set the secret for use with optional HMAC auth, as configured in the Extern Guest Auth config on the SonicWALL
Dim strHmac as String = "password"
 
'Set the digest method for the HMAC, either MD5 or SHA1
Dim hmacType as String = "MD5"
'Dim hmacType as String = "SHA1"
 
'Set the logo image to use
Dim logo as String = "sonicwall.gif"
 
'------------------------End of Configurable Settings-------------------------
 
</script>
quiz.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Web.Mail" %>
 
<!-- Original quiz code from www.codeproject.com -->
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Set the path to the XML quiz data
Dim strXmlFilePath as String = Server.MapPath(quizFile)
 
'Setup our variables
Dim emailAddr as String
Dim userName as String
Dim req as String
Dim sessionId as String
Dim mgmtBaseUrl as String
Dim xDoc as XmlDocument = New XmlDocument()
Dim intTotalQuestion as Integer
Dim intQuestionNo as Integer = 1
Dim intScore as Integer = 0
Dim arrAnswerHistory as new ArrayList()
Dim arrRightOrWrong as new ArrayList()
Dim arrCorrect as new ArrayList()
 
Sub Page_Load(src as Object, e as EventArgs)
 
LHMResult.Text=""
catchError.Text=""
 
'Grab context items set in default.aspx
emailAddr = Context.Items("emailAddr")
userName = Context.Items("userName")
req = Context.Items("req")
sessionId = Context.Items("sessionId")
mgmtBaseUrl = Context.Items("mgmtBaseUrl")
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Load xml data
xDoc.Load(strXmlFilePath)
 
'Start a new quiz?
If Not Page.IsPostBack Then
 
'Yes. Count total question
intTotalQuestion = xDoc.SelectNodes("/quiz/mchoice").Count
 
'Record start time
ViewState("StartTime") = DateTime.Now
 
ShowQuestion(intQuestionNo)
End If
End Sub
 
Sub btnSubmit_Click(src as Object, e as EventArgs)
 
'Retrieve variables from ViewState
intTotalQuestion = ViewState("TotalQuestion")
intQuestionNo = ViewState("QuestionNo")
intScore = ViewState("Score")
arrAnswerHistory = ViewState("AnswerHistory")
arrRightOrWrong = ViewState("RightOrWrong")
arrCorrect = ViewState("AnswerList")
req = ViewState("origReq")
userName = ViewState("origUserName")
emailAddr = ViewState("origEmailAddr")
mgmtBaseUrl = ViewState("mgmtUrl")
sessionId = ViewState("sessID")
 
'Correct answer?
If rblAnswer.SelectedItem.Value = ViewState("CorrectAnswer") Then
intScore += 1
arrRightOrWrong.Add(0)
Else
arrRightOrWrong.Add(rblAnswer.SelectedItem.Value)
End If
'Remember all selected answers
arrAnswerHistory.Add(rblAnswer.SelectedItem.Value)
arrCorrect.Add(ViewState("CorrectAnswer"))
 
'End of quiz?
If intQuestionNo=intTotalQuestion Then
 
'Yes. Show the result.
QuizScreen.Visible = False
ResultScreen.Visible = True
 
'Render result screen
ShowResult()
 
Else
 
'Not yet. Show another question.
QuizScreen.Visible = True
ResultScreen.Visible = False
intQuestionNo += 1
'Render next question
ShowQuestion(intQuestionNo)
End If
End Sub
 
Sub ShowQuestion(intQuestionNo as Integer)
Dim xNodeList as XmlNodeList
Dim xNodeAttr as Object
Dim strXPath as String
Dim i as Integer
Dim tsTimeSpent as TimeSpan
 
strXPath = "/quiz/mchoice[" & intQuestionNo.ToString() & "]"
 
'Extract question
lblQuestion.Text = intQuestionNo.ToString() & ". " & xDoc.SelectSingleNode(strXPath & "/question").InnerXml
 
'Extract answers
xNodeList = xDoc.SelectNodes(strXPath & "/answer")
 
'Clear previous listitems
rblAnswer.Items.Clear
For i = 0 to xNodeList.Count-1
 
'Add item to radiobuttonlist
rblAnswer.Items.Add(new ListItem(xNodeList.Item(i).InnerText, i+1))
 
'Extract correct answer
xNodeAttr = xNodeList.Item(i).Attributes.ItemOf("correct")
If not xNodeAttr is Nothing Then
If xNodeAttr.Value = "yes" Then
ViewState("CorrectAnswer") = i+1
End If
End If
Next
 
'Output Total Question and passing score
lblTotalQuestion.Text = intTotalQuestion
lblPassingScore.Text = passingScore
 
'Output Time Spent
tsTimeSpent = DateTime.Now.Subtract(ViewState("StartTime"))
lblTimeSpent.Text = tsTimeSpent.Minutes.ToString() & ":" & tsTimeSpent.Seconds.ToString()
 
'Store data to viewstate
ViewState("TotalQuestion") = intTotalQuestion
ViewState("Score") = intScore
ViewState("QuestionNo") = intQuestionNo
ViewState("AnswerHistory") = arrAnswerHistory
ViewState("RightOrWrong") = arrRightOrWrong
ViewState("AnswerList") = arrCorrect
ViewState("origReq")=req
ViewState("origUserName")=userName
ViewState("origEmailAddr")=emailAddr
ViewState("mgmtUrl")=mgmtBaseUrl
ViewState("sessID")=sessionID
 
End Sub
 
Sub ShowResult()
Dim strResult as String
Dim intCompetency as Integer
Dim i as Integer
Dim strXPath as String
Dim tsTimeSpent as TimeSpan
tsTimeSpent = DateTime.Now.Subtract(ViewState("StartTime"))
 
strResult = "<center>"
 
if passingScore <= Int(intScore/intTotalQuestion*100).ToString()
strResult += "<h2><font color=""green"">You Passed!</h3></font>"
else
strResult += "<h2><font color=""red"">You Failed!</h3><b>Please review the answers and retake the test.</b><br></font>"
End If
 
strResult += "User Name: " & userName & "<br>"
strResult += "Elapsed Time: " & tsTimeSpent.Minutes.ToString() & ":" & tsTimeSpent.Seconds.ToString() & "<br>"
strResult += "Correct Answers: " & intScore.ToString() & " out of " & intTotalQuestion.ToString() & "<br>"
strResult += "Your Percentage: " & Int(intScore/intTotalQuestion*100).ToString() & "%<br>"
strResult += "Required Percentage:" & passingScore.ToString() & "%<br>"
strResult += "</center>"
 
strResult += "<h3>Quiz Results</h3>"
For i = 1 to intTotalQuestion
strXPath = "/quiz/mchoice[" & i.ToString() & "]"
strResult += "<b>" & i.ToString() & ". " & xDoc.SelectNodes(strXPath & "/question").Item(0).InnerXml & "</b><br>"
If arrRightOrWrong.Item(i-1)=0 Then
strResult += "<img src = ""checkMark.gif""><font color=""green"">&nbsp"
strResult += "<b>You answered:</b> " & xDoc.SelectNodes(strXPath & "/answer[" & arrAnswerHistory.Item(i-1).ToString() & "]").Item(0).InnerXml & "</font><br><br>"
Else
strResult += "<img src = ""Block.gif""><font color=""red"">&nbsp"
strResult += "<b>You answered:</b> " & xDoc.SelectNodes(strXPath & "/answer[" & arrAnswerHistory.Item(i-1).ToString() & "]").Item(0).InnerXml & "<br>"
strResult += "The correct anwer is: " & xDoc.SelectNodes(strXPath & "/answer[" & arrCorrect.Item(i-1).ToString() & "]").Item(0).InnerXml & "</font><br><br>"
End If
Next
'Setup the common Mail settings
Dim objMail As MailMessage
objMail = New MailMessage()
objMail.From = quizFrom
objMail.Body = strResult
objMail.BodyFormat = MailFormat.Html
 
'Path to the attachments for the Check and X images - update these in myvars.aspx
objMail.Attachments.Add(New MailAttachment(imagePath & "block.gif"))
objMail.Attachments.Add(New MailAttachment(imagePath & "checkMark.gif"))
 
'Address of the SMTP server - can be localhost if SMTP is running on IIS - in myvars.aspx
SmtpMail.SmtpServer = smtpServer
 
'Determine pass/fail
If passingScore <= Int(intScore/intTotalQuestion*100).ToString()
'Mail the passing test result to the test-taker
'Be sure to update the mail fields in myvars.aspx
objMail.To =emailAddr
objMail.Subject = quizName & " Results for " & emailAddr
 
'Send the mail
SmtpMail.Send(objMail)
strResult +="Your test is being emailed to you at " & emailAddr
 
'Send the session Auth message to LHM
postLHM()
else
'Mail failing test results to the instuctor
objMail.To =quizTo
objMail.Subject = "Failing " & quizName & " Test Results for " & emailAddr
 
'Send the mail
SmtpMail.Send(objMail)
strResult += "<a href=""quiz.aspx"">Click here to retake the quiz</a>"
End If
 
'Write it
lblResult.Text = strResult
 
End Sub
 
Sub postLHM()
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & Server.URLEncode(userName) & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/AuthenticationReply/ResponseCode"
 
'Response code 50 - Login Succeeded
 
If snwlResponse.SelectSingleNode(codePath).InnerXml = "50"
 
'Do we want to provide a logout popup window?
If logoutPopup = "1" Then
'Popup hack using Javascript for logout window
Dim sb As New System.Text.StringBuilder()
sb.Append("<script language='javascript'>")
sb.Append("window.open('logout.aspx?sessId=")
sb.Append(Server.URLEncode(CStr(sessionId)))
sb.Append("&mgmtBaseUrl=")
sb.Append(Server.URLEncode(CStr(mgmtBaseUrl)))
sb.Append("&sessTimer=")
sb.Append(Server.URLEncode(CStr(sessTimer)))
sb.Append("','logOut','toolbar=no,")
sb.Append("addressbar=no,menubar=no,")
sb.Append("width=400,height=250');")
sb.Append("<")
sb.Append("/")
sb.Append("script>")
RegisterStartupScript("stp", sb.ToString)
End If
 
LHMResult.Text = "<br><b><font color=""green"">Session authorized:</font></b> You may now go to the URL you originally requested: <a target=""_blank"" href=""" & req & """>" & req & "</a>"
 
'Response code 51 - Session Limit Exceeded
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "51"
LHMResult.Text = "<br><b><font color=""red"">Session Limit Reached:</font></b> The maximum number of guest session has been reached. Sorry for the inconvenience. Please close and relaunch your browser to try again."
'Response code 100 - Login Failed.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "100"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> Your session cannot be created at this time. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it
'in the same color as the background, but still show the quiz results.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
</script>
<html>
<head>
<title><%= quizName %> </title>
</head>
<style>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</style>
 
<HTML>
<HEAD>
<TITLE>LHM Quiz Script</TITLE>
</HEAD>
 
<body>
<span id="QuizScreen" runat="server">
<form runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b><%= quizName %> - <%= userName%></b></font></td>
<td><center><img width="216" height="51" src="<%= logo %>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>This quiz has <asp:label id="lblTotalQuestion" runat="server" /> questions</b></font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr>
<td colspan="2">
<b><asp:label id="lblQuestion" runat="server" /></b><br>
<asp:radiobuttonlist id="rblAnswer" RepeatDirection="vertical" TextAlign="right" RepeatLayout="table" runat="server" /><br>
<asp:button id="btnSubmit" class="button" text=" Submit " onClick="btnSubmit_Click" runat="server" />
<asp:requiredfieldvalidator ControlToValidate="rblAnswer" ErrorMessage="Please select an answer" runat="server" />
</td>
</tr>
<tr class="heading">
<td width="70%"><font color="white"><b>Score required to pass <asp:label id="lblPassingScore" runat="server" />%</b></font></td>
<td width="30%" align="right"><font color="white"><b>Time spent <asp:label id="lblTimeSpent" runat="server" /></b></font></td>
</tr>
</table>
</form>
</span>
 
<span id="ResultScreen" runat="server"> <asp:label id="lblResult" runat="server" /> <br>
<asp:Label id=LHMResult runat="server" />
<asp:Label id=catchError runat="server" />
</span>
 
</body>
</html>

PayPal Script

 

Authentication Model

The Guest Client buys 1-hour or 24-hour access with a Buy Now button using their PayPal account. Payment is made through PayPal to the hotspot provider's PayPal merchant account.

Purpose

Nearly everyone who buys or sells on the Internet uses PayPal. It is very easy to setup a buyer account, and to link it to any form of payment (such as credit card, bank card, checking account). I

t is almost equally easy to upgrade a buyer-only account to a merchant account. Having a merchant account allows PayPal users to accept payment from other PayPal users for goods or services. The funds transfer is run through PayPal, providing merchants a way to do business online, accepting any form of payment, without having to setup any sort of complicated payment processing. This eliminates what is perhaps the single biggest obstacle to being a fee-based hotspot provider.

 

Paypal provides a feature called the Buy Now button, which allows for one-click transactions. The buttons are forms, generated with the assistance of PayPal, that contain information about the item or service being purchased. When the buyer clicks on the Buy Now button, the session is redirected to the PayPal site with a querystring containing all the details of the transaction (such as the seller, the item, the price). Rather than using the basic Buy Now button (which is client-side rather than server-side code), the PayPal script uses a custom, server-side Buy Now routine.

 

Also included in the Buy Now redirect is the path for the auto-return. Auto-return is a PayPal feature that sends the buyer back to the merchant's site after the PayPal transaction. Auto-return is required when using PDT (pdtPath, described below).

The custom Buy Now redirect also embeds the LHM sessionID and the mgmtBaseUrl into a custom string in the Buy Now redirect to PayPal. This allows us to track the session even though it leaves the LHM server, goes to PayPal, and then comes back (via auto-return for PDT).

 

The basic PayPal payment system provides notification of payment to merchants by email. This is acceptable for physical goods because the purchase/ship transaction does not have to occur in real-time; the merchant can wait hours or days for the notification before shipping the product. For transactions that require instantaneous delivery, such as buying hotspot access, a more real-time method of payment is required.

 

PayPal offers two methods of payment notification:

Instant Payment Notification (IPN), which works by PayPal making a web-services call to the merchant's site indicating that payment for a particular transaction has cleared. Unfortunately, this does not always occur in real-time (it can take up to 20 minutes for this asynchronous notification to arrive), so it was not employed in this script. (More can be read about IPN at https://www.paypal.com/cgi-bin/webscr?cmd=p/xcl/rec/ipn-intro-outside)

 

Payment Data Transfer (PDT: see http://www.paypal.com/cgi-bin/webscr?cmd=p/xcl/rec/pdt-intro-outside). This method occurs in absolute real-time using PayPal's auto-return method. PDT provides instant notification to the merchant of the state of a transaction (either SUCCESS or FAIL), as well as of the payment_status (Completed, Pending, Denied, Failed, Refunded, Reversed, or Cancelled_Reversal). By instantly knowing the status of the transaction and the payment, it is possible to immediately provide service without the risk of losing payment.

myvars Variables

logoutPopup

Controls the use of the logout popup window. Set to:

0 to disable the popup window.
1 to enable the popup window.

 

debugFlag

Sets the debug output for the PayPal PDT transfer:

0 = Off
1 = On

 

pdtPath

The path to which the Guest Client is redirected by the PDT auto-return (described above in the Purpose section).

 

paypalCGI

The URL for the PayPal CGI serving as the gateway for the PayPal transaction. The URL itself should not be changed, but there are two options; either the:

Live (real) PayPal site.
Paypal sandbox (part of the PayPal developer network), which can be used for testing.

 

myBusiness

The email address (how PayPal recognizes the business) of the hotspot provider. This must match the email address of the merchant account that is receiving payment for the transactions.

 

token

The Payment Data Transfer option generates a unique token for each merchant. This is where you specify your PayPal-provided unique token. The token must be correct, or the PDT transaction (not the actual PayPal transaction) fails.

 

itemName1
itemName2

The names of the two access options, such as 1 Hour Secure Internet Access and 24 Hours Secure Internet Access.

 

itemNumber1
itemNumber2

The item number (a mostly arbitrary internal PayPal reference) for the two access options, such as 1hour and 24hour.

 

itemTimer1
itemTimer2

The session timer, in seconds, for the two access options, such as 3600 for 1 hour and 86400 for 24 hours.

 

itemAmount1
itemAmount2

The price in US dollars for the two access options, such as 0.01 (one cent) and 0.02 (two cents). Limited time promotional bargain pricing.

 

itemButton1
itemButton2

The button text for the two access options, such as 1 Hour Access - $0.01 and 24 Hours Access - $0.02.

 

strHmac

The shared secret for the optional HMAC function.

 

hmacType

The digest type to use if HMAC is in use: MD5 or SHA1.

 

logo

The names of the logo (image) file to use on page headers.

Session Flow

1
The Guest Client launches their web-browser, and is redirected by LHM to http://<lhmserver>/paypal/default.aspx, where <lhmserver> is your LHM server.
2
Guest client (buyer) clicks on one of the Buy Now buttons, such as 1 Hour Access - $0.01.
3
The client is redirected to the PayPal site with a querystring containing all the information about the merchant, the item, the LHM session (in the custom variable), and the auto-return URL (defined in myvars as pdtPath).

The pdtPath resides on the LHM server. The path should be the same as the default.aspx path (as configured on the SonicWall security appliance), but should point to the pdt.aspx file. This way, when the PayPal transaction is completed and PayPal redirects the client back to the merchant site, the client is redirected back to the http://<lhmserver>/paypal/pdt.aspx page.

HTTP can be used on the LHM Server because no sensitive information is entered on the LHM server itself; the PayPal transaction occurs via HTTPS directly between the Guest Client and PayPal.

 

Sample Buy Now redirect string:

https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_xclick&business=demo@sonicwall.com&item_name=1%20Hour%20Access&item_number=1hour&amount=0.01&currency_code=USD&lc=US&bn=PP-BuyNowBF&no_note=1&no_shipping=1&cancel_return=http://lhmserverpaypal/default.aspx&return=http://lhmserver/lhm/paypal/pdt.aspx&custom=35378e67833faa3de83aa3b771https%3a%2f%2f172.16.17.1%3a4043%2f

4
The Guest Client logs into PayPal (or creates a new account, as needed) and completes the transaction with PayPal. After the transaction is completed, the client is redirected back to http://<lhmserver>/paypal/pdt.aspx. Included in the redirect is a querystring containing the transaction id (tx), the status (st), the amount (amt), the currency type (cc), the custom value (cm), and an encrypted signature (sig).

Sample redirect string:

http://lhmserver/lhm/paypal/pdt.aspx?tx=4LN76482JF4605045&st=Completed&amt=0.01&cc=USD&cm=35378e67833faa3b771https%3a%2f%2f172%2e16%2e17%2e1%3a4043%2f&sig=qdsNC4flKwtPviggoGAXCpeV9gS%2f2E%2bGGVbTZ3STrUV1Ci9K3c2zTdJMuuKCmRiif1SybsZtUqDYqzzfMg64AF3PKCk85rrPubYT4K4aC

5
The Guest Client accessing the pdt.aspx script at the URL above starts the PDT process on the LHM server. The script builds a querystring consisting on cmd=_notify-synch (indicating that it is a PDT transacation) along with the tx (transaction ID) and the at variable set to the merchant's token (defined in myvars). This is then POSTed to the paypalCGI URL (as defined in myvars).
6
PayPal responds to the POST with a SUCCESS of a FAIL code.
FAIL – the script indicates to the client that the PayPal transaction fails, and they are prompted to seek assistance.

 

SUCCESS – provides details about the transaction:

 

 

SUCCESS
txn_type=web_accept
payment_date=00%3A39%3A48+Oct+30%2C+2005+PDT
last_name=Niqual
item_name=1+Hour+Secure+Internet+Access
payment_gross=0.01
mc_currency=USD
business=lhmdemo%40sonicwall.com
payment_type=instant
payer_status=verified
tax=0.00
payer_email=lhmClient%40sonicwall.com
txn_id=84K306380G150640T
quantity=1
receiver_email=lhmdemo%40sonicwall.com
first_name=Sah
payer_id=XWRZGABD6UV2W
receiver_id=REW4W5WANU294
item_number=1hour
payment_status=Completed
payment_fee=0.01
mc_fee=0.01
shipping=0.00
mc_gross=0.01
custom=35378e67833faa3de833755d3aa3b771https%3A//172.16.17.1%3A4043/
charset=windows-1252

 

7
The script checks the payment_status to make sure the payment is completed. If it is not completed, an incomplete-payment message is provided to the user.
8
If payment_status is completed, the script also obtains the client name, item name, amount, transaction ID, business, and custom variables for generating the client's receipt, a userName for the LHM session, and identifying the LHM sessionID and mgmtBaseUrl.
9
The script presents the PayPal transaction receipt to the Guest Client.
10
The script performs the LHM post to the SonicWall to authorize the session.

Additional Considerations

Requires a PayPal merchant account.

Requires that the PayPal account be setup for auto-return and for PDT (see http://www.paypal.com/cgi-bin/webscr?cmd=p/xcl/rec/pdt-techview-outside)

For testing, it is strongly suggested that a (free) PayPal sandbox account be setup through the PayPal Developer's Network (https://developer.paypal.com) and (https://www.sandbox.paypal.com)

IMPORTANT: Because the Guest Client is redirected directly to the PayPal site, ALL PayPal site IP addresses must be setup on the SonicWall as Allowed Networks on the Guest Services configuration. These include the following:

 

www.paypal.com

64.4.241.32
64.4.241.33
216.113.188.32
216.113.188.35
216.113.188.66
216.113.188.67

 

www.paypalobjects.com

216.113.188.25
64.4.241.62
216.113.188.9

 

www.sandbox.paypal.com

66.135.197.160

 

developer.paypal.com

66.135.197.163
Topics:  
default.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Note: For PayPal authorization to work, it is necessary to set up the PayPal sites (www.paypal.com, www.paypalobjects.com, and www.sandbox.paypal.com) as a bypass network on WGS. This is so that WGS/LHM users can access PayPal directly to complete the payment transactions. This list currently includes the following addresses: [64.4.241.32, 64.4.241.33, 216.113.188.32, 216.113.188.35, 216.113.188.66, 216.113.188.67], [216.113.188.25, 64.4.241.62, 216.113.188.9] and [66.135.197.160].
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/paypal/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim customCode as String
 
Sub Page_Load(src as Object, e as EventArgs)
 
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Set the button Text for the two buttons with the variable configured in myvars
btnBuyNow1.Text=itemButton1
btnBuyNow2.Text=itemButton2
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
Sub btnBuyNow_Click(Sender As Object, E As EventArgs)
 
'sample redirect generated by this routine:
'https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=jlevy@sonicwall.com&item_name=24%20Hour%20Secure%20Internet%20Access&item_number=24hour&amount=0.02&currency_code=USD&lc=US&bn=PP-BuyNowBF&no_note=1&no_shipping=1&cancel_return=http://127.0.0.1/lhm/paypal/default.aspx&return=http://www.moosifer.com/pdt.aspx
 
'sample redirect from the paypal server back the LHM server on transaction completion (modified).
'http://127.0.0.1/lhm/paypal/pdt.aspx?tx=4PG453F7LS133715V&st=Completed&amt=0.02&cc=USD&cm=&sig=EZhZtJygi7RTXulJt4SEhVBRi%2bJwLaC9z9kRLsrsXk4gQKnzvI5vjGy0vdhKPXAVyhbh%2bwBxWon2cieEQDJ9P6R9qqjuKnzvI5vjGy0vdhKPXAVyJ3GtOq5Jd3%2fvTY3s7FrRcKdKnzvI5vjGy0vdhKPXAVyyEKNxY3d
 
Dim str, itemName, itemNumber, itemAmount As String
Dim sb As New StringBuilder()
'Determine which button was pressed, and set item attributes appropriately
Select Case Sender.Text
Case itemButton1
itemName = itemName1
itemNumber = itemNumber1
itemAmount = itemAmount1
Case itemButton2
itemName = itemName2
itemNumber = itemNumber2
itemAmount = itemAmount2
End Select
 
'The paypal CGI URL - You can select either the real CGI or the sandbox CGI in myvars
sb.Append(paypalCGI & "?")
'The cmd passed to PayPal - do not change!
sb.Append("cmd=_xclick")
'The email address of the paypal merchant receiving payment. Replace in myvars with your paypal email address.
sb.Append("&business=" & myBusiness)
'The name of the item being purchased. This is the first item option (e.g. 1 hour). Set in myvars
sb.Append("&item_name=" & itemName)
'The optional item id
sb.Append("&item_number=" & itemNumber)
'The price being charged for the item (access)
sb.Append("&amount=" & itemAmount)
'The currency
sb.Append("&currency_code=USD")
'The country
sb.Append("&lc=US")
'The banana nullifier
sb.Append("&bn=PP-BuyNowBF")
'Disables the note option on the transaction
sb.Append("&no_note=1")
'Disables the shipping option on the transaction
sb.Append("&no_shipping=1")
'Build the path to return the client to (the LHM server address) on a cancelled transaction
sb.Append("&cancel_return=http://" & Request.ServerVariables("SERVER_NAME") & Request.ServerVariables("URL"))
'The return (success page) path to return the buyer to after the transaction. This is the PDT receiver/processor page.
sb.Append("&return=" & pdtPath)
'The LHM sessionID - append this so that it can be returned to us later by the PDT transaction - do not change!
sb.Append("&custom=" & sessionId & Server.URLEncode(mgmtBaseUrl))
'Optional notify_url that paypal will asynchronously send IPN confirmation to. Not used since it's not real-time.
'sb.Append("&notify_url=http://www.moosifer.com/ipn.aspx")
str = sb.ToString
Response.Redirect(str)
 
End Sub
 
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM PayPal Script</TITLE>
</HEAD>
 
<BODY>
<form id="frmValidator" runat="server">
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>LHM Access with PayPal Buy Now</b></font></td>
<td><center><img width="216" height="51" src="<%= logo%>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
 
<tr>
<td colspan=3><br></td>
</tr>
<tr>
<td colspan=3 align="left">Purchase Secure Internet Access through SonicWALL's LHM and PayPal's Buy Now feature.
<br><br>The two Buy Now buttons below will send you to PayPal's website where you can use your PayPal account to pay <b>$<%= itemAmount1 %> for <%= itemName1 %></b>, or <b>$<%= itemAmount2 %> for <%= itemName2 %></b>.
<br><br>
PayPal will then redirect you to this site to initiate the Payment Data Transfer (PDT) exchange. The PDT exchange begins with the LHM server posting a paypal constructed querystring back to paypal. The response to the post will then be parsed by the LHM server to determine if the PayPal transaction was successful. Once all data are exchanged and verified, LHM will authorize access on the SonicWALL for the period of time purchased.
<br><br>
The clock for access will start immediately upon successful session authorization, and can be used on the local SonicWALL appliance by the client (as tracked by IP and MAC address) so long as session time remains. The idle timeout will effectively be disabled by setting the idle timer to the same value as the session timer.
<br><br>
Please select "<%= itemName1 %>" or "<%= itemName2 %>" below. You will be redirected to the PayPal site, and will be returned to this site on transaction completion.
 
<br><br>
</td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td align="center"><asp:Button ID="btnBuyNow1" Class="button" OnClick="btnBuyNow_Click" runat="server" />
&nbsp&nbsp<asp:Button ID="btnBuyNow2" Class="button" OnClick="btnBuyNow_Click" runat="server" /></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr>
<td colspan=3><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td colspan=3><asp:Label id=catchError runat="server"/></td>
</tr>
</table>
 
</form>
</BODY>
</HTML>
logout.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
Dim sessionId as String
Dim mgmtBaseUrl as String
Dim eventId as String = "&eventId=1"
 
'Grab the code and the session lifetime from the generator page
Sub Page_Load(src as Object, e as EventArgs)
sessionId=Request.QueryString("sessId")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
sessTimer=Request.QueryString("sessTimer")
 
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'When the page loads, make the loggedIn span visible
loggedIn.Visible=True
loggedOut.Visible=False
 
Me.Button1.Attributes.Add("OnClick", "self.close()")
 
End Sub
 
'The Logout button
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogoff.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & eventId
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Make the loggedOut span visible
loggedIn.Visible=False
loggedOut.Visible=True
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/LogoffReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 150 - Logout Succeeded
If snwlResponse.SelectSingleNode(codePath).InnerXml = "150"
LHMResult.Text = "<br><b><font color=""green"">Your session has been logged out.<br><br>Thank you for using LHM Guest Services.</font></b>"
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session logout failed:</font></b> The request failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
</script>
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
font-size: 10pt;
background-color:#006699;
}
 
tr.smalltext {
font-size: 8pt;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
font-size: 8pt;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM Logout Page</TITLE>
 
<SCRIPT LANGUAGE="Javascript">
 
//'Javascript Seconds Countdown Timer
var SecondsToCountDown = <%= sessTimer%>;
var originalTime=" ";
 
function CountDown()
{
clockStr="";
 
dayStr=Math.floor(SecondsToCountDown/86400)%100000
if(dayStr>0){
if(dayStr>1){
dayStr+=" days ";
} else dayStr+=" day ";
clockStr=dayStr;
}
hourStr=Math.floor(SecondsToCountDown/3600)%24
if(hourStr>0){
if(hourStr>1){
hourStr+=" hours ";
} else hourStr+=" hour ";
clockStr+=hourStr;
}
minuteStr=Math.floor(SecondsToCountDown/60)%60
if(minuteStr>0){
if(minuteStr>1){
minuteStr+=" minutes ";
} else minuteStr+=" minute ";
clockStr+=minuteStr;
}
secondStr=Math.floor(SecondsToCountDown/1)%60
if(secondStr>0){
if(secondStr>1){
secondStr+=" seconds ";
} else secondStr+=" second ";
clockStr+=secondStr;
}
 
if(SecondsToCountDown > 0)
{
--SecondsToCountDown;
}
 
if(originalTime.length < 2)
{
originalTime = clockStr;
}
 
// Make sure the form is still there before trying to set a value
if(document.frmValidator){
document.frmValidator.originalTime.value = originalTime;
document.frmValidator.countdown.value = clockStr;
}
setTimeout("CountDown()", 1000);
if(SecondsToCountDown == 0)
{
document.frmValidator.countdown.value = "Session Expired";
}
}
 
//'Disable right-click so that the window doesn't get refreshed since the countdown is clientside.
document.oncontextmenu = disableRightClick;
function disableRightClick()
{
return false;
}
 
//'Disable F5 key, too, on IE at least.
function noF5()
{
var key_f5 = 116;
if (key_f5==event.keyCode)
{
event.keyCode=0;
return false;
}
return false;
}
 
document.onkeydown=noF5
document.onmousedown=disableRightClick
 
</SCRIPT>
 
</HEAD>
 
<BODY onload='CountDown()'>
<span id="loggedIn" runat="server">
<form id="frmValidator" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="smalltext"><td><br></td></tr>
<tr class="smalltext">
<td>Original Session Time:</td>
<td><asp:textbox width=250 id="originalTime" runat="server" /></td>
</tr>
<tr class="smalltext">
<td>Remaining Session Time:</td>
<td><asp:textbox width=250 id="countdown" runat="server" /></td>
</tr>
<tr class="smalltext">
<td colspan=2><br>You may use this window to manually logout your session at any time, or you may safely close this window if you prefer to let your session timeout automatically.</font></td>
</td>
<tr>
<td colspan=2><center><asp:button id="btnSubmit" class="button" text=" Logout " onClick="btnSubmit_Click" runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
<span id="loggedOut" runat="server">
<form id="logout" runat="server">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr class="heading">
<td colspan=2 align="center"><font color="white"><b>SonicWALL LHM Logout Window</b></font></td>
</tr>
<tr class="heading">
<td colspan=2 align="center">&nbsp</td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=catchError runat="server" /></td>
</tr>
<tr><td><br></td></tr>
<tr>
<td><center><asp:button id="Button1" class="button" text=" Close " runat="server" /></center></td>
</tr>
</table>
</form>
</span>
 
</BODY>
</HTML>
myvars.aspx
<script language="VB" runat="server">
 
'Set the logoutPopup window flag - 0 = no popup, 1 = popup
'The use of the logoutPopup in this script is discouraged because the login event is exclusive.
Dim logoutPopup as String = "0"
 
'Set the debug flag (0 = off, 1 = on)
Dim debugFlag as String = "0"
 
'Set the path and file for the PDT responder script - this should be the same path as the LHM settings
'configured on the SonicWALL "External Web Server Settings" page, but pointing to the PDT handler script.
'Refer to http://www.paypal.com/cgi-bin/webscr?cmd=p/xcl/rec/pdt-techview-outside for information on PDT
Dim pdtPath as String = "http://10.50.165.2/lhm/paypal/pdt.aspx"
 
'Set the path the PayPal processing CGI. Use the sandbox (https://developer.paypal.com) and (https://www.sandbox.paypal.com) for testing
'Using the sandbox requires a developer network account and login.
Dim paypalCGI as String = "https://www.sandbox.paypal.com/cgi-bin/webscr"
'Dim paypalCGI as String = "https://www.paypal.com/cgi-bin/webscr"
 
'Set the email addres of the paypal merchant account to which payment will be made
'The following is a valid sandbox account, but requires authentication by the parent (real) account.
'You must replace this with you own (real or sandbox account) for use.
Dim myBusiness as String = "lhmdemo@sonicwall.com"
 
'Set this to token from PayPal account. It must be your actual, valid token.
'Refer to http://paypaltech.com/PDTGen/PDTtokenhelp.htm for information on the identity token
'The following is a valid sandbox token, but requires authentication by the parent (real) account.
'You must replace this with you own (real or sandbox token) for use.
Dim token as String = "ucistq6vmKGWPxwJbrTJFDhFq889RxYt_6Mkz_3viraSzjiQJ5iPYCZ5Mdq"
'Set the names for the purchase item options (e.g. 1 hour Access, 3 hours access, etc.)
Dim itemName1 as String = "1 Hour Secure Internet Access"
Dim itemName2 as String = "24 Hours Secure Internet Access"
 
'Set the paypal querystring number for purchase item options (e.g. 1hour, 60mins, itemone, etc.)
Dim itemNumber1 as String = "1hour"
Dim itemNumber2 as String = "24hour"
 
'Set the purchase item options session and idle timers (timers use thesame value since we do not want sessions idling out)
Dim itemTimer1 as String = "3600 "'One hour, in minutes
Dim itemTimer2 as String = "86400 "'24 hours
 
'Set the costs in dollars for purchase item options (e.g. one penny = 0.01, one dollar = 1.00, etc.)
Dim itemAmount1 as String = "0.01"
Dim itemAmount2 as String = "0.02"
 
'Set the button names and descriptions for purchase item options
Dim itemButton1 as String = "1 Hour Access - $0.01"
Dim itemButton2 as String = "24 Hours Access - $0.02"
 
'Set the secret for use with optional HMAC auth, as configured in the Extern Guest Auth config on the SonicWALL
Dim strHmac as String = "password"
 
'Set the digest method for the HMAC, either MD5 or SHA1
Dim hmacType as String = "MD5"
'Dim hmacType as String = "SHA1"
 
'Set the logo image to use
Dim logo as String = "sonicwall.gif"
'------------------------End of Configurable Settings-------------------------
 
</script>
pdt.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Security" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/paypal/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim sessTimer as String
Dim idleTimer as String
Dim userName as String
Dim hmac as String
Dim firstname, lastName, itemName, mcGross, mcCurrency, itemNumber, business, txn, payStatus As String
 
Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
'Use the override class to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
Dim tx, PDTvalidateQuery As String
Dim strResponse As HttpWebResponse
Dim temp As String
Dim PDTArray() As String
Dim iParts, sResults(0, 0), aParts(), sParts(), sKey, sValue, snwlCustom As String
Dim i As Integer
 
'Set tx to value of tx passed in via Querystring from PayPal
tx = Request.QueryString("tx")
 
'Set string = to the cmd value, tx and at that needs to be
'POSTed back to PayPal to validate the PDT
PDTvalidateQuery = "cmd=_notify-synch&tx=" & tx & "&at=" & token
 
'Now we need to POST this info back to PayPal for validation of the PDT
'Create the request back
Dim req As HttpWebRequest = CType(WebRequest.Create(paypalCGI), HttpWebRequest)
 
'Set values for the request back
'set method
req.Method = "POST"
'set content type
req.ContentType = "application/x-www-form-urlencoded"
'set length
req.ContentLength = PDTvalidateQuery.Length
 
'Write the request back to PayPal
Dim stOut As StreamWriter = New StreamWriter(req.GetRequestStream(), Encoding.ASCII)
stOut.Write(PDTvalidateQuery)
stOut.Close()
 
Try
strResponse = CType(req.GetResponse(), HttpWebResponse)
Catch ex As SystemException
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
End Try
 
'Once we write the stream back to PayPal, we need to read the response.
 
Dim IPNResponseStream As Stream = strResponse.GetResponseStream
Dim encode As Encoding = System.Text.Encoding.GetEncoding("utf-8")
Dim readStream As New StreamReader(IPNResponseStream, encode)
 
'Read the response in String variable "temp"
temp = readStream.ReadToEnd
 
'Debug flag, set in myvars - prints the whole output from the POST reply
If debugFlag = "1" Then
OutputEntirePDTString(temp)
End If
 
'Check to see if the 1st line of the response was "SUCCESS"
If Mid(temp, 1, 7) = "SUCCESS" Then
 
'if it is SUCCESS, the code below puts the response in a nice array
temp = Mid(temp, 9)
sParts = Split(temp, vbLf)
iParts = UBound(sParts) - 1
ReDim sResults(iParts, 1)
 
For i = 0 To iParts
 
aParts = Split(sParts(i), "=")
sKey = aParts(0)
sValue = aParts(1)
sResults(i, 0) = sKey
sResults(i, 1) = sValue
 
'You can add more case statements here for other returned variables
 
Try
Select Case sKey
Case "first_name"
firstname = Server.URLDecode(sValue)
Case "last_name"
lastName = Server.URLDecode(sValue)
Case "item_name"
itemName = Server.URLDecode(sValue)
Case "mc_gross"
mcGross = sValue
Case "mc_currency"
mcCurrency = sValue
Case "item_number"
itemNumber = Server.URLDecode(sValue)
Case "business"
business = Server.URLDecode(sValue)
Case "txn_id"
txn = sValue
Case "payment_status"
payStatus = sValue
Case "custom"
snwlCustom = sValue
sessionID = snwlCustom.SubString(0,32)
mgmtBaseUrl=(Server.URLDecode(Mid(snwlCustom,33)))
End Select
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
End Try
 
Next
If payStatus = "Completed" Then
'Transaction Succeeded - Give the Guest a receipt
Dim receipt as String
 
receipt = "<h3>Transaction Succeeded. Thank you for selecting SonicWALL LHM.</h3><br>"
receipt + = "<b>Transaction Invoice:</b><br><br>"
receipt + = "Name: " & firstname & " " & lastName & "<br>"
receipt + = "Description: " & itemName & "<br>"
receipt + = "Amount: " & mcCurrency & " " & mcGross &"<br>"
receipt + = "Paid to: " & business &"<br>"
receipt + = "Transaction ID: " & txn &"<br>"
receipt + = "<br><br>"
 
paypalResult.Text = receipt
LHMResult.Text = "Authorizing your LHM session."
 
'Setup the LHM session variables and call LHM Routine
'Set the session and idle timers to match the variables set in myvars
If itemNumber = itemNumber1 Then
sessTimer=itemTimer1
idleTimer=itemTimer1
Else
sessTimer=itemTimer2
idleTimer=itemTimer2
End If
 
userName = firstname & " " & lastName
 
LHM()
Else
'The transaction itself was a success, but the payment status was not Completed.
paypalResult.Text = "The transaction succeeded, but the payment was not completed. The session cannot be authorized at this time."
End If
 
Else
' If PDT response is not "SUCCESS"
paypalResult.Text = "The PayPal transaction did not succeed. The returned status is: <b>" & temp & "</b>"
End If
 
'Close the streams
readStream.Close()
strResponse.Close()
 
End Sub
 
'This is the parser for the debug function to print the entire resonse to the PDT POST
Private Function OutputEntirePDTString(ByVal myPDTString As String) As String
Dim tempString() As String = Split(myPDTString, vbLf)
Dim x As Integer
For x = 0 To tempString.GetUpperBound(0)
Response.Write(tempString(x) & "<br>")
Next
End Function
 
Sub LHM()
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & Server.URLEncode(userName) & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
 
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length
 
'Set the method for the webrequest to POST
toSNWL.Method = "POST"
 
'Set the content type
toSNWL.ContentType = "application/x-www-form-urlencoded"
 
'Open the request stream
Dim dataStream As Stream = toSNWL.GetRequestStream()
 
'Write the byte array to the request stream
dataStream.Write(byteArray, 0, byteArray.Length)
 
'Close the Stream object
dataStream.Close()
 
'Get the response
Dim snwlReply As WebResponse = toSNWL.GetResponse()
 
'Display the status - looking for 200 = OK.
'Response.Write(CType(snwlReply, HttpWebResponse).StatusCode)
'Grab the response and stuff it into an xml doc for possible review
Dim snwlResponse as XmlDocument = New XmlDocument()
snwlResponse.Load(snwlReply.GetResponseStream())
 
'Set the xPath to the SNWL reply, and get the response
Dim codePath as String = "SonicWALLAccessGatewayParam/AuthenticationReply/ResponseCode"
'Response.Write(snwlResponse.SelectSingleNode(codePath).InnerXml)
'Response code 50 - Login Succeeded
 
If snwlResponse.SelectSingleNode(codePath).InnerXml = "50"
 
'Do we want to provide a logout popup window?
If logoutPopup = "1" Then
'Popup hack using Javascript for logout window
Dim sb As New System.Text.StringBuilder()
sb.Append("<script language='javascript'>")
sb.Append("window.open('logout.aspx?sessId=")
sb.Append(Server.URLEncode(CStr(sessionId)))
sb.Append("&mgmtBaseUrl=")
sb.Append(Server.URLEncode(CStr(mgmtBaseUrl)))
sb.Append("&sessTimer=")
sb.Append(Server.URLEncode(CStr(sessTimer)))
sb.Append("','logOut','toolbar=no,")
sb.Append("addressbar=no,menubar=no,")
sb.Append("width=400,height=250');")
sb.Append("<")
sb.Append("/")
sb.Append("script>")
RegisterStartupScript("stp", sb.ToString)
End If
LHMResult.Text = "<br><b><font color=""green"">Session authorized:</font></b> You may now begin your secure Internet access session."
 
'Response code 51 - Session Limit Exceeded
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "51"
LHMResult.Text = "<br><b><font color=""red"">Session Limit Reached:</font></b> The maximum number of guest session has been reached. Sorry for the inconvenience. Please close and relaunch your browser to try again."
'Response code 100 - Login Failed.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "100"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> Your session cannot be created at this time. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 251 - Bad HMAC.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "251"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed message authentication. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 253 - Invalid SessionID.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "253"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed to match a known session identity. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 254 - Invalid CGI.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "254"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization was missing an essential parameter. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
'Response code 255 - Internal Error.
ElseIf snwlResponse.SelectSingleNode(codePath).InnerXml = "255"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again."
 
End If
 
'Close the streams
dataStream.Close()
snwlReply.Close()
 
'If there is some asp.net error trying to talk to the SonicWALL, print it in the same color as the background.
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
LHMResult.Text = "<br><b><font color=""red"">Session creation failed:</font></b> The request for authorization failed due to an unspecified error. Sorry for the inconvenience. Please close and relaunch your browser to try again. If the problem persists, please notify an attendant."
End Try
End Sub
 
</script>
 
<STYLE>
body {
font-size: 10pt;
font-family: verdana,helvetica,arial,sans-serif;
color:#000000;
background-color:#9CBACE;
}
 
tr.heading {
background-color:#006699;
}
 
.button {
border: 1px solid #000000;
background-color: #ffffff;
}
</STYLE>
 
<HTML>
<HEAD>
<TITLE>LHM PayPal Script</TITLE>
</HEAD>
 
<BODY>
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
<tr class="heading">
<td width="50%" valign="center"><font color="white"><b>LHM Access with PayPal Buy Now</b></font></td>
<td><center><img width="216" height="51" src="<%= logo%>"></center></td>
<td width="50%" align="right" valign="center"><font color="white"><b>Powered by SonicWALL LHM</b>&nbsp</font></td>
</tr>
<tr class="heading">
<td colspan=3 align="center"><font color="white">&nbsp</td>
</tr>
</table>
 
<table width="100%" border="0" cellpadding="2" cellspacing="0">
 
<tr>
<td><br></td>
</tr>
<tr>
<td><asp:Label id=paypalResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=LHMResult runat="server" /></td>
</tr>
<tr>
<td><asp:Label id=catchError runat="server" /></td>
</tr>
</table>
</BODY>
</HTML>

Random Script

 

Authentication Model

The Guest Client enters an algorithmically validated, randomly generated passcode.

Purpose

Traditional passcode authentication requires that a passcode be generated prior to use and stored on the authenticating platform. For example, Wireless Guest Services requires that accounts be generated on the particular SonicWall security appliance on which they are used. The Random script eliminates this dependency by using a salted algorithm to generate and validate passcodes. This means that passcodes never have to be stored anywhere, and as long as the salt is the same, passcodes are completely migratory (that is, they can be used at any site, even against different LHM servers).

 

The practical implication of this is that guest account passcodes can be generated in bulk, distributed, and used at any time in the future. For example, passcodes could be generated (using a particular salt), printed (for example, on certificates, business cards, scratch cards) distributed, and used at any site whose LHM server employs the same algorithmic salt. The passcodes could be given an absolute (rather than relative) expiration date, at which time the salt can be changed to invalidate the expired passcodes.

 

The same way that a common salt can be used to validate a set of passcodes across multiple sites, unique salts can ensure that passcodes generated at one site cannot be used at another with a dissimilar salt; so although a common algorithm is used to generate and validate all passcodes, the addition of the salt to the hash function provides uniqueness as needed.

 

In addition to the default.aspx script is a generator.aspx script, which is where passcodes are generated. Anywhere from 1 to 999 passcodes may be generated at one time. After generation, individual passcodes can be printed or the entire list can be exported to a .csv file.

 

Support was included for two classes of passcodes: 1 hour and 24 hour. Either type of passcode can be generated by the generator script.

 

How the generation algorithm works:

1
Generate a random code (root-passcode) of randChars (integer with a default value of six) characters, as defined in myvars. The character set for the random code generator can be modified within the default.aspx file.
2
The salt (defined in myvars as the salt string) is prefixed to the root-passcode.

 

3
A SHA1 hash is then calculated on the resulting string. Three pairs of characters are then obtained from the hash; for a:
1-hour passcode, the 408 pair are obtained (characters 4,5 + 0,1 + 8,9).
24-hour passcode, the 752 pair are obtained (characters 7,8 + 5,6 + 2,3).
4
The six characters chosen from the hash are then concatenated to root-passcode.
5
The result is the distributable passcode.

 

The validation algorithm works in reverse:

1
Guest client enters their passcode (call this enteredCode).
2
The script grabs the first randChars characters of the entered code (call this root-passcode).
3
The salt is prefixed to the root-passcode, and a SHA1 hash is calculated. The 408 pair of characters are obtained and attached to the root-passcode. The 408 pair is then matched to the enteredCode:
If the 408 pair matches, then it is validated as a 1-hour passcode.
If the 408 pair did not match, then the 752 pair is tried. If this matches the enteredCode, then it is validated as a 24-hour passcode.
If neither matches, then the code is not valid.

After the enteredCode has been validated, the usedcodes.mdb database is queried to see if the code has already been used. If the enteredCode is not found in the database, the LHM session authorization sequence commences, using the MAC address as the userName. After the LHM session is authorized and an acknowledgement has been received by the LHM server, the root-passcode from the enteredCode is written to the usedcodes.mdb database so that it cannot be re-used. When (if) the salt is changed, it is advisable to flush the database.

myvars Variables

logoutPopup

Controls the use of the logout popup window. Set to:

0 to disable the popup window.
1 to enable the popup window.

 

useDB

Controls the use of the used passcode database. If useDB is:

0, then the database is not read from or written to, allowing passcodes to be used repeatedly.
1, then used passcodes are written to the database, and new authentication processes check the database to determine whether the passcodes have already been used.

 

randChars

The number of random characters to include in the root-passcode. The default is six. This results in 12-character passcodes because the hash component always adds an additional six characters.

 

salt

The salt to use in computing the hash. Be sure to use a good salt to prevent unwanted passcode migration/collisions.

 

sessTimer

The session timer in seconds.

 

idleTimer

The idle timer in seconds.

 

strHmac

The shared secret for the optional HMAC function.

 

hmacType

The digest type to use if HMAC is in use: MD5 or SHA1.

 

logo

The name of the logo (image) file to use on page headers.

Session Flow

1
The Guest Client enters their passcode.
2
The passcode is validated using algorithmic validation, described in the Purpose section above.
3
If the code is validated, it is checked for previous use in the usedcodes.mdb database.
4
If it is not present, the LHM session (either 1-hour or 24-hours) is initiated, using the MAC address as the username.
5
After the LHM session is initiated, the script writes the root-passcode to the usedcodes.mdb database so that it cannot be reused.
6
The script performs the LHM post to the SonicWall to authorize the session.

Additional Considerations

Because the script is writing to the database, it is necessary to configure write privileges for the IUSR_MACHINENAME and IWAM_MACHINENAME (or ASPNET) accounts, as described in the I want to use the sample scripts SonicWall provided. What do I need to do to use them?

The generator.aspx script should be located in a secure (publicly inaccessible) area on the web-server.

Topics:  
default.aspx
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDB" %>
<%@ Import Namespace="System.Security" %>
<%@ Import Namespace="System.Security.Cryptography" %>
<%@ Import namespace="System.Security.Cryptography.X509Certificates"%>
 
<!-- #INCLUDE file="myvars.aspx" -->
 
<script language="VB" runat="server">
 
'This class allows SSL certs signed by unknown CAs to be accepted.
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
Public Class acceptAllCerts
Implements System.Net.ICertificatePolicy
Public Function CheckValidationResult(ByVal srvPoint As ServicePoint, _
ByVal cert As X509Certificate, ByVal request As WebRequest, ByVal problem As Integer) _
As Boolean Implements ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
 
'Sample LHM redirect querystring:
'http://127.0.0.1/lhm/random/default.aspx?sessionId=0b712fd83b9f5313db5af1cea6b1004f&ip=10.50.165.231&mac=00:0e:35:bd:c9:37&ufi=0006b11184300&mgmtBaseUrl=https://10.50.165.193:4043/&clientRedirectUrl=https://10.50.165.193:444/&req=http%3A//www.google.com/ig
 
Dim ip as String
Dim sessionId as String
Dim mac as String
Dim ufi as String
Dim mgmtBaseUrl as String
Dim clientRedirectUrl as String
Dim req as String
Dim hmac as String
Dim customCode as String
 
Dim passCode as String
Dim grabCode as String
 
Sub Page_Load(Source as Object, E as EventArgs)
 
LHMResult.Text=""
catchError.Text=""
authResult.Text=""
 
ip=Request.QueryString("ip")
sessionId=Request.QueryString("sessionId")
mac=Request.QueryString("mac")
ufi=Request.QueryString("ufi")
mgmtBaseUrl=Request.QueryString("mgmtBaseUrl")
clientRedirectUrl=Request.QueryString("clientRedirectUrl")
req=Request.QueryString("req")
hmac=Request.QueryString("hmac")
customCode=Request.QueryString("cc")
 
'customCode grabs the "cc=" querystring value sent by the SonicWALL. This allows you to use the same
'page (e.g. this page) for the "Session Expiration" (?cc=2), "Idle Timeout" (?cc=3) and "Max Sessions" (?cc=4) page.
If customCode <> "" Then
Select Case customCode
Case "2"
LHMResult.Text="<br><H3><font color=""red"">Your LHM session has expired. You may try to initiate a new session.</font></H3>"
Case "3"
LHMResult.Text="<br><H3><font color=""red"">You have exceeded your idle timeout. Please log back in.</font></H3>"
Case "4"
LHMResult.Text="<br><H3><font color=""red"">The maximum number of sessions has been reached. Please try again later.</font></H3>"
End Select
End If
 
'Use the override class in myvars.aspx to accept untrusted certificates from the SonicWALL
'This is necessary for the POST to the SonicWALL authorizing the LHM session.
System.Net.ServicePointManager.CertificatePolicy = New acceptAllCerts
 
'Note - the routine below for handling the hmac requires the use of the SonicSSL.dll and libeay.dll libraries.
'The DLL must be copied to the IIS server, and the SonicSSL dll must be registered with "regsvr32 sonicssl.dll"
If hmac <> "" Then
'SonicWALL URL Encode routine is different from Microsoft - this is the SonicWALL method
req=Replace(req,"%","%25")
req=Replace(req,":","%3A")
req=Replace(req," ","%20")
req=Replace(req,"?","%3F")
req=Replace(req,"+","%2B")
req=Replace(req,"&","%26")
req=Replace(req,"=","%3D")
 
Dim strHmacText as String
Dim objCrypto as Object
Dim strHmacGenerated
Dim loginError as String
 
'Initialize the Crypto object
objCrypto = Server.CreateObject("SonicSSL.Crypto")
 
'The text to be encoded
strHmacText = sessionId & ip & mac & ufi & mgmtBaseUrl & clientRedirectUrl & req
 
'Calculate the hash with a key strHmac, the return value is a string converted form the output sha1 binary.
'The hash algorithm (MD5 or SHA1) is configured in myvars and in the Extern Guest Auth config on the SonicWALL
If hmacType = "MD5" Then
strHmacGenerated = objCrypto.hmac_md5(strHmacText, strHmac)
Else
strHmacGenerated = objCrypto.hmac_sha1(strHmacText, strHmac)
End If
 
If strHmacGenerated <> hmac Then
Dim hmacFail as String
hmacFail = "<font color=""red"">The HMAC failed validation. Please notify an attendant.</font><br><br>"
hmacFail+="<font color=""9CBACE"">Received HMAC: " & hmac & "<br>Calculated HMAC: " & strHmacGenerated & "<br>"
hmacFail+="Make sure the digest functions on the SonicWALL and LHM server match.<br>"
hmacFail+="Also make sure the shared secret on the SonicWALL and myvars match</font>"
catchError.Text=hmacFail
End If
End If
 
End Sub
 
sub OnBtnClearClicked (Sender As Object, e As EventArgs)
enteredCode.Text = ""
LHMResult.Text=""
catchError.Text=""
end sub
 
Sub btnSubmit_Click(Sender As Object, E As EventArgs)
 
'The following subroutine validates client provided passcodes.
'The first 6 characters (definable in myars) are grabbed.
'These characters are then run though a SHA1 hash with a salt that is defined in myvars.
 
'3 pairs of substrings are then retrieved from the hash.
'The code is validated if the 3 pairs concatenated to the randChars (defined in myvars) characters consist of the following:
 
'Validating the 4 0 8 pairs (4,5+0,1+8,9 characters) will provide 1 hour of guest access.
'Validating the 7 5 2 pairs (7,8+5,6+2,3 characters) will provide 24 hours of guest access.
 
grabCode = enteredCode.Text.SubString(0,randChars)
 
'Manually compute SHA1 on salt+randomCode, and convert result to base64 - gives stranger output
Dim sha1 As sha1 = sha1.Create()
Dim manualHash As Byte() = sha1.ComputeHash(Encoding.UTF8.GetBytes(salt & grabCode))
Dim hashResult as String = Convert.ToBase64String(manualHash)
 
'Alternatively, use forms hash routine - only provides upper case A-Z + 0-9 output.
'Dim hashResult as String = FormsAuthentication.HashPasswordForStoringInConfigFile(salt & randomCode,"SHA1")
 
'First try to match on 1 hour code
passCode = ""
passCode = grabCode & hashResult.SubString(4, 2)
passCode = passCode & hashResult.SubString(0, 2)
passCode = passCode & hashResult.SubString(8, 2)
If enteredCode.Text = passCode Then
sessTimer = "3600"
authResult.Text="<font color=""green""><b>1 hour code validated.</b></font>"
'Check the used passcode DB if useDB is enabled in myvars.
If useDB = "1" Then
wasItUsed()
End If
Else
'Now try to match on 24 hour code
passCode = ""
passCode = grabCode & hashResult.SubString(7, 2)
passCode = passCode & hashResult.SubString(5, 2)
passCode = passCode & hashResult.SubString(2, 2)
If enteredCode.Text = passCode Then
sessTimer = "86400"
authResult.Text="<font color=""green""><b>24 hour code validated.</b></font>"
'Check the used passcode DB if useDB is enabled in myvars.
If useDB = "1" Then
wasItUsed()
End If
 
Else
authResult.Text="<font color=""Red""><b>Passcode cannot be validated.</b><br>The passcode is case-sensitive.<br>Please try again.</font>"
End if
End If
 
End Sub
 
Sub wasItUsed ()
 
'Check to see if the root (randChars) of the passcode is already in the used database.
Dim strConn as string = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("usedcodes.mdb") & ";"
Dim MySQL as string = "SELECT * From passCodes Where passCode = '" & grabCode & "'"
Dim MyConn as New OleDBConnection (strConn)
Dim cmd as New OleDBCommand (MySQL, MyConn)
Dim objDR As OleDbDataReader
Dim isUsed As Boolean
 
MyConn.Open()
objDR = cmd.ExecuteReader()
isUsed = objDR.Read()
objDR.Close()
MyConn.Close()
 
'If the passcode is not found in the database
if isUsed = False
LHM()
Else
authResult.Text="<font color=""Red""><b>Passcode has already been used.</b><br>Please see an attendant for assistance.</font>"
End If
 
End Sub
 
Sub writeToDB ()
 
'Try to write the submitted (only randChars characters instead of the whole passcode) info to the database file
Try
Dim strConn as string = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & server.mappath("usedcodes.mdb") & ";"
Dim MySQL as string = "INSERT INTO passCodes (passCode) VALUES ('" & grabCode & "')"
Dim MyConn as New OleDBConnection (strConn)
Dim cmd as New OleDBCommand (MySQL, MyConn)
MyConn.Open ()
cmd.ExecuteNonQuery ()
MyConn.Close ()
Catch ex as Exception
catchError.Text = "<font color=""9CBACE"">" & ex.ToString & "</font>"
End Try
 
End Sub
 
Sub LHM()
 
'The writeToDB sub is in the Response code 50 - Login Succeeded routine, after the LHM exchange succeeds. You may move it to the top to write the passcode to the DB before the LHM transaction for testing purposes.
'writeToDB ()
 
enteredCode.Text = "Code Accepted."
 
'Let the user know that we are setting up the session, just in case it takes more than a second
LHMResult.Text = "Authorizing session. Please wait."
 
'The LHM cgi on the SonicWALL - this does not change
Dim loginCgi as String = "externalGuestLogin.cgi"
'Assemble the data to post back to the SonicWALL to authorize the LHM session
Dim loginParams as String = "sessId=" & sessionId & "&userName=" & mac & "&sessionLifetime=" & sessTimer & "&idleTimeout=" & idleTimer
'Combine mgmtBaseUrl from the original redirect with the login cgi
Dim postToSNWL as String = mgmtBaseUrl & loginCgi
 
'Convert the loginParams to a well behaved byte array
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(loginParams)
Try
'Create the webrequest to the SonicWALL
Dim toSNWL as WebRequest = WebRequest.Create(postToSNWL)
 
'Calculate the length of the byte array
toSNWL.ContentLength = byteArray.Length