1
+ from functools import wraps
2
+
1
3
from sqlalchemy import func
2
4
3
5
from flask_httpauth import HTTPBasicAuth
9
11
from db .database import db_session
10
12
from db .models import TeamScore , AttendingTeam , Event , Team , Submission , Flag , Challenge , Member , User , Catering , Food , \
11
13
Tick , TeamServiceState , TeamScriptsRunStatus , Script , ScriptPayload , ScriptRun
14
+ from app .api import verify_flag
12
15
13
16
from hashlib import sha512
14
17
15
18
import redis
16
- import requests
19
+ import ipaddress
17
20
18
21
web = Blueprint ('web' , __name__ ,
19
22
template_folder = 'templates' )
22
25
redis_client = redis .StrictRedis (host = 'localhost' , port = 6379 , db = 0 )
23
26
24
27
25
- def get_attacking_team ():
26
- team = Team .query .filter (func .lower (Team .team_name ) == func .lower (get_real_username (auth .username ()))).first ()
27
- event = Event .query .order_by (Event .id .desc ()).first ()
28
- attacking_team = AttendingTeam .query .filter_by (team = team , event = event ).first ()
29
- return attacking_team
30
-
31
-
32
- @auth .get_password
33
- def get_password (username ):
34
- event = Event .query .order_by (Event .id .desc ()).first ()
35
-
36
- try_split = username .rsplit ("-" , 1 )
37
- if len (try_split ) == 2 :
38
- if try_split [1 ] == "admin" :
39
- real_username = try_split [0 ]
40
- team = Team .query .filter (func .lower (Team .team_name ) == func .lower (real_username )).first ()
41
-
42
- if AttendingTeam .query .filter_by (team = team , event = event ).first ():
43
- db_session .remove ()
44
- return current_app .config ["ADMIN_CREDENTIALS" ][1 ]
45
- else :
46
- db_session .remove ()
47
- return None
48
- team = Team .query .filter (func .lower (Team .team_name ) == func .lower (username )).first ()
49
-
50
- # only attending teams can login
51
- if not AttendingTeam .query .filter_by (team = team , event = event ).first ():
52
- return None
53
-
54
- db_session .remove ()
55
- return team .password
28
+ def get_team_num (ip ):
29
+ request .environ .get ('HTTP_X_REAL_IP' , request .remote_addr )
56
30
31
+ def find_team (f ):
32
+ @wraps (f )
33
+ def decorated_function (* args , ** kwargs ):
34
+ ip = request .environ .get ('HTTP_X_REAL_IP' , request .remote_addr )
35
+ try :
36
+ a , b , c , d = [int (x ) for x in ip .split ("." )]
37
+ assert a == 10
38
+ assert b in [40 , 41 , 42 , 43 ]
39
+ event = Event .query .order_by (Event .id .desc ()).first ()
40
+ ateam = AttendingTeam .query .filter_by (subnet = c , event = event ).one_or_none ()
41
+ team = ateam .team if ateam is not None else None
42
+ if not team :
43
+ return redirect (url_for ('web.error' ))
44
+ kwargs ['team' ] = team
45
+ kwargs ['ateam' ] = ateam
46
+ except Exception as e :
47
+ return redirect (url_for ('error' ))
48
+ return f (* args , ** kwargs )
49
+ return decorated_function
57
50
58
- @auth .hash_password
59
- def hash_password (username , password ):
60
- event = Event .query .order_by (Event .id .desc ()).first ()
61
51
62
- try_split = username .rsplit ("-" , 1 )
63
- if len (try_split ) == 2 :
64
- if try_split [1 ] == "admin" :
65
- real_username = try_split [0 ]
66
- team = Team .query .filter (func .lower (Team .team_name ) == func .lower (real_username )).first ()
52
+ @web .route ("/error" )
53
+ def error ():
54
+ return "ERROR, are you connected to VPN or are in the correct subnet?"
67
55
68
- if AttendingTeam .query .filter_by (team = team , event = event ).first ():
69
- db_session .remove ()
70
- return current_app .config ["ADMIN_CREDENTIALS" ][1 ]
71
- else :
72
- db_session .remove ()
73
- return None
74
-
75
- team = Team .query .filter (func .lower (Team .team_name ) == func .lower (username )).first ()
76
- if not AttendingTeam .query .filter_by (team = team , event = event ).first ():
77
- return None
78
-
79
- db_session .remove ()
80
- pw_salt = "{}{}" .format (password , team .password_salt )
81
- return sha512 (pw_salt .encode ("utf8" )).hexdigest ()
82
-
83
-
84
- def get_real_username (username ):
85
- """allows admins to login as TEAMNAME-admin instead of TEAMNAME but with admin password"""
86
- try_split = username .rsplit ("-" , 1 )
87
- if len (try_split ) == 2 :
88
- if try_split [1 ] == "admin" :
89
- real_username = try_split [0 ]
90
- return real_username
91
-
92
- return username
93
56
94
57
95
58
@web .route ("/" )
96
- @auth . login_required
97
- def index ():
59
+ @find_team
60
+ def index (team = None , ateam = None ):
98
61
return render_template ('index.html' )
99
62
100
63
101
64
@web .route ('/config' )
102
- @auth .login_required
103
- def get_config ():
104
- return jsonify ({'ctf_name' : current_app .config ["CTF_NAME" ], 'team_name' : get_real_username (auth .username ())})
65
+ @find_team
66
+ def get_config (team = None , ateam = None ):
67
+ team_name = "UNKNOWN"
68
+ try :
69
+ team_name = team .team_name
70
+ except AttributeError :
71
+ pass
72
+ finally :
73
+ return jsonify ({'ctf_name' : current_app .config ["CTF_NAME" ], 'team_name' : team_name })
105
74
106
75
107
- from app .api import verify_flag
108
76
109
77
110
78
@web .route ('/flag' , methods = ['POST' ])
111
- @auth . login_required
112
- def submit_flag ():
113
- attacking_team = get_attacking_team ()
79
+ @find_team
80
+ def submit_flag (team = None , ateam = None ):
81
+ attacking_team = ateam
114
82
115
83
return verify_flag (int (attacking_team .id ), request .get_json ()['flag' ])
116
84
@@ -121,27 +89,26 @@ def get_scores():
121
89
122
90
123
91
@web .route ('/services' )
124
- @auth . login_required
125
- def get_services ():
92
+ @find_team
93
+ def get_services (team = None , ateam = None ):
126
94
return redis_client .get ('ctf_services' )
127
95
128
96
129
97
@web .route ('/jeopardies' )
130
- @auth . login_required
131
- def get_jeopardies ():
98
+ @find_team
99
+ def get_jeopardies (team = None , ateam = None ):
132
100
return redis_client .get ('ctf_jeopardy_list' )
133
101
134
102
135
103
@web .route ('/services_status' )
136
- @auth . login_required
137
- def get_services_status ():
104
+ @find_team
105
+ def get_services_status (team = None , ateam = None ):
138
106
status = json .loads (redis_client .get ('ctf_services_status' ))
139
107
result = {}
140
108
141
- team = get_attacking_team ()
142
109
143
110
for state in status :
144
- if state ['team_id' ] == team .id :
111
+ if state ['team_id' ] == ateam .id :
145
112
for entry in state ['services' ]:
146
113
result [entry ['service_id' ]] = entry ['state' ]
147
114
@@ -152,8 +119,3 @@ def get_services_status():
152
119
@web .route ('/tick_change_time' )
153
120
def get_tick_duration ():
154
121
return redis_client .get ('ctf_tick_change_time' )
155
-
156
-
157
- @web .route ('/logout' )
158
- def logout ():
159
- return ('Logout' , 401 , {'WWW-Authenticate' : 'Basic realm="Login required"' })
0 commit comments