2021-09-13 20:41:05 +00:00
|
|
|
import { Alert, NativeModules, Platform } from 'react-native';
|
2020-11-30 17:00:06 +00:00
|
|
|
import DocumentPicker from 'react-native-document-picker';
|
|
|
|
import * as FileSystem from 'expo-file-system';
|
|
|
|
|
2022-06-06 14:17:51 +00:00
|
|
|
import UserPreferences from '../userPreferences';
|
|
|
|
import I18n from '../../../i18n';
|
2021-09-13 20:41:05 +00:00
|
|
|
import { extractHostname } from './server';
|
2022-06-06 14:17:51 +00:00
|
|
|
import { ICertificate } from '../../../definitions';
|
2020-11-30 17:00:06 +00:00
|
|
|
|
|
|
|
const { SSLPinning } = NativeModules;
|
2021-12-07 13:57:11 +00:00
|
|
|
const { documentDirectory } = FileSystem;
|
|
|
|
|
2022-01-12 12:54:04 +00:00
|
|
|
const extractFileScheme = (path: string) => path.replace('file://', ''); // file:// isn't allowed by obj-C
|
2021-12-07 13:57:11 +00:00
|
|
|
|
2022-01-12 12:54:04 +00:00
|
|
|
const getPath = (name: string) => `${documentDirectory}/${name}`;
|
2021-12-07 13:57:11 +00:00
|
|
|
|
2022-03-09 19:41:26 +00:00
|
|
|
const persistCertificate = (name: string, password: string) => {
|
2021-12-07 13:57:11 +00:00
|
|
|
const certificatePath = getPath(name);
|
2022-01-12 12:54:04 +00:00
|
|
|
const certificate: ICertificate = {
|
2021-12-07 13:57:11 +00:00
|
|
|
path: extractFileScheme(certificatePath),
|
|
|
|
password
|
|
|
|
};
|
2022-03-09 19:41:26 +00:00
|
|
|
UserPreferences.setMap(name, certificate);
|
2021-12-07 13:57:11 +00:00
|
|
|
return certificate;
|
|
|
|
};
|
2020-11-30 17:00:06 +00:00
|
|
|
|
|
|
|
const RCSSLPinning = Platform.select({
|
|
|
|
ios: {
|
2021-09-13 20:41:05 +00:00
|
|
|
pickCertificate: () =>
|
|
|
|
new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
2022-05-20 03:01:34 +00:00
|
|
|
const res = await DocumentPicker.pickSingle({
|
2021-09-13 20:41:05 +00:00
|
|
|
type: ['com.rsa.pkcs-12']
|
|
|
|
});
|
|
|
|
const { uri, name } = res;
|
|
|
|
Alert.prompt(
|
|
|
|
I18n.t('Certificate_password'),
|
|
|
|
I18n.t('Whats_the_password_for_your_certificate'),
|
|
|
|
[
|
|
|
|
{
|
|
|
|
text: 'OK',
|
|
|
|
onPress: async password => {
|
|
|
|
try {
|
2021-12-07 13:57:11 +00:00
|
|
|
const certificatePath = getPath(name);
|
2021-09-13 20:41:05 +00:00
|
|
|
await FileSystem.copyAsync({ from: uri, to: certificatePath });
|
2022-03-09 19:41:26 +00:00
|
|
|
persistCertificate(name, password!);
|
2021-09-13 20:41:05 +00:00
|
|
|
resolve(name);
|
|
|
|
} catch (e) {
|
|
|
|
reject(e);
|
|
|
|
}
|
2020-11-30 17:00:06 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-13 20:41:05 +00:00
|
|
|
],
|
|
|
|
'secure-text'
|
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
reject(e);
|
|
|
|
}
|
|
|
|
}),
|
2022-03-09 19:41:26 +00:00
|
|
|
setCertificate: (name: string, server: string) => {
|
2021-12-07 13:57:11 +00:00
|
|
|
if (name) {
|
2022-03-09 19:41:26 +00:00
|
|
|
let certificate = UserPreferences.getMap(name) as ICertificate;
|
2022-01-12 12:54:04 +00:00
|
|
|
if (!certificate.path.match(extractFileScheme(documentDirectory!))) {
|
2022-03-09 19:41:26 +00:00
|
|
|
certificate = persistCertificate(name, certificate.password);
|
2021-12-07 13:57:11 +00:00
|
|
|
}
|
2022-03-09 19:41:26 +00:00
|
|
|
UserPreferences.setMap(extractHostname(server), certificate);
|
2020-11-30 17:00:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
android: {
|
|
|
|
pickCertificate: () => SSLPinning?.pickCertificate(),
|
2021-12-07 13:57:11 +00:00
|
|
|
setCertificate: name => SSLPinning?.setCertificate(name)
|
2020-11-30 17:00:06 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
export default RCSSLPinning;
|