Skip to content

Commit a930c10

Browse files
committed
Merge branch 'release/1.3.0'
2 parents 19d9923 + 68ba917 commit a930c10

File tree

56 files changed

+309
-152
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+309
-152
lines changed

pom.xml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>org.cryptomator</groupId>
77
<artifactId>integrations-mac</artifactId>
8-
<version>1.2.4</version>
8+
<version>1.3.0</version>
99

1010
<name>Cryptomator Integrations for macOS</name>
1111
<description>Provides optional macOS services used by Cryptomator</description>
@@ -30,16 +30,16 @@
3030
<project.jdk.version>17</project.jdk.version>
3131

3232
<!-- runtime dependencies -->
33-
<api.version>1.3.1</api.version>
34-
<slf4j.version>2.0.13</slf4j.version>
33+
<api.version>1.5.0</api.version>
34+
<slf4j.version>2.0.16</slf4j.version>
3535

3636
<!-- test dependencies -->
37-
<junit.jupiter.version>5.10.2</junit.jupiter.version>
38-
<mockito.version>5.12.0</mockito.version>
37+
<junit.jupiter.version>5.11.4</junit.jupiter.version>
38+
<mockito.version>5.15.2</mockito.version>
3939

4040
<!-- build plugin dependencies -->
41-
<dependency-check.version>9.2.0</dependency-check.version>
42-
<nexus-staging.version>1.6.14</nexus-staging.version>
41+
<dependency-check.version>11.1.1</dependency-check.version>
42+
<nexus-staging.version>1.7.0</nexus-staging.version>
4343
</properties>
4444

4545
<licenses>
@@ -88,7 +88,7 @@
8888
<plugin>
8989
<groupId>org.apache.maven.plugins</groupId>
9090
<artifactId>maven-clean-plugin</artifactId>
91-
<version>3.3.2</version>
91+
<version>3.4.0</version>
9292
<configuration>
9393
<filesets>
9494
<fileset>
@@ -145,7 +145,7 @@
145145
<plugin>
146146
<groupId>org.codehaus.mojo</groupId>
147147
<artifactId>exec-maven-plugin</artifactId>
148-
<version>3.3.0</version>
148+
<version>3.5.0</version>
149149
<executions>
150150
<execution>
151151
<goals>
@@ -199,7 +199,7 @@
199199
<plugin>
200200
<groupId>org.apache.maven.plugins</groupId>
201201
<artifactId>maven-surefire-plugin</artifactId>
202-
<version>3.2.5</version>
202+
<version>3.5.2</version>
203203
</plugin>
204204
<plugin>
205205
<artifactId>maven-source-plugin</artifactId>
@@ -215,7 +215,7 @@
215215
</plugin>
216216
<plugin>
217217
<artifactId>maven-javadoc-plugin</artifactId>
218-
<version>3.7.0</version>
218+
<version>3.11.2</version>
219219
<executions>
220220
<execution>
221221
<id>attach-javadocs</id>
@@ -307,7 +307,7 @@
307307
<plugins>
308308
<plugin>
309309
<artifactId>maven-gpg-plugin</artifactId>
310-
<version>3.2.4</version>
310+
<version>3.2.7</version>
311311
<executions>
312312
<execution>
313313
<id>sign-artifacts</id>
@@ -368,10 +368,10 @@
368368
<plugin>
369369
<groupId>org.apache.maven.plugins</groupId>
370370
<artifactId>maven-deploy-plugin</artifactId>
371-
<version>3.1.2</version>
371+
<version>3.1.3</version>
372372
</plugin>
373373
</plugins>
374374
</build>
375375
</profile>
376376
</profiles>
377-
</project>
377+
</project>

src/main/headers/org_cryptomator_macos_keychain_MacKeychain_Native.h

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/module-info.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
66
import org.cryptomator.macos.autostart.MacAutoStartProvider;
77
import org.cryptomator.macos.keychain.MacSystemKeychainAccess;
8+
import org.cryptomator.macos.keychain.TouchIdKeychainAccess;
89
import org.cryptomator.macos.revealpath.OpenCmdRevealPathService;
910
import org.cryptomator.macos.tray.MacTrayIntegrationProvider;
1011
import org.cryptomator.macos.uiappearance.MacUiAppearanceProvider;
@@ -14,7 +15,7 @@
1415
requires org.slf4j;
1516

1617
provides AutoStartProvider with MacAutoStartProvider;
17-
provides KeychainAccessProvider with MacSystemKeychainAccess;
18+
provides KeychainAccessProvider with MacSystemKeychainAccess, TouchIdKeychainAccess;
1819
provides RevealPathService with OpenCmdRevealPathService;
1920
provides TrayIntegrationProvider with MacTrayIntegrationProvider;
2021
provides UiAppearanceProvider with MacUiAppearanceProvider;

src/main/java/org/cryptomator/macos/keychain/MacKeychain.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,17 @@ class MacKeychain {
1717
/**
1818
* Associates the specified password with the specified key in the system keychain.
1919
*
20-
* @param serviceName Service name
21-
* @param account Unique account identifier
22-
* @param password Passphrase to store
20+
* @param serviceName Service name
21+
* @param account Unique account identifier
22+
* @param password Passphrase to store
23+
* @param requireOsAuthentication Defines, whether the user needs to authenticate to store a passphrase
2324
* @see <a href="https://developer.apple.com/documentation/security/1398366-seckeychainaddgenericpassword">SecKeychainAddGenericPassword</a>
2425
*/
25-
public void storePassword(String serviceName, String account, CharSequence password) throws KeychainAccessException {
26+
public void storePassword(String serviceName, String account, CharSequence password, boolean requireOsAuthentication) throws KeychainAccessException {
2627
ByteBuffer pwBuf = UTF_8.encode(CharBuffer.wrap(password));
2728
byte[] pwBytes = new byte[pwBuf.remaining()];
2829
pwBuf.get(pwBytes);
29-
int errorCode = Native.INSTANCE.storePassword(serviceName.getBytes(UTF_8), account.getBytes(UTF_8), pwBytes);
30+
int errorCode = Native.INSTANCE.storePassword(serviceName.getBytes(UTF_8), account.getBytes(UTF_8), pwBytes, requireOsAuthentication);
3031
Arrays.fill(pwBytes, (byte) 0x00);
3132
Arrays.fill(pwBuf.array(), (byte) 0x00);
3233
if (errorCode != OSSTATUS_SUCCESS) {
@@ -75,7 +76,7 @@ private boolean tryMigratePassword(String account) {
7576
if (pwBytes == null) {
7677
return false;
7778
}
78-
int errorCode = Native.INSTANCE.storePassword(newServiceName, account.getBytes(UTF_8), pwBytes);
79+
int errorCode = Native.INSTANCE.storePassword(newServiceName, account.getBytes(UTF_8), pwBytes, false);
7980
Arrays.fill(pwBytes, (byte) 0x00);
8081
if (errorCode != OSSTATUS_SUCCESS) {
8182
return false;
@@ -103,6 +104,15 @@ public boolean deletePassword(String serviceName, String account) throws Keychai
103104
}
104105
}
105106

107+
/**
108+
* Tests whether biometric authentication via Touch ID is supported and allowed on the device
109+
*
110+
* @return <code>true</code> if biometric authentication is available, <code>false</code> otherwise
111+
*/
112+
public boolean isTouchIDavailable() {
113+
return Native.INSTANCE.isTouchIDavailable();
114+
}
115+
106116
// initialization-on-demand pattern, as loading the .dylib is an expensive operation
107117
private static class Native {
108118
static final Native INSTANCE = new Native();
@@ -111,11 +121,13 @@ private Native() {
111121
NativeLibLoader.loadLib();
112122
}
113123

114-
public native int storePassword(byte[] service, byte[] account, byte[] value);
124+
public native int storePassword(byte[] service, byte[] account, byte[] value, boolean requireOsAuthentication);
115125

116126
public native byte[] loadPassword(byte[] service, byte[] account);
117127

118128
public native int deletePassword(byte[] service, byte[] account);
129+
130+
public native boolean isTouchIDavailable();
119131
}
120132

121133
}

src/main/java/org/cryptomator/macos/keychain/MacSystemKeychainAccess.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ public String displayName() {
3636

3737
@Override
3838
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
39-
keychain.storePassword(SERVICE_NAME, key, passphrase);
39+
keychain.storePassword(SERVICE_NAME, key, passphrase, false);
40+
}
41+
42+
@Override
43+
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean requireOsAuthentication) throws KeychainAccessException {
44+
keychain.storePassword(SERVICE_NAME, key, passphrase, requireOsAuthentication);
4045
}
4146

4247
@Override
@@ -62,7 +67,7 @@ public void deletePassphrase(String key) throws KeychainAccessException {
6267
@Override
6368
public void changePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
6469
if (keychain.deletePassword(SERVICE_NAME, key)) {
65-
keychain.storePassword(SERVICE_NAME, key, passphrase);
70+
keychain.storePassword(SERVICE_NAME, key, passphrase, false);
6671
}
6772
}
6873

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.cryptomator.macos.keychain;
2+
3+
import org.cryptomator.integrations.common.OperatingSystem;
4+
import org.cryptomator.integrations.common.Priority;
5+
import org.cryptomator.integrations.keychain.KeychainAccessException;
6+
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
7+
import org.cryptomator.macos.common.Localization;
8+
9+
/**
10+
* Stores passwords in the macOS system keychain. Requires an authenticated user to do so.
11+
* Authentication is done via TouchID or password as a fallback, when TouchID is not available.
12+
* <p>
13+
* Items are stored in the default keychain with the service name <code>Cryptomator</code>, unless configured otherwise
14+
* using the system property <code>cryptomator.integrationsMac.keychainServiceName</code>.
15+
*/
16+
@Priority(1010)
17+
@OperatingSystem(OperatingSystem.Value.MAC)
18+
public class TouchIdKeychainAccess implements KeychainAccessProvider {
19+
20+
private static final String SERVICE_NAME = System.getProperty("cryptomator.integrationsMac.keychainServiceName", "Cryptomator");
21+
22+
private final MacKeychain keychain;
23+
24+
public TouchIdKeychainAccess() {
25+
this(new MacKeychain());
26+
}
27+
28+
// visible for testing
29+
TouchIdKeychainAccess(MacKeychain keychain) {
30+
this.keychain = keychain;
31+
}
32+
33+
@Override
34+
public String displayName() {
35+
return Localization.get().getString("org.cryptomator.macos.keychain.touchIdDisplayName");
36+
}
37+
38+
@Override
39+
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
40+
keychain.storePassword(SERVICE_NAME, key, passphrase, true);
41+
}
42+
43+
@Override
44+
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean requireOsAuthentication) throws KeychainAccessException {
45+
keychain.storePassword(SERVICE_NAME, key, passphrase, requireOsAuthentication);
46+
}
47+
48+
@Override
49+
public char[] loadPassphrase(String key) {
50+
return keychain.loadPassword(SERVICE_NAME, key);
51+
}
52+
53+
@Override
54+
public boolean isSupported() {
55+
return keychain.isTouchIDavailable();
56+
}
57+
58+
@Override
59+
public boolean isLocked() {
60+
return false;
61+
}
62+
63+
@Override
64+
public void deletePassphrase(String key) throws KeychainAccessException {
65+
keychain.deletePassword(SERVICE_NAME, key);
66+
}
67+
68+
@Override
69+
public void changePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
70+
if (keychain.deletePassword(SERVICE_NAME, key)) {
71+
keychain.storePassword(SERVICE_NAME, key, passphrase, true);
72+
}
73+
}
74+
75+
}

0 commit comments

Comments
 (0)