rugged 1.4.2 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca4d518c34a0642302d00faa7d9cebf7a2541f12bf7b19a977e0d51a3c64eee1
4
- data.tar.gz: 447603f2a0c3ea4aec48a107b9026ac1094016e2c1fc3b61a51752d61793fdb5
3
+ metadata.gz: fd9e9d1521fe3c4ead7642651af0bbf071c2b076be3144458d8f11abc58a95b3
4
+ data.tar.gz: 4f1cfdbbd40ec1cf1061a62ee73265b2e3b51b4cdc076096ab90984fa284549d
5
5
  SHA512:
6
- metadata.gz: 33ffc07452cc1463143d34db00d74b9816e82e682d5ae5a26d07e3264a9d0f0f45fc66ebc5ac96d03be69d1ddbb57692dc729cccf2d9755c77a814159540e514
7
- data.tar.gz: 9e83d292922396712035031ebbb606d7185acdd9258b88e56b6d5f8ab4cfd7db6e01afebf0eae1cfe09ee47c123ef23ea64def5012abfb666e47a93d50b01d39
6
+ metadata.gz: 8bb5a3504f11e676cfc01ae0212e8d0e67cd3bf79bf32e73f4d88662e15f1e6997b50ade4cc7cd4d453f55670d921fa00f2feeec17bbfc69e82e31323114a837
7
+ data.tar.gz: 3c1d68d25b56f587ab5e7532d077cc793feebed4d1d90d25b566c7969c326328d0c96d847f90774c2beb0b33de914b7887b0316a1960cd8620133bdc5e451449
@@ -4,5 +4,5 @@
4
4
  # For full terms see the included LICENSE file.
5
5
 
6
6
  module Rugged
7
- Version = VERSION = '1.4.2'
7
+ Version = VERSION = '1.4.3'
8
8
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  cmake_minimum_required(VERSION 3.5.1)
5
5
 
6
- project(libgit2 VERSION "1.4.0" LANGUAGES C)
6
+ project(libgit2 VERSION "1.4.3" LANGUAGES C)
7
7
 
8
8
  # Add find modules to the path
9
9
  set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
@@ -214,7 +214,9 @@ typedef enum {
214
214
  GIT_OPT_SET_ODB_PACKED_PRIORITY,
215
215
  GIT_OPT_SET_ODB_LOOSE_PRIORITY,
216
216
  GIT_OPT_GET_EXTENSIONS,
217
- GIT_OPT_SET_EXTENSIONS
217
+ GIT_OPT_SET_EXTENSIONS,
218
+ GIT_OPT_GET_OWNER_VALIDATION,
219
+ GIT_OPT_SET_OWNER_VALIDATION
218
220
  } git_libgit2_opt_t;
219
221
 
220
222
  /**
@@ -452,6 +454,14 @@ typedef enum {
452
454
  * > to support repositories with the `noop` extension but does want
453
455
  * > to support repositories with the `newext` extension.
454
456
  *
457
+ * opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled)
458
+ * > Gets the owner validation setting for repository
459
+ * > directories.
460
+ *
461
+ * opts(GIT_OPT_SET_OWNER_VALIDATION, int enabled)
462
+ * > Set that repository directories should be owned by the current
463
+ * > user. The default is to validate ownership.
464
+ *
455
465
  * @param option Option key
456
466
  * @param ... value to set the option
457
467
  * @return 0 on success, <0 on failure
@@ -57,7 +57,8 @@ typedef enum {
57
57
  GIT_RETRY = -32, /**< Internal only */
58
58
  GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */
59
59
  GIT_EINDEXDIRTY = -34, /**< Unsaved changes in the index would be overwritten */
60
- GIT_EAPPLYFAIL = -35 /**< Patch application failed */
60
+ GIT_EAPPLYFAIL = -35, /**< Patch application failed */
61
+ GIT_EOWNER = -36 /**< The object is not owned by the current user */
61
62
  } git_error_code;
62
63
 
63
64
  /**
@@ -7,10 +7,10 @@
7
7
  #ifndef INCLUDE_git_version_h__
8
8
  #define INCLUDE_git_version_h__
9
9
 
10
- #define LIBGIT2_VERSION "1.4.2"
10
+ #define LIBGIT2_VERSION "1.4.3"
11
11
  #define LIBGIT2_VER_MAJOR 1
12
12
  #define LIBGIT2_VER_MINOR 4
13
- #define LIBGIT2_VER_REVISION 2
13
+ #define LIBGIT2_VER_REVISION 3
14
14
  #define LIBGIT2_VER_PATCH 0
15
15
 
16
16
  #define LIBGIT2_SOVERSION "1.4"
@@ -1170,14 +1170,18 @@ int git_config_find_programdata(git_buf *path)
1170
1170
 
1171
1171
  int git_config__find_programdata(git_str *path)
1172
1172
  {
1173
- int ret;
1173
+ bool is_safe;
1174
1174
 
1175
- ret = git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA);
1175
+ if (git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA) < 0 ||
1176
+ git_fs_path_owner_is_system_or_current_user(&is_safe, path->ptr) < 0)
1177
+ return -1;
1176
1178
 
1177
- if (ret != GIT_OK)
1178
- return ret;
1179
+ if (!is_safe) {
1180
+ git_error_set(GIT_ERROR_CONFIG, "programdata path has invalid ownership");
1181
+ return -1;
1182
+ }
1179
1183
 
1180
- return git_fs_path_validate_system_file_ownership(path->ptr);
1184
+ return 0;
1181
1185
  }
1182
1186
 
1183
1187
  int git_config__global_location(git_str *buf)
@@ -316,6 +316,11 @@ static int diff_print_oid_range(
316
316
  static int diff_delta_format_path(
317
317
  git_str *out, const char *prefix, const char *filename)
318
318
  {
319
+ if (!filename) {
320
+ /* don't prefix "/dev/null" */
321
+ return git_str_puts(out, "/dev/null");
322
+ }
323
+
319
324
  if (git_str_joinpath(out, prefix, filename) < 0)
320
325
  return -1;
321
326
 
@@ -76,8 +76,11 @@ static int maybe_want_oid(git_remote *remote, git_refspec *spec)
76
76
  GIT_ERROR_CHECK_ALLOC(oid_head);
77
77
 
78
78
  git_oid_fromstr(&oid_head->oid, spec->src);
79
- oid_head->name = git__strdup(spec->dst);
80
- GIT_ERROR_CHECK_ALLOC(oid_head->name);
79
+
80
+ if (spec->dst) {
81
+ oid_head->name = git__strdup(spec->dst);
82
+ GIT_ERROR_CHECK_ALLOC(oid_head->name);
83
+ }
81
84
 
82
85
  if (git_vector_insert(&remote->local_heads, oid_head) < 0 ||
83
86
  git_vector_insert(&remote->refs, oid_head) < 0)
@@ -1779,82 +1779,241 @@ done:
1779
1779
  return supported;
1780
1780
  }
1781
1781
 
1782
- int git_fs_path_validate_system_file_ownership(const char *path)
1782
+ static git_fs_path__mock_owner_t mock_owner = GIT_FS_PATH_MOCK_OWNER_NONE;
1783
+
1784
+ void git_fs_path__set_owner(git_fs_path__mock_owner_t owner)
1785
+ {
1786
+ mock_owner = owner;
1787
+ }
1788
+
1789
+ #ifdef GIT_WIN32
1790
+ static PSID *sid_dup(PSID sid)
1791
+ {
1792
+ DWORD len;
1793
+ PSID dup;
1794
+
1795
+ len = GetLengthSid(sid);
1796
+
1797
+ if ((dup = git__malloc(len)) == NULL)
1798
+ return NULL;
1799
+
1800
+ if (!CopySid(len, dup, sid)) {
1801
+ git_error_set(GIT_ERROR_OS, "could not duplicate sid");
1802
+ git__free(dup);
1803
+ return NULL;
1804
+ }
1805
+
1806
+ return dup;
1807
+ }
1808
+
1809
+ static int current_user_sid(PSID *out)
1783
1810
  {
1784
- #ifndef GIT_WIN32
1785
- GIT_UNUSED(path);
1786
- return GIT_OK;
1787
- #else
1788
- git_win32_path buf;
1789
- PSID owner_sid;
1790
- PSECURITY_DESCRIPTOR descriptor = NULL;
1791
- HANDLE token;
1792
1811
  TOKEN_USER *info = NULL;
1793
- DWORD err, len;
1794
- int ret;
1812
+ HANDLE token = NULL;
1813
+ DWORD len = 0;
1814
+ int error = -1;
1795
1815
 
1796
- if (git_win32_path_from_utf8(buf, path) < 0)
1797
- return -1;
1816
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
1817
+ git_error_set(GIT_ERROR_OS, "could not lookup process information");
1818
+ goto done;
1819
+ }
1820
+
1821
+ if (GetTokenInformation(token, TokenUser, NULL, 0, &len) ||
1822
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1823
+ git_error_set(GIT_ERROR_OS, "could not lookup token metadata");
1824
+ goto done;
1825
+ }
1798
1826
 
1799
- err = GetNamedSecurityInfoW(buf, SE_FILE_OBJECT,
1800
- OWNER_SECURITY_INFORMATION |
1801
- DACL_SECURITY_INFORMATION,
1802
- &owner_sid, NULL, NULL, NULL, &descriptor);
1827
+ info = git__malloc(len);
1828
+ GIT_ERROR_CHECK_ALLOC(info);
1803
1829
 
1804
- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
1805
- ret = GIT_ENOTFOUND;
1806
- goto cleanup;
1830
+ if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
1831
+ git_error_set(GIT_ERROR_OS, "could not lookup current user");
1832
+ goto done;
1807
1833
  }
1808
1834
 
1809
- if (err != ERROR_SUCCESS) {
1835
+ if ((*out = sid_dup(info->User.Sid)))
1836
+ error = 0;
1837
+
1838
+ done:
1839
+ if (token)
1840
+ CloseHandle(token);
1841
+
1842
+ git__free(info);
1843
+ return error;
1844
+ }
1845
+
1846
+ static int file_owner_sid(PSID *out, const char *path)
1847
+ {
1848
+ git_win32_path path_w32;
1849
+ PSECURITY_DESCRIPTOR descriptor = NULL;
1850
+ PSID owner_sid;
1851
+ DWORD ret;
1852
+ int error = -1;
1853
+
1854
+ if (git_win32_path_from_utf8(path_w32, path) < 0)
1855
+ return -1;
1856
+
1857
+ ret = GetNamedSecurityInfoW(path_w32, SE_FILE_OBJECT,
1858
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
1859
+ &owner_sid, NULL, NULL, NULL, &descriptor);
1860
+
1861
+ if (ret == ERROR_FILE_NOT_FOUND || ret == ERROR_PATH_NOT_FOUND)
1862
+ error = GIT_ENOTFOUND;
1863
+ else if (ret != ERROR_SUCCESS)
1810
1864
  git_error_set(GIT_ERROR_OS, "failed to get security information");
1811
- ret = GIT_ERROR;
1812
- goto cleanup;
1865
+ else if (!IsValidSid(owner_sid))
1866
+ git_error_set(GIT_ERROR_OS, "file owner is not valid");
1867
+ else if ((*out = sid_dup(owner_sid)))
1868
+ error = 0;
1869
+
1870
+ if (descriptor)
1871
+ LocalFree(descriptor);
1872
+
1873
+ return error;
1874
+ }
1875
+
1876
+ int git_fs_path_owner_is_current_user(bool *out, const char *path)
1877
+ {
1878
+ PSID owner_sid = NULL, user_sid = NULL;
1879
+ int error = -1;
1880
+
1881
+ if (mock_owner) {
1882
+ *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
1883
+ return 0;
1813
1884
  }
1814
1885
 
1815
- if (!IsValidSid(owner_sid)) {
1816
- git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is unknown");
1817
- ret = GIT_ERROR;
1818
- goto cleanup;
1886
+ if ((error = file_owner_sid(&owner_sid, path)) < 0 ||
1887
+ (error = current_user_sid(&user_sid)) < 0)
1888
+ goto done;
1889
+
1890
+ *out = EqualSid(owner_sid, user_sid);
1891
+ error = 0;
1892
+
1893
+ done:
1894
+ git__free(owner_sid);
1895
+ git__free(user_sid);
1896
+ return error;
1897
+ }
1898
+
1899
+ int git_fs_path_owner_is_system(bool *out, const char *path)
1900
+ {
1901
+ PSID owner_sid;
1902
+
1903
+ if (mock_owner) {
1904
+ *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
1905
+ return 0;
1819
1906
  }
1820
1907
 
1908
+ if (file_owner_sid(&owner_sid, path) < 0)
1909
+ return -1;
1910
+
1911
+ *out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
1912
+ IsWellKnownSid(owner_sid, WinLocalSystemSid);
1913
+
1914
+ git__free(owner_sid);
1915
+ return 0;
1916
+ }
1917
+
1918
+ int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
1919
+ {
1920
+ PSID owner_sid = NULL, user_sid = NULL;
1921
+ int error = -1;
1922
+
1923
+ if (mock_owner) {
1924
+ *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
1925
+ mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
1926
+ return 0;
1927
+ }
1928
+
1929
+ if (file_owner_sid(&owner_sid, path) < 0)
1930
+ goto done;
1931
+
1821
1932
  if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
1822
1933
  IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
1823
- ret = GIT_OK;
1824
- goto cleanup;
1825
- }
1826
-
1827
- /* Obtain current user's SID */
1828
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) &&
1829
- !GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
1830
- info = git__malloc(len);
1831
- GIT_ERROR_CHECK_ALLOC(info);
1832
- if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
1833
- git__free(info);
1834
- info = NULL;
1934
+ *out = 1;
1935
+ error = 0;
1936
+ goto done;
1937
+ }
1938
+
1939
+ if (current_user_sid(&user_sid) < 0)
1940
+ goto done;
1941
+
1942
+ *out = EqualSid(owner_sid, user_sid);
1943
+ error = 0;
1944
+
1945
+ done:
1946
+ git__free(owner_sid);
1947
+ git__free(user_sid);
1948
+ return error;
1949
+ }
1950
+
1951
+ #else
1952
+
1953
+ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uids_len)
1954
+ {
1955
+ struct stat st;
1956
+ size_t i;
1957
+
1958
+ *out = false;
1959
+
1960
+ if (p_lstat(path, &st) != 0) {
1961
+ if (errno == ENOENT)
1962
+ return GIT_ENOTFOUND;
1963
+
1964
+ git_error_set(GIT_ERROR_OS, "could not stat '%s'", path);
1965
+ return -1;
1966
+ }
1967
+
1968
+ for (i = 0; i < uids_len; i++) {
1969
+ if (uids[i] == st.st_uid) {
1970
+ *out = true;
1971
+ break;
1835
1972
  }
1836
1973
  }
1837
1974
 
1838
- /*
1839
- * If the file is owned by the same account that is running the current
1840
- * process, it's okay to read from that file.
1841
- */
1842
- if (info && EqualSid(owner_sid, info->User.Sid))
1843
- ret = GIT_OK;
1844
- else {
1845
- git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is not valid");
1846
- ret = GIT_ERROR;
1975
+ return 0;
1976
+ }
1977
+
1978
+ int git_fs_path_owner_is_current_user(bool *out, const char *path)
1979
+ {
1980
+ uid_t userid = geteuid();
1981
+
1982
+ if (mock_owner) {
1983
+ *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
1984
+ return 0;
1847
1985
  }
1848
- git__free(info);
1849
1986
 
1850
- cleanup:
1851
- if (descriptor)
1852
- LocalFree(descriptor);
1987
+ return fs_path_owner_is(out, path, &userid, 1);
1988
+ }
1853
1989
 
1854
- return ret;
1855
- #endif
1990
+ int git_fs_path_owner_is_system(bool *out, const char *path)
1991
+ {
1992
+ uid_t userid = 0;
1993
+
1994
+ if (mock_owner) {
1995
+ *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
1996
+ return 0;
1997
+ }
1998
+
1999
+ return fs_path_owner_is(out, path, &userid, 1);
1856
2000
  }
1857
2001
 
2002
+ int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
2003
+ {
2004
+ uid_t userids[2] = { geteuid(), 0 };
2005
+
2006
+ if (mock_owner) {
2007
+ *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
2008
+ mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
2009
+ return 0;
2010
+ }
2011
+
2012
+ return fs_path_owner_is(out, path, userids, 2);
2013
+ }
2014
+
2015
+ #endif
2016
+
1858
2017
  int git_fs_path_find_executable(git_str *fullpath, const char *executable)
1859
2018
  {
1860
2019
  #ifdef GIT_WIN32
@@ -731,17 +731,37 @@ int git_fs_path_normalize_slashes(git_str *out, const char *path);
731
731
 
732
732
  bool git_fs_path_supports_symlinks(const char *dir);
733
733
 
734
+ typedef enum {
735
+ GIT_FS_PATH_MOCK_OWNER_NONE = 0, /* do filesystem lookups as normal */
736
+ GIT_FS_PATH_MOCK_OWNER_SYSTEM = 1,
737
+ GIT_FS_PATH_MOCK_OWNER_CURRENT_USER = 2,
738
+ GIT_FS_PATH_MOCK_OWNER_OTHER = 3
739
+ } git_fs_path__mock_owner_t;
740
+
741
+ /**
742
+ * Sets the mock ownership for files; subsequent calls to
743
+ * `git_fs_path_owner_is_*` functions will return this data until cleared
744
+ * with `GIT_FS_PATH_MOCK_OWNER_NONE`.
745
+ */
746
+ void git_fs_path__set_owner(git_fs_path__mock_owner_t owner);
747
+
734
748
  /**
735
- * Validate a system file's ownership
736
- *
737
749
  * Verify that the file in question is owned by an administrator or system
738
- * account, or at least by the current user.
739
- *
740
- * This function returns 0 if successful. If the file is not owned by any of
741
- * these, or any other if there have been problems determining the file
742
- * ownership, it returns -1.
750
+ * account.
751
+ */
752
+ int git_fs_path_owner_is_system(bool *out, const char *path);
753
+
754
+ /**
755
+ * Verify that the file in question is owned by the current user;
756
+ */
757
+
758
+ int git_fs_path_owner_is_current_user(bool *out, const char *path);
759
+
760
+ /**
761
+ * Verify that the file in question is owned by an administrator or system
762
+ * account _or_ the current user;
743
763
  */
744
- int git_fs_path_validate_system_file_ownership(const char *path);
764
+ int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path);
745
765
 
746
766
  /**
747
767
  * Search the current PATH for the given executable, returning the full
@@ -401,6 +401,14 @@ int git_libgit2_opts(int key, ...)
401
401
  }
402
402
  break;
403
403
 
404
+ case GIT_OPT_GET_OWNER_VALIDATION:
405
+ *(va_arg(ap, int *)) = git_repository__validate_ownership;
406
+ break;
407
+
408
+ case GIT_OPT_SET_OWNER_VALIDATION:
409
+ git_repository__validate_ownership = (va_arg(ap, int) != 0);
410
+ break;
411
+
404
412
  default:
405
413
  git_error_set(GIT_ERROR_INVALID, "invalid option key");
406
414
  error = -1;
@@ -225,8 +225,13 @@ int git_midx_parse(
225
225
  chunk_hdr = data + sizeof(struct git_midx_header);
226
226
  last_chunk = NULL;
227
227
  for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
228
- chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32 |
229
- ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
228
+ uint32_t chunk_id = ntohl(*((uint32_t *)(chunk_hdr + 0)));
229
+ uint64_t high_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) & 0xffffffffu;
230
+ uint64_t low_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 8)))) & 0xffffffffu;
231
+
232
+ if (high_offset >= INT32_MAX)
233
+ return midx_error("chunk offset out of range");
234
+ chunk_offset = (off64_t)(high_offset << 32 | low_offset);
230
235
  if (chunk_offset < last_chunk_offset)
231
236
  return midx_error("chunks are non-monotonic");
232
237
  if (chunk_offset >= trailer_offset)
@@ -235,7 +240,7 @@ int git_midx_parse(
235
240
  last_chunk->length = (size_t)(chunk_offset - last_chunk_offset);
236
241
  last_chunk_offset = chunk_offset;
237
242
 
238
- switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
243
+ switch (chunk_id) {
239
244
  case MIDX_PACKFILE_NAMES_ID:
240
245
  chunk_packfile_names.offset = last_chunk_offset;
241
246
  last_chunk = &chunk_packfile_names;
@@ -1895,8 +1895,11 @@ static int update_tips_for_spec(
1895
1895
  if (git_oid__is_hexstr(spec->src)) {
1896
1896
  git_oid id;
1897
1897
 
1898
- if ((error = git_oid_fromstr(&id, spec->src)) < 0 ||
1899
- (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
1898
+ if ((error = git_oid_fromstr(&id, spec->src)) < 0)
1899
+ goto on_error;
1900
+
1901
+ if (spec->dst &&
1902
+ (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
1900
1903
  goto on_error;
1901
1904
 
1902
1905
  git_oid_cpy(&oid_head.oid, &id);
@@ -39,6 +39,7 @@
39
39
  # include "win32/w32_util.h"
40
40
  #endif
41
41
 
42
+ bool git_repository__validate_ownership = true;
42
43
  bool git_repository__fsync_gitdir = false;
43
44
 
44
45
  static const struct {
@@ -65,6 +66,7 @@ static const struct {
65
66
 
66
67
  static int check_repositoryformatversion(int *version, git_config *config);
67
68
  static int check_extensions(git_config *config, int version);
69
+ static int load_global_config(git_config **config);
68
70
 
69
71
  #define GIT_COMMONDIR_FILE "commondir"
70
72
  #define GIT_GITDIR_FILE "gitdir"
@@ -483,6 +485,63 @@ static int read_gitfile(git_str *path_out, const char *file_path)
483
485
  return error;
484
486
  }
485
487
 
488
+ typedef struct {
489
+ const char *repo_path;
490
+ git_str tmp;
491
+ bool is_safe;
492
+ } validate_ownership_data;
493
+
494
+ static int validate_ownership_cb(const git_config_entry *entry, void *payload)
495
+ {
496
+ validate_ownership_data *data = payload;
497
+
498
+ if (strcmp(entry->value, "") == 0)
499
+ data->is_safe = false;
500
+
501
+ if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 &&
502
+ strcmp(data->tmp.ptr, data->repo_path) == 0)
503
+ data->is_safe = true;
504
+
505
+ return 0;
506
+ }
507
+
508
+ static int validate_ownership(const char *repo_path)
509
+ {
510
+ git_config *config = NULL;
511
+ validate_ownership_data data = { repo_path, GIT_STR_INIT, false };
512
+ bool is_safe;
513
+ int error;
514
+
515
+ if ((error = git_fs_path_owner_is_current_user(&is_safe, repo_path)) < 0) {
516
+ if (error == GIT_ENOTFOUND)
517
+ error = 0;
518
+
519
+ goto done;
520
+ }
521
+
522
+ if (is_safe) {
523
+ error = 0;
524
+ goto done;
525
+ }
526
+
527
+ if (load_global_config(&config) == 0) {
528
+ error = git_config_get_multivar_foreach(config, "safe.directory", NULL, validate_ownership_cb, &data);
529
+
530
+ if (!error && data.is_safe)
531
+ goto done;
532
+ }
533
+
534
+ git_error_set(GIT_ERROR_CONFIG,
535
+ "repository path '%s' is not owned by current user",
536
+ repo_path);
537
+ error = GIT_EOWNER;
538
+
539
+ done:
540
+ git_config_free(config);
541
+ git_str_dispose(&data.tmp);
542
+ return error;
543
+ }
544
+
486
545
  static int find_repo(
487
546
  git_str *gitdir_path,
488
547
  git_str *workdir_path,
@@ -856,6 +915,7 @@ int git_repository_open_ext(
856
915
  gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
857
916
  git_repository *repo = NULL;
858
917
  git_config *config = NULL;
918
+ const char *validation_path;
859
919
  int version = 0;
860
920
 
861
921
  if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
@@ -904,16 +964,24 @@ int git_repository_open_ext(
904
964
  if ((error = check_extensions(config, version)) < 0)
905
965
  goto cleanup;
906
966
 
907
- if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
967
+ if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
908
968
  repo->is_bare = 1;
909
- else {
910
-
969
+ } else {
911
970
  if (config &&
912
971
  ((error = load_config_data(repo, config)) < 0 ||
913
972
  (error = load_workdir(repo, config, &workdir)) < 0))
914
973
  goto cleanup;
915
974
  }
916
975
 
976
+ /*
977
+ * Ensure that the git directory is owned by the current user.
978
+ */
979
+ validation_path = repo->is_bare ? repo->gitdir : repo->workdir;
980
+
981
+ if (git_repository__validate_ownership &&
982
+ (error = validate_ownership(validation_path)) < 0)
983
+ goto cleanup;
984
+
917
985
  cleanup:
918
986
  git_str_dispose(&gitdir);
919
987
  git_str_dispose(&workdir);
@@ -1606,13 +1674,40 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path)
1606
1674
  return is_insensitive;
1607
1675
  }
1608
1676
 
1609
- static bool are_symlinks_supported(const char *wd_path)
1677
+ /*
1678
+ * Return a configuration object with only the global and system
1679
+ * configurations; no repository-level configuration.
1680
+ */
1681
+ static int load_global_config(git_config **config)
1610
1682
  {
1611
- git_config *config = NULL;
1612
1683
  git_str global_buf = GIT_STR_INIT;
1613
1684
  git_str xdg_buf = GIT_STR_INIT;
1614
1685
  git_str system_buf = GIT_STR_INIT;
1615
1686
  git_str programdata_buf = GIT_STR_INIT;
1687
+ int error;
1688
+
1689
+ git_config__find_global(&global_buf);
1690
+ git_config__find_xdg(&xdg_buf);
1691
+ git_config__find_system(&system_buf);
1692
+ git_config__find_programdata(&programdata_buf);
1693
+
1694
+ error = load_config(config, NULL,
1695
+ path_unless_empty(&global_buf),
1696
+ path_unless_empty(&xdg_buf),
1697
+ path_unless_empty(&system_buf),
1698
+ path_unless_empty(&programdata_buf));
1699
+
1700
+ git_str_dispose(&global_buf);
1701
+ git_str_dispose(&xdg_buf);
1702
+ git_str_dispose(&system_buf);
1703
+ git_str_dispose(&programdata_buf);
1704
+
1705
+ return error;
1706
+ }
1707
+
1708
+ static bool are_symlinks_supported(const char *wd_path)
1709
+ {
1710
+ git_config *config = NULL;
1616
1711
  int symlinks = 0;
1617
1712
 
1618
1713
  /*
@@ -1623,19 +1718,9 @@ static bool are_symlinks_supported(const char *wd_path)
1623
1718
  * _not_ set, then we do not test or enable symlink support.
1624
1719
  */
1625
1720
  #ifdef GIT_WIN32
1626
- git_config__find_global(&global_buf);
1627
- git_config__find_xdg(&xdg_buf);
1628
- git_config__find_system(&system_buf);
1629
- git_config__find_programdata(&programdata_buf);
1630
-
1631
- if (load_config(&config, NULL,
1632
- path_unless_empty(&global_buf),
1633
- path_unless_empty(&xdg_buf),
1634
- path_unless_empty(&system_buf),
1635
- path_unless_empty(&programdata_buf)) < 0)
1636
- goto done;
1637
-
1638
- if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || !symlinks)
1721
+ if (load_global_config(&config) < 0 ||
1722
+ git_config_get_bool(&symlinks, config, "core.symlinks") < 0 ||
1723
+ !symlinks)
1639
1724
  goto done;
1640
1725
  #endif
1641
1726
 
@@ -1643,10 +1728,6 @@ static bool are_symlinks_supported(const char *wd_path)
1643
1728
  goto done;
1644
1729
 
1645
1730
  done:
1646
- git_str_dispose(&global_buf);
1647
- git_str_dispose(&xdg_buf);
1648
- git_str_dispose(&system_buf);
1649
- git_str_dispose(&programdata_buf);
1650
1731
  git_config_free(config);
1651
1732
  return symlinks != 0;
1652
1733
  }
@@ -34,6 +34,7 @@
34
34
  #define GIT_DIR_SHORTNAME "GIT~1"
35
35
 
36
36
  extern bool git_repository__fsync_gitdir;
37
+ extern bool git_repository__validate_ownership;
37
38
 
38
39
  /** Cvar cache identifiers */
39
40
  typedef enum {
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rugged
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon
8
8
  - Vicent Marti
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-02-28 00:00:00.000000000 Z
12
+ date: 2022-04-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
@@ -697,7 +697,7 @@ licenses:
697
697
  - MIT
698
698
  metadata:
699
699
  msys2_mingw_dependencies: libssh2 cmake
700
- post_install_message:
700
+ post_install_message:
701
701
  rdoc_options: []
702
702
  require_paths:
703
703
  - lib
@@ -712,8 +712,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
712
712
  - !ruby/object:Gem::Version
713
713
  version: '0'
714
714
  requirements: []
715
- rubygems_version: 3.1.2
716
- signing_key:
715
+ rubygems_version: 3.2.33
716
+ signing_key:
717
717
  specification_version: 4
718
718
  summary: Rugged is a Ruby binding to the libgit2 linkable library
719
719
  test_files: []