Archives de catégorie : SMB

Path: Dépasser les 260 caractères

Voici un moyen pour gérer les fichiers dont le path dépasse les 260 caractères en utilisant AlphaFS de Alphaleonis (OpenSource sur Github)

Ceci peut générer une exception car la plupart des API et autres cmdlets sont limités à 260 caractères:

Et ceci fonctionnera jusqu’à 32.000 caractères !

Et ceci fonctionnera aussi pour modifier le owner, par exemple:

L’objet $Acl est le même que celui donné par Get-Acl ou (Get-Item $file).GetAccessControl()

Les permissions d’un share

Dans cet article, nous avions exploré les fonctions de Netapi32.dll pour récupérer des informations relatives aux shares SMB.

Nous allons maintenant voir comment récupérer les permissions de ces shares.

Il existe des fonctions qui gèrent les SIDs, ACLs, et ACEs dans advapi32.dll, et nous allons capitaliser sur l’article concernant le Netapi pour en faire un tout, et lire les permissions sans passer par WMI.

Tout d’abord voici une nouvelle version du script netapi.ps1:

Il faudra avec cette version dot-sourcer le script pour que les cmdlets soient définies:

 

Une fois les cmdlets définies nous allons avoir besoin de celle qui récupère le level 502 des shares:

et avec cet array, nous allons pour chaque élément vérifier si le SecurityDescriptor est présent. Pour ensuite récupérer l’ACL dans un buffer en mémoire.

A partir de l’ACL nous pouvons récupérer l’ACE qui contient le SID et la permission.

Avec un peu de gymnastique de pointeurs et buffers de structures, nous allons pouvoir traduire tout cela en objets Powershell qui peuvent être utilisés.

Voici le script complet:

L’output est simple mais peut être adapté:

Sans les mains WMI.

Voici l’article de référence en C# qui traite de ce sujet http://blogs.msdn.com/b/dsadsi/archive/2012/03/30/to-read-shared-permissions-of-a-server-resource-in-c-using-netsharegetinfo.aspx

Voici un mise à jour du script d’exemple, cette nouvelle version traite le problème de l’exception « Some or all identity references could not be translated. ».

Pour régler ce problème nous allons récupérer la liste des utilisateurs locaux d’une machine donnée et comparer les SIDs sans passer par Translate.

 

Voici le script en entier (renseigner $server en début du script):

 

Taille d’un répertoire revisité

 

Lorsque j’ai répondu à une question sur Stack Overflow concernant la récupération de la taille d’un répertoire, j’ai réalisé qu’en plus de la méthode classique qui consiste à calculer la taille du répertoire en fonction de la taille des fichiers qu’il contient (et dont j’avais écrit à ce propos ici), et bien, il y a une autre méthode bien plus rapide à coder, en utilisant un objet de type: Scripting.FileSystemObject.

Avec cet objet nous pouvons appeler la méthode GetFolder ce qui nous rend un objet COM qui contient la méthode Size. Cette méthode nous donne la taille du répertoire voulu.

Du coup j’ai écrit une fonction qui permet de récupérer les répertoires dont la taille est au moins celle demandée (en GB dans le code ci-dessous).

 

Pour l’exécuter il suffit de l’appeler ainsi, par exemple:

Partager ce contenu

Comparer les ACL de deux arborescences

Voici une cmdlet bien utile qui permet de comparer les ACL de deux arborescences de répertoires. C’est particulièrement utile pour s’assurer qu’une opération avec un outil de copie, comme EMCopy ou Robocopy, ait bien placé les ACL sur les répertoires cible.

Pour l’utiliser:

Compare-ACL -source <répertoire source> -target <répertoire cible>

Partager ce contenu

Quotas d’un répertoire

C’est quoi un quota. C’est une limite. On définit souvent ces limites dans des shares pour gérer ce que les utilisateurs peuvent générer comme place disque à l’usage.

Il existe deux grandes familles de quotas dans le monde Windows.
Les Volume quotas, et les Folder quotas.

Les Folder quotas sont aux Volume quotas, ce que le Barça est à l’Amicale de Puteaux. Aucune offense, mais Messi c’est Messi, et le FSRM est l’outil indispensable quand on veut gérer des shares dans une entreprise.

Les volumes quota c’est ce qu’on a quand on veut juste créer des quotas sur des disques et c’est tout.

Les folder quotas sont des quotas par répertoire. C’est le moyen de vendre de la place disque et de la manager à travers des shares. Les entreprises ont des milliers de ces shares là.

Cette cmdlet requiert l’installation du rôle FSRM. Sans ça, nous ne pourrons pas créer d’objets de type :

Cette cmdlet prend en input et à travers de pipelines des paths, et pour ces paths elle nous rendra les Folder Quotas en cours.

Quelques exemples d’utilisation:

Voici le script complet:

Taille d’un répertoire

Dans cet article j’ai voulu revenir sur la création de cmdlets et plus particulièrement le paramètre switch. 

Voyons cette déclaration de fonction:

Cette fonction appelée Get-FolderSize a pour but de parcourir une arborescence de répertoires et retourner la taille totale.

Elle définit un paramètre qui peut être passé par le pipeline et qui est un string appelé $Name, c’est le nom du folder (répertoire) à traiter.

Elle définit aussi un paramètre appelé $Folder, qui est un objet de type System.IO.FileSystemInfo. Ca tombe bien, c’est ce que retourne un appel à la cmdlet Get-Item. Et qui peut être passé sans transition à notre cmdlet via un pipe.

Du coup notre cmdlet peut recevoir une simple chaine de caractères ou un objet complexe et saura se débrouiller.

Avec les tailles, surtout les grandes tailles, il n’est pas facile d’un coup d’œil  de savoir combien de zéros il y a après le premier chiffre, parlons nous de milliers, de millions, de milliards de milliards comme disait Carl Sagan?

En informatique nous pouvons réduire la voilure sur les chiffres de façon radicale en transformant l’unité en Giga-octets, Tera-octets etc. C’est le but des switchs à la fin de la déclaration de la fonction. MB pour mega-octets, GB pour giga-octets et TB pour tera-octets.

Un paramètre de type switch, est un argument sans valeur, donc ne pas confondre avec un booléen car ça n’en est pas un.

Regardons ce switch de plus près.

Il s’agit d’un type SwitchParameter et si on regarde sa valeur:

On voit seulement s’il est présent.

Pour le tester on utilisera un if tout simplement.

Si le switch est présent, nous allons diviser le nombre de bytes par 1MB, 1GB ou 1TB en fonction du switch. Powershell saura quoi faire et nous rendra la valeur en mega, giga ou tera.

Quelques exemples d’exécution du script.

Voici une exécution sans switch, la fonction retourne des bytes.

Exécution avec Giga-octets en retour.

Mega-octets.

Et voici le script en entier.

Se rappeler d’exécuter le script avant d’appeler la cmdlet, sinon elle ne sera pas définie.

Partager ce contenu

Netapi et Powershell

Ecrit par @mickyballadelli

Dans mon précèdent blog, J’ai écrit un script qui s’interfaçait avec la DLL Netapi32.dll pour utiliser la fonction NetShareEnum. Dans cette nouvelle version j’ai étendu l’idée à plusieurs fonctions intéressantes de Netapi32.dll. Les fonctions traitées sont NetShareEnum, NetStatisticsGet, NetConnectionEnum et NetFileEnum.

Autre but de ce script est de créer des cmdlets à travers les fonctions Powershell et gérer les sets de paramètres pour permettre une utilisation facile de ces fonctions.

Get-Shares utilise NetShareEnum pour lister les partages réseau d’un serveur.

Get-Statistics utilise NetStatisticsGet pour lister les stats serveur ou workstation tels que les transferts réseaux, temps de démarrage etc.

Get-Sessions utilise NetConnectionEnum pour lister l’historique des sessions ouvertes sur un poste.

Get-OpenFiles utilise NetFileEnum pour lister les fichiers actuellement ouverts sur une machine.

Ces fonctions utilisent les paramètres par défaut, ce qui simplifie utilisation.

A noter le header du fichier qui permet une intégration automatique avec Get-Help :

NOM
Get-Shares

SYNTAXE
Get-Shares [[-server] <string>] [[-level] <int>]  [<CommonParameters>]

ALIAS
Aucun(e)

REMARQUES
Aucun(e)

 

Partager ce contenu

Enumération de shares SMB

Ecrit par @mickyballadelli

Avec l’utilisation en production de serveurs NAS il n’est souvent plus possible d’utiliser les commandes WMI pour récupérer la liste des Shares.

Ce script se base sur le protocole Remote Administration Protocol (MS-RAP) qui lui-même se base sur SMB pour exécuter la commande NetShareEnum et lister les Shares sur un serveur donné.

Les paramètres du script sont, le nom du serveur à interroger (avec localhost par défaut), le niveau de détail en retour souhaité

Pour la définition du niveau de détail Microsoft s’appuie sur des structures qu’on va devoir déclarer dans notre script afin de nous accorder avec la taille des buffers que la commande NetShareEnum va nous renvoyer. Nous allons nous appuyer sur les déclarations style C# afin de créer notre namespace et pouvoir appeler la fonction NetShareEnum ainsi qu’avoir le retour souhaité avec les déclarations des structures de différents niveaux.

Pour cela nous allons utiliser Add-type qui nous permet de créer un namespace .NET au sein de notre script.

Le bloc de texte est délimité par @ » et « @ car il comporte plusieurs lignes. Ce bloc de texte est en fait du C# qui sera compilé on the fly lors de l’exécution du script.

On commence par déclarer les librairies .NET dont nous allons avoir besoin :

System est la librairie de base qui contient la gestion des exceptions ainsi que la définition des types de données fondamentales pour .NET.

System.Runtime.InteropServices contient tous les services d’interopérabilité entre objets COM et autres services et s’assure de la gestion des variables managées (Managed) versus les variables non-managées (Unmanaged). La différence étant qu’une variable exécutée dans le runtime du framework .NET est managée et une variable qui est utilisée en dehors de ce runtime sera non-managée. Managée veut simplement dire gérée par .NET (dans son CLR), c’est-à-dire que chaque variable est checkée et la gestion de la mémoire comme le garbage collection sont prise en charge par le framework. Unmanaged code veut dire que vous êtes en pleine descente et personne ne vous a fourni de freins, à vous d’y avoir pensé.

Nous définissons notre classe:

Et nous déclarons que nos structures sont séquentielles. Ceci indique au compilateur que la taille de notre structure est telle que nous l’avons définie, et le compilateur n’ajoutera pas d’octets pour aligner la mémoire (padding), ce qui grossirait la structure en mémoire et nous ne saurions plus forcément la référencer correctement.

Nous déclarons aussi que nos caractères sont stockés sur deux bytes au lieu d’un pour le format ANSI.

Finalement nous déclarons nos structures :

La structure plus simple déclare un nom, qui sera le nom du Share, et on signale au compilateur qu’il sera un Long Pointeur vers une large (Wide) chaîne de caractères LPWStr.

Nous allons faire de même avec les structures des autres niveaux de détail.

Ensuite nous allons déclarer la fonction NetShareEnum et l’importer à partir d’une DLL (Netapi32.dll) où elle se trouve.

NetShareEnum alloue de la mémoire (qui sera référencée par le pointeur bufptr) et il incombera de la libérer après utilisation. Donc on déclare la fonction à cet effet, NetApiBufferFree:

Voilà, notre namespace est déclaré et nous pouvons y accéder à travers Powershell via la commande [netapi]::NetShareEnum.

Nous déclarons ensuite un objet $struct qui sera créé en fonction du choix du niveau de détail souhaité :

Nous allons maintenant faire un peu d’arithmétique de pointeurs. Ce qui est chose courante dans des langages comme le C, et l’est beaucoup moins avec des langages de scripting comme Powershell (en tout cas c’est mon expérience).

Généralement , une variable contient une valeur. Un pointeur est une variable qui contient l’adresse en mémoire où se trouve la valeur. Pour être plus précis, une variable classique est définie sur le stack (allocation statique effectuée avant l’exécution du programme) et sa mémoire est libérée lorsque nous quittons son block de code ou fonction. Si nous voulons qu’une variable survive au-delà du bloc de code dans laquelle elle est déclarée, nous devons l’allouer sur le Heap (pile persistante créée de façon dynamique lors de l’exécution du programme).

L’arithmétique de pointeur est une façon de repositionner le pointeur sur la bonne adresse de mémoire.

NetShareEnum alloue suffisamment de mémoire pour tous les shares à retourner, chaque share équivaut à une structure en mémoire. Nous devons donc trouver l’endroit en mémoire ou se trouve le premier élément, on récupère la structure, ensuite on bougera le pointeur en fonction de la taille de la structure, pour trouver l’élément suivant.
Dans le cas le plus simple, la structure contient un pointeur vers une chaine de caractères, donc l’élément suivant se trouvera après la taille (le sizeof) de la première structure (8 bytes). Finalement c’est une simple addition.

Voyons tout ça étape par étape.

On appelle la fonction NetShareEnum en passant le paramètre $buffer par référence, ceci fait en sorte que le contenu de notre variable est mis à jour par la fonction avec l’adresse de la mémoire allouée. Sans ce [ref], une nouvelle variable serait créée sur le stack et passée à la fonction sans que nous puissions récupérer l’adresse du buffer.

Une fois la fonction exécutée, on récupère l’adresse du buffer en mémoire, la variable $buffer contient cette information qu’on transforme en Int64 :

On crée un objet $ptr qui pointe vers cette mémoire, voici comment le créer :

Le constructeur d’un objet IntPtr prend comme argument une adresse, nous avons notre pointeur.

Nous allons récupérer le contenu de la structure à partir du pointeur, Powershell créera un objet qu’on ajoutera à un array:

Nous allons maintenant calculer la taille de la structure, ceci permettra de repositionner le pointeur correctement une fois utilisé :

Nous calculons le nouveau offset, en ajoutant à l’adresse la taille de la structure, nous utiliserons cet offset pour créer un nouveau pointeur qui sera positionné sur l’élément suivant.

Et on boucle pour tous les éléments retournés.

Finalement on formate en tableau, à titre d’exemple, l’array $shares.

Voici le script complet:

Partager ce contenu