Skip to content

Commit 43b5c51

Browse files
committed
osx: only update keychain entries when needed
Only update keychain entries when the password/secret is different to what is already stored.
1 parent e0218ac commit 43b5c51

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

src/shared/Core/Interop/InteropUtils.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using System.Runtime.InteropServices;
34

45
namespace GitCredentialManager.Interop
@@ -11,5 +12,21 @@ public static byte[] ToByteArray(IntPtr ptr, long count)
1112
Marshal.Copy(ptr, destination, 0, destination.Length);
1213
return destination;
1314
}
15+
16+
public static bool AreEqual(byte[] bytes, IntPtr ptr, uint length)
17+
{
18+
if (bytes.Length == 0 && (ptr == IntPtr.Zero || length == 0))
19+
{
20+
return true;
21+
}
22+
23+
if (bytes.Length != length)
24+
{
25+
return false;
26+
}
27+
28+
byte[] ptrBytes = ToByteArray(ptr, length);
29+
return bytes.SequenceEqual(ptrBytes);
30+
}
1431
}
1532
}

src/shared/Core/Interop/MacOS/MacOSKeychain.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ public void AddOrUpdate(string service, string account, string secret)
103103

104104
string serviceName = CreateServiceName(service);
105105

106-
107106
uint serviceNameLength = (uint) serviceName.Length;
108107
uint accountLength = (uint) (account?.Length ?? 0);
109108

@@ -112,12 +111,12 @@ public void AddOrUpdate(string service, string account, string secret)
112111
// Check if an entry already exists in the keychain
113112
int findResult = SecKeychainFindGenericPassword(
114113
IntPtr.Zero, serviceNameLength, serviceName, accountLength, account,
115-
out uint _, out passwordData, out itemRef);
114+
out uint passwordDataLength, out passwordData, out itemRef);
116115

117116
switch (findResult)
118117
{
119-
// Update existing entry
120-
case OK:
118+
// Update existing entry only if the password/secret is different
119+
case OK when !InteropUtils.AreEqual(secretBytes, passwordData, passwordDataLength):
121120
ThrowIfError(
122121
SecKeychainItemModifyAttributesAndData(itemRef, IntPtr.Zero, (uint) secretBytes.Length, secretBytes),
123122
"Could not update existing item"

0 commit comments

Comments
 (0)