def test_hex_entropy(self): """hex_entropy() returns random hex digits""" hex_digits = set('0123456789abcdef') for i in xrange(129): entropy = util.hex_entropy(i) self.assertEqual(i, len(entropy)) self.assertEqual(set(), set(entropy) - hex_digits)
def test_file_metadata(self): pkgname = 'TestModule_' + util.hex_entropy(16) modname = pkgname.lower() with open(os.path.join(self.dir, pkgname + '-0.1.egg-info'), 'w') as f: f.write('Metadata-Version: 1.1\n' 'Name: %(pkgname)s\n' 'Version: 0.1\n' 'Author: Joe\n' 'Author-email: [email protected]\n' 'Home-page: http://example.org/\n' 'Summary: summary.\n' 'Description: description.\n' 'Provides: %(modname)s\n' 'Provides: %(modname)s.foo\n' % { 'pkgname': pkgname, 'modname': modname }) os.mkdir(os.path.join(self.dir, modname)) for name in ('__init__.py', 'bar.py', 'foo.py'): with open(os.path.join(self.dir, modname, name), 'w') as f: f.write('# -*- coding: utf-8 -*-\n') mod = __import__(modname, {}, {}, ['bar', 'foo']) pkginfo = util.get_pkginfo(mod) self.assertEqual('0.1', pkginfo['version']) self.assertEqual('Joe', pkginfo['author']) self.assertEqual('*****@*****.**', pkginfo['author_email']) self.assertEqual('http://example.org/', pkginfo['home_page']) self.assertEqual('summary.', pkginfo['summary']) self.assertEqual('description.', pkginfo['description']) self.assertEqual(pkginfo, util.get_pkginfo(mod.bar)) self.assertEqual(pkginfo, util.get_pkginfo(mod.foo))
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: # TRANSLATOR: ... refer to the 'installation documentation'. (link) inst_doc = tag.a(_("installation documentation"), title=_("Configuring Authentication"), href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication") raise TracError(tag_("Authentication information not available. " "Please refer to the %(inst_doc)s.", inst_doc=inst_doc)) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() if req.authname not in ('anonymous', remote_user): raise TracError(_("Already logged in as %(user)s.", user=req.authname)) with self.env.db_transaction as db: # Delete cookies older than 10 days db("DELETE FROM auth_cookie WHERE time < %s", (int(time_now()) - 86400 * 10,)) # Insert a new cookie if we haven't already got one cookie = None trac_auth = req.incookie.get('trac_auth') if trac_auth is not None: name = self._cookie_to_name(req, trac_auth) cookie = trac_auth.value if name == remote_user else None if cookie is None: cookie = hex_entropy() db(""" INSERT INTO auth_cookie (cookie, name, ipnr, time) VALUES (%s, %s, %s, %s) """, (cookie, remote_user, req.remote_addr, int(time_now()))) req.authname = remote_user req.outcookie['trac_auth'] = cookie if self.auth_cookie_domain: req.outcookie['trac_auth']['domain'] = self.auth_cookie_domain req.outcookie['trac_auth']['path'] = self.auth_cookie_path \ or req.base_path or '/' if self.env.secure_cookies: req.outcookie['trac_auth']['secure'] = True req.outcookie['trac_auth']['httponly'] = True if self.auth_cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = self.auth_cookie_lifetime
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: # TRANSLATOR: ... refer to the 'installation documentation'. (link) inst_doc = tag.a(_('installation documentation'), title=_("Configuring Authentication"), href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication") raise TracError(tag_("Authentication information not available. " "Please refer to the %(inst_doc)s.", inst_doc=inst_doc)) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() if req.authname not in ('anonymous', remote_user): raise TracError(_('Already logged in as %(user)s.', user=req.authname)) with self.env.db_transaction as db: # Delete cookies older than 10 days db("DELETE FROM auth_cookie WHERE time < %s", (int(time.time()) - 86400 * 10,)) # Insert a new cookie if we haven't already got one cookie = None trac_auth = req.incookie.get('trac_auth') if trac_auth is not None: name = self._cookie_to_name(req, trac_auth) cookie = trac_auth.value if name == remote_user else None if cookie is None: cookie = hex_entropy() db(""" INSERT INTO auth_cookie (cookie, name, ipnr, time) VALUES (%s, %s, %s, %s) """, (cookie, remote_user, req.remote_addr, int(time.time()))) req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = self.auth_cookie_path \ or req.base_path or '/' if self.env.secure_cookies: req.outcookie['trac_auth']['secure'] = True if sys.version_info >= (2, 6): req.outcookie['trac_auth']['httponly'] = True if self.auth_cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = self.auth_cookie_lifetime
def _do_login(self, req): """Log the remote user in. This function displays a form to the user to log themselves in, and verifies the information when the user submits that form. If the authentication is successful, the user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web form 'username' variable will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if req.args.get("username"): assert req.args.get("password"), "No password" # Test authentication try: self._try_http_auth( req.base_url[: req.base_url.find("/", 8)] + "/login", req.args.get("username"), req.args.get("password"), ) except IOError, e: # Incorrect password req.hdf["title"] = "Login Failed" req.hdf["login.action"] = self.env.href() + "/login" req.hdf["login.referer"] = req.args.get("ref") req.hdf["login.error"] = "Invalid username or password" return None # Successful authentication, set cookies and stuff remote_user = req.args.get("username") ignore_case = self.env.config.get("trac", "ignore_auth_case") ignore_case = ignore_case.strip().lower() in TRUE if ignore_case: remote_user = remote_user.lower() assert req.authname in ("anonymous", remote_user), "Already logged in as %s." % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time())), ) db.commit() req.authname = remote_user req.outcookie["trac_auth"] = cookie req.outcookie["trac_auth"]["path"] = self.env.href() req.redirect(req.args.get("ref") or self.env.abs_href())
def _do_login(self, req): """Log the remote user in. This function displays a form to the user to log themselves in, and verifies the information when the user submits that form. If the authentication is successful, the user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web form 'username' variable will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if req.args.get('username'): assert req.args.get('password'), 'No password' # Test authentication try: self._try_http_auth( req.base_url[:req.base_url.find('/', 8)] + '/login', req.args.get('username'), req.args.get('password')) except IOError, e: # Incorrect password req.hdf['title'] = 'Login Failed' req.hdf['login.action'] = self.env.href() + '/login' req.hdf['login.referer'] = req.args.get('ref') req.hdf['login.error'] = 'Invalid username or password' return None # Successful authentication, set cookies and stuff remote_user = req.args.get('username') ignore_case = self.env.config.get('trac', 'ignore_auth_case') ignore_case = ignore_case.strip().lower() in TRUE if ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ 'Already logged in as %s.' % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = self.env.href() req.redirect(req.args.get('ref') or self.env.abs_href())
def send_auth_request(self, environ, start_response, stale='false'): """Send a digest challange to the browser. Record used nonces to avoid replay attacks. """ nonce = hex_entropy() self.active_nonces.append(nonce) if len(self.active_nonces) > self.MAX_NONCES: self.active_nonces = self.active_nonces[-self.MAX_NONCES:] start_response('401 Unauthorized', [('WWW-Authenticate', 'Digest realm="%s", nonce="%s", qop="auth", stale="%s"' % (self.realm, nonce, stale))])('')
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: # TRANSLATOR: ... refer to the 'installation documentation'. (link) inst_doc = tag.a(_('installation documentation'), title=_("Configuring Authentication"), href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication") raise TracError( tag_( "Authentication information not available. " "Please refer to the %(inst_doc)s.", inst_doc=inst_doc)) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ _('Already logged in as %(user)s.', user=req.authname) cookie = hex_entropy() @self.env.with_transaction() def store_session_cookie(db): cursor = db.cursor() # Delete cookies older than 10 days cursor.execute("DELETE FROM auth_cookie WHERE time < %s", (int(time.time()) - 86400 * 10, )) cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = self.auth_cookie_path \ or req.base_path or '/' if self.env.secure_cookies: req.outcookie['trac_auth']['secure'] = True if self.auth_cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = self.auth_cookie_lifetime
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: # TRANSLATOR: ... refer to the 'installation documentation'. (link) inst_doc = tag.a( _("installation documentation"), title=_("Configuring Authentication"), href=req.href.wiki("TracInstall") + "#ConfiguringAuthentication", ) raise TracError( tag_( "Authentication information not available. " "Please refer to the %(inst_doc)s.", inst_doc=inst_doc ) ) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ("anonymous", remote_user), _("Already logged in as %(user)s.", user=req.authname) cookie = hex_entropy() @self.env.with_transaction() def store_session_cookie(db): cursor = db.cursor() # Delete cookies older than 10 days cursor.execute("DELETE FROM auth_cookie WHERE time < %s", (int(time.time()) - 86400 * 10,)) cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time())), ) req.authname = remote_user req.outcookie["trac_auth"] = cookie req.outcookie["trac_auth"]["path"] = self.auth_cookie_path or req.base_path or "/" if self.env.secure_cookies: req.outcookie["trac_auth"]["secure"] = True if self.auth_cookie_lifetime > 0: req.outcookie["trac_auth"]["expires"] = self.auth_cookie_lifetime
def __init__(self, env, req): super(Session, self).__init__(env, None) self.req = req if req.authname == 'anonymous': if not req.incookie.has_key(COOKIE_KEY): self.sid = hex_entropy(24) self.bake_cookie() else: sid = req.incookie[COOKIE_KEY].value self.get_session(sid) else: if req.incookie.has_key(COOKIE_KEY): sid = req.incookie[COOKIE_KEY].value self.promote_session(sid) self.get_session(req.authname, authenticated=True)
def send_auth_request(self, req, stale='false'): """ Send a digest challange to the browser. Record used nonces to avoid replay attacks. """ nonce = util.hex_entropy() self.active_nonces.append(nonce) if len(self.active_nonces) > DigestAuth.MAX_NONCES: self.active_nonces = self.active_nonces[-DigestAuth.MAX_NONCES:] req.send_response(401) req.send_header( 'WWW-Authenticate', 'Digest realm="%s", nonce="%s", qop="auth", stale="%s"' % (self.realm, nonce, stale)) req.end_headers()
def __init__(self, env, req): super(Session, self).__init__(env, None) self.req = req if not req.is_authenticated: if COOKIE_KEY not in req.incookie: self.sid = hex_entropy(24) self.bake_cookie() else: sid = req.incookie[COOKIE_KEY].value self.get_session(sid) else: if COOKIE_KEY in req.incookie: sid = req.incookie[COOKIE_KEY].value self.promote_session(sid) self.get_session(req.authname, authenticated=True)
def _get_form_token(self, req): """Used to protect against CSRF. The 'form_token' is strong shared secret stored in a user cookie. By requiring that every POST form to contain this value we're able to protect against CSRF attacks. Since this value is only known by the user and not by an attacker. If the the user does not have a `trac_form_token` cookie a new one is generated. """ if req.incookie.has_key('trac_form_token'): return req.incookie['trac_form_token'].value else: req.outcookie['trac_form_token'] = hex_entropy(24) req.outcookie['trac_form_token']['path'] = req.base_path return req.outcookie['trac_form_token'].value
def save(self, db=None): handle_commit = False if db is None: db = self.env.get_db_cnx() handle_commit = True cursor = db.cursor() if self.key is None: self.key = hex_entropy(16) if self.exists: cursor.execute('UPDATE tracbl_apikeys SET key=%s WHERE email=%s', (self.key, self.email)) # ???: Is this needed? else: cursor.execute('INSERT INTO tracbl_apikeys (email, key) VALUES (%s, %s)', (self.email, self.key)) if handle_commit: db.commit()
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: raise TracError( tag( "Authentication information not available. " "Please refer to the ", tag.a( "installation documentation", title="Configuring Authentication", href=req.href.wiki("TracInstall") + "#ConfiguringAuthentication", ), ".", ) ) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ("anonymous", remote_user), "Already logged in as %s." % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time())), ) db.commit() req.authname = remote_user req.outcookie["trac_auth"] = cookie req.outcookie["trac_auth"]["path"] = req.base_path or "/" if self.env.secure_cookies: req.outcookie["trac_auth"]["secure"] = True
def __init__(self, env, req, newsession=False): dict.__init__(self) self.env = env self.req = req self.sid = None self._old = {} if req.authname == 'anonymous': if newsession or not req.incookie.has_key(COOKIE_KEY): self.sid = hex_entropy(24) self.bake_cookie() else: sid = req.incookie[COOKIE_KEY].value self.get_session(sid) else: if req.incookie.has_key(COOKIE_KEY): sid = req.incookie[COOKIE_KEY].value self.promote_session(sid) self.get_session(req.authname, authenticated=True)
def _do_login(self, req, remote_user): """Log the remote user in.""" cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie " "(cookie ,name ,ipnr ,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.outcookie['db_auth'] = cookie req.outcookie['db_auth']['path'] = req.href() req.outcookie['db_auth']['expires'] = 100000000 self._update_email(remote_user)
def send_auth_request(self, environ, start_response, stale="false"): """Send a digest challange to the browser. Record used nonces to avoid replay attacks. """ nonce = hex_entropy() self.active_nonces.append(nonce) if len(self.active_nonces) > self.MAX_NONCES: self.active_nonces = self.active_nonces[-self.MAX_NONCES :] start_response( "401 Unauthorized", [ ( "WWW-Authenticate", 'Digest realm="%s", nonce="%s", qop="auth", stale="%s"' % (self.realm, nonce, stale), ), ("Content-Length", "0"), ], )("")
def _do_login(self, req): """Log the remote user in.""" remote_user, pwd = req.args.get('uid'), req.args.get('pwd') remote_user = remote_user.lower() cookie = hex_entropy() db = get_db(self.env) cursor = db.cursor() cursor.execute("INSERT INTO trac_cookies " "(envname, cookie, username, ipnr, unixtime) " "VALUES (%s, %s, %s, %s, %s)", (self.envname, cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_db_auth'] = cookie req.outcookie['trac_db_auth']['expires'] = 100000000 req.outcookie['trac_db_auth']['path'] = self.env.href()
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: raise TracError( html( u"Pas d'information d'authentification disponible. " u"Merci de vous référer à la ", html.a(u"documentation d'installation", title="Configuration de l'authentification", href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication"), ".")) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ u'Déjà connecté sous %s.' % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href()
def save(self, db=None): handle_commit = False if db is None: db = self.env.get_db_cnx() handle_commit = True cursor = db.cursor() if self.key is None: self.key = hex_entropy(16) if self.exists: cursor.execute('UPDATE tracbl_apikeys SET key=%s WHERE email=%s', (self.key, self.email)) # ???: Is this needed? else: cursor.execute( 'INSERT INTO tracbl_apikeys (email, key) VALUES (%s, %s)', (self.email, self.key)) if handle_commit: db.commit()
def __init__(self, env, req): super(Session, self).__init__(env, None) self.req = req if req.incookie: sid = '' need_bake = False if not req.incookie.has_key(COOKIE_KEY): sid = hex_entropy(32) need_bake = True else: sid = req.incookie[COOKIE_KEY].value self.get_session(sid) if need_bake or sid != self.sid: self.bake_cookie() else: env.log.warning('no incookie')
def _create_auth_cookie(self, req, remote_user): cookie = hex_entropy() sql = """ INSERT IGNORE INTO auth_cookie (cookie, name, ipnr, time) VALUES (%s, %s, %s, %s) """ with admin_transaction() as cursor: try: cursor.execute(sql, (cookie, remote_user, req.remote_addr, int(time.time()))) except Exception: self.log.exception("Failed to store auth cookie into database") raise # Make new cookie self._set_outcookie(req, cookie) # Create cached cookie self.cookie.add(cookie) return cookie
def __init__(self, env, req): dict.__init__(self) self.env = env self.req = req self.sid = None self.last_visit = 0 self._new = True self._old = {} if req.authname == 'anonymous': if not req.incookie.has_key(COOKIE_KEY): self.sid = hex_entropy(24) self.bake_cookie() else: sid = req.incookie[COOKIE_KEY].value self.get_session(sid) else: if req.incookie.has_key(COOKIE_KEY): sid = req.incookie[COOKIE_KEY].value self.promote_session(sid) self.get_session(req.authname, authenticated=True)
def html_to_pdf(self, req, html_pages, book=True, title='', subject='', version='', date=''): self.env.log.debug('WikiPrint => Start function html_to_pdf') page = Markup('\n<div><pdf:nextpage /></div>'.join(html_pages)) #Replace PageOutline macro with Table of Contents if book: #If book, remove [[TOC]], and add at beginning page = page.replace('[[pdf-toc]]','') page = Markup(self.get_toc()) + Markup(page) else: page = page.replace('[[pdf-toc]]',self.get_toc()) page = self.add_headers(req, page, book, title=title, subject=subject, version=version, date=date) page = page.encode(self.default_charset, 'replace') css_data = self.get_css(req) pdf_file = StringIO.StringIO() auth_cookie = hex_entropy() loader = linkLoader(self.env, req, auth_cookie) #Temporary authentication self.env.log.debug("Storing temporary auth cookie %s for user %s", auth_cookie, req.authname) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (auth_cookie, req.authname, '127.0.0.1', int(time.time()))) db.commit() pdf = pisa.CreatePDF(page, pdf_file, show_errors_as_pdf = True, default_css = css_data, link_callback = loader.getFileName) out = pdf_file.getvalue() pdf_file.close() cursor.execute("DELETE FROM auth_cookie WHERE cookie=%s", (auth_cookie,)) db.commit() self.env.log.debug('WikiPrint => Finish function html_to_pdf') return out
def _get_form_token(self, req): """Used to protect against CSRF. The 'form_token' is strong shared secret stored in a user cookie. By requiring that every POST form to contain this value we're able to protect against CSRF attacks. Since this value is only known by the user and not by an attacker. If the the user does not have a `trac_form_token` cookie a new one is generated. """ if 'trac_form_token' in req.incookie: return req.incookie['trac_form_token'].value else: req.outcookie['trac_form_token'] = hex_entropy(24) req.outcookie['trac_form_token']['path'] = req.base_path or '/' if self.env.secure_cookies: req.outcookie['trac_form_token']['secure'] = True if sys.version_info >= (2, 6): req.outcookie['trac_form_token']['httponly'] = True return req.outcookie['trac_form_token'].value
def _login(self, req, response): """Store login information into session.""" cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie " "(cookie ,name ,ipnr ,time) " "VALUES (%s, %s, %s, %s)", (cookie, response.identity_url, req.remote_addr, int(time.time())), ) db.commit() req.outcookie["trac_auth"] = cookie req.outcookie["trac_auth"]["path"] = self.env.href() req.outcookie["trac_auth"]["expires"] = 60 * 60 * 24 # update user's contact details info = response.extensionResponse("sreg") if info and info.has_key("fullname") and len(info["fullname"]) > 0: req.session["name"] = info["fullname"] if info and info.has_key("email") and len(info["email"]) > 0: req.session["email"] = info["email"]
def _do_login(self, req): """Log the remote user in.""" remote_user, pwd = req.args.get('uid'), req.args.get('pwd') remote_user = remote_user.lower() cookie = hex_entropy() db = get_db(self.env) cursor = db.cursor() cursor.execute( "INSERT INTO trac_cookies " "(envname, cookie, username, ipnr, unixtime) " "VALUES (%s, %s, %s, %s, %s)", (self.envname, cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_db_auth'] = cookie req.outcookie['trac_db_auth']['expires'] = 100000000 req.outcookie['trac_db_auth']['path'] = self.env.href()
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: raise TracError(html(u"Pas d'information d'authentification disponible. " u"Merci de vous référer à la ", html.a(u"documentation d'installation", title="Configuration de l'authentification", href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication"), ".")) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ u'Déjà connecté sous %s.' % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href()
def _write_module(self, version, url): modname = 'TestModule_' + util.hex_entropy(16) modpath = os.path.join(self.dir, modname + '.py') with open(modpath, 'w', encoding='utf-8') as f: f.write(textwrap.dedent("""\ # -*- coding: utf-8 -*- from trac.core import Component version = '%s' author = 'Joe' author_email = '*****@*****.**' maintainer = 'Jim' maintainer_email = '*****@*****.**' home_page = '%s' license = 'BSD 3-Clause' summary = 'summary.' trac = 'http://my.trac.com' class TestModule(Component): pass """) % (version, url)) return modname
def _login(self, req, response): """Store login information into session.""" cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute('INSERT INTO auth_cookie ' \ '(cookie ,name ,ipnr ,time) ' \ 'VALUES (%s, %s, %s, %s)', (cookie, response.identity_url, req.remote_addr, int(time.time()))) db.commit() req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = self.env.href() req.outcookie['trac_auth']['expires'] = 60 * 60 * 24 # update user's contact details info = response.extensionResponse('sreg') if info and info.has_key('fullname') and len(info['fullname']) > 0: req.session['name'] = info['fullname'] if info and info.has_key('email') and len(info['email']) > 0: req.session['email'] = info['email']
def _do_login(self, req): """Log the remote user in.""" remote_user = req.args.get('uid') remote_user = remote_user.lower() cookie = hex_entropy() db = get_db(self.env) cursor = db.cursor() sql = "INSERT INTO %s " \ "(%s, %s, %s, %s, %s) " \ "VALUES (%%s, %%s, %%s, %%s, %%s)" % \ (self.cookies['table'], self.cookies['envname'], self.cookies['cookie'], self.cookies['username'], self.cookies['ipnr'], self.cookies['unixtime']) cursor.execute(sql, (self.envname, cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_db_auth'] = cookie req.outcookie['trac_db_auth']['expires'] = 100000000 req.outcookie['trac_db_auth']['path'] = self.env.href()
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ assert req.remote_user, 'Authentication information not available.' remote_user = req.remote_user ignore_case = self.env.config.get('trac', 'ignore_auth_case') ignore_case = ignore_case.strip().lower() in TRUE if ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ 'Already logged in as %s.' % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = self.env.href()
def get_auth_url(self, req): flow = self.flow state = hex_entropy() req.session[self.STATE_SKEY] = state flow.params['state'] = state return flow.step1_get_authorize_url()
def test_hex_entropy(self): """hex_entropy() not affected by global random generator state""" random.seed(0) data = util.hex_entropy(64) random.seed(0) self.assertNotEqual(data, util.hex_entropy(64))
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, session = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args,req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri,[]) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = (' '.join(filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or email.split('@',1)[0].replace('.', ' ').title()) if self.strip_protocol: remote_user = remote_user[remote_user.find('://')+3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += (" This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),)) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug("Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug("Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and email and self.re_email_white_list: self.env.log.debug("Filtering email '%s' through email white-list." % email) allowed = False for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) result = json.load(urllib.urlopen(url)) if not result[self.check_list_key]: allowed = False elif self.check_list_username: new_user = result[self.check_list_username] if new_user: remote_user = new_user if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime req.session[self.openid_session_identity_url_key] = info.identity_url if email: req.session['email'] = email if fullname: req.session['name'] = fullname self._commit_session(session, req) if req.session.get('name'): authname = req.session['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() # Make authname unique in case of collisions # # XXX: We ought to first look for an existing authenticated # ssession with matching identity_url, and just use that # for the authid. (E.g. what if the user changes his # fullname at the openid provider?) However, trac does # not seem to provide an API for searching sessions other # than by sid/authname. # def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) for authname in authnames(authname): ds = DetachedSession(self.env, authname) if ds.last_visit == 0 and len(ds) == 0: # At least in 0.12.2, this mean no session exists. break ds_identity = ds.get(self.openid_session_identity_url_key) if ds_identity == info.identity_url: # No collision break req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address(req.remote_addr), int(time.time()))) db.commit() req.redirect(req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.' elif info.status == consumer.CANCEL: # cancelled message = 'Verification cancelled' elif info.status == consumer.SETUP_NEEDED: if info.setup_url: message = '<a href=%s>Setup needed</a>' % ( quoteattr(info.setup_url),) else: # This means auth didn't succeed, but you're welcome to try # non-immediate mode. message = 'Setup needed' else: # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. message = 'Verification failed.' self._commit_session(session, req) add_stylesheet(req, 'authopenid/css/openid.css') add_script(req, 'authopenid/js/openid-jquery.js') return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': message, 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': css_class, 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None
def _get_name_for_cookie(self, req, cookie): """Returns the user name for the current Trac session. It's called by authenticate() when the cookie 'trac_auth' is sent by the browser. """ acctmgr = AccountManager(self.env) # Disable IP checking when a persistent session is available, as the # user may have a dynamic IP adress and this would lead to the user # being logged out due to an IP address conflict. checkIPSetting = self.check_ip and acctmgr.persistent_sessions and \ 'trac_auth_session' in req.incookie if checkIPSetting: self.env.config.set('trac', 'check_auth_ip', False) name = auth.LoginModule._get_name_for_cookie(self, req, cookie) if checkIPSetting: # Re-enable IP checking self.env.config.set('trac', 'check_auth_ip', True) if acctmgr.persistent_sessions and name and \ 'trac_auth_session' in req.incookie and \ int(req.incookie['trac_auth_session'].value) < \ int(time.time()) - self.UPDATE_INTERVAL: # Persistent sessions enabled, the user is logged in # ('name' exists) and has actually decided to use this feature # (indicated by the 'trac_auth_session' cookie existing). # # NOTE: This method is called on every request. # Refresh session cookie # Update the timestamp of the session so that it doesn't expire. self.env.log.debug('Updating session %s for user %s' % (cookie.value, name)) # Refresh in database db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(""" UPDATE auth_cookie SET time=%s WHERE cookie=%s """, (int(time.time()), cookie.value)) db.commit() # Change session ID (cookie.value) now and then as it otherwise # never would change at all (i.e. stay the same indefinitely and # therefore is more vulnerable to be hacked). if random.random() + self.cookie_refresh_pct / 100.0 > 1: old_cookie = cookie.value # Update auth cookie value cookie.value = hex_entropy() self.env.log.debug('Changing session id for user %s to %s' % (name, cookie.value)) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(""" UPDATE auth_cookie SET cookie=%s WHERE cookie=%s """, (cookie.value, old_cookie)) db.commit() self._distribute_cookie(req, cookie.value) cookie_lifetime = self.cookie_lifetime cookie_path = self._get_cookie_path(req) req.outcookie['trac_auth'] = cookie.value req.outcookie['trac_auth']['path'] = cookie_path req.outcookie['trac_auth']['expires'] = cookie_lifetime req.outcookie['trac_auth_session'] = int(time.time()) req.outcookie['trac_auth_session']['path'] = cookie_path req.outcookie['trac_auth_session']['expires'] = cookie_lifetime try: if self.env.secure_cookies: req.outcookie['trac_auth']['secure'] = True req.outcookie['trac_auth_session']['secure'] = True except AttributeError: # Report details about Trac compatibility for the feature. self.env.log.debug( """Restricting cookies to HTTPS connections is requested, but is supported only by Trac 0.11.2 or later version. """) return name
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, oidsession = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args, req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' session_attr = {} # attributes for new "user" # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url), ) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri, []) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = (' '.join( filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or (email and email.split('@', 1)[0].replace('.', ' ').title())) nickname = sreg_info.get('nickname') if self.groups_to_request and TeamsResponse: teams_response = TeamsResponse.fromSuccessResponse(info) if teams_response: # be careful not to make user a member of any trac groups # not named in groups_to_request teams = set(teams_response.teams).intersection( self.groups_to_request) if teams: session_attr['openid.teams'] = ','.join(teams) if self.strip_protocol: remote_user = remote_user[remote_user.find('://') + 3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += ( " This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID), )) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug( "Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug( "Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and self.re_email_white_list: self.env.log.debug( "Filtering email %r through email white-list." % email) allowed = False if email: for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: allowed = False params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) try: result = json.load(urllib.urlopen(url)) if result[self.check_list_key]: if self.check_list_username: cl_username = unicode( result[self.check_list_username]) if not cl_username: raise ValueError("Bad value for username") allowed = True except Exception, ex: self.env.log.error('OpenID check_list failed: %s' % ex) if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime session_attr[ self.openid_session_identity_url_key] = info.identity_url if email: session_attr['email'] = email if fullname: session_attr['name'] = fullname self._commit_oidsession(oidsession, req) if self.check_list and self.check_list_username: authname = cl_username elif self.use_nickname_as_authname and nickname: authname = nickname elif session_attr.get('name'): authname = session_attr['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) else: authname = remote_user # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() if self.trust_authname: ds = DetachedSession(self.env, authname) else: # Make authname unique in case of collisions # # XXX: We ought to first look for an existing authenticated # session with matching identity_url, and just use that # for the authid. (E.g. what if the user changes his # fullname at the openid provider?) However, trac does # not seem to provide an API for searching sessions other # than by sid/authname. # def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) existing_users_and_groups = set( user for user, perm in PermissionSystem( self.env).get_all_permissions()) for authname in authnames(authname): ds = DetachedSession(self.env, authname) if ds.last_visit == 0 and len(ds) == 0: # At least in 0.12.2, this mean no session exists. if authname in existing_users_and_groups: # Permissions are already defined for this user continue break ds_identity = ds.get( self.openid_session_identity_url_key) if ds_identity == info.identity_url: # No collision break if ds and (ds.last_visit != 0 or len(ds) > 0): # The user already exists, update team membership # XXX: Should also update name and/or email? (This would # be an API change.) for name in ['openid.teams']: if name in session_attr: ds[name] = session_attr[name] elif name in ds: del ds[name] ds.save() else: # We are creating a new "user". Set attributes on the # current anonymous session. It will be promoted to # the new authenticated session on the next request # (by Session.__init__). # # NB: avoid dict.update here to ensure that # DetachedSession.__getitem__ gets a chance to # normalize values for name, value in session_attr.items(): req.session[name] = value req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address( req.remote_addr), int(time.time()))) db.commit() req.redirect( req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.'
def _get_name_for_cookie(self, req, cookie): """Returns the username for the current Trac session. It's called by authenticate() when the cookie 'trac_auth' is sent by the browser. """ acctmgr = AccountManager(self.env) name = None # Replicate _get_name_for_cookie() or _cookie_to_name() since Trac 1.0 # adding special handling of persistent sessions, as the user may have # a dynamic IP adress and this would lead to the user being logged out # due to an IP address conflict. if 'trac_auth_session' in req.incookie or True: db = self.env.get_db_cnx() cursor = db.cursor() sql = "SELECT name FROM auth_cookie WHERE cookie=%s AND ipnr=%s" args = (cookie.value, req.remote_addr) if acctmgr.persistent_sessions or not self.check_ip: sql = "SELECT name FROM auth_cookie WHERE cookie=%s" args = (cookie.value, ) cursor.execute(sql, args) name = cursor.fetchone() name = name and name[0] or None if name is None: self._expire_cookie(req) if acctmgr.persistent_sessions and name and \ 'trac_auth_session' in req.incookie and \ int(req.incookie['trac_auth_session'].value) < \ int(time.time()) - self.UPDATE_INTERVAL: # Persistent sessions enabled, the user is logged in # ('name' exists) and has actually decided to use this feature # (indicated by the 'trac_auth_session' cookie existing). # # NOTE: This method is called on every request. # Refresh session cookie # Update the timestamp of the session so that it doesn't expire. self.env.log.debug('Updating session %s for user %s' % (cookie.value, name)) # Refresh in database db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( """ UPDATE auth_cookie SET time=%s WHERE cookie=%s """, (int(time.time()), cookie.value)) db.commit() # Change session ID (cookie.value) now and then as it otherwise # never would change at all (i.e. stay the same indefinitely and # therefore is more vulnerable to be hacked). if random.random() + self.cookie_refresh_pct / 100.0 > 1: old_cookie = cookie.value # Update auth cookie value cookie.value = hex_entropy() self.env.log.debug('Changing session id for user %s to %s' % (name, cookie.value)) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( """ UPDATE auth_cookie SET cookie=%s WHERE cookie=%s """, (cookie.value, old_cookie)) db.commit() if self.auth_cookie_path: self._distribute_auth(req, cookie.value, name) cookie_lifetime = self.cookie_lifetime cookie_path = self._get_cookie_path(req) req.outcookie['trac_auth'] = cookie.value req.outcookie['trac_auth']['path'] = cookie_path req.outcookie['trac_auth']['expires'] = cookie_lifetime req.outcookie['trac_auth_session'] = int(time.time()) req.outcookie['trac_auth_session']['path'] = cookie_path req.outcookie['trac_auth_session']['expires'] = cookie_lifetime try: if self.env.secure_cookies: req.outcookie['trac_auth']['secure'] = True req.outcookie['trac_auth_session']['secure'] = True except AttributeError: # Report details about Trac compatibility for the feature. self.env.log.debug( """Restricting cookies to HTTPS connections is requested, but is supported only by Trac 0.11.2 or later version. """) return name
def html_to_pdf(self, req, html_pages, book=True, title='', subject='', version='', date=''): self.env.log.debug('WikiPrint => Start function html_to_pdf') page = Markup('\n<div><pdf:nextpage /></div>'.join(html_pages)) #Replace PageOutline macro with Table of Contents if book: #If book, remove [[TOC]], and add at beginning page = page.replace('[[pdf-toc]]', '') page = Markup(self.get_toc()) + Markup(page) else: page = page.replace('[[pdf-toc]]', self.get_toc()) page = self.add_headers(req, page, book, title=title, subject=subject, version=version, date=date) page = page.encode(self.default_charset, 'replace') css_data = self.get_css(req) pdf_file = StringIO.StringIO() auth_cookie = hex_entropy() loader = linkLoader(self.env, req, auth_cookie) #Temporary authentication self.env.log.debug("Storing temporary auth cookie %s for user %s", auth_cookie, req.authname) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (auth_cookie, req.authname, '127.0.0.1', int(time.time()))) db.commit() pdf = pisa.CreatePDF(page, pdf_file, show_errors_as_pdf=True, default_css=css_data, link_callback=loader.getFileName) out = pdf_file.getvalue() pdf_file.close() cursor.execute("DELETE FROM auth_cookie WHERE cookie=%s", (auth_cookie, )) db.commit() self.env.log.debug('WikiPrint => Finish function html_to_pdf') return out
def new_biff_key(self): return hex_entropy(16)
def generate_key(self): return hex_entropy(32)
def _generate_module_name(self): return 'tracmigratetest_' + hex_entropy(16)
def _do_process(self, req): """Handle the redirect from the OpenID server. """ oidconsumer, session = self._get_consumer(req) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args,req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += (" This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),)) remote_user = info.endpoint.canonicalID cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, self._get_masked_address(req.remote_addr), int(time.time()))) db.commit() req.authname = info.identity_url req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() req.outcookie['trac_auth']['expires'] = 60*60*24 reg_info = sreg.SRegResponse.fromSuccessResponse(info).getExtensionArgs() if reg_info and reg_info.has_key('nickname') and len(reg_info['nickname']) > 0: req.session['name'] = reg_info['nickname'] if reg_info and reg_info.has_key('email') and len(reg_info['email']) > 0: req.session['email'] = reg_info['email'] elif info.status == consumer.CANCEL: # cancelled message = 'Verification cancelled' elif info.status == consumer.SETUP_NEEDED: if info.setup_url: message = '<a href=%s>Setup needed</a>' % ( quoteattr(info.setup_url),) else: # This means auth didn't succeed, but you're welcome to try # non-immediate mode. message = 'Setup needed' else: # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. message = 'Verification failed.' self._commit_session(session, req) add_stylesheet(req, 'authopenid/css/openid.css') return 'openidlogin.html', { 'action': req.href.openidverify(), 'message': message, 'css_class': css_class }, None
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, session = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args, req.args["openid.return_to"]) css_class = "error" if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = "alert" # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url reg_info = None ax_response = ax.FetchResponse.fromSuccessResponse(info) if ax_response: ax_data = ax_response.getExtensionArgs() email = ax_data.get("value.ext0.1", "") if email: reg_info = {"email": email, "fullname": email.split("@", 1)[0].replace(".", " ").title()} if not reg_info: response = sreg.SRegResponse.fromSuccessResponse(info) if response: reg_info = response.getExtensionArgs() if self.strip_protocol: remote_user = remote_user[remote_user.find("://") + 3 :] if self.strip_trailing_slash and remote_user[-1] == "/": remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += " This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug("Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug("Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and self.check_list: params = {self.check_list_key: remote_user} if reg_info and reg_info.has_key("email") and len(reg_info["email"]) > 0: params["email"] = reg_info["email"] url = self.check_list + "?" + urllib.urlencode(params) self.env.log.debug("OpenID check list URL: %s" % url) result = simplejson.load(urllib.urlopen(url)) if not result[self.check_list_key]: allowed = False elif self.check_list_username: new_user = result[self.check_list_username] if new_user: remote_user = new_user if allowed: cookie = hex_entropy() req.outcookie["trac_auth"] = cookie req.outcookie["trac_auth"]["path"] = req.href() req.outcookie["trac_auth"]["expires"] = self.trac_auth_expires req.session[self.openid_session_identity_url_key] = info.identity_url if reg_info and reg_info.has_key("fullname") and len(reg_info["fullname"]) > 0: req.session["name"] = reg_info["fullname"] if reg_info and reg_info.has_key("email") and len(reg_info["email"]) > 0: req.session["email"] = reg_info["email"] self._commit_session(session, req) if self.combined_username and req.session["name"]: remote_user = "******" % (req.session["name"], remote_user) else: if req.session.has_key("name"): remote_user = req.session["name"] # Check if we generated a colliding remote_user and make the user unique collisions = 0 cremote_user = remote_user while True: ds = DetachedSession(self.env, remote_user) if not ds.last_visit: # New session break if not ds.has_key(self.openid_session_identity_url_key): # Old session, without the identity url set # Save the identity url then (bascially adopt the session) ds[self.openid_session_identity_url_key] = info.identity_url ds.save() break if ds[self.openid_session_identity_url_key] == info.identity_url: # No collision break # We got us a collision # Make the thing unique collisions += 1 remote_user = "******" % (cremote_user, collisions + 1) req.authname = remote_user db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, self._get_masked_address(req.remote_addr), int(time.time())), ) db.commit() req.redirect(req.session.get("oid.referer") or self.env.abs_href()) else: message = "You are not allowed here." elif info.status == consumer.CANCEL: # cancelled message = "Verification cancelled" elif info.status == consumer.SETUP_NEEDED: if info.setup_url: message = "<a href=%s>Setup needed</a>" % (quoteattr(info.setup_url),) else: # This means auth didn't succeed, but you're welcome to try # non-immediate mode. message = "Setup needed" else: # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. message = "Verification failed." self._commit_session(session, req) add_stylesheet(req, "authopenid/css/openid.css") add_script(req, "authopenid/js/openid-jquery.js") return ( "openidlogin.html", { "images": req.href.chrome("authopenid/images") + "/", "action": req.href.openidverify(), "message": message, "signup": self.signup_link, "whatis": self.whatis_link, "css_class": css_class, "custom_provider_name": self.custom_provider_name, "custom_provider_label": self.custom_provider_label, "custom_provider_url": self.custom_provider_url, "custom_provider_image": self.custom_provider_image, }, None, )
def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, oidsession = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. current_url = req.abs_href(req.path_info) info = oidconsumer.complete(req.args,current_url) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' session_attr = {} # attributes for new "user" # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri,[]) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = ( ' '.join(filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or (email and email.split('@',1)[0].replace('.', ' ').title())) nickname = sreg_info.get('nickname') if self.groups_to_request and TeamsResponse: teams_response = TeamsResponse.fromSuccessResponse(info) if teams_response: # be careful not to make user a member of any trac groups # not named in groups_to_request teams = set(teams_response.teams ).intersection(self.groups_to_request) if teams: session_attr['openid.teams'] = ','.join(teams) if self.strip_protocol: remote_user = remote_user[remote_user.find('://')+3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += (" This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),)) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug("Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug("Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and self.re_email_white_list: self.env.log.debug("Filtering email %r through email white-list." % email) allowed = False if email: for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: allowed = False params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) try: result = json.load(urllib.urlopen(url)) if result[self.check_list_key]: if self.check_list_username: cl_username = unicode( result[self.check_list_username]) if not cl_username: raise ValueError("Bad value for username") allowed = True except Exception, ex: self.env.log.error('OpenID check_list failed: %s' % ex) if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime session_attr[self.openid_session_identity_url_key] = info.identity_url if email: session_attr['email'] = email if fullname: session_attr['name'] = fullname self._commit_oidsession(oidsession, req) # First look for an existing authenticated session with # matching identity_url. self.env.log.debug('Checking URL: %s' % info.identity_url) authname_for_identity_url = self.get_user(info.identity_url) if authname_for_identity_url: authname = authname_for_identity_url ds = DetachedSession(self.env, authname) # The user already exists, update team membership # XXX: Should also update name and/or email? (This would # be an API change.) for name in ['openid.teams']: if name in session_attr: ds[name] = session_attr[name] elif name in ds: del ds[name] ds.save() else: # New identity URL -> create new authname/user. if self.check_list and self.check_list_username: authname = cl_username elif self.use_email_as_authname and email: authname = email elif self.use_nickname_as_authname and nickname: authname = nickname elif session_attr.get('name'): authname = session_attr['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) else: authname = remote_user # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() if self.trust_authname: ds = DetachedSession(self.env, authname) else: # Make authname unique in case of collisions def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) users_and_groups_with_permissions = set( user for user, perm in PermissionSystem(self.env).get_all_permissions()) for authname in authnames(authname): ds = DetachedSession(self.env, authname) # At least in 0.12.2, this means no session exists. no_session_exists = ds.last_visit == 0 and len(ds) == 0 no_permissions_defined = authname not in users_and_groups_with_permissions if (no_session_exists and no_permissions_defined): # name is free :-) break # Set attributes for new user on the # current anonymous session. It will be promoted to # the new authenticated session on the next request # (by Session.__init__). # # NB: avoid dict.update here to ensure that # DetachedSession.__getitem__ gets a chance to # normalize values for name, value in session_attr.items(): req.session[name] = value self.env.log.info("Created new user '%s' for " "OpenID identifier %s", authname, info.identity_url) req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address(req.remote_addr), int(time.time()))) db.commit() req.redirect(req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.'
def _generate_module_name(self): return 'trac_convert_db_' + hex_entropy(16)
def _get_name_for_cookie(self, req, cookie): """Returns the username for the current Trac session. It's called by authenticate() when the cookie 'trac_auth' is sent by the browser. """ acctmgr = AccountManager(self.env) name = None # Replicate _get_name_for_cookie() or _cookie_to_name() since Trac 1.0 # adding special handling of persistent sessions, as the user may have # a dynamic IP adress and this would lead to the user being logged out # due to an IP address conflict. if 'trac_auth_session' in req.incookie or True: with self.env.db_query as db: cursor = db.cursor() sql = "SELECT name FROM auth_cookie WHERE cookie=%s AND ipnr=%s" args = (cookie.value, req.remote_addr) if acctmgr.persistent_sessions or not self.check_ip: sql = "SELECT name FROM auth_cookie WHERE cookie=%s" args = (cookie.value,) cursor.execute(sql, args) name = cursor.fetchone() name = name and name[0] or None if name is None: self._expire_cookie(req) if acctmgr.persistent_sessions and name and \ 'trac_auth_session' in req.incookie and \ int(req.incookie['trac_auth_session'].value) < \ int(time.time()) - self.UPDATE_INTERVAL: # Persistent sessions enabled, the user is logged in # ('name' exists) and has actually decided to use this feature # (indicated by the 'trac_auth_session' cookie existing). # # NOTE: This method is called on every request. # Refresh session cookie # Update the timestamp of the session so that it doesn't expire. self.env.log.debug('Updating session %s for user %s' % (cookie.value, name)) # Refresh in database with self.env.db_transaction as db: cursor = db.cursor() cursor.execute(""" UPDATE auth_cookie SET time=%s WHERE cookie=%s """, (int(time.time()), cookie.value)) # Change session ID (cookie.value) now and then as it otherwise # never would change at all (i.e. stay the same indefinitely and # therefore is more vulnerable to be hacked). if random.random() + self.cookie_refresh_pct / 100.0 > 1: old_cookie = cookie.value # Update auth cookie value cookie.value = hex_entropy() self.env.log.debug('Changing session id for user %s to %s' % (name, cookie.value)) with self.env.db_transaction: cursor = db.cursor() cursor.execute(""" UPDATE auth_cookie SET cookie=%s WHERE cookie=%s """, (cookie.value, old_cookie)) if self.auth_cookie_path: self._distribute_auth(req, cookie.value, name) cookie_lifetime = self.cookie_lifetime cookie_path = self._get_cookie_path(req) req.outcookie['trac_auth'] = cookie.value req.outcookie['trac_auth']['path'] = cookie_path req.outcookie['trac_auth']['expires'] = cookie_lifetime req.outcookie['trac_auth_session'] = int(time.time()) req.outcookie['trac_auth_session']['path'] = cookie_path req.outcookie['trac_auth_session']['expires'] = cookie_lifetime try: if self.env.secure_cookies: req.outcookie['trac_auth']['secure'] = True req.outcookie['trac_auth_session']['secure'] = True except AttributeError: # Report details about Trac compatibility for the feature. self.env.log.debug( """Restricting cookies to HTTPS connections is requested, but is supported only by Trac 0.11.2 or later version. """) return name