locked
LDAP search with other certificate attribute than CN RRS feed

  • Question

  • Hi,

    I have follwoing problem: users are authenticating themseleves with user certificates at the UAG portal. So far so good. Unfortunately some of them have a special character (Umlaut) in their CN. It seems that this causes a problem with the way the UAG checks if the user exists in the Active Directory as it uses the SubjectCN for searching via LDAP. I think that the CN is not very suitable for this search anyway (the ISA/TMG uses obviously the UPN User name). I found that in InternalSite\cert.asp the relevant code for getting the SubjectCN from the certificate is located. At least I could change this to SubjectEMAIL which seems to work (I would also need to change the RepostoryType.xml in order to get this working (searching for mail-attribute via LDAP). However it would be better in my opinion if it would be possible to use the UPN for the ldap search. Another thing what troubles me that it seems that I need to modify the cert.asp file in order to get this working (not a CustomUpdate Hook).

    Any ideas?

    Best regards

    Thomas

    Tuesday, November 2, 2010 6:34 PM

Answers

  • Hola Raul,

    this is obviously a bug. The customer who is facing the same issues (with german special characters). The problem in this case is obviously that after the first ldap lookup has failed the UAG is trying to access DCs in other sites. As this was blocked by the local TMG the login failed alltogether. In my test environment it worked as I only have one DC. MS is currently investigating this issue and there seem to be 2 issues: 1) The timing issue as other DCs are asked 2) The user can login despite the fact that he cannot be found in the AD. I will post an update whenever this is fixed (I guess/hope there will be a kind of hotfix).

    Best regards

    Thomas

    • Marked as answer by Erez Benari Thursday, May 5, 2011 4:46 PM
    Wednesday, March 23, 2011 4:24 PM

All replies

  • I assume you've seen this: http://technet.microsoft.com/en-us/library/ee861163.aspx

    I am not 100% sure what you are asking?

    Cheers

    JJ


    Jason Jones | Forefront MVP | Silversands Ltd | My Blogs: http://blog.msedge.org.uk and http://blog.msfirewall.org.uk
    Tuesday, November 2, 2010 8:23 PM
  • Hi Jason,

    yes indeed. The verification of the E-Mail address is not the problem this works fine. The problem is with users who are having a special character (in our case german Umlauts) in their CN. The UAG does an LDAP search based on the CN it retrieves out of the certificate subject. This seemingly does not work as the special character gets not correctly quoted or converted. I think the CN is also not a very good search criteria as it is possible that it is not unique. The best attribute would be the UPN imho. The TMG/ISA does this in contrast to the UAG. You can hovewer change the cert.asp in order to use something else as Subject-Attribute, e.g. the E-Mail address. With this change the LDAP search works fine as the E-Mail address is also unique and does not contain special characters. However I see this only as a workaround because changing the cert.asp is not update proof (no CustomUpdate mechanism). I also could not get it working with UPN that way.

    Best regards

    Thomas

    Wednesday, November 3, 2010 9:20 AM
  • Ah ok, a bit out of my league there!

    Hopefully Ben or Ran can provide some insight...

    Cheers

    JJ


    Jason Jones | Forefront MVP | Silversands Ltd | My Blogs: http://blog.msedge.org.uk and http://blog.msfirewall.org.uk
    Wednesday, November 3, 2010 9:26 AM
  • Hi Thomas,

    you can make your changes update-proof if you place your code within <InstallDir>\von\InternalSite\inc\CustomUpdate. Name your files <portalName>Validate.inc , <portalName>Cert.inc and <portalName>Login.inc  for example and place you custom code there to override the predefined functions.

    Regards,

    Andreas


    Andreas Hecker - Blog: http://microsoft-iag.blogspot.com/
    Wednesday, November 3, 2010 10:54 AM
  • Hallo Andreas,

    indeed this is the solution for implementing certificate based authentication. However my question was regarding cert.asp (in InternalSite). From my understanding you cannot make asp files in UAG update proof.

    Viele Grüße

    Thomas

    Wednesday, November 3, 2010 11:03 AM
  • [...] You can hovewer change the cert.asp in order to use something else as Subject-Attribute, e.g. the E-Mail address. With this change the LDAP search works fine as the E-Mail address is also unique and does not contain special characters. However I see this only as a workaround because changing the cert.asp is not update proof (no CustomUpdate mechanism [...]

    Best regards

    Thomas

    Hi Thomas,

    regarding the above concern of yours, and as Andreas just stated, there are several INC hooks, which I'm sure you know about, involved in certificate authentication in UAG. I do understand your concern about having to change cert.asp in order to get some specific functionality working, but you do have a workaround: copy the original ASP code of cert.asp into your custom cert.inc, and change whatever you need to change, right there, in cert.inc. This will ensure that once cert.asp includes cert.inc, is it that code that gets executed, and not the one in cert.asp.

    Also, since after copying the original ASP code from cert.asp, your cert.inc will end with a response.redirect directive, you do not have to worry about IIS returning from cert.inc to execute any more code from cert.asp. If you wish, as an additional safety measure, you cal also add at the very end of your custom cert.inc this directive: response.end.

    HTH,


    -Ran
    Wednesday, November 3, 2010 11:18 AM
  • Hi Ran,

    fair enough, that sounds to be a good workaround (I was not aware that I could use the .inc files in that way). However I still would like to search for the UPN (in the Subject Alternative Name attribute of the certificate) instead of the email address. I cold not get this working. The code in the cert.asp which I have changed for the email address looks like this:

    function GetClientCertificateSubject (subject_array)
     Dim subject_array_value()
     size = UBound(subject_array)
     if size < 0 then
      GetClientCertificateSubject = subject_array_value
      HEAVY_TRACE "There is no need for get information from the certificate"
      exit function
     end if
     Subject = Request.ClientCertificate ( "Subject" )
     SubjectLen = len ( Subject )
     if SubjectLen > 0 then
      if bSmartCardCertificate then
       pos = InStr(upn, "@")
                     if pos <> 0 then
                           user = Left(upn,pos-1)
                     end if
      else  
       user = Request.ClientCertificate("SubjectEMAIL")
      end if
      HEAVY_TRACE "user [" & user & "]"
      SetSessionParamWithType g_cookie,CERTIFICATE_USER_PARAM,user,PARAM_TYPE_INTERNAL

      Redim subject_array_value(size)
      i = 0
      for each s in subject_array
       subject_array_value(i) = Request.ClientCertificate (s)
       HEAVY_TRACE "The certificate have for the param [" & s & "] the value [" & subject_array_value(i) & "]"
       i = i + 1
      next
     Else
      LIGHT_TRACE "ERROR: The client didn't present a client certificate"
     End if
     GetClientCertificateSubject = subject_array_value
    end function

    I was wondering whether using this code

    pos = InStr(upn, "@")
                     if pos <> 0 then
                           user = Left(upn,pos-1)
                     end if

    would achive this. Unfortunately it did not work.

    Thanks and best regards

    Thomas

    Wednesday, November 3, 2010 12:16 PM
  • Hi Ran,

    it seems that we have another problem. We want to use KCD for SSO to several Web Applications. Obviously the Kerberos Ticket gets requested in the name of the attribute which the UAG reads out of the certificate subject (by default this is CN, I have changed it to E-Mail). The problem now is, that the customer has a different UPN than the E-Mail address or the CN which results in the error message KDC_ERR_C_PRINCIPAL_UNKNOWN. From looking into the certificate inc files (especially repository_for_cert.inc) I got the impression that UPN should be used for requesting the Kerberos ticket, at least UAG reads the UPN successfully from the certificate as I can see in the Web Monitor. This really puzzles me as I cannot get it working unless I could use the UPN.

    Best regards

    Thomas

    Wednesday, November 3, 2010 2:48 PM
  • Hi Ran,

    that´s exactly the way to get the customization update proof. Thank you for your better words.

    Regards,

    Andreas


    Andreas Hecker - Blog: http://microsoft-iag.blogspot.com/
    Wednesday, November 3, 2010 3:03 PM
  • Finally I got it working (thanks to Raúl's post: http://social.technet.microsoft.com/Forums/en/forefrontedgeiag/thread/7903db0a-ccb1-4e21-bf5f-2a33c297f109).

    The trick is to change the function GetClientCertificateSubject in cert.asp the following way:

    <%
    ' xxxxxxxxxxxxxxxxxxxxxxx DO NOT EDIT THIS FILE xxxxxxxxxxxxxxxxxxxxxxxx
    Const INFO_SUBJECT_UPN = 11

    ...

    function GetClientCertificateSubject (subject_array)
     Dim subject_array_value()
     size = UBound(subject_array)
     if size < 0 then
      GetClientCertificateSubject = subject_array_value
      HEAVY_TRACE "There is no need for get information from the certificate"
      exit function
     end if
     Subject = Request.ClientCertificate ( "Subject" )
     SubjectLen = len ( Subject )
     if SubjectLen > 0 then
      if bSmartCardCertificate then
       pos = InStr(upn, "@")
                     if pos <> 0 then
                           user = Left(upn,pos-1)
                     end if
      else  
       Set objCert = Server.CreateObject("Microsoft.UAG.CertificateComHelper")

       If err.number = 0 Then
        blob = Request.ClientCertificate("Certificate")
        objCert.Import(blob)
        upn = objCert.GetInfo(INFO_SUBJECT_UPN)
        set objCert = Nothing
       Else
            LIGHT_TRACE "CERT.inc: ERROR: Microsoft.UAG.CertificateComHelper interface not installed, failed to check if this is a Smart Card certificate and to obtain the certificate UPN! (err.number = " & err.number & ")"
       End If

       pos = InStr(upn, "@")
       if pos <> 0 then
        userupn = Left(upn,pos-1)
       end if

       user = userupn
      end if

      HEAVY_TRACE "user [" & user & "]"

      SetSessionParamWithType g_cookie,CERTIFICATE_USER_PARAM,user,PARAM_TYPE_INTERNAL

      Redim subject_array_value(size)
      i = 0
      for each s in subject_array
       subject_array_value(i) = Request.ClientCertificate (s)
       HEAVY_TRACE "The certificate have for the param [" & s & "] the value [" & subject_array_value(i) & "]"
       i = i + 1
      next
     Else
      LIGHT_TRACE "ERROR: The client didn't present a client certificate"
     End if
     GetClientCertificateSubject = subject_array_value
    end function

    ...

    Now I only need to make this update proof.

    Thanks all and best wishes

    Thomas

    P.S.: I found it a little bit disturbing that you have to do asp coding in order to achive such a function and I also think that the UPN should be checked in the first place instead of the CN or EMAIL (but that's just my opinion). This whole issue took me nearly 2 days by the way - I hope the customer understands all this :-(

    Wednesday, November 3, 2010 8:48 PM
  • Hi Ran,

    where exactly do I have to put the cert.asp code in the Trunk1cert.inc file? My original file looks like this:

    <%
    Dim subject_array(0)
    subject_array(0) = "SubjectEMAIL"
    %>

    I have tried to put the code from cert.asp at the end but with no luck (the CPU gets to 100% and after a while I get a internal server error.

    Cheers

    Thomas

    Wednesday, November 3, 2010 9:08 PM
  • Hi Thomas,

    Yeah, I should have been more specific: that's because the original cert.asp code contains the "include cert.inc" stuff, so if you copy that too into cert.inc, the result will be cert.inc attempting to include itself, so an endless loop resulting in 100% CPU.

    Please take out those one or two lines that include cert.inc

    DISCLAIMER: I'm not in front of, or next to, a UAG server now. Also, please understand that I am giving you some ideas, based on my experience, but they are by no means a verified solution.

    Best regards,


    -Ran
    Wednesday, November 3, 2010 9:21 PM
  • Hi Ran,

    I really appreciate your help! I still have problems including the cert.asp code into the cert.inc file.

    I have found the following lines in the original cert.asp:

    if Application(g_site_name&g_secure&CERT_INC) <> FILE_NOT_EXIST then
     ' the include file must declare subject_array as an array
      include Application(g_site_name&g_secure&CERT_INC)

    I have tried commenting out the include and the complete if clause but with not much success :(

    Could it be that there is also a problem with the realtive paths, e.g. url =  "/InternalSite/PostValidate.asp" or
    '<!--#include file="inc/PolicyEvaluation.inc"-->?

    I would really like to have some better doucumentation especially about all the customization options (maybe the upcoming books have some insights). Is there a way to debug the asp code? AFAIK the tracing has been disabled (despite trace.ini and trace.inc are still there, a little bit confusing imo)

    Cheers

    Thomas

    Thursday, November 4, 2010 9:04 AM
  • Have you tried the IAG user guides?

    http://www.microsoft.com/forefront/edgesecurity/iag/en/us/product-documentation.aspx#

    A lot of content is still relevant...

    Cheers

    JJ


    Jason Jones | Forefront MVP | Silversands Ltd | My Blogs: http://blog.msedge.org.uk and http://blog.msfirewall.org.uk
    Thursday, November 4, 2010 9:34 AM
  • Hi Jason,

    unfortunately there is no such information there too. I really prefer a pdf documentation rather than (dynamic) web content like technet though. It's really a shame that all companies do not create real product documentation anymore (Citrix is also a good example). I see the point of having dynamic content but often it lacks deeper information about the technology and is imo also difficult to read/search.

    Best regards

    Thomas

    Thursday, November 4, 2010 9:40 AM
  • Hi Jason,

    unfortunately there is no such information there too. I really prefer a pdf documentation rather than (dynamic) web content like technet though. It's really a shame that all companies do not create real product documentation anymore (Citrix is also a good example). I see the point of having dynamic content but often it lacks deeper information about the technology and is imo also difficult to read/search.

    Best regards

    Thomas


    Ok, sorry...sometimes the old docs have more detail than Technet in certain areas...
    Jason Jones | Forefront MVP | Silversands Ltd | My Blogs: http://blog.msedge.org.uk and http://blog.msfirewall.org.uk
    Thursday, November 4, 2010 9:45 AM
  • Hi Thomas,

    I hope I’m not leading you down a too much winding road…

    Think of it this way: when executing cert.asp, IIS executes it line by line, from top to bottom, until it reaches the point where it is told to include cert.inc. At that point, the code of cert.inc is being executed, still from top to bottom. At the end of it *normally*, IIS would return to the immediate following line in cert.asp and continue from there (I’m saying “normally”, since, as we discussed in a previous reply of mine in this thread, in this special case cert.inc will instruct IIS to stop processing further, by having the Response.redirect and Respone.end directives in it).

    You could also think of it as if you are copy-pasting the cert.inc ASP content in the middle of cert.asp, starting right where the include Application (g_site_name & g_secure & CERT_INC) is.

     

    So, once you understand that, you will realize that anything that is located in cert.asp above the include Application (g_site_name & g_secure & CERT_INC) is already executed by IIS by the time it includes cert.inc, so you do not need to copy that stuff to cert.inc. For example, you don’t need to copy the CheckCertificateTime() function, the g_filename = …, the Session(“secure”) = …, nor the include file=”inc/PolicyEvaluation.inc”.

     

    You have a good point regarding the relative paths of URLs, but in this case, if you follow my advice above and leave the include file=”inc/PolicyEvaluation.inc” where it is in cert.asp, there are no other URLs that I see that could cause a problem (there are a couple of url=”/InternalSite/…” but those are OK, you do not need to change anything there).

     

    Finally, regarding tracing: you can certainly (and I would warmly advise you to do so!) continue to trace the ASP code. Take a look at the UAGTracingTool.docx found at this link, for information on how to turn on tracing in general, and especially for InternalSite.

     

    Regards,


    -Ran
    • Marked as answer by Thomas Wendler Tuesday, November 9, 2010 3:38 PM
    • Unmarked as answer by Thomas Wendler Monday, February 14, 2011 8:09 AM
    • Edited by Ran [MSFT] Thursday, September 29, 2011 5:10 PM
    Thursday, November 4, 2010 12:53 PM
  • Useful disection Ran...Thanks!
    Jason Jones | Forefront MVP | Silversands Ltd | My Blogs: http://blog.msedge.org.uk and http://blog.msfirewall.org.uk
    Thursday, November 4, 2010 5:26 PM
  • Hi Jason,

    unfortunately there is no such information there too. I really prefer a pdf documentation rather than (dynamic) web content like technet though. It's really a shame that all companies do not create real product documentation anymore (Citrix is also a good example). I see the point of having dynamic content but often it lacks deeper information about the technology and is imo also difficult to read/search.

    Best regards

    Thomas

    Hi All. Just to say that the information we share in this forum is "dynamic web content" and there is no pdf compilation about it !

    (Thomas, I am not trying to be rude, just joking ;-P


    // Raúl - I love this game
    Thursday, November 4, 2010 8:25 PM
  • Hi Jason,

    unfortunately there is no such information there too. I really prefer a pdf documentation rather than (dynamic) web content like technet though. It's really a shame that all companies do not create real product documentation anymore (Citrix is also a good example). I see the point of having dynamic content but often it lacks deeper information about the technology and is imo also difficult to read/search.

    Best regards

    Thomas

    Hi All. Just to say that the information we share in this forum is "dynamic web content" and there is no pdf compilation about it !

    (Thomas, I am not trying to be rude, just joking ;-P


    // Raúl - I love this game

    :)
    Jason Jones | Forefront MVP | Silversands Ltd | My Blogs: http://blog.msedge.org.uk and http://blog.msfirewall.org.uk
    Thursday, November 4, 2010 11:09 PM
  • Hi Ran,

    it works exactly as you wrote.

    Thanks again!

    Thomas

    Tuesday, November 9, 2010 3:38 PM
  • Ah and for the curious, here is my site1cert.inc file:

    <%
    Dim subject_array(0)
    subject_array(0) = "SubjectEMAIL"

    Const INFO_SUBJECT_UPN = 11       'X509Certificate2.GetNameInfo(X509NameType.UpnName, false)
    %>

    <%
    function GetClientCertificateSubject (subject_array)
     Dim subject_array_value()
     size = UBound(subject_array)
     if size < 0 then
      GetClientCertificateSubject = subject_array_value
      HEAVY_TRACE "There is no need for get information from the certificate"
      exit function
     end if
     Subject = Request.ClientCertificate ( "Subject" )
     SubjectLen = len ( Subject )
     if SubjectLen > 0 then
      if bSmartCardCertificate then
       pos = InStr(upn, "@")
                     if pos <> 0 then
                           user = Left(upn,pos-1)
                     end if
      else  
       Set objCert = Server.CreateObject("Microsoft.UAG.CertificateComHelper")

       If err.number = 0 Then
        blob = Request.ClientCertificate("Certificate")
        objCert.Import(blob)
        upn = objCert.GetInfo(INFO_SUBJECT_UPN)
        set objCert = Nothing
       Else
            LIGHT_TRACE "CERT.inc: ERROR: Microsoft.UAG.CertificateComHelper interface not installed, failed to check if this is a Smart Card certificate and to obtain the certificate UPN! (err.number = " & err.number & ")"
       End If

       pos = InStr(upn, "@")
       if pos <> 0 then
        userupn = Left(upn,pos-1)
       end if

       user = userupn
      end if

      HEAVY_TRACE "user [" & user & "]"

      SetSessionParamWithType g_cookie,CERTIFICATE_USER_PARAM,user,PARAM_TYPE_INTERNAL

      Redim subject_array_value(size)
      i = 0
      for each s in subject_array
       subject_array_value(i) = Request.ClientCertificate (s)
       HEAVY_TRACE "The certificate have for the param [" & s & "] the value [" & subject_array_value(i) & "]"
       i = i + 1
      next
     Else
      LIGHT_TRACE "ERROR: The client didn't present a client certificate"
     End if
     GetClientCertificateSubject = subject_array_value
    end function

    dim url
    ' DetectionDOSFix - Storing include files in application and not in session

      if IsClientCertificateValid () then
        MEDIUM_TRACE "The client certificate is valid"
        subject_array_value = GetClientCertificateSubject (subject_array)
        i = 0
        for each s in subject_array_value
          HEAVY_TRACE "Add to the session the parameter [" & subject_array(i) & "]"
          SetSessionParamWithType g_cookie,subject_array(i),s,CERTIFICATE_PARAM_TYPE
          i = i + 1
        next
      else
        LIGHT_TRACE "ERROR: The client certificate is not valid"
      End if

      url = "/InternalSite/Validate.asp"

      if GetSiteUseSep() then
     if IsSecureEndPoint() then
      MEDIUM_TRACE "The session is in secure end point"
      
      ' DetectionDOSFix - Current Detection results are stored in asp session
      SetSessionParamWithType g_cookie, SECURE_END_POINT_PARAM, "TRUE", "Policy"
      set lstDetectionVars = GetSessionMgrPolicyParameters()
      if not IsEmpty(lstDetectionVars) then
          lstDetectionVars(SECURE_END_POINT_PARAM) = true
          PolicyEvaluation lstDetectionVars, false
      end if

      set trunk_param = Server.CreateObject("MonitorMgrComLayer.MessageParam")
      trunk_param.Name = "TrunkName"
      trunk_param.ValueVec = Array(g_site_name)

      set secure_param = Server.CreateObject("MonitorMgrComLayer.MessageParam")
      secure_param.Name = "TrunkSecure"
      secure_param.ValueVec = Array(g_secure)

      set session_id_param = Server.CreateObject("MonitorMgrComLayer.MessageParam")
      session_id_param.Name = "SessionId"
      session_id_param.ValueVec = Array(g_session_id)

      SetMessage MONITOR_MSG_SECURE_END_POINT,Array(trunk_param,secure_param,session_id_param)

      set trunk_param = Nothing
      set secure_param = Nothing
      set session_id_param = Nothing
     
     else
      MEDIUM_TRACE "The session is not in secure end point"
     end if
     if url = "" then
      url =  "/InternalSite/PostValidate.asp"
     end if
    end if
    ClearSessionVariables
    Session.abandon
    HEAVY_TRACE "Redirect to [" & url & "]"
    response.redirect url
    response.end
    %>

    Tuesday, November 9, 2010 3:39 PM
  • That's great, glad to hear!

    Best regards,


    -Ran
    Tuesday, November 9, 2010 4:43 PM
  • Hi,

    it seems that this is not working correctly in any case. In my test environment and for the customer it worked for a while. Now it seems that it does not work anymore for the customer. I did some tracing for the LDAP queries and found out that the request for getting the mail and upn attributes from Active Directory (I presume this is for comparing it with those in the certificate) is failing when the CN contains special characters (in our case german umlaut). The LDAP search fails with the error noSuchObject (0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT). Strange enough this also happens in my VMWare environment but the user gets logged in anyway.

    I am not sure, but I guess this function in the repository_for_cert.inc fails: GetUserInformation(repository,user_name,"",Array(param_email,param_UPN)). What seems really strange to me is that the function first queries the DN with the samAccountname and then uses the DN to query for mail and upn. There it fails as it does not uses the correct characters in the DN.

    Best regards

    Thomas

    Monday, February 14, 2011 8:08 AM
  • Obviously this ldap request is not relevant for granting access to the user. However if the LDAP query fails because not all domain controllers are reachable (in our case DCs in branch locations) the authentication fails. We have opened a ticket with MS support to figure out why this happens.
    Thursday, March 10, 2011 5:42 PM
  • Hi Thomas. I am fighting a similar issue but in my case with Spanish characters. What is driving me crazy is that in my test lab it is working fine but in the production environment it fails and apparently there is no difference between them. Furthermore, if the call to the function Getuserinformation is substituted by a query with ADODB then it works. Did you find anyting out? Does the SP1 Rollup 1 have to do with this?

    Regards


    // Raúl - I love this game
    Tuesday, March 22, 2011 5:57 PM
  • Hola Raul,

    this is obviously a bug. The customer who is facing the same issues (with german special characters). The problem in this case is obviously that after the first ldap lookup has failed the UAG is trying to access DCs in other sites. As this was blocked by the local TMG the login failed alltogether. In my test environment it worked as I only have one DC. MS is currently investigating this issue and there seem to be 2 issues: 1) The timing issue as other DCs are asked 2) The user can login despite the fact that he cannot be found in the AD. I will post an update whenever this is fixed (I guess/hope there will be a kind of hotfix).

    Best regards

    Thomas

    • Marked as answer by Erez Benari Thursday, May 5, 2011 4:46 PM
    Wednesday, March 23, 2011 4:24 PM
  • Thanks Thomas.
    // Raúl - I love this game
    Wednesday, March 23, 2011 5:06 PM
  • I also found this kind of bug which my AD account cn includes Chinese characters...

    Do you have any new feedback from MS?

    TKX.


    邁格行動 技術顧問 George 小顧 部落格: http://www.magg.com.tw/blog/
    Thursday, September 29, 2011 9:58 AM