def signal_server_event_db(self, _, event_type, rows): get_node = lambda id: self.rpc.graphql(self.node_query, {'id': str(id)})['db']['node'] for row in rows: if str(row.campaign_id) != self.config['campaign_id']: continue model = self.gobjects['treeview_campaign'].get_model() for case in utilities.switch(event_type): if case('inserted'): row_data = self.format_node_data(get_node(row.id)) row_data = list(map(self.format_cell_data, row_data)) row_data.insert(0, str(row.id)) gui_utilities.glib_idle_add_wait(model.append, row_data) ti = gui_utilities.gtk_list_store_search(model, str(row.id)) if ti is None: self.logger.warning( "received server db event: {0} for non-existent row {1}:{2}" .format(event_type, self.table_name, str(row.id))) break if case('deleted'): model.remove(ti) break if case('updated'): row_data = self.format_node_data(get_node(row.id)) for idx, cell_data in enumerate(row_data, 1): model[ti][idx] = self.format_cell_data(cell_data) break
def session_has_permissions(self, access, session): """ Check that the authenticated session has the permissions specified in *access*. The permissions in *access* are abbreviated with the first letter of create, read, update, and delete. :param str access: The desired permissions. :param session: The authenticated session to check access for. :return: Whether the session has the desired permissions. :rtype: bool """ if self.is_private: return False access = access.lower() for case in utilities.switch(access, comp=operator.contains, swapped=True): if case('c') and not self.session_has_create_access(session): break if case('r') and not self.session_has_read_access(session): break if case('u') and not self.session_has_update_access(session): break if case('d') and not self.session_has_delete_access(session): break else: return True return False
def main(): parser = argparse.ArgumentParser(description='King Phisher TOTP Enrollment Utility', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', type=argparse.FileType('r'), help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') parser.add_argument('--otp', dest='otp_secret', help='a specific otp secret') parser.add_argument('user', help='the user to mange') parser.add_argument('action', choices=('remove', 'set', 'show'), help='the action to preform') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() utilities.configure_stream_logger(arguments.loglvl, arguments.logger) if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = yaml.load(arguments.server_config) database_connection_url = server_config['server']['database'] else: raise RuntimeError('no database connection was specified') manager.init_database(database_connection_url) session = manager.Session() user = session.query(models.User).filter_by(id=arguments.user).first() if not user: color.print_error("invalid user id: {0}".format(arguments.user)) return for case in utilities.switch(arguments.action): if case('remove'): user.otp_secret = None break if case('set'): if user.otp_secret: color.print_error("the specified user already has an otp secret set") return if arguments.otp_secret: new_otp = arguments.otp_secret else: new_otp = pyotp.random_base32() if len(new_otp) != 16: color.print_error("invalid otp secret length, must be 16") return user.otp_secret = new_otp break if user.otp_secret: color.print_status("user: {0} otp: {1}".format(user.id, user.otp_secret)) totp = pyotp.TOTP(user.otp_secret) uri = totp.provisioning_uri(user.id + '@king-phisher') + '&issuer=King%20Phisher' color.print_status("provisioning uri: {0}".format(uri)) else: color.print_status("user: {0} otp: N/A".format(user.id)) session.commit()
def to_elementtree_subelement(parent, tag, value, attrib=None): """ Serialize *value* to an :py:class:`xml.etree.ElementTree.SubElement` with appropriate information describing it's type. If *value* is not of a supported type, a :py:exc:`TypeError` will be raised. :param parent: The parent element to associate this subelement with. :type parent: :py:class:`xml.etree.ElementTree.Element` :param str tag: The name of the XML tag. :param value: The value to serialize to an XML element. :param dict attrib: Optional attributes to include in the element. :return: The newly created XML element, representing *value*. :rtype: :py:class:`xml.etree.ElementTree.Element` """ attrib = attrib or {} for case in switch(type(value)): if case(type(None)): value = '' type_ = 'null' break if case(bool): value = str(value).lower() type_ = 'boolean' break if case(datetime.date): value = value.isoformat() type_ = 'date' break if case(datetime.datetime): value = value.isoformat() type_ = 'datetime' break if case(float): value = str(value) type_ = 'float' break if case(int): value = str(value) type_ = 'integer' break if case(str): type_ = 'string' break if case(datetime.time): value = value.isoformat() type_ = 'time' break else: raise TypeError('can not serialize value to an xml subelement') attrib['type'] = type_ sub_element = ET.SubElement(parent, tag, attrib=attrib) sub_element.text = value return sub_element
def to_elementtree_subelement(parent, tag, value, attrib=None): """ Serialize *value* to an :py:class:`xml.etree.ElementTree.SubElement` with appropriate information describing it's type. If *value* is not of a supported type, a :py:exc:`TypeError` will be raised. :param parent: The parent element to associate this subelement with. :type parent: :py:class:`xml.etree.ElementTree.Element` :param str tag: The name of the XML tag. :param value: The value to serialize to an XML element. :param dict attrib: Optional attributes to include in the element. :return: The newly created XML element, representing *value*. :rtype: :py:class:`xml.etree.ElementTree.Element` """ attrib = attrib or {} for case in switch(type(value)): if case(type(None)): value = '' type_ = 'null' break if case(bool): value = str(value).lower() type_ = 'boolean' break if case(datetime.date): value = value.isoformat() type_ = 'date' break if case(datetime.datetime): value = value.isoformat() type_ = 'datetime' break if case(float): value = str(value) type_ = 'float' break if case(int): value = str(value) type_ = 'integer' break if case(str) or (its.py_v2 and case(unicode)): type_ = 'string' break if case(datetime.time): value = value.isoformat() type_ = 'time' break else: raise TypeError('can not serialize value to an xml subelement') attrib['type'] = type_ sub_element = ET.SubElement(parent, tag, attrib=attrib) sub_element.text = value return sub_element
def _json_default(obj): for case in switch(obj.__class__): if case(datetime.date): obj_type, obj_value = 'datetime.date', obj.isoformat() break if case(datetime.datetime): obj_type, obj_value = 'datetime.datetime', obj.isoformat() break if case(datetime.time): obj_type, obj_value = 'datetime.time', obj.isoformat() break else: raise TypeError('Unknown type: ' + repr(obj)) return {'__complex_type__': obj_type, 'value': obj_value}
def _serialize_ext_load(obj_type, obj_value, default): for case in switch(obj_type): if case('datetime.date'): value = datetime.datetime.strptime(obj_value, '%Y-%m-%d').date() break if case('datetime.datetime'): value = datetime.datetime.strptime(obj_value, '%Y-%m-%dT%H:%M:%S' + ('.%f' if '.' in obj_value else '')) break if case('datetime.time'): value = datetime.datetime.strptime(obj_value, '%H:%M:%S' + ('.%f' if '.' in obj_value else '')).time() break else: return default return value
def _serialize_ext_dump(obj): for case in switch(obj.__class__): if case(datetime.date): obj_type, obj_value = 'datetime.date', obj.isoformat() break if case(datetime.datetime): obj_type, obj_value = 'datetime.datetime', obj.isoformat() break if case(datetime.time): obj_type, obj_value = 'datetime.time', obj.isoformat() break else: raise TypeError('Unknown type: ' + repr(obj)) return obj_type, obj_value
def _serialize_ext_load(obj_type, obj_value, default): for case in switch(obj_type): if case('datetime.date'): value = dateutil.parser.parse(obj_value).date() break if case('datetime.datetime'): value = dateutil.parser.parse(obj_value) break if case('datetime.time'): value = dateutil.parser.parse(obj_value).time() break else: return default return value
def _json_object_hook(obj): obj_type = obj.get('__complex_type__') obj_value = obj.get('value') for case in switch(obj_type): if case('datetime.date'): value = datetime.datetime.strptime(obj_value, '%Y-%m-%d').date() break if case('datetime.datetime'): value = datetime.datetime.strptime(obj_value, '%Y-%m-%dT%H:%M:%S' + ('.%f' if '.' in obj_value else '')) break if case('datetime.time'): value = datetime.datetime.strptime(obj_value, '%H:%M:%S' + ('.%f' if '.' in obj_value else '')).time() break else: return obj return value
def from_elementtree_element(element, require_type=True): """ Load a value from an :py:class:`xml.etree.ElementTree.SubElement` instance. If *require_type* is True, then the element must specify an acceptable value via the "type" attribute. If *require_type* is False and no type attribute is specified, the value is returned as a string. :param element: The element to load a value from. :type element: :py:class:`xml.etree.ElementTree.Element` :param bool require_type: Whether or not to require type information. :return: The deserialized value from the element. """ if require_type and not 'type' in element.attrib: raise TypeError('type is not specified in the element attributes') type_ = element.attrib.get('type', 'string') value = element.text for case in switch(type_): if case('boolean'): value = value.lower() if not value in ('true', 'false'): raise ValueError('unknown boolean value: ' + value) value = value == 'true' break if case('date'): value = dateutil.parser.parse(value).date() break if case('datetime'): value = dateutil.parser.parse(value) break if case('float'): value = float(value) break if case('integer'): value = int(value) break if case('null'): value = None break if case('string'): value = value or '' break if case('time'): value = dateutil.parser.parse(value).time() else: raise TypeError('can not serialize value to an xml subelement') return value
def session_has_permissions(self, access, session): """ Check that the authenticated session has the permissions specified in *access*. The permissions in *access* are abbreviated with the first letter of create, read, update, and delete. For example, to check for read and update permissions, *access* would be ``'ru'``. .. note:: This will always return ``True`` for sessions which are for administrative users. To maintain this logic, this method **should not** be overridden in subclasses. Instead override the specific ``_session_has_*_access`` methods as necessary. :param str access: The desired permissions. :param session: The authenticated session to check access for. :return: Whether the session has the desired permissions. :rtype: bool """ if session.user_is_admin: return True cls = self.__class__ if cls.is_private: return False access = access.lower() for case in utilities.switch(access, comp=operator.contains, swapped=True): if case('c') and not cls.session_has_create_access(session, instance=self): break if case('r') and not cls.session_has_read_access(session, instance=self): break if case('u') and not cls.session_has_update_access(session, instance=self): break if case('d') and not cls.session_has_delete_access(session, instance=self): break else: return True return False
def signal_server_event_db(self, _, event_type, rows): get_node = lambda id: self.rpc.graphql(self.node_query, {'id': str(id)})['db']['node'] for row in rows: if str(row.campaign_id) != self.config['campaign_id']: continue for case in utilities.switch(event_type): if case('inserted'): row_data = (str(row.id),) + tuple(self.format_node_data(get_node(row.id))) gui_utilities.glib_idle_add_wait(self._tv_model.append, row_data) ti = gui_utilities.gtk_list_store_search(self._tv_model, str(row.id)) if ti is None: self.logger.warning("received server db event: {0} for non-existent row {1}:{2}".format(event_type, self.table_name, str(row.id))) break if case('deleted'): self._tv_model.remove(ti) break if case('updated'): row_data = self.format_node_data(get_node(row.id)) for idx, cell_data in enumerate(row_data, 1): self._tv_model[ti][idx] = cell_data break
def __init__(self, organizer_email, start, summary, organizer_cn=None, description=None, duration='1h', location=None): """ :param str organizer_email: The email of the event organizer. :param start: The start time for the event. :type start: :py:class:`datetime.datetime` :param str summary: A short summary of the event. :param str organizer_cn: The name of the event organizer. :param str description: A more complete description of the event than what is provided by the *summary* parameter. :param duration: The events scheduled duration. :type duration: int, str, :py:class:`~datetime.timedelta`, :py:class:`.DurationAllDay` :param str location: The location for the event. """ utilities.assert_arg_type(start, datetime.datetime, 2) super(Calendar, self).__init__() if start.tzinfo is None: start = start.replace(tzinfo=dateutil.tz.tzlocal()) start = start.astimezone(dateutil.tz.tzutc()) for case in utilities.switch(duration, comp=isinstance): if case(str): duration = smoke_zephyr.utilities.parse_timespan(duration) duration = datetime.timedelta(seconds=duration) break if case(int): duration = datetime.timedelta(seconds=duration) break if case(datetime.timedelta): break if case(DurationAllDay): break else: raise TypeError('unknown duration type') self.add('method', 'REQUEST') self.add('prodid', 'Microsoft Exchange Server 2010') self.add('version', '2.0') self._event = icalendar.Event() event = self._event self.add_component(event) self.add_component(Timezone()) organizer = icalendar.vCalAddress('MAILTO:' + organizer_email) organizer.params['cn'] = icalendar.vText(organizer_cn or organizer_email) event['organizer'] = organizer event.add('description', description or summary) event.add('uid', str(uuid.uuid4())) event.add('summary', summary) if isinstance(duration, DurationAllDay): event.add('dtstart', start.date()) event.add('dtend', (start + datetime.timedelta(days=duration.days)).date()) else: event.add('dtstart', start) event.add('dtend', start + duration) event.add('class', 'PUBLIC') event.add('priority', 5) event.add('dtstamp', datetime.datetime.now(dateutil.tz.tzutc())) event.add('transp', 'OPAQUE') event.add('status', 'CONFIRMED') event.add('sequence', 0) if location: event.add('location', icalendar.vText(location)) alarm = icalendar.Alarm() alarm.add('description', 'REMINDER') alarm.add('trigger;related=start', '-PT1H') alarm.add('action', 'DISPLAY') event.add_component(alarm)
def main(): parser = argparse.ArgumentParser( conflict_handler='resolve', description=PARSER_DESCRIPTION, epilog=PARSER_EPILOG, formatter_class=argparse.RawTextHelpFormatter) utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') parser.add_argument('--force', dest='force', action='store_true', default=False, help='create the user if necessary') parser.add_argument('--otp', dest='otp_secret', help='a specific otp secret') if has_qrcode: parser.add_argument('--qrcode', dest='qrcode_filename', help='generate a qrcode image file') parser.add_argument('user', help='the user to mange') parser.add_argument('action', choices=('remove', 'set', 'show'), help='the action to preform') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = configuration.ex_load_config(arguments.server_config) database_connection_url = server_config.get('server.database') else: raise RuntimeError('no database connection was specified') manager.init_database(database_connection_url) session = manager.Session() user = session.query(models.User).filter_by(name=arguments.user).first() if not user: if not arguments.force: color.print_error("invalid user id: {0}".format(arguments.user)) return user = models.User(name=arguments.user) session.add(user) color.print_status('the specified user was created') for case in utilities.switch(arguments.action): if case('remove'): user.otp_secret = None break if case('set'): if user.otp_secret: color.print_error( "the specified user already has an otp secret set") return if arguments.otp_secret: new_otp = arguments.otp_secret else: new_otp = pyotp.random_base32() if len(new_otp) != 16: color.print_error("invalid otp secret length, must be 16") return user.otp_secret = new_otp break if user.otp_secret: color.print_status("user: {0} otp: {1}".format(user.name, user.otp_secret)) totp = pyotp.TOTP(user.otp_secret) uri = totp.provisioning_uri(user.name + '@king-phisher') + '&issuer=King%20Phisher' color.print_status("provisioning uri: {0}".format(uri)) if has_qrcode and arguments.qrcode_filename: img = qrcode.make(uri) img.save(arguments.qrcode_filename) color.print_status("wrote qrcode image to: " + arguments.qrcode_filename) else: color.print_status("user: {0} otp: N/A".format(user.id)) session.commit()
def main(): parser = argparse.ArgumentParser(description='King Phisher TOTP Enrollment Utility', conflict_handler='resolve') utilities.argp_add_args(parser) config_group = parser.add_mutually_exclusive_group(required=True) config_group.add_argument('-c', '--config', dest='server_config', help='the server configuration file') config_group.add_argument('-u', '--url', dest='database_url', help='the database connection url') parser.add_argument('--force', dest='force', action='store_true', default=False, help='create the user if necessary') parser.add_argument('--otp', dest='otp_secret', help='a specific otp secret') if has_qrcode: parser.add_argument('--qrcode', dest='qrcode_filename', help='generate a qrcode image file') parser.add_argument('user', help='the user to mange') parser.add_argument('action', choices=('remove', 'set', 'show'), help='the action to preform') parser.epilog = PARSER_EPILOG arguments = parser.parse_args() if arguments.database_url: database_connection_url = arguments.database_url elif arguments.server_config: server_config = configuration.ex_load_config(arguments.server_config) database_connection_url = server_config.get('server.database') else: raise RuntimeError('no database connection was specified') manager.init_database(database_connection_url) session = manager.Session() user = session.query(models.User).filter_by(name=arguments.user).first() if not user: if not arguments.force: color.print_error("invalid user id: {0}".format(arguments.user)) return user = models.User(name=arguments.user) session.add(user) color.print_status('the specified user was created') for case in utilities.switch(arguments.action): if case('remove'): user.otp_secret = None break if case('set'): if user.otp_secret: color.print_error("the specified user already has an otp secret set") return if arguments.otp_secret: new_otp = arguments.otp_secret else: new_otp = pyotp.random_base32() if len(new_otp) != 16: color.print_error("invalid otp secret length, must be 16") return user.otp_secret = new_otp break if user.otp_secret: color.print_status("user: {0} otp: {1}".format(user.name, user.otp_secret)) totp = pyotp.TOTP(user.otp_secret) uri = totp.provisioning_uri(user.name + '@king-phisher') + '&issuer=King%20Phisher' color.print_status("provisioning uri: {0}".format(uri)) if has_qrcode and arguments.qrcode_filename: img = qrcode.make(uri) img.save(arguments.qrcode_filename) color.print_status("wrote qrcode image to: " + arguments.qrcode_filename) else: color.print_status("user: {0} otp: N/A".format(user.id)) session.commit()