diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cf3af0c2e6157d2e31b4f589bf5c256849b89d..0c5decad3d8be81a49dccdd4a748dc667994c587 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,11 +32,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed ### +* Denying a role permission has no effect + [#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). See security + notes below. * Missing RecordType leads to unexpected server error [#166](https://gitlab.com/caosdb/caosdb-server/-/issues/166) ### Security ### +* Fixed [#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). This was + an error in the authorization procedure which allowed unprivileged users + execute insert, update or delete transactions on entities. However, the + unprivileged users would also need the correct entity permissions to do that. + + Without backup, this means possible data loss. Also there was the possibility + to spam the database by creating unwanted entities. + ### Documentation ### - Nested queries. diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index d772f4b392b782e7bcb9a82f77898402218660c1..fbcb186e45ff5bff20ca7ff20fa321f547048527 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -7,6 +7,7 @@ * `>=Java 11` * `>=Apache Maven 3.6.0` * `>=Make 4.2` +* `>=gcc 8` (if PAM authentication is required) * `libpam` (if PAM authentication is required) * More dependencies are being pulled and installed automatically by Maven. See the complete list of dependencies in the [pom.xml](pom.xml) diff --git a/README_SETUP.md b/README_SETUP.md index ce6f03d7c287f3842eac6af2d017eed5a7d8bcb5..acb3a79ad256fbba6a0d0a69887bb7c7ba7b28b9 100644 --- a/README_SETUP.md +++ b/README_SETUP.md @@ -15,12 +15,18 @@ See [DEPENDENCIES.md](DEPENDENCIES.md). On Debian, the required packages can be installed with: - apt-get install git make mariadb-server maven openjdk-11-jdk-headless \ - python3-pip screen libpam0g-dev unzip + apt-get install make mariadb-server maven openjdk-11-jdk-headless \ + python3-pip libpam0g-dev unzip Note that installing MariaDB will uninstall existing MySQL packages and vice versa. +#### Install the requirements on Fedora + +On Fedora, the required packages can be installed with: + + sudo dnf install make pam-devel mariadb-server mariadb python3 java-17-openjdk-headless unzip gcc + ### System * `>=Linux 4.0.0`, `x86_64`, e.g. Ubuntu 18.04 @@ -160,20 +166,47 @@ sources (if you called `make run` previously). ## Setup Eclipse -1. Open Eclipse (recommended version: Oxygen.1a Release (4.7.1a)) -2. `File > New > Java Project`: Choose a project name and specify the location - of this repo. The JRE and Project layout should be configured automatically. - Now, the project should initially have two source-folders: `./src/main/java` - and `./src/test/java`. After a build, another one, - `./target/generated-sources/antlr4` should be generated. If there are more - than these three source-folders, reconfigure the projects source folders - appropriately with `Project > Properties > Java Build Path > Source`. -3. In the `Package Explorer` view, right-click on the project and `Configure > - Convert to Maven Project`. -4. In the `Package Explorer` view, right-click on the project and `Maven > - Update Project`. -5. Usually a build of the project is started automatically. Otherwise `Project > - Build Project`. +1. Open Eclipse (tested with 2022-R12) +2. File > Import > Maven > Existing Maven Projects: Specify location. +3. You will most likely encounter "Plugin execution not covered by lifecycle + configuration: ..." errors. Adapt the file + `<eclipse-workspace>/.metadata/.plugins/org.eclipse.m2e.core/lifecycle-mapping-metadata.xml`. + + Example: + + ```xml + <?xml version="1.0" encoding="UTF-8"?> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>com.coveo</groupId> + <artifactId>fmt-maven-plugin</artifactId> + <versionRange>2.5.1</versionRange> + <goals> + <goal>format</goal> + </goals> + </pluginExecutionFilter> + <action> + <ignore /> + </action> + </pluginExecution> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <versionRange>1.4</versionRange> + <goals> + <goal>create-metadata</goal> + </goals> + </pluginExecutionFilter> + <action> + <ignore /> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + ``` Done! diff --git a/conf/core/server.conf b/conf/core/server.conf index 46c0f83d4b7327d84c9009bdcba10b54ee0df70f..c030d6eb63d61ad2d9adc6a174877b1006396537 100644 --- a/conf/core/server.conf +++ b/conf/core/server.conf @@ -67,7 +67,7 @@ MYSQL_DATABASE_NAME=caosdb # User name for connecting to mysql MYSQL_USER_NAME=caosdb # Password for the user -MYSQL_USER_PASSWORD=caosdb +MYSQL_USER_PASSWORD=random1234 # Schema of mysql procedures and tables which is required by this CaosDB instance MYSQL_SCHEMA_VERSION=v5.0 diff --git a/src/main/java/org/caosdb/server/jobs/core/AccessControl.java b/src/main/java/org/caosdb/server/jobs/core/AccessControl.java index 4217c55e1153dafc302630823873fc75640ca9be..ede7658580811671f19f955f36faa59db4df922f 100644 --- a/src/main/java/org/caosdb/server/jobs/core/AccessControl.java +++ b/src/main/java/org/caosdb/server/jobs/core/AccessControl.java @@ -1,9 +1,10 @@ /* - * ** header v3.0 * This file is a part of the CaosDB Project. * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2023 IndiScale <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -17,17 +18,17 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header */ package org.caosdb.server.jobs.core; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.caosdb.server.accessControl.ACMPermissions; -import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity; +import org.caosdb.server.entity.DeleteEntity; import org.caosdb.server.entity.EntityInterface; -import org.caosdb.server.entity.wrapper.Parent; +import org.caosdb.server.entity.InsertEntity; +import org.caosdb.server.entity.Role; +import org.caosdb.server.entity.UpdateEntity; import org.caosdb.server.jobs.ContainerJob; import org.caosdb.server.jobs.JobAnnotation; import org.caosdb.server.jobs.TransactionStage; @@ -35,6 +36,14 @@ import org.caosdb.server.transaction.Retrieve; import org.caosdb.server.utils.EntityStatus; import org.caosdb.server.utils.ServerMessages; +/** + * Checks the TRANSACTION:* permissions before a transaction begins. + * + * <p>Users need TRANSACTION:INSERT:?ENTITY_ROLE? permission to insert an entity of the particular + * entity role. Likewise, they need the TRANSACTION:UPDATE or TRANSACTION:DELETE permissions. + * + * @author Timm Fitschen <f.fitschen@indiscale.com> + */ @JobAnnotation(stage = TransactionStage.INIT) public class AccessControl extends ContainerJob { @@ -46,12 +55,15 @@ public class AccessControl extends ContainerJob { super(permission, description); } - public final String toString(String entityRole) { - return toString().replace(ENTITY_ROLE_PARAMETER, entityRole); + public final String toString(Role entityRole) { + String roleString = entityRole == null ? "" : entityRole.toString(); + return toString().replace(ENTITY_ROLE_PARAMETER, roleString); } - public final String toString(String transaction, String entityRole) { - return "TRANSACTION:" + transaction + (entityRole != null ? (":" + entityRole) : ""); + public final String toString(String transaction, Role entityRole) { + return "TRANSACTION:" + + transaction + + (entityRole != null ? (":" + entityRole.toString()) : ""); } public static String init() { @@ -80,38 +92,26 @@ public class AccessControl extends ContainerJob { protected void run() { final Subject subject = SecurityUtils.getSubject(); - // subject has complete permissions for this kind of transaction - if (subject.isPermitted( - TRANSACTION_PERMISSIONS.toString(getTransaction().getClass().getSimpleName(), null))) { - return; - } - if (getTransaction() instanceof Retrieve) { return; } for (final EntityInterface e : getContainer()) { - // per role permission - if (subject.isPermitted( - TRANSACTION_PERMISSIONS.toString( - getTransaction().getClass().getSimpleName(), e.getRole().toString()))) { - continue; - } - - // special annotations permission - if (e.hasParents() && e.getParents().size() == 1) { - final Parent par1 = e.getParents().get(0); - if (par1.hasId() && !par1.getId().isTemporary()) { - execute(new RetrieveSparseEntity(par1)); + if (e instanceof InsertEntity) { + if (subject.isPermitted(INSERT.toString(e.getRole()))) { + continue; } - if (par1.hasName() - && par1.getName().equals("CommentAnnotation") - && subject.isPermitted( - getTransaction().getClass().getSimpleName() + ":CommentAnnotation")) { + } else if (e instanceof DeleteEntity) { + if (subject.isPermitted(DELETE.toString(e.getRole()))) { + continue; + } + } else if (e instanceof UpdateEntity) { + if (subject.isPermitted(UPDATE.toString(e.getRole()))) { continue; } } + e.setEntityStatus(EntityStatus.UNQUALIFIED); e.addMessage(ServerMessages.AUTHORIZATION_ERROR); }