Beispiel #1
0
    def archive(self):

        # store zipped version of /opt/websafety/etc to the shared folder
        zip_dir = os.path.join(Paths.var_dir(), "cluster")
        if not os.path.exists(zip_dir):
            os.makedirs(zip_dir)

        # copy the database
        backup_db_file = os.path.join(Paths.etc_dir(), "config.sqlite")
        db_file = os.path.join(Paths.var_dir(), "db", "config.sqlite")

        try:
            c = connection.cursor()
            c.execute("BEGIN IMMEDIATE")
            shutil.copyfile(db_file, backup_db_file)
        finally:
            c.close()
            connection.rollback()

        # remove all old configs, only last 10 will stay
        files = [
            f for f in os.listdir(zip_dir)
            if os.path.isfile(os.path.join(zip_dir, f))
        ]
        for f in files[:-9]:
            os.remove(os.path.join(zip_dir, f))

        # source and target paths
        etc_dir = Paths.etc_dir()
        zip_file = os.path.join(
            zip_dir, "%s-%s.zip" % (str(self.timestamp), str(self.version)))

        # zip it
        zipdir(etc_dir, zip_file)
Beispiel #2
0
    def collect_license(self):

        # will write license data to a temp folder
        folder = os.path.join(Paths.var_dir(), "temp", "license_upload")
        try:
            shutil.rmtree(folder)
        except Exception as e:
            pass
        os.makedirs(folder)

        # collect all chunks into it
        data = self.request.FILES['file']
        name = os.path.join(folder, "license.pem")

        try:
            os.unlink(name)
        except Exception as e:
            pass

        with open(name, "wb") as fout:
            for chunk in data.chunks():
                fout.write(chunk)

        # also copy out the diladele.pem and websafety.pem files into temp folder too
        shutil.copy(os.path.join(Paths.etc_dir(), "diladele.pem"),
                    os.path.join(folder, "diladele.pem"))

        shutil.copy(os.path.join(Paths.etc_dir(), "websafety.pem"),
                    os.path.join(folder, "websafety.pem"))

        # fine, license is there
        return folder
Beispiel #3
0
    def get_context_data(self, **kwargs):
        
        context = super(ViewSafetySystemInfo, self).get_context_data(**kwargs)

        v = Version()

        info = {
            'product_name'      : 'Web Safety for Squid Proxy',
            'installed_version' : v.installed,
            'latest_version'    : v.latest,
            'need_to_upgrade'   : v.need_to_upgrade(),        # 0 - no_need_to_upgrade, 1 - may_upgrade, 2 - should_upgrade, 3 - must_upgrade
            'whats_new'         : v.whats_new
        };
        context['info'] = info

        # add hardcoded settings
        context['WEBSAFETY_ETC_DIR']      = Paths.etc_dir()
        context['WEBSAFETY_ETC_DIR_SIZE'] = long(FolderInfo(Paths.etc_dir()).get_size()) 
        context['WEBSAFETY_VAR_DIR']      = Paths.var_dir()
        context['WEBSAFETY_VAR_DIR_SIZE'] = long(FolderInfo(Paths.var_dir()).get_size())
        context['WEBSAFETY_BIN_DIR']      = Paths.bin_dir()
        context['WEBSAFETY_BIN_DIR_SIZE'] = long(FolderInfo(Paths.bin_dir()).get_size())
        context['WEBSAFETY_VERSION']      = Build.version()
        context['WEBSAFETY_ARCH']         = Distrib.arch()
        context['WEBSAFETY_DISTRIB']      = Distrib.name()
        context['WEBSAFETY_SYSTEM']       = System.name()
        
        return context
Beispiel #4
0
    def form_valid(self, form):

        try:

            # get realm
            realm = form.cleaned_data['realm']

            # debug check it is fine
            assert(len(realm) > 0)
            assert(realm.upper() == realm)
            
            # aways update the kerberos conf file
            self.write_krb5_conf(realm)

            # update the kerberos keytab file if provided by user                        
            self.write_keytab(form.cleaned_data['krb5_spn'], form.cleaned_data.get('keytab', None))

            # see what we must do
            enable = form.cleaned_data['krb5_enable']
            if enable:

                # ok user wants to enable the authenticator, check if everything is in place
                keytab   = os.path.join(Paths.etc_dir(), "krb5.keytab")
                krb5conf = os.path.join(Paths.etc_dir(), "krb5.conf")

                if os.path.isfile(krb5conf) and os.path.isfile(keytab):
                    
                    # good everything is fine, proceed
                    pass

                else:

                    # no-no, we cannot enable!
                    if not os.path.isfile(keytab):

                        errors = form._errors.setdefault("keytab", ErrorList())
                        errors.append(u"This field is required to enable Kerberos authenticator.")

                        errstr = "Cannot enable Kerberos authenticator. KeyTab file '%s' is not found! Please click on the Browse button and upload the KeyTab from your computer." % keytab

                    else:
                        errstr = "Cannot enable Kerberos authenticator. krb5.conf file '%s' is not found!" % krb5conf

                    # and fail 
                    raise Exception(errstr)

            # if we got here everything is fine (either enabled or disabled successfully)
            return super(ViewAuthNegotiateSchemeEdit, self).form_valid(form)
            
        except Exception as e:        
            form.errors['__all__'] = form.error_class([
                "%s\n%s" % (str(e), traceback.format_exc()) 
            ])

            # failure
            return super(ViewAuthNegotiateSchemeEdit, self).form_invalid(form)
Beispiel #5
0
    def post(self, request, *args, **kwargs):

        form  = ClusterClientForm(request.POST)
        if form.is_valid():

            # ok form is valid, fill the data
            data = {
                "enabled"       : form.cleaned_data['enabled'], 
                "server_port"   : form.cleaned_data['server_port'], 
                "server_address": form.cleaned_data['server_address'], 
                "sync_interval" : form.cleaned_data['sync_interval']
            }

            # and write it
            w = FileWriter(os.path.join(Paths.etc_dir(), "node"))
            d = JsonDumper()

            w.write('cluster_client.json', d.dumps(data))

            # mark as needing relstart
            messages.info(request, "need_squid_restart")

            return HttpResponseRedirect(self.get_success_url()) 

        return render(request, self.template_name, {'form': form })
Beispiel #6
0
    def test_ldap(self, object):

        # here we have django model auth domain updated, but we also need to generate JSON files in /opt/websafety/etc
        g = Generator(os.path.join(Paths.etc_dir(), "squid"))
        w = FileWriter(os.path.join(Paths.etc_dir(), "squid"))
        d = JsonDumper()
        
        g.generate_auth(w, d)

        # and run the tests
        result = LdapTester().run();
        if result['exit_code'] == 0:
            return (True, "%s %s" % (result['stdout'], result['stderr']))
        else:
            return (False, "Exit code: %s\nSTDOUT: %s\nSTDERR: %s\n" % (str(result['exit_code']), result['stdout'], result['stderr']))
        pass
Beispiel #7
0
    def generate_linux_debian_manual(self, manual):

        # construct file names
        cur_file = os.path.join(Paths.etc_dir(), "node",
                                "etc_network_interfaces.manual")
        bak_file = cur_file + ".bak"
        new_file = cur_file + ".new"

        # clear the environment
        if os.path.exists(bak_file):
            os.unlink(bak_file)
        if os.path.exists(new_file):
            os.unlink(new_file)

        # always generate manual file (even if manual is empty)
        t = loader.get_template("node/network/etc_network_interfaces.manual")
        m = manual.replace("\r\n", "\n")
        c = {"manual": m}

        # the contents
        contents = t.render(c)

        # write data into new file
        with open(new_file, "w") as fout:
            fout.write(contents)
            fout.flush()

        # move files around
        if os.path.exists(cur_file):
            shutil.move(cur_file, bak_file)
        shutil.move(new_file, cur_file)
Beispiel #8
0
    def form_valid(self, form):

        try:

            # ok the user wants us to reset the cache
            disk_cache = DiskCache.objects.first()

            # first we must enable the cache in the database
            disk_cache.enabled = True
            disk_cache.save()

            # now we generate the squid configuration on disk
            g = Generator(
                os.path.join(Paths.etc_dir(), "squid")
            )
            g.generate()

            # and we call special sudoing binary that will stop squid, reset the cache and start squid again
            SquidCacheInitializer().initialize()

            # perfect now we have the cache enabled and reinitialized, return nicely
            return super(ViewCacheDiskReset, self).form_valid(form)
            
        except Exception as e:        
            form.errors['__all__'] = form.error_class([
                "%s\n%s" % (str(e), traceback.format_exc()) 
            ])

            # failure
            return super(ViewCacheDiskReset, self).form_invalid(form)
Beispiel #9
0
    def form_valid(self, form):

        try:
            data = self.request.FILES['file']

            # first we try to write the file next to actual one
            old_file = os.path.join(Paths.etc_dir(), "users.htpasswd")
            new_file = old_file + ".new"

            # remove the existing new file(s) which may not even exist
            try:
                os.remove(new_file)
            except OSError as e:
                if e.errno != errno.ENOENT:
                    raise

            # write the new file
            with open(new_file, 'wb') as fout:
                for chunk in data.chunks():
                    fout.write(chunk)

            # now replace the new files
            if os.path.isfile(old_file):
                os.remove(old_file)

            os.rename(new_file, old_file)

            # ok if we got here everything is fine
            return super(ViewAuthLocalDbImport, self).form_valid(form)

        except Exception as e:
            form.errors['__all__'] = form.error_class(["%s" % str(e)])

            # failure
            return super(ViewAuthLocalDbImport, self).form_invalid(form)
Beispiel #10
0
    def save_certificate(self, cert_contents):

        # first we try to write the file next to actual one
        old_pem = os.path.join(Paths.etc_dir(), "ldaps.pem")
        new_pem = old_pem + ".new"

        # remove the existing new file(s) which may not even exist
        try:
            os.remove(new_pem)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise

        # write the new pem file 
        with open(new_pem, 'wb') as fout:
            fout.write(cert_contents)

        # run the certmgr that will verify this file - may throw!
        detector = LdapsDetector()
        output   = detector.dump(new_pem)
        
        # now replace the new files 
        if os.path.isfile(old_pem):
            os.remove(old_pem)
        os.rename(new_pem, old_pem)
Beispiel #11
0
    def get(self, request, *args, **kwargs):            

        path = os.path.join(Paths.etc_dir(), "ldaps.pem")
        with open(path, "rb") as fin:
            response = HttpResponse(fin.read(), content_type="application/x-x509-ca-cert")
            response['Content-Disposition'] = "attachment; filename=\"%s\"" % "ldaps.pem"
            return response
Beispiel #12
0
    def get_settings(self):

        name = os.path.join(Paths.etc_dir(), "system.json")
        with open(name) as fin:
            data = json.load(fin)

        return data
Beispiel #13
0
    def install_license(self):

        # collect the license into a temporary folder
        folder = self.collect_license()

        # protect against users loading key instead of pem
        if os.path.getsize(os.path.join(folder, "license.pem")) < 255:
            raise Exception(
                "You might be uploading a 4.2 style license.key file. This version requires license.pem instead. Contact [email protected] to get it."
            )

        # check if the license is fine
        try:
            license = CommandLicense().run(folder)

            if license['valid'] != "1":

                message = license["error"]

                if license["error"].find("local issuer certificate") != -1:
                    message += ". You might be trying to upload a valid license key but for Web Safety version 5. Such keys are not supported. Please contact [email protected] to convert your valid license key to a new format."

                raise Exception(message)

        except Exception as e:

            raise Exception("License key is invalid, error: %s" % str(e))

        # if we got here, then the license key is fine, replace the current one
        shutil.copy(os.path.join(folder, "license.pem"),
                    os.path.join(Paths.etc_dir(), "license.pem"))

        # good, now if the license is community, activate/deactivate web safety
        self.activate_safety()
Beispiel #14
0
    def __init__(self, dc_addr, port, use_ldaps, base_dn, bind_user,
                 bind_pass):

        # set size limit
        self.size_limit = 150

        # we do not support referrals
        ldap.set_option(ldap.OPT_REFERRALS, 0)
        ldap.set_option(ldap.OPT_SIZELIMIT, self.size_limit)

        # set schema
        schema = "ldap"
        if use_ldaps:
            schema = "ldaps"

            # it is ldapS so set the path to the trusted cert
            ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,
                            os.path.join(Paths.etc_dir(), "ldaps.pem"))

            # disable certificate checking only on windows to ease development
            if System.name() == System.WS_WINDOWS:
                ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,
                                ldap.OPT_X_TLS_NEVER)

        # construct uri
        uri = "%s://%s:%d" % (schema, dc_addr, port)

        # init LDAP and bind to it
        self.conn = ldap.initialize(uri)

        # bind to LDAP server
        self.conn.simple_bind_s(bind_user, bind_pass)

        # and save the base dn
        self.base_dn = base_dn
Beispiel #15
0
    def generate(self, contents):

        # debug check
        assert (len(contents) > 0)

        # first generate a temporary file in /opt/websafety/etc/node folder (it will be removed after close automatically)
        prefix = "etc_network_interfaces."
        folder = os.path.join(Paths.etc_dir(), "node")

        # write to temp file
        with tempfile.NamedTemporaryFile(prefix=prefix,
                                         dir=folder,
                                         delete=True) as temp:

            temp.write(contents)
            temp.flush()

            # call the sudoing binary
            exe = os.path.join(Paths.bin_dir(), "network_debian.py")
            arg1 = "--file=%s" % temp.name
            arg2 = "--system=%s" % System.name()
            arg3 = "--distrib=%s" % Distrib.name()
            args = [exe, arg1, arg2, arg3]

            # and run it
            (exit_code, stdout, stderr) = CommandElevated().run(args)
            if exit_code != 0:
                raise Exception(
                    "Cannot generate network settings. Error: %d, STDOUT: %s, STDERR: %s"
                    % (exit_code, stdout, stderr))
Beispiel #16
0
    def get(self, request, *args, **kwargs):

        path = os.path.join(Paths.etc_dir(), "wpad.dat")
        with open(path, "rb") as fin:
            response = HttpResponse(
                fin.read(), content_type="application/x-ns-proxy-autoconfig")
            return response
Beispiel #17
0
    def get(self, request, *args, **kwargs):            

        # construct the path
        path = os.path.join(Paths.etc_dir(), "blocked_safe_browsing.html")

        # run it all in the exception block
        try:

            # get the file
            with open(path, "r") as fin:
                contents = fin.read()

            # render everything
            templ   = Template(contents)
            context = {
                "VERSION"     : Build.version(),
                "URI"         : request.GET.get('url', ''),
                "RESULT_INFO" : request.GET.get('reason', '')
            }

            # and return response
            response = HttpResponse(templ.render(Context(context)), content_type="text/html")
            
            return response

        except Exception as e:

            return HttpResponse(str(e), content_type="text/html")
Beispiel #18
0
    def get_context_data(self, **kwargs):

        context = super(ViewAuthNegotiateSchemeEdit, self).get_context_data(**kwargs)        

        # this is the path to keytab
        keytab_path = os.path.join(Paths.etc_dir(), "krb5.keytab")
        
        # dump contents of keytab
        try:
            context['keytab'] = KeyTabDumper().dump(keytab_path)
        except Exception as e:
            context['keytab'] = str(e)
        
        # verify keytab is valid for spn
        (result, output) = KeyTabInitializer().initialize(keytab_path, self.object.krb5_spn)
        context['kinit_result'] = result
        context['kinit_output'] = output

        # read krb5.conf
        try:
            path = os.path.join(Paths.etc_dir(), "krb5.conf")
            with open(path, "r") as fin:
                context['krb5conf'] = fin.read()
        except Exception as e:
            context['krb5conf'] = "Error reading %s file: %s" % (path, str(e))


        # construct some params
        use_ldaps = False
        if self.object.lookup_mode in (AuthAd.LOOKUP_MODE_LDAP, AuthAd.LOOKUP_MODE_GC):
            use_ldaps = False
        if self.object.lookup_mode in (AuthAd.LOOKUP_MODE_LDAPS, AuthAd.LOOKUP_MODE_GCS):
            use_ldaps = True

        # check kvno
        (result, output) = KvnoChecker(
            self.object.dc1addr,  
            self.object.lookup_mode,
            use_ldaps,
            self.object.base_dn,
            self.object.bind_user,
            self.object.bind_pass
        ).check(keytab_path, self.object.krb5_spn)
        context['kvno_result'] = result
        context['kvno_output'] = output
        
        return context
Beispiel #19
0
    def get(self, request, *args, **kwargs):
        wpad_dat = ""
        try:
            path = os.path.join(Paths.etc_dir(), "wpad.dat")
            os.unlink(path)
        except Exception as e:
            pass

        return HttpResponseRedirect(reverse_lazy("ToolsUploadWpad"))
Beispiel #20
0
    def dump_raw(self, cacert):

        cacert_path = os.path.join(Paths.etc_dir(), cacert)
        if not os.path.isfile(cacert_path):
            raise Exception("File %s does not exist or is not accessible!" %
                            cacert_path)

        with open(cacert_path, 'r') as fin:
            return fin.read()
Beispiel #21
0
    def get(self, request, *args, **kwargs):

        path = os.path.join(Paths.etc_dir(), "users.htpasswd")
        with open(path, "rb") as fin:
            response = HttpResponse(fin.read(),
                                    content_type="application/octet-stream")
            response[
                'Content-Disposition'] = "attachment; filename=\"%s\"" % "users.htpasswd"
            return response
Beispiel #22
0
    def get(self, request, *args, **kwargs):

        data = {}
        name = os.path.join(Paths.etc_dir(), "node", "cluster_client.json")
        if os.path.exists(name):
            with open(name) as fin:    
                data = json.load(fin)

        form = ClusterClientForm(initial=data)

        return render(request, self.template_name, {'form': form })
Beispiel #23
0
    def generate(self, country, state, city, organization, ou, email, cn,
                 days):

        # first we try to write the file next to actual one
        cur_pem = os.path.join(Paths.etc_dir(), "myca.pem")
        new_pem = cur_pem + ".new"
        cur_der = os.path.join(Paths.etc_dir(), "myca.der")
        new_der = cur_der + ".new"

        # remove the existing new file(s) which may not even exist
        try:
            os.remove(new_pem)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise

        try:
            os.remove(new_der)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise

        # generate the new pem file by calling special command
        SquidCertGenerator().generate(new_pem, country, state, city,
                                      organization, ou, email, cn, days)

        # ok file is good; now we need to convert it to DER
        SquidCertConverter().to_der(new_pem, new_der)

        # replace the new files
        if os.path.isfile(cur_pem):
            os.remove(cur_pem)
        if os.path.isfile(cur_der):
            os.remove(cur_der)

        os.rename(new_pem, cur_pem)
        os.rename(new_der, cur_der)

        # perfect now reinitialize the SSL storage (ensure you have the right to write into squid folder!)
        SquidCertDbInitializer().initialize()
Beispiel #24
0
    def get(self, request, *args, **kwargs):
        wpad_dat = ""
        try:
            path = os.path.join(Paths.etc_dir(), "wpad.dat")
            with open(path, "rb") as fin:
                wpad_dat = fin.read()
        except Exception as e:
            wpad_dat = str(e)

        return render(request, 'squid/tools/wpad.html', {
            'form': WpadUploadForm(),
            'wpad_dat': wpad_dat
        })
Beispiel #25
0
    def do_import(self, form, unpack_dir, version2, version4):

        # see what we need to do
        test_only = form.cleaned_data.get('dryrun', False)
        restore_config = form.cleaned_data.get('restore_config', False)
        restore_certs = form.cleaned_data.get('restore_certs', False)
        restore_htmls = form.cleaned_data.get('restore_htmls', False)
        restore_lic = form.cleaned_data.get('restore_lic', False)
        restore_ad = form.cleaned_data.get('restore_ad', False)

        if restore_config:

            upgrader = Upgrader(test_only, version2)
            upgrader.upgrade(os.path.join(unpack_dir, "etc"))

        files = []
        if restore_htmls:
            files.extend([
                "blocked_adult.html", "blocked_domains.html",
                "blocked_general.html", "bypass_partial.html",
                "blocked_image.gif"
            ])
        if restore_certs:
            files.extend(["myca.der", "myca.pem"])
        if restore_lic:
            files.extend(["license.pem"])
        if restore_ad:
            files.extend(["krb5.conf", "krb5.keytab", "ldaps.pem"])

        # copy files
        for file in files:

            src_file = os.path.join(unpack_dir, "etc", file)
            if not os.path.isfile(src_file):
                continue

            bak_file = os.path.join(unpack_dir, "etc", file + ".bak")
            dst_file = os.path.join(Paths.etc_dir(), file)

            if os.path.isfile(bak_file):
                os.unlink(bak_file)

            if os.path.isfile(dst_file):
                shutil.move(dst_file, bak_file)
            shutil.move(src_file, dst_file)

        # do some additional actions for certificates
        if restore_certs:
            SquidCertDbInitializer().initialize()
Beispiel #26
0
    def clean_enabled(self):

        enabled = self.cleaned_data['enabled']
        if enabled:
            
            # ok admin wants to enable client, let's see we are NOT server already
            name = os.path.join(Paths.etc_dir(), "node", "cluster_server.json")
            with open(name) as fin:    
                data = json.load(fin)

                if data['enabled']:
                    self.errors['__all__'] = self.error_class(["Cannot activate configuration client functionality because this node is already activated as configuration server."])            
                    raise forms.ValidationError("")

        return enabled
Beispiel #27
0
    def get_context_data(self, **kwargs):
        
        context = super(ViewClusterServerNodesList, self).get_context_data(**kwargs)

        # allocate default response
        data = { 
            'error' : False,  
            'desc'  : '',  
            'items' : {} 
        }
        
        try:
            # get the wssyncd port for the REST service
            wsport = 18889
            
            name = os.path.join(Paths.etc_dir(), "node", "wssyncd.json")
            with open(name) as fin:    
                wssyncd = json.load(fin)
                wsport  = wssyncd['rest_service']['port']

            # see if server is enabled
            name = os.path.join(Paths.etc_dir(), "node", "cluster_server.json")
            with open(name) as fin:    
                cluster = json.load(fin)
                print(cluster)

                if cluster['enabled']:
                    data['items'] = ClusterServerNodesList().run(wsport)
            
        except Exception as e:
            data['error'] = True
            data['desc']  = str(e)
        
        context['nodes'] = data

        return context
Beispiel #28
0
    def dump(self, cacert):

        cacert_path = os.path.join(Paths.etc_dir(), cacert)
        if not os.path.isfile(cacert_path):
            raise Exception("File %s does not exist or is not accessible!" %
                            cacert_path)

        args = [self.exe, "x509", "-in", cacert_path, "-text"]

        (exit_code, stdout, stderr) = Command().run(args)
        if exit_code != 0:
            raise Exception("Cannot run command %s, error:\n%s" %
                            (" ".join(args), stdout + stderr))

        # if everything is fine - return the cert contents
        return "%s\n%s" % (stdout, stderr)
Beispiel #29
0
    def get(self, request, *args, **kwargs):

        # construct the path
        path = os.path.join(Paths.etc_dir(), "squid",
                            "foreign_intermediate_certs.pem")

        # if no file exist, create it
        if not os.path.isfile(path):
            with open(path, "wb") as fin:
                pass

        # and send contents
        with open(path, "rb") as fin:
            response = HttpResponse(fin.read(),
                                    content_type="application/x-x509-ca-cert")
            response[
                'Content-Disposition'] = "attachment; filename=\"%s\"" % "foreign_intermediate_certs.pem"
            return response
Beispiel #30
0
    def get(self): # return (bool, license|error)
        
        try:
            
            # get contents of license key
            license = CommandLicense().run(Paths.etc_dir())

            # let's try to parse expires field into python date
            license['expires_in'] = self._parse_expires(license['expires'])

            # and return nicely
            return (True, license)

            # color = 'default','cyan'
                    
        except Exception as e:

            return (False, str(e))