From 6def565be1d9b28b443da796e9319c1e51c9b5cc Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:05:00 +0100 Subject: [PATCH 01/35] Update AsyncRequestCallable.java --- src/main/java/org/privacyidea/AsyncRequestCallable.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/privacyidea/AsyncRequestCallable.java b/src/main/java/org/privacyidea/AsyncRequestCallable.java index 5519125..3a5757e 100644 --- a/src/main/java/org/privacyidea/AsyncRequestCallable.java +++ b/src/main/java/org/privacyidea/AsyncRequestCallable.java @@ -16,16 +16,17 @@ */ package org.privacyidea; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.Response; -import org.jetbrains.annotations.NotNull; import static org.privacyidea.PIConstants.ENDPOINT_AUTH; From 12c97b4cf7fb9f0106a32d8d862693f82cf8aaae Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:39:52 +0100 Subject: [PATCH 02/35] Update Challenge.java --- src/main/java/org/privacyidea/Challenge.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/privacyidea/Challenge.java b/src/main/java/org/privacyidea/Challenge.java index 861757a..3da7fa4 100644 --- a/src/main/java/org/privacyidea/Challenge.java +++ b/src/main/java/org/privacyidea/Challenge.java @@ -25,17 +25,17 @@ public class Challenge private final String serial; private final String clientMode; private final String message; - private final String transactionId; + private final String transactionID; private final String type; private final String image; - public Challenge(String serial, String message, String clientMode, String image, String transactionId, String type) + public Challenge(String serial, String message, String clientMode, String image, String transactionID, String type) { this.serial = serial; this.message = message; this.clientMode = clientMode; this.image = image; - this.transactionId = transactionId; + this.transactionID = transactionID; this.type = type; } @@ -49,7 +49,7 @@ public Challenge(String serial, String message, String clientMode, String image, public String getImage() {return image.replaceAll("\"", "");} - public String getTransactionID() {return transactionId;} + public String getTransactionID() {return transactionID;} public String getType() {return type;} } From 4a6c7fccc133eca7fbc19b9ab66733ce6968a721 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:04 +0100 Subject: [PATCH 03/35] Update Endpoint.java --- src/main/java/org/privacyidea/Endpoint.java | 51 +++++++++------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/privacyidea/Endpoint.java b/src/main/java/org/privacyidea/Endpoint.java index b4658a5..0ae7cb3 100644 --- a/src/main/java/org/privacyidea/Endpoint.java +++ b/src/main/java/org/privacyidea/Endpoint.java @@ -16,28 +16,21 @@ */ package org.privacyidea; +import okhttp3.*; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import okhttp3.Callback; -import okhttp3.FormBody; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import static org.privacyidea.PIConstants.GET; -import static org.privacyidea.PIConstants.HEADER_USER_AGENT; -import static org.privacyidea.PIConstants.POST; -import static org.privacyidea.PIConstants.WEBAUTHN_PARAMETERS; +import static org.privacyidea.PIConstants.*; /** * This class handles sending requests to the server. @@ -45,7 +38,7 @@ class Endpoint { private final PrivacyIDEA privacyIDEA; - private final PIConfig piconfig; + private final PIConfig piConfig; private final OkHttpClient client; final TrustManager[] trustAllManager = new TrustManager[]{new X509TrustManager() @@ -70,14 +63,14 @@ public java.security.cert.X509Certificate[] getAcceptedIssuers() Endpoint(PrivacyIDEA privacyIDEA) { this.privacyIDEA = privacyIDEA; - this.piconfig = privacyIDEA.configuration(); + this.piConfig = privacyIDEA.configuration(); OkHttpClient.Builder builder = new OkHttpClient.Builder(); - builder.connectTimeout(piconfig.httpTimeoutMs, TimeUnit.MILLISECONDS) - .writeTimeout(piconfig.httpTimeoutMs, TimeUnit.MILLISECONDS) - .readTimeout(piconfig.httpTimeoutMs, TimeUnit.MILLISECONDS); + builder.connectTimeout(piConfig.getHttpTimeoutMs(), TimeUnit.MILLISECONDS) + .writeTimeout(piConfig.getHttpTimeoutMs(), TimeUnit.MILLISECONDS) + .readTimeout(piConfig.getHttpTimeoutMs(), TimeUnit.MILLISECONDS); - if (!this.piconfig.doSSLVerify) + if (!this.piConfig.getVerifySSL()) { // Trust all certs and verify every host try @@ -108,10 +101,10 @@ public java.security.cert.X509Certificate[] getAcceptedIssuers() void sendRequestAsync(String endpoint, Map params, Map headers, String method, Callback callback) { - HttpUrl httpUrl = HttpUrl.parse(piconfig.serverURL + endpoint); + HttpUrl httpUrl = HttpUrl.parse(piConfig.getServerURL() + endpoint); if (httpUrl == null) { - privacyIDEA.error("Server url could not be parsed: " + (piconfig.serverURL + endpoint)); + privacyIDEA.error("Server url could not be parsed: " + (piConfig.getServerURL() + endpoint)); // Invoke the callback to terminate the thread that called this function. callback.onFailure(null, new IOException("Request could not be created because the url could not be parsed")); return; @@ -119,22 +112,22 @@ void sendRequestAsync(String endpoint, Map params, Map - { + { if (k.equals("pass") || k.equals("password")) { v = "*".repeat(v.length()); } privacyIDEA.log(k + "=" + v); - }); + }); if (GET.equals(method)) { params.forEach((key, value) -> - { + { String encValue = URLEncoder.encode(value, StandardCharsets.UTF_8); urlBuilder.addQueryParameter(key, encValue); - }); + }); } String url = urlBuilder.build().toString(); @@ -142,7 +135,7 @@ void sendRequestAsync(String endpoint, Map params, Map params, Map - { + { if (key != null && value != null) { String encValue = value; @@ -164,7 +157,7 @@ void sendRequestAsync(String endpoint, Map params, Map Date: Wed, 13 Nov 2024 14:40:08 +0100 Subject: [PATCH 04/35] Update IPISimpleLogger.java --- src/main/java/org/privacyidea/IPISimpleLogger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/privacyidea/IPISimpleLogger.java b/src/main/java/org/privacyidea/IPISimpleLogger.java index 0962247..7b7ab59 100644 --- a/src/main/java/org/privacyidea/IPISimpleLogger.java +++ b/src/main/java/org/privacyidea/IPISimpleLogger.java @@ -21,5 +21,5 @@ */ public interface IPISimpleLogger { - void pilog(String message); + void piLog(String message); } From 9da081c2e6719defb945cf3a367b1f0a1964bc0f Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:20 +0100 Subject: [PATCH 05/35] Update JSONParser.java --- src/main/java/org/privacyidea/JSONParser.java | 124 ++++++------------ 1 file changed, 38 insertions(+), 86 deletions(-) diff --git a/src/main/java/org/privacyidea/JSONParser.java b/src/main/java/org/privacyidea/JSONParser.java index b91ae2b..2757141 100644 --- a/src/main/java/org/privacyidea/JSONParser.java +++ b/src/main/java/org/privacyidea/JSONParser.java @@ -16,57 +16,14 @@ */ package org.privacyidea; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSyntaxException; +import com.google.gson.*; + import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import static org.privacyidea.PIConstants.ASSERTIONCLIENTEXTENSIONS; -import static org.privacyidea.PIConstants.ATTRIBUTES; -import static org.privacyidea.PIConstants.AUTHENTICATION; -import static org.privacyidea.PIConstants.AUTHENTICATORDATA; -import static org.privacyidea.PIConstants.CLIENTDATA; -import static org.privacyidea.PIConstants.CLIENT_MODE; -import static org.privacyidea.PIConstants.CODE; -import static org.privacyidea.PIConstants.CREDENTIALID; -import static org.privacyidea.PIConstants.DETAIL; -import static org.privacyidea.PIConstants.ERROR; -import static org.privacyidea.PIConstants.ID; -import static org.privacyidea.PIConstants.IMAGE; -import static org.privacyidea.PIConstants.INFO; -import static org.privacyidea.PIConstants.JSONRPC; -import static org.privacyidea.PIConstants.MAXFAIL; -import static org.privacyidea.PIConstants.MESSAGE; -import static org.privacyidea.PIConstants.MESSAGES; -import static org.privacyidea.PIConstants.MULTI_CHALLENGE; -import static org.privacyidea.PIConstants.OTPLEN; -import static org.privacyidea.PIConstants.PREFERRED_CLIENT_MODE; -import static org.privacyidea.PIConstants.REALMS; -import static org.privacyidea.PIConstants.RESULT; -import static org.privacyidea.PIConstants.SERIAL; -import static org.privacyidea.PIConstants.SIGNATURE; -import static org.privacyidea.PIConstants.SIGNATUREDATA; -import static org.privacyidea.PIConstants.STATUS; -import static org.privacyidea.PIConstants.TOKEN; -import static org.privacyidea.PIConstants.TOKENS; -import static org.privacyidea.PIConstants.TOKEN_TYPE_U2F; -import static org.privacyidea.PIConstants.TOKEN_TYPE_WEBAUTHN; -import static org.privacyidea.PIConstants.TRANSACTION_ID; -import static org.privacyidea.PIConstants.TYPE; -import static org.privacyidea.PIConstants.U2F_SIGN_REQUEST; -import static org.privacyidea.PIConstants.USERHANDLE; -import static org.privacyidea.PIConstants.USERNAME; -import static org.privacyidea.PIConstants.VALUE; -import static org.privacyidea.PIConstants.VERSION_NUMBER; -import static org.privacyidea.PIConstants.WEBAUTHN_SIGN_REQUEST; +import static org.privacyidea.PIConstants.*; public class JSONParser { @@ -221,12 +178,12 @@ else if ("interactive".equals(modeFromResponse)) if (arrMessages != null) { arrMessages.forEach(val -> - { + { if (val != null) { response.messages.add(val.getAsString()); } - }); + }); } JsonArray arrChallenges = detail.getAsJsonArray(MULTI_CHALLENGE); @@ -237,24 +194,19 @@ else if ("interactive".equals(modeFromResponse)) JsonObject challenge = arrChallenges.get(i).getAsJsonObject(); String serial = getString(challenge, SERIAL); String message = getString(challenge, MESSAGE); - String clientmode = getString(challenge, CLIENT_MODE); + String clientMode = getString(challenge, CLIENT_MODE); String image = getString(challenge, IMAGE); - String transactionid = getString(challenge, TRANSACTION_ID); + String transactionID = getString(challenge, TRANSACTION_ID); String type = getString(challenge, TYPE); if (TOKEN_TYPE_WEBAUTHN.equals(type)) { - String webAuthnSignRequest = getItemFromAttributes(WEBAUTHN_SIGN_REQUEST, challenge); - response.multichallenge.add(new WebAuthn(serial, message, clientmode, image, transactionid, webAuthnSignRequest)); - } - else if (TOKEN_TYPE_U2F.equals(type)) - { - String u2fSignRequest = getItemFromAttributes(U2F_SIGN_REQUEST, challenge); - response.multichallenge.add(new U2F(serial, message, clientmode, image, transactionid, u2fSignRequest)); + String webauthnSignRequest = getItemFromAttributes(WEBAUTHN_SIGN_REQUEST, challenge); + response.multiChallenge.add(new WebAuthn(serial, message, clientMode, image, transactionID, webauthnSignRequest)); } else { - response.multichallenge.add(new Challenge(serial, message, clientmode, image, transactionid, type)); + response.multiChallenge.add(new Challenge(serial, message, clientMode, image, transactionID, type)); } } } @@ -262,7 +214,7 @@ else if (TOKEN_TYPE_U2F.equals(type)) return response; } - static String mergeWebAuthnSignRequest(WebAuthn webAuthn, List arr) throws JsonSyntaxException + static String mergeWebAuthnSignRequest(WebAuthn webauthn, List arr) throws JsonSyntaxException { List extracted = new ArrayList<>(); for (String signRequest : arr) @@ -271,7 +223,7 @@ static String mergeWebAuthnSignRequest(WebAuthn webAuthn, List arr) thro extracted.add(obj.getAsJsonArray("allowCredentials")); } - JsonObject signRequest = JsonParser.parseString(webAuthn.signRequest()).getAsJsonObject(); + JsonObject signRequest = JsonParser.parseString(webauthn.signRequest()).getAsJsonObject(); JsonArray allowCredentials = new JsonArray(); extracted.forEach(allowCredentials::addAll); @@ -391,24 +343,24 @@ private TokenInfo parseSingleTokenInfo(String json) if (joInfo != null) { joInfo.entrySet().forEach(entry -> - { + { if (entry.getKey() != null && entry.getValue() != null) { info.info.put(entry.getKey(), entry.getValue().getAsString()); } - }); + }); } JsonArray arrRealms = obj.getAsJsonArray(REALMS); if (arrRealms != null) { arrRealms.forEach(val -> - { + { if (val != null) { info.realms.add(val.getAsString()); } - }); + }); } return info; } @@ -421,15 +373,15 @@ private TokenInfo parseSingleTokenInfo(String json) */ RolloutInfo parseRolloutInfo(String serverResponse) { - RolloutInfo rinfo = new RolloutInfo(); - rinfo.raw = serverResponse; - rinfo.googleurl = new RolloutInfo.GoogleURL(); - rinfo.oathurl = new RolloutInfo.OATHURL(); - rinfo.otpkey = new RolloutInfo.OTPKey(); + RolloutInfo rInfo = new RolloutInfo(); + rInfo.raw = serverResponse; + rInfo.googleurl = new RolloutInfo.GoogleURL(); + rInfo.oathurl = new RolloutInfo.OATHURL(); + rInfo.otpkey = new RolloutInfo.OTPKey(); if (serverResponse == null || serverResponse.isEmpty()) { - return rinfo; + return rInfo; } JsonObject obj; @@ -442,8 +394,8 @@ RolloutInfo parseRolloutInfo(String serverResponse) if (errElem != null && !errElem.isJsonNull()) { JsonObject errObj = result.getAsJsonObject(ERROR); - rinfo.error = new PIError(getInt(errObj, CODE), getString(errObj, MESSAGE)); - return rinfo; + rInfo.error = new PIError(getInt(errObj, CODE), getString(errObj, MESSAGE)); + return rInfo; } JsonObject detail = obj.getAsJsonObject("detail"); @@ -452,39 +404,39 @@ RolloutInfo parseRolloutInfo(String serverResponse) JsonObject google = detail.getAsJsonObject("googleurl"); if (google != null) { - rinfo.googleurl.description = getString(google, "description"); - rinfo.googleurl.img = getString(google, "img"); - rinfo.googleurl.value = getString(google, "value"); + rInfo.googleurl.description = getString(google, "description"); + rInfo.googleurl.img = getString(google, "img"); + rInfo.googleurl.value = getString(google, "value"); } JsonObject oath = detail.getAsJsonObject("oath"); if (oath != null) { - rinfo.oathurl.description = getString(oath, "description"); - rinfo.oathurl.img = getString(oath, "img"); - rinfo.oathurl.value = getString(oath, "value"); + rInfo.oathurl.description = getString(oath, "description"); + rInfo.oathurl.img = getString(oath, "img"); + rInfo.oathurl.value = getString(oath, "value"); } JsonObject otp = detail.getAsJsonObject("otpkey"); if (otp != null) { - rinfo.otpkey.description = getString(otp, "description"); - rinfo.otpkey.img = getString(otp, "img"); - rinfo.otpkey.value = getString(otp, "value"); - rinfo.otpkey.value_b32 = getString(otp, "value_b32"); + rInfo.otpkey.description = getString(otp, "description"); + rInfo.otpkey.img = getString(otp, "img"); + rInfo.otpkey.value = getString(otp, "value"); + rInfo.otpkey.value_b32 = getString(otp, "value_b32"); } - rinfo.serial = getString(detail, "serial"); - rinfo.rolloutState = getString(detail, "rollout_state"); + rInfo.serial = getString(detail, "serial"); + rInfo.rolloutState = getString(detail, "rollout_state"); } } catch (JsonSyntaxException | ClassCastException e) { privacyIDEA.error(e); - return rinfo; + return rInfo; } - return rinfo; + return rInfo; } /** From 6fc087e65951442cc4c6fc7e4f7d0f22b4ddb849 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:34 +0100 Subject: [PATCH 06/35] Update PIConfig.java --- src/main/java/org/privacyidea/PIConfig.java | 108 ++++++++++++++++++-- 1 file changed, 99 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/privacyidea/PIConfig.java b/src/main/java/org/privacyidea/PIConfig.java index 0d494e4..c3fec5e 100644 --- a/src/main/java/org/privacyidea/PIConfig.java +++ b/src/main/java/org/privacyidea/PIConfig.java @@ -18,19 +18,109 @@ class PIConfig { - String serverURL; - String realm = ""; - boolean doSSLVerify = true; - String serviceAccountName = ""; - String serviceAccountPass = ""; - String serviceAccountRealm = ""; - boolean disableLog = false; - String userAgent; - int httpTimeoutMs = 30000; + private final String serverURL; + private final String userAgent; + private String realm = ""; + private boolean verifySSL = true; + private String serviceAccountName = ""; + private String serviceAccountPass = ""; + private String serviceAccountRealm = ""; + private boolean disableLog = false; + private final boolean forwardClientIP = false; + private int httpTimeoutMs = 30000; public PIConfig(String serverURL, String userAgent) { this.serverURL = serverURL; this.userAgent = userAgent; } + + // SETTERS + + public void setRealm(String realm) + { + this.realm = realm; + } + + public void setVerifySSL(boolean verifySSL) + { + this.verifySSL = verifySSL; + } + + public void setServiceAccountName(String serviceAccountName) + { + this.serviceAccountName = serviceAccountName; + } + + public void setServiceAccountPass(String serviceAccountPass) + { + this.serviceAccountPass = serviceAccountPass; + } + + public void setServiceAccountRealm(String serviceAccountRealm) + { + this.serviceAccountRealm = serviceAccountRealm; + } + + public void setDisableLog(boolean disableLog) + { + this.disableLog = disableLog; + } + + public void setHttpTimeoutMs(int httpTimeoutMs) + { + this.httpTimeoutMs = httpTimeoutMs; + } + + // GETTERS + + public String getServerURL() + { + return serverURL; + } + + public String getUserAgent() + { + return userAgent; + } + + public String getRealm() + { + return realm; + } + + public boolean getVerifySSL() + { + return verifySSL; + } + + public String getServiceAccountName() + { + return serviceAccountName; + } + + public String getServiceAccountPass() + { + return serviceAccountPass; + } + + public String getServiceAccountRealm() + { + return serviceAccountRealm; + } + + public boolean getDisableLog() + { + return disableLog; + } + + public boolean getForwardClientIP() + { + return forwardClientIP; + } + + public int getHttpTimeoutMs() + { + return httpTimeoutMs; + } } \ No newline at end of file From 95d13f58c68914d32ad0f4c9d0344b627033075b Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:38 +0100 Subject: [PATCH 07/35] Update PIConstants.java --- .../java/org/privacyidea/PIConstants.java | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/privacyidea/PIConstants.java b/src/main/java/org/privacyidea/PIConstants.java index 8fe17cd..e404d89 100644 --- a/src/main/java/org/privacyidea/PIConstants.java +++ b/src/main/java/org/privacyidea/PIConstants.java @@ -42,9 +42,6 @@ private PIConstants() // TOKEN TYPES public static final String TOKEN_TYPE_PUSH = "push"; - public static final String TOKEN_TYPE_OTP = "otp"; - public static final String TOKEN_TYPE_TOTP = "totp"; - public static final String TOKEN_TYPE_HOTP = "hotp"; public static final String TOKEN_TYPE_WEBAUTHN = "webauthn"; public static final String TOKEN_TYPE_U2F = "u2f"; @@ -83,15 +80,6 @@ private PIConstants() public static final String ID = "id"; public static final String MAXFAIL = "maxfail"; public static final String INFO = "info"; - public static final String LOCKED = "locked"; - public static final String FAILCOUNT = "failcount"; - public static final String DESCRIPTION = "description"; - public static final String COUNT = "count"; - public static final String COUNT_WINDOW = "count_window"; - public static final String ACTIVE = "active"; - public static final String RESOLVER = "resolver"; - public static final String REVOKED = "revoked"; - public static final String SYNC_WINDOW = "sync_window"; // WebAuthn and U2F params public static final String WEBAUTHN_SIGN_REQUEST = "webAuthnSignRequest"; @@ -105,8 +93,8 @@ private PIConstants() // These will be excluded from url encoding - public static final List WEBAUTHN_PARAMETERS = Arrays.asList(CREDENTIALID, CLIENTDATA, SIGNATUREDATA, AUTHENTICATORDATA, USERHANDLE, - ASSERTIONCLIENTEXTENSIONS); - public static final List U2F_PARAMETERS = Arrays.asList(CLIENTDATA, SIGNATUREDATA); - + public static final List + WEBAUTHN_PARAMETERS = + Arrays.asList(CREDENTIALID, CLIENTDATA, SIGNATUREDATA, AUTHENTICATORDATA, USERHANDLE, + ASSERTIONCLIENTEXTENSIONS); } From 1544491f9487e3ad164d5a4ab8faaaaf0d701ada Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:42 +0100 Subject: [PATCH 08/35] Update PIError.java --- src/main/java/org/privacyidea/PIError.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/privacyidea/PIError.java b/src/main/java/org/privacyidea/PIError.java index 093f6cf..14cc925 100644 --- a/src/main/java/org/privacyidea/PIError.java +++ b/src/main/java/org/privacyidea/PIError.java @@ -18,12 +18,22 @@ public class PIError { + private final int code; + private final String message; + public PIError(int code, String message) { this.code = code; this.message = message; } - public int code; - public String message; + public int getCode() + { + return code; + } + + public String getMessage() + { + return message; + } } From dfa4aeb2b03a4ea0a449b3b1187f7b4f04045a99 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:48 +0100 Subject: [PATCH 09/35] Update PIResponse.java --- src/main/java/org/privacyidea/PIResponse.java | 124 ++++++++---------- 1 file changed, 58 insertions(+), 66 deletions(-) diff --git a/src/main/java/org/privacyidea/PIResponse.java b/src/main/java/org/privacyidea/PIResponse.java index c880aad..a7a9485 100644 --- a/src/main/java/org/privacyidea/PIResponse.java +++ b/src/main/java/org/privacyidea/PIResponse.java @@ -17,49 +17,54 @@ package org.privacyidea; import com.google.gson.JsonSyntaxException; + import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; -import static org.privacyidea.PIConstants.TOKEN_TYPE_PUSH; -import static org.privacyidea.PIConstants.TOKEN_TYPE_U2F; -import static org.privacyidea.PIConstants.TOKEN_TYPE_WEBAUTHN; +import static org.privacyidea.PIConstants.*; /** * This class parses the JSON response of privacyIDEA into a POJO for easier access. */ public class PIResponse { - public String message = ""; - public String preferredClientMode = ""; - public List messages = new ArrayList<>(); - public List multichallenge = new ArrayList<>(); - public String transactionID = ""; - public String serial = ""; - public String image = ""; - public int id = 0; - public String jsonRPCVersion = ""; - public boolean status = false; - public boolean value = false; - public AuthenticationStatus authentication = AuthenticationStatus.NONE; - public String piVersion = ""; // e.g. 3.2.1 - public String rawMessage = ""; - public String signature = ""; - public String type = ""; // Type of token that was matching the request - public int otpLength = 0; - - public PIError error = null; + String message = ""; + String preferredClientMode = ""; + List messages = new ArrayList<>(); + List multiChallenge = new ArrayList<>(); + String transactionID = ""; + String serial = ""; + String image = ""; + int id = 0; + String jsonRPCVersion = ""; + boolean status = false; + boolean value = false; + AuthenticationStatus authentication = AuthenticationStatus.NONE; + String piVersion = ""; // e.g. 3.2.1 + String rawMessage = ""; + String signature = ""; + String type = ""; // Type of token that was matching the request + int otpLength = 0; + PIError error = null; + + + /** + * Check if a PUSH token was triggered. + * + * @return True if a PUSH token was triggered. + */ public boolean pushAvailable() { - return multichallenge.stream().anyMatch(c -> TOKEN_TYPE_PUSH.equals(c.getType())); + return multiChallenge.stream().anyMatch(c -> TOKEN_TYPE_PUSH.equals(c.getType())); } /** - * Get the messages of all triggered push challenges reduced to a string to show on the push UI. + * Get the messages of all triggered PUSH challenges. * - * @return messages of all push challenges combined + * @return Combined messages of all PUSH challenges. */ public String pushMessage() { @@ -67,36 +72,38 @@ public String pushMessage() } /** - * Get the messages of all token that require an input field (HOTP, TOTP, SMS, Email...) reduced to a single string - * to show with the input field. + * Get the messages of all token that require an input field (HOTP, TOTP, SMS, Email...) reduced to a single string. * - * @return message string + * @return Message string. */ public String otpMessage() { - // Any challenge that is not WebAuthn, U2F or Push is considered OTP return reduceChallengeMessagesWhere(c -> !(TOKEN_TYPE_PUSH.equals(c.getType()))); } private String reduceChallengeMessagesWhere(Predicate predicate) { StringBuilder sb = new StringBuilder(); - sb.append(multichallenge.stream().filter(predicate).map(Challenge::getMessage).distinct().reduce("", (a, s) -> a + s + ", ").trim()); + sb.append(multiChallenge.stream() + .filter(predicate) + .map(Challenge::getMessage) + .distinct() + .reduce("", (a, s) -> a + s + ", ") + .trim()); if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); } - return sb.toString(); } /** - * @return list of token types that were triggered or an empty list + * @return List of token types that were triggered or an empty list. */ public List triggeredTokenTypes() { - return multichallenge.stream().map(Challenge::getType).distinct().collect(Collectors.toList()); + return multiChallenge.stream().map(Challenge::getType).distinct().collect(Collectors.toList()); } /** @@ -107,13 +114,16 @@ public List triggeredTokenTypes() public List webAuthnSignRequests() { List ret = new ArrayList<>(); - multichallenge.stream().filter(c -> TOKEN_TYPE_WEBAUTHN.equals(c.getType())).collect(Collectors.toList()).forEach(c -> - { - if (c instanceof WebAuthn) - { - ret.add((WebAuthn) c); - } - }); + multiChallenge.stream() + .filter(c -> TOKEN_TYPE_WEBAUTHN.equals(c.getType())) + .collect(Collectors.toList()) + .forEach(c -> + { + if (c instanceof WebAuthn) + { + ret.add((WebAuthn) c); + } + }); return ret; } @@ -123,26 +133,26 @@ public List webAuthnSignRequests() *

* Can return an empty string if an error occurred or if no WebAuthn challenges have been triggered. * - * @return merged SignRequest or empty string. + * @return Merged SignRequest or empty string. */ public String mergedSignRequest() { - List webAuthnSignRequests = webAuthnSignRequests(); - if (webAuthnSignRequests.isEmpty()) + List webauthnSignRequests = webAuthnSignRequests(); + if (webauthnSignRequests.isEmpty()) { return ""; } - if (webAuthnSignRequests.size() == 1) + if (webauthnSignRequests.size() == 1) { - return webAuthnSignRequests.get(0).signRequest(); + return webauthnSignRequests.get(0).signRequest(); } - WebAuthn webAuthn = webAuthnSignRequests.get(0); - List stringSignRequests = webAuthnSignRequests.stream().map(WebAuthn::signRequest).collect(Collectors.toList()); + WebAuthn webauthn = webauthnSignRequests.get(0); + List stringSignRequests = webauthnSignRequests.stream().map(WebAuthn::signRequest).collect(Collectors.toList()); try { - return JSONParser.mergeWebAuthnSignRequest(webAuthn, stringSignRequests); + return JSONParser.mergeWebAuthnSignRequest(webauthn, stringSignRequests); } catch (JsonSyntaxException e) { @@ -150,24 +160,6 @@ public String mergedSignRequest() } } - /** - * Get all U2F challenges from the multi_challenge. - * - * @return List of U2F objects or empty list - */ - public List u2fSignRequests() - { - List ret = new ArrayList<>(); - multichallenge.stream().filter(c -> TOKEN_TYPE_U2F.equals(c.getType())).collect(Collectors.toList()).forEach(c -> - { - if (c instanceof U2F) - { - ret.add((U2F) c); - } - }); - return ret; - } - @Override public String toString() { From 65270f7e9887f17f178b017cefb43fbbee56f34e Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:51 +0100 Subject: [PATCH 10/35] Update PrivacyIDEA.java --- .../java/org/privacyidea/PrivacyIDEA.java | 187 +++++++----------- 1 file changed, 67 insertions(+), 120 deletions(-) diff --git a/src/main/java/org/privacyidea/PrivacyIDEA.java b/src/main/java/org/privacyidea/PrivacyIDEA.java index 62d736e..b46e583 100644 --- a/src/main/java/org/privacyidea/PrivacyIDEA.java +++ b/src/main/java/org/privacyidea/PrivacyIDEA.java @@ -18,39 +18,10 @@ import java.io.Closeable; import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.privacyidea.PIConstants.ENDPOINT_AUTH; -import static org.privacyidea.PIConstants.ENDPOINT_POLLTRANSACTION; -import static org.privacyidea.PIConstants.ENDPOINT_TOKEN; -import static org.privacyidea.PIConstants.ENDPOINT_TOKEN_INIT; -import static org.privacyidea.PIConstants.ENDPOINT_TRIGGERCHALLENGE; -import static org.privacyidea.PIConstants.ENDPOINT_VALIDATE_CHECK; -import static org.privacyidea.PIConstants.GENKEY; -import static org.privacyidea.PIConstants.GET; -import static org.privacyidea.PIConstants.HEADER_ORIGIN; -import static org.privacyidea.PIConstants.OTPKEY; -import static org.privacyidea.PIConstants.PASS; -import static org.privacyidea.PIConstants.PASSWORD; -import static org.privacyidea.PIConstants.POST; -import static org.privacyidea.PIConstants.REALM; -import static org.privacyidea.PIConstants.SERIAL; -import static org.privacyidea.PIConstants.TRANSACTION_ID; -import static org.privacyidea.PIConstants.TYPE; -import static org.privacyidea.PIConstants.USER; -import static org.privacyidea.PIConstants.USERNAME; +import java.util.*; +import java.util.concurrent.*; + +import static org.privacyidea.PIConstants.*; /** * This is the main class. It implements the common endpoints such as /validate/check as methods for easy usage. @@ -99,9 +70,9 @@ public PIResponse validateCheck(String username, String pass, Map headers) + public PIResponse validateCheck(String username, String pass, String transactionID, Map headers) { - return getPIResponse(USER, username, pass, headers, transactionId); + return getPIResponse(USER, username, pass, headers, transactionID); } /** @@ -139,9 +110,9 @@ public PIResponse validateCheckSerial(String serial, String pass, Map headers) + public PIResponse validateCheckSerial(String serial, String pass, String transactionID, Map headers) { - return getPIResponse(SERIAL, serial, pass, headers, transactionId); + return getPIResponse(SERIAL, serial, pass, headers, transactionID); } /** @@ -164,19 +135,19 @@ public PIResponse validateCheckSerial(String serial, String pass, String transac * @param input forwarded username for classic validateCheck or serial to trigger exact token * @param pass OTP, PIN+OTP or password to use * @param headers optional headers for the request - * @param transactionId optional, will be appended if set + * @param transactionID optional, will be appended if set * @return PIResponse object containing the response or null if error */ - private PIResponse getPIResponse(String type, String input, String pass, Map headers, String transactionId) + private PIResponse getPIResponse(String type, String input, String pass, Map headers, String transactionID) { Map params = new LinkedHashMap<>(); // Add forwarded user or serial to the params params.put(type, input); params.put(PASS, (pass != null ? pass : "")); appendRealm(params); - if (transactionId != null && !transactionId.isEmpty()) + if (transactionID != null && !transactionID.isEmpty()) { - params.put(TRANSACTION_ID, transactionId); + params.put(TRANSACTION_ID, transactionID); } String response = runRequestAsync(ENDPOINT_VALIDATE_CHECK, params, headers, false, POST); return this.parser.parsePIResponse(response); @@ -185,27 +156,28 @@ private PIResponse getPIResponse(String type, String input, String pass, Map headers) + public PIResponse validateCheckWebAuthn(String user, String transactionID, String webAuthnSignResponse, String origin, + Map headers) { Map params = new LinkedHashMap<>(); // Standard validateCheck data params.put(USER, user); - params.put(TRANSACTION_ID, transactionId); + params.put(TRANSACTION_ID, transactionID); params.put(PASS, ""); appendRealm(params); @@ -221,39 +193,6 @@ public PIResponse validateCheckWebAuthn(String user, String transactionId, Strin return this.parser.parsePIResponse(response); } - /** - * @see PrivacyIDEA#validateCheckU2F(String, String, String, Map) - */ - public PIResponse validateCheckU2F(String user, String transactionId, String signResponse) - { - return this.validateCheckU2F(user, transactionId, signResponse, Collections.emptyMap()); - } - - /** - * Sends a request to /validate/check with the data required to authenticate a U2F token. - * - * @param user username - * @param transactionId transactionId - * @param u2fSignResponse the U2F Sign Response as returned from the browser - * @return PIResponse or null if error - */ - public PIResponse validateCheckU2F(String user, String transactionId, String u2fSignResponse, Map headers) - { - Map params = new LinkedHashMap<>(); - // Standard validateCheck data - params.put(USER, user); - params.put(TRANSACTION_ID, transactionId); - params.put(PASS, ""); - appendRealm(params); - - // Additional U2F data - Map u2fParams = parser.parseU2FSignResponse(u2fSignResponse); - params.putAll(u2fParams); - - String response = runRequestAsync(ENDPOINT_VALIDATE_CHECK, params, headers, false, POST); - return this.parser.parsePIResponse(response); - } - /** * @see PrivacyIDEA#triggerChallenges(String, Map) */ @@ -289,15 +228,17 @@ public PIResponse triggerChallenges(String username, Map headers /** * Poll for status of the given transaction ID once. * - * @param transactionId transaction ID to poll for + * @param transactionID transaction ID to poll for * @return the status value, true or false */ - public boolean pollTransaction(String transactionId) + public boolean pollTransaction(String transactionID) { - Objects.requireNonNull(transactionId, "TransactionID is required!"); + Objects.requireNonNull(transactionID, "TransactionID is required!"); - String response = runRequestAsync(ENDPOINT_POLLTRANSACTION, Collections.singletonMap(TRANSACTION_ID, transactionId), Collections.emptyMap(), - false, GET); + String + response = + runRequestAsync(ENDPOINT_POLLTRANSACTION, Collections.singletonMap(TRANSACTION_ID, transactionID), Collections.emptyMap(), + false, GET); PIResponse piresponse = this.parser.parsePIResponse(response); return piresponse.value; } @@ -321,16 +262,16 @@ public String getAuthToken() Map serviceAccountParam() { Map authTokenParams = new LinkedHashMap<>(); - authTokenParams.put(USERNAME, configuration.serviceAccountName); - authTokenParams.put(PASSWORD, configuration.serviceAccountPass); + authTokenParams.put(USERNAME, configuration.getServiceAccountName()); + authTokenParams.put(PASSWORD, configuration.getServiceAccountPass()); - if (configuration.serviceAccountRealm != null && !configuration.serviceAccountRealm.isEmpty()) + if (configuration.getServiceAccountRealm() != null && !configuration.getServiceAccountRealm().isEmpty()) { - authTokenParams.put(REALM, configuration.serviceAccountRealm); + authTokenParams.put(REALM, configuration.getServiceAccountRealm()); } - else if (configuration.realm != null && !configuration.realm.isEmpty()) + else if (configuration.getRealm() != null && !configuration.getRealm().isEmpty()) { - authTokenParams.put(REALM, configuration.realm); + authTokenParams.put(REALM, configuration.getRealm()); } return authTokenParams; } @@ -409,9 +350,9 @@ public RolloutInfo tokenInit(String username, String typeToEnroll, String otpKey private void appendRealm(Map params) { - if (configuration.realm != null && !configuration.realm.isEmpty()) + if (configuration.getRealm() != null && !configuration.getRealm().isEmpty()) { - params.put(REALM, configuration.realm); + params.put(REALM, configuration.getRealm()); } } @@ -426,7 +367,8 @@ private void appendRealm(Map params) * @param method http request method * @return response of the server as string or null */ - private String runRequestAsync(String path, Map params, Map headers, boolean authTokenRequired, String method) + private String runRequestAsync(String path, Map params, Map headers, boolean authTokenRequired, + String method) { Callable callable = new AsyncRequestCallable(this, endpoint, path, params, headers, authTokenRequired, method); Future future = threadPool.submit(callable); @@ -458,10 +400,14 @@ public void logExcludedEndpoints(List list) this.logExcludedEndpoints = list; } + /** + * @return true if a service account is available + */ public boolean serviceAccountAvailable() { - return configuration.serviceAccountName != null && !configuration.serviceAccountName.isEmpty() && configuration.serviceAccountPass != null && - !configuration.serviceAccountPass.isEmpty(); + return configuration.getServiceAccountName() != null && !configuration.getServiceAccountName().isEmpty() + && configuration.getServiceAccountPass() != null && + !configuration.getServiceAccountPass().isEmpty(); } PIConfig configuration() @@ -476,7 +422,7 @@ PIConfig configuration() */ void error(String message) { - if (!configuration.disableLog) + if (!configuration.getDisableLog()) { if (this.log != null) { @@ -484,7 +430,7 @@ void error(String message) } else if (this.simpleLog != null) { - this.simpleLog.pilog(message); + this.simpleLog.piLog(message); } else { @@ -500,7 +446,7 @@ else if (this.simpleLog != null) */ void error(Throwable e) { - if (!configuration.disableLog) + if (!configuration.getDisableLog()) { if (this.log != null) { @@ -508,7 +454,7 @@ void error(Throwable e) } else if (this.simpleLog != null) { - this.simpleLog.pilog(e.getMessage()); + this.simpleLog.piLog(e.getMessage()); } else { @@ -524,7 +470,7 @@ else if (this.simpleLog != null) */ void log(String message) { - if (!configuration.disableLog) + if (!configuration.getDisableLog()) { if (this.log != null) { @@ -532,7 +478,7 @@ void log(String message) } else if (this.simpleLog != null) { - this.simpleLog.pilog(message); + this.simpleLog.piLog(message); } else { @@ -548,7 +494,7 @@ else if (this.simpleLog != null) */ void log(Throwable e) { - if (!configuration.disableLog) + if (!configuration.getDisableLog()) { if (this.log != null) { @@ -556,7 +502,7 @@ void log(Throwable e) } else if (this.simpleLog != null) { - this.simpleLog.pilog(e.getMessage()); + this.simpleLog.piLog(e.getMessage()); } else { @@ -588,7 +534,7 @@ public static class Builder private final String serverURL; private final String userAgent; private String realm = ""; - private boolean doSSLVerify = true; + private boolean verifySSL = true; private String serviceAccountName = ""; private String serviceAccountPass = ""; private String serviceAccountRealm = ""; @@ -649,12 +595,12 @@ public Builder realm(String realm) * Set whether to verify the peer when connecting. * It is not recommended to set this to false in productive environments. * - * @param sslVerify boolean + * @param verifySSL boolean * @return Builder */ - public Builder sslVerify(boolean sslVerify) + public Builder verifySSL(boolean verifySSL) { - this.doSSLVerify = sslVerify; + this.verifySSL = verifySSL; return this; } @@ -697,6 +643,7 @@ public Builder disableLog() /** * Set the timeout for http requests in milliseconds. + * * @param httpTimeoutMs timeout in milliseconds * @return Builder */ @@ -709,13 +656,13 @@ public Builder httpTimeoutMs(int httpTimeoutMs) public PrivacyIDEA build() { PIConfig configuration = new PIConfig(serverURL, userAgent); - configuration.realm = realm; - configuration.doSSLVerify = doSSLVerify; - configuration.serviceAccountName = serviceAccountName; - configuration.serviceAccountPass = serviceAccountPass; - configuration.serviceAccountRealm = serviceAccountRealm; - configuration.disableLog = disableLog; - configuration.httpTimeoutMs = httpTimeoutMs; + configuration.setRealm(realm); + configuration.setVerifySSL(verifySSL); + configuration.setServiceAccountName(serviceAccountName); + configuration.setServiceAccountPass(serviceAccountPass); + configuration.setServiceAccountRealm(serviceAccountRealm); + configuration.setDisableLog(disableLog); + configuration.setHttpTimeoutMs(httpTimeoutMs); return new PrivacyIDEA(configuration, logger, simpleLogBridge); } } From bd38a1ab88a50767debc7375dddcd410c44d80a8 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:55 +0100 Subject: [PATCH 11/35] Delete U2F.java --- src/main/java/org/privacyidea/U2F.java | 37 -------------------------- 1 file changed, 37 deletions(-) delete mode 100644 src/main/java/org/privacyidea/U2F.java diff --git a/src/main/java/org/privacyidea/U2F.java b/src/main/java/org/privacyidea/U2F.java deleted file mode 100644 index 22473a4..0000000 --- a/src/main/java/org/privacyidea/U2F.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2023 NetKnights GmbH - lukas.matusiewicz@netknights.it - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License here: - * License - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.privacyidea; - -public class U2F extends Challenge -{ - private final String signRequest; - - public U2F(String serial, String message, String client_mode, String image, String transaction_id, String signRequest) - { - super(serial, message, client_mode, image, transaction_id, PIConstants.TOKEN_TYPE_U2F); - this.signRequest = signRequest; - } - - /** - * Returns the U2FSignRequest in JSON format as a string, ready to use with pi-u2f.js. - * If this returns an empty string, it *might* indicate that the PIN of this token should be changed. - * - * @return sign request or empty string - */ - public String signRequest() - { - return signRequest; - } -} From c31228940eb84d81bc041918c00fa08381f374a6 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:40:59 +0100 Subject: [PATCH 12/35] Update WebAuthn.java --- src/main/java/org/privacyidea/WebAuthn.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/privacyidea/WebAuthn.java b/src/main/java/org/privacyidea/WebAuthn.java index c4e7ea1..8a8977a 100644 --- a/src/main/java/org/privacyidea/WebAuthn.java +++ b/src/main/java/org/privacyidea/WebAuthn.java @@ -20,14 +20,14 @@ public class WebAuthn extends Challenge { private final String signRequest; - public WebAuthn(String serial, String message, String client_mode, String image, String transaction_id, String signRequest) + public WebAuthn(String serial, String message, String clientMode, String image, String transactionID, String signRequest) { - super(serial, message, client_mode, image, transaction_id, PIConstants.TOKEN_TYPE_WEBAUTHN); + super(serial, message, clientMode, image, transactionID, PIConstants.TOKEN_TYPE_WEBAUTHN); this.signRequest = signRequest; } /** - * Returns the WebAuthnSignRequest in JSON format as a string, ready to use with pi-webauthn.js. + * Returns the WebAuthn sign request in JSON format as a string, ready to use with pi-webauthn.js. * If this returns an empty string, it *might* indicate that the PIN of this token should be changed. * * @return sign request or empty string From 5b82be8e97ad39b103eacefffbeb5d0ccd29e730 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:03 +0100 Subject: [PATCH 13/35] Update TestGetTokenInfo.java --- src/test/java/org/privacyidea/TestGetTokenInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/privacyidea/TestGetTokenInfo.java b/src/test/java/org/privacyidea/TestGetTokenInfo.java index fb002e5..5aa97ec 100644 --- a/src/test/java/org/privacyidea/TestGetTokenInfo.java +++ b/src/test/java/org/privacyidea/TestGetTokenInfo.java @@ -50,7 +50,7 @@ public void setup() .serviceRealm(serviceRealm) .disableLog() .httpTimeoutMs(15000) - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); } @@ -117,7 +117,7 @@ public void testForNoToken() @Test public void testNoServiceAccount() { - privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test").sslVerify(false).logger(new PILogImplementation()).build(); + privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test").verifySSL(false).logger(new PILogImplementation()).build(); List tokenInfoList = privacyIDEA.getTokenInfo(username); From 55dcc0d0995b181a10f535ec8dc0bae970b0758b Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:07 +0100 Subject: [PATCH 14/35] Update TestPollTransaction.java --- src/test/java/org/privacyidea/TestPollTransaction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/privacyidea/TestPollTransaction.java b/src/test/java/org/privacyidea/TestPollTransaction.java index 6e85eda..2a8fedb 100644 --- a/src/test/java/org/privacyidea/TestPollTransaction.java +++ b/src/test/java/org/privacyidea/TestPollTransaction.java @@ -44,7 +44,7 @@ public void setup() mockServer = ClientAndServer.startClientAndServer(1080); privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .simpleLogger(System.out::println) .build(); @@ -67,7 +67,7 @@ public void testPushSynchronous() throws InterruptedException PIResponse initialResponse = privacyIDEA.validateCheck(username, null); // Check the triggered challenges - the other things are already tested in org.privacyidea.TestOTP - List challenges = initialResponse.multichallenge; + List challenges = initialResponse.multiChallenge; Challenge hotpChallenge = challenges.stream() .filter(c -> c.getSerial().equals("OATH00020121")) From 4d36bbc7f9c6cbd30768884579d1cc8c8a1e6833 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:11 +0100 Subject: [PATCH 15/35] Update TestRollout.java --- src/test/java/org/privacyidea/TestRollout.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/privacyidea/TestRollout.java b/src/test/java/org/privacyidea/TestRollout.java index 38c6dbd..4dfe886 100644 --- a/src/test/java/org/privacyidea/TestRollout.java +++ b/src/test/java/org/privacyidea/TestRollout.java @@ -40,7 +40,7 @@ public void setup() mockServer = ClientAndServer.startClientAndServer(1080); privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .serviceAccount("admin", "admin") .logger(new PILogImplementation()) .build(); @@ -89,7 +89,7 @@ public void testSuccess() public void testNoServiceAccount() { privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); @@ -102,7 +102,7 @@ public void testNoServiceAccount() public void testRolloutViaValidateCheck() { privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); From 25540a25aee1bf483763555a54846b7390640551 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:14 +0100 Subject: [PATCH 16/35] Update TestTriggerChallenge.java --- .../java/org/privacyidea/TestTriggerChallenge.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/privacyidea/TestTriggerChallenge.java b/src/test/java/org/privacyidea/TestTriggerChallenge.java index 2b6eecb..77ef698 100644 --- a/src/test/java/org/privacyidea/TestTriggerChallenge.java +++ b/src/test/java/org/privacyidea/TestTriggerChallenge.java @@ -42,7 +42,7 @@ public void setup() mockServer = ClientAndServer.startClientAndServer(1080); privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .serviceAccount(serviceAccount, servicePass) .logger(new PILogImplementation()) .realm("realm") @@ -79,7 +79,7 @@ public void testTriggerChallengeSuccess() assertTrue(responseTriggerChallenge.status); assertFalse(responseTriggerChallenge.value); - List challenges = responseTriggerChallenge.multichallenge; + List challenges = responseTriggerChallenge.multiChallenge; String imageTOTP = ""; for (Challenge c : challenges) { @@ -98,7 +98,7 @@ public void testTriggerChallengeSuccess() public void testNoServiceAccount() { privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); @@ -111,7 +111,7 @@ public void testNoServiceAccount() public void testWrongServerURL() { privacyIDEA = PrivacyIDEA.newBuilder("https://12ds7:1nvcbn080", "test") - .sslVerify(false) + .verifySSL(false) .serviceAccount(serviceAccount, servicePass) .logger(new PILogImplementation()) .realm("realm") @@ -126,7 +126,7 @@ public void testWrongServerURL() public void testNoUsername() { privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .serviceAccount(serviceAccount, servicePass) .logger(new PILogImplementation()) .realm("realm") From 6b80c16063615831bafc018857025cc85193b946 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:17 +0100 Subject: [PATCH 17/35] Update TestU2F.java --- src/test/java/org/privacyidea/TestU2F.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/privacyidea/TestU2F.java b/src/test/java/org/privacyidea/TestU2F.java index b02d208..fae6f7c 100644 --- a/src/test/java/org/privacyidea/TestU2F.java +++ b/src/test/java/org/privacyidea/TestU2F.java @@ -41,7 +41,7 @@ public void setup() mockServer = ClientAndServer.startClientAndServer(1080); privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); } @@ -79,7 +79,7 @@ public void testTriggerU2F() assertTrue(response.status); assertFalse(response.value); - Optional opt = response.multichallenge.stream() + Optional opt = response.multiChallenge.stream() .filter(challenge -> TOKEN_TYPE_U2F.equals(challenge.getType())) .findFirst(); if (opt.isPresent()) From e2ed830927c38f4d1ee9470838c465fa8cf04b15 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:20 +0100 Subject: [PATCH 18/35] Update TestValidateCheck.java --- src/test/java/org/privacyidea/TestValidateCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/privacyidea/TestValidateCheck.java b/src/test/java/org/privacyidea/TestValidateCheck.java index bc58ea5..08ebb24 100644 --- a/src/test/java/org/privacyidea/TestValidateCheck.java +++ b/src/test/java/org/privacyidea/TestValidateCheck.java @@ -46,7 +46,7 @@ public void setup() mockServer = ClientAndServer.startClientAndServer(1080); privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); } From 698211531c64b74ab6c4b6f7ce446389d83f4c99 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:24 +0100 Subject: [PATCH 19/35] Update TestValidateCheckSerial.java --- src/test/java/org/privacyidea/TestValidateCheckSerial.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/privacyidea/TestValidateCheckSerial.java b/src/test/java/org/privacyidea/TestValidateCheckSerial.java index 930d6fd..f708abe 100644 --- a/src/test/java/org/privacyidea/TestValidateCheckSerial.java +++ b/src/test/java/org/privacyidea/TestValidateCheckSerial.java @@ -35,7 +35,7 @@ public void setup() mockServer = ClientAndServer.startClientAndServer(1080); privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .sslVerify(false) + .verifySSL(false) .logger(new PILogImplementation()) .build(); } From b45eb5fa52eba7a3fc7a804dae79982654a1d57d Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:41:31 +0100 Subject: [PATCH 20/35] Update TestWebAuthn.java --- src/test/java/org/privacyidea/TestWebAuthn.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/privacyidea/TestWebAuthn.java b/src/test/java/org/privacyidea/TestWebAuthn.java index 38db299..e0faa0c 100644 --- a/src/test/java/org/privacyidea/TestWebAuthn.java +++ b/src/test/java/org/privacyidea/TestWebAuthn.java @@ -40,7 +40,7 @@ public void setup() { mockServer = ClientAndServer.startClientAndServer(1080); - privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test").sslVerify(false).logger(new PILogImplementation()).build(); + privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test").verifySSL(false).logger(new PILogImplementation()).build(); } @After @@ -94,7 +94,7 @@ public void testTriggerWebAuthn() PIResponse response = privacyIDEA.validateCheck(username, pass); - Optional opt = response.multichallenge.stream().filter(challenge -> TOKEN_TYPE_WEBAUTHN.equals(challenge.getType())).findFirst(); + Optional opt = response.multiChallenge.stream().filter(challenge -> TOKEN_TYPE_WEBAUTHN.equals(challenge.getType())).findFirst(); assertTrue(opt.isPresent()); assertEquals(AuthenticationStatus.CHALLENGE, response.authentication); assertEquals("webauthn", response.preferredClientMode); From 6328451d5c59a331a7be9e6f7ee46e43fd0de43e Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 13 Nov 2024 14:46:01 +0100 Subject: [PATCH 21/35] rm u2f --- src/main/java/org/privacyidea/JSONParser.java | 27 --- .../java/org/privacyidea/PIConstants.java | 3 +- src/test/java/org/privacyidea/TestU2F.java | 168 ------------------ src/test/java/org/privacyidea/Utils.java | 27 --- 4 files changed, 1 insertion(+), 224 deletions(-) delete mode 100644 src/test/java/org/privacyidea/TestU2F.java diff --git a/src/main/java/org/privacyidea/JSONParser.java b/src/main/java/org/privacyidea/JSONParser.java index 2757141..09ee417 100644 --- a/src/main/java/org/privacyidea/JSONParser.java +++ b/src/main/java/org/privacyidea/JSONParser.java @@ -479,33 +479,6 @@ Map parseWebAuthnSignResponse(String json) return params; } - /** - * Parse the json string that is returned from the browser after signing the U2FSignRequest into a map. - * The map contains the parameters with the corresponding keys ready to be sent to the server. - * - * @param json json string from the browser - * @return map - */ - Map parseU2FSignResponse(String json) - { - Map params = new LinkedHashMap<>(); - JsonObject obj; - try - { - obj = JsonParser.parseString(json).getAsJsonObject(); - } - catch (JsonSyntaxException e) - { - privacyIDEA.error("U2F sign response has the wrong format: " + e.getLocalizedMessage()); - return null; - } - - params.put(CLIENTDATA, getString(obj, "clientData")); - params.put(SIGNATUREDATA, getString(obj, "signatureData")); - - return params; - } - private boolean getBoolean(JsonObject obj, String name) { JsonPrimitive primitive = getPrimitiveOrNull(obj, name); diff --git a/src/main/java/org/privacyidea/PIConstants.java b/src/main/java/org/privacyidea/PIConstants.java index e404d89..7774fc9 100644 --- a/src/main/java/org/privacyidea/PIConstants.java +++ b/src/main/java/org/privacyidea/PIConstants.java @@ -81,7 +81,7 @@ private PIConstants() public static final String MAXFAIL = "maxfail"; public static final String INFO = "info"; - // WebAuthn and U2F params + // WebAuthn params public static final String WEBAUTHN_SIGN_REQUEST = "webAuthnSignRequest"; public static final String CREDENTIALID = "credentialid"; public static final String CLIENTDATA = "clientdata"; @@ -89,7 +89,6 @@ private PIConstants() public static final String AUTHENTICATORDATA = "authenticatordata"; public static final String USERHANDLE = "userhandle"; public static final String ASSERTIONCLIENTEXTENSIONS = "assertionclientextensions"; - public static final String U2F_SIGN_REQUEST = "u2fSignRequest"; // These will be excluded from url encoding diff --git a/src/test/java/org/privacyidea/TestU2F.java b/src/test/java/org/privacyidea/TestU2F.java deleted file mode 100644 index fae6f7c..0000000 --- a/src/test/java/org/privacyidea/TestU2F.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2023 NetKnights GmbH - lukas.matusiewicz@netknights.it - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License here: - * License - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.privacyidea; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.model.HttpRequest; -import org.mockserver.model.HttpResponse; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.privacyidea.PIConstants.TOKEN_TYPE_U2F; - -public class TestU2F -{ - private ClientAndServer mockServer; - private PrivacyIDEA privacyIDEA; - - @Before - public void setup() - { - mockServer = ClientAndServer.startClientAndServer(1080); - - privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") - .verifySSL(false) - .logger(new PILogImplementation()) - .build(); - } - - @After - public void teardown() - { - mockServer.stop(); - } - - @Test - public void testTriggerU2F() - { - String u2fSignRequest = "{" + "\"appId\":\"https://ttype.u2f\"," + - "\"challenge\":\"TZKiB0VFFMFsnlz00lF5iCqtQduDJf56AeJAY_BT4NU\"," + - "\"keyHandle\":\"UUHmZ4BUFCrt7q88MhlQJYu4G5qB9l7ScjRRxA-M35cTH-uHWyMEpxs4WBzbkjlZqzZW1lC-jDdFd2pKDUsNnA\"," + - "\"version\":\"U2F_V2\"" + "}"; - - mockServer.when(HttpRequest.request() - .withPath(PIConstants.ENDPOINT_VALIDATE_CHECK) - .withMethod("POST") - .withBody("user=Test&pass=test")) - .respond(HttpResponse.response().withBody(Utils.triggerU2FSuccess())); - - PIResponse response = privacyIDEA.validateCheck("Test", "test"); - - assertEquals(1, response.id); - assertEquals("Please confirm with your U2F token (Yubico U2F EE Serial 61730834)", response.message); - assertEquals(0, response.otpLength); - assertEquals("U2F00014651", response.serial); - assertEquals("u2f", response.type); - assertEquals("2.0", response.jsonRPCVersion); - assertEquals("3.6.3", response.piVersion); - assertEquals("rsa_sha256_pss:3e51d814...dccd5694b8c15943e37e1", response.signature); - assertTrue(response.status); - assertFalse(response.value); - - Optional opt = response.multiChallenge.stream() - .filter(challenge -> TOKEN_TYPE_U2F.equals(challenge.getType())) - .findFirst(); - if (opt.isPresent()) - { - Challenge a = opt.get(); - if (a instanceof U2F) - { - U2F b = (U2F) a; - String trimmedRequest = u2fSignRequest.replaceAll("\n", "").replaceAll(" ", ""); - assertEquals(trimmedRequest, b.signRequest()); - } - else - { - fail(); - } - } - else - { - fail(); - } - } - - @Test - public void testSuccess() - { - String username = "Test"; - - String u2fSignResponse = "{\"clientData\":\"eyJjaGFsbGVuZ2UiOiJpY2UBc3NlcnRpb24ifQ\"," + "\"errorCode\":0," + - "\"keyHandle\":\"UUHmZ4BUFCrt7q88MhlQkjlZqzZW1lC-jDdFd2pKDUsNnA\"," + - "\"signatureData\":\"AQAAAxAwRQIgZwEObruoCRRo738F9up1tdV2M0H1MdP5pkO5Eg\"}"; - - mockServer.when(HttpRequest.request() - .withPath(PIConstants.ENDPOINT_VALIDATE_CHECK) - .withMethod("POST") - .withBody("user=Test&transaction_id=16786665691788289392&pass=" + - "&clientdata=eyJjaGFsbGVuZ2UiOiJpY2UBc3NlcnRpb24ifQ" + - "&signaturedata=AQAAAxAwRQIgZwEObruoCRRo738F9up1tdV2M0H1MdP5pkO5Eg")) - .respond(HttpResponse.response().withBody(Utils.matchingOneToken())); - - Map header = new HashMap<>(); - header.put("accept-language", "en"); - PIResponse response = privacyIDEA.validateCheckU2F(username, "16786665691788289392", u2fSignResponse, header); - - assertEquals(1, response.id); - assertEquals("matching 1 tokens", response.message); - assertEquals(6, response.otpLength); - assertEquals("PISP0001C673", response.serial); - assertEquals("totp", response.type); - assertEquals("2.0", response.jsonRPCVersion); - assertEquals("3.2.1", response.piVersion); - assertEquals("rsa_sha256_pss:AAAAAAAAAAA", response.signature); - assertTrue(response.status); - assertTrue(response.value); - } - - @Test - public void testSuccessWithoutHeader() - { - String username = "Test"; - - mockServer.when(HttpRequest.request() - .withPath(PIConstants.ENDPOINT_VALIDATE_CHECK) - .withMethod("POST") - .withBody("user=Test&transaction_id=16786665691788289392&pass=" + - "&clientdata=eyJjaGFsbGVuZ2UiOiJpY2UBc3NlcnRpb24ifQ" + - "&signaturedata=AQAAAxAwRQIgZwEObruoCRRo738F9up1tdV2M0H1MdP5pkO5Eg")) - .respond(HttpResponse.response().withBody(Utils.matchingOneToken())); - - String u2fSignResponse = "{\"clientData\":\"eyJjaGFsbGVuZ2UiOiJpY2UBc3NlcnRpb24ifQ\"," + "\"errorCode\":0," + - "\"keyHandle\":\"UUHmZ4BUFCrt7q88MhlQkjlZqzZW1lC-jDdFd2pKDUsNnA\"," + - "\"signatureData\":\"AQAAAxAwRQIgZwEObruoCRRo738F9up1tdV2M0H1MdP5pkO5Eg\"}"; - - PIResponse response = privacyIDEA.validateCheckU2F(username, "16786665691788289392", u2fSignResponse); - - assertEquals(1, response.id); - assertEquals("matching 1 tokens", response.message); - assertEquals(6, response.otpLength); - assertEquals("PISP0001C673", response.serial); - assertEquals("totp", response.type); - assertEquals("2.0", response.jsonRPCVersion); - assertEquals("3.2.1", response.piVersion); - assertEquals("rsa_sha256_pss:AAAAAAAAAAA", response.signature); - assertTrue(response.status); - assertTrue(response.value); - } -} \ No newline at end of file diff --git a/src/test/java/org/privacyidea/Utils.java b/src/test/java/org/privacyidea/Utils.java index 5d850c9..559c24f 100644 --- a/src/test/java/org/privacyidea/Utils.java +++ b/src/test/java/org/privacyidea/Utils.java @@ -180,33 +180,6 @@ public static String triggerChallengeSuccess() "\"signature\":\"rsa_sha256_pss:4b0f0e12c2...89409a2e65c87d27b\"}"; } - public static String triggerU2FSuccess() - { - return "{" + "\"detail\":{" + "\"attributes\":{" + "\"hideResponseInput\":true," + - "\"img\":\"static/img/FIDO-U2F-Security-Key-444x444.png\"," + "\"u2fSignRequest\":{" + - "\"appId\":\"http//ttype.u2f\"," + - "\"challenge\":\"TZKiB0VFFMF...tQduDJf56AeJAY_BT4NU\"," + - "\"keyHandle\":\"UUHmZ4BUFCrt7q88MhlQ...qzZW1lC-jDdFd2pKDUsNnA\"," + - "\"version\":\"U2F_V2\"}}," + - "\"message\":\"Please confirm with your U2F token (Yubico U2F EE Serial 61730834)\"," + - "\"messages\":[\"Please confirm with your U2F token (Yubico U2F EE Serial 61730834)\"]," + - "\"multi_challenge\":[{" + "\"attributes\":{" + "\"hideResponseInput\":true," + - "\"img\":\"static/img/FIDO-U2F-Security-Key-444x444.png\"," + "\"u2fSignRequest\":{" + - "\"appId\":\"https://ttype.u2f\"," + - "\"challenge\":\"TZKiB0VFFMFsnlz00lF5iCqtQduDJf56AeJAY_BT4NU\"," + - "\"keyHandle\":\"UUHmZ4BUFCrt7q88MhlQJYu4G5qB9l7ScjRRxA-M35cTH-uHWyMEpxs4WBzbkjlZqzZW1lC-jDdFd2pKDUsNnA\"," + - "\"version\":\"U2F_V2\"}}," + - "\"message\":\"Please confirm with your U2F token (Yubico U2F EE Serial 61730834)\"," + - "\"serial\":\"U2F00014651\"," + "\"transaction_id\":\"12399202888279169736\"," + - "\"type\":\"u2f\"}]," + "\"serial\":\"U2F00014651\"," + "\"threadid\":140050978137856," + - "\"transaction_id\":\"12399202888279169736\"," + - "\"transaction_ids\":[\"12399202888279169736\"]," + "\"type\":\"u2f\"}," + "\"id\":1," + - "\"jsonrpc\":\"2.0\"," + "\"result\":{" + "\"status\":true," + "\"value\":false}," + - "\"time\":1649769348.7552881," + "\"version\":\"privacyIDEA 3.6.3\"," + - "\"versionnumber\":\"3.6.3\"," + - "\"signature\":\"rsa_sha256_pss:3e51d814...dccd5694b8c15943e37e1\"}"; - } - public static String lostValues() { return "{\n" + " \"detail\": {\n" + " \"threadid\": 140536383567616,\n" + " \"result\": {\n" + From d6deb0c3c3676f432de867884090331d1dae3e0e Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 11:16:20 +0100 Subject: [PATCH 22/35] Update Endpoint.java add get client ip --- src/main/java/org/privacyidea/Endpoint.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/privacyidea/Endpoint.java b/src/main/java/org/privacyidea/Endpoint.java index 0ae7cb3..68b9cd9 100644 --- a/src/main/java/org/privacyidea/Endpoint.java +++ b/src/main/java/org/privacyidea/Endpoint.java @@ -110,6 +110,11 @@ void sendRequestAsync(String endpoint, Map params, Map { From 143642be4d3d70cb6b4b6473425105ba4b3318b4 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 11:16:33 +0100 Subject: [PATCH 23/35] Update PIConfig.java add get client ip --- src/main/java/org/privacyidea/PIConfig.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/privacyidea/PIConfig.java b/src/main/java/org/privacyidea/PIConfig.java index c3fec5e..6bbad7a 100644 --- a/src/main/java/org/privacyidea/PIConfig.java +++ b/src/main/java/org/privacyidea/PIConfig.java @@ -26,7 +26,7 @@ class PIConfig private String serviceAccountPass = ""; private String serviceAccountRealm = ""; private boolean disableLog = false; - private final boolean forwardClientIP = false; + private String forwardClientIP = ""; private int httpTimeoutMs = 30000; public PIConfig(String serverURL, String userAgent) @@ -62,6 +62,11 @@ public void setServiceAccountRealm(String serviceAccountRealm) this.serviceAccountRealm = serviceAccountRealm; } + public void setForwardClientIP(String forwardClientIP) + { + this.forwardClientIP = forwardClientIP; + } + public void setDisableLog(boolean disableLog) { this.disableLog = disableLog; @@ -114,7 +119,7 @@ public boolean getDisableLog() return disableLog; } - public boolean getForwardClientIP() + public String getForwardClientIP() { return forwardClientIP; } From 8637e774268af0f400271f2dde80da32cb762969 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 11:16:52 +0100 Subject: [PATCH 24/35] Update PIConstants.java add client, rm u2f --- src/main/java/org/privacyidea/PIConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/privacyidea/PIConstants.java b/src/main/java/org/privacyidea/PIConstants.java index 7774fc9..944ab92 100644 --- a/src/main/java/org/privacyidea/PIConstants.java +++ b/src/main/java/org/privacyidea/PIConstants.java @@ -43,7 +43,6 @@ private PIConstants() // TOKEN TYPES public static final String TOKEN_TYPE_PUSH = "push"; public static final String TOKEN_TYPE_WEBAUTHN = "webauthn"; - public static final String TOKEN_TYPE_U2F = "u2f"; // JSON KEYS public static final String USERNAME = "username"; @@ -65,6 +64,7 @@ private PIConstants() public static final String MESSAGE = "message"; public static final String CLIENT_MODE = "client_mode"; public static final String IMAGE = "image"; + public static final String CLIENT_IP = "client"; public static final String MESSAGES = "messages"; public static final String MULTI_CHALLENGE = "multi_challenge"; public static final String ATTRIBUTES = "attributes"; From 050e82ed7aa230347934ced1ae6749a0aa88d1ff Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 11:17:14 +0100 Subject: [PATCH 25/35] Update PIResponse.java --- src/main/java/org/privacyidea/PIResponse.java | 94 ++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/privacyidea/PIResponse.java b/src/main/java/org/privacyidea/PIResponse.java index a7a9485..33c70b8 100644 --- a/src/main/java/org/privacyidea/PIResponse.java +++ b/src/main/java/org/privacyidea/PIResponse.java @@ -49,8 +49,6 @@ public class PIResponse int otpLength = 0; PIError error = null; - - /** * Check if a PUSH token was triggered. * @@ -165,4 +163,96 @@ public String toString() { return rawMessage; } + + // GETTERS + + public String getMessage() + { + return message; + } + + public String getPreferredClientMode() + { + return preferredClientMode; + } + + public List getMessages() + { + return messages; + } + + public List getMultiChallenge() + { + return multiChallenge; + } + + public String getTransactionID() + { + return transactionID; + } + + public String getSerial() + { + return serial; + } + + public String getImage() + { + return image; + } + + public int getId() + { + return id; + } + + public String getJsonRPCVersion() + { + return jsonRPCVersion; + } + + public boolean getStatus() + { + return status; + } + + public boolean getValue() + { + return value; + } + + public AuthenticationStatus getAuthentication() + { + return authentication; + } + + public String getPiVersion() + { + return piVersion; + } + + public String getRawMessage() + { + return rawMessage; + } + + public String getSignature() + { + return signature; + } + + public String getType() + { + return type; + } + + public int getOtpLength() + { + return otpLength; + } + + public PIError getError() + { + return error; + } } From 63acc43e688e448debe4be4b795b4e1f0a29e5ee Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 11:17:44 +0100 Subject: [PATCH 26/35] Update PrivacyIDEA.java add forward client ip --- src/main/java/org/privacyidea/PrivacyIDEA.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/org/privacyidea/PrivacyIDEA.java b/src/main/java/org/privacyidea/PrivacyIDEA.java index b46e583..5664371 100644 --- a/src/main/java/org/privacyidea/PrivacyIDEA.java +++ b/src/main/java/org/privacyidea/PrivacyIDEA.java @@ -370,6 +370,10 @@ private void appendRealm(Map params) private String runRequestAsync(String path, Map params, Map headers, boolean authTokenRequired, String method) { + if (!configuration().getForwardClientIP().isEmpty()) + { + params.put(CLIENT_IP,configuration().getForwardClientIP()); + } Callable callable = new AsyncRequestCallable(this, endpoint, path, params, headers, authTokenRequired, method); Future future = threadPool.submit(callable); String response = null; @@ -538,6 +542,7 @@ public static class Builder private String serviceAccountName = ""; private String serviceAccountPass = ""; private String serviceAccountRealm = ""; + private String forwardClientIP = ""; private IPILogger logger = null; private boolean disableLog = false; private IPISimpleLogger simpleLogBridge = null; @@ -630,6 +635,18 @@ public Builder serviceRealm(String serviceAccountRealm) return this; } + /** + * Set the client IP to be forwarded to the privacyIDEA server. + * + * @param clientIP client IP or an empty String + * @return Builder + */ + public Builder forwardClientIP(String clientIP) + { + this.forwardClientIP = clientIP; + return this; + } + /** * Disable logging completely regardless of any set loggers. * @@ -661,6 +678,7 @@ public PrivacyIDEA build() configuration.setServiceAccountName(serviceAccountName); configuration.setServiceAccountPass(serviceAccountPass); configuration.setServiceAccountRealm(serviceAccountRealm); + configuration.setForwardClientIP(forwardClientIP); configuration.setDisableLog(disableLog); configuration.setHttpTimeoutMs(httpTimeoutMs); return new PrivacyIDEA(configuration, logger, simpleLogBridge); From 93da9d7764ef77c527047e75ac9c8491970c408b Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 14:44:57 +0100 Subject: [PATCH 27/35] Update PrivacyIDEA.java --- src/main/java/org/privacyidea/PrivacyIDEA.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/privacyidea/PrivacyIDEA.java b/src/main/java/org/privacyidea/PrivacyIDEA.java index 5664371..1149266 100644 --- a/src/main/java/org/privacyidea/PrivacyIDEA.java +++ b/src/main/java/org/privacyidea/PrivacyIDEA.java @@ -370,9 +370,9 @@ private void appendRealm(Map params) private String runRequestAsync(String path, Map params, Map headers, boolean authTokenRequired, String method) { - if (!configuration().getForwardClientIP().isEmpty()) + if (!configuration.getForwardClientIP().isEmpty()) { - params.put(CLIENT_IP,configuration().getForwardClientIP()); + params.put(CLIENT_IP,configuration.getForwardClientIP()); } Callable callable = new AsyncRequestCallable(this, endpoint, path, params, headers, authTokenRequired, method); Future future = threadPool.submit(callable); From ebf2d6a1642b95c7f8d89e21f167574662d1c6a8 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Mon, 18 Nov 2024 14:45:29 +0100 Subject: [PATCH 28/35] Update pom.xml --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index a80f601..182f84a 100644 --- a/pom.xml +++ b/pom.xml @@ -50,8 +50,8 @@ maven-compiler-plugin 3.8.1 - 1.8 - 1.8 + 11 + 11 @@ -86,7 +86,7 @@ com.squareup.okhttp3 okhttp - 4.10.0 + 4.12.0 org.jetbrains.kotlin From c6e6c1e2c41946ee049b05068566c5f5275e43d4 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Tue, 19 Nov 2024 12:23:52 +0100 Subject: [PATCH 29/35] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b11b54..00d46f0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: echo "branches = ${{ steps.jacoco.outputs.branches }}" - name: Upload JaCoCo coverage report as a workflow artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: jacoco-report path: target/site/jacoco/ From a86029a585e053f70fb1ce3764ba53ceeaac3c80 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Tue, 19 Nov 2024 13:22:03 +0100 Subject: [PATCH 30/35] Update TestTriggerChallenge.java test the new function --- src/test/java/org/privacyidea/TestTriggerChallenge.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/privacyidea/TestTriggerChallenge.java b/src/test/java/org/privacyidea/TestTriggerChallenge.java index 77ef698..eb521bf 100644 --- a/src/test/java/org/privacyidea/TestTriggerChallenge.java +++ b/src/test/java/org/privacyidea/TestTriggerChallenge.java @@ -35,6 +35,7 @@ public class TestTriggerChallenge private PrivacyIDEA privacyIDEA; String serviceAccount = "service"; String servicePass = "pass"; + String forwardClientIP = "127.0.0.1"; @Before public void setup() @@ -44,6 +45,7 @@ public void setup() privacyIDEA = PrivacyIDEA.newBuilder("https://127.0.0.1:1080", "test") .verifySSL(false) .serviceAccount(serviceAccount, servicePass) + .forwardClientIP(forwardClientIP) .logger(new PILogImplementation()) .realm("realm") .build(); @@ -60,7 +62,7 @@ public void testTriggerChallengeSuccess() mockServer.when(HttpRequest.request() .withPath(PIConstants.ENDPOINT_TRIGGERCHALLENGE) .withMethod("POST") - .withBody("user=testuser&realm=realm")) + .withBody("user=testuser&realm=realm&client=127.0.0.1")) .respond(HttpResponse.response().withBody(Utils.triggerChallengeSuccess())); String username = "testuser"; From c35cff75c7dfb269db3e2878abf3da38fdf2cd12 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 20 Nov 2024 10:16:26 +0100 Subject: [PATCH 31/35] Update PIConfig.java --- src/main/java/org/privacyidea/PIConfig.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/org/privacyidea/PIConfig.java b/src/main/java/org/privacyidea/PIConfig.java index 6bbad7a..179c0a9 100644 --- a/src/main/java/org/privacyidea/PIConfig.java +++ b/src/main/java/org/privacyidea/PIConfig.java @@ -28,6 +28,8 @@ class PIConfig private boolean disableLog = false; private String forwardClientIP = ""; private int httpTimeoutMs = 30000; + private String proxyHost = ""; + private int proxyPort = 0; public PIConfig(String serverURL, String userAgent) { @@ -77,6 +79,12 @@ public void setHttpTimeoutMs(int httpTimeoutMs) this.httpTimeoutMs = httpTimeoutMs; } + public void setProxy(String proxyHost, int proxyPort) + { + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + } + // GETTERS public String getServerURL() @@ -128,4 +136,14 @@ public int getHttpTimeoutMs() { return httpTimeoutMs; } + + public String getProxyHost() + { + return proxyHost; + } + + public int getProxyPort() + { + return proxyPort; + } } \ No newline at end of file From f676429340d89b0fee886368b925123f1e693d7f Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 20 Nov 2024 10:17:37 +0100 Subject: [PATCH 32/35] Update PrivacyIDEA.java --- .../java/org/privacyidea/PrivacyIDEA.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/org/privacyidea/PrivacyIDEA.java b/src/main/java/org/privacyidea/PrivacyIDEA.java index 1149266..3c58284 100644 --- a/src/main/java/org/privacyidea/PrivacyIDEA.java +++ b/src/main/java/org/privacyidea/PrivacyIDEA.java @@ -547,6 +547,8 @@ public static class Builder private boolean disableLog = false; private IPISimpleLogger simpleLogBridge = null; private int httpTimeoutMs = 30000; + private String proxyHost = ""; + private int proxyPort = 0; /** * @param serverURL the server URL is mandatory to communicate with privacyIDEA. @@ -670,6 +672,25 @@ public Builder httpTimeoutMs(int httpTimeoutMs) return this; } + /** + * Set the proxy for the http requests. + * + * @param proxyHost proxy host + * @param proxyPort proxy port + * @return Builder + */ + public Builder proxy(String proxyHost, int proxyPort) + { + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + return this; + } + + /** + * Build the PrivacyIDEA instance with the set parameters. + * + * @return PrivacyIDEA instance + */ public PrivacyIDEA build() { PIConfig configuration = new PIConfig(serverURL, userAgent); @@ -681,6 +702,7 @@ public PrivacyIDEA build() configuration.setForwardClientIP(forwardClientIP); configuration.setDisableLog(disableLog); configuration.setHttpTimeoutMs(httpTimeoutMs); + configuration.setProxy(proxyHost, proxyPort); return new PrivacyIDEA(configuration, logger, simpleLogBridge); } } From 4879f56f513da813da70db32b8b6b38ed7c36c8e Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Wed, 20 Nov 2024 10:49:03 +0100 Subject: [PATCH 33/35] Update Endpoint.java --- src/main/java/org/privacyidea/Endpoint.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/privacyidea/Endpoint.java b/src/main/java/org/privacyidea/Endpoint.java index 68b9cd9..1c35ebd 100644 --- a/src/main/java/org/privacyidea/Endpoint.java +++ b/src/main/java/org/privacyidea/Endpoint.java @@ -23,6 +23,8 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.KeyManagementException; @@ -60,6 +62,11 @@ public java.security.cert.X509Certificate[] getAcceptedIssuers() } }}; + /** + * Constructor + * + * @param privacyIDEA privacyIDEA instance + */ Endpoint(PrivacyIDEA privacyIDEA) { this.privacyIDEA = privacyIDEA; @@ -86,6 +93,13 @@ public java.security.cert.X509Certificate[] getAcceptedIssuers() privacyIDEA.error(e); } } + + if (!piConfig.getProxyHost().isEmpty()) + { + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(piConfig.getProxyHost(), piConfig.getProxyPort())); + builder.proxy(proxy); + } + this.client = builder.build(); } @@ -98,8 +112,7 @@ public java.security.cert.X509Certificate[] getAcceptedIssuers() * @param method http request method * @param callback okhttp3 callback */ - void sendRequestAsync(String endpoint, Map params, Map headers, String method, - Callback callback) + void sendRequestAsync(String endpoint, Map params, Map headers, String method, Callback callback) { HttpUrl httpUrl = HttpUrl.parse(piConfig.getServerURL() + endpoint); if (httpUrl == null) @@ -122,7 +135,6 @@ void sendRequestAsync(String endpoint, Map params, Map @@ -147,7 +147,7 @@ void sendRequestAsync(String endpoint, Map params, Map messages = new ArrayList<>(); - List multiChallenge = new ArrayList<>(); - String transactionID = ""; - String serial = ""; - String image = ""; - int id = 0; - String jsonRPCVersion = ""; - boolean status = false; - boolean value = false; - AuthenticationStatus authentication = AuthenticationStatus.NONE; - String piVersion = ""; // e.g. 3.2.1 - String rawMessage = ""; - String signature = ""; - String type = ""; // Type of token that was matching the request - int otpLength = 0; - PIError error = null; + public String message = ""; + public String preferredClientMode = ""; + public List messages = new ArrayList<>(); + public List multiChallenge = new ArrayList<>(); + public String transactionID = ""; + public String serial = ""; + public String image = ""; + public int id = 0; + public String jsonRPCVersion = ""; + public boolean status = false; + public boolean value = false; + public AuthenticationStatus authentication = AuthenticationStatus.NONE; + public String piVersion = ""; // e.g. 3.2.1 + public String rawMessage = ""; + public String signature = ""; + public String type = ""; // Type of token that was matching the request + public int otpLength = 0; + public PIError error = null; /** * Check if a PUSH token was triggered. @@ -163,96 +163,4 @@ public String toString() { return rawMessage; } - - // GETTERS - - public String getMessage() - { - return message; - } - - public String getPreferredClientMode() - { - return preferredClientMode; - } - - public List getMessages() - { - return messages; - } - - public List getMultiChallenge() - { - return multiChallenge; - } - - public String getTransactionID() - { - return transactionID; - } - - public String getSerial() - { - return serial; - } - - public String getImage() - { - return image; - } - - public int getId() - { - return id; - } - - public String getJsonRPCVersion() - { - return jsonRPCVersion; - } - - public boolean getStatus() - { - return status; - } - - public boolean getValue() - { - return value; - } - - public AuthenticationStatus getAuthentication() - { - return authentication; - } - - public String getPiVersion() - { - return piVersion; - } - - public String getRawMessage() - { - return rawMessage; - } - - public String getSignature() - { - return signature; - } - - public String getType() - { - return type; - } - - public int getOtpLength() - { - return otpLength; - } - - public PIError getError() - { - return error; - } } diff --git a/src/main/java/org/privacyidea/PrivacyIDEA.java b/src/main/java/org/privacyidea/PrivacyIDEA.java index 3c58284..85ec839 100644 --- a/src/main/java/org/privacyidea/PrivacyIDEA.java +++ b/src/main/java/org/privacyidea/PrivacyIDEA.java @@ -262,16 +262,16 @@ public String getAuthToken() Map serviceAccountParam() { Map authTokenParams = new LinkedHashMap<>(); - authTokenParams.put(USERNAME, configuration.getServiceAccountName()); - authTokenParams.put(PASSWORD, configuration.getServiceAccountPass()); + authTokenParams.put(USERNAME, configuration.serviceAccountName); + authTokenParams.put(PASSWORD, configuration.serviceAccountPass); - if (configuration.getServiceAccountRealm() != null && !configuration.getServiceAccountRealm().isEmpty()) + if (configuration.serviceAccountRealm != null && !configuration.serviceAccountRealm.isEmpty()) { - authTokenParams.put(REALM, configuration.getServiceAccountRealm()); + authTokenParams.put(REALM, configuration.serviceAccountRealm); } - else if (configuration.getRealm() != null && !configuration.getRealm().isEmpty()) + else if (configuration.realm != null && !configuration.realm.isEmpty()) { - authTokenParams.put(REALM, configuration.getRealm()); + authTokenParams.put(REALM, configuration.realm); } return authTokenParams; } @@ -350,9 +350,9 @@ public RolloutInfo tokenInit(String username, String typeToEnroll, String otpKey private void appendRealm(Map params) { - if (configuration.getRealm() != null && !configuration.getRealm().isEmpty()) + if (configuration.realm != null && !configuration.realm.isEmpty()) { - params.put(REALM, configuration.getRealm()); + params.put(REALM, configuration.realm); } } @@ -370,9 +370,9 @@ private void appendRealm(Map params) private String runRequestAsync(String path, Map params, Map headers, boolean authTokenRequired, String method) { - if (!configuration.getForwardClientIP().isEmpty()) + if (!configuration.forwardClientIP.isEmpty()) { - params.put(CLIENT_IP,configuration.getForwardClientIP()); + params.put(CLIENT_IP,configuration.forwardClientIP); } Callable callable = new AsyncRequestCallable(this, endpoint, path, params, headers, authTokenRequired, method); Future future = threadPool.submit(callable); @@ -409,9 +409,9 @@ public void logExcludedEndpoints(List list) */ public boolean serviceAccountAvailable() { - return configuration.getServiceAccountName() != null && !configuration.getServiceAccountName().isEmpty() - && configuration.getServiceAccountPass() != null && - !configuration.getServiceAccountPass().isEmpty(); + return configuration.serviceAccountName != null && !configuration.serviceAccountName.isEmpty() + && configuration.serviceAccountPass != null && + !configuration.serviceAccountPass.isEmpty(); } PIConfig configuration() @@ -426,7 +426,7 @@ PIConfig configuration() */ void error(String message) { - if (!configuration.getDisableLog()) + if (!configuration.disableLog) { if (this.log != null) { @@ -450,7 +450,7 @@ else if (this.simpleLog != null) */ void error(Throwable e) { - if (!configuration.getDisableLog()) + if (!configuration.disableLog) { if (this.log != null) { @@ -474,7 +474,7 @@ else if (this.simpleLog != null) */ void log(String message) { - if (!configuration.getDisableLog()) + if (!configuration.disableLog) { if (this.log != null) { @@ -498,7 +498,7 @@ else if (this.simpleLog != null) */ void log(Throwable e) { - if (!configuration.getDisableLog()) + if (!configuration.disableLog) { if (this.log != null) { @@ -694,14 +694,14 @@ public Builder proxy(String proxyHost, int proxyPort) public PrivacyIDEA build() { PIConfig configuration = new PIConfig(serverURL, userAgent); - configuration.setRealm(realm); - configuration.setVerifySSL(verifySSL); - configuration.setServiceAccountName(serviceAccountName); - configuration.setServiceAccountPass(serviceAccountPass); - configuration.setServiceAccountRealm(serviceAccountRealm); - configuration.setForwardClientIP(forwardClientIP); - configuration.setDisableLog(disableLog); - configuration.setHttpTimeoutMs(httpTimeoutMs); + configuration.realm = realm; + configuration.verifySSL = verifySSL; + configuration.serviceAccountName = serviceAccountName; + configuration.serviceAccountPass = serviceAccountPass; + configuration.serviceAccountRealm = serviceAccountRealm; + configuration.forwardClientIP = forwardClientIP; + configuration.disableLog = disableLog; + configuration.httpTimeoutMs = httpTimeoutMs; configuration.setProxy(proxyHost, proxyPort); return new PrivacyIDEA(configuration, logger, simpleLogBridge); }