summaryrefslogtreecommitdiff
path: root/kpov_judge/tasks/radius_mysql_pam/task.py
blob: b53c1b726da6e70fed6fdabadb1c04d3e36d09d5 (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
#!/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. SimpleArbeiterDhcp dobis na naslovu polz.si/media/uploads/kpov/virtualke. Na RadiusServer namesti FreeRadius.
Na SimpleArbiter preberi skrivnost ter poskrbi, da se bo s to skrivnostjo SimpleArbiter lahko povezal na RadiusServer.

Nato na RadiusServer namesti še podatkovno bazo mysql. Na SimpleArbiter preberi ime podatkovne baze, uporabniško ime na bazi ter geslo, s katerim se bo lahko klient s SimpleArbiter na to bazo lahko povezal.
 
V bazi ustvari tabele, potrebne za delovanje FreeRadius (več na http://wiki.freeradius.org/guide/SQL-HOWTO). Nastavi FreeRadius tako, da se bodo podatki o uporabnikih črpali iz baze mysql.

Na SimpleArbiter preberi uporabnisko ime in geslo
uporabnika ter ga dodaj v mysql tako, da bo strežnik Radius uporabnika s tem geslom sprejel. Za uporabnika ustvari tudi uporabniški račun (npr. z ukazom adduser). Upoštevaj, da testni program lahko temu uporabniku spremeni geslo. Poleg tega naj še vedno deluje prijava z uporabniškim imenom student in geslom vaje.

Nastavi PAM za prijavo (login) tako, da bo dovolj, če se uporabnik na ssh predstavi z geslom na strežniku Radius, ne glede na vnos v /etc/passwd oziroma /etc/shadow.
""",
   'en':u"""
TODO: correct this.
Create two virtual computers - SimpleArbiter (using the SimpleArbiterDhcp.vdi disk) and RadiusServer. You can get the disk image at polz.si/media/uploads/kpov/virtualke. Install OpenRadius on the RadiusServer VM. Installation instructions can be found at evbergen.home.xs4all.nl/openradius/doc-using-openradius.html. OpenRadius uses two configuration files /etc/openradius/configuration and /etc/openradius/behaviour. The first one defines sources and interfaces of the server, the second one defines how the server responds to requests. Add your username and password from the SimpleArbiter VM to the OpenRadius configuration. Make shure that SimpleArbiter is able to connect to RadiusServer using the shared secret.
Install the MySQL database on the RadiusServer VM. Log into the MySQL server using mysql -u root -p . Create the database using CREATE DATABASE <dbnamehere>. Add the columns username and password. Create the user test on RadiusServer and setup PAM so that the user password is checked against the MySQL database instead of the file /etc/passwd or /etc/shadow.
"""
}

#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
    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

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