| Index: telemetry/third_party/webpagereplay/adb_install_cert.py
|
| diff --git a/telemetry/third_party/webpagereplay/adb_install_cert.py b/telemetry/third_party/webpagereplay/adb_install_cert.py
|
| deleted file mode 100644
|
| index 7d56df474a764260012dbb49b8cc07e79ccd90d4..0000000000000000000000000000000000000000
|
| --- a/telemetry/third_party/webpagereplay/adb_install_cert.py
|
| +++ /dev/null
|
| @@ -1,275 +0,0 @@
|
| -# Copyright 2014 Google Inc. All Rights Reserved.
|
| -#
|
| -# Licensed under the Apache License, Version 2.0 (the "License");
|
| -# you may not use this file except in compliance with the License.
|
| -# You may obtain a copy of the License at
|
| -#
|
| -# http://www.apache.org/licenses/LICENSE-2.0
|
| -#
|
| -# Unless required by applicable law or agreed to in writing, software
|
| -# distributed under the License is distributed on an "AS IS" BASIS,
|
| -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -# See the License for the specific language governing permissions and
|
| -# limitations under the License.
|
| -
|
| -"""Installs certificate on phone with KitKat."""
|
| -
|
| -import argparse
|
| -import logging
|
| -import os
|
| -import subprocess
|
| -import sys
|
| -
|
| -KEYCODE_ENTER = '66'
|
| -KEYCODE_TAB = '61'
|
| -
|
| -
|
| -class CertInstallError(Exception):
|
| - pass
|
| -
|
| -
|
| -class CertRemovalError(Exception):
|
| - pass
|
| -
|
| -
|
| -class AdbShellError(subprocess.CalledProcessError):
|
| - pass
|
| -
|
| -
|
| -_ANDROID_M_BUILD_VERSION = 23
|
| -
|
| -
|
| -class AndroidCertInstaller(object):
|
| - """Certificate installer for phones with KitKat."""
|
| -
|
| - def __init__(self, device_id, cert_name, cert_path, adb_path=None):
|
| - if not os.path.exists(cert_path):
|
| - raise ValueError('Not a valid certificate path')
|
| - self.adb_path = adb_path or 'adb'
|
| - self.android_cacerts_path = None
|
| - self.cert_name = cert_name
|
| - self.cert_path = cert_path
|
| - self.device_id = device_id
|
| - self.file_name = os.path.basename(self.cert_path)
|
| - self.reformatted_cert_fname = None
|
| - self.reformatted_cert_path = None
|
| -
|
| - @staticmethod
|
| - def _run_cmd(cmd, dirname=None):
|
| - return subprocess.check_output(cmd, cwd=dirname)
|
| -
|
| - def _get_adb_cmd(self, *args):
|
| - cmd = [self.adb_path]
|
| - if self.device_id:
|
| - cmd.extend(['-s', self.device_id])
|
| - cmd.extend(args)
|
| - return cmd
|
| -
|
| - def _adb(self, *args):
|
| - """Runs the adb command."""
|
| - return self._run_cmd(self._get_adb_cmd(*args))
|
| -
|
| - def _adb_shell(self, *args):
|
| - """Runs the adb shell command."""
|
| - # We are not using self._adb() because adb shell return 0 even if the
|
| - # command has failed. This method is taking care of checking the actual
|
| - # return code of the command line ran on the device.
|
| - RETURN_CODE_PREFIX = '%%%s%% ' % __file__
|
| - adb_cmd = self._get_adb_cmd('shell', '(%s); echo %s$?' % (
|
| - subprocess.list2cmdline(args), RETURN_CODE_PREFIX))
|
| - process = subprocess.Popen(adb_cmd, stdout=subprocess.PIPE)
|
| - adb_stdout, _ = process.communicate()
|
| - if process.returncode != 0:
|
| - raise subprocess.CalledProcessError(
|
| - cmd=adb_cmd, returncode=process.returncode, output=adb_stdout)
|
| - assert adb_stdout[-1] == '\n'
|
| - prefix_pos = adb_stdout.rfind(RETURN_CODE_PREFIX)
|
| - assert prefix_pos != -1, \
|
| - 'Couldn\'t find "%s" at the end of the output of %s' % (
|
| - RETURN_CODE_PREFIX, subprocess.list2cmdline(adb_cmd))
|
| - returncode = int(adb_stdout[prefix_pos + len(RETURN_CODE_PREFIX):])
|
| - stdout = adb_stdout[:prefix_pos]
|
| - if returncode != 0:
|
| - raise AdbShellError(cmd=args, returncode=returncode, output=stdout)
|
| - return stdout
|
| -
|
| - def _adb_su_shell(self, *args):
|
| - """Runs command as root."""
|
| - build_version_sdk = int(self._get_property('ro.build.version.sdk'))
|
| - if build_version_sdk >= _ANDROID_M_BUILD_VERSION:
|
| - cmd = ['su', '0']
|
| - else:
|
| - cmd = ['su', '-c']
|
| - cmd.extend(args)
|
| - return self._adb_shell(*cmd)
|
| -
|
| - def _get_property(self, prop):
|
| - return self._adb_shell('getprop', prop).strip()
|
| -
|
| - def check_device(self):
|
| - install_warning = False
|
| - if self._get_property('ro.product.device') != 'hammerhead':
|
| - logging.warning('Device is not hammerhead')
|
| - install_warning = True
|
| - if self._get_property('ro.build.version.release') != '4.4.2':
|
| - logging.warning('Version is not 4.4.2')
|
| - install_warning = True
|
| - if install_warning:
|
| - logging.warning('Certificate may not install properly')
|
| -
|
| - def _input_key(self, key):
|
| - """Inputs a keyevent."""
|
| - self._adb_shell('input', 'keyevent', key)
|
| -
|
| - def _input_text(self, text):
|
| - """Inputs text."""
|
| - self._adb_shell('input', 'text', text)
|
| -
|
| - @staticmethod
|
| - def _remove(file_name):
|
| - """Deletes file."""
|
| - if os.path.exists(file_name):
|
| - os.remove(file_name)
|
| -
|
| - def _format_hashed_cert(self):
|
| - """Makes a certificate file that follows the format of files in cacerts."""
|
| - self._remove(self.reformatted_cert_path)
|
| - contents = self._run_cmd(['openssl', 'x509', '-inform', 'PEM', '-text',
|
| - '-in', self.cert_path])
|
| - description, begin_cert, cert_body = contents.rpartition('-----BEGIN '
|
| - 'CERTIFICATE')
|
| - contents = ''.join([begin_cert, cert_body, description])
|
| - with open(self.reformatted_cert_path, 'w') as cert_file:
|
| - cert_file.write(contents)
|
| -
|
| - def _remove_cert_from_cacerts(self):
|
| - self._adb_su_shell('mount', '-o', 'remount,rw', '/system')
|
| - self._adb_su_shell('rm', '-f', self.android_cacerts_path)
|
| -
|
| - def _is_cert_installed(self):
|
| - try:
|
| - return (self._adb_su_shell('ls', self.android_cacerts_path).strip() ==
|
| - self.android_cacerts_path)
|
| - except AdbShellError:
|
| - return False
|
| -
|
| - def _generate_reformatted_cert_path(self):
|
| - # Determine OpenSSL version, string is of the form
|
| - # 'OpenSSL 0.9.8za 5 Jun 2014' .
|
| - openssl_version = self._run_cmd(['openssl', 'version']).split()
|
| -
|
| - if len(openssl_version) < 2:
|
| - raise ValueError('Unexpected OpenSSL version string: ', openssl_version)
|
| -
|
| - # subject_hash flag name changed as of OpenSSL version 1.0.0 .
|
| - is_old_openssl_version = openssl_version[1].startswith('0')
|
| - subject_hash_flag = (
|
| - '-subject_hash' if is_old_openssl_version else '-subject_hash_old')
|
| -
|
| - output = self._run_cmd(['openssl', 'x509', '-inform', 'PEM',
|
| - subject_hash_flag, '-in', self.cert_path],
|
| - os.path.dirname(self.cert_path))
|
| - self.reformatted_cert_fname = output.partition('\n')[0].strip() + '.0'
|
| - self.reformatted_cert_path = os.path.join(os.path.dirname(self.cert_path),
|
| - self.reformatted_cert_fname)
|
| - self.android_cacerts_path = ('/system/etc/security/cacerts/%s' %
|
| - self.reformatted_cert_fname)
|
| -
|
| - def remove_cert(self):
|
| - self._generate_reformatted_cert_path()
|
| -
|
| - if self._is_cert_installed():
|
| - self._remove_cert_from_cacerts()
|
| -
|
| - if self._is_cert_installed():
|
| - raise CertRemovalError('Cert Removal Failed')
|
| -
|
| - def install_cert(self, overwrite_cert=False):
|
| - """Installs a certificate putting it in /system/etc/security/cacerts."""
|
| - self._generate_reformatted_cert_path()
|
| -
|
| - if self._is_cert_installed():
|
| - if overwrite_cert:
|
| - self._remove_cert_from_cacerts()
|
| - else:
|
| - logging.info('cert is already installed')
|
| - return
|
| -
|
| - self._format_hashed_cert()
|
| - self._adb('push', self.reformatted_cert_path, '/sdcard/')
|
| - self._remove(self.reformatted_cert_path)
|
| - self._adb_su_shell('mount', '-o', 'remount,rw', '/system')
|
| - self._adb_su_shell(
|
| - 'cp', '/sdcard/%s' % self.reformatted_cert_fname,
|
| - '/system/etc/security/cacerts/%s' % self.reformatted_cert_fname)
|
| - self._adb_su_shell('chmod', '644', self.android_cacerts_path)
|
| - if not self._is_cert_installed():
|
| - raise CertInstallError('Cert Install Failed')
|
| -
|
| - def install_cert_using_gui(self):
|
| - """Installs certificate on the device using adb commands."""
|
| - self.check_device()
|
| - # TODO(mruthven): Add a check to see if the certificate is already installed
|
| - # Install the certificate.
|
| - logging.info('Installing %s on %s', self.cert_path, self.device_id)
|
| - self._adb('push', self.cert_path, '/sdcard/')
|
| -
|
| - # Start credential install intent.
|
| - self._adb_shell('am', 'start', '-W', '-a', 'android.credentials.INSTALL')
|
| -
|
| - # Move to and click search button.
|
| - self._input_key(KEYCODE_TAB)
|
| - self._input_key(KEYCODE_TAB)
|
| - self._input_key(KEYCODE_ENTER)
|
| -
|
| - # Search for certificate and click it.
|
| - # Search only works with lower case letters
|
| - self._input_text(self.file_name.lower())
|
| - self._input_key(KEYCODE_ENTER)
|
| -
|
| - # These coordinates work for hammerhead devices.
|
| - self._adb_shell('input', 'tap', '300', '300')
|
| -
|
| - # Name the certificate and click enter.
|
| - self._input_text(self.cert_name)
|
| - self._input_key(KEYCODE_TAB)
|
| - self._input_key(KEYCODE_TAB)
|
| - self._input_key(KEYCODE_TAB)
|
| - self._input_key(KEYCODE_ENTER)
|
| -
|
| - # Remove the file.
|
| - self._adb_shell('rm', '/sdcard/' + self.file_name)
|
| -
|
| -
|
| -def parse_args():
|
| - """Parses command line arguments."""
|
| - parser = argparse.ArgumentParser(description='Install cert on device.')
|
| - parser.add_argument(
|
| - '-n', '--cert-name', default='dummycert', help='certificate name')
|
| - parser.add_argument(
|
| - '--overwrite', default=False, action='store_true',
|
| - help='Overwrite certificate file if it is already installed')
|
| - parser.add_argument(
|
| - '--remove', default=False, action='store_true',
|
| - help='Remove certificate file if it is installed')
|
| - parser.add_argument(
|
| - '--device-id', help='device serial number')
|
| - parser.add_argument(
|
| - '--adb-path', help='adb binary path')
|
| - parser.add_argument(
|
| - 'cert_path', help='Certificate file path')
|
| - return parser.parse_args()
|
| -
|
| -
|
| -def main():
|
| - args = parse_args()
|
| - cert_installer = AndroidCertInstaller(args.device_id, args.cert_name,
|
| - args.cert_path, adb_path=args.adb_path)
|
| - if args.remove:
|
| - cert_installer.remove_cert()
|
| - else:
|
| - cert_installer.install_cert(args.overwrite)
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - sys.exit(main())
|
|
|