sso.py 5.33 KB
Newer Older
marcus-tun's avatar
marcus-tun committed
1
2
3
4
5
6
7
8
#!/usr/bin/env python 

from mod_python import apache
from mod_python import util
import httplib2
import hashlib
from base64 import b64encode, b64decode

9
from Crypto.Cipher import Blowfish
marcus-tun's avatar
marcus-tun committed
10
from Crypto.Cipher import AES
11
12
from Crypto import Random
from struct import pack
marcus-tun's avatar
marcus-tun committed
13

14
15
import urllib
from string import replace
marcus-tun's avatar
marcus-tun committed
16
17
18
from binascii import hexlify, unhexlify

from interop import decrypt
19
20
21
22
23
24
25

def write_var (req, var, filename):
    log_path=req.document_root() + '/assertions/' + filename
    logfile=open(log_path, 'w')
    logfile.write(var)
    logfile.close

marcus-tun's avatar
marcus-tun committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

def handler(req):
    assertionLocation = str(req.subprocess_env['Shib-Assertion-01'])
    h1 = httplib2.HTTPSConnectionWithTimeout('saml-delegation.data.kit.edu')

    # get the path portion of the assertion link
    (i, assertionPath) = assertionLocation.split('https://saml-delegation.data.kit.edu')

    # get the assertion
    h1.request('GET', assertionPath)
    response = h1.getresponse()
    assertion = response.read()

    # remove newlines
    assertion = assertion.replace("\n", "")

    # find out at which url we were called
    (none, none, location) = req.uri.split('/')

marcus-tun's avatar
marcus-tun committed
45
46
47
    ############################
     # js: sso via javascript #
    ############################
marcus-tun's avatar
marcus-tun committed
48
49
    if location == 'js.py':
        req.content_type = 'text/html'
marcus-tun's avatar
marcus-tun committed
50
        req.write('''<!DOCTYPE html> <meta charset="ASCII" />
marcus-tun's avatar
marcus-tun committed
51
            <html>
marcus-tun's avatar
marcus-tun committed
52
53
54
<!-- TODO(daniel): host locally; jquery v1 for included IE support.. --!>
<script src="js/crypto-js/aes.js"></script>
<script src="js/jquery-1.11.1.min.js"></script>
marcus-tun's avatar
marcus-tun committed
55
56
57
58
59
60
61
62
63
64
                  <p> Obtaining temporary password url </p>
                  <table border="1">
                  <tr> <th>  Action                      </th><th> Status </th></tr>
                  <tr> <td>  Get assertion:              </td><td id="stat_get">  Wait </td> </tr>
                  <tr> <td>  Encrypting assertion:       </td><td id="stat_enc">  Wait </td> </tr>
                  <tr> <td>  Upload encrypted assertion  </td><td id="stat_post"> Wait </td> </tr>
                  </table>

                  <br/><p> You can now use this URL as a temporary password:<br/>
                  <b id="url"> Wait </b></p>
65
66
67
                  <p> You can also download the <a  id="url2" href="" >  Wait for link </a> and save it to /tmp/samlup_uXXXX.encr</p>
				  <p> You can also download the <a href="/sd/assertion.py">unencrypted assertion</a> and save it to /tmp/samlup_uXXXX</p>
				  <p> Replace XXXX with the UID on your client system</p>
marcus-tun's avatar
marcus-tun committed
68
69
<script src="js-new.js"></script>
                <head> </head>
70
                <body> </body>
marcus-tun's avatar
marcus-tun committed
71
            </html> ''')
marcus-tun's avatar
marcus-tun committed
72
73
74
        return apache.OK

    # ecp
75
    if location in ('ecp.py', 'assertion.py'):
76
77
78
        # octet stream will force saving to disk, while
        # text will allow to open with a text editor
        #req.content_type='application/octet-stream'\
79
        req.content_type = 'application/text'\
80
                '\nContent-Disposition: attachment; filename=samlup_uXXXX'
marcus-tun's avatar
marcus-tun committed
81
82
83
        req.write(assertion)
        return apache.OK

marcus-tun's avatar
marcus-tun committed
84
85
86
    ############
    #  upload  #
    ############
87
    if location in ('upload.py', 'jsupload.py'):
marcus-tun's avatar
marcus-tun committed
88
89
90
91
        req.content_type = 'text/plain'
        # we expect the data via post in encrypted assertion.
        # we will return the url of where to collect the assertion
        # request.
marcus-tun's avatar
marcus-tun committed
92

93
94
95
96
        if req.method != 'POST':
            req.write("Error, i was expecting a post request")
            return apache.OK

marcus-tun's avatar
marcus-tun committed
97
        form = util.FieldStorage(req)
98
        client = form.get ("client", "oops").replace(' ', '+')
99
100
101
        if not form.has_key("encrypted_assertion"):
            req.write ("Error: did not obtain the encrypted_assertion")
            return apache.OK
marcus-tun's avatar
marcus-tun committed
102
        b64 = form.get("encrypted_assertion", "Error: no assertion present").replace(' ', '+')
103
        #write_var (req, b64, 'b64')
104
        client_version = form.get ("client_verions", "oops").replace(' ', '+')
marcus-tun's avatar
marcus-tun committed
105

106
        # decode assertion
107
        encrypted_assertion = unhexlify(b64)
108
109
110
111
112

        # create hash
        assertion_hash = str(hashlib.md5(encrypted_assertion).hexdigest())
        assertion_url ='https://' + req.hostname + '/assertions/' + assertion_hash

113
114
115
        # Publish encrypted assertion on the web
        write_var (req, encrypted_assertion, assertion_hash)

marcus-tun's avatar
marcus-tun committed
116
117
        # return the url as key=value FIXME
        req.write("url=%s" % assertion_url)
marcus-tun's avatar
marcus-tun committed
118
        #req.write("%s" % assertion_url)
119
120
121
122

        #########
        # debug #
        #########
123
        # decrypt assertion in case a key is uploaded by the client
124

marcus-tun's avatar
marcus-tun committed
125
126
        if form.has_key("key"):
            enc_key = form.get("key", "")
127
            write_var (req, enc_key, 'enc_key')
marcus-tun's avatar
marcus-tun committed
128
            client = form.get("client","")
129
            key = unhexlify(enc_key)
marcus-tun's avatar
marcus-tun committed
130
131

            write_var(req,enc_key, "key")
132
            write_var(req, encrypted_assertion, 'encrypted_assertion')
133

marcus-tun's avatar
marcus-tun committed
134
135
136
137
138
139
140
            # some logging
            log_path=req.document_root() + '/assertions/' + 'log'
            logfile=open(log_path, 'w')
            logfile.write("keylen:    %d\n" % len(key))
            logfile.write("cipherlen: %d\n" % len(encrypted_assertion))
            #logfile.write("iv:        %d\n" % len(iv))
            logfile.close
marcus-tun's avatar
marcus-tun committed
141

142

marcus-tun's avatar
marcus-tun committed
143
            plaintext = decrypt(key, encrypted_assertion)
144
            write_var(req, plaintext, 'plaintext')
marcus-tun's avatar
marcus-tun committed
145
146
147
148
149
        return apache.OK

    req.content_type = 'text/plain'
    req.write("Error: Your request was not understood")
    return apache.OK