Pages

Tuesday, September 27, 2011

How to read Windows Active Directory with Powerbuilder


Here is the tips and trick how to read Windows Active Directory in Powerbuilder script, made by William Franklin (wfranklin@plg.cc) with Powerbuilder version 8, but I'm sure it will run smoothly in other newest version.

First of all we cannot retrieve the password from LDAP, only we can validate the password against it. Here is the code, do the following steps and I tested it in my network it is working fine.


STEP 1:
Create the following Local/Global External functions

1:    
2:  Function ulong WNetGetUser( &  
3:  string lpname, &  
4:  ref string lpusername, &  
5:  ref ulong buflen &  
6:  ) Library "mpr.dll" Alias For "WNetGetUserA"  
7:    
8:    
9:  Function boolean LogonUser ( &  
10:  string lpszUsername, &  
11:  string lpszDomain, &  
12:  string lpszPassword, &  
13:  ulong dwLogonType, &  
14:  ulong dwLogonProvider, &  
15:  ref ulong phToken &  
16:  ) Library "advapi32.dll" Alias For "LogonUserA"  
17:    
18:    
19:  Function boolean CloseHandle ( &  
20:  ulong hObject &  
21:  ) Library "kernel32.dll"  


Note :Create a instance variable is_domain


STEP 2:
I had created a Window with username and password textboxes, I populate the username automatically by using the WNetGetUser in the open even of the Window, I get the domain name using the OleObject which I gave the code yesterday.
Following will be the code in Open event of the login Window.

1:  String ls_userid  
2:  Ulong lul_result, lul_buflen  
3:  OleObject LDAP  
4:    
5:  //Get the username  
6:  lul_buflen = 32  
7:  ls_userid = Space(lul_buflen)  
8:  lul_result = WNetGetUser("", ls_userid, lul_buflen)  
9:    
10:  If lul_result = 0 Then  
11:       sle_userid.text = ls_userid  
12:       sle_password.SetFocus()  
13:  End If  
14:    
15:  //Get the Domain  
16:    
17:  LDAP = CREATE OleObject  
18:  LDAP.ConnectToNewObject( "ADSystemInfo" )  
19:  is_domain = string(LDAP.DomainDNSName)  


STEP 3:
In the Login Command button where we do validation on what the user type as password along with the AD password. (Note : LogonUser function is the one which gets triggerd when you login into a computer, we use the same to do the authentication, and if you are using PB higher version, then you may use the
LogonUserEx function)

1:  Constant ULong LOGON32_LOGON_NETWORK = 3  
2:  Constant ULong LOGON32_PROVIDER_DEFAULT = 0  
3:  String ls_username, ls_password  
4:  ULong lul_token  
5:  Boolean lb_result  
6:    
7:  ls_domain = ""  
8:  ls_username = sle_userid.text  
9:  ls_password = sle_password.text  
10:    
11:  lb_result = LogonUser( ls_username, is_domain, &  
12:  ls_password, LOGON32_LOGON_NETWORK, &  
13:  LOGON32_PROVIDER_DEFAULT, lul_token )  
14:    
15:  If lb_result Then  
16:       CloseHandle(lul_token)  
17:       MessageBox(Parent.title, "The userid/password is valid!")  
18:  Else  
19:       MessageBox(Parent.title, "The userid/password is not valid!")  
20:  End If  

9 comments :

  1. Tu ejemplo me ha sido de gran ayuda para realizar una validaciĆ³n contra LDAP de Windows
    Gracias

    ReplyDelete
  2. imma newbies to powerbuilder, and i would like to know what if my username and password is keep in window user management then can i still using this code/solution to do the authentication?
    my purpose just want to authenticate the use when the system offline. therefore im not able to do any soap connection and etc. so do you have any idea how to do the authentication on this situation?

    thanks

    ReplyDelete
  3. after i tried the coding that you provided, it prompt the error code = 126 in window function call GetLastError() which mean to The specified module could not be found. so may i know what happening and how to solve it?

    millions thanks

    ReplyDelete
  4. I'm contacting William Franklin, who wrote the original article to answer your question. Please contact him directly if you want too, to wfranklin[at]plg.cc

    ReplyDelete
  5. I am not sure what you meant by GetLastError(), debug the code and find out where the error is coming from. PB 12 uses unicode and the external functions need to be modified according to that, I mentioned about that in Step 3 comments.

    Regards
    -William

    ReplyDelete
  6. I am also getting 126 error. Can you please provide the solution

    ReplyDelete
  7. This works great. For PB12.5 The external function needs ;ANSI at the end.

    // This function gets the network login userid
    Function ulong WNetGetUser(string lpname, ref string lpusername, ref ulong buflen) Library "mpr.dll" Alias For "WNetGetUserA;Ansi"

    // This function validates the login userid/password
    Function boolean LogonUser (string lpszUsername, string lpszDomain, string lpszPassword, ulong dwLogonType, ulong dwLogonProvider, ref ulong phToken) Library "advapi32.dll" Alias For "LogonUserA;Ansi"

    // Close the connection
    Function boolean CloseHandle (ulong hObject) Library "kernel32.dll"

    ReplyDelete