From 4f2e8b9ff7a496361b9ec81b05614fe6f23ec451 Mon Sep 17 00:00:00 2001 From: Martin Gross Date: Mon, 11 Apr 2022 11:33:21 +0200 Subject: [PATCH] Cashier OTP-Login --- libpretixsync/build.gradle | 2 + .../libpretixsync/db/AbstractCashier.java | 37 ++++++++++++++++++- .../libpretixsync/db/AbstractSettings.java | 2 + .../sync/CashierSyncAdapter.java | 2 + 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/libpretixsync/build.gradle b/libpretixsync/build.gradle index 77344b46..237ff75f 100644 --- a/libpretixsync/build.gradle +++ b/libpretixsync/build.gradle @@ -115,6 +115,8 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'org.xerial:sqlite-jdbc:3.36.0.1' + + implementation 'dev.samstevens.totp:totp:1.7.1' } task copyTestResources(type: Copy) { diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractCashier.java b/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractCashier.java index d06de8ac..98de50aa 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractCashier.java +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractCashier.java @@ -1,6 +1,14 @@ package eu.pretix.libpretixsync.db; +import dev.samstevens.totp.code.CodeGenerator; +import dev.samstevens.totp.code.CodeVerifier; +import dev.samstevens.totp.code.DefaultCodeGenerator; +import dev.samstevens.totp.code.DefaultCodeVerifier; +import dev.samstevens.totp.code.HashingAlgorithm; +import dev.samstevens.totp.time.SystemTimeProvider; +import dev.samstevens.totp.time.TimeProvider; import eu.pretix.libpretixsync.BuildConfig; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -25,8 +33,12 @@ public class AbstractCashier implements RemoteObject, CashierLike { public String userid; + public String login_method; + public String pin; + public String otp_key; + @Column(value = BuildConfig.BOOLEAN_FALSE, nullable = false) public boolean active; @@ -40,10 +52,33 @@ public JSONObject getJSON() throws JSONException { @Override public boolean checkPIN(String pin) { + // LOGIN_AUTO = 'a' + // LOGIN_PIN = 'p' + // LOGIN_OTP = 'o' + // LOGIN_RFID = 'r' if (!this.active) { return false; } - return this.pin.equals(pin); + + if ( + (this.login_method.contains("p") || this.login_method.isEmpty()) && this.pin.equals(pin) + ) { + return true; + } + + if (this.login_method.contains("a")) { + return true; + } + + // TODO: Read Length from settings (pretixpos_cashier_otp_length) + if (this.login_method.contains("o") && pin.length() == 6) { + CodeGenerator codeGenerator = new DefaultCodeGenerator(HashingAlgorithm.SHA1, 6); + TimeProvider timeProvider = new SystemTimeProvider(); + CodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider); + return verifier.isValidCode(this.otp_key, pin); + } + + return false; } @Override diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractSettings.java b/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractSettings.java index e8ac39ed..0c988c54 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractSettings.java +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/db/AbstractSettings.java @@ -35,6 +35,8 @@ public abstract class AbstractSettings implements RemoteObject { @Nullable public String pretixpos_additional_receipt_text; + public Integer pretixpos_cashier_otp_length; + @Nullable public Boolean covid_certificates_record_proof; diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/sync/CashierSyncAdapter.java b/libpretixsync/src/main/java/eu/pretix/libpretixsync/sync/CashierSyncAdapter.java index 4d2e24cc..ad8b24a4 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/sync/CashierSyncAdapter.java +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/sync/CashierSyncAdapter.java @@ -24,7 +24,9 @@ public void updateObject(Cashier obj, JSONObject jsonobj) throws JSONException { obj.setServer_id(jsonobj.getLong("id")); obj.setName(jsonobj.getString("name")); obj.setUserid(jsonobj.getString("userid")); + obj.setLogin_method(jsonobj.getString("login_method")); obj.setPin(jsonobj.isNull("pin") ? "" : jsonobj.getString("pin")); + obj.setOtp_key(jsonobj.isNull("otp_key") ? "" : jsonobj.getString("otp_key")); obj.setJson_data(jsonobj.toString()); obj.setActive(jsonobj.getBoolean("active")); }