def get_config(): """ Get the CRITs configuration. :returns: :class:`crits.config.config.CRITsConfig` """ crits_config = CRITsConfig.objects().first() if not crits_config: crits_config = CRITsConfig() crits_config.save() return crits_config
def clean_db(): """ Clean up the DB after testing. """ src = SourceAccess.objects(name=TSRC).first() if src: src.delete() user = CRITsUser.objects(username=TUSER_NAME).first() if user: user.delete() TestObject.drop_collection() TestSourceObject.drop_collection() CRITsConfig.drop_collection()
def _generate_request_instance(self, request_type): """Automatically generate a request instance to use. In the end, this saves us from having to load each request class in a explicit way. Loading via a string is helpful to reduce the code per call. """ crits_config = CRITsConfig.objects().first() http_proxy_value = None if crits_config.http_proxy: http_proxy_value = crits_config.http_proxy class_lookup = {'dns': 'DnsRequest', 'whois': 'WhoisRequest', 'ssl': 'SslRequest', 'enrichment': 'EnrichmentRequest', 'attributes': 'AttributeRequest'} class_name = class_lookup[request_type] mod = __import__('passivetotal.libs.%s' % request_type, fromlist=[class_name]) loaded = getattr(mod, class_name) headers = {'PT-INTEGRATION': 'CRITs'} authenticated = loaded(self.username, self.api_key, headers=headers, http_proxy=http_proxy_value, https_proxy=http_proxy_value) return authenticated
def change_user_password(username, current_p, new_p, new_p_c): """ Change the password for a user. :param username: The user to query for. :type username: str :param current_p: The user's current password. :type current_p: str :param new_p: The new password. :type new_p: str :param new_p_c: New password confirmation. :type new_p_c: str :returns: dict with keys "success" (boolean) and "message" (str) if failed. """ if new_p != new_p_c: return {'success': False, 'message': 'New password confirmation does not match.'} from crits.core.user import CRITsUser username = str(username) user = CRITsUser.objects(username=username).first() if not user: return {'success': False, 'message': 'Unknown user.'} if not user.check_password(current_p): return {'success': False, 'message': 'Current password invalid.'} if user.set_password(new_p, username): return {'success': True, 'message': 'Password Change Successful.'} else: from crits.config.config import CRITsConfig crits_config = CRITsConfig.objects().first() if crits_config: regex_desc = crits_config.password_complexity_desc else: regex_desc = settings.PASSWORD_COMPLEXITY_DESC return {'success': False, 'message': 'Password not complex enough: %s' % regex_desc}
def _generate_request_instance(self, request_type): """Automatically generate a request instance to use. In the end, this saves us from having to load each request class in a explicit way. Loading via a string is helpful to reduce the code per call. """ crits_config = CRITsConfig.objects().first() http_proxy_value = None if crits_config.http_proxy: http_proxy_value = crits_config.http_proxy class_lookup = { 'dns': 'DnsRequest', 'whois': 'WhoisRequest', 'ssl': 'SslRequest', 'enrichment': 'EnrichmentRequest', 'attributes': 'AttributeRequest' } class_name = class_lookup[request_type] mod = __import__('passivetotal.libs.%s' % request_type, fromlist=[class_name]) loaded = getattr(mod, class_name) headers = {'PT-INTEGRATION': 'CRITs'} authenticated = loaded(self.username, self.api_key, headers=headers, http_proxy=http_proxy_value, https_proxy=http_proxy_value) return authenticated
def __init__(self, username=None, email=None): """ Set the default subject, body, from address, and other bits. """ # set the user and email address to send to self.username = username self.email = email # grab the CRITs url to use for links crits_config = CRITsConfig.objects().first() self.instance_url = crits_config.instance_url if self.instance_url.endswith("/"): self.instance_url = self.instance_url[:-1] # set the email address to send this email from self.from_address = crits_config.crits_email # setup the email subject if crits_config.crits_email_end_tag: self.subject = "CRITs: Subscriptions and Notifications" + crits_config.crits_email_subject_tag else: self.subject = crits_config.crits_email_subject_tag + "CRITs: Subscriptions and Notifications" # start the body of the email comments_url = self.instance_url + reverse('crits-comments-views-activity') self.body = "Here's info on the latest comments and updates to CRITs that you are subscribed to!\n\n" self.body += "For more info, check out the Activity page: %s\n\n" % comments_url
def __init__(self, username=None, email=None): """ Set the default subject, body, from address, and other bits. """ # set the user and email address to send to self.username = username self.email = email # grab the CRITs url to use for links crits_config = CRITsConfig.objects().first() self.instance_url = crits_config.instance_url if self.instance_url.endswith("/"): self.instance_url = self.instance_url[:-1] # set the email address to send this email from self.from_address = crits_config.crits_email # setup the email subject if crits_config.crits_email_end_tag: self.subject = "CRITs: Subscriptions and Notifications" + crits_config.crits_email_subject_tag else: self.subject = crits_config.crits_email_subject_tag + "CRITs: Subscriptions and Notifications" # start the body of the email comments_url = self.instance_url + reverse( 'crits-comments-views-activity') self.body = "Here's info on the latest comments and updates to CRITs that you are subscribed to!\n\n" self.body += "For more info, check out the Activity page: %s\n\n" % comments_url
def reset_password(self, rcode, new_p, new_p_c, analyst): """ Reset the user's password. Validate the reset code, ensure the two passwords are identical, and then set. :param rcode: Reset Code to validate. :type rcode: str :param new_p: New password. :type new_p: str :param new_p_c: New password confirmation. :type new_p_c: str :param analyst: The user. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str). """ if self.validate_reset_code(rcode, analyst)['success']: if new_p == new_p_c: self.password_reset.reset_code = "" if self.set_password(new_p): return {'success': True, 'message': 'Password reset.'} else: crits_config = CRITsConfig.objects().first() if crits_config: pw_desc = crits_config.password_complexity_desc else: pw_desc = settings.PASSWORD_COMPLEXITY_DESC message = 'Password not complex enough: %s' % pw_desc return {'success': False, 'message': message} else: return {'success': False, 'message': 'Passwords do not match.'} else: self.password_reset.reset_code = "" self.save(username=analyst) return {'success': False, 'message': 'Reset Code Expired.'}
def upgrade(lv, options): """ Perform the upgrade. :param lv: The CRITs version we are running. :type lv: str :param options: The options passed in for what to upgrade. :type options: dict """ # eventually we will do something to check to see what the current version # of the CRITs DB is so we can upgrade through several versions at once. # this is important if prep scripts need to be run for certain upgrades # to work properly. mall = options.get('mall') campaigns = options.get('campaigns') domains = options.get('domains') emails = options.get('emails') events = options.get('events') indicators = options.get('indicators') ips = options.get('ips') pcaps = options.get('pcaps') samples = options.get('samples') targets = options.get('targets') skip = options.get('skip') sort_ids = options.get('sort_ids') # run prep migrations if not skip: prep_database() # run full migrations if mall or campaigns: migrate_collection(Campaign, sort_ids) if mall or domains: migrate_collection(Domain, sort_ids) if mall or emails: migrate_collection(Email, sort_ids) if mall or events: migrate_collection(Event, sort_ids) if mall or indicators: migrate_collection(Indicator, sort_ids) if mall or ips: migrate_collection(IP, sort_ids) if mall or pcaps: migrate_collection(PCAP, sort_ids) if mall or samples: migrate_collection(Sample, sort_ids) if mall or targets: migrate_collection(Target, sort_ids) # Always bump the version to the latest in settings.py config = CRITsConfig.objects() if len(config) > 1: print "You have more than one config object. This is really bad." else: config = config[0] config.crits_version = settings.CRITS_VERSION config.save()
def modify_configuration(config_form, analyst): """ Modify the configuration with the submitted changes. :param config_form: The form data. :type config_form: dict :param analyst: The user making the modifications. :type analyst: str :returns: dict with key "message" """ config = CRITsConfig.objects().first() if not config: config = CRITsConfig() data = config_form.cleaned_data allowed_hosts_list = data['allowed_hosts'].split(',') allowed_hosts = () for allowed_host in allowed_hosts_list: allowed_hosts = allowed_hosts + (allowed_host.strip(), ) data['allowed_hosts'] = allowed_hosts service_dirs_list = data['service_dirs'].split(',') service_dirs = () for service_dir in service_dirs_list: service_dirs = service_dirs + (service_dir.strip(), ) data['service_dirs'] = service_dirs config.merge(data, overwrite=True) try: config.save(username=analyst) return {'message': "Success!"} except Exception, e: return {'message': "Failure: %s" % e}
def authenticate(self, username, password=None, user_agent=None, remote_addr=None, accept_language=None, totp_enabled='Disabled'): """ Perform the authentication of the user. :param username: The user to authenticate. :type username: str :param password: The password provided to authenticate with. :type password: str :param user_agent: The user-agent in the request. :type user_agent: str :param remote_addr: The hostname/ip in the request. :type remote_addr: str :param accept_language: The Accept Language in the request. :type accept_language: str :param totp_enabled: If TOTP is enabled and should be checked as well. :type totp_enabled: str :returns: :class:`crits.core.user.CRITsUser`, None """ e = EmbeddedLoginAttempt() e.user_agent = user_agent e.remote_addr = remote_addr e.accept_language = accept_language if not username: logger.warn("No username passed to CRITsRemoteUserBackend (auth)") return None config = CRITsConfig.objects().first() user = None username = self.clean_username(username) user = CRITsUser.objects(username=username).first() if user and user.is_active: if self._exceeded_login_threshold(user): return None # Log in user self._successful_settings(user, e, totp_enabled) if config.ldap_update_on_login: user.update_from_ldap("Auto LDAP update", config) return user elif not user and config.create_unknown_user: # Create the user user = CRITsUser.create_user(username=username, password=None) user.sources.append(config.company_name) # Attempt to update info from LDAP user.update_from_ldap("Auto LDAP update", config) user = self._successful_settings(user, e, totp_enabled) return user else: logger.warn("Unknown user and not creating accounts.") return None
def create_config_if_not_exist(): """ If the CRITsConfig already exists then the CRITsConfig is returned, otherwise a new CRITsConfig will be created, saved, and returned. Returns: Returns the CRITsConfig if it already exists, otherwise a default CRITsConfig is returned. """ crits_config = CRITsConfig.objects().first() if not crits_config: print "Creating a new CRITs configuration." crits_config = CRITsConfig() crits_config.save() else: print "A CRITs configuration already exists. Skipping default creation." return crits_config
def email_user(self, subject, message, from_email=None): """ Sends an e-mail to this User. """ from django.core.mail import send_mail if not from_email: crits_config = CRITsConfig.objects().first() if crits_config: from_email = crits_config.crits_email send_mail(subject, message, from_email, [self.email])
def modify_configuration(config_form, analyst): """ Modify the configuration with the submitted changes. :param config_form: The form data. :type config_form: dict :param analyst: The user making the modifications. :type analyst: str :returns: dict with key "message" """ config = CRITsConfig.objects().first() if not config: config = CRITsConfig() data = config_form.cleaned_data allowed_hosts_list = data['allowed_hosts'].split(',') allowed_hosts = () for allowed_host in allowed_hosts_list: allowed_hosts = allowed_hosts + (allowed_host.strip(),) data['allowed_hosts'] = allowed_hosts service_dirs_list = data['service_dirs'].split(',') service_dirs = () for service_dir in service_dirs_list: service_dirs = service_dirs + (service_dir.strip(),) data['service_dirs'] = service_dirs config.merge(data, overwrite=True) try: config.save(username=analyst) return {'message': "Success!"} except Exception, e: return {'message': "Failure: %s" % e}
def handle(self, *args, **options): """ Script execution. """ username = options.get('username') firstname = options.get('firstname') lastname = options.get('lastname') email = options.get('email') sendemail = options.get('sendemail') admin = options.get('admin') organization = options.get('organization') password = self.temp_password() if not username: raise CommandError("Must provide a username.") if not email: raise CommandError("Must provide an email address.") user = CRITsUser.objects(username=username).first() if user: raise CommandError("User '%s' exists in CRITs!" % username) else: user = CRITsUser.create_user(username, password, email) user.first_name = firstname user.last_name = lastname user.is_staff = True user.save() user.organization = organization if admin: user.role = "Administrator" user.save() if sendemail: crits_config = CRITsConfig.objects().first() if crits_config.crits_email_end_tag: subject = "New CRITs User Account" + crits_config.crits_email_subject_tag else: subject = crits_config.crits_email_subject_tag + "New CRITs User Account" body = """You are receiving this email because someone has created a CRITs account for you. If you feel like you have received this in error, please ignore this email. Your account information is below:\n\n """ body += "Username:\t%s\n" % username body += "Password:\t%s\n\n\n" % password body += """You should log in immediately and reset your password.\n Thank you! """ user.email_user(subject, body) self.stdout.write("User '%s' created successfully!" % username) self.stdout.write("\nTemp password: \t%s" % password) self.stdout.write("\n")
def prep_db(): """ Prep the DB for testing. """ clean_db() # Create a new default config crits_config = CRITsConfig() crits_config.save() # Add Source handlers.add_new_source(TSRC, TRANDUSER) # Add User user = CRITsUser.create_user(username=TUSER_NAME, password=TUSER_PASS, email=TUSER_EMAIL) user.first_name = TUSER_FNAME user.last_name = TUSER_LNAME user.save() # Add test source object '''
def prep_db(): """ Prep the DB for testing. """ clean_db() # Create a new default config crits_config = CRITsConfig() crits_config.save() # Add Source handlers.add_new_source(TSRC, TRANDUSER) # Add User user = CRITsUser.create_user(username=TUSER_NAME, password=TUSER_PASS, email=TUSER_EMAIL ) user.first_name = TUSER_FNAME user.last_name = TUSER_LNAME user.save() # Add test source object '''
def prep_db(): """ Prep the DB for testing. """ clean_db() # Create a new default config crits_config = CRITsConfig() crits_config.save() # Add Source handlers.add_new_source(TSRC, TRANDUSER) # Add User user = CRITsUser.create_user( username=TUSER_NAME, password=TUSER_PASS, email=TUSER_EMAIL, ) user.first_name = TUSER_FNAME user.last_name = TUSER_LNAME user.save() # Add test source object obj = TestSourceObject() obj.name = TOBJS_NAME obj.value = TOBJS_VALUE obj.add_source(source=TSRC, analyst=TUSER_NAME) obj.save() # Add another with Different source obj = TestSourceObject() obj.name = TOBJS_NAME obj.value = TOBJS_VALUE obj.add_source(source=TUNKSRC, analyst=TRANDUSER) obj.save() # Add test non-source object obj = TestObject() obj.name = TOBJ_NAME obj.value = TOBJ_VALUE obj.save()
def crits_config(request): """ Generate the CRITs Configuration template. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ crits_config = CRITsConfig.objects().first() user = request.user if user.has_access_to(GeneralACL.CONTROL_PANEL_READ): if crits_config: crits_config = crits_config.to_dict() crits_config['allowed_hosts'] = ", ".join(crits_config['allowed_hosts']) crits_config['service_dirs'] = ", ".join(crits_config['service_dirs']) config_general_form = ConfigGeneralForm(initial=crits_config) config_LDAP_form = ConfigLDAPForm(initial=crits_config) config_security_form = ConfigSecurityForm(initial=crits_config) config_logging_form = ConfigLoggingForm(initial=crits_config) config_services_form = ConfigServicesForm(initial=crits_config) config_download_form = ConfigDownloadForm(initial=crits_config) config_CRITs_form = ConfigCritsForm(initial=crits_config) else: config_general_form = ConfigGeneralForm() config_LDAP_form = ConfigLDAPForm() config_security_form = ConfigSecurityForm() config_logging_form = ConfigLoggingForm() config_services_form = ConfigServicesForm() config_download_form = ConfigDownloadForm() config_CRITs_form = ConfigCritsForm() user_list = get_user_list() try: return render(request, 'config.html', {'config_general_form': config_general_form, 'config_LDAP_form': config_LDAP_form, 'config_security_form': config_security_form, 'config_logging_form': config_logging_form, 'config_services_form': config_services_form, 'config_download_form': config_download_form, 'config_CRITs_form': config_CRITs_form, 'user_list': user_list}) except Exception as e: # this should help troubleshooting config forms logger.error(e) else: return render(request, 'error.html', {'error': 'User does not have permission to view Control Panel.'})
def crits_config(request): """ Generate the CRITs Configuration template. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ crits_config = CRITsConfig.objects().first() user = request.user if user.has_access_to(GeneralACL.CONTROL_PANEL_READ): if crits_config: crits_config = crits_config.to_dict() crits_config['allowed_hosts'] = ", ".join( crits_config['allowed_hosts']) crits_config['service_dirs'] = ", ".join( crits_config['service_dirs']) config_general_form = ConfigGeneralForm(initial=crits_config) config_LDAP_form = ConfigLDAPForm(initial=crits_config) config_security_form = ConfigSecurityForm(initial=crits_config) config_logging_form = ConfigLoggingForm(initial=crits_config) config_services_form = ConfigServicesForm(initial=crits_config) config_download_form = ConfigDownloadForm(initial=crits_config) config_CRITs_form = ConfigCritsForm(initial=crits_config) else: config_general_form = ConfigGeneralForm() config_LDAP_form = ConfigLDAPForm() config_security_form = ConfigSecurityForm() config_logging_form = ConfigLoggingForm() config_services_form = ConfigServicesForm() config_download_form = ConfigDownloadForm() config_CRITs_form = ConfigCritsForm() return render_to_response( 'config.html', { 'config_general_form': config_general_form, 'config_LDAP_form': config_LDAP_form, 'config_security_form': config_security_form, 'config_logging_form': config_logging_form, 'config_services_form': config_services_form, 'config_download_form': config_download_form, 'config_CRITs_form': config_CRITs_form, }, RequestContext(request)) else: return render_to_response( 'error.html', {'error': 'User does not have permission to view Control Panel.'}, RequestContext(request))
def prep_db(): """ Prep the DB for testing. """ clean_db() # Create a new default config crits_config = CRITsConfig() crits_config.save() # Add Source handlers.add_new_source(TSRC, TRANDUSER) # Add User user = CRITsUser.create_user(username=TUSER_NAME, password=TUSER_PASS, email=TUSER_EMAIL, ) user.first_name = TUSER_FNAME user.last_name = TUSER_LNAME user.save() # Add test source object obj = TestSourceObject() obj.name = TOBJS_NAME obj.value = TOBJS_VALUE obj.add_source(source=TSRC, analyst=TUSER_NAME) obj.save() # Add another with Different source obj = TestSourceObject() obj.name = TOBJS_NAME obj.value = TOBJS_VALUE obj.add_source(source=TUNKSRC, analyst=TRANDUSER) obj.save() # Add test non-source object obj = TestObject() obj.name = TOBJ_NAME obj.value = TOBJ_VALUE obj.save()
def setup_access(): sc = get_config('ThreatExchange') config = CRITsConfig.objects().first() access_token.access_token(app_id=sc['app_id'], app_secret=sc['app_secret']) headers = None if len(sc['headers']) > 0: hlist = sc['headers'].split(',') headers = {} for h in hlist: tmp = h.split(':') if len(tmp) == 2: headers[tmp[0].strip()] = tmp[1].strip() proxies = {'http': config.http_proxy, 'https': config.http_proxy} connection(headers=headers, proxies=proxies, verify=sc['verify']) return
def force_reset_config(): """ Resets the values for the CRITsConfig class by dropping the database collection and then saving a new default CRITsConfig. """ print "Resetting CRITs configuration settings." CRITsConfig.drop_collection(); crits_config = CRITsConfig(); crits_config.save();
def info_from_ldap(self, config=None, password=''): """ Get information about this user from LDAP. """ import ldap, ldapurl resp = {"result": "ERROR"} if not config: config = CRITsConfig.objects().first() # Make sure we have the rquired settings, else return failure if not config.ldap_server or not config.ldap_userdn: return resp ldap_server = config.ldap_server.split(':') scheme = "ldap" if config.ldap_tls: scheme = "ldaps" url = ldapurl.LDAPUrl('%s://%s' % (scheme, ldap_server[0])) if len(ldap_server) == 2: l = ldap.initialize('%s:%s' % (url.unparse(), ldap_server[1])) else: l = ldap.initialize(url.unparse()) l.protocol_version = 3 l.set_option(ldap.OPT_REFERRALS, 0) l.set_option(ldap.OPT_TIMEOUT, 10) # setup auth for custom cn's cn = "cn=" if config.ldap_usercn: cn = config.ldap_usercn # setup auth for custom cn's if len(config.ldap_usercn) > 0: un = "%s%s,%s" % (config.ldap_usercn, self.username, config.ldap_userdn) elif "@" in config.ldap_userdn: un = "%s%s" % (self.username, config.ldap_userdn) else: un = self.username try: # Try auth bind first l.simple_bind_s(un, password) logger.info("Bound to LDAP for: %s" % self.username) except Exception, e: logger.error("Error binding to LDAP for: %s" % self.username) logger.error("ERR: %s" % e)
def __init__(self, *args, **kwargs): crits_config = CRITsConfig.objects().first() depth_max = getattr(crits_config, 'depth_max', settings.DEPTH_MAX) total_max = getattr(crits_config, 'total_max', settings.TOTAL_MAX) rel_max = getattr(crits_config, 'rel_max', settings.REL_MAX) super(DownloadFileForm, self).__init__(*args, **kwargs) self.fields['objects'].choices = [('Certificate', 'Certificates'), ('Domain', 'Domains'), ('Email', 'Emails'), ('Indicator', 'Indicators'), ('PCAP', 'PCAPs'), ('RawData', 'Raw Data'), ('Sample', 'Samples')] self.fields['total_limit'].initial = total_max self.fields['rel_limit'].initial = rel_max self.fields['depth_limit'].help_text = self.fields['depth_limit'].help_text % depth_max self.fields['total_limit'].help_text = self.fields['total_limit'].help_text % total_max self.fields['rel_limit'].help_text = self.fields['rel_limit'].help_text % rel_max
def crits_config(request): """ Generate the CRITs Configuration template. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ crits_config = CRITsConfig.objects().first() if crits_config: crits_config = crits_config.to_dict() crits_config["allowed_hosts"] = ", ".join(crits_config["allowed_hosts"]) crits_config["service_dirs"] = ", ".join(crits_config["service_dirs"]) config_form = ConfigForm(initial=crits_config) else: config_form = ConfigForm() return render_to_response("config.html", {"config_form": config_form}, RequestContext(request))
def is_password_complex(self, password): """ Based on the CRITsConfig, is the password provided complex enough to be used? :param password: The password to check for complexity. :type password: str :returns: True, False """ crits_config = CRITsConfig.objects().first() if crits_config: pw_regex = crits_config.password_complexity_regex else: pw_regex = settings.PASSWORD_COMPLEXITY_REGEX complex_regex = re.compile(pw_regex) if complex_regex.match(password): return True return False
def temp_password(self): """ Temporary password must match the password complexity regex. If we don't have one in the DB use the one out of settings. """ crits_config = CRITsConfig.objects().first() if crits_config: pw_regex = crits_config.password_complexity_regex else: pw_regex = settings.PASSWORD_COMPLEXITY_REGEX rex = re.compile(pw_regex) chars = string.letters + string.digits + string.punctuation for i in xrange(20): passwd = '' while len(passwd) < 50: passwd += choice(chars) if rex.match(passwd): return passwd raise CommandError("Unable to generate complex enough password.")
def crits_config(request): """ Generate the CRITs Configuration template. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ crits_config = CRITsConfig.objects().first() if crits_config: crits_config = crits_config.to_dict() crits_config['allowed_hosts'] = ", ".join( crits_config['allowed_hosts']) crits_config['service_dirs'] = ", ".join(crits_config['service_dirs']) config_form = ConfigForm(initial=crits_config) else: config_form = ConfigForm() return render_to_response('config.html', {'config_form': config_form}, RequestContext(request))
def crits_config(request): """ Generate the CRITs Configuration template. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ crits_config = CRITsConfig.objects().first() if crits_config: crits_config = crits_config.to_dict() crits_config['allowed_hosts'] = ", ".join( crits_config['allowed_hosts']) crits_config['service_dirs'] = ", ".join(crits_config['service_dirs']) config_general_form = ConfigGeneralForm(initial=crits_config) config_LDAP_form = ConfigLDAPForm(initial=crits_config) config_security_form = ConfigSecurityForm(initial=crits_config) config_logging_form = ConfigLoggingForm(initial=crits_config) config_services_form = ConfigServicesForm(initial=crits_config) config_download_form = ConfigDownloadForm(initial=crits_config) config_CRITs_form = ConfigCritsForm(initial=crits_config) else: config_general_form = ConfigGeneralForm() config_LDAP_form = ConfigLDAPForm() config_security_form = ConfigSecurityForm() config_logging_form = ConfigLoggingForm() config_services_form = ConfigServicesForm() config_download_form = ConfigDownloadForm() config_CRITs_form = ConfigCritsForm() return render_to_response( 'config.html', { 'config_general_form': config_general_form, 'config_LDAP_form': config_LDAP_form, 'config_security_form': config_security_form, 'config_logging_form': config_logging_form, 'config_services_form': config_services_form, 'config_download_form': config_download_form, 'config_CRITs_form': config_CRITs_form }, RequestContext(request))
def __init__(self, *args, **kwargs): crits_config = CRITsConfig.objects().first() depth_max = getattr(crits_config, "depth_max", settings.DEPTH_MAX) total_max = getattr(crits_config, "total_max", settings.TOTAL_MAX) rel_max = getattr(crits_config, "rel_max", settings.REL_MAX) super(DownloadFileForm, self).__init__(*args, **kwargs) self.fields["objects"].choices = [ ("Actor", "Actors"), ("Certificate", "Certificates"), ("Domain", "Domains"), ("Email", "Emails"), ("Indicator", "Indicators"), ("PCAP", "PCAPs"), ("RawData", "Raw Data"), ("Sample", "Samples"), ("Signature", "Signatures"), ] self.fields["total_limit"].initial = total_max self.fields["rel_limit"].initial = rel_max self.fields["depth_limit"].help_text = self.fields["depth_limit"].help_text % depth_max self.fields["total_limit"].help_text = self.fields["total_limit"].help_text % total_max self.fields["rel_limit"].help_text = self.fields["rel_limit"].help_text % rel_max
def crits_config(request): """ Generate the CRITs Configuration template. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ crits_config = CRITsConfig.objects().first() if crits_config: crits_config = crits_config.to_dict() crits_config['allowed_hosts'] = ", ".join(crits_config['allowed_hosts']) crits_config['service_dirs'] = ", ".join(crits_config['service_dirs']) config_general_form = ConfigGeneralForm(initial=crits_config) config_LDAP_form = ConfigLDAPForm(initial=crits_config) config_security_form = ConfigSecurityForm(initial=crits_config) config_logging_form = ConfigLoggingForm(initial=crits_config) config_services_form = ConfigServicesForm(initial=crits_config) config_download_form = ConfigDownloadForm(initial=crits_config) config_CRITs_form = ConfigCritsForm(initial=crits_config) else: config_general_form = ConfigGeneralForm() config_LDAP_form = ConfigLDAPForm() config_security_form = ConfigSecurityForm() config_logging_form = ConfigLoggingForm() config_services_form = ConfigServicesForm() config_download_form = ConfigDownloadForm() config_CRITs_form = ConfigCritsForm() return render_to_response('config.html', {'config_general_form': config_general_form, 'config_LDAP_form': config_LDAP_form, 'config_security_form': config_security_form, 'config_logging_form': config_logging_form, 'config_services_form': config_services_form, 'config_download_form': config_download_form, 'config_CRITs_form': config_CRITs_form}, RequestContext(request))
def info_from_ldap(self, config=None, password=''): """ Get information about this user from LDAP. """ import ldap, ldapurl resp = {"result": "ERROR"} if not config: config = CRITsConfig.objects().first() # Make sure we have the rquired settings, else return failure if not config.ldap_server or not config.ldap_userdn: return resp ldap_server = config.ldap_server.split(':') scheme = "ldap" if config.ldap_tls: scheme = "ldaps" url = ldapurl.LDAPUrl('%s://%s' % (scheme, ldap_server[0])) if len(ldap_server) == 2: l = ldap.initialize('%s:%s' % (url.unparse(), ldap_server[1])) else: l = ldap.initialize(url.unparse()) l.protocol_version = 3 l.set_option(ldap.OPT_REFERRALS, 0) l.set_option(ldap.OPT_TIMEOUT, 10) # setup auth for custom cn's cn = "cn=" if config.ldap_usercn: cn = config.ldap_usercn # two-step ldap binding if len(config.ldap_bind_dn) > 0: try: logger.info("binding with bind_dn: %s" % config.ldap_bind_dn) l.simple_bind_s(config.ldap_bind_dn, config.ldap_bind_password) filter = '(|(cn='+self.username+')(uid='+self.username+')(mail='+self.username+'))' # use the retrieved dn for the second bind un = l.search_s(config.ldap_userdn,ldap.SCOPE_SUBTREE,filter,['dn'])[0][0] except Exception as err: #logger.error("Error binding to LDAP for: %s" % config.ldap_bind_dn) logger.error("Error in info_from_ldap: %s" % err) l.unbind() if len(ldap_server) == 2: l = ldap.initialize('%s:%s' % (url.unparse(), ldap_server[1])) else: l = ldap.initialize(url.unparse()) l.protocol_version = 3 l.set_option(ldap.OPT_REFERRALS, 0) l.set_option(ldap.OPT_TIMEOUT, 10) else: un = self.username # setup auth for custom cn's if len(config.ldap_usercn) > 0: un = "%s%s,%s" % (config.ldap_usercn, self.username, config.ldap_userdn) elif "@" in config.ldap_userdn: un = "%s%s" % (self.username, config.ldap_userdn) try: # Try auth bind first l.simple_bind_s(un, password) logger.info("Bound to LDAP for: %s" % un) except Exception as e: #logger.error("Error binding to LDAP for: %s" % self.username) logger.error("info_from_ldap:ERR: %s" % e) try: uatr = None uatr = l.search_s(config.ldap_userdn, ldap.SCOPE_SUBTREE, '(|(cn='+self.username+')(uid='+self.username+'))' )[0][1] resp['first_name'] = uatr['givenName'][0] resp['last_name'] = uatr['sn'][0] resp['email'] = uatr['mail'][0] resp['result'] = "OK" logger.info("Retrieved LDAP info for: %s" % self.username) except Exception as e: #logger.error("Error retrieving LDAP info for: %s" % self.username) logger.error("info_from_ldap ERR: %s" % e) l.unbind() return resp
def authenticate(self, username=None, password=None, user_agent=None, remote_addr=None, accept_language=None, totp_enabled='Disabled'): """ Perform the authentication of the user. :param username: The user to authenticate. :type username: str :param password: The password provided to authenticate with. :type password: str :param user_agent: The user-agent in the request. :type user_agent: str :param remote_addr: The hostname/ip in the request. :type remote_addr: str :param accept_language: The Accept Language in the request. :type accept_language: str :param totp_enabled: If TOTP is enabled and should be checked as well. :type totp_enabled: str :returns: :class:`crits.core.user.CRITsUser`, None """ # Need username and password for logins, checkem both if not all([username, password]): return None e = EmbeddedLoginAttempt() e.user_agent = user_agent e.remote_addr = remote_addr e.accept_language = accept_language fusername = username if '\\' in username: username = username.split("\\")[1] user = CRITsUser.objects(username=username).first() if user: # If the user needs TOTP and it is not disabled system-wide, and # the user has exceeded the login threshold for this time period # don't go any further. Track the invalid login and return. if (((user.totp and totp_enabled == 'Optional') or totp_enabled == 'Required') and self._exceeded_login_threshold(user)): e.success = False self.track_login_attempt(user, e) user.reload() return None config = CRITsConfig.objects().first() if not config: return None if config.ldap_auth: import ldap, ldapurl try: # If you are using Oracle's server that's based on # Netscape's code, and your users can't login after # password expiration warning kicks in, you need: # python-ldap 2.4.15 installed and # import ldap.controls.pwdpolicy to fix it # import ldap.controls.pwdpolicy except ImportError: logger.info("ldap.controls.pwdpolicy not present.") try: # don't parse the port if there is one ldap_server = config.ldap_server.split(':') scheme = "ldap" if config.ldap_tls: scheme = "ldaps" url = ldapurl.LDAPUrl('%s://%s' % (scheme, ldap_server[0])) if len(ldap_server) == 2: l = ldap.initialize('%s:%s' % (url.unparse(), ldap_server[1])) else: l = ldap.initialize(url.unparse()) l.protocol_version = 3 l.set_option(ldap.OPT_REFERRALS, 0) l.set_option(ldap.OPT_TIMEOUT, 10) # setup auth for custom cn's if len(config.ldap_usercn) > 0: un = "%s%s,%s" % (config.ldap_usercn, fusername, config.ldap_userdn) elif "@" in config.ldap_userdn: un = "%s%s" % (fusername, config.ldap_userdn) else: un = fusername logger.info("Logging in user: %s" % un) l.simple_bind_s(un, password) user = self._successful_settings(user, e, totp_enabled) if config.ldap_update_on_login: user.update_from_ldap("Auto LDAP update", config, password) l.unbind() return user except ldap.INVALID_CREDENTIALS: l.unbind() logger.info("Invalid LDAP credentials for: %s" % un) except Exception, err: logger.info("LDAP Auth error: %s" % err) # If LDAP auth fails, attempt normal CRITs auth. # This will help with being able to use local admin accounts when # you have LDAP auth enabled. if password and user.check_password(password): self._successful_settings(user, e, totp_enabled) if config.ldap_update_on_login: user.update_from_ldap("Auto LDAP update", config) return user else: e.success = False user.invalid_login_attempts += 1 if user.is_active and user.invalid_login_attempts > settings.INVALID_LOGIN_ATTEMPTS: user.is_active = False logger.info("Account disabled due to too many invalid login attempts: %s" % user.username) if config.crits_email_end_tag: subject = "CRITs Account Lockout" + config.crits_email_subject_tag else: subject = config.crits_email_subject_tag + "CRITs Account Lockout" body = """ You are receiving this email because your CRITs account has been locked out due to too many invalid login attempts. If you did not perform this action, someone may be attempting to access your account. Please contact a site administrator to resolve. """ user.email_user(subject, body) self.track_login_attempt(user, e) user.reload()
def generate_indicator_jtable(request, option): """ Generate the jtable data for rendering in the list template. :param request: The request for this jtable. :type request: :class:`django.http.HttpRequest` :param option: Action to take. :type option: str of either 'jtlist', 'jtdelete', or 'inline'. :returns: :class:`django.http.HttpResponse` """ obj_type = Indicator type_ = "indicator" mapper = obj_type._meta['jtable_opts'] if option == "jtlist": # Sets display url details_url = mapper['details_url'] details_url_key = mapper['details_url_key'] fields = mapper['fields'] response = jtable_ajax_list(obj_type, details_url, details_url_key, request, includes=fields) return HttpResponse(json.dumps(response, default=json_handler), content_type="application/json") if option == "jtdelete": response = {"Result": "ERROR"} if jtable_ajax_delete(obj_type, request): response = {"Result": "OK"} return HttpResponse(json.dumps(response, default=json_handler), content_type="application/json") jtopts = { 'title': "Indicators", 'default_sort': mapper['default_sort'], 'listurl': reverse('crits.%ss.views.%ss_listing' % (type_, type_), args=('jtlist',)), 'deleteurl': reverse('crits.%ss.views.%ss_listing' % (type_, type_), args=('jtdelete',)), 'searchurl': reverse(mapper['searchurl']), 'fields': mapper['jtopts_fields'], 'hidden_fields': mapper['hidden_fields'], 'linked_fields': mapper['linked_fields'], 'details_link': mapper['details_link'], 'no_sort': mapper['no_sort'] } config = CRITsConfig.objects().first() print config.splunk_search_url if not config.splunk_search_url: del jtopts['fields'][1] jtable = build_jtable(jtopts, request) jtable['toolbar'] = [ { 'tooltip': "'All Indicators'", 'text': "'All'", 'click': "function () {$('#indicator_listing').jtable('load', {'refresh': 'yes'});}", 'cssClass': "'jtable-toolbar-center'", }, { 'tooltip': "'New Indicators'", 'text': "'New'", 'click': "function () {$('#indicator_listing').jtable('load', {'refresh': 'yes', 'status': 'New'});}", 'cssClass': "'jtable-toolbar-center'", }, { 'tooltip': "'In Progress Indicators'", 'text': "'In Progress'", 'click': "function () {$('#indicator_listing').jtable('load', {'refresh': 'yes', 'status': 'In Progress'});}", 'cssClass': "'jtable-toolbar-center'", }, { 'tooltip': "'Analyzed Indicators'", 'text': "'Analyzed'", 'click': "function () {$('#indicator_listing').jtable('load', {'refresh': 'yes', 'status': 'Analyzed'});}", 'cssClass': "'jtable-toolbar-center'", }, { 'tooltip': "'Deprecated Indicators'", 'text': "'Deprecated'", 'click': "function () {$('#indicator_listing').jtable('load', {'refresh': 'yes', 'status': 'Deprecated'});}", 'cssClass': "'jtable-toolbar-center'", }, { 'tooltip': "'Add Indicator'", 'text': "'Add Indicator'", 'click': "function () {$('#new-indicator').click()}", }, ] if config.splunk_search_url: for field in jtable['fields']: if field['fieldname'].startswith("'splunk"): field['display'] = """ function (data) { return '<a href="%s' + data.record.value + '"><img src="/new_images/splunk.png" /></a>'; } """ % config.splunk_search_url if option == "inline": return render_to_response("jtable.html", {'jtable': jtable, 'jtid': '%s_listing' % type_, 'button': '%ss_tab' % type_}, RequestContext(request)) else: return render_to_response("%s_listing.html" % type_, {'jtable': jtable, 'jtid': '%s_listing' % type_}, RequestContext(request))
def update_database_version(): c = CRITsConfig.objects().first() c.crits_version = "3.1.0" c.save()
def create_zip(files, pw_protect=True): """ Create a zip file. Creates a temporary directory to write files to on disk using :class:`tempfile`. Uses /usr/bin/zip as the zipping mechanism currently. Will password protect the zip file as a default. The password for the zip file defaults to "infected", but it can be changed in the config under zip7_password. :param files: The files to add to the zip file. :type files: list of files which are in the format of a list or tuple of (<filename>, <data>). :param pw_protect: To password protect the zip file or not. :type pw_protect: boolean :returns: :class:`crits.core.exceptions.ZipFileError`, str """ dumpdir = "" try: # Zip can take data from stdin to compress, but # you can't define the filenames within the archive, # they show up as "-". Therefore, we need to write # out the file, compress it and return the zip. # Save the sample as a file in a temp directory # NOTE: the following line was causing a "permission denied" exception. # Removed dir arg. from crits.config.config import CRITsConfig crits_config = CRITsConfig.objects().first() if crits_config: zip7_password = crits_config.zip7_password else: zip7_password = settings.ZIP7_PASSWORD dumpdir = tempfile.mkdtemp() #dir=temproot #write out binary files for f in files: filename = f[0] file_data = f[1] # make sure our desired path doesn't already exist (some files may # have the same name but different data) path = dumpdir + "/" + filename.encode("utf-8") i = 1 tmp = path while os.path.exists(tmp): tmp = path+"("+str(i)+")" i += 1 with open(tmp, "wb") as fh: fh.write(file_data) # Build the command line for zip # NOTE: forking subprocess instead of using Python's ZipFile library # because ZipFile does not allow us to create password-protected zip # archives, only read them. # -j don't include original filepath zipname = "zip.zip" #The name we give it doesn't really matter args = ["/usr/bin/zip", "-r", "-j", dumpdir+"/"+zipname, dumpdir] if pw_protect: args += ["-P", zip7_password] args += [dumpdir+"/"+zipname, dumpdir] proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # Give the process 30 seconds to complete, otherwise kill it waitSeconds = 30 while (proc.poll() is None and waitSeconds): time.sleep(1) waitSeconds -= 1 zipdata = "" if proc.returncode: # zip spit out an error errmsg = "Error while creating archive\n" + proc.stdout.read() raise ZipFileError, errmsg elif not waitSeconds: # Process timed out proc.terminate() raise ZipFileError, "Error:\nProcess failed to terminate" else: with open(dumpdir + "/" + zipname, "rb") as fh: zipdata = fh.read() if not len(zipdata): raise ZipFileError, "Error:\nThe zip archive contains no data" return zipdata except ZipFileError: raise except Exception, ex: errmsg = "" for err in ex.args: errmsg = errmsg + " " + unicode(err) raise ZipFileError, errmsg
class Command(BaseCommand): """ Script Class. """ option_list = BaseCommand.option_list + ( make_option('--adduser', '-a', dest='adduser', action='store_true', default=False, help='Add a new user to CRITs.'), make_option('--administrator', '-A', dest='admin', action='store_true', default=False, help='Make this user an administrator.'), make_option('--clearsecret', '-c', dest='clearsecret', action='store_true', default=False, help="Clear a user's secret."), make_option('--deactivateuser', '-d', dest='deactivate', action='store_true', default=False, help='Deactivate a user account.'), make_option('--email', '-e', dest='email', default=None, help='Email address of new user.'), make_option('--sendemail', '-E', dest='sendemail', action='store_true', default=False, help='Email new user their temporary password.'), make_option('--firstname', '-f', dest='firstname', default='', help='First name of new user.'), make_option('--invalidreset', '-i', dest='invalidreset', action='store_true', default=False, help="Reset a user's invalid login attempts to 0."), make_option('--lastname', '-l', dest='lastname', default='', help='Last name of new user.'), make_option('--organization', '-o', dest='organization', default='', help='Assign user to an organization/source.'), make_option('--reset', '-r', dest='reset', action='store_true', default=False, help='Assign a new temporary password to a user.'), make_option('--setactive', '-s', dest='setactive', action='store_true', default=False, help='Set a user account to active.'), make_option('--enabletotp', '-t', dest='enabletotp', action='store_true', default=False, help='Enable TOTP for a user.'), make_option('--disabletotp', '-T', dest='disabletotp', action='store_true', default=False, help='Disable TOTP for a user.'), make_option('--username', '-u', dest='username', default=None, help='Username for new user.'), ) help = 'Add and edit a CRITs user. If "-a" is not used, we will try to edit.' def handle(self, *args, **options): """ Script execution. """ adduser = options.get('adduser') admin = options.get('admin') clearsecret = options.get('clearsecret') deactivate = options.get('deactivate') disabletotp = options.get('disabletotp') email = options.get('email') enabletotp = options.get('enabletotp') firstname = options.get('firstname') invalidreset = options.get('invalidreset') lastname = options.get('lastname') sendemail = options.get('sendemail') organization = options.get('organization') password = self.temp_password() reset = options.get('reset') setactive = options.get('setactive') username = options.get('username') # We always need a username if not username: raise CommandError("Must provide a username.") user = CRITsUser.objects(username=username).first() # If we've found a user with that username and we aren't trying to add a # new user... if user and not adduser: if admin: user.role = "Adminstrator" if clearsecret: user.secret = "" if deactivate and not setactive: user.is_active = False if disabletotp and not enabletotp: user.totp = False if email: user.email = email if enabletotp and not disabletotp: user.totp = True if firstname: user.first_name = firstname if lastname: user.last_name = lastname if invalidreset: user.invalid_login_attempts = 0 if organization: user.organization = organization if reset: user.set_password(password) if setactive and not deactivate: user.is_active = True try: user.save() if reset: print "New temporary password for %s: %s" % (username, password) print "User %s has been updated!" % username except Exception, e: raise CommandError("Error saving changes: %s" % str(e)) if adduser: raise CommandError("User '%s' exists in CRITs!" % username) elif adduser: if not email: raise CommandError("Must provide an email address!") user = CRITsUser.create_user(username, password, email) user.first_name = firstname user.last_name = lastname user.is_staff = True user.save() user.organization = organization if admin: user.role = "Administrator" user.save() if sendemail: crits_config = CRITsConfig.objects().first() if crits_config.crits_email_end_tag: subject = "New CRITs User Account" + crits_config.crits_email_subject_tag else: subject = crits_config.crits_email_subject_tag + "New CRITs User Account" body = """You are receiving this email because someone has created a CRITs account for you. If you feel like you have received this in error, please ignore this email. Your account information is below:\n\n """ body += "Username:\t%s\n" % username body += "Password:\t%s\n\n\n" % password body += """You should log in immediately and reset your password.\n Thank you! """ user.email_user(subject, body) self.stdout.write("User '%s' created successfully!" % username) self.stdout.write("\nTemp password: \t%s" % password) self.stdout.write("\n")
def modify_config(request): """ Modify the CRITs Configuration. Should be an AJAX POST. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ from django.forms.util import ErrorList # Get the current configuration, set as default unless user has permission to edit. crits_config = CRITsConfig.objects().first() config_data = crits_config.__dict__.get('_data') analyst = request.user.username user = request.user errors = [] permission_error = False if request.method == "POST" and request.is_ajax(): if user.has_access_to(GeneralACL.CONTROL_PANEL_GENERAL_EDIT): config_general_form = ConfigGeneralForm(request.POST) else: config_general_form = ConfigGeneralForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_LDAP_EDIT): config_LDAP_form = ConfigLDAPForm(request.POST) else: config_LDAP_form = ConfigLDAPForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_SECURITY_EDIT): config_security_form = ConfigSecurityForm(request.POST) else: new_allowed_hosts = [] for host in config_data['allowed_hosts']: new_allowed_hosts.append(str(host)) config_data['allowed_hosts'] = ','.join(new_allowed_hosts) config_security_form = ConfigSecurityForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_LOGGING_EDIT): config_logging_form = ConfigLoggingForm(request.POST) else: config_logging_form = ConfigLoggingForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_SYSTEM_SERVICES_EDIT): config_services_form = ConfigServicesForm(request.POST) else: new_service_dirs = [] for directory in config_data['service_dirs']: new_service_dirs.append(str(directory)) config_data['service_dirs'] = ','.join(new_service_dirs) config_services_form = ConfigServicesForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_DOWNLOADING_EDIT): config_download_form = ConfigDownloadForm(request.POST) else: config_download_form = ConfigDownloadForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_CRITS_EDIT): config_CRITs_form = ConfigCritsForm(request.POST) else: config_CRITs_form = ConfigCritsForm(config_data) permission_error = True forms = [ config_general_form, config_LDAP_form, config_security_form, config_logging_form, config_services_form, config_download_form, config_CRITs_form ] #Used in defining the error message displayed to the user errorStringDict = { "ConfigGeneralForm": "General", "ConfigLDAPForm": "LDAP", "ConfigSecurityForm": "Security", "ConfigLoggingForm": "Logging", "ConfigServicesForm": "Services", "ConfigDownloadForm": "Downloading", "ConfigCritsForm": "CRITs", } #iterate over all the forms, checking if they're valid #if the form is valid, remove it from the errorStringDict for form in forms: if form.is_valid(): formName = type(form).__name__ errorStringDict.pop(formName, None) else: errors.extend(form.errors) #submit if the errorStringDict is empty if not errorStringDict and not permission_error: result = modify_configuration(forms, analyst) message = result['message'] elif permission_error: message = "User does not have permission to edit form." elif len(errorStringDict) == 2: formsWithErrors = " and ".join(errorStringDict.values()) message = "Invalid Form: The " + formsWithErrors + " tabs have errors." elif len( errorStringDict ) > 1: #if there are multiple tabs with errors, pluralize the error message formsWithErrors = ", ".join(errorStringDict.values()) lastWhiteSpace = formsWithErrors.rfind(" ") formsWithErrors = formsWithErrors[: lastWhiteSpace] + " and " + formsWithErrors[ lastWhiteSpace:] message = "Invalid Form: The " + formsWithErrors + " tabs have errors." else: #if there is only one tab with errors, make the error message singular formsWithErrors = errorStringDict.values()[0] message = "Invalid Form: The " + formsWithErrors + " tab has errors." message = {'message': message, 'errors': errors} return HttpResponse(json.dumps(message), content_type="application/json") else: return render_to_response('error.html', {'error': 'Expected AJAX POST'}, RequestContext(request))
def create_zip(files, pw_protect=True): """ Create a zip file. Creates a temporary directory to write files to on disk using :class:`tempfile`. Uses /usr/bin/zip as the zipping mechanism currently. Will password protect the zip file as a default. The password for the zip file defaults to "infected", but it can be changed in the config under zip7_password. :param files: The files to add to the zip file. :type files: list of files which are in the format of a list or tuple of (<filename>, <data>). :param pw_protect: To password protect the zip file or not. :type pw_protect: boolean :returns: :class:`crits.core.exceptions.ZipFileError`, str """ dumpdir = "" try: # Zip can take data from stdin to compress, but # you can't define the filenames within the archive, # they show up as "-". Therefore, we need to write # out the file, compress it and return the zip. # Save the sample as a file in a temp directory # NOTE: the following line was causing a "permission denied" exception. # Removed dir arg. from crits.config.config import CRITsConfig crits_config = CRITsConfig.objects().first() if crits_config: zip7_password = crits_config.zip7_password else: zip7_password = settings.ZIP7_PASSWORD dumpdir = tempfile.mkdtemp() #dir=temproot #write out binary files for f in files: filename = f[0] file_data = f[1] # make sure our desired path doesn't already exist (some files may # have the same name but different data) path = dumpdir + "/" + filename.encode("utf-8") i = 1 tmp = path while os.path.exists(tmp): tmp = path + "(" + str(i) + ")" i += 1 with open(tmp, "wb") as fh: fh.write(file_data) # Build the command line for zip # NOTE: forking subprocess instead of using Python's ZipFile library # because ZipFile does not allow us to create password-protected zip # archives, only read them. # -j don't include original filepath zipname = "zip.zip" #The name we give it doesn't really matter args = ["/usr/bin/zip", "-r", "-j", dumpdir + "/" + zipname, dumpdir] if pw_protect: args += ["-P", zip7_password] args += [dumpdir + "/" + zipname, dumpdir] proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # Give the process 30 seconds to complete, otherwise kill it waitSeconds = 30 while (proc.poll() is None and waitSeconds): time.sleep(1) waitSeconds -= 1 zipdata = "" if proc.returncode: # zip spit out an error errmsg = "Error while creating archive\n" + proc.stdout.read() raise ZipFileError, errmsg elif not waitSeconds: # Process timed out proc.terminate() raise ZipFileError, "Error:\nProcess failed to terminate" else: with open(dumpdir + "/" + zipname, "rb") as fh: zipdata = fh.read() if not len(zipdata): raise ZipFileError, "Error:\nThe zip archive contains no data" return zipdata except ZipFileError: raise except Exception, ex: errmsg = "" for err in ex.args: errmsg = errmsg + " " + unicode(err) raise ZipFileError, errmsg
def modify_config(request): """ Modify the CRITs Configuration. Should be an AJAX POST. :param request: Django request object (Required) :type request: :class:`django.http.HttpRequest` :returns: :class:`django.http.HttpResponse` """ # Get the current configuration, set as default unless user has permission to edit. crits_config = CRITsConfig.objects().first() config_data = crits_config.__dict__.get('_data') analyst = request.user.username user = request.user errors = [] permission_error = False if request.method == "POST" and request.is_ajax(): if user.has_access_to(GeneralACL.CONTROL_PANEL_GENERAL_EDIT): config_general_form = ConfigGeneralForm(request.POST) else: config_general_form = ConfigGeneralForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_LDAP_EDIT): config_LDAP_form = ConfigLDAPForm(request.POST) else: config_LDAP_form = ConfigLDAPForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_SECURITY_EDIT): config_security_form = ConfigSecurityForm(request.POST) else: new_allowed_hosts = [] for host in config_data['allowed_hosts']: new_allowed_hosts.append(str(host)) config_data['allowed_hosts'] = ','.join(new_allowed_hosts) config_security_form = ConfigSecurityForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_LOGGING_EDIT): config_logging_form = ConfigLoggingForm(request.POST) else: config_logging_form = ConfigLoggingForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_SYSTEM_SERVICES_EDIT): config_services_form = ConfigServicesForm(request.POST) else: new_service_dirs = [] for directory in config_data['service_dirs']: new_service_dirs.append(str(directory)) config_data['service_dirs'] = ','.join(new_service_dirs) config_services_form = ConfigServicesForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_DOWNLOADING_EDIT): config_download_form = ConfigDownloadForm(request.POST) else: config_download_form = ConfigDownloadForm(config_data) permission_error = True if user.has_access_to(GeneralACL.CONTROL_PANEL_CRITS_EDIT): config_CRITs_form = ConfigCritsForm(request.POST) else: config_CRITs_form = ConfigCritsForm(config_data) permission_error = True forms = [config_general_form, config_LDAP_form, config_security_form, config_logging_form, config_services_form, config_download_form, config_CRITs_form] #Used in defining the error message displayed to the user errorStringDict = { "ConfigGeneralForm": "General", "ConfigLDAPForm": "LDAP", "ConfigSecurityForm": "Security", "ConfigLoggingForm": "Logging", "ConfigServicesForm": "Services", "ConfigDownloadForm": "Downloading", "ConfigCritsForm": "CRITs", } #iterate over all the forms, checking if they're valid #if the form is valid, remove it from the errorStringDict for form in forms: if form.is_valid(): formName = type(form).__name__ errorStringDict.pop(formName, None) else: errors.extend(form.errors) #submit if the errorStringDict is empty if not errorStringDict and not permission_error: result = modify_configuration(forms, analyst) message = result['message'] elif permission_error: message = "User does not have permission to edit form." elif len(errorStringDict) == 2: formsWithErrors = " and ".join(errorStringDict.values()) message = "Invalid Form: The " + formsWithErrors + " tabs have errors." elif len(errorStringDict) > 1: #if there are multiple tabs with errors, pluralize the error message formsWithErrors = ", ".join(errorStringDict.values()) lastWhiteSpace = formsWithErrors.rfind(" ") formsWithErrors = formsWithErrors[:lastWhiteSpace] + " and " + formsWithErrors[lastWhiteSpace:] message = "Invalid Form: The " + formsWithErrors + " tabs have errors." else: #if there is only one tab with errors, make the error message singular formsWithErrors = errorStringDict.values()[0] message = "Invalid Form: The " + formsWithErrors + " tab has errors." message = {'message': message, 'errors': errors} return HttpResponse(json.dumps(message), content_type="application/json") else: return render_to_response('error.html', {'error': 'Expected AJAX POST'}, RequestContext(request))