diff --git a/.github/workflows/publish.servicenow.plugin.yml b/.github/workflows/publish.servicenow.plugin.yml index 1ebff720..41197239 100644 --- a/.github/workflows/publish.servicenow.plugin.yml +++ b/.github/workflows/publish.servicenow.plugin.yml @@ -42,8 +42,8 @@ jobs: if: ${{ false }} # disable for now run: | TAG="${{ github.event.inputs.tagname }}" - GRADLE_CFG=./build.gradle - BUILD_VERSION=`fgrep version $GRADLE_CFG | sed -r 's/^version\s+//g' | sed "s/'//g"` + GRADLE_CFG=./build.gradle.kts + BUILD_VERSION=`fgrep version $GRADLE_CFG | sed -r 's/^version\s+//g' | sed 's/"//g'` if [[ "$TAG" == *"-$BUILD_VERSION"* ]]; then echo "Build version $BUILD_VERSION is included in the tag $TAG" else @@ -56,6 +56,8 @@ jobs: cat <<'EOF' > build.sh #!/usr/bin/env bash MID_SERVER_URLS='' + MID_SERVER_URLS=${MID_SERVER_URLS},https://install.service-now.com/glide/distribution/builds/package/mid/2024/09/01/mid.xanadu-07-02-2024__patch1-08-24-2024_09-01-2024_1853.linux.x86-64.zip + MID_SERVER_URLS=${MID_SERVER_URLS},https://install.service-now.com/glide/distribution/builds/package/mid/2024/08/31/mid.washingtondc-12-20-2023__patch7-08-21-2024_08-31-2024_1809.linux.x86-64.zip MID_SERVER_URLS=${MID_SERVER_URLS},https://install.service-now.com/glide/distribution/builds/package/mid/2023/07/26/mid.vancouver-07-06-2023__patch0-07-18-2023_07-26-2023_1029.linux.x86-64.zip MID_SERVER_URLS=${MID_SERVER_URLS},https://install.service-now.com/glide/distribution/builds/package/mid/2023/08/20/mid.utah-12-21-2022__patch6-08-09-2023_08-20-2023_0545.linux.x86-64.zip MID_SERVER_URLS=${MID_SERVER_URLS},https://install.service-now.com/glide/distribution/builds/package/mid/2023/06/23/mid.tokyo-07-08-2022__patch9-hotfix2-06-07-2023_06-23-2023_1740.linux.x86-64.zip @@ -69,11 +71,11 @@ jobs: buildroot=`pwd` chmod u+x ${buildroot}/gradlew - gradlecfg=${buildroot}/build.gradle + gradlecfg=${buildroot}/build.gradle.kts - buildname=`fgrep archivesName ${gradlecfg} | sed -r 's/^\s*archivesName\s*=\s*//g' | sed "s/'//g"` - buildversion=`fgrep version ${gradlecfg} | sed -r 's/^version\s+//g' | sed "s/'//g"` - srcjarpath=${buildroot}/build/libs/${buildname}-${buildversion}.jar + buildname=`fgrep archivesName ${gradlecfg} | sed -r 's/^\s*archivesName\s*=\s*//g' | sed 's/"//g'` + buildversion=`fgrep version ${gradlecfg} | sed -r 's/^version\s+//g' | sed 's/"//g'` + srcjarpath=${buildroot}/build/libs/${buildname}.jar IFS="," read -a urls <<< ${MID_SERVER_URLS} for url in "${urls[@]}"; do @@ -88,7 +90,7 @@ jobs: libpath=${midsdir}/${version}/agent/lib elibpath=${libpath//\//\\/} - sed -i "s/def midserver_agent_dir =.*/def midserver_agent_dir = \'${elibpath}\'/" ${gradlecfg} + sed -i "s/val midServerAgentDir =.*/val midServerAgentDir = \"${elibpath}\"/" ${gradlecfg} cd ${buildroot} gradlew_return_code=0 @@ -117,8 +119,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | TAG="${{ github.event.inputs.tagname }}" - GRADLE_CFG=./build.gradle - BUILD_NAME=`fgrep archivesName $GRADLE_CFG | sed -r 's/^\s*archivesName\s*=\s*//g' | sed "s/'//g"` - BUILD_VERSION=`fgrep version $GRADLE_CFG | sed -r 's/^version\s+//g' | sed "s/'//g"` + GRADLE_CFG=./build.gradle.kts + BUILD_NAME=`fgrep archivesName $GRADLE_CFG | sed -r 's/^\s*archivesName\s*=\s*//g' | sed 's/"//g'` + BUILD_VERSION=`fgrep version $GRADLE_CFG | sed -r 's/^version\s+//g' | sed 's/"//g'` RELEASE_NAME=${BUILD_NAME}-${BUILD_VERSION}.jar gh release create ${TAG} `pwd`/releases/*.jar --repo="$GITHUB_REPOSITORY" --title="$RELEASE_NAME" --generate-notes diff --git a/integration/servicenow-external-credential-resolver/build.gradle b/integration/servicenow-external-credential-resolver/build.gradle deleted file mode 100644 index 28dbcd15..00000000 --- a/integration/servicenow-external-credential-resolver/build.gradle +++ /dev/null @@ -1,57 +0,0 @@ -plugins { - id 'base' - id 'java' -} - -group 'com.keepersecurity' -version '0.1.0' - -base { - archivesName = 'keeper-external-credentials' -} -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -// TODO: replace with mid server path -// This must point to the MID Server installation location (agent directory path). -def midserver_agent_dir = '/opt/servicenow/mid/agent/lib' - -repositories { - mavenCentral() - flatDir { - dirs("$midserver_agent_dir") - } -} - -dependencies { - implementation 'com.keepersecurity.secrets-manager:core:16.6.2+' - - // MID server dependencies, not required to be uploaded - // MID jar dependency for config APIs - compileOnly 'com.snc:mid' - compileOnly 'com.snc:commons-glide' - compileOnly 'com.snc:commons-core-automation' - compileOnly 'com.snc:snc-automation-api' - - // NB! JDK16+/Vancouver+ may require: export _JAVA_OPTIONS="--add-opens=java.base/sun.security.util=ALL-UNNAMED" - // Vancouver and newer: IFileSystem is in the new mid-api.jar - if( !fileTree("$midserver_agent_dir").filter{File f -> (f.name == "mid-api.jar")}.isEmpty() ) { - compileOnly 'com.snc:mid-api' - } -} - -jar { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - manifest { - attributes('Main-Class': 'com.snc.discovery.CredentialResolver') - } - from { - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } { - exclude "META-INF/*.SF" - exclude "META-INF/*.DSA" - exclude "META-INF/*.RSA" - } -} diff --git a/integration/servicenow-external-credential-resolver/build.gradle.kts b/integration/servicenow-external-credential-resolver/build.gradle.kts new file mode 100644 index 00000000..e77de111 --- /dev/null +++ b/integration/servicenow-external-credential-resolver/build.gradle.kts @@ -0,0 +1,69 @@ +group "com.keepersecurity" +version "0.1.0" + +plugins { + base + java +} + +base { + archivesName = "keeper-external-credentials" +} + +java { + toolchain { + // Vancouver-- built with OpenJDK 11.x + languageVersion = JavaLanguageVersion.of(11) + + // Washington DC: A ServiceNow build of OpenJDK 17.0.8.1 is Supported and Included (17.0.8.1-sncmid1) + // Administrators will need to make sure any 3rd party JAR files for Credential resolvers, JDBC drivers, etc. + // are compatible with Java 17 and 'strong encapsulation', before upgrading. + // More information: KB1273036 MID Server - JRE 17 Upgrade + + // Washington DC, Xanadu++ built with OpenJDK 17.x + //languageVersion = JavaLanguageVersion.of(17) + } +} + +// This must point to the MID Server installation location (agent directory path). +val midServerAgentDir = "/opt/servicenow/mid/agent/lib" + +repositories { + mavenCentral() + flatDir { + dirs(midServerAgentDir) + } +} + +dependencies { + implementation ("com.keepersecurity.secrets-manager:core:16.6.4+") + + // MID server dependencies, not required to be uploaded + // MID jar dependency for config APIs + compileOnly("com.snc:mid") + compileOnly("com.snc:commons-glide") + compileOnly("com.snc:commons-core-automation") + compileOnly("com.snc:snc-automation-api") + + // NB! JDK16+/Vancouver+ may require: export _JAVA_OPTIONS="--add-opens=java.base/sun.security.util=ALL-UNNAMED" + // Vancouver and newer: IFileSystem is in the new mid-api.jar + if (file("${midServerAgentDir}/mid-api.jar").exists()) { + compileOnly("com.snc:mid-api") + } +} + +tasks.jar { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + manifest { + attributes("Main-Class" to "com.snc.discovery.CredentialResolver") + } + from(configurations + .runtimeClasspath + .get() // Gradle 6+ + .files // Gradle 6+ + .map { if (it.isDirectory) it else zipTree(it) } + ) + exclude("META-INF/*.SF") + exclude("META-INF/*.DSA") + exclude("META-INF/*.RSA") +} diff --git a/integration/servicenow-external-credential-resolver/gradle/wrapper/gradle-wrapper.properties b/integration/servicenow-external-credential-resolver/gradle/wrapper/gradle-wrapper.properties index c30b486a..d642e7f8 100644 --- a/integration/servicenow-external-credential-resolver/gradle/wrapper/gradle-wrapper.properties +++ b/integration/servicenow-external-credential-resolver/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip -networkTimeout=10000 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/integration/servicenow-external-credential-resolver/settings.gradle.kts b/integration/servicenow-external-credential-resolver/settings.gradle.kts new file mode 100644 index 00000000..c75f1d39 --- /dev/null +++ b/integration/servicenow-external-credential-resolver/settings.gradle.kts @@ -0,0 +1,16 @@ +rootProject.name = "keeper-external-credentials" + +plugins { + id("org.gradle.toolchains.foojay-resolver") version "0.8.0" +} + +@Suppress("UnstableApiUsage") +toolchainManagement { + jvm { + javaRepositories { + repository("foojay") { + resolverClass.set(org.gradle.toolchains.foojay.FoojayToolchainResolver::class.java) + } + } + } +} diff --git a/sdk/java/core/README.md b/sdk/java/core/README.md index af3359fc..058bd672 100644 --- a/sdk/java/core/README.md +++ b/sdk/java/core/README.md @@ -4,6 +4,11 @@ For more information see our official documentation page https://docs.keeper.io/ # Change Log +## 16.6.5 +- KSM-548 - Make sure autogenerated UIDs don't start with '-' +- KSM-553 - Added new field types and updated PAM field types +- Upgraded package dependencies to latest versions and switched to gradle-8.10.1 + ## 16.6.4 - KSM-501 - Switched to non-strict JSON parser - KSM-506 - Adding support for Privacy screen in the passkey field type @@ -28,7 +33,7 @@ For more information see our official documentation page https://docs.keeper.io/ - KSM-421 - Improved Logging ## 16.5.3 -- KSM-401 - Update PAM Record types and Field types to have latest updates +- KSM-401 - Update PAM Record types and Field types to have the latest updates - KSM-406 - New field type: Passkey - KSM-382 - Support for record Transactions diff --git a/sdk/java/core/build.gradle.kts b/sdk/java/core/build.gradle.kts index 0c02def1..eff0e7c7 100644 --- a/sdk/java/core/build.gradle.kts +++ b/sdk/java/core/build.gradle.kts @@ -1,20 +1,21 @@ import org.gradle.api.publish.maven.MavenPublication import org.gradle.kotlin.dsl.`maven-publish` import org.gradle.kotlin.dsl.signing +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import java.util.* group = "com.keepersecurity.secrets-manager" // During publishing, If version ends with '-SNAPSHOT' then it will be published to Maven snapshot repository -version = "16.6.4" +version = "16.6.5" plugins { `java-library` - kotlin("jvm") version "1.9.23" - kotlin("plugin.serialization") version "1.9.23" + kotlin("jvm") version "2.0.20" + kotlin("plugin.serialization") version "2.0.20" `maven-publish` signing - id("io.github.gradle-nexus.publish-plugin") version "1.3.0" + id("io.github.gradle-nexus.publish-plugin") version "2.0.0" } java { @@ -29,8 +30,8 @@ tasks.withType().configureEach { } tasks.withType().configureEach { - kotlinOptions { - jvmTarget = "1.8" + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) } } @@ -42,20 +43,20 @@ repositories { dependencies { // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.9.23")) + implementation(platform("org.jetbrains.kotlin:kotlin-bom:2.0.20")) // Use the Kotlin JDK 8 standard library. - api("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.23") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") - implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.23") + api("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.20") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2") + implementation("org.jetbrains.kotlin:kotlin-reflect:2.0.20") // Use the Kotlin test library. - testImplementation("org.jetbrains.kotlin:kotlin-test:1.9.23") + testImplementation("org.jetbrains.kotlin:kotlin-test:2.0.20") // Use the Kotlin JUnit integration. - testImplementation("org.jetbrains.kotlin:kotlin-test-junit:1.9.23") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit:2.0.20") - testImplementation("org.bouncycastle:bc-fips:1.0.2.4") + testImplementation("org.bouncycastle:bc-fips:2.0.0") // testImplementation("org.bouncycastle:bcprov-jdk15on:1.70") } diff --git a/sdk/java/core/gradle/wrapper/gradle-wrapper.properties b/sdk/java/core/gradle/wrapper/gradle-wrapper.properties index b719751c..793ed65e 100644 --- a/sdk/java/core/gradle/wrapper/gradle-wrapper.properties +++ b/sdk/java/core/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/sdk/java/core/settings.gradle.kts b/sdk/java/core/settings.gradle.kts index cccc8600..7c2709aa 100644 --- a/sdk/java/core/settings.gradle.kts +++ b/sdk/java/core/settings.gradle.kts @@ -1,7 +1,7 @@ rootProject.name = "core" plugins { - id("org.gradle.toolchains.foojay-resolver") version "0.7.0" + id("org.gradle.toolchains.foojay-resolver") version "0.8.0" } @Suppress("UnstableApiUsage") diff --git a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/CryptoUtils.kt b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/CryptoUtils.kt index b7cdbf2d..3b4da08e 100644 --- a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/CryptoUtils.kt +++ b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/CryptoUtils.kt @@ -3,7 +3,7 @@ package com.keepersecurity.secretsManager.core import java.math.BigInteger -import java.net.URL +import java.net.URI import java.net.URLDecoder import java.nio.ByteBuffer import java.security.* @@ -16,6 +16,7 @@ import javax.crypto.Mac import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec +import kotlin.experimental.and import kotlin.math.pow import kotlin.math.abs @@ -81,6 +82,20 @@ internal fun getRandomBytes(length: Int): ByteArray { return bytes } +internal fun generateUid(): ByteArray { + val dash = 0b11111000.toByte() + var bytes = ByteArray(16) + + for (i in 1..8) { + bytes = getRandomBytes(16) + if (dash.and(bytes[0]) != dash) break + } + if (dash.and(bytes[0]) == dash) + bytes[0] = bytes[0].and(0b01111111.toByte()) + + return bytes +} + internal fun generateKeyPair(): java.security.KeyPair { return KeeperCryptoParameters.keyGen.genKeyPair() } @@ -235,7 +250,7 @@ data class TotpCode(val code: String, val timeLeft: Int, val period: Int) { if (protocol != "otpauth") return null - val totpUrl = URL("http://" + url.substring(10)) + val totpUrl = URI.create("http://" + url.substring(10)).toURL() val queryPairs = mutableMapOf() val pairs: List = totpUrl.query.split("&") for (pair in pairs) { diff --git a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/Notation.kt b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/Notation.kt index 0bb9af98..90f8139e 100644 --- a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/Notation.kt +++ b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/Notation.kt @@ -135,6 +135,7 @@ internal fun fieldType(field: KeeperRecordField): String { @ExperimentalSerializationApi internal fun getFieldValuesCount(field: KeeperRecordField): Int { return when (field) { + is AppFillers -> field.value.size is AccountNumber -> field.value.size is AddressRef -> field.value.size is Addresses -> field.value.size @@ -142,14 +143,17 @@ internal fun getFieldValuesCount(field: KeeperRecordField): Int { is BirthDate -> field.value.size is CardRef -> field.value.size is Checkbox -> field.value.size + is Controller -> field.value.size is DatabaseType -> field.value.size is Date -> field.value.size is DirectoryType -> field.value.size + is Dropdown -> field.value.size is Email -> field.value.size is ExpirationDate -> field.value.size is FileRef -> field.value.size is HiddenField -> field.value.size is Hosts -> field.value.size + is IsSsidHidden -> field.value.size is KeyPairs -> field.value.size is LicenseNumber -> field.value.size is Login -> field.value.size @@ -158,19 +162,26 @@ internal fun getFieldValuesCount(field: KeeperRecordField): Int { is OneTimeCode -> field.value.size is OneTimePassword -> field.value.size is PamHostnames -> field.value.size + is PamProvider -> field.value.size + is PamRemoteBrowserSettings -> field.value.size is PamResources -> field.value.size + is PamSettings -> field.value.size is Passkeys -> field.value.size is Password -> field.value.size is PaymentCards -> field.value.size is Phones -> field.value.size is PinCode -> field.value.size + is RbiUrl -> field.value.size is RecordRef -> field.value.size is Schedules -> field.value.size is Scripts -> field.value.size is SecureNote -> field.value.size is SecurityQuestions -> field.value.size is Text -> field.value.size + is TrafficEncryptionKey -> field.value.size + is TrafficEncryptionSeed -> field.value.size is Url -> field.value.size + is WifiEncryption -> field.value.size } } @@ -181,6 +192,14 @@ internal fun getFieldValuesCount(field: KeeperRecordField): Int { internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, property: String? = null): List { val emptyRes = listOf() return when (field) { + is AppFillers -> if (index >= field.value.size) emptyRes + else if (index < 0) { + if (property == null) field.value.map { Json.encodeToString(it) }.toList() + else field.value.map { getObjectProperty(it, property) }.toList() + } else { + if (property == null) listOf(Json.encodeToString(field.value[index])) + else listOf(getObjectProperty(field.value[index], property)) + } is AccountNumber -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) is AddressRef -> if (index >= field.value.size || property != null) emptyRes @@ -207,12 +226,16 @@ internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, pro else if (index < 0) field.value else listOf(field.value[index]) is Checkbox -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value.map { it.toString() }.toList() else listOf(field.value[index].toString()) + is Controller -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) is DatabaseType -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) is Date -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value.map { it.toString() }.toList() else listOf(field.value[index].toString()) is DirectoryType -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) + is Dropdown -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) is Email -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) is ExpirationDate -> if (index >= field.value.size || property != null) emptyRes @@ -229,6 +252,8 @@ internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, pro if (property == null) listOf(Json.encodeToString(field.value[index])) else listOf(getObjectProperty(field.value[index], property)) } + is IsSsidHidden -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value.map { it.toString() }.toList() else listOf(field.value[index].toString()) is KeyPairs -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value.map { it.toString() }.toList() else listOf(field.value[index].toString()) is LicenseNumber -> if (index >= field.value.size || property != null) emptyRes @@ -257,6 +282,16 @@ internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, pro if (property == null) listOf(Json.encodeToString(field.value[index])) else listOf(getObjectProperty(field.value[index], property)) } + is PamProvider -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) + is PamRemoteBrowserSettings -> if (index >= field.value.size) emptyRes + else if (index < 0) { + if (property == null) field.value.map { Json.encodeToString(it) }.toList() + else field.value.map { getObjectProperty(it, property) }.toList() + } else { + if (property == null) listOf(Json.encodeToString(field.value[index])) + else listOf(getObjectProperty(field.value[index], property)) + } is PamResources -> if (index >= field.value.size) emptyRes else if (index < 0) { if (property == null) field.value.map { Json.encodeToString(it) }.toList() @@ -265,6 +300,14 @@ internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, pro if (property == null) listOf(Json.encodeToString(field.value[index])) else listOf(getObjectProperty(field.value[index], property)) } + is PamSettings -> if (index >= field.value.size) emptyRes + else if (index < 0) { + if (property == null) field.value.map { Json.encodeToString(it) }.toList() + else field.value.map { getObjectProperty(it, property) }.toList() + } else { + if (property == null) listOf(Json.encodeToString(field.value[index])) + else listOf(getObjectProperty(field.value[index], property)) + } is Passkeys -> if (index >= field.value.size) emptyRes else if (index < 0) { if (property == null) field.value.map { Json.encodeToString(it) }.toList() @@ -293,6 +336,8 @@ internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, pro } is PinCode -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) + is RbiUrl -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) is RecordRef -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) is Schedules -> if (index >= field.value.size) emptyRes @@ -323,14 +368,21 @@ internal fun getFieldStringValues(field: KeeperRecordField, index: Int = -1, pro } is Text -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) + is TrafficEncryptionKey -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) + is TrafficEncryptionSeed -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) is Url -> if (index >= field.value.size || property != null) emptyRes else if (index < 0) field.value else listOf(field.value[index]) + is WifiEncryption -> if (index >= field.value.size || property != null) emptyRes + else if (index < 0) field.value else listOf(field.value[index]) } } @ExperimentalSerializationApi private fun getFieldStringValue(field: KeeperRecordField, valueIdx: Int): String { return when (field) { + is AppFillers -> Json.encodeToString(field.value[valueIdx]) is AccountNumber -> field.value[valueIdx] is AddressRef -> field.value[valueIdx] is Addresses -> Json.encodeToString(field.value[valueIdx]) @@ -338,14 +390,17 @@ private fun getFieldStringValue(field: KeeperRecordField, valueIdx: Int): String is BirthDate -> field.value[valueIdx].toString() is CardRef -> field.value[valueIdx] is Checkbox -> field.value[valueIdx].toString() + is Controller -> field.value[valueIdx] is DatabaseType -> field.value[valueIdx] is Date -> field.value[valueIdx].toString() is DirectoryType -> field.value[valueIdx] + is Dropdown -> field.value[valueIdx] is Email -> field.value[valueIdx] is ExpirationDate -> field.value[valueIdx].toString() is FileRef -> field.value[valueIdx] is HiddenField -> field.value[valueIdx] is Hosts -> Json.encodeToString(field.value[valueIdx]) + is IsSsidHidden -> field.value[valueIdx].toString() is KeyPairs -> field.value[valueIdx].toString() is LicenseNumber -> field.value[valueIdx] is Login -> field.value[valueIdx] @@ -354,30 +409,40 @@ private fun getFieldStringValue(field: KeeperRecordField, valueIdx: Int): String is OneTimeCode -> field.value[valueIdx] is OneTimePassword -> field.value[valueIdx] is PamHostnames -> Json.encodeToString(field.value[valueIdx]) + is PamProvider -> field.value[valueIdx] + is PamRemoteBrowserSettings -> Json.encodeToString(field.value[valueIdx]) is PamResources -> Json.encodeToString(field.value[valueIdx]) + is PamSettings -> Json.encodeToString(field.value[valueIdx]) is Passkeys -> Json.encodeToString(field.value[valueIdx]) is Password -> field.value[valueIdx] is PaymentCards -> Json.encodeToString(field.value[valueIdx]) is Phones -> Json.encodeToString(field.value[valueIdx]) is PinCode -> field.value[valueIdx] + is RbiUrl -> field.value[valueIdx] is RecordRef -> field.value[valueIdx] is Schedules -> Json.encodeToString(field.value[valueIdx]) is Scripts -> Json.encodeToString(field.value[valueIdx]) is SecureNote -> field.value[valueIdx] is SecurityQuestions -> Json.encodeToString(field.value[valueIdx]) is Text -> field.value[valueIdx] + is TrafficEncryptionKey -> field.value[valueIdx] + is TrafficEncryptionSeed -> field.value[valueIdx] is Url -> field.value[valueIdx] + is WifiEncryption -> field.value[valueIdx] } } private fun getFieldValueProperty(field: KeeperRecordField, valueIdx: Int, propertyName: String): String { return when (field) { + is AppFillers -> getObjectProperty(field.value[valueIdx], propertyName) is Addresses -> getObjectProperty(field.value[valueIdx], propertyName) is BankAccounts -> getObjectProperty(field.value[valueIdx], propertyName) is Hosts -> getObjectProperty(field.value[valueIdx], propertyName) is Names -> getObjectProperty(field.value[valueIdx], propertyName) is PamHostnames -> getObjectProperty(field.value[valueIdx], propertyName) + is PamRemoteBrowserSettings -> getObjectProperty(field.value[valueIdx], propertyName) is PamResources -> getObjectProperty(field.value[valueIdx], propertyName) + is PamSettings -> getObjectProperty(field.value[valueIdx], propertyName) is Passkeys -> getObjectProperty(field.value[valueIdx], propertyName) is PaymentCards -> getObjectProperty(field.value[valueIdx], propertyName) is Phones -> getObjectProperty(field.value[valueIdx], propertyName) @@ -395,6 +460,7 @@ private fun getObjectProperty(obj: Any, propertyName: String): String { @ExperimentalSerializationApi private fun getFieldJsonValue(field: KeeperRecordField): String { return when (field) { + is AppFillers -> Json.encodeToString(field.value) is AccountNumber -> Json.encodeToString(field.value) is AddressRef -> Json.encodeToString(field.value) is Addresses -> Json.encodeToString(field.value) @@ -402,14 +468,17 @@ private fun getFieldJsonValue(field: KeeperRecordField): String { is BirthDate -> Json.encodeToString(field.value) is CardRef -> Json.encodeToString(field.value) is Checkbox -> Json.encodeToString(field.value) + is Controller -> Json.encodeToString(field.value) is DatabaseType -> Json.encodeToString(field.value) is Date -> Json.encodeToString(field.value) is DirectoryType -> Json.encodeToString(field.value) + is Dropdown -> Json.encodeToString(field.value) is Email -> Json.encodeToString(field.value) is ExpirationDate -> Json.encodeToString(field.value) is FileRef -> Json.encodeToString(field.value) is HiddenField -> Json.encodeToString(field.value) is Hosts -> Json.encodeToString(field.value) + is IsSsidHidden -> Json.encodeToString(field.value) is KeyPairs -> Json.encodeToString(field.value) is LicenseNumber -> Json.encodeToString(field.value) is Login -> Json.encodeToString(field.value) @@ -418,19 +487,26 @@ private fun getFieldJsonValue(field: KeeperRecordField): String { is OneTimeCode -> Json.encodeToString(field.value) is OneTimePassword -> Json.encodeToString(field.value) is PamHostnames -> Json.encodeToString(field.value) + is PamProvider -> Json.encodeToString(field.value) + is PamRemoteBrowserSettings -> Json.encodeToString(field.value) is PamResources -> Json.encodeToString(field.value) + is PamSettings -> Json.encodeToString(field.value) is Passkeys -> Json.encodeToString(field.value) is Password -> Json.encodeToString(field.value) is PaymentCards -> Json.encodeToString(field.value) is Phones -> Json.encodeToString(field.value) is PinCode -> Json.encodeToString(field.value) + is RbiUrl -> Json.encodeToString(field.value) is RecordRef -> Json.encodeToString(field.value) is Schedules -> Json.encodeToString(field.value) is Scripts -> Json.encodeToString(field.value) is SecureNote -> Json.encodeToString(field.value) is SecurityQuestions -> Json.encodeToString(field.value) is Text -> Json.encodeToString(field.value) + is TrafficEncryptionKey -> Json.encodeToString(field.value) + is TrafficEncryptionSeed -> Json.encodeToString(field.value) is Url -> Json.encodeToString(field.value) + is WifiEncryption -> Json.encodeToString(field.value) } } diff --git a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/RecordData.kt b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/RecordData.kt index beaa0444..17e22b83 100644 --- a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/RecordData.kt +++ b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/RecordData.kt @@ -28,6 +28,15 @@ sealed class KeeperRecordField { abstract val label: String? } +@Serializable +data class KeeperFileData( + val title: String, + val name: String, + val type: String? = null, + val size: Long, + val lastModified: Long +) + @Serializable @SerialName("login") data class Login @JvmOverloads constructor( @@ -36,10 +45,6 @@ data class Login @JvmOverloads constructor( var privacyScreen: Boolean? = null, val value: MutableList ) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -62,10 +67,6 @@ data class Password @JvmOverloads constructor( var complexity: PasswordComplexity? = null, val value: MutableList ) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, null, null, mutableListOf(value)) } @@ -76,22 +77,16 @@ data class Url @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } +// "file" - obsolete and removed legacy field - "fldt_file": { key: 'file_or_photo', default: "File or Photo" }, @Serializable @SerialName("fileRef") data class FileRef @JvmOverloads constructor( override var label: String? = null, var required: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, mutableListOf(value)) } @@ -102,11 +97,6 @@ data class OneTimeCode @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - * @param value TOTP URL. Ex. otpauth://totp/asdfsadf:asdf@asdf.com?secret=2355666655444334&issuer=asdfsadf&algorithm=SHA256&digits=6&period=30 - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -117,10 +107,6 @@ data class OneTimePassword @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -134,10 +120,6 @@ data class Names @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Name): this(null, null, null, mutableListOf(value)) } @@ -148,10 +130,6 @@ data class BirthDate @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Long): this(null, null, null, mutableListOf(value)) } @@ -162,10 +140,6 @@ data class Date @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Long): this(null, null, null, mutableListOf(value)) } @@ -176,10 +150,6 @@ data class ExpirationDate @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Long): this(null, null, null, mutableListOf(value)) } @@ -190,10 +160,6 @@ data class Text @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, var value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -208,10 +174,6 @@ data class SecurityQuestions @JvmOverloads constructor( var privacyScreen: Boolean? = null, val value: MutableList ) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: SecurityQuestion): this(null, null, null, mutableListOf(value)) } @@ -222,10 +184,6 @@ data class Multiline @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -236,10 +194,6 @@ data class Email @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -250,10 +204,6 @@ data class CardRef @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -264,10 +214,6 @@ data class AddressRef @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -278,10 +224,6 @@ data class PinCode @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -316,10 +258,6 @@ data class Phones @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: List) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Phone): this(null, null, null, mutableListOf(value)) } @@ -330,10 +268,6 @@ data class HiddenField @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: List) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -344,10 +278,6 @@ data class SecureNote @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: List) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -358,10 +288,6 @@ data class AccountNumber @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: List) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } @@ -379,10 +305,6 @@ data class PaymentCards @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField(){ - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: PaymentCard): this(null, null, null, mutableListOf(value)) } @@ -401,10 +323,6 @@ data class BankAccounts @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField() { - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: BankAccount): this(null, null, null, mutableListOf(value)) } @@ -421,10 +339,6 @@ data class KeyPairs @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField() { - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: KeyPair): this(null, null, null, mutableListOf(value)) } @@ -441,10 +355,6 @@ data class Hosts @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField() { - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Host): this(null, null, null, mutableListOf(value)) } @@ -465,10 +375,6 @@ data class Addresses @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList
) : KeeperRecordField() { - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: Address): this(null, null, null, mutableListOf(value)) } @@ -479,18 +385,24 @@ data class LicenseNumber @JvmOverloads constructor( var required: Boolean? = null, var privacyScreen: Boolean? = null, val value: MutableList) : KeeperRecordField() { - - /** - * Constructor with the single value to eliminate the complexity of the passing List as a value - */ constructor(value: String): this(null, null, null, mutableListOf(value)) } +@Serializable +@SerialName("allowedSettings") +data class AllowedSettings @JvmOverloads constructor( + val connections: Boolean? = null, + val portForwards: Boolean? = null, + val rotation: Boolean? = null, + val sessionRecording: Boolean? = null, + val typescriptRecording: Boolean? = null +) @Serializable data class PamResource @JvmOverloads constructor( val controllerUid: String? = null, val folderUid: String? = null, - val resourceRef: MutableList + val resourceRef: MutableList? = null, + val allowedSettings: AllowedSettings? = null ) @Serializable @@ -505,7 +417,10 @@ data class PamResources @JvmOverloads constructor( @Serializable data class Schedule @JvmOverloads constructor( val type: String? = null, - val utcTime: String? = null, + val cron: String? = null, + // utcTime - replaced by time and tz + val time: String? = null, + val tz: String? = null, val weekday: String? = null, val intervalCount: Int? = null ) @@ -571,7 +486,7 @@ data class PrivateKey @JvmOverloads constructor( val crv: String? = null, val d: String? = null, val ext: Boolean? = null, - val key_ops: List? = null, + @SerialName("key_ops") val keyOps: List? = null, val kty: String? = null, val x: String? = null, val y: String? = null @@ -616,10 +531,150 @@ data class Scripts @JvmOverloads constructor( } @Serializable -data class KeeperFileData( - val title: String, - val name: String, - val type: String? = null, - val size: Long, - val lastModified: Long -) \ No newline at end of file +@SerialName("isSSIDHidden") +data class IsSsidHidden @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + val value: MutableList) : KeeperRecordField(){ + constructor(value: Boolean): this(null, null, mutableListOf(value)) +} + +@Serializable +@SerialName("wifiEncryption") +data class WifiEncryption @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} + +@Serializable +@SerialName("dropdown") +data class Dropdown @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} + +@Serializable +@SerialName("rbiUrl") +data class RbiUrl @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} + +@Serializable +data class AppFiller @JvmOverloads constructor( + val applicationTitle: String? = null, + val contentFilter: String? = null, + val macroSequence: String? = null, +) + +@Serializable +@SerialName("appFiller") +data class AppFillers @JvmOverloads constructor( + override val label: String? = null, + var required: Boolean? = null, + var privacyScreen: Boolean? = null, + val value: MutableList) : KeeperRecordField() { + constructor(value: AppFiller): this(null, null, null, mutableListOf(value)) +} + +@Serializable +@SerialName("connection") +data class PamRbiConnection @JvmOverloads constructor( + val protocol: String? = null, + val userRecords: MutableList? = null, + val allowUrlManipulation: Boolean? = null, + val allowedUrlPatterns: String? = null, + val allowedResourceUrlPatterns: String? = null, + val httpCredentialsUid: String? = null, + val autofillConfiguration: String? = null +) +@Serializable +data class PamRemoteBrowserSetting @JvmOverloads constructor( + val connection: PamRbiConnection? = null, +) + +@Serializable +@SerialName("pamRemoteBrowserSettings") +data class PamRemoteBrowserSettings @JvmOverloads constructor( + override val label: String? = null, + var required: Boolean? = null, + val value: MutableList) : KeeperRecordField() { + constructor(value: PamRemoteBrowserSetting): this(null, null, mutableListOf(value)) +} + +@Serializable +@SerialName("connection") +data class PamSettingsConnection @JvmOverloads constructor( + val protocol: String? = null, + val userRecords: MutableList? = null, + val security: String? = null, + val ignoreCert: Boolean? = null, + val resizeMethod: String? = null, + val colorScheme: String? = null +) +@Serializable +@SerialName("portForward") +data class PamSettingsPortForward @JvmOverloads constructor( + val reusePort: Boolean? = null, + val port: String? = null +) +@Serializable +data class PamSetting @JvmOverloads constructor( + val portForward: MutableList? = null, + val connection: MutableList? = null, +) + +@Serializable +@SerialName("pamSettings") +data class PamSettings @JvmOverloads constructor( + override val label: String? = null, + var required: Boolean? = null, + val value: MutableList) : KeeperRecordField() { + constructor(value: PamSetting): this(null, null, mutableListOf(value)) +} + +@Serializable +@SerialName("trafficEncryptionSeed") +data class TrafficEncryptionSeed @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} + +// List of retired field types: +// Replaced by trafficEncryptionSeed +@Serializable +@SerialName("trafficEncryptionKey") +internal data class TrafficEncryptionKey @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} + +// Deprecated for legacy/internal use only +@Serializable +@SerialName("pamProvider") +internal data class PamProvider @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} + +// Deprecated for legacy/internal use only +@Serializable +@SerialName("controller") +internal data class Controller @JvmOverloads constructor( + override var label: String? = null, + var required: Boolean? = null, + var value: MutableList) : KeeperRecordField(){ + constructor(value: String): this(null, null, mutableListOf(value)) +} diff --git a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/SecretsManager.kt b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/SecretsManager.kt index a702a296..c92bf7bf 100644 --- a/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/SecretsManager.kt +++ b/sdk/java/core/src/main/kotlin/com/keepersecurity/secretsManager/core/SecretsManager.kt @@ -7,7 +7,7 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonPrimitive import java.net.HttpURLConnection.HTTP_OK -import java.net.URL +import java.net.URI import java.security.KeyManagementException import java.security.NoSuchAlgorithmException import java.security.SecureRandom @@ -17,7 +17,7 @@ import java.util.* import java.util.concurrent.* import javax.net.ssl.* -const val KEEPER_CLIENT_VERSION = "mj16.6.4" +const val KEEPER_CLIENT_VERSION = "mj16.6.5" const val KEY_HOSTNAME = "hostname" // base url for the Secrets Manager service const val KEY_SERVER_PUBIC_KEY_ID = "serverPublicKeyId" @@ -669,7 +669,7 @@ fun downloadThumbnail(file: KeeperFile): ByteArray { } private fun downloadFile(file: KeeperFile, url: String): ByteArray { - with(URL(url).openConnection() as HttpsURLConnection) { + with(URI.create(url).toURL().openConnection() as HttpsURLConnection) { requestMethod = "GET" val statusCode = responseCode val data = when { @@ -689,7 +689,7 @@ private fun uploadFile(url: String, parameters: String, fileData: ByteArray): Ke val boundary = String.format("----------%x", Instant.now().epochSecond) val boundaryBytes: ByteArray = stringToBytes("\r\n--$boundary") val paramJson = Json.parseToJsonElement(parameters) as JsonObject - with(URL(url).openConnection() as HttpsURLConnection) { + with(URI.create(url).toURL().openConnection() as HttpsURLConnection) { requestMethod = "POST" useCaches = false doInput = true @@ -934,7 +934,7 @@ private fun prepareCreatePayload( val ownerPublicKey = storage.getBytes(KEY_OWNER_PUBLIC_KEY) ?: throw Exception("Application owner public key is missing from the configuration") val recordBytes = stringToBytes(Json.encodeToString(recordData)) val recordKey = getRandomBytes(32) - val recordUid = getRandomBytes(16) + val recordUid = generateUid() val encryptedRecord = encrypt(recordBytes, recordKey) val encryptedRecordKey = publicEncrypt(recordKey, ownerPublicKey) val encryptedFolderKey = encrypt(recordKey, folderKey) @@ -957,7 +957,7 @@ private fun prepareCreateFolderPayload( val clientId = storage.getString(KEY_CLIENT_ID) ?: throw Exception("Client Id is missing from the configuration") val folderDataBytes = stringToBytes(Json.encodeToString(KeeperFolderName(folderName))) val folderKey = getRandomBytes(32) - val folderUid = getRandomBytes(16) + val folderUid = generateUid() val encryptedFolderData = encrypt(folderDataBytes, folderKey, true) val encryptedFolderKey = encrypt(folderKey, sharedFolderKey, true) return CreateFolderPayload(KEEPER_CLIENT_VERSION, clientId, @@ -1055,7 +1055,7 @@ fun postFunction( ): KeeperHttpResponse { var statusCode: Int var data: ByteArray - with(URL(url).openConnection() as HttpsURLConnection) { + with(URI.create(url).toURL().openConnection() as HttpsURLConnection) { if (allowUnverifiedCertificate) { sslSocketFactory = trustAllSocketFactory() } @@ -1191,4 +1191,4 @@ internal object TestStubs { fun transmissionKeyStubReady(): Boolean { return this::transmissionKeyStub.isInitialized } -} \ No newline at end of file +}