aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/api')
-rw-r--r--src/main/java/org/traccar/api/resource/PasswordResource.java8
-rw-r--r--src/main/java/org/traccar/api/resource/ReportResource.java2
-rw-r--r--src/main/java/org/traccar/api/resource/ServerResource.java2
-rw-r--r--src/main/java/org/traccar/api/security/LoginService.java7
-rw-r--r--src/main/java/org/traccar/api/signature/CryptoManager.java98
-rw-r--r--src/main/java/org/traccar/api/signature/KeystoreModel.java44
6 files changed, 150 insertions, 11 deletions
diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java
index 643471797..91c2d8ecf 100644
--- a/src/main/java/org/traccar/api/resource/PasswordResource.java
+++ b/src/main/java/org/traccar/api/resource/PasswordResource.java
@@ -16,7 +16,7 @@
package org.traccar.api.resource;
import org.traccar.api.BaseResource;
-import org.traccar.database.MailManager;
+import org.traccar.mail.MailManager;
import org.traccar.model.User;
import org.traccar.notification.TextTemplateFormatter;
import org.traccar.storage.StorageException;
@@ -58,7 +58,8 @@ public class PasswordResource extends BaseResource {
if (user != null) {
String token = UUID.randomUUID().toString().replaceAll("-", "");
user.set(PASSWORD_RESET_TOKEN, token);
- storage.updateObject(user, new Request(new Columns.Exclude("id"), new Condition.Equals("id", "id")));
+ storage.updateObject(user, new Request(
+ new Columns.Include("attributes"), new Condition.Equals("id", "id")));
var velocityContext = textTemplateFormatter.prepareContext(permissionsService.getServer(), user);
velocityContext.put("token", token);
@@ -79,7 +80,8 @@ public class PasswordResource extends BaseResource {
if (user != null) {
user.getAttributes().remove(PASSWORD_RESET_TOKEN);
user.setPassword(password);
- storage.updateObject(user, new Request(new Columns.Exclude("id"), new Condition.Equals("id", "id")));
+ storage.updateObject(user, new Request(
+ new Columns.Include("attributes", "hashedPassword", "salt"), new Condition.Equals("id", "id")));
return Response.ok().build();
}
return Response.status(Response.Status.NOT_FOUND).build();
diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java
index 6176013c1..70177dd4d 100644
--- a/src/main/java/org/traccar/api/resource/ReportResource.java
+++ b/src/main/java/org/traccar/api/resource/ReportResource.java
@@ -19,7 +19,7 @@ package org.traccar.api.resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.api.BaseResource;
-import org.traccar.database.MailManager;
+import org.traccar.mail.MailManager;
import org.traccar.helper.LogAction;
import org.traccar.model.Event;
import org.traccar.model.Position;
diff --git a/src/main/java/org/traccar/api/resource/ServerResource.java b/src/main/java/org/traccar/api/resource/ServerResource.java
index 4fc76a0d7..e35cd7d95 100644
--- a/src/main/java/org/traccar/api/resource/ServerResource.java
+++ b/src/main/java/org/traccar/api/resource/ServerResource.java
@@ -16,7 +16,7 @@
package org.traccar.api.resource;
import org.traccar.api.BaseResource;
-import org.traccar.database.MailManager;
+import org.traccar.mail.MailManager;
import org.traccar.geocoder.Geocoder;
import org.traccar.helper.Log;
import org.traccar.helper.LogAction;
diff --git a/src/main/java/org/traccar/api/security/LoginService.java b/src/main/java/org/traccar/api/security/LoginService.java
index 9938cf6dc..104a6fac3 100644
--- a/src/main/java/org/traccar/api/security/LoginService.java
+++ b/src/main/java/org/traccar/api/security/LoginService.java
@@ -83,12 +83,7 @@ public class LoginService {
if (user == null) {
throw new SecurityException("Unknown account");
}
- if (user.getDisabled()) {
- throw new SecurityException("Account is disabled");
- }
- if (user.getExpirationTime() != null && System.currentTimeMillis() > user.getExpirationTime().getTime()) {
- throw new SecurityException("Account has expired");
- }
+ user.checkDisabled();
}
}
diff --git a/src/main/java/org/traccar/api/signature/CryptoManager.java b/src/main/java/org/traccar/api/signature/CryptoManager.java
new file mode 100644
index 000000000..ea59dcd70
--- /dev/null
+++ b/src/main/java/org/traccar/api/signature/CryptoManager.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2022 Anton Tananaev (anton@traccar.org)
+ *
+ * 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 at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.traccar.api.signature;
+
+import org.traccar.helper.DataConverter;
+import org.traccar.storage.Storage;
+import org.traccar.storage.StorageException;
+import org.traccar.storage.query.Columns;
+import org.traccar.storage.query.Request;
+
+import javax.inject.Inject;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public class CryptoManager {
+
+ private final Storage storage;
+
+ private PublicKey publicKey;
+ private PrivateKey privateKey;
+
+ @Inject
+ public CryptoManager(Storage storage) {
+ this.storage = storage;
+ }
+
+ public String sign(String data) throws GeneralSecurityException, StorageException {
+ if (privateKey == null) {
+ initializeKeys();
+ }
+ Signature signature = Signature.getInstance("SHA256withECDSA");
+ signature.initSign(privateKey);
+ signature.update(data.getBytes());
+ return data + '.' + DataConverter.printBase64(signature.sign());
+ }
+
+ public String verify(String data) throws GeneralSecurityException, StorageException {
+ if (publicKey == null) {
+ initializeKeys();
+ }
+ Signature signature = Signature.getInstance("SHA256withECDSA");
+ signature.initVerify(publicKey);
+
+ int delimiter = data.lastIndexOf('.');
+ String originalData = data.substring(0, delimiter);
+
+ signature.update(originalData.getBytes());
+ if (!signature.verify(DataConverter.parseBase64(data.substring(delimiter + 1)))) {
+ throw new SecurityException("Invalid signature");
+ }
+ return originalData;
+ }
+
+ private void initializeKeys() throws StorageException, GeneralSecurityException {
+ KeystoreModel model = storage.getObject(KeystoreModel.class, new Request(new Columns.All()));
+ if (model != null) {
+ publicKey = KeyFactory.getInstance("EC")
+ .generatePublic(new X509EncodedKeySpec(model.getPublicKey()));
+ privateKey = KeyFactory.getInstance("EC")
+ .generatePrivate(new PKCS8EncodedKeySpec(model.getPrivateKey()));
+ } else {
+ KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
+ generator.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
+ KeyPair pair = generator.generateKeyPair();
+
+ publicKey = pair.getPublic();
+ privateKey = pair.getPrivate();
+
+ model = new KeystoreModel();
+ model.setPublicKey(publicKey.getEncoded());
+ model.setPrivateKey(privateKey.getEncoded());
+ storage.addObject(model, new Request(new Columns.Exclude("id")));
+ }
+ }
+
+}
diff --git a/src/main/java/org/traccar/api/signature/KeystoreModel.java b/src/main/java/org/traccar/api/signature/KeystoreModel.java
new file mode 100644
index 000000000..7f3140e81
--- /dev/null
+++ b/src/main/java/org/traccar/api/signature/KeystoreModel.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2022 Anton Tananaev (anton@traccar.org)
+ *
+ * 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 at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.traccar.api.signature;
+
+import org.traccar.model.BaseModel;
+import org.traccar.storage.StorageName;
+
+@StorageName("tc_keystore")
+public class KeystoreModel extends BaseModel {
+
+ private byte[] publicKey;
+
+ public byte[] getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(byte[] publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ private byte[] privateKey;
+
+ public byte[] getPrivateKey() {
+ return privateKey;
+ }
+
+ public void setPrivateKey(byte[] privateKey) {
+ this.privateKey = privateKey;
+ }
+
+}