Commit 1659b51e authored by Grzegorz Pietrusza's avatar Grzegorz Pietrusza

getting back to single flag - initial version

parent d74fbd2d
...@@ -4,7 +4,7 @@ server: ...@@ -4,7 +4,7 @@ server:
- type: http - type: http
port: 8080 port: 8080
dbHost: 46.4.242.141 dbHost: 92f653f4-cf83-4801-8475-cd748954c3b6.node.dockerapp.io
#dbHost: 127.0.0.1 #dbHost: 127.0.0.1
dbPort: 27017 dbPort: 27017
dbName: db dbName: db
...@@ -70,19 +70,19 @@ textTasks: ...@@ -70,19 +70,19 @@ textTasks:
text: "Odszyfruj1" text: "Odszyfruj1"
level: 1 level: 1
flags: flags:
- value: "sdfg1f1" - value: "AGH_sdfg1f1"
description: "flaga 1" description: "flaga 1"
- value: "sdfg1f2" - value: "AGH_sdfg1f2"
description: "flaga 2" description: "flaga 2"
- value: "sdfgf13" - value: "AGH_sdfgf13"
description: "flaga 3" description: "flaga 3"
- name: "Szyfro2" - name: "Szyfro2"
text: "Odszyfruj2" text: "Odszyfruj2"
level: 2 level: 2
flags: flags:
- value: "sdfg1" - value: "AGH_sdfg1"
description: "flaga 1" description: "AGH_flaga 1"
- value: "sdfg1" - value: "sdfg1"
description: "flaga 2" description: "flaga 2"
...@@ -91,20 +91,20 @@ webTasks: ...@@ -91,20 +91,20 @@ webTasks:
url: "http://google.pl" url: "http://google.pl"
level: 3 level: 3
flags: flags:
- value: "sdfg1fs" - value: "AGH_sdfg1fs"
description: "flaga 11" description: "flaga 11"
- value: "sdfdg1f" - value: "AGH_sdfdg1f"
description: "flaga 22" description: "flaga 22"
- value: "sfdfgf1" - value: "AGH_sfdfgf1"
description: "flaga 33" description: "flaga 33"
- name: "Inna dziura" - name: "Inna dziura"
url: "http://wikipedia.pl" url: "http://wikipedia.pl"
level: 4 level: 4
flags: flags:
- value: "sdfffg1fs" - value: "AGH_sdfffg1fs"
description: "flaga 11" description: "flaga 11"
- value: "sffdfdg1f" - value: "AGH_sffdfdg1f"
description: "flaga 22" description: "flaga 22"
- value: "sdfassfdfgf1" - value: "AGH_sdfassfdfgf1"
description: "flaga 33" description: "flaga 33"
...@@ -15,14 +15,12 @@ public class Solution ...@@ -15,14 +15,12 @@ public class Solution
private Task task; private Task task;
private Team team; private Team team;
private Flag flag; private Flag flag;
private String hashValue;
public Solution(Team team, Task task, Flag flag, String hashValue) public Solution(Team team, Task task, Flag flag)
{ {
this.team = checkNotNull(team); this.team = checkNotNull(team);
this.task = checkNotNull(task); this.task = checkNotNull(task);
this.flag = checkNotNull(flag); this.flag = checkNotNull(flag);
this.hashValue = checkNotNull(hashValue);
} }
public Solution() public Solution()
...@@ -58,14 +56,4 @@ public class Solution ...@@ -58,14 +56,4 @@ public class Solution
{ {
this.flag = flag; this.flag = flag;
} }
public String getHashValue()
{
return hashValue;
}
public void setHashValue(String hashValue)
{
this.hashValue = hashValue;
}
} }
package com.telephoners.krakyournet.ctf.core;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.providers.MessageDigestProvider;
import org.apache.commons.codec.binary.Hex;
@Singleton
public class HashValidator
{
private ApplicationConfiguration applicationConfiguration;
private MessageDigestProvider messageDigestProvider;
@Inject
public HashValidator(ApplicationConfiguration applicationConfiguration,
MessageDigestProvider messageDigestProvider)
{
this.applicationConfiguration = applicationConfiguration;
this.messageDigestProvider = messageDigestProvider;
}
public String calculateHashValue(User user, String flagValue)
{
String combinedStrings = applicationConfiguration.getSalt() + user.getName() + flagValue;
return Hex.encodeHexString(messageDigestProvider.getMessageDigest().digest(combinedStrings.getBytes()));
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class InvalidSolutionException extends WebApplicationException
{
public InvalidSolutionException() {
super(Response.status(Response.Status.NOT_ACCEPTABLE)
.entity("Solution invalid").type("text/plain").build());
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class SolutionAlreadySubmittedException extends WebApplicationException
{
public SolutionAlreadySubmittedException()
{
super(Response.status(Response.Status.NOT_ACCEPTABLE)
.entity("Solution already submitted.").type("text/plain").build());
}
}
package com.telephoners.krakyournet.ctf.exceptions;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class TaskNotFoundException extends WebApplicationException
{
public TaskNotFoundException() {
super(Response.status(Response.Status.NOT_FOUND)
.entity("Task not found.").type("text/plain").build());
}
}
...@@ -3,6 +3,7 @@ package com.telephoners.krakyournet.ctf.repositories; ...@@ -3,6 +3,7 @@ package com.telephoners.krakyournet.ctf.repositories;
import com.telephoners.krakyournet.ctf.beans.Solution; import com.telephoners.krakyournet.ctf.beans.Solution;
import com.telephoners.krakyournet.ctf.beans.Team; import com.telephoners.krakyournet.ctf.beans.Team;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.exceptions.SolutionAlreadySubmittedException;
import org.mongodb.morphia.Datastore; import org.mongodb.morphia.Datastore;
import javax.inject.Inject; import javax.inject.Inject;
...@@ -29,7 +30,7 @@ public class SolutionsRepository extends Repository<Solution> ...@@ -29,7 +30,7 @@ public class SolutionsRepository extends Repository<Solution>
{ {
//todo: do not identify team by name? conflict in team ids? //todo: do not identify team by name? conflict in team ids?
return datastore.createQuery(Solution.class) return datastore.createQuery(Solution.class)
.filter("team.name",team.getName()).asList() .filter("team.name", team.getName()).asList()
.stream() .stream()
.collect(Collectors.groupingBy(new Function<Solution, Task>() .collect(Collectors.groupingBy(new Function<Solution, Task>()
{ {
...@@ -67,12 +68,11 @@ public class SolutionsRepository extends Repository<Solution> ...@@ -67,12 +68,11 @@ public class SolutionsRepository extends Repository<Solution>
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public boolean submitSolution(Solution solution) public void submitSolution(Solution solution)
{ {
if (!isAlreadySubmittedSolution(solution)) { if (isAlreadySubmittedSolution(solution)) {
add(solution); throw new SolutionAlreadySubmittedException();
return true;
} }
return false; add(solution);
} }
} }
\ No newline at end of file
package com.telephoners.krakyournet.ctf.repositories; package com.telephoners.krakyournet.ctf.repositories;
import com.telephoners.krakyournet.ctf.beans.Flag;
import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.core.HashValidator; import com.telephoners.krakyournet.ctf.exceptions.TaskNotFoundException;
import com.telephoners.krakyournet.ctf.helpers.DBObjectUtils; import com.telephoners.krakyournet.ctf.helpers.DBObjectUtils;
import javafx.util.Pair;
import org.mongodb.morphia.Datastore; import org.mongodb.morphia.Datastore;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Singleton @Singleton
public class TasksRepository extends Repository<Task> public class TasksRepository extends Repository<Task>
{ {
private Datastore datastore; private Datastore datastore;
private UsersRepository usersRepository;
private HashValidator hashValidator;
@Inject @Inject
public TasksRepository(Datastore datastore, public TasksRepository(Datastore datastore)
UsersRepository usersRepository,
HashValidator hashValidator)
{ {
super(datastore); super(datastore);
this.datastore = datastore; this.datastore = datastore;
this.usersRepository = usersRepository;
this.hashValidator = hashValidator;
} }
public Task getByLevel(int level) public Task getByLevel(int level)
{ {
return datastore.createQuery(Task.class) return datastore.createQuery(Task.class)
.filter("level", level) .filter("level", level)
.get(); .asList()
.stream()
.findFirst()
.orElseThrow(TaskNotFoundException::new);
} }
public List<Task> getAllPublic() public List<Task> getAllPublic()
...@@ -45,24 +37,4 @@ public class TasksRepository extends Repository<Task> ...@@ -45,24 +37,4 @@ public class TasksRepository extends Repository<Task>
.retrievedFields(true, DBObjectUtils.getPublicFields(Task.class)) .retrievedFields(true, DBObjectUtils.getPublicFields(Task.class))
.asList(); .asList();
} }
public Map<Integer, List<String>> getUserFlagsHashes(String username)
{
return getAll().stream()
.collect(Collectors.toMap(
Task::getLevel,
task -> task.getFlags().stream()
.map(flag -> hashValidator.calculateHashValue(usersRepository.getUserByName(username), flag.getValue()))
.collect(Collectors.toList())
));
}
public Pair<Task, Flag> getTaskFlagPairByHashValue(User user, String userHash, int taskLevel)
{
Flag matchedFlag = getByLevel(taskLevel).getFlags().stream()
.filter(flag -> hashValidator.calculateHashValue(user, flag.getValue()).equals(userHash))
.findFirst()
.get();
return new Pair<>(getByLevel(taskLevel), matchedFlag);
}
} }
\ No newline at end of file
...@@ -5,12 +5,11 @@ import com.telephoners.krakyournet.ctf.beans.Solution; ...@@ -5,12 +5,11 @@ import com.telephoners.krakyournet.ctf.beans.Solution;
import com.telephoners.krakyournet.ctf.beans.Team; import com.telephoners.krakyournet.ctf.beans.Team;
import com.telephoners.krakyournet.ctf.beans.User; import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.core.HashValidator; import com.telephoners.krakyournet.ctf.exceptions.InvalidSolutionException;
import com.telephoners.krakyournet.ctf.repositories.SolutionsRepository; import com.telephoners.krakyournet.ctf.repositories.SolutionsRepository;
import com.telephoners.krakyournet.ctf.repositories.TasksRepository; import com.telephoners.krakyournet.ctf.repositories.TasksRepository;
import com.telephoners.krakyournet.ctf.repositories.TeamsRepository; import com.telephoners.krakyournet.ctf.repositories.TeamsRepository;
import io.dropwizard.auth.Auth; import io.dropwizard.auth.Auth;
import javafx.util.Pair;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
...@@ -43,15 +42,18 @@ public class SolutionsResource ...@@ -43,15 +42,18 @@ public class SolutionsResource
@Path("/{task_level}") @Path("/{task_level}")
public Response submitSolution(@Auth User user, public Response submitSolution(@Auth User user,
@PathParam("task_level") int taskLevel, @PathParam("task_level") int taskLevel,
String hash) throws Exception String userFlag) throws Exception
{ {
Pair<Task, Flag> taskFlagPair = tasksRepository.getTaskFlagPairByHashValue(user, hash, taskLevel); Task task = tasksRepository.getByLevel(taskLevel);
if (taskFlagPair != null) { Flag flag = task.getFlags()
if(solutionsRepository.submitSolution(new Solution(teamsRepository.getTeamByUser(user), taskFlagPair.getKey(), taskFlagPair.getValue(), hash))) { .stream()
.filter(taskFlag -> taskFlag.getValue().equals(userFlag))
.findFirst()
.orElseThrow(InvalidSolutionException::new); //what will be returned?
solutionsRepository.submitSolution(new Solution(teamsRepository.getTeamByUser(user), task, flag));
return Response.ok().build(); return Response.ok().build();
} // return Response.status(Response.Status.NOT_ACCEPTABLE).build();
}
return Response.status(Response.Status.NOT_ACCEPTABLE).build();
} }
@GET @GET
...@@ -61,6 +63,7 @@ public class SolutionsResource ...@@ -61,6 +63,7 @@ public class SolutionsResource
return solutionsRepository.getCompletedTasks(teamsRepository.getTeamByUser(user)); return solutionsRepository.getCompletedTasks(teamsRepository.getTeamByUser(user));
} }
//todo: rethink
@GET @GET
@Path("/completed/all") @Path("/completed/all")
public Map<String, List<Integer>> getAllTeamsCompletetdTasks(@Auth User user) public Map<String, List<Integer>> getAllTeamsCompletetdTasks(@Auth User user)
......
package com.telephoners.krakyournet.ctf.resources; package com.telephoners.krakyournet.ctf.resources;
import com.telephoners.krakyournet.ctf.beans.User;
import com.telephoners.krakyournet.ctf.beans.tasks.Task; import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import com.telephoners.krakyournet.ctf.repositories.TasksRepository; import com.telephoners.krakyournet.ctf.repositories.TasksRepository;
import io.dropwizard.auth.Auth;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List; import java.util.List;
@Singleton @Singleton
...@@ -33,20 +29,4 @@ public class TasksResource ...@@ -33,20 +29,4 @@ public class TasksResource
{ {
return tasksRepository.getAllPublic(); return tasksRepository.getAllPublic();
} }
@GET
@Path("/{username}")
public Response getUserFlags(@Auth User user, final @PathParam("username") String username)
{
if (user.isAdmin()) {
try {
return Response.ok()
.entity(tasksRepository.getUserFlagsHashes(username))
.build();
} catch (Exception e) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
return Response.status(Response.Status.UNAUTHORIZED).build();
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment