Zugriffsberechtigungen für Netzwerkfreigabe prüfen



  • Hallo,

    ich habe auf einem Rechner eine Netzwerkfreigabe, für die nur ein bestimmter lokaler Benutzer Schreibrechte hat (sagen wir einfach die Freigabe ist \Server1\share). Aus einem Programm möchte ich jetzt prüfen, ob ein Benutzer (sagen wir user1//pass1) Lese-/und oder Schreibberechtigungen für diese Freigabe hat.
    Erster Naiver Ansatz: WNetAddConnection:

    bool check_share_access()
    {
       NETRESOURCE net_res;
       ::SecureZeroMemory( &net_res, sizeof( net_res ) );
       net_res.dwType = RESOURCETYPE_DISK;
       net_res.lpLocal = nullptr;
       net_res.lpRemote = "\\\\server1\\share";
       return ::WNetAddConnection( &net_res, nullptr, nullptr ) == ERROR_SUCCESS;
    }
    

    Komischerweise liefert mit die Funktion true zurück, obwohl der aktuelle Benutzer keinen Zugriff auf die Freigabe hat. Ich glaube, hier wird nur geprüft, ob es eine Freigabe gibt und erst bei tatsächlichen Dateizugriffen im freigegebenen Order werden die Zugriffsrechte überprüft. Solange es eine Freigabe mit diesem Namen gibt liefert mir die Funktion true zurück, unabhängig von den Zugriffsrechten darauf.

    Zweiter Naiver Ansatz: GetNamedSecurityInfo

    bool check_access()
    {
        PACL acl = nullptr;
        PSECURITY_DESCRIPTOR sd = nullptr;
        DWORD r = ::GetNamedSecurityInfo( "\\\\server1\\share", SE_LMSHARE, DACL_SECURITY_INFORMATION, nullptr, nullptr, &acl, nullptr, &sd );
        // hier ist r = 5 (Access denied) .... wat nu?
    }
    

    Der Aufruf in Zeile 5 schlägt mit dem Fehlercode 5 fehl (Access denied). Ich kriege also nichtmal Informationen darüber, wer Zugriff auf die Freigabe hat.

    Hat jemand eine Ahnung, über welche WINAPI Funktionen ich diese Funktion implementieren kann?

    bool check_access( const std::string& share_name, DWORD access_mode )
    {
        // Magic happens here
        return retval;
    }
    
    int main()
    {
        bool b1 = check_access( "\\\\server1\\share", GENERIC_READ );
        bool b2 = check_access( "\\\\server1\\share", GENERIC_WRITE );
    }
    


  • Man kann bei Windows-Freigaben an zwei Stellen Berechtigungen einstellen. Erstmal bei der Freigabe selbst und dann die üblichen File-System Berechtigungen auf dem freigegebenen Ordner (bzw. den sich darin befindlichen Dateien/Unterverzeichnissen). Eine oft verwendete Praktik ist es auf der Freigabe selbst "full access" für "Everyone" herzugeben, und dann alles über die File-System Berechtigungen zu regeln.

    Wenn das so eingestellt sein sollte, könnte ich mir gut vorstellen dass WNetAddConnection noch funktioniert, weil der Benutzer ja grundsätzlich Zugriff auf die Freigabe hat -- bloss nicht auf die darüber erreichbaren File-System Objekte (Verzeichnisse, Dateien). (EDIT: Und auch sonst könnte ich mir vorstellen dass WNetAddConnection funktioniert. Ich sehe nichtmal nen Grund warum es fehlschlagen sollte nur weil die Freigabe nicht existiert. Speziell wenn man nen Laufwerksbuchstaben mappt. /EDIT)

    Aber egal.

    Die viel wichtigere Frage ist: Was genau willst du überhaupt prüfen und zu welchem Zweck? Man kann in Windows nämlich dummerweise sehr viele komische Einstellungen diesbezüglich machen. Z.B. kannst du einen Benutzer erlauben irgendwo Files zu erzeugen die er dann danach aber nichtmal mehr auflisten geschweige denn aufmachen kann. Oder du kannst jmd. verbieten ein Verzeichnis aufzulisten aber gleichzeitig erlauben Files in diesem Verzeichnis aufzumachen (neue, aber auch bestehende wenn er irgendwoher den Namen weiss). Oder erlauben Files zu schreiben aber verbieten die selben Files zu lesen.

    Versuche vorab irgendwie abzufragen ob alle nötigen Berechtigungen da sind führen meist dazu dass das Programm dadurch mehr Berechtigungen benötigt als eigentlich nötig wären. (z.B. die Berechtigung die Berechtigungen auszulesen)



  • @hustbaer
    Wir haben ein Archivsystem, das automatisch Dateien aus dem Netzwerk einsammelt und auf einem FileServer ablegt. Dazu gibt es eine Reihe Quell- und Zielnetzwerkfreigaben, die die Software benutzt, um Dateien zu kopieren. Von der Quellfreigabe werden einfach Dateien in die Zielfreigabe kopiert. In der Konfiguration kann man für jede Freigabe zusätzlich einen Benutzernamen und Kennwort eingeben, um auf möglicherweise geschützte Freigaben zugreifen zu können. Es gibt einen "Test"-Button, mit dem der Zugriff auf die Freigaben getestet werden kann. Und genau da bin ich jetzt: Der Test mit Freigabennamen, Benutzernamen und Kennwort gelingt, aber die Software meldet beim Schreiben, dass sie keine Schreibrechte für die Freigabe hat. Beim ersten Angucken habe ich dann das Verhalten aus dem Eingangspost festgestellt.
    Der Test in der jetzigen Form ist natürlich sinnlos, er überprüft ja eigentlich nur, ob es die Freigabe und die Kombination aus Benutzernamen und Kennwort gibt. Ob das Lesen/Schreiben gelingt lässt sich darüber ja nicht feststellen. Daher jetzt die Frage: WIE überprüfe ich, ob effektiv Lesen- oder Schreiboperationen erlaubt sind?
    Naiv könnte ich beim Schreiben einfach eine temporäre Datei erzeugen und wenn GetLastError() iwas außer ERROR_ACCESS_DENIED liefert habe ich Schreibrechte. Wie das beim Lesen aussehen soll weiß ich nicht, weil ich nicht davon ausgehen kann, dass sich im freigegebenen Verzeichnis eine Datei befindet, die ich zum Lesen öffnen könnte.



  • OK, verstehe. Die einfachste "Lösung" wäre natürlich den Test-Button zu entfernen. Wie man am besten prüft ob man was lesen könnte wenn es denn was zu lesen gäbe kann ich dir leider nicht sagen. Nur Sonderfälle die den Test ad-absurdum führen 😉

    Wäre es evtl. möglich statt des Tests einen ganz normalen Backup-Lauf zu machen? Oder evtl. einen Backup-Lauf der nach den ersten paar Dateien abbricht (damit man nicht so lange warten muss) und dann meldet was kopiert wurde (damit man sehen kann ob überhaupt Dateien gefunden wurden) und ob dabei irgendwelche Fehler aufgetreten sind. Dabei könnte man auch das Test-Backup in ein eigenes Unterverzeichnis durchführen das nach dem Test wieder gelöscht wird -- damit man das ganze wiederholt durchführen kann und dabei das normale Backup nicht "stört" (z.B. wenn das Backup schon mal gelaufen war und sich bloss die nötigen Credentials geändert haben).

    100% sicher ist das natürlich auch nicht, da es auch Berechtigungen auf Unterverzeichnissen geben kann. Nur dass ich in \\server\share\x lesen bzw. schreiben kann heisst ja nicht dass ich auch in \\server\share\x\y oder \\server\share\z lesen/schreiben kann.

    Und natürlich erfordert das dass im Source Verzeichnis bereits mindestens ein File liegt, aber das ist vielleicht eine Einschränkung mit der man leben kann. Und für Fälle wo die Files im Source Verzeichnis riesig sind (und man daher beim Test ewig warten müsste) könnte man den Test ja so anpassen dass er nur die ersten X kB kopiert.


  • Mod

    @DocShoe sagte in Zugriffsberechtigungen für Netzwerkfreigabe prüfen:

    WNetAddConnection

    Du könnest versuchen einfach das Directory Objekt selbst zum Schreiben zu öffnen, dann müsstest Du eigentlich auch direkt einen Fehler erhalten. Das passiert jetzt einfach mit dem Befehl, ohne das Du testweise Schreiben musst.

    Gleichfalls solltest Du mal den folgenden Syntax für den Pfad versuchen:

    "\\\\server1\\share\\.";
    

    Testcode ungeprüft

    h1 = CreateFileW(
      L"\\\\Server1\\Share\\.", // Note the "\\."
      FILE_ADD_FILE | SYNCHRONIZE, // or FILE_ADD_SUBDIRECTORY | SYNCHRONIZE
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // Don't lock
      NULL,
      OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS, // Allows opening directory handles
      NULL);
    if (h1 && h1 != INVALID_HANDLE_VALUE) {
      CloseHandle(h1);
      return TRUE:
    }
    


  • Warum nicht einfach eine dummy Datei dorthinschreiben und das Rückgabeergebniss prüfen? Wenn das passt kann man dann auch noch die Leseberechtigung prüfen.



  • @der-Quaker Ja der Schreibende Teil ist ja noch eher einfach zu prüfen. Nur wie prüfst du den Lesenden in dem Fall dass das Verzeichnis beim Einrichten des Backup noch leer ist?


  • Mod

    Naja, man bekommt auch . nicht gelesen, wenn man keinen Lesezugriff hat, oder?
    (Ich meine den Verweis auf das eigene Verzeichnis..., bin mir nicht ganz sicher)



  • Kommt drauf an wie genau man es haben möchte. Es kann durchaus sein dass man die Berechtigung hat das Verzeichnis aufzulisten, aber nicht die Files darin zu lesen.



  • @hustbaer
    Du gehst jetzt von einer völlig vermurksten Rechtevergabe aus, den Fall schließe ich jetzt einfach aus und verlasse mich drauf, dass da kein Quatsch gemacht wird. Ich werde in den nächsten Tagen eure Vorschläge ausprobieren und mich dann zu diesem Thema zurückmelden.
    Danke für die Hinweise.



  • So,

    ich habe jetzt Martins Vorschlag umgesetzt und bin mit dem Ergebnis zufrieden. Ich versuche per CreateFile mit GENERIC_READ bzw. GENERIC_WRITE auf das Verzeichnis der Freigabe zuzugreifen ( "\\server\share\." ). Bisher verhält sich das so, wie man es erwarten würde. Und da das Ganze auch nur zum Testen ist stecke ich da auch nicht mehr Arbeit rein.


Anmelden zum Antworten