aboutsummaryrefslogtreecommitdiffstats
path: root/templating/templating.py
blob: 515638348f2c1959d386139006af24215cce2a60 (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
#!/usr/bin/env python3

import requests,traceback
from jinja2 import Template,Environment,FileSystemLoader,TemplateNotFound
import json
import http.server
from enum import Enum

endpoints = "read/oplog read/snmp read/switches-management public/config public/dhcp public/dhcp-summary public/ping public/switches public/switch-state".split()
objects = dict()

def getEndpoint(endpoint):
    r = requests.get("http://gondul-front/api/%s" % endpoint)
    if (r.status_code != 200):
        raise Exception("Bad status code for endpoint %s: %s" % (endpoint, r.status_code))
    return r.json()

def updateData():
    for a in endpoints:
        objects[a] = getEndpoint(a)

env = Environment(loader=FileSystemLoader(['templates/','/opt/gondul/data/templates', '/opt/gondul/web/templates']),lstrip_blocks=True, trim_blocks=True)

class Mode(Enum):
    Get = 1
    Post = 2

class MyHandler(http.server.BaseHTTPRequestHandler):

    options = dict()

    def parse_options(self):
        self.url = self.path[1:]
        self.options = dict()
        if self.url.find("?") != -1:
            (self.url, tmpoptions) = self.url.split("?")
            tmptuples = tmpoptions.split("&")
            for a in tmptuples:
                (x,y) = a.split("=")
                self.options[x] = y

    def generic(self, mode):
        updateData()
        self.parse_options()
        body = ""
        try:
            if mode == Mode.Get:
                template = env.get_template(self.url)
            elif mode == Mode.Post:
                length = self.headers.get('content-length')
                if not length:
                    length = 0
                content = self.rfile.read(int(length)).decode('UTF-8')
                template = env.from_string(content)
            else:
                raise Exception("Invalid mode")

            body = template.render(objects=objects, options=self.options)
            self.send_response(200)
        except TemplateNotFound as err:
           body = "Template \"%s\" not found\n" % self.url
           self.send_response(404)
        except Exception as err:
            body = ("Templating of \"%s\" failed to render. Most likely due to an error in the template. Error transcript:\n\n%s\n----\n\n%s\n" % (self.url, err, traceback.format_exc()))
            if mode == Mode.Get:
                self.send_response(400)
            else:
                self.send_response(500)
        finally:
            self.send_header('Cache-Control','max-age=5, s-maxage=1')
        body = body.encode('UTF-8')
        self.send_header('Content-Length', int(len(body)))
        self.end_headers()
        self.wfile.write(body)
        self.wfile.flush()
        
    def do_GET(self):
        self.generic(Mode.Get) 

    def do_POST(self):
        self.generic(Mode.Post) 

def run(server_class=http.server.HTTPServer, handler_class=http.server.BaseHTTPRequestHandler):
    server_address = ('', 8080)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever() 

run(handler_class=MyHandler)
= 0; i < cycles; i ++ ) arc_getbyte( st ); return st; } /* For those who don't know, ArcFour is basically an algorithm that generates a stream of bytes after you give it a key. Just get a byte from it and xor it with your cleartext. To decrypt, just give it the same key again and start xorring. The function above initializes the byte generator, the next function can be used to get bytes from the generator (and shuffle things a bit). */ unsigned char arc_getbyte( struct arc_state *st ) { unsigned char tmp; /* Unfortunately the st-> stuff doesn't really improve readability here... */ st->i ++; st->j += st->S[st->i]; tmp = st->S[st->i]; st->S[st->i] = st->S[st->j]; st->S[st->j] = tmp; tmp = (st->S[st->i] + st->S[st->j]) & 0xff; return st->S[tmp]; } /* The following two functions can be used for reliable encryption and decryption. Known plaintext attacks are prevented by adding some (6, by default) random bytes to the password before setting up the state structures. These 6 bytes are also saved in the results, because of course we'll need them in arc_decode(). Because the length of the resulting string is unknown to the caller, it should pass a char**. Since the encode/decode functions allocate memory for the string, make sure the char** points at a NULL-pointer (or at least to something you already free()d), or you'll leak memory. And of course, don't forget to free() the result when you don't need it anymore. Both functions return the number of bytes in the result string. Note that if you use the pad_to argument, you will need zero-termi- nation to find back the original string length after decryption. So it shouldn't be used if your string contains \0s by itself! */ int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to ) { struct arc_state *st; unsigned char *key; char *padded = NULL; int key_len, i, padded_len; key_len = strlen( password ) + ARC_IV_LEN; if( clear_len <= 0 ) clear_len = strlen( clear ); /* Pad the string to the closest multiple of pad_to. This makes it impossible to see the exact length of the password. */ if( pad_to > 0 && ( clear_len % pad_to ) > 0 ) { padded_len = clear_len + pad_to - ( clear_len % pad_to ); padded = g_malloc( padded_len ); memcpy( padded, clear, clear_len ); /* First a \0 and then random data, so we don't have to do anything special when decrypting. */ padded[clear_len] = 0; random_bytes( (unsigned char*) padded + clear_len + 1, padded_len - clear_len - 1 ); clear = padded; clear_len = padded_len; } /* Prepare buffers and the key + IV */ *crypt = g_malloc( clear_len + ARC_IV_LEN ); key = g_malloc( key_len ); strcpy( (char*) key, password ); /* Add the salt. Save it for later (when decrypting) and, of course, add it to the encryption key. */ random_bytes( crypt[0], ARC_IV_LEN ); memcpy( key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN ); /* Generate the initial S[] from the IVed key. */ st = arc_keymaker( key, key_len, ARC_CYCLES ); g_free( key ); for( i = 0; i < clear_len; i ++ ) crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st ); g_free( st ); g_free( padded ); return clear_len + ARC_IV_LEN; } int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ) { struct arc_state *st; unsigned char *key; int key_len, clear_len, i; key_len = strlen( password ) + ARC_IV_LEN; clear_len = crypt_len - ARC_IV_LEN; if( clear_len < 0 ) { *clear = g_strdup( "" ); return 0; } /* Prepare buffers and the key + IV */ *clear = g_malloc( clear_len + 1 ); key = g_malloc( key_len ); strcpy( (char*) key, password ); for( i = 0; i < ARC_IV_LEN; i ++ ) key[key_len-ARC_IV_LEN+i] = crypt[i]; /* Generate the initial S[] from the IVed key. */ st = arc_keymaker( key, key_len, ARC_CYCLES ); g_free( key ); for( i = 0; i < clear_len; i ++ ) clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st ); clear[0][i] = 0; /* Nice to have for plaintexts. */ g_free( st ); return clear_len; }