Skip navigation
All People > SungHoon_Kim > Sung Hoon Kim's Blog > 2016 > March
2016
SungHoon_Kim

Adding CRL to CDS

Posted by SungHoon_Kim Employee Mar 29, 2016

While trying to import a CRL via SiteMinder AdminUI, getting the following exception.

(Before proceeding, the prerequisite is to import the Issuer certificate(CA) first. Following screenshot shows "geotrust" certificate is already imported as Trusted CA.)

 

CRL3.jpg

CRL1.jpg

 

server.log from AdminUI

2016-03-29 10:52:05,791 INFO  [com.ca.CertificateDataStore] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-7) Logging initialized

2016-03-29 11:12:13,422 INFO  [STDOUT] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-2) NavigationUtil.handleNavChange returning: fmCRLImport

2016-03-29 11:12:44,703 INFO  [STDOUT] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-2) NavigationUtil.handleNavChange returning: fmCRLList

2016-03-29 11:16:45,182 ERROR [ims.ui] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-2) Page cannot be found.  Please check the URL. (/iam/siteminder/console/ui7/nullback_month_2.png)

2016-03-29 11:16:45,185 ERROR [ims.ui] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-2) Page cannot be found.  Please check the URL. (/iam/siteminder/console/ui7/nullforward_month_2.png)

2016-03-29 11:16:45,189 ERROR [ims.ui] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-5) Page cannot be found.  Please check the URL. (/iam/siteminder/console/ui7/nullportlet16x16del.png)

2016-03-29 11:16:45,283 ERROR [ims.ui] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-2) Page cannot be found.  Please check the URL. (/iam/siteminder/console/ui7/nullback_month_2.png)

2016-03-29 11:16:52,100 INFO  [STDOUT] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-4) NavigationUtil.handleNavChange returning: fmCertImport

2016-03-29 11:17:56,418 INFO  [STDOUT] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-5) NavigationUtil.handleNavChange returning: fmAuthorityList

2016-03-29 11:18:25,407 INFO  [STDOUT] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-5) NavigationUtil.handleNavChange returning: fmCRLImport

2016-03-29 11:20:22,929 ERROR [com.ca.federation.adminui.backingbean.keystore.CRLImportBean] (http-TESTMC1.sso.lab%2F192.168.0.1-8443-5) **ERROR** java.security.cert.CertStoreException during UI operation.

java.security.cert.CertStoreException: java.lang.IllegalArgumentException: Invalid URI for CRL: http://crl.geotrust.com/crls/gtglobal.crl

  at com.ca.siteminder.security.SMCertDatabaseStore.addCRL(SMCertDatabaseStore.java:202)

  at com.ca.siteminder.security.SMCertDatabaseStore.engineGetCRLs(SMCertDatabaseStore.java:119)

  at java.security.cert.CertStore.getCRLs(CertStore.java:154)

  at com.ca.federation.adminui.backingbean.keystore.CRLImportBean.importCRL(CRLImportBean.java:285)

  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

  at java.lang.reflect.Method.invoke(Method.java:597)

  at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:132)

  at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:61)

  at javax.faces.component.UICommand.broadcast(UICommand.java:109)

  at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:97)

  at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:171)

  at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)

  at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:95)

  at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:70)

  at com.netegrity.webapp.page.jsf.JSFParentPage.update(JSFParentPage.java:94)

  at com.netegrity.webapp.page.TaskController.update(TaskController.java:601)

  at com.netegrity.taglib.skin.TagUtilLocal.update(TagUtilLocal.java:268)

  at com.netegrity.taglib.skin.UpdateTag.doEndTag(UpdateTag.java:145)

  at idm_jsp.app.ui7.index_jsp._jspx_meth_skin_update_0(Unknown Source)

  at idm_jsp.app.ui7.index_jsp._jspService(Unknown Source)

  at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)

  at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:638)

  at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:444)

  at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:382)

  at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:310)

  at com.netegrity.webapp.filter.ConsolePageFilter.doFilter(ConsolePageFilter.java:531)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at com.netegrity.webapp.page.jsf.FacesFilter.doFilter2(FacesFilter.java:180)

  at com.netegrity.webapp.page.jsf.FacesFilter.doFilter(FacesFilter.java:151)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:147)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at com.netegrity.webapp.authentication.FrameworkLoginFilter.doFilter(FrameworkLoginFilter.java:322)

  at com.ca.siteminder.webadmin.configuration.ui.servlet.SiteMinderLoginFilter.doFilter(SiteMinderLoginFilter.java:457)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at com.netegrity.webapp.filter.LocaleFilter.doFilter(LocaleFilter.java:100)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at com.netegrity.webapp.filter.SessionFilter.doFilter(SessionFilter.java:103)

  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)

  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

  at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)

  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)

  at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)

  at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)

  at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)

  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

  at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)

  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)

  at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)

  at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)

  at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)

  at java.lang.Thread.run(Thread.java:662)

Caused by: java.lang.IllegalArgumentException: Invalid URI for CRL: http://crl.geotrust.com/crls/gtglobal.crl

  at com.ca.siteminder.security.SMKeyDatabaseFacade.addRevocationInfoToDB(SMKeyDatabaseFacade.java:388)

  at com.ca.siteminder.security.SMCertDatabaseStore.addCRL(SMCertDatabaseStore.java:163)

  ... 65 more

 

If you look at the first screenshot above, it actually explains there are 2 options for importing CRL.

1. LDAP based URL ("LDAP://<server>/<path to crl>", for example "LDAP://crlserver:9100/cn=MasterCRL")

2. FILE based URL ("file:///<file path on the Policy Server machine>", for example "file://C:/CRLs/MasterCRL.crl")

 

It does not list HTTP based URL as an option.

So, if you entered the location as "http://crl.geotrust.com/crls/gtglobal.crl" then it is expected to throw an error.

 

Following is a sample import using FILE based URL.

In this sample, the the CRL file is downloaded to Policy Server machine and stored at "C:\revocation\gtglobal.crl" as below.

CRL8_177.jpg

CRL6.jpg

 

CRL7.jpg

 

Following is R12.52SP1 online documentation explaining the feature.

Check Certificate Validity with CRLs

Check Certificate Validity with CRLs

Check Certificate Validity with CRLs

A Certificate Revocation List (CRL) is issued by a Certificate Authority to its subscribers. The list contains serial numbers of certificates that are invalid or have been revoked. When a request to access a server is received, the server allows or denies access based on the CRL.

Federation can leverage CRLs for its certificate functions. For CA SiteMinder® to use a CRL, the certificate data store must point to a current CRL. If CA SiteMinder® tries using a revoked partner certificate, you see an error message. For legacy federation, the error message is in the SAML assertion. The message indicates that authentication failed.

Note: Federation features implement the use of CRLs differently than X.509 authentication schemes. The authentication schemes use an independent LDAP directory that stores CRLs. The authentication schemes do not use the certificate data store.

CA SiteMinder® supports the following CRL features:

  • File-based CRLs or LDAP CRLs

CA SiteMinder® stores CRLs in the certificate data store. File-based CRLs must be in Base64 or binary encoding. LDAP CRLs must be in binary encoding. Additionally, LDAP CRLs must include CRL data in one of the following attributes:

  • certificateRevocationList;binary
  • authorityRevocationList;binary

When a Certificate Authority publishes an LDAP CRL, it must return the CRL data in binary format, in accordance with RFC4522 and RFC4523. Otherwise, CA SiteMinder® cannot use it.

  • PEM and DER encoding formats for a file CRL
  • DER encoding format for an LDAP CRL

CA SiteMinder® does not validate an SSL server certificate against a CRL. The web server where the CA SiteMinder® web agent is installed manages the SSL server certificate.You are not required to have a CRL for each root CA in the system. If there is no CRL for the root CA, it is assumed that all certificates signed by that CA are trusted certificates.

Add a CRL for Certificate Management

Help ensure that only valid certificates are used for PKI functions by using CRLs. Verify the validity of certificates against a CRL.Important! CA SiteMinder® explicitly requests LDAP CRLs in binary encoding. Additionally, CRL data must be stored in the LDAP attribute named certificateRevocationList;binary or authorityRevocationList;binary. When a Certificate Authority (CA) publishes an LDAP CRL, it must return the CRL data in binary format, in accordance with RFC4522 and RFC4523. Otherwise, CA SiteMinder® cannot use it.The CRL location is required to use a CRL.Follow these steps:

  1. Log in to the Administrative UI.
  2. Select Infrastructure, X509 Certificate Management, Certificate Validity.
  3. Click Add.The Configure Revocation List dialog opens.
  4. Specify an alias for the CRL and the location (URL) of the certificate revocation list.The location has to be a file path for a file CRL and an LDAP search path for an LDAP CRL.
  5. Click Save.

The CRL is added to the certificate data store.

Update a CRL

Update a CRL to verify that the certificate data in use is current.Follow these steps:

  1. Log in to the Administrative UI.
  2. Select Infrastructure, X509 Certificate Management, Certificate Validity.
  3. Delete a CRL from the list.
  4. Do one of the following steps to add a CRL:
    • Click Add and complete the settings for the new CRL file or LDAP location. Click Save.
    • Navigate back to the Certificate Management dialog. Specify a value for the Default CRL Update Period setting. At the time of the next CRL update, the certificate data store automatically goes to the configured file or LDAP location and reloads the CRL.

 

In case if it is LDAP based, it could be upto date(for example, the Microsoft Certificate Services maintains the CRL itself) but if it is FILE based then it would mean the administrator must replace the CRL file in the same filepath manually each time (before the expiry days it was defined while importing the file crl).

 

How to check when this certificate will be updated next?

If you are logged on to AdminUI, it will be displayed as the screenshot above.

But if you need to check from command-line, you can do the same via XPSExplorer.

 

Logon to the Policy Server machine as smuser(or whichever user you run siteminder).

Run XPSExplorer.

 

Look for "CA --> CDS --> CRLRevocationData*".

In the above case, it is number 4.

Enter "4" and press "ENTER" key.

Enter "S" and press "ENTER" key to search the entries.

Now, you can see there is 1 entry.

Enter the entry number "1" and press "ENTER".

 

Here you can see the "ThisUpdate" timestamp and "NextUpdate" timestamp.

This is unix time(epoch).

 

You need to convert this timestamp.

You can google any unix time converter and following is a sample site http://www.epochconverter.com

The Unix Timestamp above, please remove the last 3 digits which would become "1467280294"

 

 

And you can also add the CRL from command-line as well.

If you run "smkeytool" without any switch, it will give you the following options.

The syntax would be:
smkeytool -addRevocationInfo -issueralias geotrust -type filecrl -location C:\revocation\gtglobal.crl -gracePeriod 90

addrevocationinfo

C:\Users\policyserver>smkeytool -addrevocationinfo -issueralias geotrust -type filecrl -location C:\revocation\gtglobal.crl -graceperiod 90

No certificates will be revoked if the CRL is added.

Do you still want to add the CRL information? [no]:

yes

Revocation Info successfully added to the Certificate Data Store.

When you create an LDAP userstore definition in AdminUI, there is a button to "View Contents".

What ldap query does it actually send?

It will make the following queries which I put in to a batch script.

So, simply by running the script(with little modification to match your env) you will get the same content.

 

The blue colour below are what you need to modify to match your configuration.

The red colour and the queries made by the "View Contents" button.

This script only displays the count of entries from each query but if you want to view the actual content you can remove the "|findstr matches" from each query line.

 

viewcontent.bat

@echo off

 

 

SET ADMIN_NAME=CN=diradmin,CN=Admins,CN=Configuration,CN={3CCD2B77-4A30-48ED-A244-10295CDF5E63}

SET ADMIN_PWD=DefaultP@ssw0rd

SET SERVER_NAME=localhost

SET SERVER_PORT=389

SET SEARCH_BASE="DC=SSO,DC=LAB"

SET SEARCH_TIMELIMIT=30

SET MAX_HOPS=10

SET SEARCH_SIZELIMIT=-1

SET SEARCH_SCOPE=sub

 

 

 

 

 

 

echo =====================================================================

echo.

echo Connecting to %SERVER_NAME%:%SERVER_PORT%

echo BaseDN: %SEARCH_BASE%

echo SEARCH TIMEOUT: %SEARCH_TIMELIMIT% sec

echo SEARCH SIZE LIMIT: %SEARCH_SIZELIMIT%

echo SEARCH SCOPE: %SEARCH_SCOPE%

echo MAX HOP: %MAX_HOPS%

echo.

echo =====================================================================

echo       View Content of LDAP userdirectory using objectClass

echo =====================================================================

echo Searching for (objectclass=organization)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectclass=organization) |findstr matches

echo =====================================================================

echo Searching for (objectclass=organizationalunit)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectclass=organizationalunit) |findstr matches

echo =====================================================================

echo Searching for (objectclass=groupOfNames)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectclass=groupOfNames)  |findstr matches

echo =====================================================================

echo Searching for (objectclass=groupOfUniqueNames)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectclass=groupOfUniqueNames)  |findstr matches

echo =====================================================================

echo Searching for (objectclass=group)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectclass=group)  |findstr matches

 

 

echo =====================================================================

echo       View Content of LDAP userdirectory using objectCategory

echo =====================================================================

echo Searching for (objectcategory=organization)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectcategory=organization)  |findstr matches

echo =====================================================================

echo Searching for (objectcategory=organizationalunit)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectcategory=organizationalunit)  |findstr matches

echo =====================================================================

echo Searching for (objectcategory=groupOfNames)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectcategory=groupOfNames)  |findstr matches

echo =====================================================================

echo Searching for (objectcategory=groupOfUniqueNames)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectcategory=groupOfUniqueNames)  |findstr matches

echo =====================================================================

echo Searching for (objectcategory=group)

ldapsearch -b %SEARCH_BASE% -h %SERVER_NAME% -p %SERVER_PORT% -D %ADMIN_NAME% -w %ADMIN_PWD% -O %MAX_HOPS% -l %SEARCH_TIMELIMIT% -z %SEARCH_SIZELIMIT% -s %SEARCH_SCOPE% -v (objectcategory=group)  |findstr matches

 

 

 

pause

 

The other 5 queries I put in the script is using "objectCategory" instead of "objectClass".

In case if you enabled "EnableObjectCategory=1" registry on your Policy Server, it will actually use objectCategory.

This is useful when you are using AD userstore because objectclass is not indexed by default but objectCategory is.

So, the query can get response quicker.

The 5 objectCategory searches are added for your reference in case if your AD is actually slowing down.

Running this script will allow you to compare the response time.

While trying to reproduce customer's issues, at times we need to create a userstore and populate lots of users, groups, OUs and etc.

In order to make things easier, I did have to write a script to perform this and also remove them when needed.

 

In the following sample, this script will create users under "OU=People,DC=SSO,DC=LAB".

You need to ensure this OU exist before running the script.

 

CreateUsers_adlds.vbs

Const SERVER = "localhost:389"

Const ROOT = "OU=People,dc=SSO,dc=LAB"

LDAPPATH = "LDAP://" & SERVER

WScript.Echo "Connecting to ADAM instance..."

set oTopContainer = GetObject(LDAPPATH & "/" & ROOT)

WScript.Echo "LDAP Server: " &LDAPPATH & newLine

 

 

 

 

Const ADS_PROPERTY_APPEND = 3

Dim objRoot, objDomain, objOU, objOUsub, objGroup, objUser

Dim ouNo, groupNo, userNo, ouSubNo

Dim defaultPassword

defaultPassword = "defaultP@ssw0rd"

Dim ouCounter

ouCounter = 0

Dim ouSubCounter

ouSubCounter = 0

Dim groupCounter

groupCounter = 0

Dim userCounter

userCounter = 0

 

 

 

 

set objDomain = oTopContainer

WScript.Echo "Click to start creating Users"

 

 

For ouNo = 1 To 100

On Error Resume Next

Set objOU=objDomain.Create("organizationalUnit", "OU=OU" & ouNo)

objOU.Put "Description", "Sample Users for OU" & ouNo

objOU.SetInfo

ouCounter = ouCounter +1

 

 

    For groupNo = 1 To 100

    On Error Resume Next

    Set objGroup = objOU.Create("Group", "cn=OU" & ouNo & "Group" & groupNo)

    objGroup.Put "CN", "OU" & ouNo & "Group" & groupNo

    objGroup.SetInfo

    groupCounter = groupCounter +1

        For userNo = 1 To 100

        On Error Resume Next

        Set objUser = objOU.Create("User", "cn=" & "OU" & ouNo & "Group" & groupNo & "User" & userNo)

        objUser.Put "CN", "OU" & ouNo & "Group" & groupNo & "User" & userNo

        objUser.Put "sn", "OU" & ouNo & "Group" & groupNo

        objUser.Put "givenName", "User" & userNo

        objUser.Put "name", "OU" & ouNo & "Group" & groupNo & "User" & userNo

        objUser.Put "msDS-UserAccountDisabled", "FALSE"

        objUser.SetInfo

        userCounter = userCounter +1

 

 

        objUser.SetPassword defaultPassword

        objUser.AccountDisabled = False

        objUser.SetInfo

 

 

        objGroup.PutEx ADS_PROPERTY_APPEND, "member", _   

        Array("cn=" & "OU" & ouNo & "Group" & groupNo & "User" & userNo & ",OU=OU" & ouNo & "," & objRoot.Get("defaultNamingContext"))

        objGroup.SetInfo

        Next

    Next

Next

WScript.Echo ouCounter & " OUs Created. " & groupCounter & " groups created with total of " & userCounter & " users."

 

DeleteUsers_adlds.vbs

Const SERVER = "localhost:389"

Const ROOT = "OU=People,DC=SSO,DC=LAB"

LDAPPATH = "LDAP://" & SERVER

WScript.Echo "Connecting to ADAM instance..."

set oTopContainer = GetObject(LDAPPATH & "/" & ROOT)

WScript.Echo "LDAP Server: " &LDAPPATH & newLine

 

 

 

 

 

 

'Option Explicit

Const ADS_PROPERTY_APPEND = 3

Dim objRoot, objDomain, objOU, objOUsub, objGroup, objUser

Dim ouNo, groupNo, userNo, ouSubNo

 

Dim ouCounter

ouCounter = 0

Dim groupCounter

groupCounter = 0

Dim userCounter

userCounter = 0

Dim ouBaseName

ouBaseName = "OU"

 

 

 

 

set objDomain = oTopContainer

WScript.Echo "Click to start deleting Users"

 

 

For ouNo = 1 To 100

On Error Resume Next

Set objOU=GetObject(LDAPPATH & "/" & "OU=" & ouBaseName & ouNo & "," & ROOT)

 

 

    For groupNo = 1 To 100

    On Error Resume Next

        For userNo = 1 To 100

        On Error Resume Next

        objOU.Delete "User", "cn=" & ouBaseName & ouNo & "Group" & groupNo & "User" & userNo

        userCounter = userCounter +1

        Next

    objOU.Delete "Group", "cn=" & ouBaseName & ouNo & "Group" & groupNo

    groupCounter = groupCounter +1

    Next

 

 

objDomain.Delete "OrganizationalUnit", "OU=" & ouBaseName & ouNo

ouCounter = ouCounter +1

Next

 

 

WScript.Echo ouCounter & " OUs, " & groupCounter & " groups and " & userCounter & " users removed."

 

Hope it helps.

The common configuration for SSO Authentication Binding is HTTP-Redirect (redirect to  http://server.domain/affwebservices/public/saml2sso with SAMLRequest query parameter).

But this poses a problem when your SAMLRequest is huge.

 

So, customer would like to use POST method for SSO Binding.

 

Here is a quick sample on how things will work.

 

First, the configuration: This is assuming you are using CA SSO for both IDP and SP.

In this sample, both the IDP and SP are running on the same machine so I have created the entities as below.

 

 

For IDP (Entity Name):

Local SAML2 IDP: idp    (EntityID is idp)

Remote SAML2 SP: sp   (EntityID is sp)

 

For SP (Entity Name):

Local SAML2 SP: sp2   (EntityID is sp)

Remote SAML2 IDP: idp2   (EntityID is idp)

 

 

And the Partnerships are created as below.

There are 2 Partnerships created as both are running on the same box.

 

idp2sp Partnership is configured as below.

index.png

 

And the sp2idp Partnership is configured as below.

sp2idp2.png

 

To note, I have configured AuthnRequest to be signed.

 

Now, when you make an AuthnRequest(SP Initiated) request by visiting "http://www.partner.lab/affwebservices/public/saml2authenrequest?ProviderID=idp" you will find the POST request going to "http://www.sso.lab/affwebservices/public/saml2sso"

 

To let you know the requirement for SSO POST Binding, you must configure a Session Server.

 

If you are familiar with CA SSO(SiteMinder), you would know about Post Preservation.

That is when you POST a data to a protected site without a valid session.

The target agent protecting the resource will preserve the POSTDATA and POST the encrypted POSTDATA to the login page.

The POST method must continue(even when you have a cookieprovider) and the same POST request must be replayed at the target after getting a valid session.

 

But /affwebservices/public/saml2sso is NOT a protected resource.

 

What happens is, the POST data is stored in the Session Server and the GUID to reference the data will be set as a cookie(cookie name is GUID).

Then the browser is HTTP 302 redirected to the AuthenticationURL(/siteminderagent/redirectjsp/redirect.jsp) which is protected.

And again HTPT 302 redirect to the login page.

So, this redirect continues until you are redirected back to saml2sso and it would be a GET request instead of POST.

 

Now that the request was a GET but it carries GUID cookie which has reference to the SAMLDATA stored in the Session Server so that gets called and the processing continues.

 

Following is a screenshot where AuthnRequest was made and redirected to the login page.

You can see in frame #4 where there is a POST to IDP's saml2sso application.

 

Request

POST http://www.sso.lab/affwebservices/public/saml2sso HTTP/1.1

Accept: image/jpeg, image/gif, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*

Referer: http://www.partner.lab/affwebservices/public/saml2authnrequest?ProviderID=idp

Accept-Language: en-US

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729)

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

Connection: Keep-Alive

Content-Length: 2861

DNT: 1

Host: www.sso.lab

Pragma: no-cache

 

ForceAuthn=false&IsPassive=false&SAMLRequest=PEF1dGh<TRIMMED>&Oid=21-7dbd8f60-d540-468a-bc2e-6d6f0810eb64&RelayState=49f7dcd0e68307e51528596923536a2c1a337486

 

If you look at the POSTDATA, it has the following.

ForceAuthn=false

IsPassive=false

SAMLRequest=XXXXXXXX

Oid=21-7dbd8f60-d540-468a-bc2e-6d6f0810eb64

RelayState=49f7dcd0e68307e51528596923536a2c1a337486

 

And the Response is as below.

The GUID cookie is being set and the value is actually same as the TransactionID for this request.

So, if you look for this GUID  value (minus the leading "1:" ) you will find matching transactions in the log.

Response

HTTP/1.1 302 Moved temporarily

Content-Type: text/xml

Location: http://www.sso.lab/affwebservices/redirectjsp/redirect.jsp?SMPORTALURL=http%3A%2F%2Fwww.sso.lab%2Faffwebservices%2Fpublic%2Fsaml2sso&SAMLTRANSACTIONID=1520386c-5ac406e5-0130cd24-96b979ec-3db0303d-0710

Server: Microsoft-IIS/7.5

X-Powered-By: ServletExec/6.0, Servlet/2.5, JSP/2.1

Set-Cookie: GUID=1:2302ab97-b89c424d-e824fc5c-9f983898-e2b51615-9c9; expires=Wed, 16-Mar-2016 06:09:28 GMT; path=/; domain=.sso.lab

X-Powered-By: ASP.NET

Date: Wed, 16 Mar 2016 06:06:28 GMT

Connection: close

Content-Length: 511

 

<html><head><title>Redirection</title></head><body>The document has been moved to <a href='http://www.sso.lab/affwebservices/redirectjsp/redirect.jsp?SMPORTALURL=http%3A%2F%2Fwww.sso.lab%2Faffwebservices%2Fpublic%2Fsaml2sso&SAMLTRANSACTIONID=1520386c-5ac406e5-0130cd24-96b979ec-3db0303d-0710'>http://www.sso.lab/affwebservices/redirectjsp/redirect.jsp?SMPORTALURL=http%3A%2F%2Fwww.sso.lab%2Faffwebservices%2Fpublic%2Fsaml2sso&SAMLTRANSACTIONID=1520386c-5ac406e5-0130cd24-96b979ec-3db0303d-0710</a></body></html>

 

 

I am attaching "IDP_FWSTrace.log" matching the above transaction and the "samplePOST.saz" fiddler trace sample for your reference.

They are in the "samplefiles.zip" file.

Web Agent is not able to handshake with Policy Server.

Then following information will help you to capture the necessary data to troubleshoot.

 

Basic INFO

IP 10.0.0.1 is Policy Server

IP 10.0.0.2 is WA1

 

HCO Name: hco

ACO Name: aco

TrustedHostName: trustme

 

Policy Server has multiple IP address(to simulate multiple Policy Server environment) which are:

 

PS1: 10.0.0.11

PS2: 10.0.0.12

PS3: 10.0.0.13

 

SmHost.conf file lists following IP.

policyserver="10.0.0.3,44441,44442,44443"

policyserver="10.0.0.1,44441,44442,44443"

 

HCO has a cluster and have following IPs.

  1. 10.0.0.11
  2. 10.0.0.12
  3. 10.0.0.13

 

This will make it easier to track which request was for bootstrap and which one was for agent requests from users.

 

Run wireshark on PS and use "tcp.port == 44443" filter to display only the WebAgent related traffic.

 

Do the same at the WebAgent machine.

Use "tcp.port == 44443" filter to display only the Web Agent related traffic.

 

Once sufficient data is captured, stop capturing network trace from both PS and WA side.

At Wireshark, click on "Edit ==> Mark All Displayed Packets" highlighted below in yellow.

 

Now that the traffic is selected, goto "File ==> Export Specified Packets…"

 

This will export only the packets that are displayed and selected.

So, no other traffic are exported. This is useful if customer is concerned about what data is being exported and if there are any sensitive information that is being exposed. (YES, IP ADDRESSES ARE REVEALED!)

 

Export the captured traffic.

In this sample, it is saved as "TestPSnetwork", the extension will be added automatically.

Double click on the file to open from wireshark.

 

Without any filter used, the whole traffic in that capture file was 174 because only those were exported.

 

Same goes to the network captured at the Web Agent side.

It has only 188 frames without using any filter.

 

Now, to see what is being communicated, all the data are encrypted with sharedsecret in the SmHost.conf file so it cannot be decrypted.

However, there is one information that is not encrypted. It is the "Trusted Host Name".

If you look at the frame 4 above, 10.0.0.2(WA) is pushing data to 10.0.0.1(PS in SmHost.conf) and you can see "trustme" trusted host name.

 

Policy Server acknowledge and push some data to WA.

It is all encrypted so we will not know what data it is but can assume it is doing siteminder handshake to establish the encrypted tunnel.

 

Then back and forth there are communications and should be downloading HCO.

Once the WebAgent has handshaked with Policy Server in SmHost.conf and downloaded the HCO, it will disconnect the connection.

 

You can see that from frame #12. You can also confirm that the port 49286 was used for contacting the Policy Server.

So, there was only 1 connection to the Policy server.

 

Then WebAgent connects to 10.0.0.11(PS1 in HCO) at frame #13.

Because the HCO lists 3 policy servers, WebAgent need to try connecting to all 3 Policy Servers.

You can see frame #13 is connection to PS1, #16 is to PS2 and #19 is to PS3.

WebAgent used Port 49287, 49288 and 49289 to attempt that connection.

 

At frame #22, WebAgent is performing 1st sharedsecret handshake with PS1.

You can see the trusted host name.

After that handshake was successful, webagent creates another connection to PS1 and is using port 49290 at frame #28.

Frame #31 shows webagent handshaking with PS1 for the 2nd connection and sending trustedhostname.

 

The reason being, the HCO said New Socket Step is 2. So, when WebAgent need to create new connections, it will have to create 2 connections each time.

Same is repeated for PS2 and PS3.

 

 

By default, wireshark displays the time in elapsed format.

Meaning, the first frame will be starting from 0 and all the subsequent frames will display the time spent from the first frame.

 

You need to change it to display the "Year/Month/Day Hour:Minute:Second" format.

 

To do so, goto "View ==> Time Display Format ==> Date and Time of Day" as highlighted below.

 

Then it will display the time as below.

This timestamp can be matched with your webagenttrace.log and smtracedefault.log to determine what is going wrong when the handshake is failing.

 

SiteMinder logs themselves will not be meaningful without the network trace.

(You will need to run "smpolicysrv -stats" at every minute to get statistic on the load changes and need to enable smtracedefault.log to get some more information if policy server was getting unexpected requests or if it had other problems while trying to handle agent requests).

 

If your environment has handshake issues, then try comparing with the sample network trace demonstrated here.

Better way is to capture your own working handshake use case from your environment and then compare it with the not-working use case.

 

If you see any "TCP Re-Transmission", then try to see if there are any ACK going missing or firewall blocking those or dropped packets.

 

Your network administrator should be able to give you statistics on the network health and also the traffic load changes between specific servers(WA to PS, PS to UserStore and etc) that might have caused a bottleneck causing unexpected behaviours such as taking longer time to handshake.

 

 

 

Sample logging options below.

 

smps.log ==> run "smpolicysrv - stats" every minute

smtracedefault.log ==> minimum you will need the following 3 lines.

components: AgentFunc/Init, AgentFunc/UnInit, AgentFunc/Tunnel, AgentFunc/GetConfig, AgentFunc/DoManagement, Server/Connection_Management, Server/Policy_Server_General, Tunnel_Service

data: Date, PreciseTime, Pid, Tid, SrcFile, Function, IPAddr, IPPort, Message, ClusterID, Throughput

version: 1.1

WebAgentTrace.log ==> use AgentConMgr.conf for tracing.

 

Also, refer to attachment "samplefiles.zip" which contains the network captured and exported from both PS and WA.