Commit fd85d088 authored by Robert Czechowski's avatar Robert Czechowski
Browse files

Use csrf token for contest start, match naming of csrf tokens

parent 3727cc51
Pipeline #198 passed with stage
in 20 minutes and 28 seconds
...@@ -206,6 +206,7 @@ pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token ...@@ -206,6 +206,7 @@ pub fn show_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token
data.insert("firstname".to_string(), to_json(&session.firstname)); data.insert("firstname".to_string(), to_json(&session.firstname));
data.insert("lastname".to_string(), to_json(&session.lastname)); data.insert("lastname".to_string(), to_json(&session.lastname));
data.insert("teacher".to_string(), to_json(&session.is_teacher)); data.insert("teacher".to_string(), to_json(&session.is_teacher));
data.insert("csrf_token".to_string(), to_json(&session.csrf_token));
} }
if c.duration == 0 { if c.duration == 0 {
data.insert("can_start".to_string(), to_json(&true)); data.insert("can_start".to_string(), to_json(&true));
...@@ -299,16 +300,21 @@ pub fn show_contest_results<T: MedalConnection>(conn: &T, contest_id: i32, sessi ...@@ -299,16 +300,21 @@ pub fn show_contest_results<T: MedalConnection>(conn: &T, contest_id: i32, sessi
} }
//TODO: use csrf_token //TODO: use csrf_token
pub fn start_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token: &str, _csrf_token: &str) pub fn start_contest<T: MedalConnection>(conn: &T, contest_id: i32, session_token: &str, csrf_token: &str)
-> MedalResult<()> { -> MedalResult<()> {
//TODO: use data or remove? // TODO: Should check if logged in or anonymous!
let _data = json_val::Map::new(); // TODO: Is _or_new the right semantic?
let session = conn.get_session_or_new(&session_token);
let _ = conn.get_session_or_new(&session_token); //.ensure_logged_in()
//.ok_or(MedalError::AccessDenied)?;
if session.is_logged_in() && session.csrf_token != csrf_token {
return Err(MedalError::CsrfCheckFailed);
}
match conn.new_participation(&session_token, contest_id) { match conn.new_participation(&session_token, contest_id) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
_ => Err(MedalError::AccessDenied), _ => Err(MedalError::AccessDenied), // Contest already started TODO: Maybe redirect to page with hint
} }
} }
...@@ -450,7 +456,7 @@ pub fn show_task<T: MedalConnection>(conn: &T, task_id: i32, session_token: &str ...@@ -450,7 +456,7 @@ pub fn show_task<T: MedalConnection>(conn: &T, task_id: i32, session_token: &str
data.insert("contestname".to_string(), to_json(&c.name)); data.insert("contestname".to_string(), to_json(&c.name));
data.insert("name".to_string(), to_json(&tg.name)); data.insert("name".to_string(), to_json(&tg.name));
data.insert("taskid".to_string(), to_json(&task_id)); data.insert("taskid".to_string(), to_json(&task_id));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token)); data.insert("csrf_token".to_string(), to_json(&session.csrf_token));
data.insert("taskpath".to_string(), to_json(&taskpath)); data.insert("taskpath".to_string(), to_json(&taskpath));
data.insert("contestid".to_string(), to_json(&c.id)); data.insert("contestid".to_string(), to_json(&c.id));
data.insert("seconds_left".to_string(), to_json(&left_secs)); data.insert("seconds_left".to_string(), to_json(&left_secs));
...@@ -485,7 +491,7 @@ pub fn show_groups<T: MedalConnection>(conn: &T, session_token: &str) -> MedalVa ...@@ -485,7 +491,7 @@ pub fn show_groups<T: MedalConnection>(conn: &T, session_token: &str) -> MedalVa
code: g.groupcode.clone() }) code: g.groupcode.clone() })
.collect(); .collect();
data.insert("group".to_string(), to_json(&v)); data.insert("group".to_string(), to_json(&v));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token)); data.insert("csrf_token".to_string(), to_json(&session.csrf_token));
Ok(("groups".to_string(), data)) Ok(("groups".to_string(), data))
} }
...@@ -542,7 +548,7 @@ pub fn add_group<T: MedalConnection>(conn: &T, session_token: &str, csrf_token: ...@@ -542,7 +548,7 @@ pub fn add_group<T: MedalConnection>(conn: &T, session_token: &str, csrf_token:
.ok_or(MedalError::AccessDenied)?; .ok_or(MedalError::AccessDenied)?;
if session.csrf_token != csrf_token { if session.csrf_token != csrf_token {
return Err(MedalError::AccessDenied); // CsrfError return Err(MedalError::CsrfCheckFailed);
} }
let group_code: String = Some('g').into_iter() let group_code: String = Some('g').into_iter()
...@@ -553,7 +559,7 @@ pub fn add_group<T: MedalConnection>(conn: &T, session_token: &str, csrf_token: ...@@ -553,7 +559,7 @@ pub fn add_group<T: MedalConnection>(conn: &T, session_token: &str, csrf_token:
}) })
.take(7) .take(7)
.collect(); .collect();
// todo: check for collisions // TODO: check for collisions
let mut group = let mut group =
Group { id: None, name: name, groupcode: group_code, tag: tag, admin: session.id, members: Vec::new() }; Group { id: None, name: name, groupcode: group_code, tag: tag, admin: session.id, members: Vec::new() };
...@@ -598,7 +604,7 @@ pub fn show_profile<T: MedalConnection>(conn: &T, session_token: &str, user_id: ...@@ -598,7 +604,7 @@ pub fn show_profile<T: MedalConnection>(conn: &T, session_token: &str, user_id:
} }
data.insert("ownprofile".into(), to_json(&true)); data.insert("ownprofile".into(), to_json(&true));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token)); data.insert("csrf_token".to_string(), to_json(&session.csrf_token));
if let Some(query) = query_string { if let Some(query) = query_string {
if query.starts_with("status=") { if query.starts_with("status=") {
...@@ -632,7 +638,7 @@ pub fn show_profile<T: MedalConnection>(conn: &T, session_token: &str, user_id: ...@@ -632,7 +638,7 @@ pub fn show_profile<T: MedalConnection>(conn: &T, session_token: &str, user_id:
data.insert("ownprofile".into(), to_json(&false)); data.insert("ownprofile".into(), to_json(&false));
data.insert("csrftoken".to_string(), to_json(&session.csrf_token)); data.insert("csrf_token".to_string(), to_json(&session.csrf_token));
if let Some(query) = query_string { if let Some(query) = query_string {
if query.starts_with("status=") { if query.starts_with("status=") {
......
...@@ -482,13 +482,13 @@ mod tests { ...@@ -482,13 +482,13 @@ mod tests {
let content = resp.text().unwrap(); let content = resp.text().unwrap();
assert!(content.contains("Gruppe anlegen")); assert!(content.contains("Gruppe anlegen"));
let params = [("name", "WrongGroupname"), ("tag", "WrongMarker"), ("csrf", "76CfTPJaoz")]; let params = [("name", "WrongGroupname"), ("tag", "WrongMarker"), ("csrf_token", "76CfTPJaoz")];
let resp = client.post("http://localhost:8084/group/").form(&params).send().unwrap(); let resp = client.post("http://localhost:8084/group/").form(&params).send().unwrap();
assert_eq!(resp.status(), StatusCode::FORBIDDEN); assert_eq!(resp.status(), StatusCode::FORBIDDEN);
let pos = content.find("type=\"hidden\" name=\"csrf\" value=\"").expect("CSRF-Token not found"); let pos = content.find("type=\"hidden\" name=\"csrf_token\" value=\"").expect("CSRF-Token not found");
let csrf = &content[pos + 33..pos + 43]; let csrf = &content[pos + 39..pos + 49];
let params = [("name", "Groupname"), ("tag", "Marker"), ("csrf", csrf)]; let params = [("name", "Groupname"), ("tag", "Marker"), ("csrf_token", csrf)];
let resp = client.post("http://localhost:8084/group/").form(&params).send().unwrap(); let resp = client.post("http://localhost:8084/group/").form(&params).send().unwrap();
assert_eq!(resp.status(), StatusCode::FOUND); assert_eq!(resp.status(), StatusCode::FOUND);
...@@ -554,7 +554,6 @@ mod tests { ...@@ -554,7 +554,6 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let content = resp.text().unwrap(); let content = resp.text().unwrap();
println!("{}", content);
assert!(content.contains("PublicContestName")); assert!(content.contains("PublicContestName"));
assert!(content.contains("InfiniteContestName")); assert!(content.contains("InfiniteContestName"));
//assert!(content.contains("PrivateContestName")); //assert!(content.contains("PrivateContestName"));
...@@ -566,21 +565,19 @@ mod tests { ...@@ -566,21 +565,19 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let content = resp.text().unwrap(); let content = resp.text().unwrap();
println!("{}", content);
assert!(content.contains("PublicContestName")); assert!(content.contains("PublicContestName"));
assert!(!content.contains("InfiniteContestName")); assert!(!content.contains("InfiniteContestName"));
assert!(!content.contains("PrivateContestName")); assert!(!content.contains("PrivateContestName"));
assert!(!content.contains("WrongContestName")); assert!(!content.contains("WrongContestName"));
assert!(!content.contains("RenamedContestName")); assert!(!content.contains("RenamedContestName"));
let params = [("csrftoken", "76CfTPJaoz")]; let params = [("csrf_token", "76CfTPJaoz")];
let resp = client.post("http://localhost:8085/contest/1").form(&params).send().unwrap(); let resp = client.post("http://localhost:8085/contest/1").form(&params).send().unwrap();
assert_eq!(resp.status(), StatusCode::FORBIDDEN); assert_eq!(resp.status(), StatusCode::FORBIDDEN);
let pos = content.find("type=\"hidden\" name=\"csrftoken\" value=\"").expect("CSRF-Token not found"); let pos = content.find("type=\"hidden\" name=\"csrf_token\" value=\"").expect("CSRF-Token not found");
let csrf = &content[pos + 38..pos + 48]; let csrf = &content[pos + 39..pos + 49];
println!("==={}===", csrf); let params = [("csrf_token", csrf)];
let params = [("csrftoken", csrf)];
let resp = client.post("http://localhost:8085/contest/1").form(&params).send().unwrap(); let resp = client.post("http://localhost:8085/contest/1").form(&params).send().unwrap();
assert_eq!(resp.status(), StatusCode::FOUND); assert_eq!(resp.status(), StatusCode::FOUND);
}) })
......
...@@ -352,7 +352,7 @@ fn contest_post<C>(req: &mut Request) -> IronResult<Response> ...@@ -352,7 +352,7 @@ fn contest_post<C>(req: &mut Request) -> IronResult<Response>
let csrf_token = { let csrf_token = {
let formdata = itry!(req.get_ref::<UrlEncodedBody>()); let formdata = itry!(req.get_ref::<UrlEncodedBody>());
iexpect!(formdata.get("csrftoken"))[0].to_owned() iexpect!(formdata.get("csrf_token"))[0].to_owned()
}; };
// TODO: Was mit dem Result? // TODO: Was mit dem Result?
...@@ -470,7 +470,7 @@ fn submission_post<C>(req: &mut Request) -> IronResult<Response> ...@@ -470,7 +470,7 @@ fn submission_post<C>(req: &mut Request) -> IronResult<Response>
let session_token = req.expect_session_token()?; let session_token = req.expect_session_token()?;
let (csrf_token, data, grade, subtask) = { let (csrf_token, data, grade, subtask) = {
let formdata = iexpect!(req.get_ref::<UrlEncodedBody>().ok()); let formdata = iexpect!(req.get_ref::<UrlEncodedBody>().ok());
(iexpect!(formdata.get("csrf"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(), (iexpect!(formdata.get("csrf_token"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(),
iexpect!(formdata.get("data"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(), iexpect!(formdata.get("data"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(),
iexpect!(formdata.get("grade").unwrap_or(&vec!["0".to_owned()])[0].parse::<i32>().ok(),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request"))), iexpect!(formdata.get("grade").unwrap_or(&vec!["0".to_owned()])[0].parse::<i32>().ok(),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request"))),
formdata.get("subtask").map(|x| x[0].to_owned()), formdata.get("subtask").map(|x| x[0].to_owned()),
...@@ -540,16 +540,14 @@ fn new_group<C>(req: &mut Request) -> IronResult<Response> ...@@ -540,16 +540,14 @@ fn new_group<C>(req: &mut Request) -> IronResult<Response>
where C: MedalConnection + std::marker::Send + 'static { where C: MedalConnection + std::marker::Send + 'static {
let session_token = req.require_session_token()?; let session_token = req.require_session_token()?;
let (csrf, name, tag) = { let (csrf_token, name, tag) = {
let formdata = iexpect!(req.get_ref::<UrlEncodedBody>().ok()); let formdata = iexpect!(req.get_ref::<UrlEncodedBody>().ok());
(iexpect!(formdata.get("csrf"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(), (iexpect!(formdata.get("csrf_token"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(),
iexpect!(formdata.get("name"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(), iexpect!(formdata.get("name"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned(),
iexpect!(formdata.get("tag"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned()) iexpect!(formdata.get("tag"),(status::BadRequest, mime!(Text/Html), format!("400 Bad Request")))[0].to_owned())
}; };
println!("{}", csrf);
println!("{}", name);
let group_id = with_conn![functions::add_group, C, req, &session_token, &csrf, name, tag].aug(req)?; let group_id = with_conn![functions::add_group, C, req, &session_token, &csrf_token, name, tag].aug(req)?;
Ok(Response::with((status::Found, Redirect(url_for!(req, "group", "groupid" => format!("{}",group_id)))))) Ok(Response::with((status::Found, Redirect(url_for!(req, "group", "groupid" => format!("{}",group_id))))))
} }
...@@ -571,7 +569,7 @@ fn profile_post<C>(req: &mut Request) -> IronResult<Response> ...@@ -571,7 +569,7 @@ fn profile_post<C>(req: &mut Request) -> IronResult<Response>
let session_token = req.expect_session_token()?; let session_token = req.expect_session_token()?;
let (csrf_token, firstname, lastname, street, zip, city, pwd, pwd_repeat, grade) = { let (csrf_token, firstname, lastname, street, zip, city, pwd, pwd_repeat, grade) = {
let formdata = itry!(req.get_ref::<UrlEncodedBody>()); let formdata = itry!(req.get_ref::<UrlEncodedBody>());
(iexpect!(formdata.get("csrftoken"))[0].to_owned(), (iexpect!(formdata.get("csrf_token"))[0].to_owned(),
iexpect!(formdata.get("firstname"))[0].to_owned(), iexpect!(formdata.get("firstname"))[0].to_owned(),
iexpect!(formdata.get("lastname"))[0].to_owned(), iexpect!(formdata.get("lastname"))[0].to_owned(),
formdata.get("street").map(|x| x[0].to_owned()), formdata.get("street").map(|x| x[0].to_owned()),
...@@ -623,7 +621,7 @@ fn user_post<C>(req: &mut Request) -> IronResult<Response> ...@@ -623,7 +621,7 @@ fn user_post<C>(req: &mut Request) -> IronResult<Response>
let session_token = req.expect_session_token()?; let session_token = req.expect_session_token()?;
let (csrf_token, firstname, lastname, street, zip, city, pwd, pwd_repeat, grade) = { let (csrf_token, firstname, lastname, street, zip, city, pwd, pwd_repeat, grade) = {
let formdata = itry!(req.get_ref::<UrlEncodedBody>()); let formdata = itry!(req.get_ref::<UrlEncodedBody>());
(iexpect!(formdata.get("csrftoken"))[0].to_owned(), (iexpect!(formdata.get("csrf_token"))[0].to_owned(),
iexpect!(formdata.get("firstname"))[0].to_owned(), iexpect!(formdata.get("firstname"))[0].to_owned(),
iexpect!(formdata.get("lastname"))[0].to_owned(), iexpect!(formdata.get("lastname"))[0].to_owned(),
formdata.get("street").map(|x| x[0].to_owned()), formdata.get("street").map(|x| x[0].to_owned()),
......
...@@ -28,7 +28,7 @@ window.save_task_object = function (object, callback) { ...@@ -28,7 +28,7 @@ window.save_task_object = function (object, callback) {
if (!callback) callback = function(data){}; // is this necessary? if (!callback) callback = function(data){}; // is this necessary?
var params = { var params = {
csrf: window.hashdict["csrftoken"], csrf_token: window.hashdict["csrftoken"],
data: JSON.stringify(object) data: JSON.stringify(object)
} }
$.post("/save/" + window.hashdict["taskid"], params, callback, "json").fail(function(){ $.post("/save/" + window.hashdict["taskid"], params, callback, "json").fail(function(){
...@@ -54,7 +54,7 @@ window.save_subtask_object = function (subtaskname, object, callback) { ...@@ -54,7 +54,7 @@ window.save_subtask_object = function (subtaskname, object, callback) {
var params = { var params = {
subtask: subtaskname, subtask: subtaskname,
csrf: window.hashdict["csrftoken"], csrf_token: window.hashdict["csrftoken"],
data: JSON.stringify(object) data: JSON.stringify(object)
} }
$.post("/save/" + window.hashdict["taskid"], params, callback, "json").fail(function(){ $.post("/save/" + window.hashdict["taskid"], params, callback, "json").fail(function(){
......
...@@ -29,7 +29,7 @@ window.save_task_object = function (object, grade, callback) { ...@@ -29,7 +29,7 @@ window.save_task_object = function (object, grade, callback) {
if (!callback) callback = function(data){}; if (!callback) callback = function(data){};
var params = { var params = {
csrf: window.hashdict["csrftoken"], csrf_token: window.hashdict["csrftoken"],
data: JSON.stringify(object), data: JSON.stringify(object),
grade: JSON.stringify(grade) grade: JSON.stringify(grade)
} }
...@@ -57,7 +57,7 @@ window.save_subtask_object = function (subtaskname, object, grade, callback) { ...@@ -57,7 +57,7 @@ window.save_subtask_object = function (subtaskname, object, grade, callback) {
var params = { var params = {
subtask: subtaskname, subtask: subtaskname,
csrf: window.hashdict["csrftoken"], csrf_token: window.hashdict["csrftoken"],
data: JSON.stringify(object), data: JSON.stringify(object),
grade: JSON.stringify(grade) grade: JSON.stringify(grade)
} }
......
...@@ -39,7 +39,7 @@ Punktestand: {{ total_points }} ★ / {{ max_total_points }} ☆ &nbsp; ({{ rela ...@@ -39,7 +39,7 @@ Punktestand: {{ total_points }} ★ / {{ max_total_points }} ☆ &nbsp; ({{ rela
{{#if can_start}} {{#if can_start}}
<p> <p>
<form action="" method="post"> <form action="" method="post">
<input type="hidden" name="csrftoken" value="{{csrftoken}}"> <input type="hidden" name="csrf_token" value="{{csrf_token}}">
<input type="submit" value="Jetzt starten!"> <input type="submit" value="Jetzt starten!">
</form> </form>
</p> </p>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<input name="name"> <input name="name">
Marker: Marker:
<input name="tag" placeholder="optional"> <input name="tag" placeholder="optional">
<input type="hidden" name="csrf" value="{{csrftoken}}"> <input type="hidden" name="csrf_token" value="{{csrf_token}}">
<input type="submit" value="Neue Gruppe anlegen"> <input type="submit" value="Neue Gruppe anlegen">
</form> </form>
</p> </p>
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
</tr> </tr>
{{/if}} {{/if}}
<tr> <tr>
<td></td><td><input type="hidden" name="csrftoken" value="{{ csrftoken }}"><input type="submit" value="Speichern"></td> <td></td><td><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><input type="submit" value="Speichern"></td>
</tr> </tr>
</table> </table>
</form> </form>
......
...@@ -185,7 +185,7 @@ else { ...@@ -185,7 +185,7 @@ else {
</div> </div>
</div> </div>
<iframe src="/{{taskpath}}#taskid={{taskid}}&csrftoken={{csrftoken}}" name="taskframe">Leider unterstützt ihr Browser keine Frames. Sie können die Aufgabe auch manuell aufrufen: <a href="/{{taskpath}}#taskid={{taskid}}&csrftoken={{csrftoken}}">Aufgabe manuell bearbeiten</a>.</iframe> <iframe src="/{{taskpath}}#taskid={{taskid}}&csrftoken={{csrf_token}}" name="taskframe">Leider unterstützt ihr Browser keine Frames. Sie können die Aufgabe auch manuell aufrufen: <a href="/{{taskpath}}#taskid={{taskid}}&csrftoken={{csrf_token}}">Aufgabe manuell bearbeiten</a>.</iframe>
</body></html> </body></html>
......
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
{{#if can_start}} {{#if can_start}}
<p> <p>
<form action="" method="post"> <form action="" method="post">
<input type="hidden" name="csrftoken" value="{{csrftoken}}"> <input type="hidden" name="csrf_token" value="{{csrf_token}}">
<input class="button is-warning" type="submit" value="⏱ &nbsp; Jetzt starten!"> <input class="button is-warning" type="submit" value="⏱ &nbsp; Jetzt starten!">
</form> </form>
</p> </p>
......
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