Lister les users et les permissions des dossiers partagés d'un ordi réseau (ou pas : ))

Description

N'ayant pas eu de réponse suite à une question sur le forum sur comment lister les permissions de tous les users des dossiers partagés d'un ordi, il a bien fallu que je démerde +/- tout seul. Voici donc la solution. Vraiment pas super facile, merci Microsoft, comme d'hab : (((

Source / Exemple :


#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <aclapi.h>
#include <lmshare.h>
#include <Lm.h>
#include "NetEnum.h"

                              /***************************************/
                              /***************************************/
                              /*          CountNetShareEnum          */
                              /***************************************/
                              /***************************************/

DWORD CountNetShareEnum
(
   const char*       p_pcServerName,
   int*              p_TotalOfShareRessource
)
{
   PSHARE_INFO_502               l_PShareInfo, l_BufPShareInfo;
   NET_API_STATUS                l_nStatus;
   DWORD                         l_dwErr=0,l_dwTr=0,l_dwResume=0, i;
   LPWSTR                        l_pwUnicodeServerName = NULL;
   int                           l_iSize;
   try
   {   
      // si on entre un nom de PC, on transforme le nom AINSI en UNICODE
      if (p_pcServerName != NULL)
      {
         l_iSize = strlen (p_pcServerName) + 1;
         l_pwUnicodeServerName = new WORD [l_iSize];
         l_pwUnicodeServerName[0] = 0;
	      MultiByteToWideChar (CP_ACP, 0, p_pcServerName, -1, l_pwUnicodeServerName, l_iSize);
      }

      do // begin do
      {
         // on liste tout ou partie des dossiers partagés de p_pcServerName
         l_nStatus = NetShareEnum (l_pwUnicodeServerName, 502, (LPBYTE *) &l_BufPShareInfo, -1, &l_dwErr, &l_dwTr, &l_dwResume);
         
         if(l_nStatus != ERROR_SUCCESS && l_nStatus != ERROR_MORE_DATA)
            throw l_nStatus;

         // on fait pointer l_PShareInfo sur les données trouvées
         l_PShareInfo=l_BufPShareInfo;

         // pour chaque entrée trouvée (jusqu'à dwErr) on incrémente
         for(i=1;i<=l_dwErr;i++)
         {
            l_PShareInfo++;
            (*p_TotalOfShareRessource) ++;
         }
         
         // on libère le buffer
         NetApiBufferFree(l_BufPShareInfo);
      }
      while (l_nStatus==ERROR_MORE_DATA);
   }
   catch (DWORD)
   {
   }
   return l_nStatus;
}

                              /***************************************/
                              /***************************************/
                              /*          CountNetShareEnum          */
                              /***************************************/
                              /***************************************/

DWORD RetrieveNetShareEnum
(
   const char*       p_pcServerName,
   const int         p_TotalOfShareRessource,
   int*              p_piCurrentIndex,
   STL_SHARE_INFO*   p_ShareInfoArray
)
{
   PSHARE_INFO_502               l_PShareInfo, l_BufPShareInfo;
   NET_API_STATUS                l_nStatus;
   DWORD                         l_dwCount=0,l_dwTr=0,l_dwResume=0, i;
   DWORD                         l_dwRetVal;
   LPWSTR                        l_pwUnicodeServerName = NULL;
   LPWSTR                        l_pwUnicodeRemark = NULL;
   LPWSTR                        l_pwUnicodePath = NULL;
   LPWSTR                        l_pwUnicodePassword = NULL;
   BOOL                          l_bRetVal;
   PACL                          l_Dacl;
   int                           l_iSize, l_iTotalEntriesIndex;
   unsigned long                 l_ulNbOfEntries = 0;
   PEXPLICIT_ACCESS              l_oAccessArray = NULL;

   try
   {        
      // si on entre un nom de PC, on transforme le nom AINSI en UNICODE 
      if (p_pcServerName != NULL)
      {
         l_iSize = strlen (p_pcServerName) + 1;
         l_pwUnicodeServerName = new WORD [l_iSize];
         l_pwUnicodeServerName[0] = 0;
	      MultiByteToWideChar (CP_ACP, 0, p_pcServerName, -1, l_pwUnicodeServerName, l_iSize);
      }
      
      // on mets le compteur à 0

  • p_piCurrentIndex = 0;
do // begin do { // on récupère une partie des dossiers réseaux l_nStatus = NetShareEnum (l_pwUnicodeServerName, 502, (LPBYTE *) &l_BufPShareInfo, -1, &l_dwCount, &l_dwTr, &l_dwResume); if(l_nStatus != ERROR_SUCCESS && l_nStatus != ERROR_MORE_DATA) throw l_nStatus; l_PShareInfo=l_BufPShareInfo; // pour tous les dossiers trouvés, on va recopier les infos pertinentes dans notre structure STL_SHARE_INFO for(i=1;i<=l_dwCount;i++) { // on convertit du unicode en char pour récupérer le netname l_dwRetVal = WideCharToMultiByte ( CP_ACP, WC_NO_BEST_FIT_CHARS, l_PShareInfo->shi502_netname, -1, p_ShareInfoArray[*p_piCurrentIndex].cNetname, _MAX_PATH, NULL, NULL); if (l_dwRetVal == 0) throw (DWORD) "STL_UNICODE_TO_AINSI_ERROR"; // on teste la validité du SID afin de ne pas lister des infos inexistantes (et faire tout exploser) // si le SID est invalide (NULL notamment) l_bRetVal = IsValidSecurityDescriptor(l_PShareInfo->shi502_security_descriptor); // si le SID est valide, on liste les infos if (l_bRetVal != 0) { int size = strlen (p_ShareInfoArray[*p_piCurrentIndex].cNetname) - 1; if (p_ShareInfoArray[*p_piCurrentIndex].cNetname[size] != '$') { // comme ce sont les values DWORD, on fait une copie brute de fonte p_ShareInfoArray[*p_piCurrentIndex].dwType = l_PShareInfo->shi502_type; p_ShareInfoArray[*p_piCurrentIndex].dwPermissions = l_PShareInfo->shi502_permissions; p_ShareInfoArray[*p_piCurrentIndex].dwMax_uses = l_PShareInfo->shi502_max_uses; p_ShareInfoArray[*p_piCurrentIndex].dwCurrent_uses = l_PShareInfo->shi502_current_uses; p_ShareInfoArray[*p_piCurrentIndex].dwReserved = l_PShareInfo->shi502_reserved; // pour les vlaues en unicode, on fait la transformation en AINSI l_dwRetVal = WideCharToMultiByte ( CP_ACP, WC_NO_BEST_FIT_CHARS, l_PShareInfo->shi502_remark, -1, p_ShareInfoArray[*p_piCurrentIndex].cRemark, _MAX_PATH, NULL, NULL); if (l_dwRetVal == 0) throw (DWORD) "STL_UNICODE_TO_AINSI_ERROR"; l_dwRetVal = WideCharToMultiByte ( CP_ACP, WC_NO_BEST_FIT_CHARS, l_PShareInfo->shi502_path, -1, p_ShareInfoArray[*p_piCurrentIndex].cPath, _MAX_PATH, NULL, NULL); if (l_dwRetVal == 0) throw (DWORD) "STL_UNICODE_TO_AINSI_ERROR"; BOOL l_bDaclPresent, l_bDaclDefault; /******************************************************************************************/ /* A cet endroit, si le l_PShareInfo->shi502_security_descriptor est NULL (ou le */ /* l_PShareInfo->shi502_reserved est = 0 (ils semblent marcher ensemble...) cela crash le */ /* le systeme completement. Ceci peut être bypassé en délétant le rep à pb et en le */ /* recréant... Bizarre, vous avez dit bizarre :D:D:D */ /******************************************************************************************/ // on récupère le Dacl lié au SID? C'est dans ce Dacl que l'on va trouver les infos de partage et de persmissions.... l_bRetVal = GetSecurityDescriptorDacl(l_PShareInfo->shi502_security_descriptor, &l_bDaclPresent, &l_Dacl, &l_bDaclDefault); if (l_bRetVal == 0) throw (DWORD) "STL_DACL_ERROR"; // on liste de façon explicite les permissions et users. La fonction renvoie un tableau de ExplicitEntries l_dwRetVal = GetExplicitEntriesFromAcl ( l_Dacl, &l_ulNbOfEntries, &l_oAccessArray); if (l_dwRetVal != 0) throw l_dwRetVal; // pour chaque entrée dans le tableau de EXPLICIT_ACCESS, on regarde si le trustee est identifié par un username, et si oui, on récupère le username et les droits d'accès for (l_iTotalEntriesIndex = 0; l_iTotalEntriesIndex < (int) l_ulNbOfEntries; l_iTotalEntriesIndex ++) { // on copie le p_ShareInfoArray[*p_piCurrentIndex].aEnumUserRights[l_iTotalEntriesIndex].AccessRights = l_oAccessArray[l_iTotalEntriesIndex].grfAccessPermissions; if (l_oAccessArray[l_iTotalEntriesIndex].Trustee.TrusteeForm == TRUSTEE_IS_NAME) { // on copie les droits (sous forme de MASK DWORD) strcpy(p_ShareInfoArray[*p_piCurrentIndex].aEnumUserRights[l_iTotalEntriesIndex].cUserName, l_oAccessArray[l_iTotalEntriesIndex].Trustee.ptstrName); } else { char l_cDomainName[_MAX_FNAME]; unsigned long l_ulDomSize = _MAX_FNAME; unsigned long l_ulBufSize = _MAX_FNAME; SID_NAME_USE l_oSIDNameUse; DWORD l_dwErr; // pour chaque entrée du tableau, on va récupérer le Nom du user depuis le SID associé l_bRetVal = LookupAccountSid ( p_pcServerName, l_oAccessArray[l_iTotalEntriesIndex].Trustee.ptstrName, p_ShareInfoArray[*p_piCurrentIndex].aEnumUserRights[l_iTotalEntriesIndex].cUserName, &l_ulBufSize, l_cDomainName, &l_ulBufSize, &l_oSIDNameUse); if (l_bRetVal == 0) { l_dwErr = GetLastError(); throw l_dwErr; } switch (l_oSIDNameUse) { case SidTypeUser : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeUser; break; case SidTypeGroup : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeGroup; break; case SidTypeDomain : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeDomain; break; case SidTypeAlias : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeAlias; break; case SidTypeWellKnownGroup : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeWellKnownGroup; break; case SidTypeDeletedAccount : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeDeletedAccount; break; case SidTypeInvalid : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeInvalid; break; default : p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeUnknown; break; }//end switch } }// end for p_ShareInfoArray[*p_piCurrentIndex].iTotalUserRights = l_iTotalEntriesIndex; LocalFree (l_oAccessArray); (*p_piCurrentIndex) ++; } } else // si pb avec le SID { sprintf(p_ShareInfoArray[(*p_piCurrentIndex)++].cRemark, "ERREUR AVEC LE SID DE CE DOSSIER"); } l_PShareInfo++; } // end for NetApiBufferFree(l_BufPShareInfo); l_BufPShareInfo = NULL; } while (l_nStatus==ERROR_MORE_DATA); } catch (DWORD dwErr) { l_nStatus = dwErr; } // on delete les pointeurs si OK if (l_BufPShareInfo != NULL) NetApiBufferFree(l_BufPShareInfo); return l_nStatus; }

Conclusion :


Ne pas oublier de linker les lib advapi32.lib, mpr.lib et netapi32.lib.
Voila, cela peut peut être servir....

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.