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 |