rugged 1.4.2 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
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: []