#!/usr/bin/env python # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Generates and passes authentication credentials to Chromium. This script can be used to simulate the login manager's process of passing authentication credentials to Chromium. Running this script will authenticate with Google Accounts with the provided login credentials and then write the result to the specified pipe. The script will then block until the pipe is read. To launch Chromium, use the command: ./chrome --cookie-pipe=/tmp/cookie_pipe """ from optparse import OptionParser import getpass import os import sys import urllib import urllib2 DEFAULT_COOKIE_PIPE = '/tmp/cookie_pipe' GOOGLE_ACCOUNTS_URL = 'https://www.google.com/accounts' LOGIN_SOURCE = 'test_harness' class CookieCollectorRedirectHandler(urllib2.HTTPRedirectHandler): def __init__(self): self.__cookie_headers = [] @property def cookie_headers(self): return self.__cookie_headers def http_error_302(self, req, fp, code, msg, headers): self.__cookie_headers.extend(fp.info().getallmatchingheaders('Set-Cookie')) result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers) return result def Authenticate(email, password): opener = urllib2.build_opener() payload = urllib.urlencode({'Email': email, 'Passwd': password, 'PersistentCookie': 'true', 'accountType' : 'HOSTED_OR_GOOGLE', 'source' : LOGIN_SOURCE}) request = urllib2.Request(GOOGLE_ACCOUNTS_URL + '/ClientLogin', payload) response = opener.open(request) data = response.read().rstrip() # Convert the SID=xxx\nLSID=yyy\n response into a dict. l = [p.split('=') for p in data.split('\n')] cookies = dict((i[0], i[1]) for i in l) payload = urllib.urlencode({'SID': cookies['SID'], 'LSID': cookies['LSID'], 'source': LOGIN_SOURCE, 'service': 'gaia'}) request = urllib2.Request(GOOGLE_ACCOUNTS_URL + '/IssueAuthToken', payload) response = opener.open(request) auth_token = response.read().rstrip() url = '/TokenAuth?continue=http://www.google.com/&source=%s&auth=%s' % \ (LOGIN_SOURCE, auth_token) # Install a custom redirect handler here so we can catch all the # cookies served as the redirects get processed. cookie_collector = CookieCollectorRedirectHandler() opener = urllib2.build_opener(cookie_collector) request = urllib2.Request(GOOGLE_ACCOUNTS_URL + url) response = opener.open(request) cookie_headers = cookie_collector.cookie_headers cookie_headers.extend(response.info().getallmatchingheaders('Set-Cookie')) cookies = [s.replace('Set-Cookie: ', '') for s in cookie_headers] return cookies def WriteToPipe(pipe_path, data): os.remove(pipe_path) os.mkfifo(pipe_path) f = open(pipe_path, 'w') f.write(data) f.close() def main(): usage = "usage: %prog [options]" parser = OptionParser(usage) parser.add_option('--email', dest='email', help='email address used for login') parser.add_option('--password', dest='password', help='password used for login (will prompt if omitted)') parser.add_option('--cookie-pipe', dest='cookiepipe', default=DEFAULT_COOKIE_PIPE, help='path of cookie pipe [default: %default]') (options, args) = parser.parse_args() if options.email is None: parser.error("You must supply an email address.") if options.password is None: options.password = getpass.getpass() cookies = Authenticate(options.email, options.password) data = ''.join(cookies) print 'Writing to "%s":' % options.cookiepipe print data WriteToPipe(options.cookiepipe, data) if __name__ == '__main__': main()