Skip to content
Snippets Groups Projects
Commit f06d6615 authored by kasperdt's avatar kasperdt
Browse files

Final commit

parent b9762f64
No related branches found
No related tags found
No related merge requests found
...@@ -145,7 +145,23 @@ correct protection flags on the session cookie.* ...@@ -145,7 +145,23 @@ correct protection flags on the session cookie.*
#### Notes – task 0 #### Notes – task 0
Here you write your notes about how this task was performed. Task A:
Used SCrypt on the password string before creating a new
Password instance as a way to have a more secure
password authentication.
Task B:
I used the older NIST guide-lines where it was common
to demand at least a lowercase- and uppercase character
and a number, at least 8 character and at most 64 character.
The password is tested for this in InChat.Register.
Task C:
Handler:145 -> set cookie to:
cookie.setHttpOnly(true);
cookie.setSecure(true);
### Task 1 – SQL injection (4 points) ### Task 1 – SQL injection (4 points)
...@@ -156,7 +172,7 @@ it wide open to injection attacks. ...@@ -156,7 +172,7 @@ it wide open to injection attacks.
#### Notes – task 1 #### Notes – task 1
Here you write your notes about how this task was performed. I Used prepared statements to protect the sql code from sql-injections.
### Task 2 – Cross-site scripting (4 points) ### Task 2 – Cross-site scripting (4 points)
...@@ -171,7 +187,8 @@ take a look at the [OWASP XSS prevention cheat sheet](https://cheatsheetseries.o ...@@ -171,7 +187,8 @@ take a look at the [OWASP XSS prevention cheat sheet](https://cheatsheetseries.o
#### Notes – task 2 #### Notes – task 2
Here you write your notes about how this task was performed. I encoded every variable before putting it into the html script in Handler
as safety measures. This prevents XSS attacks by untrusted input-variables.
### Task 3 – Cross-site request forgery (1 point) ### Task 3 – Cross-site request forgery (1 point)
...@@ -243,6 +260,13 @@ can ignore issues related HTTPS. ...@@ -243,6 +260,13 @@ can ignore issues related HTTPS.
#### Notes – task ω #### Notes – task ω
Here you write your notes about how this task was performed. Issue 1:
No implementation for asserting that password and password_repeat
are the same when registering a new user.
Issue 2:
It's possible to create a new user though it already exists.
Both issues are resolved in InChat.register.
...@@ -61,8 +61,12 @@ public final class Account { ...@@ -61,8 +61,12 @@ public final class Account {
* @return true if password matches. * @return true if password matches.
*/ */
public boolean checkPassword(String password) { public boolean checkPassword(String password) {
// TODO: This does not seem right. if (SCryptUtil.check(password,hashedPassword.toString())) {
return true; return true;
}
System.out.println("Wrong password");
return false;
} }
......
package inf226.inchat; package inf226.inchat;
import java.sql.Connection; import java.sql.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
...@@ -39,7 +36,7 @@ public final class AccountStorage ...@@ -39,7 +36,7 @@ public final class AccountStorage
this.channelStore = channelStore; this.channelStore = channelStore;
connection.createStatement() connection.createStatement()
.executeUpdate("CREATE TABLE IF NOT EXISTS Account (id TEXT PRIMARY KEY, version TEXT, user TEXT, FOREIGN KEY(user) REFERENCES User(id) ON DELETE CASCADE)"); .executeUpdate("CREATE TABLE IF NOT EXISTS Account (id TEXT PRIMARY KEY, version TEXT, user TEXT, password TEXT ,FOREIGN KEY(user) REFERENCES User(id) ON DELETE CASCADE)");
connection.createStatement() connection.createStatement()
.executeUpdate("CREATE TABLE IF NOT EXISTS AccountChannel (account TEXT, channel TEXT, alias TEXT, ordinal INTEGER, PRIMARY KEY(account,channel), FOREIGN KEY(account) REFERENCES Account(id) ON DELETE CASCADE, FOREIGN KEY(channel) REFERENCES Channel(id) ON DELETE CASCADE)"); .executeUpdate("CREATE TABLE IF NOT EXISTS AccountChannel (account TEXT, channel TEXT, alias TEXT, ordinal INTEGER, PRIMARY KEY(account,channel), FOREIGN KEY(account) REFERENCES Account(id) ON DELETE CASCADE, FOREIGN KEY(channel) REFERENCES Channel(id) ON DELETE CASCADE)");
} }
...@@ -49,10 +46,13 @@ public final class AccountStorage ...@@ -49,10 +46,13 @@ public final class AccountStorage
throws SQLException { throws SQLException {
final Stored<Account> stored = new Stored<Account>(account); final Stored<Account> stored = new Stored<Account>(account);
String sql = "INSERT INTO Account VALUES('" + stored.identity + "','" final String sql = "INSERT INTO Account VALUES(?, ?, ?, ?)";
+ stored.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ account.user.identity + "')"; prepStmt.setObject(1, stored.identity);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(2, stored.version);
prepStmt.setObject(3, account.user.identity);
prepStmt.setString(4, account.hashedPassword.toString());
prepStmt.executeUpdate();
// Write the list of channels // Write the list of channels
final Maybe.Builder<SQLException> exception = Maybe.builder(); final Maybe.Builder<SQLException> exception = Maybe.builder();
...@@ -61,11 +61,16 @@ public final class AccountStorage ...@@ -61,11 +61,16 @@ public final class AccountStorage
String alias = element.first; String alias = element.first;
Stored<Channel> channel = element.second; Stored<Channel> channel = element.second;
final String msql final String msql
= "INSERT INTO AccountChannel VALUES('" + stored.identity + "','" = "INSERT INTO AccountChannel VALUES(?, ?, ?, ?)";
+ channel.identity + "','"
+ alias + "','" try {
+ ordinal.get().toString() + "')"; PreparedStatement prepStmt2 = connection.prepareStatement(msql);
try { connection.createStatement().executeUpdate(msql); } prepStmt2.setObject(1, stored.identity);
prepStmt2.setObject(2, channel.identity);
prepStmt2.setObject(3, alias);
prepStmt2.setString(4, ordinal.get().toString());
prepStmt2.executeUpdate();
}
catch (SQLException e) { exception.accept(e) ; } catch (SQLException e) { exception.accept(e) ; }
ordinal.accept(ordinal.get() + 1); ordinal.accept(ordinal.get() + 1);
}); });
...@@ -84,27 +89,35 @@ public final class AccountStorage ...@@ -84,27 +89,35 @@ public final class AccountStorage
final Stored<Account> updated = current.newVersion(new_account); final Stored<Account> updated = current.newVersion(new_account);
if(current.version.equals(account.version)) { if(current.version.equals(account.version)) {
String sql = "UPDATE Account SET" + String sql = "UPDATE Account SET" +
" (version,user) =('" " (version,user) =(?, ?) WHERE id= ?";
+ updated.version + "','"
+ new_account.user.identity
+ "') WHERE id='"+ updated.identity + "'";
connection.createStatement().executeUpdate(sql); connection.createStatement().executeUpdate(sql);
PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1, updated.version);
prepStmt.setObject(2, new_account.user.identity);
prepStmt.setObject(3, updated.identity);
prepStmt.executeUpdate();
// Rewrite the list of channels // Rewrite the list of channels
connection.createStatement().executeUpdate("DELETE FROM AccountChannel WHERE account='" + account.identity + "'"); String sql2 = "DELETE FROM AccountChannel WHERE account=?";
PreparedStatement prepStmt2 = connection.prepareStatement(sql2);
prepStmt2.setObject(1, account.identity);
prepStmt2.executeUpdate();
final Maybe.Builder<SQLException> exception = Maybe.builder(); final Maybe.Builder<SQLException> exception = Maybe.builder();
final Mutable<Integer> ordinal = new Mutable<Integer>(0); final Mutable<Integer> ordinal = new Mutable<Integer>(0);
new_account.channels.forEach(element -> { new_account.channels.forEach(element -> {
String alias = element.first; String alias = element.first;
Stored<Channel> channel = element.second; Stored<Channel> channel = element.second;
final String msql final String msql = "INSERT INTO AccountChannel VALUES(?, ?, ?, ?)";
= "INSERT INTO AccountChannel VALUES('" + account.identity + "','" try (PreparedStatement ps3 = connection.prepareStatement(msql)) {
+ channel.identity + "','" ps3.setObject(1, account.identity);
+ alias + "','" ps3.setObject(2, channel.identity);
+ ordinal.get().toString() + "')"; ps3.setString(3, alias);
try { connection.createStatement().executeUpdate(msql); } ps3.setString(4, ordinal.get().toString());
ps3.executeUpdate();
}
catch (SQLException e) { exception.accept(e) ; } catch (SQLException e) { exception.accept(e) ; }
ordinal.accept(ordinal.get() + 1); ordinal.accept(ordinal.get() + 1);
}); });
...@@ -123,8 +136,10 @@ public final class AccountStorage ...@@ -123,8 +136,10 @@ public final class AccountStorage
SQLException { SQLException {
final Stored<Account> current = get(account.identity); final Stored<Account> current = get(account.identity);
if(current.version.equals(account.version)) { if(current.version.equals(account.version)) {
String sql = "DELETE FROM Account WHERE id ='" + account.identity + "'"; String sql = "DELETE FROM Account WHERE id=?";
connection.createStatement().executeUpdate(sql); PreparedStatement ps = connection.prepareStatement(sql);
ps.setObject(1, account.identity);
ps.executeUpdate();
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -134,7 +149,7 @@ public final class AccountStorage ...@@ -134,7 +149,7 @@ public final class AccountStorage
throws DeletedException, throws DeletedException,
SQLException { SQLException {
final String accountsql = "SELECT version,user FROM Account WHERE id = '" + id.toString() + "'"; final String accountsql = "SELECT version,user,password FROM Account WHERE id = '" + id.toString() + "'";
final String channelsql = "SELECT channel,alias,ordinal FROM AccountChannel WHERE account = '" + id.toString() + "' ORDER BY ordinal DESC"; final String channelsql = "SELECT channel,alias,ordinal FROM AccountChannel WHERE account = '" + id.toString() + "' ORDER BY ordinal DESC";
final Statement accountStatement = connection.createStatement(); final Statement accountStatement = connection.createStatement();
...@@ -171,12 +186,13 @@ public final class AccountStorage ...@@ -171,12 +186,13 @@ public final class AccountStorage
public Stored<Account> lookup(String username) public Stored<Account> lookup(String username)
throws DeletedException, throws DeletedException,
SQLException { SQLException {
final String sql = "SELECT Account.id from Account INNER JOIN User ON user=User.id where User.name='" + username + "'";
final String sql = "SELECT Account.id from Account INNER JOIN User ON user=User.id where User.name=?";
System.err.println(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
final Statement statement = connection.createStatement(); prepStmt.setObject(1, username);
final ResultSet rs = statement.executeQuery(sql); //System.err.println(sql);
final ResultSet rs = prepStmt.executeQuery();
if(rs.next()) { if(rs.next()) {
final UUID identity = final UUID identity =
UUID.fromString(rs.getString("id")); UUID.fromString(rs.getString("id"));
...@@ -184,6 +200,18 @@ public final class AccountStorage ...@@ -184,6 +200,18 @@ public final class AccountStorage
} }
throw new DeletedException(); throw new DeletedException();
} }
/**
* Gets the password based on the username
*/
public String getPassword(String username) throws SQLException {
final String sql = "SELECT Account.password FROM Account INNER JOIN User on user=User.id WHERE User.name=?";
PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setString(1, username);
final ResultSet result = prepStmt.executeQuery();
return result.getString("password");
}
} }
package inf226.inchat; package inf226.inchat;
import java.sql.Connection; import java.sql.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
import java.util.TreeMap; import java.util.TreeMap;
...@@ -46,19 +43,25 @@ public final class ChannelStorage ...@@ -46,19 +43,25 @@ public final class ChannelStorage
throws SQLException { throws SQLException {
final Stored<Channel> stored = new Stored<Channel>(channel); final Stored<Channel> stored = new Stored<Channel>(channel);
String sql = "INSERT INTO Channel VALUES('" + stored.identity + "','" String sql = "INSERT INTO Channel VALUES(?, ?, ?)";
+ stored.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ channel.name + "')"; prepStmt.setObject(1, stored.identity);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(2, stored.version);
prepStmt.setObject(3, channel.name);
prepStmt.execute();
// Write the list of events // Write the list of events
final Maybe.Builder<SQLException> exception = Maybe.builder(); final Maybe.Builder<SQLException> exception = Maybe.builder();
final Mutable<Integer> ordinal = new Mutable<Integer>(0); final Mutable<Integer> ordinal = new Mutable<Integer>(0);
channel.events.forEach(event -> { channel.events.forEach(event -> {
final String msql = "INSERT INTO ChannelEvent VALUES('" + stored.identity + "','" final String msql = "INSERT INTO ChannelEvent VALUES(?, ?, ?)";
+ event.identity + "','" try {
+ ordinal.get().toString() + "')"; PreparedStatement prepStmt2 = connection.prepareStatement(msql);
try { connection.createStatement().executeUpdate(msql); } prepStmt2.setObject(1, stored.identity);
prepStmt2.setObject(2, event.identity);
prepStmt2.setObject(3, ordinal.get().toString());
prepStmt2.execute();
}
catch (SQLException e) { exception.accept(e) ; } catch (SQLException e) { exception.accept(e) ; }
ordinal.accept(ordinal.get() + 1); ordinal.accept(ordinal.get() + 1);
}); });
...@@ -77,23 +80,29 @@ public final class ChannelStorage ...@@ -77,23 +80,29 @@ public final class ChannelStorage
final Stored<Channel> updated = current.newVersion(new_channel); final Stored<Channel> updated = current.newVersion(new_channel);
if(current.version.equals(channel.version)) { if(current.version.equals(channel.version)) {
String sql = "UPDATE Channel SET" + String sql = "UPDATE Channel SET" +
" (version,name) =('" " (version,name) = (?, ?) WHERE id=?";
+ updated.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ new_channel.name prepStmt.setObject(1, updated.version);
+ "') WHERE id='"+ updated.identity + "'"; prepStmt.setObject(2, new_channel.name);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(3, updated.identity);
prepStmt.execute();
// Rewrite the list of events // Rewrite the list of events
connection.createStatement().executeUpdate("DELETE FROM ChannelEvent WHERE channel='" + channel.identity + "'"); String sql2 = "DELETE FROM ChannelEvent WHERE channel=?";
PreparedStatement prepStmt2 = connection.prepareStatement(sql2);
prepStmt2.setObject(1,channel.identity);
prepStmt2.execute();
final Maybe.Builder<SQLException> exception = Maybe.builder(); final Maybe.Builder<SQLException> exception = Maybe.builder();
final Mutable<Integer> ordinal = new Mutable<Integer>(0); final Mutable<Integer> ordinal = new Mutable<Integer>(0);
new_channel.events.forEach(event -> { new_channel.events.forEach(event -> {
final String msql = "INSERT INTO ChannelEvent VALUES('" + channel.identity + "','" final String msql = "INSERT INTO ChannelEvent VALUES(?, ?, ?)";
+ event.identity + "','" try {
+ ordinal.get().toString() + "')"; PreparedStatement prepStmt3 = connection.prepareStatement(msql);
try { connection.createStatement().executeUpdate(msql); } prepStmt3.setObject(1,channel.identity);
prepStmt3.setObject(2,event.identity);
prepStmt3.setObject(3,ordinal.get().toString());
prepStmt3.execute();
}
catch (SQLException e) { exception.accept(e) ; } catch (SQLException e) { exception.accept(e) ; }
ordinal.accept(ordinal.get() + 1); ordinal.accept(ordinal.get() + 1);
}); });
...@@ -113,8 +122,11 @@ public final class ChannelStorage ...@@ -113,8 +122,11 @@ public final class ChannelStorage
SQLException { SQLException {
final Stored<Channel> current = get(channel.identity); final Stored<Channel> current = get(channel.identity);
if(current.version.equals(channel.version)) { if(current.version.equals(channel.version)) {
String sql = "DELETE FROM Channel WHERE id ='" + channel.identity + "'"; String sql = "DELETE FROM Channel WHERE id =?";
connection.createStatement().executeUpdate(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1,channel.identity);
prepStmt.execute();
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -158,8 +170,11 @@ public final class ChannelStorage ...@@ -158,8 +170,11 @@ public final class ChannelStorage
public Stored<Channel> noChangeUpdate(UUID channelId) public Stored<Channel> noChangeUpdate(UUID channelId)
throws SQLException, DeletedException { throws SQLException, DeletedException {
String sql = "UPDATE Channel SET" + String sql = "UPDATE Channel SET" +
" (version) =('" + UUID.randomUUID() + "') WHERE id='"+ channelId + "'"; " (version) = (?) WHERE id=?";
connection.createStatement().executeUpdate(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1, UUID.randomUUID());
prepStmt.setObject(2, channelId);
prepStmt.execute();
Stored<Channel> channel = get(channelId); Stored<Channel> channel = get(channelId);
giveNextVersion(channel); giveNextVersion(channel);
return channel; return channel;
...@@ -173,10 +188,10 @@ public final class ChannelStorage ...@@ -173,10 +188,10 @@ public final class ChannelStorage
throws DeletedException, throws DeletedException,
SQLException { SQLException {
final String channelsql = "SELECT version FROM Channel WHERE id = '" + id.toString() + "'"; final String channelsql = "SELECT version FROM Channel WHERE id = ?";
final Statement channelStatement = connection.createStatement(); PreparedStatement prepStmt = connection.prepareStatement(channelsql);
prepStmt.setObject(1, id.toString());
final ResultSet channelResult = channelStatement.executeQuery(channelsql); final ResultSet channelResult = prepStmt.executeQuery();
if(channelResult.next()) { if(channelResult.next()) {
return UUID.fromString( return UUID.fromString(
channelResult.getString("version")); channelResult.getString("version"));
...@@ -247,8 +262,10 @@ public final class ChannelStorage ...@@ -247,8 +262,10 @@ public final class ChannelStorage
*/ */
public Stored<Channel> lookupChannelForEvent(Stored<Channel.Event> e) public Stored<Channel> lookupChannelForEvent(Stored<Channel.Event> e)
throws SQLException, DeletedException { throws SQLException, DeletedException {
String sql = "SELECT channel FROM ChannelEvent WHERE event='" + e.identity + "'"; String sql = "SELECT channel FROM ChannelEvent WHERE event=?";
final ResultSet rs = connection.createStatement().executeQuery(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1,e.identity);
final ResultSet rs = prepStmt.executeQuery();
if(rs.next()) { if(rs.next()) {
final UUID channelId = UUID.fromString(rs.getString("channel")); final UUID channelId = UUID.fromString(rs.getString("channel"));
return get(channelId); return get(channelId);
......
package inf226.inchat; package inf226.inchat;
import java.sql.Connection; import java.sql.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
...@@ -36,23 +33,31 @@ public final class EventStorage ...@@ -36,23 +33,31 @@ public final class EventStorage
final Stored<Channel.Event> stored = new Stored<Channel.Event>(event); final Stored<Channel.Event> stored = new Stored<Channel.Event>(event);
String sql = "INSERT INTO Event VALUES('" + stored.identity + "','" String sql = "INSERT INTO Event VALUES(?, ?, ?, ?)";
+ stored.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ event.type.code + "','" prepStmt.setObject(1, stored.identity);
+ event.time + "')"; prepStmt.setObject(2, stored.version);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(3, event.type.code);
prepStmt.setObject(4, event.time);
prepStmt.execute();
switch (event.type) { switch (event.type) {
case message: case message:
sql = "INSERT INTO Message VALUES('" + stored.identity + "','" sql = "INSERT INTO Message VALUES(?, ?, ?)";
+ event.sender + "','" PreparedStatement prepStmt2 = connection.prepareStatement(sql);
+ event.message +"')"; prepStmt2.setObject(1, stored.identity);
prepStmt2.setObject(2, event.sender);
prepStmt2.setObject(3, event.message);
prepStmt2.execute();
break; break;
case join: case join:
sql = "INSERT INTO Joined VALUES('" + stored.identity + "','" sql = "INSERT INTO Joined VALUES(?, ?)";
+ event.sender +"')"; PreparedStatement prepStmt3 = connection.prepareStatement(sql);
prepStmt3.setObject(1, stored.identity);
prepStmt3.setObject(2, event.sender);
prepStmt3.execute();
break; break;
} }
connection.createStatement().executeUpdate(sql);
return stored; return stored;
} }
...@@ -66,22 +71,30 @@ public final class EventStorage ...@@ -66,22 +71,30 @@ public final class EventStorage
final Stored<Channel.Event> updated = current.newVersion(new_event); final Stored<Channel.Event> updated = current.newVersion(new_event);
if(current.version.equals(event.version)) { if(current.version.equals(event.version)) {
String sql = "UPDATE Event SET" + String sql = "UPDATE Event SET" +
" (version,time,type) =('" " (version,time,type) = (?, ?, ?) WHERE id=?";
+ updated.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ new_event.time + "','" prepStmt.setObject(1, updated.version);
+ new_event.type.code prepStmt.setObject(2, new_event.time);
+ "') WHERE id='"+ updated.identity + "'"; prepStmt.setObject(3, new_event.type.code);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(4, updated.identity);
prepStmt.execute();
switch (new_event.type) { switch (new_event.type) {
case message: case message:
sql = "UPDATE Message SET (sender,content)=('" + new_event.sender + "','" sql = "UPDATE Message SET (sender,content)= (?, ?) WHERE id=?";
+ new_event.message +"') WHERE id='"+ updated.identity + "'"; PreparedStatement prepStmt2 = connection.prepareStatement(sql);
prepStmt2.setObject(1, new_event.sender);
prepStmt2.setObject(2, new_event.message);
prepStmt2.setObject(3, updated.identity);
prepStmt2.execute();
break; break;
case join: case join:
sql = "UPDATE Joined SET (sender)=('" + new_event.sender +"') WHERE id='"+ updated.identity + "'"; sql = "UPDATE Joined SET (sender)= (?) WHERE id=?";
PreparedStatement prepStmt3 = connection.prepareStatement(sql);
prepStmt3.setObject(1, new_event.sender);
prepStmt3.setObject(2, updated.identity);
prepStmt3.execute();
break; break;
} }
connection.createStatement().executeUpdate(sql);
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -95,8 +108,10 @@ public final class EventStorage ...@@ -95,8 +108,10 @@ public final class EventStorage
SQLException { SQLException {
final Stored<Channel.Event> current = get(event.identity); final Stored<Channel.Event> current = get(event.identity);
if(current.version.equals(event.version)) { if(current.version.equals(event.version)) {
String sql = "DELETE FROM Event WHERE id ='" + event.identity + "'"; String sql = "DELETE FROM Event WHERE id =?";
connection.createStatement().executeUpdate(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1, event.identity);
prepStmt.execute();
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -105,9 +120,10 @@ public final class EventStorage ...@@ -105,9 +120,10 @@ public final class EventStorage
public Stored<Channel.Event> get(UUID id) public Stored<Channel.Event> get(UUID id)
throws DeletedException, throws DeletedException,
SQLException { SQLException {
final String sql = "SELECT version,time,type FROM Event WHERE id = '" + id.toString() + "'"; final String sql = "SELECT version,time,type FROM Event WHERE id = ?";
final Statement statement = connection.createStatement(); final PreparedStatement prepStmt = connection.prepareStatement(sql);
final ResultSet rs = statement.executeQuery(sql); prepStmt.setObject(1,id.toString());
final ResultSet rs = prepStmt.executeQuery();
if(rs.next()) { if(rs.next()) {
final UUID version = UUID.fromString(rs.getString("version")); final UUID version = UUID.fromString(rs.getString("version"));
...@@ -116,22 +132,26 @@ public final class EventStorage ...@@ -116,22 +132,26 @@ public final class EventStorage
final Instant time = final Instant time =
Instant.parse(rs.getString("time")); Instant.parse(rs.getString("time"));
final Statement mstatement = connection.createStatement(); //final Statement mstatement = connection.createStatement();
switch(type) { switch(type) {
case message: case message:
final String msql = "SELECT sender,content FROM Message WHERE id = '" + id.toString() + "'"; final String sql2 = "SELECT sender,content FROM Message WHERE id = ?";
final ResultSet mrs = mstatement.executeQuery(msql); PreparedStatement prepStmt2 = connection.prepareStatement(sql2);
mrs.next(); prepStmt2.setObject(1, id.toString());
final ResultSet rs2 = prepStmt2.executeQuery();
rs2.next();
return new Stored<Channel.Event>( return new Stored<Channel.Event>(
Channel.Event.createMessageEvent(time,mrs.getString("sender"),mrs.getString("content")), Channel.Event.createMessageEvent(time,rs2.getString("sender"),rs2.getString("content")),
id, id,
version); version);
case join: case join:
final String asql = "SELECT sender FROM Joined WHERE id = '" + id.toString() + "'"; final String sql3 = "SELECT sender FROM Joined WHERE id = ?";
final ResultSet ars = mstatement.executeQuery(asql); PreparedStatement prepStmt3 = connection.prepareStatement(sql3);
ars.next(); prepStmt3.setObject(1, id.toString());
final ResultSet rs3 = prepStmt3.executeQuery();
rs3.next();
return new Stored<Channel.Event>( return new Stored<Channel.Event>(
Channel.Event.createJoinEvent(time,ars.getString("sender")), Channel.Event.createJoinEvent(time,rs3.getString("sender")),
id, id,
version); version);
} }
......
...@@ -101,11 +101,10 @@ public class Handler extends AbstractHandler ...@@ -101,11 +101,10 @@ public class Handler extends AbstractHandler
(request.getParameter("username"))).get(); (request.getParameter("username"))).get();
String password = (new Maybe<String> String password = (new Maybe<String>
(request.getParameter("password"))).get(); (request.getParameter("password"))).get();
System.err.println("Registering user: \"" + username String passwordRepeat = (new Maybe<String>
+ "\" with password \"" + password + "\""); (request.getParameter("password_repeat"))).get();
inchat.register(username,password).forEach(sessionBuilder); inchat.register(username,password,passwordRepeat).forEach(sessionBuilder);
} catch (Maybe.NothingException e) { } catch (Maybe.NothingException e) {
// Not enough data suppied for login // Not enough data suppied for login
System.err.println("Broken usage of register"); System.err.println("Broken usage of register");
...@@ -142,7 +141,10 @@ public class Handler extends AbstractHandler ...@@ -142,7 +141,10 @@ public class Handler extends AbstractHandler
final Stored<Account> account = session.value.account; final Stored<Account> account = session.value.account;
// User is now logged in with a valid sesion. // User is now logged in with a valid sesion.
// We set the session cookie to keep the user logged in: // We set the session cookie to keep the user logged in:
response.addCookie(new Cookie("session",session.identity.toString())); final Cookie cookie = new Cookie("session",session.identity.toString());
cookie.setHttpOnly(true);
cookie.setSecure(true);
response.addCookie(cookie);
final PrintWriter out = response.getWriter(); final PrintWriter out = response.getWriter();
// Handle a logged in request. // Handle a logged in request.
...@@ -570,7 +572,7 @@ public class Handler extends AbstractHandler ...@@ -570,7 +572,7 @@ public class Handler extends AbstractHandler
= new SessionStorage(connection,accountStore); = new SessionStorage(connection,accountStore);
inchat = new InChat(userStore,channelStore,accountStore,sessionStore); inchat = new InChat(userStore,channelStore,accountStore,sessionStore);
try { try {
final Stored<Session> admin = inchat.register("admin","pa$$w0rd").get(); final Stored<Session> admin = inchat.register("admin","pa$$w0rd","pa$$w0rd").get();
final Stored<Channel> debug = inchat.createChannel(admin.value.account, "debug").get(); final Stored<Channel> debug = inchat.createChannel(admin.value.account, "debug").get();
(new Thread(){ public void run() { (new Thread(){ public void run() {
Mutable<Stored<Channel>> chan = new Mutable<Stored<Channel>>(debug); Mutable<Stored<Channel>> chan = new Mutable<Stored<Channel>>(debug);
......
...@@ -50,9 +50,11 @@ public class InChat { ...@@ -50,9 +50,11 @@ public class InChat {
// TODO: Here you can implement login. // TODO: Here you can implement login.
try { try {
final Stored<Account> account = accountStore.lookup(username); final Stored<Account> account = accountStore.lookup(username);
final Stored<Session> session = if (account.value.checkPassword(password)) {
sessionStore.save(new Session(account, Instant.now().plusSeconds(60*60*24))); final Stored<Session> session =
return Maybe.just(session); sessionStore.save(new Session(account, Instant.now().plusSeconds(60 * 60 * 24)));
return Maybe.just(session);
}
} catch (SQLException e) { } catch (SQLException e) {
} catch (DeletedException e) { } catch (DeletedException e) {
} }
...@@ -62,15 +64,31 @@ public class InChat { ...@@ -62,15 +64,31 @@ public class InChat {
/** /**
* Register a new user. * Register a new user.
*/ */
public Maybe<Stored<Session>> register(String username, String password) { public Maybe<Stored<Session>> register(String username, String password, String passwordRepeat) {
try { try {
try {
accountStore.lookup(username);
System.err.println("ERROR: User already exists");
return Maybe.nothing();
} catch (DeletedException e) {}
if (!Password.validPassword(password)) {
System.err.println("ERROR: Unsafe password");
return Maybe.nothing();
}
if (!password.equals(passwordRepeat)) {
System.err.println("ERROR: Failed to repeat password");
return Maybe.nothing();
}
final Stored<User> user = final Stored<User> user =
userStore.save(User.create(username)); userStore.save(User.create(username));
final Stored<Account> account = final Stored<Account> account =
accountStore.save(Account.create(user, password)); accountStore.save(Account.create(user, password));
final Stored<Session> session = final Stored<Session> session =
sessionStore.save(new Session(account, Instant.now().plusSeconds(60*60*24))); sessionStore.save(new Session(account, Instant.now().plusSeconds(60 * 60 * 24)));
return Maybe.just(session); System.err.println("Registering user: \"" + username
+ "\" with password \"" + password +"\"");
return Maybe.just(session);
} catch (SQLException e) { } catch (SQLException e) {
return Maybe.nothing(); return Maybe.nothing();
} }
......
...@@ -8,9 +8,10 @@ public final class Password { ...@@ -8,9 +8,10 @@ public final class Password {
this.password = password; this.password = password;
} }
public boolean validPassword (String password) {
public static boolean validPassword(String password) {
int hPLength = password.length(); int hPLength = password.length();
if (hPLength >= 6 && hPLength <= 30) { if (hPLength >= 8 && hPLength <= 64) {
int digits, upperCases, lowerCases; int digits, upperCases, lowerCases;
digits = upperCases = lowerCases = 0; digits = upperCases = lowerCases = 0;
for (char c : password.toCharArray()) { for (char c : password.toCharArray()) {
...@@ -27,6 +28,7 @@ public final class Password { ...@@ -27,6 +28,7 @@ public final class Password {
if (digits != 0 && upperCases != 0 && lowerCases != 0) { if (digits != 0 && upperCases != 0 && lowerCases != 0) {
return true; return true;
} }
System.out.println("Password is invalid");
} }
return false; return false;
} }
......
package inf226.inchat; package inf226.inchat;
import java.sql.Connection; import java.sql.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
...@@ -32,11 +29,13 @@ public final class SessionStorage ...@@ -32,11 +29,13 @@ public final class SessionStorage
throws SQLException { throws SQLException {
final Stored<Session> stored = new Stored<Session>(session); final Stored<Session> stored = new Stored<Session>(session);
String sql = "INSERT INTO Session VALUES('" + stored.identity + "','" String sql = "INSERT INTO Session VALUES(?, ?, ?, ?)";
+ stored.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ session.account.identity + "','" prepStmt.setObject(1, stored.identity);
+ session.expiry.toString() + "')"; prepStmt.setObject(2, stored.version);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(3, session.account.identity);
prepStmt.setObject(4, session.expiry.toString());
prepStmt.execute();
return stored; return stored;
} }
...@@ -50,12 +49,13 @@ public final class SessionStorage ...@@ -50,12 +49,13 @@ public final class SessionStorage
final Stored<Session> updated = current.newVersion(new_session); final Stored<Session> updated = current.newVersion(new_session);
if(current.version.equals(session.version)) { if(current.version.equals(session.version)) {
String sql = "UPDATE Session SET" + String sql = "UPDATE Session SET" +
" (version,account,expiry) =('" " (version,account,expiry) = (?, ?, ?) WHERE id=?";
+ updated.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ new_session.account.identity + "','" prepStmt.setObject(1, updated.version);
+ new_session.expiry.toString() prepStmt.setObject(2, new_session.account.identity);
+ "') WHERE id='"+ updated.identity + "'"; prepStmt.setObject(3, new_session.expiry.toString());
connection.createStatement().executeUpdate(sql); prepStmt.setObject(4, updated.identity);
prepStmt.execute();
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -69,8 +69,10 @@ public final class SessionStorage ...@@ -69,8 +69,10 @@ public final class SessionStorage
SQLException { SQLException {
final Stored<Session> current = get(session.identity); final Stored<Session> current = get(session.identity);
if(current.version.equals(session.version)) { if(current.version.equals(session.version)) {
String sql = "DELETE FROM Session WHERE id ='" + session.identity + "'"; String sql = "DELETE FROM Session WHERE id = ?";
connection.createStatement().executeUpdate(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1,session.identity);
prepStmt.execute();
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -79,9 +81,10 @@ public final class SessionStorage ...@@ -79,9 +81,10 @@ public final class SessionStorage
public Stored<Session> get(UUID id) public Stored<Session> get(UUID id)
throws DeletedException, throws DeletedException,
SQLException { SQLException {
final String sql = "SELECT version,account,expiry FROM Session WHERE id = '" + id.toString() + "'"; final String sql = "SELECT version,account,expiry FROM Session WHERE id = ?";
final Statement statement = connection.createStatement(); final PreparedStatement prepStmt = connection.prepareStatement(sql);
final ResultSet rs = statement.executeQuery(sql); prepStmt.setObject(1, id.toString());
final ResultSet rs = prepStmt.executeQuery();
if(rs.next()) { if(rs.next()) {
final UUID version = UUID.fromString(rs.getString("version")); final UUID version = UUID.fromString(rs.getString("version"));
......
package inf226.inchat; package inf226.inchat;
import java.sql.Connection; import java.sql.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
...@@ -31,11 +28,13 @@ public final class UserStorage ...@@ -31,11 +28,13 @@ public final class UserStorage
public Stored<User> save(User user) public Stored<User> save(User user)
throws SQLException { throws SQLException {
final Stored<User> stored = new Stored<User>(user); final Stored<User> stored = new Stored<User>(user);
String sql = "INSERT INTO User VALUES('" + stored.identity + "','" String sql = "INSERT INTO User VALUES(?, ?, ?, ?)";
+ stored.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ user.name + "','" prepStmt.setObject(1, stored.identity);
+ user.joined.toString() + "')"; prepStmt.setObject(2, stored.version);
connection.createStatement().executeUpdate(sql); prepStmt.setObject(3, user.name);
prepStmt.setObject(4, user.joined.toString());
prepStmt.execute();
return stored; return stored;
} }
...@@ -49,12 +48,13 @@ public final class UserStorage ...@@ -49,12 +48,13 @@ public final class UserStorage
final Stored<User> updated = current.newVersion(new_user); final Stored<User> updated = current.newVersion(new_user);
if(current.version.equals(user.version)) { if(current.version.equals(user.version)) {
String sql = "UPDATE User SET" + String sql = "UPDATE User SET" +
" (version,name,joined) =('" " (version,name,joined) = (?, ?, ?, ?) WHERE id=?";
+ updated.version + "','" PreparedStatement prepStmt = connection.prepareStatement(sql);
+ new_user.name + "','" prepStmt.setObject(1, updated.version);
+ new_user.joined.toString() prepStmt.setObject(2, new_user.name);
+ "') WHERE id='"+ updated.identity + "'"; prepStmt.setObject(3, new_user.joined.toString());
connection.createStatement().executeUpdate(sql); prepStmt.setObject(4, updated.identity);
prepStmt.execute();
} else { } else {
throw new UpdatedException(current); throw new UpdatedException(current);
} }
...@@ -66,21 +66,25 @@ public final class UserStorage ...@@ -66,21 +66,25 @@ public final class UserStorage
throws UpdatedException, throws UpdatedException,
DeletedException, DeletedException,
SQLException { SQLException {
final Stored<User> current = get(user.identity); final Stored<User> current = get(user.identity);
if(current.version.equals(user.version)) { if(current.version.equals(user.version)) {
String sql = "DELETE FROM User WHERE id ='" + user.identity + "'"; String sql = "DELETE FROM User WHERE id = ?";
connection.createStatement().executeUpdate(sql); PreparedStatement prepStmt = connection.prepareStatement(sql);
} else { prepStmt.setObject(1, user.identity);
throw new UpdatedException(current); prepStmt.execute();
} } else {
throw new UpdatedException(current);
}
} }
@Override @Override
public Stored<User> get(UUID id) public Stored<User> get(UUID id)
throws DeletedException, throws DeletedException,
SQLException { SQLException {
final String sql = "SELECT version,name,joined FROM User WHERE id = '" + id.toString() + "'"; final String sql = "SELECT version,name,joined FROM User WHERE id = ?";
final Statement statement = connection.createStatement(); final PreparedStatement prepStmt = connection.prepareStatement(sql);
final ResultSet rs = statement.executeQuery(sql); prepStmt.setObject(1, id.toString());
final ResultSet rs = prepStmt.executeQuery();
if(rs.next()) { if(rs.next()) {
final UUID version = final UUID version =
...@@ -97,11 +101,12 @@ public final class UserStorage ...@@ -97,11 +101,12 @@ public final class UserStorage
/** /**
* Look up a user by their username; * Look up a user by their username;
**/ **/
public Maybe<Stored<User>> lookup(String name) { public Maybe<Stored<User>> lookup(String name) throws SQLException {
final String sql = "SELECT id FROM User WHERE name = '" + name + "'"; final String sql = "SELECT id FROM User WHERE name = ?";
final PreparedStatement prepStmt = connection.prepareStatement(sql);
prepStmt.setObject(1, name);
try{ try{
final Statement statement = connection.createStatement(); final ResultSet rs = prepStmt.executeQuery();
final ResultSet rs = statement.executeQuery(sql);
if(rs.next()) if(rs.next())
return Maybe.just( return Maybe.just(
get(UUID.fromString(rs.getString("id")))); get(UUID.fromString(rs.getString("id"))));
......
...@@ -32,8 +32,8 @@ public class InchatTest{ ...@@ -32,8 +32,8 @@ public class InchatTest{
SessionStorage sessionStore SessionStorage sessionStore
= new SessionStorage(connection,accountStore); = new SessionStorage(connection,accountStore);
InChat inchat = new InChat(userStore,channelStore,accountStore,sessionStore); InChat inchat = new InChat(userStore,channelStore,accountStore,sessionStore);
Stored<Session> aliceSession = inchat.register("Alice","badpassword").get(); Stored<Session> aliceSession = inchat.register("Alice","badpassword","badpassword").get();
inchat.register("Bob","worse").get(); inchat.register("Bob","worse","worse").get();
Stored<Session> bobSession = inchat.login("Bob","worse").get(); Stored<Session> bobSession = inchat.login("Bob","worse").get();
Stored<Channel> channel = inchat.createChannel(aliceSession.value.account,"Awesome").get(); Stored<Channel> channel = inchat.createChannel(aliceSession.value.account,"Awesome").get();
inchat.postMessage(aliceSession.value.account,channel, "Test message.").get(); inchat.postMessage(aliceSession.value.account,channel, "Test message.").get();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment