summaryrefslogtreecommitdiff
path: root/kpov_judge/tasks/radius_mysql_pam/task.py
blob: 7dbfe8ccdf7ca5203ce47aadd484edec013e9bf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# kpov_random_helpers should be imported by add_assignment.py

instructions = {
    'si':u"""
Ustvari dva navidezna računalnika - SimpleArbiter z diska simpleArbiterDhcp ter
RadiusServer. Na RadiusServer namesti FreeRadius ter MySQL. 

Ustvari mysql podatkovno bazo z imenom {MYSQL_DB_NAME}. Ustvari mysql
uporabnika z imenom {MYSQL_ADMIN_USER} in geslom {MYSQL_ADMIN_PASSWORD},
ki naj ima poln dostop do te baze. Prijava za tega uporabnika mora biti
omogočena tudi s SimpleArbiter.

Nastavi FreeRadius tako, da bo podatke o uporabnikih in geslih pobiral iz baze 
MySQL z imenom {MYSQL_DB_NAME}. Podatkovna shema (imena tabel) naj ostane
privzeta.

Dostop do strežnika Radius na RadiusServer s SimpleArbiter naj bo mogoč ob
uporabi skrivnosti {RADIUS_SECRET}.

V bazi ustvari vnos, ki bo omogočil, da se na RadiusServer s pomočjo protokola
Radius avtenticira uporabnik {RADIUS_USERNAME} z geslom {RADIUS_PASSWORD}.

Nastavi PAM za prijavo (login) tako, da bo dovolj, če se uporabnik na ssh
predstavi z uporabniškim imenom in geslom, ki sta veljavna na FreeRadius,
ne glede na /etc/shadow oziroma /etc/password.
""",
   'en':u"""
Create two virtual machines - SimpleArbiter using the disk simpleArbiterDhcp
and RadiusServer. On RadiusServer, install FreeRadius and MySQL.

Create a mysql database named {MYSQL_DB_NAME}. Create a mysql user with the
username {MYSQL_ADMIN_USER} and password {MYSQL_ADMIN_PASSWORD}. Make sure
this user can access the database from SimpleArbiter and has administrative 
rights over the {MYSQL_DB_NAME} database.

Set up FreeRadius so that the data about users and passwords is stored in the
MySQL database. Keep the default schema (table names).

Make the Radius server on RadiusServer accessible from SimpleArbiter using
{RADIUS_SECRET} as the secret.

Create an entry in the database which will enable a user with the username
{RADIUS_USERNAME} to authenticate themself against the Radius server using
the password {RADIUS_PASSWORD}.

Set up PAM to enable login over ssh using a username and password which are
valida on the FreeRadius server, regardless of the entries in /etc/shadow
and/or /etc/password.
"""
}

#KABOOM

computers = {
    'RadiusServer': {
        'disks': [
            {   'name': 'RadiusServer',
            },
            #{   'name': 'CDROM',
            #    'options':{'readonly': True},
            #    'parts': [],# no parts, no mounting.
            #}
        ],
        'network_interfaces': [{'network': 'net1'}],
        'flavor': 'm1.tiny',
        'config_drive': False

    },
    'SimpleArbiter': {
        'disks': [
            {   'name': 'simpleArbiterDhcp',
                # attempt automount
            },
            #{   'name': 'CDROM',
            #    'options': {'readonly': True},
            #    'parts': [{'dev': 'b1', 'path': '/cdrom'}],
            #},
        ],
        'network_interfaces': [{'network': 'net1'}, {'network': 'test-net'}],
        'flavor': 'm1.tiny',
        'config_drive': False
    }
}

networks = { 'net1': {'public': False}, 'test-net': {'public': True} }

params_meta = {
    'IP_RS': {'descriptions': {'si': 'Naslov RadiusServer'}, 'w': True, 'public':True, 'type': 'IP', 'generated': False},
    'RADIUS_SECRET':{'descriptions': {'si': 'Skrivnost RADIUS'}, 'w': False, 'public':True, 'type': 'password', 'generated': True},
    'RADIUS_USERNAME': {'descriptions': {'si': 'Uporabniško ime'}, 'w': True, 'public':True, 'type': 'username', 'generated': False},
    'RADIUS_PASSWORD': {'descriptions': {'si': 'geslo uporabnika'}, 'w': False, 'public':True, 'type': None, 'generated': True},
    'MYSQL_DB_NAME': {'descriptions': {'si': 'Ime baze v mysql'}, 'w': False, 'public':True, 'type': None, 'generated': True},
    'MYSQL_ADMIN_USER':{'descriptions': {'si': 'Uporabniško ime za dostop do MySQL'}, 'w': False, 'public':True, 'type': 'username', 'generated': True},
    'MYSQL_ADMIN_PASSWORD': {'descriptions': {'si': 'Geslo za dostop do MySQL'}, 'w': True, 'public':True, 'type': 'password', 'generated': True},
    'MYSQL_SEED':{'descriptions': {'si': 'seed'}, 'w': False, 'public':True, 'type': None, 'generated': True},
}

def task(IP_RS, RADIUS_SECRET, RADIUS_USERNAME, RADIUS_PASSWORD, MYSQL_DB_NAME, MYSQL_ADMIN_USER, MYSQL_ADMIN_PASSWORD, MYSQL_SEED):
    import pxssh
    import pexpect
    import random
    results = dict()
    peer_user = 'student'
    peer_passwd = 'vaje'
    r = random.Random(MYSQL_SEED)
    MYSQL_TEST_USER = kpov_random_helpers.username_gen(r)
    MYSQL_TEST_PASSWORD = kpov_random_helpers.alnum_gen(r, 7)
    RADIUS_NEW_PASSWORD = kpov_random_helpers.alnum_gen(r, 7)
    # Testiranje radius strtežnika
    results['Test_RadiusServer'] = pexpect.run('radtest {0} {1} {2} 1812 {3}'.format(
        RADIUS_USERNAME, RADIUS_PASSWORD, IP_RS, RADIUS_SECRET))
    # Testiranje podatkovne base mysql
    mysql = pexpect.spawn('mysql -u {MYSQL_ADMIN_USER} -p{MYSQL_ADMIN_PASSWORD} -h {IP_RS}'.format(**locals()))
    mysql.expect("mysql>")
    results['mysql_login'] = mysql.before
    mysql.sendline('USE {MYSQL_DB_NAME}'.format(**locals()))	
    mysql.expect("mysql>")
    results['database_connect'] = mysql.before
    mysql.sendline('SELECT UserName, Value FROM radcheck;')
    mysql.expect("mysql>")
    results['select_from_users'] = mysql.before
    mysql.sendline("INSERT INTO radcheck (UserName, Attribute, Value, Op) VALUES ('{MYSQL_TEST_USER}', 'Cleartext-Password', '{MYSQL_TEST_PASSWORD}', ':=');".format(**locals()))
    mysql.expect("mysql>")
    results['radtest_OK'] = pexpect.run('radtest {0} {1} {2} 1812 {3}'.format(
        MYSQL_TEST_USER, MYSQL_TEST_PASSWORD, IP_RS, RADIUS_SECRET))
    results['radtest_NOK'] = pexpect.run('radtest {0} {1} {2} 1812 {3}'.format(
        MYSQL_TEST_USER, "Flügzeug", IP_RS, RADIUS_SECRET))
    results['radtest_NOK'] = pexpect.run('radtest {0} {1} {2} 1812 {3}'.format(
        MYSQL_TEST_USER, "Flügzeug", IP_RS, RADIUS_SECRET))
    sT = pxssh.pxssh()
    mysql.sendline("UPDATE radcheck SET value='{RADIUS_NEW_PASSWORD}' where UserName='{RADIUS_USERNAME}' and Attribute='Cleartext-Password';".format(**locals()))
    sT.login(IP_RS, RADIUS_USERNAME, RADIUS_NEW_PASSWORD)
    results['login_test'] = sT.before
    mysql.sendline("UPDATE radcheck SET value='{RADIUS_PASSWORD}' where UserName='{RADIUS_USERNAME}' and Attribute='Cleartext-Password';".format(**locals()))
    mysql.expect('mysql>')
    mysql.sendline("DELETE FROM radcheck where UserName='{MYSQL_TEST_USER}' and Attribute='Cleartext-Password';".format(**locals()))
    mysql.expect('mysql>')
    mysql.sendline('\q');
    # Testiranje PAM s testnim uporabnikom
    return results
    
def gen_params(user_id, params_meta):
    params = dict()
    r = random.Random(user_id)
    params['RADIUS_SECRET'] = kpov_random_helpers.alnum_gen(r, 8)
    params['RADIUS_PASSWORD'] = kpov_random_helpers.alnum_gen(r, 8)
    params['RADIUS_USERNAME'] = kpov_random_helpers.username_gen(r)
    params['MYSQL_ADMIN_USER'] = kpov_random_helpers.alnum_gen(r, 6)
    params['MYSQL_ADMIN_PASSWORD'] = kpov_random_helpers.alnum_gen(r, 6)
    params['MYSQL_DB_NAME'] = kpov_random_helpers.alnum_gen(r, 4)
    params['MYSQL_SEED'] = str(r.random())
    return params

def task_check(results, params):
    import re
    import pickle
    score = 0
    hints = []
    r = random.Random(params['MYSQL_SEED'])
    MYSQL_TEST_USER = kpov_random_helpers.username_gen(r)
    MYSQL_TEST_PASSWORD = kpov_random_helpers.alnum_gen(r, 7)
    RADIUS_NEW_PASSWORD = kpov_random_helpers.alnum_gen(r, 7)
    s = "Sending Access-Request of id [0-9]+ to {IP_RS} port 1812\r\n\tUser-Name = \"{RADIUS_USERNAME}\"\r\n\tUser-Password = \"{RADIUS_PASSWORD}\".*Access-Accept packet from host {IP_RS}".format(**params)
    #with open('test.pickle', 'w') as f:
    #    pickle.dump({'pattern': s, 'res': results['Test_RadiusServer']}, f)
    if re.search(s, results['Test_RadiusServer'], flags=re.DOTALL):
        # print "Test OK"
        score += 2
    else:
        print (results['Test_RadiusServer'], s)
    # Testiranje podatkovne base mysql
    s = "Welcome to the MySQL monitor.*Type 'help;' or '\\\\h' for help\\. Type '\\\\c' to clear the current input statement\\.\r\n"
    if re.search(s, results['mysql_login'], flags=re.DOTALL):
        # print "mysql_login OK"
        score += 1
    else:
        print (results['mysql_login'], s)
    s = " USE {MYSQL_DB_NAME}\r\nReading table information.*Database changed\r\n".format(**params)
    if re.search(s, results['database_connect'], flags=re.DOTALL):
        # print "database_connect OK"
        score += 1
    else:
        print (results['database_connect'],)
    s = " SELECT UserName, Value FROM radcheck;\r\n.*{RADIUS_USERNAME} *| *{RADIUS_PASSWORD}".format(**params)
    if re.search(s, results['select_from_users'], flags=re.DOTALL):
        # print "select_from_users OK"
        score += 2
    else:
        print (results['select_from_users'], )
    s = "Sending Access-Request of id [0-9]+ to {0} port 1812\r\n\tUser-Name = \"{1}\"\r\n\tUser-Password = \"{2}\".*Access-Accept packet from host {0}".format(params['IP_RS'], MYSQL_TEST_USER, MYSQL_TEST_PASSWORD)
    if re.search(s, results['radtest_OK'], flags=re.DOTALL):
        # print "radtest_OK OK"
        score += 2
    else:
        print (s, results['radtest_OK'])
    s = "Sending Access-Request of id [0-9]+ to {0} port 1812\r\n\tUser-Name = \"{1}\"\r\n\tUser-Password = \"Flügzeug\".*rad_recv: Access-Reject packet from host {0}".format(params['IP_RS'], MYSQL_TEST_USER)
    if re.search(s, results['radtest_NOK'], flags=re.DOTALL):
        # print "radtest_NOK OK"
        score += 1
    else:
        print (results['radtest_NOK'], s)
    s = "{RADIUS_USERNAME}@.*:~\\$".format(**params)
    if re.search(s, results['login_test'], flags=re.DOTALL):
        # print "login_test OK"
        score += 1
    else:
        print (results['login_test'],s)
    return score, hints

def prepare_disks(templates, params):
#    d = templates['simpleArbiterDhcp']
    pass