pass
class CommandFile(object):
- def __init__(self, path, log=None):
+ def __init__(self, filename, data, log=None):
if log is None:
from daklib.daklog import Logger
log = Logger()
self.cc = []
self.result = []
self.log = log
- self.path = path
- self.filename = os.path.basename(path)
+ self.filename = filename
+ self.data = data
def _check_replay(self, signed_file, session):
"""check for replays
session.add(signature_history)
session.commit()
+ def _quote_section(self, section):
+ lines = []
+ for l in str(section).splitlines():
+ lines.append("> {0}".format(l))
+ return "\n".join(lines)
+
def _evaluate_sections(self, sections, session):
session.rollback()
try:
- sections.next()
- section = sections.section
-
- action = section.get('Action', None)
- if action is None:
- raise CommandError('Encountered section without Action field')
- self.result.append('Action: {0}'.format(action))
-
- if action == 'dm':
- self.action_dm(self.fingerprint, section, session)
- elif action == 'break-the-archive':
- self.action_break_the_archive(self.fingerprint, section, session)
- else:
- raise CommandError('Unknown action: {0}'.format(action))
+ while True:
+ sections.next()
+ section = sections.section
+ self.result.append(self._quote_section(section))
+
+ action = section.get('Action', None)
+ if action is None:
+ raise CommandError('Encountered section without Action field')
+
+ if action == 'dm':
+ self.action_dm(self.fingerprint, section, session)
+ elif action == 'dm-remove':
+ self.action_dm_remove(self.fingerprint, section, session)
+ elif action == 'dm-migrate':
+ self.action_dm_migrate(self.fingerprint, section, session)
+ elif action == 'break-the-archive':
+ self.action_break_the_archive(self.fingerprint, section, session)
+ else:
+ raise CommandError('Unknown action: {0}'.format(action))
+
+ self.result.append('')
except StopIteration:
pass
finally:
keyrings = session.query(Keyring).filter_by(active=True).order_by(Keyring.priority)
keyring_files = [ k.keyring_name for k in keyrings ]
- raw_contents = open(self.path, 'r').read()
- signed_file = SignedFile(raw_contents, keyring_files)
+ signed_file = SignedFile(self.data, keyring_files)
if not signed_file.valid:
self.log.log(['invalid signature', self.filename])
return False
section = sections.section
if 'Uploader' in section:
self.uploader = section['Uploader']
+ if 'Cc' in section:
+ self.cc.append(section['Cc'])
# TODO: Verify first section has valid Archive field
if 'Archive' not in section:
raise CommandError('No Archive field in first section.')
self.result.append('')
except Exception as e:
self.log.log(['ERROR', e])
- self.result.append("There was an error processing this section:\n{0}".format(e))
+ self.result.append("There was an error processing this section. No changes were committed.\nDetails:\n{0}".format(e))
result = False
self._notify_uploader()
session.close()
- self.log.log(['done', self.filename])
return result
acl_name = cnf.get('Command::DM::ACL', 'dm')
acl = session.query(ACL).filter_by(name=acl_name).one()
- fpr = session.query(Fingerprint).filter_by(fingerprint=section['Fingerprint']).one()
+ fpr_hash = section['Fingerprint'].translate(None, ' ')
+ fpr = session.query(Fingerprint).filter_by(fingerprint=fpr_hash).first()
+ if fpr is None:
+ raise CommandError('Unknown fingerprint {0}'.format(fpr_hash))
if fpr.keyring is None or fpr.keyring.keyring_name not in cnf.value_list('Command::DM::Keyrings'):
raise CommandError('Key {0} is not in DM keyring.'.format(fpr.fingerprint))
addresses = gpg_get_key_addresses(fpr.fingerprint)
self.result.append('Uid: {0}'.format(addresses[0]))
for source in self._split_packages(section.get('Allow', '')):
+ # Check for existance of source package to catch typos
+ if session.query(DBSource).filter_by(source=source).first() is None:
+ raise CommandError('Tried to grant permissions for unknown source package: {0}'.format(source))
+
if session.query(ACLPerSource).filter_by(acl=acl, fingerprint=fpr, source=source).first() is None:
aps = ACLPerSource()
aps.acl = acl
session.flush()
for source in self._split_packages(section.get('Deny', '')):
- session.query(ACLPerSource).filter_by(acl=acl, fingerprint=fpr, source=source).delete()
+ count = session.query(ACLPerSource).filter_by(acl=acl, fingerprint=fpr, source=source).delete()
+ if count == 0:
+ raise CommandError('Tried to remove upload permissions for package {0}, '
+ 'but no upload permissions were granted before.'.format(source))
+
self.log.log(['dm', 'deny', fpr.fingerprint, source])
self.result.append('Denied: {0}'.format(source))
session.commit()
+ def _action_dm_admin_common(self, fingerprint, section, session):
+ cnf = Config()
+
+ if 'Command::DM-Admin::AdminFingerprints' not in cnf \
+ or 'Command::DM::ACL' not in cnf:
+ raise CommandError('DM admin command is not configured for this archive.')
+
+ allowed_fingerprints = cnf.value_list('Command::DM-Admin::AdminFingerprints')
+ if fingerprint.fingerprint not in allowed_fingerprints:
+ raise CommandError('Key {0} is not allowed to admin DM'.format(fingerprint.fingerprint))
+
+ def action_dm_remove(self, fingerprint, section, session):
+ self._action_dm_admin_common(fingerprint, section, session)
+
+ cnf = Config()
+ acl_name = cnf.get('Command::DM::ACL', 'dm')
+ acl = session.query(ACL).filter_by(name=acl_name).one()
+
+ fpr_hash = section['Fingerprint'].translate(None, ' ')
+ fpr = session.query(Fingerprint).filter_by(fingerprint=fpr_hash).first()
+ if fpr is None:
+ self.result.append('Unknown fingerprint: {0}\nNo action taken.'.format(fpr_hash))
+ return
+
+ self.log.log(['dm-remove', fpr.fingerprint])
+
+ count = 0
+ for entry in session.query(ACLPerSource).filter_by(acl=acl, fingerprint=fpr):
+ self.log.log(['dm-remove', fpr.fingerprint, 'source={0}'.format(entry.source)])
+ count += 1
+ session.delete(entry)
+
+ self.result.append('Removed: {0}.\n{1} acl entries removed.'.format(fpr.fingerprint, count))
+
+ session.commit()
+
+ def action_dm_migrate(self, fingerprint, section, session):
+ self._action_dm_admin_common(fingerprint, section, session)
+ cnf = Config()
+ acl_name = cnf.get('Command::DM::ACL', 'dm')
+ acl = session.query(ACL).filter_by(name=acl_name).one()
+
+ fpr_hash_from = section['From'].translate(None, ' ')
+ fpr_from = session.query(Fingerprint).filter_by(fingerprint=fpr_hash_from).first()
+ if fpr_from is None:
+ self.result.append('Unknown fingerprint (From): {0}\nNo action taken.'.format(fpr_hash_from))
+ return
+
+ fpr_hash_to = section['To'].translate(None, ' ')
+ fpr_to = session.query(Fingerprint).filter_by(fingerprint=fpr_hash_to).first()
+ if fpr_to is None:
+ self.result.append('Unknown fingerprint (To): {0}\nNo action taken.'.format(fpr_hash_to))
+ return
+ if fpr_to.keyring is None or fpr_to.keyring.keyring_name not in cnf.value_list('Command::DM::Keyrings'):
+ self.result.append('Key (To) {0} is not in DM keyring.\nNo action taken.'.format(fpr_to.fingerprint))
+ return
+
+ self.log.log(['dm-migrate', 'from={0}'.format(fpr_hash_from), 'to={0}'.format(fpr_hash_to)])
+
+ sources = []
+ for entry in session.query(ACLPerSource).filter_by(acl=acl, fingerprint=fpr_from):
+ self.log.log(['dm-migrate', 'from={0}'.format(fpr_hash_from), 'to={0}'.format(fpr_hash_to), 'source={0}'.format(entry.source)])
+ entry.fingerprint = fpr_to
+ sources.append(entry.source)
+
+ self.result.append('Migrated {0} to {1}.\n{2} acl entries changed: {3}'.format(fpr_hash_from, fpr_hash_to, len(sources), ", ".join(sources)))
+
+ session.commit()
+
def action_break_the_archive(self, fingerprint, section, session):
name = 'Dave'
uid = fingerprint.uid