@@ -1785,82 +1785,199 @@ bool git_fs_path_supports_symlinks(const char *dir)
17851785 return supported ;
17861786}
17871787
1788- int git_fs_path_validate_system_file_ownership (const char * path )
1788+ #ifdef GIT_WIN32
1789+ static PSID * sid_dup (PSID sid )
17891790{
1790- #ifndef GIT_WIN32
1791- GIT_UNUSED (path );
1792- return GIT_OK ;
1793- #else
1794- git_win32_path buf ;
1795- PSID owner_sid ;
1796- PSECURITY_DESCRIPTOR descriptor = NULL ;
1797- HANDLE token ;
1798- TOKEN_USER * info = NULL ;
1799- DWORD err , len ;
1800- int ret ;
1791+ DWORD len ;
1792+ PSID dup ;
18011793
1802- if (git_win32_path_from_utf8 (buf , path ) < 0 )
1803- return -1 ;
1794+ len = GetLengthSid (sid );
18041795
1805- err = GetNamedSecurityInfoW (buf , SE_FILE_OBJECT ,
1806- OWNER_SECURITY_INFORMATION |
1807- DACL_SECURITY_INFORMATION ,
1808- & owner_sid , NULL , NULL , NULL , & descriptor );
1796+ if ((dup = git__malloc (len )) == NULL )
1797+ return NULL ;
18091798
1810- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ) {
1811- ret = GIT_ENOTFOUND ;
1812- goto cleanup ;
1799+ if (!CopySid (len , dup , sid )) {
1800+ git_error_set (GIT_ERROR_OS , "could not duplicate sid" );
1801+ git__free (dup );
1802+ return NULL ;
18131803 }
18141804
1815- if (err != ERROR_SUCCESS ) {
1816- git_error_set (GIT_ERROR_OS , "failed to get security information" );
1817- ret = GIT_ERROR ;
1818- goto cleanup ;
1805+ return dup ;
1806+ }
1807+
1808+ static int current_user_sid (PSID * out )
1809+ {
1810+ TOKEN_USER * info = NULL ;
1811+ HANDLE token = NULL ;
1812+ DWORD len = 0 ;
1813+ int error = -1 ;
1814+
1815+ if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY , & token )) {
1816+ git_error_set (GIT_ERROR_OS , "could not lookup process information" );
1817+ goto done ;
18191818 }
18201819
1821- if (! IsValidSid ( owner_sid )) {
1822- git_error_set ( GIT_ERROR_INVALID , "programdata configuration file owner is unknown" );
1823- ret = GIT_ERROR ;
1824- goto cleanup ;
1820+ if (GetTokenInformation ( token , TokenUser , NULL , 0 , & len ) ||
1821+ GetLastError () != ERROR_INSUFFICIENT_BUFFER ) {
1822+ git_error_set ( GIT_ERROR_OS , "could not lookup token metadata" ) ;
1823+ goto done ;
18251824 }
18261825
1826+ info = git__malloc (len );
1827+ GIT_ERROR_CHECK_ALLOC (info );
1828+
1829+ if (!GetTokenInformation (token , TokenUser , info , len , & len )) {
1830+ git_error_set (GIT_ERROR_OS , "could not lookup current user" );
1831+ goto done ;
1832+ }
1833+
1834+ if ((* out = sid_dup (info -> User .Sid )))
1835+ error = 0 ;
1836+
1837+ done :
1838+ if (token )
1839+ CloseHandle (token );
1840+
1841+ git__free (info );
1842+ return error ;
1843+ }
1844+
1845+ static int file_owner_sid (PSID * out , const char * path )
1846+ {
1847+ git_win32_path path_w32 ;
1848+ PSECURITY_DESCRIPTOR descriptor = NULL ;
1849+ PSID owner_sid ;
1850+ DWORD ret ;
1851+ int error = -1 ;
1852+
1853+ if (git_win32_path_from_utf8 (path_w32 , path ) < 0 )
1854+ return -1 ;
1855+
1856+ ret = GetNamedSecurityInfoW (path_w32 , SE_FILE_OBJECT ,
1857+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION ,
1858+ & owner_sid , NULL , NULL , NULL , & descriptor );
1859+
1860+ if (ret == ERROR_FILE_NOT_FOUND || ret == ERROR_PATH_NOT_FOUND )
1861+ error = GIT_ENOTFOUND ;
1862+ else if (ret != ERROR_SUCCESS )
1863+ git_error_set (GIT_ERROR_OS , "failed to get security information" );
1864+ else if (!IsValidSid (owner_sid ))
1865+ git_error_set (GIT_ERROR_OS , "file owner is not valid" );
1866+ else if ((* out = sid_dup (owner_sid )))
1867+ error = 0 ;
1868+
1869+ if (descriptor )
1870+ LocalFree (descriptor );
1871+
1872+ return error ;
1873+ }
1874+
1875+ int git_fs_path_owner_is_current_user (bool * out , const char * path )
1876+ {
1877+ PSID owner_sid = NULL , user_sid = NULL ;
1878+ int error = -1 ;
1879+
1880+ if ((error = file_owner_sid (& owner_sid , path )) < 0 ||
1881+ (error = current_user_sid (& user_sid )) < 0 )
1882+ goto done ;
1883+
1884+ * out = EqualSid (owner_sid , user_sid );
1885+ error = 0 ;
1886+
1887+ done :
1888+ git__free (owner_sid );
1889+ git__free (user_sid );
1890+ return error ;
1891+ }
1892+
1893+ int git_fs_path_owner_is_system (bool * out , const char * path )
1894+ {
1895+ PSID owner_sid ;
1896+
1897+ if (file_owner_sid (& owner_sid , path ) < 0 )
1898+ return -1 ;
1899+
1900+ * out = IsWellKnownSid (owner_sid , WinBuiltinAdministratorsSid ) ||
1901+ IsWellKnownSid (owner_sid , WinLocalSystemSid );
1902+
1903+ git__free (owner_sid );
1904+ return 0 ;
1905+ }
1906+
1907+ int git_fs_path_owner_is_system_or_current_user (bool * out , const char * path )
1908+ {
1909+ PSID owner_sid = NULL , user_sid = NULL ;
1910+ int error = -1 ;
1911+
1912+ if (file_owner_sid (& owner_sid , path ) < 0 )
1913+ goto done ;
1914+
18271915 if (IsWellKnownSid (owner_sid , WinBuiltinAdministratorsSid ) ||
18281916 IsWellKnownSid (owner_sid , WinLocalSystemSid )) {
1829- ret = GIT_OK ;
1830- goto cleanup ;
1917+ * out = 1 ;
1918+ error = 0 ;
1919+ goto done ;
18311920 }
18321921
1833- /* Obtain current user's SID */
1834- if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY , & token ) &&
1835- !GetTokenInformation (token , TokenUser , NULL , 0 , & len )) {
1836- info = git__malloc (len );
1837- GIT_ERROR_CHECK_ALLOC (info );
1838- if (!GetTokenInformation (token , TokenUser , info , len , & len )) {
1839- git__free (info );
1840- info = NULL ;
1841- }
1922+ if (current_user_sid (& user_sid ) < 0 )
1923+ goto done ;
1924+
1925+ * out = EqualSid (owner_sid , user_sid );
1926+ error = 0 ;
1927+
1928+ done :
1929+ git__free (owner_sid );
1930+ git__free (user_sid );
1931+ return error ;
1932+ }
1933+
1934+ #else
1935+
1936+ static int fs_path_owner_is (bool * out , const char * path , uid_t * uids , size_t uids_len )
1937+ {
1938+ struct stat st ;
1939+ size_t i ;
1940+
1941+ * out = false;
1942+
1943+ if (p_lstat (path , & st ) != 0 ) {
1944+ if (errno == ENOENT )
1945+ return GIT_ENOTFOUND ;
1946+
1947+ git_error_set (GIT_ERROR_OS , "could not stat '%s'" , path );
1948+ return -1 ;
18421949 }
18431950
1844- /*
1845- * If the file is owned by the same account that is running the current
1846- * process, it's okay to read from that file.
1847- */
1848- if (info && EqualSid (owner_sid , info -> User .Sid ))
1849- ret = GIT_OK ;
1850- else {
1851- git_error_set (GIT_ERROR_INVALID , "programdata configuration file owner is not valid" );
1852- ret = GIT_ERROR ;
1951+ for (i = 0 ; i < uids_len ; i ++ ) {
1952+ if (uids [i ] == st .st_uid ) {
1953+ * out = true;
1954+ break ;
1955+ }
18531956 }
1854- git__free (info );
18551957
1856- cleanup :
1857- if (descriptor )
1858- LocalFree (descriptor );
1958+ return 0 ;
1959+ }
18591960
1860- return ret ;
1861- #endif
1961+ int git_fs_path_owner_is_current_user (bool * out , const char * path )
1962+ {
1963+ uid_t userid = geteuid ();
1964+ return fs_path_owner_is (out , path , & userid , 1 );
18621965}
18631966
1967+ int git_fs_path_owner_is_system (bool * out , const char * path )
1968+ {
1969+ uid_t userid = 0 ;
1970+ return fs_path_owner_is (out , path , & userid , 1 );
1971+ }
1972+
1973+ int git_fs_path_owner_is_system_or_current_user (bool * out , const char * path )
1974+ {
1975+ uid_t userids [2 ] = { geteuid (), 0 };
1976+ return fs_path_owner_is (out , path , userids , 2 );
1977+ }
1978+
1979+ #endif
1980+
18641981int git_fs_path_find_executable (git_str * fullpath , const char * executable )
18651982{
18661983#ifdef GIT_WIN32
0 commit comments