Active Directory

Hi all :-)

Does anyone have a COBOL example of a user validation in Active Directory they´d like to share?

Regards

Steen

  • Hi.

    We did something like that but using external (non COBOL) module.

    I don't really know if it's possible to do it differently.
    --
    Davide
  • Hi
    Yes I'm aware that I might have do do some ActiveX / DLL calls but I what I ment was if there's anyone who already did some COBOL code for this and would like to share?
    Steen
  • You can use Call "C$SYSTEM" to call the microsoft user exe just like you would in C , C#, VB.Net.
  • What do you mean by "user validation"?

    If you have a username and password, and you're running on Windows, you're probably better off just calling the standard Windows LogonUser function. It's simpler and almost always faster.

    Here's the thing: There are essentially two ways to validate user credentials against an LDAP server such as AD. (I'm omitting proprietary, non-LDAP interfaces to AD, because they're basically equivalent for this purpose.) You can try to bind to the server using the credentials and see if that succeeds; or you can do a search against the server for the object representing the user, and then do something with the returned information.

    Binding to AD as the user is equivalent to doing a domain signon in most cases, except:

    • Some users may not have permission to bind to AD
    • You don't get the benefits of local credential caching, such as:
      • Better performance (saves a network round trip and processing in AD)
      • Offline support

    Looking up the user in AD generally isn't a good way to go, because:

    • Unless AD is configured to allow anonymous binds and then let the anonymous client search successfully for user records (which would be bad), you'll have to bind to AD first using some credentials.
      • If you use the credentials you're trying to validate, then you've just validated them, so why do anything more?
      • Otherwise, you have to get credentials from somewhere:
        • You can use the thread token (if you're running on Windows), but are you sure that account has appropriate permissions?
        • You can store a username and password somewhere. Now you have a security vulnerability.
    • Say you get the user information out of LDAP. How do you plan to validate the credentials you have against it?

    So, if all you want to do is confirm the user's credentials, talking directly to AD probably isn't the way to go - if you're running on Windows.

    If you're not running on Windows, you have a few choices:

    1. Use the bind-to-AD method described above.
    2. Use a remote mechanism for signing into a Windows domain, such as Samba. Or write your own (though I don't recommend this).
    3. Use Kerberos instead.

    It'd help to know what problem you're actually trying to solve, in some detail.

  • I see what you mean, and I simply just want to check if the user is a "known user" and the user account isn't disabled / expired. So the best solution properly is to call the Windows LogonUser function as you suggest. Do you have an example of thsi?

    And yes I'm running Windows.
  • I don't have an ACU version - I'm not running ACU COBOL / Extend (so many MF products, so little time). I do have an old sample for this, for some now-forgotten reason, that I wrote in MF COBOL. I think that should work in ACU with relatively little massaging.

     

          $set mf sourceformat"variable"
           identification division.
           program-id. logon.
    
           data division.
           working-storage section.
           77 userid           pic x(40).
           77 password         pic x(40).
           77 strpos           pic x(4) comp-5.
          $if USEPTR defined
           77 token            pointer.
          $else
          $if P64 set
           77 token            pic x(8) comp-5.
          $else
           77 token            pic x(4) comp-5.
          $end
          $end
           77 result           pic x(4) comp-5.
           77 loadlib          procedure-pointer.
           77 errcode          pic x(4) comp-5.
           77 errdisp          pic z(4)9 display.
    
           procedure division.
           *> Load Windows DLLs
           set loadlib to entry "advapi32"
           set loadlib to entry "kernel32"
    
           perform until exit
               *> Get username and password
               display "Userid: " with no advancing
               accept userid
               if userid = spaces
                   exit perform
               end-if
               display "Password: " with no advancing
               accept password
    
               *> Nul-terminate strings
               move 0 to strpos
               inspect userid tallying strpos for characters before initial space
               add 1 to strpos
               move low-values to userid(strpos:1)
    
               move 0 to strpos
               inspect password tallying strpos for characters before initial space
               add 1 to strpos
               move low-values to password(strpos:1)
    
               *> Try the logon
          $if USEPTR defined
               set token to null
          $else
               move 0 to token
          $end
               call "LogonUserA" using
                   by reference userid
                   by reference z"."
                   by reference password
                   by value     3
                   by value     0
                   by reference token
                   returning    result
               end-call
               call "GetLastError" returning errcode
    
          $if USEPTR defined
               if token = null
          $else
               if token = 0
          $end
                   display "No token returned"
               else
                   display "Token returned"
                   *>call "CloseHandle" using by value token
                   call "CloseHandle" using by reference token
               end-if
               if result = 0
                   display "LogonUser returned false"
                   move errcode to errdisp
                   display "Error code was " errdisp
               else
                   display "LogonUser returned true"
               end-if
    
           end-perform
    
           move 0 to return-code
           stop run.
    
  • Hi Michael
    Thanks a lot for your example :-)
    I do however get an error compiling the code:

    call "LogonUserA" using
    by reference userid
    by reference z"."
    by reference password
    by value 3
    by value 0
    by reference token
    returning result
    end-call

    There's an error in the

    by reference z"."

    line. Should it just be by reference "."

    Or?

    Regards
    Steen
  • The z"somevalue" notation is used by various flavors of Micro Focus COBOL to indicate a null-terminated string literal; unfortunately, ACUCOBOL doesn't support this notation. However, you can use hexadecimal notation: ... by reference x"2e00". (2e is the hex value of the "dot" character, and 00 is a null byte).
  • Chuck is correct, but while the x in front of the quotes can be lower case, I believe the "e" in 2e should be in caps. eg) x"2E00".
  • Thanks all - but the call to LogonUserA returns a zero result. And the subsequently call to GetLastError returns an Errcode = 1326
    Any ideas?