def checkAccess(irc, uid, channel, command): """Checks the caller's access to Automode.""" # Automode defines the following permissions, where <command> is either "manage", "list", # "sync", "clear", "remotemanage", "remotelist", "remotesync", "remoteclear": # - automode.<command> OR automode.<command>.*: ability to <command> automode on all channels. # - automode.<command>.relay_owned: ability to <command> automode on channels owned via Relay. # If Relay isn't loaded, this permission check FAILS. # - automode.<command>.#channel: ability to <command> automode on the given channel. # - automode.savedb: ability to save the automode DB. log.debug('(%s) Automode: checking access for %s/%s for %s capability on %s', irc.name, uid, irc.getHostmask(uid), command, channel) baseperm = 'automode.%s' % command try: # First, check the catch all and channel permissions. perms = [baseperm, baseperm+'.*', '%s.%s' % (baseperm, channel)] return permissions.checkPermissions(irc, uid, perms) except utils.NotAuthorizedError: if not command.startswith('remote'): # Relay-based ACL checking only works with local calls. log.debug('(%s) Automode: falling back to automode.%s.relay_owned', irc.name, command) permissions.checkPermissions(irc, uid, [baseperm+'.relay_owned'], also_show=perms) relay = world.plugins.get('relay') if relay is None: raise utils.NotAuthorizedError("You are not authorized to use Automode when Relay is " "disabled. You are missing one of the following " "permissions: %s or %s.%s" % (baseperm, baseperm, channel)) elif (irc.name, channel) not in relay.db: raise utils.NotAuthorizedError("The network you are on does not own the relay channel %s." % channel) return True raise
def identify(irc, source, args): """<username> <password> Logs in to PyLink using the configured administrator account.""" if irc.is_channel(irc.called_in): irc.reply('Error: This command must be sent in private. ' '(Would you really type a password inside a channel?)') return try: username, password = args[0], args[1] except IndexError: irc.reply('Error: Not enough arguments.') return # Process new-style accounts. if check_login(username, password): _irc_try_login(irc, source, username) return # Process legacy logins (login:user). if username.lower() == conf.conf['login'].get( 'user', '').lower() and password == conf.conf['login'].get('password'): realuser = conf.conf['login']['user'] _irc_try_login(irc, source, realuser, skip_checks=True) return # Username not found or password incorrect. log.warning("(%s) Failed login to %r from %s", irc.name, username, irc.get_hostmask(source)) raise utils.NotAuthorizedError('Bad username or password.')
def checkPermissions(irc, uid, perms, also_show=[]): """ Checks permissions of the caller. If the caller has any of the permissions listed in perms, this function returns True. Otherwise, NotAuthorizedError is raised. """ # For old (< 1.1 login blocks): # If the user is logged in, they automatically have all permissions. if irc.matchHost('$pylinkacc', uid) and conf.conf['login'].get('user'): log.debug( 'permissions: overriding permissions check for old-style admin user %s', irc.getHostmask(uid)) return True # Iterate over all hostmask->permission list mappings. for host, permlist in permissions.copy().items(): log.debug('permissions: permlist for %s: %s', host, permlist) if irc.matchHost(host, uid): # Now, iterate over all the perms we are looking for. for perm in permlist: # Use irc.matchHost to expand globs in an IRC-case insensitive and wildcard # friendly way. e.g. 'xyz.*.#Channel\' will match 'xyz.manage.#channel|' on IRCds # using the RFC1459 casemapping. log.debug( 'permissions: checking if %s glob matches anything in %s', perm, permlist) if any(irc.matchHost(perm, p) for p in perms): return True raise utils.NotAuthorizedError( "You are missing one of the following permissions: %s" % (', '.join(perms + also_show)))
def verifyHash(password, passhash): """Checks whether the password given matches the hash.""" if password: if not pwd_context: raise utils.NotAuthorizedError("Cannot log in to an account with a hashed password " "because passlib is not installed.") return pwd_context.verify(password, passhash) return False # No password given!
def _irc_try_login(irc, source, username, skip_checks=False): """Internal function to process logins via IRC.""" if irc.is_internal_client(source): irc.error("Cannot use 'identify' via a command proxy.") return if not skip_checks: logindata = _get_account(username) network_filter = logindata.get('networks') require_oper = logindata.get('require_oper', False) hosts_filter = logindata.get('hosts', []) if network_filter and irc.name not in network_filter: log.warning( "(%s) Failed login to %r from %s (wrong network: networks filter says %r but we got %r)", irc.name, username, irc.get_hostmask(source), ', '.join(network_filter), irc.name) raise utils.NotAuthorizedError( "Account is not authorized to login on this network.") elif require_oper and not irc.is_oper(source): log.warning("(%s) Failed login to %r from %s (needs oper)", irc.name, username, irc.get_hostmask(source)) raise utils.NotAuthorizedError("You must be opered.") elif hosts_filter and not any( irc.match_host(host, source) for host in hosts_filter): log.warning("(%s) Failed login to %r from %s (hostname mismatch)", irc.name, username, irc.get_hostmask(source)) raise utils.NotAuthorizedError("Hostname mismatch.") irc.users[source].account = username irc.reply('Successfully logged in as %s.' % username) log.info("(%s) Successful login to %r by %s", irc.name, username, irc.get_hostmask(source)) return True
def check_permissions(irc, uid, perms, also_show=[]): """ Checks permissions of the caller. If the caller has any of the permissions listed in perms, this function returns True. Otherwise, NotAuthorizedError is raised. """ # For old (< 1.1 login blocks): # If the user is logged in, they automatically have all permissions. olduser = conf.conf['login'].get('user') if olduser and irc.match_host('$pylinkacc:%s' % olduser, uid): log.debug( 'permissions: overriding permissions check for old-style admin user %s', irc.get_hostmask(uid)) return True permissions = defaultdict(set) # Enumerate the configured permissions list. for k, v in (conf.conf.get('permissions') or {}).items(): permissions[k] |= set(v) # Merge in default permissions if enabled. if conf.conf.get('permissions_merge_defaults', True): for k, v in default_permissions.items(): permissions[k] |= v for host, permlist in permissions.items(): log.debug('permissions: permlist for %s: %s', host, permlist) if irc.match_host(host, uid): # Now, iterate over all the perms we are looking for. for perm in permlist: # Use irc.match_host to expand globs in an IRC-case insensitive and wildcard # friendly way. e.g. 'xyz.*.#Channel\' will match 'xyz.manage.#channel|' on IRCds # using the RFC1459 casemapping. log.debug( 'permissions: checking if %s glob matches anything in %s', perm, permlist) if any(irc.match_host(perm, p) for p in perms): return True raise utils.NotAuthorizedError( "You are missing one of the following permissions: %s" % (', '.join(perms + also_show)))