Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # Virtual Me2Me implementation. This script runs and manages the processes | 6 # Virtual Me2Me implementation. This script runs and manages the processes |
| 7 # required for a Virtual Me2Me desktop, which are: X server, X desktop | 7 # required for a Virtual Me2Me desktop, which are: X server, X desktop |
| 8 # session, and Host process. | 8 # session, and Host process. |
| 9 # This script is intended to run continuously as a background daemon | 9 # This script is intended to run continuously as a background daemon |
| 10 # process, running under an ordinary (non-root) user account. | 10 # process, running under an ordinary (non-root) user account. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 def clear_host_info(self): | 122 def clear_host_info(self): |
| 123 del self.data["host_id"] | 123 del self.data["host_id"] |
| 124 del self.data["host_name"] | 124 del self.data["host_name"] |
| 125 del self.data["host_secret_hash"] | 125 del self.data["host_secret_hash"] |
| 126 del self.data["private_key"] | 126 del self.data["private_key"] |
| 127 | 127 |
| 128 class Authentication: | 128 class Authentication: |
| 129 """Manage authentication tokens for Chromoting/xmpp""" | 129 """Manage authentication tokens for Chromoting/xmpp""" |
| 130 | 130 |
| 131 def __init__(self): | 131 def __init__(self): |
| 132 pass | 132 self.chromoting_auth_token = None |
| 133 self.login = None | |
| 134 self.xmpp_auth_token = None | |
| 133 | 135 |
| 134 def generate_tokens(self): | 136 def generate_tokens(self): |
| 135 """Prompt for username/password and use them to generate new authentication | 137 """Prompt for username/password and use them to generate new authentication |
| 136 tokens. | 138 tokens. |
| 137 | 139 |
| 138 Raises: | 140 Raises: |
| 139 Exception: Failed to get new authentication tokens. | 141 Exception: Failed to get new authentication tokens. |
| 140 """ | 142 """ |
| 141 print "Email:", | 143 print "Email:", |
| 142 self.login = raw_input() | 144 self.login = raw_input() |
| 143 password = getpass.getpass("App-specific password: ") | 145 password = getpass.getpass("App-specific password: ") |
| 144 | 146 |
| 145 chromoting_auth = gaia_auth.GaiaAuthenticator('chromoting') | 147 chromoting_auth = gaia_auth.GaiaAuthenticator('chromoting') |
| 146 self.chromoting_auth_token = chromoting_auth.authenticate(self.login, | 148 self.chromoting_auth_token = chromoting_auth.authenticate(self.login, |
| 147 password) | 149 password) |
| 148 | 150 |
| 149 xmpp_authenticator = gaia_auth.GaiaAuthenticator('chromiumsync') | 151 xmpp_authenticator = gaia_auth.GaiaAuthenticator('chromiumsync') |
| 150 self.xmpp_auth_token = xmpp_authenticator.authenticate(self.login, | 152 self.xmpp_auth_token = xmpp_authenticator.authenticate(self.login, |
| 151 password) | 153 password) |
| 152 | 154 |
| 155 def has_chromoting_token(self): | |
| 156 return self.chromoting_auth_token != None | |
| 157 | |
| 158 def has_xmpp_token(self): | |
| 159 # XMPP connection can be authenticated using either OAuth or XMPP token. | |
| 160 return self.oauth_refresh_token != None or self.xmpp_auth_token != None | |
| 161 | |
| 153 def load_config(self, config): | 162 def load_config(self, config): |
| 163 # Only some of the auth tokens may be present in the config. We still | |
| 164 # consider config to be valid in this case. | |
|
Jamie
2012/08/13 23:44:31
I'm not a Python expert--I take it .get doesn't th
Lambros
2012/08/14 01:07:44
That is correct, get(key) returns None if the key
Sergey Ulanov
2012/08/14 18:00:37
Done.
| |
| 165 self.chromoting_auth_token = config.get("chromoting_auth_token") | |
| 166 self.oauth_refresh_token = config.get("oauth_refresh_token") | |
| 167 self.xmpp_auth_token = config.get("xmpp_auth_token") | |
| 168 | |
| 154 try: | 169 try: |
| 155 self.login = config["xmpp_login"] | 170 self.login = config["xmpp_login"] |
| 156 self.chromoting_auth_token = config["chromoting_auth_token"] | |
| 157 self.xmpp_auth_token = config["xmpp_auth_token"] | |
| 158 except KeyError: | 171 except KeyError: |
| 159 return False | 172 return False |
| 160 return True | 173 return True |
| 161 | 174 |
| 162 def save_config(self, config): | 175 def save_config(self, config): |
| 163 config["xmpp_login"] = self.login | 176 config["xmpp_login"] = self.login |
| 164 config["chromoting_auth_token"] = self.chromoting_auth_token | 177 config["chromoting_auth_token"] = self.chromoting_auth_token |
| 165 config["xmpp_auth_token"] = self.xmpp_auth_token | 178 config["xmpp_auth_token"] = self.xmpp_auth_token |
| 166 | 179 |
| 167 class Host: | 180 class Host: |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 654 help="stop the daemon currently running") | 667 help="stop the daemon currently running") |
| 655 parser.add_option("-p", "--new-pin", dest="new_pin", default=False, | 668 parser.add_option("-p", "--new-pin", dest="new_pin", default=False, |
| 656 action="store_true", | 669 action="store_true", |
| 657 help="set new PIN before starting the host") | 670 help="set new PIN before starting the host") |
| 658 parser.add_option("", "--check-running", dest="check_running", default=False, | 671 parser.add_option("", "--check-running", dest="check_running", default=False, |
| 659 action="store_true", | 672 action="store_true", |
| 660 help="return 0 if the daemon is running, or 1 otherwise") | 673 help="return 0 if the daemon is running, or 1 otherwise") |
| 661 parser.add_option("", "--silent", dest="silent", default=False, | 674 parser.add_option("", "--silent", dest="silent", default=False, |
| 662 action="store_true", | 675 action="store_true", |
| 663 help="Start the host without trying to configure it.") | 676 help="Start the host without trying to configure it.") |
| 677 parser.add_option("", "--reload", dest="reload", default=False, | |
| 678 action="store_true", help="Reload the config.") | |
|
Lambros
2012/08/14 01:07:44
Clarify: "Reload the config of the currently-runni
| |
| 664 (options, args) = parser.parse_args() | 679 (options, args) = parser.parse_args() |
| 665 | 680 |
| 666 host_hash = hashlib.md5(socket.gethostname()).hexdigest() | 681 host_hash = hashlib.md5(socket.gethostname()).hexdigest() |
| 667 pid_filename = os.path.join(CONFIG_DIR, "host#%s.pid" % host_hash) | 682 pid_filename = os.path.join(CONFIG_DIR, "host#%s.pid" % host_hash) |
| 668 | 683 |
| 669 if options.check_running: | 684 if options.check_running: |
| 670 running, pid = PidFile(pid_filename).check() | 685 running, pid = PidFile(pid_filename).check() |
| 671 return 0 if (running and pid != 0) else 1 | 686 return 0 if (running and pid != 0) else 1 |
| 672 | 687 |
| 673 if options.stop: | 688 if options.stop: |
| 674 running, pid = PidFile(pid_filename).check() | 689 running, pid = PidFile(pid_filename).check() |
| 675 if not running: | 690 if not running: |
| 676 print "The daemon currently is not running" | 691 print "The daemon currently is not running" |
| 677 else: | 692 else: |
| 678 print "Killing process %s" % pid | 693 print "Killing process %s" % pid |
| 679 os.kill(pid, signal.SIGTERM) | 694 os.kill(pid, signal.SIGTERM) |
| 680 return 0 | 695 return 0 |
| 681 | 696 |
| 697 if options.reload: | |
| 698 running, pid = PidFile(pid_filename).check() | |
| 699 if not running: | |
| 700 return 1 | |
| 701 os.kill(pid, signal.SIGUSR1) | |
| 702 return 0 | |
| 703 | |
| 682 if not options.size: | 704 if not options.size: |
| 683 options.size = [DEFAULT_SIZE] | 705 options.size = [DEFAULT_SIZE] |
| 684 | 706 |
| 685 sizes = [] | 707 sizes = [] |
| 686 for size in options.size: | 708 for size in options.size: |
| 687 size_components = size.split("x") | 709 size_components = size.split("x") |
| 688 if len(size_components) != 2: | 710 if len(size_components) != 2: |
| 689 parser.error("Incorrect size format '%s', should be WIDTHxHEIGHT" % size) | 711 parser.error("Incorrect size format '%s', should be WIDTHxHEIGHT" % size) |
| 690 | 712 |
| 691 try: | 713 try: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 # If we were able to read auth.json then copy its content to the host | 758 # If we were able to read auth.json then copy its content to the host |
| 737 # config. | 759 # config. |
| 738 if auth_config_loaded: | 760 if auth_config_loaded: |
| 739 auth.save_config(host_config) | 761 auth.save_config(host_config) |
| 740 host_config.save() | 762 host_config.save() |
| 741 | 763 |
| 742 host = Host(auth) | 764 host = Host(auth) |
| 743 host_config_loaded = host.load_config(host_config) | 765 host_config_loaded = host.load_config(host_config) |
| 744 | 766 |
| 745 if options.silent: | 767 if options.silent: |
| 768 # Just validate the config when run with --silent. | |
| 746 if not host_config_loaded or not auth_config_loaded: | 769 if not host_config_loaded or not auth_config_loaded: |
| 747 logging.error("Failed to load host configuration.") | 770 logging.error("Failed to load host configuration.") |
| 748 return 1 | 771 return 1 |
| 772 if not auth.has_xmpp_token(): | |
| 773 logging.error("Auth tokens are not configured.") | |
|
Jamie
2012/08/13 23:44:31
In a previous comment, you state that we can use e
Lambros
2012/08/14 01:07:44
+1 It's not clear to me what's going on here. The
Sergey Ulanov
2012/08/14 18:00:37
The host needs tokens to authenticate XMPP connect
Sergey Ulanov
2012/08/14 18:00:37
has_xmpp_token() returns true if we have any types
| |
| 774 return 1 | |
| 749 else: | 775 else: |
| 750 need_auth_tokens = not auth_config_loaded | 776 need_auth_tokens = not auth_config_loaded or not auth.has_chromoting_token() |
| 751 need_register_host = not host_config_loaded | 777 need_register_host = not host_config_loaded |
| 752 # Outside the loop so user doesn't get asked twice. | 778 # Outside the loop so user doesn't get asked twice. |
| 753 if need_register_host: | 779 if need_register_host: |
| 754 host.ask_pin() | 780 host.ask_pin() |
| 755 elif options.new_pin or not host.is_pin_set(): | 781 elif options.new_pin or not host.is_pin_set(): |
| 756 host.ask_pin() | 782 host.ask_pin() |
| 757 host.save_config(host_config) | 783 host.save_config(host_config) |
| 758 running, pid = PidFile(pid_filename).check() | 784 running, pid = PidFile(pid_filename).check() |
| 759 if running and pid != 0: | 785 if running and pid != 0: |
| 760 os.kill(pid, signal.SIGUSR1) | 786 os.kill(pid, signal.SIGUSR1) |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 host_config.save() | 939 host_config.save() |
| 914 return 0 | 940 return 0 |
| 915 elif os.WEXITSTATUS(status) == 5: | 941 elif os.WEXITSTATUS(status) == 5: |
| 916 logging.info("Host domain is blocked by policy - exiting.") | 942 logging.info("Host domain is blocked by policy - exiting.") |
| 917 os.remove(host.config_file) | 943 os.remove(host.config_file) |
| 918 return 0 | 944 return 0 |
| 919 | 945 |
| 920 if __name__ == "__main__": | 946 if __name__ == "__main__": |
| 921 logging.basicConfig(level=logging.DEBUG) | 947 logging.basicConfig(level=logging.DEBUG) |
| 922 sys.exit(main()) | 948 sys.exit(main()) |
| OLD | NEW |