Seite 1 von 1

LDAP schreiben und lesen im AD

Verfasst: 23.06.2015 11:08
von Amor_2001
Hallo zusammen,
bisher habe ich mir ein wenig mit VBS helfen können, wenn ich über LDAP auf die AD zugreifen wollte. Nun möchte ich aber mal eine richtige Anwendung in PB schreiben. Kann mir jemand mal Tipps geben, oder evtl. auch schon Prozeduren, mit denen ich das bewerkstelligen kann? Ich bin total hilflos.

Danke schon mal vorab.

Re: LDAP schreiben und lesen im AD

Verfasst: 23.06.2015 11:37
von JMaker
Was ist LDAP?

Re: LDAP schreiben und lesen im AD

Verfasst: 23.06.2015 11:40
von Amor_2001
Lightweight Directory Access Protocol
Das ist ein Protokoll mit dem man auf das Active Directory zugreifen kann.

Re: LDAP schreiben und lesen im AD

Verfasst: 23.06.2015 12:42
von ts-soft
Meines Wissens nach, ist das ganze nur über COM Objecte verfügbar. Hierfür eignet sich natürlich ComMATEPlus.pbi.
Solltest Dir vielleicht erstmal das ADO Beispiel anschauen. Die meisten werden wohl VBS nutzen. Es gibt wohl auch
eine PHP Anbindung, aber für PB oder C sieht es da eher schlecht aus.
Ich denke mal, PB ist nicht gerade die optimale Wahl.

Gruß
Thomas

Re: LDAP schreiben und lesen im AD

Verfasst: 23.06.2015 14:10
von Amor_2001
Das wäre ja sehr schade. Hatte gehofft, dass es da auch was für PB gibt. Was ich über Comateplus gefunden habe, ist nur lesender Zugriff. Leider möchte/muss ich auch schreiben können.
Aber vielen Dank erst mal.

Re: LDAP schreiben und lesen im AD

Verfasst: 23.06.2015 16:28
von Shardik
Es gibt außer den von ts-soft aufgezählten Möglichkeiten des LDAP-Zugriffs mit COMatePLUS oder ADOmate auch noch zumindest diese beiden Möglichkeiten:
- Eine limitierte Abfrage von Informationen des Domänen Controllers mit den Windows API-Funktionen NetUserGetInfo() und NetUserGetGroups()
- Eine Abfrage mit Hilfe der Bibliotheken WLDAP32.DLL (gehört bei Windows XP bis Windows 8.1 zum Betriebssystemumfang) und LDAPSDK.DLL (von Novell)

Zunächst einmal ein stark gekürztes Beispiel auf der Grundlage dieses Beispiels von flaith aus dem englischen Forum zum Auslesen diverser Infos des Domain Controllers mit NetUserGetInfo() und NetUserGetGroups():

Code: Alles auswählen

EnableExplicit

#UserID = "DeineUserID"

Define *Buffer = AllocateMemory(1024)
Define *DCName
Define DCName.S
Define Entries.I
Define EntriesTotal.I
Define *Groups
Define i.I
Define *UserInfo.USER_INFO_3

If NetGetDCName_(0, 0, @*DCName) <> 0
  MessageRequester("Fehler", "Die Namensabfrage des Domain Controllers ist fehlgeschlagen!", #MB_ICONERROR)
  End
Else
  DCName = PeekS(*DCName, -1, #PB_Unicode)

  If Left(DCName, 2) = "\\"
    DCName = Mid(dcname, 3)
  EndIf

  Debug "DCName = " + DCName
EndIf  

PokeS(*Buffer, #UserID, -1, #PB_Unicode)

If NetUserGetInfo_(*DCName, *Buffer, 3, @*UserInfo) <> 0
  MessageRequester("Fehler", "Die NetUserGetInfo-Abfrage ist fehlgeschlagen!", #MB_ICONERROR)
Else
  Debug "Fullname = " + #DQUOTE$ + PeekS(*UserInfo\usri3_full_name, -1, #PB_Unicode) + #DQUOTE$
  Debug "Comment = " + #DQUOTE$ + PeekS(*UserInfo\usri3_comment, -1, #PB_Unicode) + #DQUOTE$
  Debug "Account expiration date = " + *UserInfo\usri3_acct_expires
  Debug "Home directory = " + #DQUOTE$ + PeekS(*UserInfo\usri3_home_dir, -1, #PB_Unicode) + #DQUOTE$
  Debug "Script path = " + #DQUOTE$ + PeekS(*UserInfo\usri3_script_path, -1, #PB_Unicode) + #DQUOTE$
  Debug "Home drive = " + #DQUOTE$ + PeekS(*UserInfo\usri3_home_dir_drive, -1, #PB_Unicode) + #DQUOTE$
  Debug "Password expiration date: " + *UserInfo\usri3_password_expired
  Debug "Flags: " + *UserInfo\usri3_flags
  Debug "Privilege: " + *UserInfo\usri3_priv
  Debug "Logon hours: " + *UserInfo\usri3_logon_hours

  If NetUserGetGroups_(*DCName, *Buffer, 0, @*Groups, -1, @Entries, @EntriesTotal) <> 0
    MessageRequester("Fehler", "Die NetUserGetGroups-Abfrage ist fehlgeschlagen!", #MB_ICONERROR)
  Else
    Debug ""
    Debug "Gruppenmitgliedschaften:"
    Entries = (Entries * SizeOf(Integer)) - SizeOf(Integer)

    For i = 0 To Entries Step SizeOf(Integer)
      Debug "- " + PeekS(PeekI(*Groups + i), -1, #PB_Unicode)
    Next

    NetApiBufferFree_(*Groups)
  EndIf
EndIf
Das folgende Beispiel zeigt, wie man mit der WLDAP32.DLL ein Attribut für eine User-ID in einem Active Directory ausliest, konkret als Beispiel das Attribut "PwdLastSet" (Datum der letzten Passwort-Änderung). Leider gehört die WLDAP32.Lib nicht zum Betriebssystemumfang von Windows. Ich habe sie mir aus dem Windows Platform SDK February 2003 extrahiert. Erfolgreich getestet habe ich dieses Beispiel mit PB 5.31 x86 unter Windows XP SP3 und Windows 8.1 x64 (vorher müssen die Konstanten #DCName, #SearchBase und der Pfad zur WLDAP32.Lib an die eigene Umgebung angepasst werden).

Code: Alles auswählen

EnableExplicit

#DCName = "10.11.12.13"          ; <-- Name oder IP-Adresse des Domain Controllers
#Port = 389
#SearchBase = "DC=example,DC=de" ; <-- Name des Eintrags, an dem die Suche beginnen soll

#LDAP_AUTH_NEGOTIATE = $486
#LDAP_OPT_PROTOCOL_VERSION = $11
#LDAP_SCOPE_SUBTREE = $02
#LDAP_SUCCESS = 0

ImportC "X:\WLDAP\WLDAP32.Lib"   ; <-- Pfad zur WLDAP32.Lib
  ldap_bind_s(SessionHandle.I, DistinguishedName.S, *AuthCredentials, AuthMethod.I)
  ldap_first_attribute(SessionHandle.I, *Entry, *Position)
  ldap_first_entry(SessionHandle.I, *SearchResult)
  ldap_get_values(SessionHandle.I, *Entry, *AttributeName)
  ldap_init(HostName.S, PortNumber.I)
  ldap_msgfree(*Msg)
  ldap_next_attribute(SessionHandle.I, *Entry, *Position)
  ldap_search_s(SessionHandle.I, DistinguishedName.S, Scope.I, Filter.S,
    *AttributeArray, AttributesOnly.I, *SearchResult)
  ldap_set_option(SessionHandle.I, Option.I, *OptionValue)
  ldap_simple_bind_s(SessionHandle.I, UserName.S, Password.S)
  ldap_unbind(SessionHandle.I)
EndImport

Procedure.S GetAttributeValue(UserID.S, AttributeName.S)
  Protected *AttributeName
  Protected AttributeValue.S
  Protected *Entry
  Protected LoginUserID.S
  Protected Password.S
  Protected *Position
  Protected ProtocolVersion.I = 3
  Protected Result.I
  Protected SearchResult.I
  Protected SessionHandle.I
  Protected *Value
  Protected *ValueList

  ; ----- Anmeldung am LDAP-Server durchführen

  SessionHandle = ldap_init(#DCName, #Port)
  
  If SessionHandle
    ; ----- LDAP-Protokollversion setzen

    If ldap_set_option(SessionHandle, #LDAP_OPT_PROTOCOL_VERSION,
      @ProtocolVersion) = #LDAP_SUCCESS
      Result = ldap_bind_s(SessionHandle, "", 0, #LDAP_AUTH_NEGOTIATE)

      If Result = #LDAP_SUCCESS
        ; ----- Gewünschte User-ID suchen und alle Attributnamen und -werte für
        ;       diesen Eintrag einlesen

        If ldap_search_s(SessionHandle, #SearchBase, #LDAP_SCOPE_SUBTREE,
          "SAMAccountName=" + UserID, 0, #False, @SearchResult) = #LDAP_SUCCESS
          *Entry = ldap_first_entry(SessionHandle, SearchResult)
          *AttributeName = ldap_first_attribute(SessionHandle, *Entry,
            @*Position)

          ; ----- Alle Attributnamen nach dem gewünschten Attributnamen
          ;       durchsuchen

          Result = #False

          While *AttributeName
            If UCase(PeekS(*AttributeName)) = UCase(AttributeName)
              Result = #True
              Break
            EndIf

            *AttributeName = ldap_next_attribute(SessionHandle, *Entry,
              *Position)
          Wend

          ; ----- Wenn der gewünschte Attributname gefunden wurde, den
          ;       Attributwert auslesen

          If Result
            *ValueList = ldap_get_values(SessionHandle, *Entry, *AttributeName)
      
            If *ValueList
              *Value = PeekI(*ValueList)
        
              If *Value
                AttributeValue = PeekS(*Value)
              EndIf
            EndIf
          EndIf
    
          If SearchResult
            ldap_msgfree(SearchResult)
          EndIf
        EndIf
      EndIf
    EndIf

    ldap_unbind(SessionHandle)
  EndIf

  ProcedureReturn AttributeValue
EndProcedure

Define AttributeName.S = "PwdLastSet"
Define AttributeValue.S
Define FileTime.Q
Define LastPasswordChange.S
Define SystemTime.SYSTEMTIME
Define UserID.S = UserName()

AttributeValue = GetAttributeValue(UserName(), AttributeName)

If Trim(AttributeValue) = ""
  MessageRequester("Fehler bei AD-Abfrage für " + UserID,
    "Die Abfrage von Attribut '" + AttributeName + "' ist fehlgeschlagen!",
    #MB_ICONEXCLAMATION)
Else
  ; ----- Attributwert im FILETIME-Format ins SYSTEMTIME-Format umwandeln und
  ;       einen Ausgabe-String erstellen

  FileTime = Val(AttributeValue)

  If FileTimeToSystemTime_(@FileTime, @SystemTime)
    LastPasswordChange = Str(SystemTime\wDay) + "." + Str(SystemTime\wMonth) +
      "." +  Str(SystemTime\wYear) + " " + Str(SystemTime\wHour) + ":" +
      Str(SystemTime\wMinute)
    MessageRequester("AD-Abfrage für " + UserID, AttributeName + " = " +
      LastPasswordChange, #MB_ICONINFORMATION)
  EndIf
EndIf
Ich selbst habe schon eine Reihe von Auswerteprogrammen mit LDAP-Zugriff über die WLDAP32.DLL auf das eDirectory von Novell geschrieben. Ein Beispiel von TeddyLM für den Zugriff auf die AD findet man hier im englischen Forum.

Hier sind noch zwei Beispiele aus dem englischen Forum für den Einsatz von COMatePLUS: von Amundo (Ermittlung aller Top Level Gruppen einer User-ID) und von em_uk (Ermittlung der eMail-Adresse einer User-ID).
Amor_2001 hat geschrieben:Was ich über Comateplus gefunden habe, ist nur lesender Zugriff. Leider möchte/muss ich auch schreiben können.
Das mit dem Schreiben ist höchstens ein Rechte-Problem. Wenn Du selbst keine DC-Administratorrechte hast, wirst Du Dir die Rechte von Deinem DC-Administrator zuteilen lassen müssen, falls er überhaupt dazu bereit ist, denn mit DC-Administratorrechten steht Dir das komplette System offen wie ein Scheunentor... :wink: