def perform_from_fd(infd, outfd, xc, proto, closefds=()): if proto == 'ejabberd': from xclib.ejabberd_io import ejabberd_io xmpp = ejabberd_io if infd == outfd: infd = infd.makefile("rb") outfd = outfd.makefile("wb") closefds = closefds + (infd, outfd) elif proto == 'saslauthd': from xclib.saslauthd_io import saslauthd_io xmpp = saslauthd_io if infd == outfd: infd = infd.makefile("rb") outfd = outfd.makefile("wb") closefds = closefds + (infd, outfd) elif proto == 'postfix': from xclib.postfix_io import postfix_io xmpp = postfix_io if infd == outfd: infd = infd.makefile("r") outfd = outfd.makefile("w") closefds = closefds + (infd, outfd) else: # 'generic' or 'prosody' from xclib.prosody_io import prosody_io xmpp = prosody_io if infd == outfd: infd = infd.makefile("r") outfd = outfd.makefile("w") closefds = closefds + (infd, outfd) for data in xmpp.read_request(infd, outfd): logging.debug('Receive operation ' + data[0]); success = False if data[0] == "auth" and len(data) == 4: sc = sigcloud(xc, data[1], data[2], data[3]) success = sc.auth() elif data[0] == "isuser" and len(data) == 3: sc = sigcloud(xc, data[1], data[2]) success = sc.isuser() elif data[0] == "roster" and len(data) == 3: # Nonstandard extension, only useful with -t generic sc = sigcloud(xc, data[1], data[2]) success, response = sc.roster_cloud() success = str(response) # Convert from unicode elif data[0] == "quit" or data[0] == "exit": break xmpp.write_response(success, outfd) logging.debug('Closing connection') for c in closefds: c.close()
def test_try_41self_deletion(): global collect collect = [] xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') xc.session.post = make_rosterfunc({'user1@domain1': {'name': 'Ce De'}}) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user1', 'domain1') assertEqual(sc.try_roster(async_=False), True) xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') logging.info(collect) assertEqual( collect, [ # The first is unnecessary but harmless (idempotent) and not easily avoidable ['srg_user_del', 'user1', 'domain1', 'Family', 'domain1'], ['srg_user_del', 'user1', 'domain1', 'Lonely', 'domain1'] ]) xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') assert_grouplist('user1@domain1', '') assert_grouplist('user2@domain1', 'Family\tFriends') assert_grouplist('user3@domain1', None) assert_groupinfo('Lonely@domain1', 'user1@domain1') assert_groupinfo('Family@domain1', 'user2@domain1') assert_groupinfo('Friends@domain1', 'user2@domain1\tuser3@domain1')
def test_try_33login_other_user(): global collect collect = [] xc.session.post = make_rosterfunc({ 'user1@domain1': { 'name': 'Ah Be', 'groups': ['Family'] }, 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user2', 'domain1') assert sc.try_roster(async=False) == True logging.info(collect) assert collect == [ ['get_vcard', 'user3', 'domain1', 'FN'], ['set_vcard', 'user3', 'domain1', 'FN', 'Xy Zzy'], ['srg_create', 'Friends', 'domain1', 'Friends', 'Friends', 'Friends'], ['srg_get_members', 'Friends', 'domain1'], ['srg_user_add', 'user3', 'domain1', 'Friends', 'domain1'], ['srg_user_add', 'user2', 'domain1', 'Friends', 'domain1'], ]
def test_try_35login_with_ignored_group(): global collect collect = [] xc.db.conn.dump('rosterinfo') xc.session.post = make_rosterfunc({ 'user1@domain1': { 'name': 'Ce De', 'groups': ['Family', 'Lonely', 'Hidden\u200b'] }, 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user1', 'domain1') assertEqual(sc.try_roster(async_=False), True) logging.info(collect) xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') assertEqual( collect, [ # No add of Hidden ]) assert_grouplist('user1@domain1', 'Family\tLonely') assert_grouplist('user2@domain1', 'Family\tFriends') assert_grouplist('user3@domain1', None) assert_groupinfo('Lonely@domain1', 'user1@domain1') assert_groupinfo('Family@domain1', 'user1@domain1\tuser2@domain1') assert_groupinfo('Friends@domain1', 'user2@domain1\tuser3@domain1')
def test_try_40third_party_deletion(): global collect collect = [] xc.db.conn.dump('rosterinfo') xc.session.post = make_rosterfunc({ 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user2', 'domain1') assertEqual(sc.try_roster(async_=False), True) logging.info(collect) assertEqual(collect, [['srg_user_del', 'user1', 'domain1', 'Family', 'domain1']]) xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') assert_grouplist( 'user1@domain1', 'Family\tLonely') # This is not touched by 3rd party deletion assert_grouplist('user2@domain1', 'Family\tFriends') assert_grouplist('user3@domain1', None) assert_groupinfo('Lonely@domain1', 'user1@domain1') assert_groupinfo('Family@domain1', 'user2@domain1') # Only this assert_groupinfo('Friends@domain1', 'user2@domain1\tuser3@domain1')
def test_20_token_success(): # ./generateTimeLimitedToken tuser tdomain 01234 3600 1000 sc = sigcloud(xc, 'tuser', 'tdomain', 'AMydsCzkh8-8vjcb9U2gqV/FZQAAEfg', now=utc(2000)) sc.verbose_cloud_request = sc_trap assertEqual(sc.auth(), True) assertEqual(0, sql1('''SELECT COUNT(*) FROM authcache WHERE jid = 'tuser@tdomain' ''')[0])
def test_try_34login_other_user_again(): global collect collect = [] xc.session.post = make_rosterfunc({ 'user1@domain1': { 'name': 'Ce De', 'groups': ['Family'], 'dummy': '1' }, 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user2', 'domain1') assertEqual(sc.try_roster(async_=False), True) logging.info(collect) assertEqual(collect, []) xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') assert_grouplist('user1@domain1', 'Family\tLonely') assert_grouplist('user2@domain1', 'Family\tFriends') assert_grouplist('user3@domain1', None) assert_groupinfo('Lonely@domain1', 'user1@domain1') assert_groupinfo('Family@domain1', 'user1@domain1\tuser2@domain1') assert_groupinfo('Friends@domain1', 'user2@domain1\tuser3@domain1')
def test_20_token_success(): # ./generateTimeLimitedToken tuser tdomain 01234 3600 1000 sc = sigcloud(xc, 'tuser', 'tdomain', 'AMydsCzkh8-8vjcb9U2gqV/FZQAAEfg', now=2000) sc.verbose_cloud_request = sc_trap assertEqual(sc.auth(), True) assert 'tuser:tdomain' not in xc.cache_db
def setup_module(): global xc, sc xc = xcauth(domain_db={ 'xdomain': '99999\thttps://remotehost\tydomain\t', 'udomain': '8888\thttps://oldhost\t', }, default_url='https://localhost', default_secret='01234') sc = sigcloud(xc, 'user1', 'domain1')
def setup_module(): global xc, sc xc = xcauth(default_url='https://localhost', default_secret='01234', #sql_db='/tmp/auth.sqlite3', cache_storage='db', #sql_db='/tmp/auth.sqlite3', cache_storage='db', #sql_db=':memory:', cache_storage='db', sql_db=':memory:', cache_storage='memory', bcrypt_rounds=(6, 6)) sc = sigcloud(xc, 'user2', 'domain2', 'pass2')
def test_20_token_fail(): # ./generateTimeLimitedToken tuser tdomain 01234 3600 1000 sc = sigcloud(xc, 'tuser', 'tdomain', 'AMydsCzkh8-8vjcb9U2gqV/FZQAAEfg', now=utc(5000)) sc.verbose_cloud_request = sc_noauth global cloud_count cloud_count = 0 assertEqual(sc.auth(), False) assertEqual(cloud_count, 1)
def test_20_token_version(): # Wrong version sc = sigcloud(xc, 'tuser', 'tdomain', 'BMydsCzkh8-8vjcb9U2gqV/FZQAAEfg', now=utc(5000)) sc.verbose_cloud_request = sc_noauth global cloud_count cloud_count = 0 assertEqual(sc.auth(), False) assertEqual(cloud_count, 1)
def setup_module(): global xc, sc xc = xcauth(domain_db={ b'xdomain': b'99999\thttps://remotehost\tydomain\t', b'udomain': b'8888\thttps://oldhost\t', }, sql_db=':memory:', cache_storage='db', default_url='https://localhost', default_secret='01234') sc = sigcloud(xc, 'user1', 'domain1')
def setup_module(): global xc, sc xc = xcauth(domain_db={ 'xdomain': '99999\thttps://remotehost\tydomain\t', 'udomain': '8888\thttps://oldhost\t', }, default_url='https://localhost', default_secret='01234', ejabberdctl='/no/bin/ejabberdctl', shared_roster_db={}) xc.ejabberd_controller = ejabberdctl(xc) sc = sigcloud(xc, 'user1', 'domain1')
def test_20_token_version(): # Wrong version sc = sigcloud(xc, 'tuser', 'tdomain', 'BMydsCzkh8-8vjcb9U2gqV/FZQAAEfg', now=5000) sc.verbose_cloud_request = sc_noauth global cloud_count cloud_count = 0 assert sc.auth() == False assert cloud_count == 1
def test_try_41self_deletion(): global collect collect = [] xc.session.post = make_rosterfunc({'user1@domain1': {'name': 'Ah Be'}}) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user1', 'domain1') assert sc.try_roster(async=False) == True logging.info(collect) assert collect == [ # The first is unnecessary but harmless and not easily avoidable ['srg_user_del', 'user1', 'domain1', 'Family', 'domain1'], ['srg_user_del', 'user1', 'domain1', 'Lonely', 'domain1'] ]
def test_try_40third_party_deletion(): global collect collect = [] xc.session.post = make_rosterfunc({ 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user2', 'domain1') assertEqual(sc.try_roster(async=False), True) logging.info(collect) assertEqual(collect, [['srg_user_del', 'user1', 'domain1', 'Family', 'domain1']])
def test_try_33login_other_user(): global collect collect = [] xc.session.post = make_rosterfunc({ 'user1@domain1': { 'name': 'Ce De', 'groups': ['Family'] }, 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user2', 'domain1') assertEqual(sc.try_roster(async_=False), True) logging.info(collect) assert collect == [ ['set_vcard', 'user3', 'domain1', 'FN', 'Xy Zzy'], ['srg_create', 'Friends', 'domain1', 'Friends', 'Friends', 'Friends'], ['srg_get_members', 'Friends', 'domain1'], ['srg_user_add', 'user3', 'domain1', 'Friends', 'domain1'], ['srg_user_add', 'user2', 'domain1', 'Friends', 'domain1'], ] or collect == [ ['set_vcard', 'user3', 'domain1', 'FN', 'Xy Zzy'], ['srg_create', 'Friends', 'domain1', 'Friends', 'Friends', 'Friends'], ['srg_get_members', 'Friends', 'domain1'], ['srg_user_add', 'user2', 'domain1', 'Friends', 'domain1'], ['srg_user_add', 'user3', 'domain1', 'Friends', 'domain1'], ] xc.db.conn.dump('rosterinfo') xc.db.conn.dump('rostergroups') assert_grouplist('user1@domain1', 'Family\tLonely') assert_grouplist('user2@domain1', 'Family\tFriends') assert_grouplist('user3@domain1', None) assert_groupinfo('Lonely@domain1', 'user1@domain1') assert_groupinfo('Family@domain1', 'user1@domain1\tuser2@domain1') assert_groupinfo('Friends@domain1', 'user2@domain1\tuser3@domain1')
def test_try_34login_other_user_again(): global collect collect = [] xc.session.post = make_rosterfunc({ 'user1@domain1': { 'name': 'Ah Be', 'groups': ['Family'], 'dummy': '1' }, 'user2@domain1': { 'name': 'De Be', 'groups': ['Family', 'Friends'] }, 'user3@domain1': { 'name': 'Xy Zzy', 'groups': ['Friends'] }, }) xc.ejabberd_controller.execute = ctrl_collect sc = sigcloud(xc, 'user2', 'domain1') assertEqual(sc.try_roster(async=False), True) logging.info(collect) assertEqual(collect, [])
def test_30_cache(): global cloud_count cloud_count = 0 sc = sigcloud(xc, 'user3', 'domain3', 'pass3', now=utc(1)) # Timeout first: No cache entry sc.verbose_cloud_request = sc_timeout assertEqual(sc.auth(), False) assertEqual(0, sql1('''SELECT COUNT(*) FROM authcache WHERE jid = 'user3@domain3' ''')[0]) assertEqual(cloud_count, 1) # Success: Cache entry sc.verbose_cloud_request = sc_success assertEqual(sc.auth(), True) assertEqual(1, sql1('''SELECT COUNT(*) FROM authcache WHERE jid = 'user3@domain3' ''')[0]) entry = sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') assert(entry != None) assert entry['pwhash'].startswith('$2b$06$') cachedpw = entry['pwhash'] assertEqual(entry['firstauth'], utc(1)) firstauth = entry['firstauth'] assertEqual(entry['remoteauth'], utc(1)) assertEqual(entry['anyauth'], utc(1)) assertEqual(cloud_count, 2) # Same request a little bit later: Should use cache (and note it) sc.now = utc(100) sc.verbose_cloud_request = sc_trap assertEqual(sc.auth(), True) entry = sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') assertEqual(cachedpw, entry['pwhash']) # No cache password update assertEqual(entry['firstauth'], firstauth) assertEqual(entry['remoteauth'], utc(1)) assertEqual(entry['anyauth'], utc(100)) assertEqual(cloud_count, 2) # Bad password request sc.now = utc(200) sc.verbose_cloud_request = sc_noauth sc.password = '******' assertEqual(sc.auth(), False) assertEqual(entry, sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''')) # Unmodified assertEqual(cloud_count, 3) # Test whether the DEFAULT values from the database are reapplied # (is the case when using INSERT OR REPLACE with DEFAULTs in schema) time.sleep(1) # New successful password request again: Should use cloud again sc.now = utc(300) sc.password = '******' sc.verbose_cloud_request = sc_success assertEqual(sc.auth(), True) entry = sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') assert cachedpw != entry['pwhash'] # Update cached password assertEqual(entry['firstauth'], firstauth) assertEqual(entry['remoteauth'], utc(300)) assertEqual(entry['anyauth'], utc(300)) assertEqual(cloud_count, 4) # Token request should not change anything # ./generateTimeLimitedToken user3 domain3 01234 3600 1 sc.password = '******' assertEqual(sc.auth(), True) assertEqual(entry, sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''')) # Unmodified assertEqual(cloud_count, 4) # More than an hour of waiting: Go to the cloud again sc.now = utc(4000) sc.password = '******' assertEqual(sc.auth(), True) assert entry != sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') # Updated entry = sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') assert cachedpw != entry['pwhash'] # Update cached password assertEqual(entry['firstauth'], firstauth) assertEqual(entry['remoteauth'], utc(4000)) assertEqual(entry['anyauth'], utc(4000)) assertEqual(cloud_count, 5) # Another hour has passed, but the server is now unreachable sc.now = utc(8000) sc.verbose_cloud_request = sc_timeout assertEqual(sc.auth(), True) entry = sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') assert cachedpw != entry['pwhash'] # Update cached password assertEqual(entry['firstauth'], firstauth) assertEqual(entry['remoteauth'], utc(4000)) assertEqual(entry['anyauth'], utc(8000)) assertEqual(cloud_count, 6) # Another request shortly after goes to the cache again sc.now = utc(8100) assertEqual(sc.auth(), True) entry = sql1('''SELECT * FROM authcache WHERE jid = 'user3@domain3' ''') assert cachedpw != entry['pwhash'] # Update cached password assertEqual(entry['firstauth'], firstauth) assertEqual(entry['remoteauth'], utc(4000)) assertEqual(entry['anyauth'], utc(8100)) assertEqual(cloud_count, 6) # Now 46 more requests spaced half an hour apart should all go to the cache while sc.now < utc(4000 + 86400 - 1800): sc.now += timedelta(seconds=1800) assertEqual(sc.auth(), True) assertEqual(cloud_count, 6) # The next goes to the cloud again, but as that times out, is considered OK as well sc.now += timedelta(seconds=1800) assertEqual(sc.auth(), True) assertEqual(cloud_count, 7) # This could go on for the rest of a week, but then it should finally fail sc.now += timedelta(days=6) assertEqual(sc.auth(), False) assertEqual(cloud_count, 8)
def test_30_cache(): global cloud_count cloud_count = 0 sc = sigcloud(xc, 'user3', 'domain3', 'pass3', now=1) # Timeout first: No cache entry sc.verbose_cloud_request = sc_timeout assert sc.auth() == False assert 'user3:domain3' not in xc.cache_db assert cloud_count == 1 # Success: Cache entry sc.verbose_cloud_request = sc_success assert sc.auth() == True assert 'user3:domain3' in xc.cache_db entry = xc.cache_db['user3:domain3'] fields = entry.split('\t') cachedpw = fields[0] assert fields[0].startswith('$2b$06$') assert fields[1] == '1' assert fields[2] == '1' assert fields[3] == '1' assert cloud_count == 2 # Same request a little bit later: Should use cache (and note it) sc.now = 100 sc.verbose_cloud_request = sc_trap assert sc.auth() == True entry = xc.cache_db['user3:domain3'] fields = entry.split('\t') assert cachedpw == fields[0] # No cache password update assert fields[1] == '1' assert fields[2] == '1' assert fields[3] == '100' assert cloud_count == 2 # Bad password request sc.now = 200 sc.verbose_cloud_request = sc_noauth sc.password = '******' assert sc.auth() == False assert xc.cache_db['user3:domain3'] == entry # Unmodified assert cloud_count == 3 # New successful password request again: Should use cloud again sc.now = 300 sc.password = '******' sc.verbose_cloud_request = sc_success assert sc.auth() == True entry = xc.cache_db['user3:domain3'] fields = entry.split('\t') assert cachedpw != fields[0] # Update cached password assert fields[1] == '1' assert fields[2] == '300' assert fields[3] == '300' assert cloud_count == 4 # Token request should not change anything # ./generateTimeLimitedToken user3 domain3 01234 3600 1 sc.password = '******' assert sc.auth() == True assert xc.cache_db['user3:domain3'] == entry # Unmodified assert cloud_count == 4 # More than an hour of waiting: Go to the cloud again sc.now = 4000 sc.password = '******' assert sc.auth() == True assert xc.cache_db['user3:domain3'] != entry # Updated entry = xc.cache_db['user3:domain3'] fields = entry.split('\t') assert cachedpw != fields[0] # Update cached password assert fields[1] == '1' assert fields[2] == '4000' assert fields[3] == '4000' assert cloud_count == 5 # Another hour has passed, but the server is now unreachable sc.now = 8000 sc.verbose_cloud_request = sc_timeout assert sc.auth() == True entry = xc.cache_db['user3:domain3'] fields = entry.split('\t') assert cachedpw != fields[0] # Update cached password assert fields[1] == '1' assert fields[2] == '4000' assert fields[3] == '8000' assert cloud_count == 6 # Another request shortly after goes to the cache again sc.now = 8100 assert sc.auth() == True entry = xc.cache_db['user3:domain3'] fields = entry.split('\t') assert cachedpw != fields[0] # Update cached password assert fields[1] == '1' assert fields[2] == '4000' assert fields[3] == '8100' assert cloud_count == 6 # Now 46 more requests spaced half an hour apart should all go to the cache while sc.now < 4000 + 86400 - 1800: sc.now += 1800 assert sc.auth() == True assert cloud_count == 6 # The next goes to the cloud again, but as that times out, is considered OK as well sc.now += 1800 assert sc.auth() == True assert cloud_count == 7 # This could go on for the rest of a week, but then it should finally fail sc.now += 6 * 86400 assert sc.auth() == False assert cloud_count == 8
def setup_module(): global xc, sc xc = xcauth(default_url='https://localhost', default_secret='01234', bcrypt_rounds=6) sc = sigcloud(xc, 'user2', 'domain2', 'pass2')
def test_domain_upgrade(): sc = sigcloud(xc, 'uuser', 'udomain') sc.verbose_cloud_request = sc_success assertEqual(sc.isuser(), True)
def test_xdomain(): sc = sigcloud(xc, 'xuser', 'xdomain') sc.verbose_cloud_request = sc_xdomain assertEqual(sc.isuser(), True)
def perform(args): logfile = args.log + '/xcauth.log' if (args.interactive or args.auth_test or args.isuser_test or args.roster_test): logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s') else: logging.basicConfig( filename=logfile, level=logging.DEBUG if args.debug else logging.INFO, format='%(asctime)s %(levelname)s: %(message)s') # redirect stderr errfile = args.log + '/xcauth.err' sys.stderr = open(errfile, 'a+') logging.debug('Start external auth script %s for %s with endpoint: %s', VERSION, args.type, args.url) if args.domain_db: domain_db = anydbm.open(args.domain_db, 'c', 0600) atexit.register(domain_db.close) else: domain_db = {} if args.cache_db: import bcrypt cache_db = anydbm.open(args.cache_db, 'c', 0600) atexit.register(cache_db.close) else: cache_db = {'': ''} # "Do not use" marker if args.shared_roster_db: shared_roster_db = anydbm.open(args.shared_roster_db, 'c', 0600) atexit.register(shared_roster_db.close) else: # Will never be accessed, as `ejabberdctl` will not be set shared_roster_db = None ttls = { 'query': args.cache_query_ttl, 'verify': args.cache_verification_ttl, 'unreach': args.cache_unreachable_ttl } xc = xcauth( default_url=args.url, default_secret=args.secret, ejabberdctl=args.ejabberdctl if 'ejabberdctl' in args else None, shared_roster_db=shared_roster_db, domain_db=domain_db, cache_db=cache_db, timeout=args.timeout, ttls=ttls, bcrypt_rounds=args.cache_bcrypt_rounds) if args.isuser_test: sc = sigcloud(xc, args.isuser_test[0], args.isuser_test[1]) success = sc.isuser() print success return if args.roster_test: sc = sigcloud(xc, args.roster_test[0], args.roster_test[1]) success, response = sc.roster_cloud() print str(response) if args.update_roster: sc.try_roster(async=False) return elif args.auth_test: sc = sigcloud(xc, args.auth_test[0], args.auth_test[1], args.auth_test[2]) success = sc.auth() print success return if args.type == 'ejabberd': from xclib.ejabberd_io import ejabberd_io xmpp = ejabberd_io elif args.type == 'saslauthd': from xclib.saslauthd_io import saslauthd_io xmpp = saslauthd_io else: # 'generic' or 'prosody' from xclib.prosody_io import prosody_io xmpp = prosody_io for data in xmpp.read_request(): logging.debug('Receive operation ' + data[0]) success = False if data[0] == "auth" and len(data) == 4: sc = sigcloud(xc, data[1], data[2], data[3]) success = sc.auth() elif data[0] == "isuser" and len(data) == 3: sc = sigcloud(xc, data[1], data[2]) success = sc.isuser() elif data[0] == "roster" and len(data) == 3: # Nonstandard extension, only useful with -t generic sc = sigcloud(xc, data[1], data[2]) success, response = sc.roster_cloud() success = str(response) # Convert from unicode elif data[0] == "quit" or data[0] == "exit": break xmpp.write_response(success) logging.debug('Shutting down...')
def verify_with_isuser(url, secret, domain, user, timeout, hook=None): xc = xcauth(default_url=url, default_secret=secret, timeout=timeout) sc = sigcloud(xc, user, domain) if hook != None: hook(sc) # For automated testing only return sc.isuser_verbose()
def perform(args): global errfile # Set up logging logfile = args.log + '/xcauth.log' signal.signal(signal.SIGUSR1, log_info) if (args.interactive or args.auth_test or args.isuser_test or args.roster_test): signal.signal(signal.SIGHUP, signal.SIG_IGN) logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s') else: errfile = args.log + '/xcauth.err' rebind_stderr(0, None) signal.signal(signal.SIGHUP, rebind_stderr) try: from logging.handlers import WatchedFileHandler logging.basicConfig(handlers=(WatchedFileHandler(logfile),), level=logging.DEBUG if args.debug else logging.INFO, format='%(asctime)s %(levelname)s: %(message)s') except OSError as e: logging.basicConfig(stream=sys.stderr) logging.warning('Cannot log to %s: %s' % (logfile, str(e))) logging.debug('Start external auth script %s for %s with endpoint: %s', VERSION, args.type, args.url) # Set up global environment (incl. cache, db) if args.cache_storage != 'none': try: import bcrypt except ImportError as e: logging.warn('Cannot import bcrypt (%s); caching disabled' % e) args.cache_storage = 'none' ttls = {'query': args.cache_query_ttl, 'verify': args.cache_verification_ttl, 'unreach': args.cache_unreachable_ttl} xc = xcauth(default_url = args.url, default_secret = args.secret, ejabberdctl = args.ejabberdctl if 'ejabberdctl' in args else None, sql_db = args.db, cache_storage = args.cache_storage, domain_db = args.domain_db, cache_db = args.cache_db, shared_roster_db = args.shared_roster_db, timeout = args.timeout, ttls = ttls, bcrypt_rounds = args.cache_bcrypt_rounds) # Check for one-shot commands if args.isuser_test: sc = sigcloud(xc, args.isuser_test[0], args.isuser_test[1]) success = sc.isuser() print(success) return if args.roster_test: sc = sigcloud(xc, args.roster_test[0], args.roster_test[1]) success, response = sc.roster_cloud() print(str(response)) if args.ejabberdctl: sc.try_roster(async=False) return elif args.auth_test: sc = sigcloud(xc, args.auth_test[0], args.auth_test[1], args.auth_test[2]) success = sc.auth() print(success) return # Read commands from file descriptors # Acceptor socket? listeners = listen_fds_with_names() if listeners is None: # Single socket; unclear whether it is connected or an acceptor try: stdinfd = sys.stdin.fileno() except io.UnsupportedOperation: stdinfd = None if stdinfd is None: # Not a real socket, assume stdio communication perform_from_fd(sys.stdin, sys.stdout, xc, args.type) else: s = socket.socket(fileno=stdinfd) try: # Is it an acceptor socket? s.listen() # Yes, accept connections (fake systemd context) perform_from_listeners({0: args.type}, xc, args.type) except OSError: # Not an acceptor socket, use for stdio perform_from_fd(sys.stdin, sys.stdout, xc, args.type, closefds=(sys.stdin,sys.stdout,s)) else: # Uses systemd socket activation perform_from_listeners(listeners, xc, args.type)