1/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 * 3 * Copyright (C) 2011,2012 Canonical Ltd 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 3 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * Authors: Robert Ancell <robert.ancell@canonical.com> 18 * Michael Terry <michael.terry@canonical.com> 19 */ 20 21int remote_server_field_sort_function (RemoteServerField? item1, RemoteServerField? item2) 22{ 23 string[] sorted_fields = { "domain", "username", "email", "password" }; 24 foreach (var field in sorted_fields) 25 { 26 if (item1.type == field) 27 return -1; 28 if (item2.type == field) 29 return 1; 30 } 31 32 return (item1.type < item2.type) ? -1 : 0; 33} 34 35public class UserList : GreeterList 36{ 37 private bool _offer_guest = false; 38 public bool offer_guest 39 { 40 get { return _offer_guest; } 41 set 42 { 43 _offer_guest = value; 44 if (value) 45 add_user ("*guest", _("Guest Session")); 46 else 47 remove_entry ("*guest"); 48 } 49 } 50 51 private Gdk.Pixbuf message_pixbuf; 52 53 private uint change_background_timeout = 0; 54 55 private uint remote_login_service_watch; 56 private RemoteLoginService remote_login_service; 57 private List<RemoteServer?> remote_directory_server_list = new List<RemoteServer?> (); 58 private List<RemoteServer?> remote_login_server_list = new List<RemoteServer?> (); 59 private HashTable<string, Gtk.Widget> current_remote_fields; 60 private string currently_browsing_server_url; 61 private string currently_browsing_server_email; 62 private EmailAutocompleter remote_server_email_field_autocompleter; 63 64 /* User to authenticate against */ 65 private string ?authenticate_user = null; 66 67 private bool show_hidden_users_ = false; 68 public bool show_hidden_users 69 { 70 set 71 { 72 show_hidden_users_ = value; 73 74 if (SlickGreeter.singleton.test_mode) 75 { 76 if (value) 77 add_user ("hidden", "Hidden User", null, false, false, null); 78 else 79 remove_entry ("hidden"); 80 return; 81 } 82 83 var hidden_users = UGSettings.get_strv (UGSettings.KEY_HIDDEN_USERS); 84 if (!value) 85 { 86 foreach (var username in hidden_users) 87 remove_entry (username); 88 return; 89 } 90 91 var users = LightDM.UserList.get_instance (); 92 foreach (var user in users.users) 93 { 94 foreach (var username in hidden_users) 95 { 96 if (user.name == username) 97 { 98 debug ("Showing hidden user %s", username); 99 user_added_cb (user); 100 } 101 } 102 } 103 } 104 105 get 106 { 107 return show_hidden_users_; 108 } 109 } 110 111 private string _default_session = "gnome"; 112 public string default_session 113 { 114 get 115 { 116 return _default_session; 117 } 118 set 119 { 120 _default_session = value; 121 if (selected_entry != null) 122 selected_entry.set_options_image (get_badge ()); 123 } 124 } 125 126 private string? _session = null; 127 public string? session 128 { 129 get 130 { 131 return _session; 132 } 133 set 134 { 135 _session = value; 136 if (selected_entry != null) 137 selected_entry.set_options_image (get_badge ()); 138 } 139 } 140 141 public UserList (Background bg, MenuBar mb) 142 { 143 Object (background: bg, menubar: mb); 144 } 145 146 construct 147 { 148 menubar.notify["high-contrast"].connect (() => { change_background (); }); 149 entry_displayed_start.connect (() => { change_background (); }); 150 entry_displayed_done.connect (() => { change_background (); }); 151 152 try 153 { 154 message_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "message.png", null)); 155 } 156 catch (Error e) 157 { 158 debug ("Error loading message image: %s", e.message); 159 } 160 161 fill_list (); 162 163 entry_selected.connect (entry_selected_cb); 164 165 connect_to_lightdm (); 166 167 if (!SlickGreeter.singleton.test_mode && 168 SlickGreeter.singleton.show_remote_login_hint ()) 169 remote_login_service_watch = Bus.watch_name (BusType.SESSION, 170 "com.canonical.RemoteLogin", 171 BusNameWatcherFlags.AUTO_START, 172 on_remote_login_service_appeared, 173 on_remote_login_service_vanished); 174 175 } 176 177 private void remove_remote_servers () 178 { 179 remote_directory_server_list = new List<RemoteServer?> (); 180 remote_login_server_list = new List<RemoteServer?> (); 181 remove_entries_with_prefix ("*remote"); 182 } 183 184 private void remove_remote_login_servers () 185 { 186 remote_login_server_list = new List<RemoteServer?> (); 187 remove_entries_with_prefix ("*remote_login"); 188 189 /* If we have no entries at all, we should show manual */ 190 if (!always_show_manual) 191 add_manual_entry (); 192 } 193 194 private async void query_directory_servers () 195 { 196 try 197 { 198 RemoteServer[] server_list; 199 yield remote_login_service.get_servers (out server_list); 200 set_remote_directory_servers (server_list); 201 } 202 catch (Error e) 203 { 204 debug ("Calling GetServers on com.canonical.RemoteLogin dbus service failed. Error: %s", e.message); 205 remove_remote_servers (); 206 } 207 } 208 209 private string user_list_name_for_remote_directory_server (RemoteServer remote_server) 210 { 211 return "*remote_directory*" + remote_server.url; 212 } 213 214 private string username_from_remote_server_fields(RemoteServer remote_server) 215 { 216 var username = ""; 217 foreach (var f in remote_server.fields) 218 { 219 if (f.type == "username" && f.default_value != null) 220 { 221 username = f.default_value.get_string (); 222 break; 223 } 224 } 225 return username; 226 } 227 228 private string user_list_name_for_remote_login_server (RemoteServer remote_server) 229 { 230 var username = username_from_remote_server_fields (remote_server); 231 return "*remote_login*" + remote_server.url + "*" + username; 232 } 233 234 private string url_from_remote_loding_server_list_name (string remote_server_list_name) 235 { 236 return remote_server_list_name.split ("*")[2]; 237 } 238 239 private string username_from_remote_loding_server_list_name (string remote_server_list_name) 240 { 241 return remote_server_list_name.split ("*")[3]; 242 } 243 244 private void set_remote_directory_servers (RemoteServer[] server_list) 245 { 246 /* Add new servers */ 247 foreach (var remote_server in server_list) 248 { 249 var list_name = user_list_name_for_remote_directory_server (remote_server); 250 if (find_entry (list_name) == null) 251 { 252 var e = new PromptBox (list_name); 253 e.label = remote_server.name; 254 e.respond.connect (remote_directory_respond_cb); 255 e.show_options.connect (show_remote_account_dialog); 256 add_entry (e); 257 258 remote_directory_server_list.append (remote_server); 259 } 260 } 261 262 /* Remove gone servers */ 263 unowned List<RemoteServer?> it = remote_directory_server_list; 264 while (it != null) 265 { 266 var remote_server = it.data; 267 var found = false; 268 for (int i = 0; !found && i < server_list.length; i++) 269 { 270 found = remote_server.url == server_list[i].url; 271 } 272 if (!found) 273 { 274 if (remote_server.url == currently_browsing_server_url) 275 { 276 /* The server we where "browsing" disappeared, so kill its children */ 277 remove_remote_login_servers (); 278 currently_browsing_server_url = ""; 279 currently_browsing_server_email = ""; 280 } 281 remove_entry (user_list_name_for_remote_directory_server (remote_server)); 282 unowned List<RemoteServer?> newIt = it.next; 283 remote_directory_server_list.delete_link (it); 284 it = newIt; 285 } 286 else 287 { 288 it = it.next; 289 } 290 } 291 292 /* Remove manual option unless specified */ 293 if (remote_directory_server_list.length() > 0 && !always_show_manual) { 294 debug ("removing manual login since we have a remote login entry"); 295 remove_entry ("*other"); 296 } 297 } 298 299 private PromptBox create_prompt_for_login_server (RemoteServer remote_server) 300 { 301 var e = new PromptBox (user_list_name_for_remote_login_server (remote_server)); 302 e.label = remote_server.name; 303 e.respond.connect (remote_login_respond_cb); 304 add_entry (e); 305 remote_login_server_list.append (remote_server); 306 307 return e; 308 } 309 310 private void remote_login_servers_updated (string url, string email_address, string data_type, RemoteServer[] server_list) 311 { 312 if (currently_browsing_server_url == url && currently_browsing_server_email == email_address) 313 { 314 /* Add new servers */ 315 foreach (var remote_server in server_list) 316 { 317 var list_name = user_list_name_for_remote_login_server (remote_server); 318 if (find_entry (list_name) == null) 319 create_prompt_for_login_server (remote_server); 320 } 321 322 /* Remove gone servers */ 323 unowned List<RemoteServer?> it = remote_login_server_list; 324 while (it != null) 325 { 326 RemoteServer remote_server = it.data; 327 var found = false; 328 for (var i = 0; !found && i < server_list.length; i++) 329 found = remote_server.url == server_list[i].url; 330 if (!found) 331 { 332 remove_entry (user_list_name_for_remote_login_server (remote_server)); 333 unowned List<RemoteServer?> newIt = it.next; 334 remote_login_server_list.delete_link (it); 335 it = newIt; 336 } 337 else 338 { 339 it = it.next; 340 } 341 } 342 } 343 } 344 345 private void remote_login_changed (string url, string email_address) 346 { 347 if (currently_browsing_server_url == url && currently_browsing_server_email == email_address) 348 { 349 /* Something happened and we are being asked for re-authentication by the remote-login-service */ 350 remove_remote_login_servers (); 351 currently_browsing_server_url = ""; 352 currently_browsing_server_email = ""; 353 354 var directory_list_name = "*remote_directory*" + url; 355 set_active_entry (directory_list_name); 356 } 357 } 358 359 private void on_remote_login_service_appeared (DBusConnection conn, string name) 360 { 361 Bus.get_proxy.begin<RemoteLoginService> (BusType.SESSION, 362 "com.canonical.RemoteLogin", 363 "/com/canonical/RemoteLogin", 364 0, 365 null, 366 (obj, res) => { 367 try 368 { 369 remote_login_service = Bus.get_proxy.end<RemoteLoginService> (res); 370 remote_login_service.servers_updated.connect (set_remote_directory_servers); 371 remote_login_service.login_servers_updated.connect (remote_login_servers_updated); 372 remote_login_service.login_changed.connect (remote_login_changed); 373 query_directory_servers.begin (); 374 } 375 catch (IOError e) 376 { 377 debug ("Getting the com.canonical.RemoteLogin dbus service failed. Error: %s", e.message); 378 remove_remote_servers (); 379 remote_login_service = null; 380 } 381 } 382 ); 383 } 384 385 private void on_remote_login_service_vanished (DBusConnection conn, string name) 386 { 387 remove_remote_servers (); 388 remote_login_service = null; 389 390 /* provide a fallback manual login option */ 391 if (SlickGreeter.singleton.hide_users_hint ()) { 392 add_manual_entry(); 393 set_active_entry ("*other"); 394 } 395 } 396 397 private async void remote_directory_respond_cb () 398 { 399 remove_remote_login_servers (); 400 currently_browsing_server_url = ""; 401 currently_browsing_server_email = ""; 402 403 var password_field = current_remote_fields.get ("password") as DashEntry; 404 var email_field = current_remote_fields.get ("email") as Gtk.Entry; 405 if (password_field == null) 406 { 407 debug ("Something wrong happened in remote_directory_respond_cb. There was no password field"); 408 return; 409 } 410 if (email_field == null) 411 { 412 debug ("Something wrong happened in remote_directory_respond_cb. There was no email field"); 413 return; 414 } 415 416 RemoteServer[] server_list = {}; 417 var email = email_field.text; 418 var email_valid = false; 419 try 420 { 421 /* Check email address is valid 422 * Using the html5 definition of a valid e-mail address 423 * http://www.w3.org/TR/html5/states-of-the-type-attribute.html#valid-e-mail-address */ 424 var re = new Regex ("[a-zA-Z0-9.!#$%&'\\*\\+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*"); 425 MatchInfo info; 426 email_valid = re.match_all (email, 0, out info); 427 email_valid = email_valid && info.get_match_count () > 0 && info.fetch (0) == email; 428 } 429 catch (RegexError e) 430 { 431 debug ("Calling email regex match failed. Error: %s", e.message); 432 } 433 434 selected_entry.reset_messages (); 435 if (!email_valid) 436 { 437 will_clear = true; 438 show_message (_("Please enter a complete e-mail address"), true); 439 create_remote_fields_for_current_item.begin (remote_directory_server_list); 440 } 441 else 442 { 443 var login_success = false; 444 try 445 { 446 var url = url_from_remote_loding_server_list_name (selected_entry.id); 447 if (SlickGreeter.singleton.test_mode) 448 { 449 if (password_field.text == "password") 450 { 451 test_fill_remote_login_servers (out server_list); 452 login_success = true; 453 } 454 else if (password_field.text == "delay1") 455 { 456 test_fill_remote_login_servers (out server_list); 457 login_success = true; 458 Timeout.add (5000, () => { test_call_set_remote_directory_servers (); return false; }); 459 } 460 else if (password_field.text == "delay2") 461 { 462 test_fill_remote_login_servers (out server_list); 463 login_success = true; 464 Timeout.add (5000, () => { test_call_remote_login_servers_updated (); return false; }); 465 } 466 else if (password_field.text == "delay3") 467 { 468 test_fill_remote_login_servers (out server_list); 469 login_success = true; 470 Timeout.add (5000, () => { remote_login_changed (currently_browsing_server_url, currently_browsing_server_email); return false; }); 471 } 472 else if (password_field.text == "duplicate") 473 { 474 test_fill_remote_login_servers_duplicate_entries (out server_list); 475 login_success = true; 476 } 477 } 478 else 479 { 480 string data_type; 481 bool allowcache = true; 482 // If we had an error and are retrying the same user and server, do not use the cache on R-L-S 483 if (selected_entry.has_errors && currently_browsing_server_email == email && currently_browsing_server_url == url) 484 allowcache = false; 485 yield remote_login_service.get_servers_for_login (url, email, password_field.text, allowcache, out login_success, out data_type, out server_list); 486 } 487 currently_browsing_server_url = url; 488 currently_browsing_server_email = email; 489 } 490 catch (Error e) 491 { 492 debug ("Calling get_servers in com.canonical.RemoteLogin dbus service failed. Error: %s", e.message); 493 } 494 495 if (login_success) 496 { 497 password_field.did_respond = false; 498 if (server_list.length == 0) 499 show_remote_account_dialog (); 500 else 501 { 502 var last_used_server_list_name = ""; 503 foreach (var remote_server in server_list) 504 { 505 var e = create_prompt_for_login_server (remote_server); 506 if (remote_server.last_used_server) 507 last_used_server_list_name = e.id; 508 } 509 if (last_used_server_list_name != "") 510 set_active_entry (last_used_server_list_name); 511 else 512 set_active_first_entry_with_prefix ("*remote_login"); 513 } 514 } 515 else 516 { 517 will_clear = true; 518 show_message (_("Incorrect e-mail address or password"), true); 519 create_remote_fields_for_current_item.begin (remote_directory_server_list); 520 } 521 } 522 } 523 524 private void remote_login_respond_cb () 525 { 526 sensitive = false; 527 will_clear = true; 528 greeter_authenticating_user = selected_entry.id; 529 if (SlickGreeter.singleton.test_mode) 530 { 531 Gtk.Entry field = current_remote_fields.get ("password") as Gtk.Entry; 532 test_is_authenticated = field.text == "password"; 533 if (field.text == "delay") 534 Timeout.add (5000, () => { authentication_complete_cb (); return false; }); 535 else 536 authentication_complete_cb (); 537 } 538 else 539 { 540 SlickGreeter.singleton.authenticate_remote (get_lightdm_session (), null); 541 remote_login_service.set_last_used_server.begin (currently_browsing_server_url, url_from_remote_loding_server_list_name (selected_entry.id)); 542 } 543 } 544 545 private void show_remote_account_dialog () 546 { 547 var dialog = new Gtk.MessageDialog (null, 0, Gtk.MessageType.OTHER, Gtk.ButtonsType.NONE, ""); 548 dialog.set_position (Gtk.WindowPosition.CENTER_ALWAYS); 549 dialog.secondary_text = _("If you have an account on an RDP or Citrix server, Remote Login lets you run applications from that server."); 550 // For 12.10 we still don't support Citrix 551 dialog.secondary_text = _("If you have an account on an RDP server, Remote Login lets you run applications from that server."); 552 if (offer_guest) 553 { 554 dialog.add_button (_("Cancel"), 0); 555 var b = dialog.add_button (_("Set Up..."), 1); 556 b.grab_focus (); 557 dialog.text = _("You need an Ubuntu Remote Login account to use this service. Would you like to set up an account now?"); 558 } 559 else 560 { 561 dialog.add_button (_("OK"), 0); 562 dialog.text = _("You need an Ubuntu Remote Login account to use this service. Visit uccs.canonical.com to set up an account."); 563 } 564 565 dialog.show_all (); 566 dialog.response.connect ((id) => 567 { 568 if (id == 1) 569 { 570 var config_session = "uccsconfigure"; 571 if (is_supported_remote_session (config_session)) 572 { 573 greeter_authenticating_user = selected_entry.id; 574 SlickGreeter.singleton.authenticate_remote (config_session, null); 575 } 576 } 577 dialog.destroy (); 578 }); 579 dialog.run (); 580 } 581 582 private bool change_background_timeout_cb () 583 { 584 string? new_background_file = null; 585 if (menubar.high_contrast || !UGSettings.get_boolean (UGSettings.KEY_DRAW_USER_BACKGROUNDS)) 586 new_background_file = null; 587 else if (selected_entry is UserPromptBox) 588 new_background_file = (selected_entry as UserPromptBox).background; 589 590 background.current_background = new_background_file; 591 592 change_background_timeout = 0; 593 return false; 594 } 595 596 private void change_background () 597 { 598 if (background.current_background != null) 599 { 600 if (change_background_timeout == 0) 601 change_background_timeout = Idle.add (change_background_timeout_cb); 602 } 603 else 604 { 605 change_background_timeout_cb (); 606 } 607 } 608 609 protected static int user_list_compare_entry (PromptBox a, PromptBox b) 610 { 611 if (a.id.has_prefix ("*remote_directory") && !b.id.has_prefix ("*remote_directory")) 612 return 1; 613 if (a.id.has_prefix ("*remote_login") && !b.id.has_prefix ("*remote_login")) 614 return 1; 615 616 /* Fall back to default behaviour of the GreeterList sorter */ 617 return GreeterList.compare_entry (a, b); 618 } 619 620 protected override void insert_entry (PromptBox entry) 621 { 622 entries.insert_sorted (entry, user_list_compare_entry); 623 } 624 625 protected override void setup_prompt_box (bool fade = true) 626 { 627 base.setup_prompt_box (fade); 628 var userbox = selected_entry as UserPromptBox; 629 if (userbox != null) 630 selected_entry.set_is_active (userbox.is_active); 631 } 632 633 private void entry_selected_cb (string? username) 634 { 635 SlickGreeter.singleton.set_state ("last-user", username); 636 if (selected_entry is UserPromptBox) 637 session = (selected_entry as UserPromptBox).session; 638 else 639 session = null; 640 selected_entry.clear (); 641 642 /* Reset this variable so it can be freed */ 643 remote_server_email_field_autocompleter = null; 644 645 start_authentication (); 646 } 647 648 protected override void start_authentication () 649 { 650 sensitive = true; 651 greeter_authenticating_user = ""; 652 if (selected_entry.id.has_prefix ("*remote_directory")) 653 { 654 prompted = true; 655 create_remote_fields_for_current_item.begin (remote_directory_server_list); 656 } 657 else if (selected_entry.id.has_prefix ("*remote_login")) 658 { 659 prompted = true; 660 create_remote_fields_for_current_item.begin (remote_login_server_list); 661 } 662 else 663 base.start_authentication (); 664 } 665 666 private async void create_remote_fields_for_current_item (List<RemoteServer?> server_list) 667 { 668 current_remote_fields = new HashTable<string, Gtk.Widget> (str_hash, str_equal); 669 var url = url_from_remote_loding_server_list_name (selected_entry.id); 670 var username = username_from_remote_loding_server_list_name (selected_entry.id); 671 672 foreach (var remote_server in server_list) 673 { 674 var remote_username = username_from_remote_server_fields (remote_server); 675 if (remote_server.url == url && (username == null || username == remote_username)) 676 { 677 if (selected_entry.id.has_prefix ("*remote_login")) 678 { 679 if (!is_supported_remote_session (remote_server.type)) 680 { 681 show_message (_("Server type not supported."), true); 682 } 683 } 684 685 var fields = new List<RemoteServerField?> (); 686 foreach (var field in remote_server.fields) 687 fields.append (field); 688 fields.sort (remote_server_field_sort_function); 689 foreach (var field in fields) 690 { 691 Gtk.Widget? widget = null; 692 var default_value = ""; 693 if (field.default_value != null && field.default_value.is_of_type (VariantType.STRING)) 694 default_value = field.default_value.get_string (); 695 if (field.type == "username") 696 { 697 var entry = add_prompt (_("Username:")); 698 entry.text = default_value; 699 widget = entry; 700 } 701 else if (field.type == "password") 702 { 703 var entry = add_prompt (_("Password:"), true); 704 entry.text = default_value; 705 widget = entry; 706 } 707 else if (field.type == "domain") 708 { 709 string[] domainsArray = {}; 710 if (field.properties != null && field.properties.contains ("domains") && field.properties.get ("domains").is_of_type (VariantType.ARRAY)) 711 domainsArray = field.properties.get ("domains").dup_strv (); 712 var domains = new GenericArray<string> (); 713 for (var i = 0; i < domainsArray.length; i++) 714 domains.add (domainsArray[i]); 715 716 var read_only = field.properties != null && 717 field.properties.contains ("read-only") && 718 field.properties.get ("read-only").is_of_type (VariantType.BOOLEAN) && 719 field.properties.get ("read-only").get_boolean (); 720 if (domains.length == 0 || (domains.length == 1 && (domains[0] == default_value || default_value.length == 0))) 721 { 722 var prompt = add_prompt (_("Domain:")); 723 prompt.text = domains.length == 1 ? domains[0] : default_value; 724 prompt.sensitive = !read_only; 725 widget = prompt; 726 } 727 else 728 { 729 if (default_value.length > 0) 730 { 731 /* Make sure the domain list contains the default value */ 732 var found = false; 733 for (var i = 0; !found && i < domains.length; i++) 734 found = default_value == domains[i]; 735 736 if (!found) 737 domains.add (default_value); 738 } 739 740 /* Sort domains alphabetically */ 741 domains.sort (strcmp); 742 var combo = add_combo (domains, read_only); 743 744 if (default_value.length > 0) 745 { 746 if (read_only) 747 { 748 for (var i = 0; i < domains.length; i++) 749 { 750 if (default_value == domains[i]) 751 { 752 combo.active = i; 753 break; 754 } 755 } 756 } 757 else 758 { 759 var entry = combo.get_child () as Gtk.Entry; 760 entry.text = default_value; 761 } 762 } 763 764 widget = combo; 765 } 766 } 767 else if (field.type == "email") 768 { 769 string[] email_domains; 770 try 771 { 772 if (SlickGreeter.singleton.test_mode) 773 email_domains = { "canonical.com", "ubuntu.org", "candy.com", "urban.net" }; 774 else 775 yield remote_login_service.get_cached_domains_for_server (url, out email_domains); 776 } 777 catch (Error e) 778 { 779 email_domains.resize (0); 780 debug ("Calling get_cached_domains_for_server in com.canonical.RemoteLogin dbus service failed. Error: %s", e.message); 781 } 782 783 var entry = add_prompt (_("Email address:")); 784 entry.text = default_value; 785 widget = entry; 786 if (email_domains.length > 0) 787 remote_server_email_field_autocompleter = new EmailAutocompleter (entry, email_domains); 788 } 789 else 790 { 791 debug ("Found field of type %s, don't know what to do with it", field.type); 792 continue; 793 } 794 current_remote_fields.insert (field.type, widget); 795 } 796 break; 797 } 798 } 799 } 800 801 public override void focus_prompt () 802 { 803 if (selected_entry.id.has_prefix ("*remote_login")) 804 { 805 var url = url_from_remote_loding_server_list_name(selected_entry.id); 806 foreach (var remote_server in remote_login_server_list) 807 { 808 if (remote_server.url == url) 809 { 810 if (!is_supported_remote_session (remote_server.type)) 811 { 812 selected_entry.sensitive = false; 813 return; 814 } 815 } 816 } 817 } 818 819 base.focus_prompt (); 820 } 821 822 public override void show_authenticated (bool successful = true) 823 { 824 if (successful) 825 { 826 /* 'Log In' here is the button for logging in. */ 827 selected_entry.add_button (_("Log In"), 828 _("Login as %s").printf (selected_entry.label)); 829 } 830 else 831 { 832 selected_entry.add_button (_("Retry"), 833 _("Retry as %s").printf (selected_entry.label)); 834 } 835 836 if (mode != Mode.SCROLLING) 837 selected_entry.show_prompts (); 838 839 focus_prompt (); 840 redraw_greeter_box (); 841 } 842 843 public void add_user (string name, string label, string? background = null, bool is_active = false, bool has_messages = false, string? session = null) 844 { 845 var e = find_entry (name) as UserPromptBox; 846 if (e == null) 847 { 848 e = new UserPromptBox (name); 849 e.respond.connect (prompt_box_respond_cb); 850 e.login.connect (prompt_box_login_cb); 851 e.show_options.connect (prompt_box_show_options_cb); 852 e.label = label; /* Do this before adding for sorting purposes */ 853 add_entry (e); 854 } 855 e.background = background; 856 e.is_active = is_active; 857 if ( session == null) 858 { 859 session = default_session; 860 } 861 e.session = SlickGreeter.validate_session (session); 862 e.label = label; 863 e.set_show_message_icon (has_messages); 864 e.set_is_active (is_active); 865 866 /* Remove manual option when have users */ 867 if (have_entries () && !always_show_manual) 868 remove_entry ("*other"); 869 } 870 871 protected override void add_manual_entry () 872 { 873 var text = manual_name; 874 if (text == null) 875 text = _("Login"); 876 add_user ("*other", text); 877 } 878 879 protected void prompt_box_respond_cb (string[] responses) 880 { 881 selected_entry.sensitive = false; 882 will_clear = true; 883 unacknowledged_messages = false; 884 885 foreach (var response in responses) 886 { 887 if (SlickGreeter.singleton.test_mode) 888 test_respond (response); 889 else 890 SlickGreeter.singleton.respond (response); 891 } 892 } 893 894 private void prompt_box_login_cb () 895 { 896 debug ("Start session for %s", selected_entry.id); 897 898 unacknowledged_messages = false; 899 var is_authenticated = false; 900 if (SlickGreeter.singleton.test_mode) 901 is_authenticated = test_is_authenticated; 902 else 903 is_authenticated = SlickGreeter.singleton.is_authenticated(); 904 905 /* Finish authentication (again) or restart it */ 906 if (is_authenticated) 907 authentication_complete_cb (); 908 else 909 { 910 selected_entry.clear (); 911 start_authentication (); 912 } 913 } 914 915 private void prompt_box_show_options_cb () 916 { 917 var session_chooser = new SessionList (background, menubar, session, default_session); 918 session_chooser.session_clicked.connect (session_clicked_cb); 919 SlickGreeter.singleton.push_list (session_chooser); 920 } 921 922 private void session_clicked_cb (string session) 923 { 924 this.session = session; 925 SlickGreeter.singleton.pop_list (); 926 } 927 928 private bool should_show_session_badge () 929 { 930 if (SlickGreeter.singleton.test_mode) 931 return get_selected_id () != "no-badge"; 932 else 933 return LightDM.get_sessions ().length () > 1; 934 } 935 936 private Gdk.Pixbuf? get_badge () 937 { 938 if (selected_entry is UserPromptBox) 939 { 940 if (!should_show_session_badge ()) 941 return null; 942 else if (session == null) 943 return SessionList.get_badge (default_session); 944 else 945 return SessionList.get_badge (session); 946 } 947 else 948 { 949 if (selected_entry.id.has_prefix ("*remote_directory")) 950 return SessionList.get_badge ("remote-login"); 951 else 952 return null; 953 } 954 } 955 956 private bool is_supported_remote_session (string session_internal_name) 957 { 958 if (SlickGreeter.singleton.test_mode) 959 return session_internal_name == "rdp"; 960 961 var found = false; 962 foreach (var session in LightDM.get_remote_sessions ()) 963 { 964 if (session.key == session_internal_name) 965 { 966 found = true; 967 break; 968 } 969 } 970 return found; 971 } 972 973 protected override string get_lightdm_session () 974 { 975 if (selected_entry.id.has_prefix ("*remote_login")) 976 { 977 var url = url_from_remote_loding_server_list_name (selected_entry.id); 978 unowned List<RemoteServer?> it = remote_login_server_list; 979 980 var answer = ""; 981 while (answer == "" && it != null) 982 { 983 RemoteServer remote_server = it.data; 984 if (remote_server.url == url) 985 answer = remote_server.type; 986 it = it.next; 987 } 988 989 if (is_supported_remote_session (answer)) 990 return answer; 991 else 992 return ""; 993 } 994 else 995 return session; 996 } 997 998 private void fill_list () 999 { 1000 if (SlickGreeter.singleton.test_mode) 1001 test_fill_list (); 1002 else 1003 { 1004 default_session = SlickGreeter.singleton.default_session_hint (); 1005 always_show_manual = SlickGreeter.singleton.show_manual_login_hint (); 1006 if (!SlickGreeter.singleton.hide_users_hint ()) 1007 { 1008 var users = LightDM.UserList.get_instance (); 1009 users.user_added.connect (user_added_cb); 1010 users.user_changed.connect (user_added_cb); 1011 users.user_removed.connect (user_removed_cb); 1012 foreach (var user in users.users) 1013 user_added_cb (user); 1014 } 1015 1016 if (SlickGreeter.singleton.has_guest_account_hint ()) 1017 { 1018 debug ("Adding guest account entry"); 1019 offer_guest = true; 1020 } 1021 1022 /* If we have no entries at all, we should show manual */ 1023 if (!have_entries ()) 1024 add_manual_entry (); 1025 1026 var last_user = SlickGreeter.singleton.get_state ("last-user"); 1027 if (SlickGreeter.singleton.select_user_hint () != null) 1028 set_active_entry (SlickGreeter.singleton.select_user_hint ()); 1029 else if (last_user != null) 1030 set_active_entry (last_user); 1031 } 1032 } 1033 1034 private void user_added_cb (LightDM.User user) 1035 { 1036 debug ("Adding/updating user %s (%s)", user.name, user.real_name); 1037 1038 if (!show_hidden_users) 1039 { 1040 var hidden_users = UGSettings.get_strv (UGSettings.KEY_HIDDEN_USERS); 1041 foreach (var username in hidden_users) 1042 if (username == user.name) 1043 return; 1044 } 1045 1046 if (!filter_group (user.name)) 1047 return; 1048 1049 var label = user.real_name; 1050 if (user.real_name == "") 1051 label = user.name; 1052 1053 add_user (user.name, label, user.background, user.logged_in, user.has_messages, user.session); 1054 } 1055 1056 private bool filter_group (string user_name) 1057 { 1058 var group_filter = UGSettings.get_strv (UGSettings.KEY_GROUP_FILTER); 1059 1060 /* Empty list means do not filter by group */ 1061 if (group_filter.length == 0) 1062 return true; 1063 1064 foreach (var group_name in group_filter) 1065 if (in_group (group_name, user_name)) 1066 return true; 1067 1068 return false; 1069 } 1070 1071 private bool in_group (string group_name, string user_name) 1072 { 1073 unowned Posix.Group? group = Posix.getgrnam (group_name); 1074 if (group == null) 1075 return false; 1076 1077 foreach (var name in group.gr_mem) 1078 if (name == user_name) 1079 return true; 1080 1081 return false; 1082 } 1083 1084 private void user_removed_cb (LightDM.User user) 1085 { 1086 debug ("Removing user %s", user.name); 1087 remove_entry (user.name); 1088 } 1089 1090 protected override void show_prompt_cb (string text, LightDM.PromptType type) 1091 { 1092 if (selected_entry.id.has_prefix ("*remote_login")) 1093 { 1094 if (text == "remote login:") 1095 { 1096 Gtk.Entry field = current_remote_fields.get ("username") as Gtk.Entry; 1097 var answer = field != null ? field.text : ""; 1098 SlickGreeter.singleton.respond (answer); 1099 } 1100 else if (text == "password:") 1101 { 1102 Gtk.Entry field = current_remote_fields.get ("password") as Gtk.Entry; 1103 var answer = field != null ? field.text : ""; 1104 SlickGreeter.singleton.respond (answer); 1105 } 1106 else if (text == "remote host:") 1107 { 1108 var answer = url_from_remote_loding_server_list_name (selected_entry.id); 1109 SlickGreeter.singleton.respond (answer); 1110 } 1111 else if (text == "domain:") 1112 { 1113 Gtk.Entry field = current_remote_fields.get ("domain") as Gtk.Entry; 1114 var answer = field != null ? field.text : ""; 1115 SlickGreeter.singleton.respond (answer); 1116 } 1117 } 1118 else 1119 base.show_prompt_cb (text, type); 1120 } 1121 1122 /* A lot of test code below here */ 1123 1124 private struct TestEntry 1125 { 1126 string username; 1127 string real_name; 1128 string? background; 1129 bool is_active; 1130 bool has_messages; 1131 string? session; 1132 } 1133 1134 private const TestEntry[] test_entries = 1135 { 1136 { "has-password", "Has Password", "*" }, 1137 { "different-prompt", "Different Prompt", "*" }, 1138 { "no-password", "No Password", "*" }, 1139 { "change-password", "Change Password", "*" }, 1140 { "auth-error", "Auth Error", "*" }, 1141 { "two-factor", "Two Factor", "*" }, 1142 { "two-prompts", "Two Prompts", "*" }, 1143 { "info-prompt", "Info Prompt", "*" }, 1144 { "long-info-prompt", "Long Info Prompt", "*" }, 1145 { "wide-info-prompt", "Wide Info Prompt", "*" }, 1146 { "multi-info-prompt", "Multi Info Prompt", "*" }, 1147 { "very-very-long-name", "Long name (far far too long to fit)", "*" }, 1148 { "long-name-and-messages", "Long name and messages (too long to fit)", "*", false, true }, 1149 { "active", "Active Account", "*", true }, 1150 { "has-messages", "Has Messages", "*", false, true }, 1151 { "gnome", "GNOME", "*", false, false, "gnome" }, 1152 { "locked", "Locked Account", "*" }, 1153 { "color-background", "Color Background", "#dd4814" }, 1154 { "white-background", "White Background", "#ffffff" }, 1155 { "black-background", "Black Background", "#000000" }, 1156 { "no-background", "No Background", null }, 1157 { "unicode", "가나다라마", "*" }, 1158 { "no-response", "No Response", "*" }, 1159 { "no-badge", "No Badge", "*" }, 1160 { "messages-after-login", "Messages After Login", "*" }, 1161 { "" } 1162 }; 1163 private List<string> test_backgrounds; 1164 private int n_test_entries = 0; 1165 private bool test_prompted_sso = false; 1166 private string test_two_prompts_first = null; 1167 private bool test_request_new_password = false; 1168 private string? test_new_password = null; 1169 1170 private void test_fill_list () 1171 { 1172 test_backgrounds = new List<string> (); 1173 try 1174 { 1175 var dir = Dir.open ("/usr/local/share/backgrounds/"); 1176 while (true) 1177 { 1178 var bg = dir.read_name (); 1179 if (bg == null) 1180 break; 1181 test_backgrounds.append ("/usr/local/share/backgrounds/" + bg); 1182 } 1183 } 1184 catch (FileError e) 1185 { 1186 } 1187 1188 if (!SlickGreeter.singleton.hide_users_hint()) 1189 while (add_test_entry ()); 1190 1191 /* add a manual entry if the list of entries is empty initially */ 1192 if (n_test_entries <= 0) 1193 { 1194 add_manual_entry(); 1195 set_active_entry ("*other"); 1196 n_test_entries++; 1197 } 1198 1199 offer_guest = SlickGreeter.singleton.has_guest_account_hint(); 1200 always_show_manual = SlickGreeter.singleton.show_manual_login_hint(); 1201 1202 key_press_event.connect (test_key_press_cb); 1203 1204 if (SlickGreeter.singleton.show_remote_login_hint()) 1205 Timeout.add (1000, () => 1206 { 1207 RemoteServer[] test_server_list = {}; 1208 RemoteServer remote_server = RemoteServer (); 1209 remote_server.type = "uccs"; 1210 remote_server.name = "Remote Login"; 1211 remote_server.url = "http://crazyurl.com"; 1212 remote_server.last_used_server = false; 1213 remote_server.fields = {}; 1214 RemoteServerField field1 = RemoteServerField (); 1215 field1.type = "email"; 1216 RemoteServerField field2 = RemoteServerField (); 1217 field2.type = "password"; 1218 remote_server.fields = {field1, field2}; 1219 1220 test_server_list += remote_server; 1221 set_remote_directory_servers (test_server_list); 1222 1223 return false; 1224 }); 1225 1226 var last_user = SlickGreeter.singleton.get_state ("last-user"); 1227 if (last_user != null) 1228 set_active_entry (last_user); 1229 1230 } 1231 1232 private void test_call_set_remote_directory_servers () 1233 { 1234 RemoteServer[] test_server_list = {}; 1235 RemoteServer remote_server = RemoteServer (); 1236 remote_server.type = "uccs"; 1237 remote_server.name = "Corporate Remote Login"; 1238 remote_server.url = "http://internalcompayserver.com"; 1239 remote_server.last_used_server = false; 1240 remote_server.fields = {}; 1241 RemoteServerField field1 = RemoteServerField (); 1242 field1.type = "email"; 1243 RemoteServerField field2 = RemoteServerField (); 1244 field2.type = "password"; 1245 remote_server.fields = {field1, field2}; 1246 1247 test_server_list += remote_server; 1248 set_remote_directory_servers (test_server_list); 1249 } 1250 1251 private void test_call_remote_login_servers_updated () 1252 { 1253 RemoteServer[] server_list = {}; 1254 RemoteServer remote_server1 = RemoteServer (); 1255 remote_server1.type = "rdp"; 1256 remote_server1.name = "Cool RDP server"; 1257 remote_server1.url = "http://coolrdpserver.com"; 1258 remote_server1.last_used_server = false; 1259 remote_server1.fields = {}; 1260 RemoteServerField field1 = RemoteServerField (); 1261 field1.type = "username"; 1262 RemoteServerField field2 = RemoteServerField (); 1263 field2.type = "password"; 1264 RemoteServerField field3 = RemoteServerField (); 1265 field3.type = "domain"; 1266 remote_server1.fields = {field1, field2, field3}; 1267 1268 RemoteServer remote_server2 = RemoteServer (); 1269 remote_server2.type = "rdp"; 1270 remote_server2.name = "MegaCool RDP server"; 1271 remote_server2.url = "http://megacoolrdpserver.com"; 1272 remote_server2.last_used_server = false; 1273 remote_server2.fields = {}; 1274 RemoteServerField field21 = RemoteServerField (); 1275 field21.type = "username"; 1276 RemoteServerField field22 = RemoteServerField (); 1277 field22.type = "password"; 1278 remote_server2.fields = {field21, field22}; 1279 1280 server_list.resize (2); 1281 server_list[0] = remote_server1; 1282 server_list[1] = remote_server2; 1283 1284 remote_login_servers_updated (currently_browsing_server_url, currently_browsing_server_email, "", server_list); 1285 } 1286 1287 private void test_fill_remote_login_servers (out RemoteServer[] server_list) 1288 { 1289 string[] domains = { "SCANNERS", "PRINTERS", "ROUTERS" }; 1290 1291 server_list = {}; 1292 RemoteServer remote_server1 = RemoteServer (); 1293 remote_server1.type = "rdp"; 1294 remote_server1.name = "Cool RDP server"; 1295 remote_server1.url = "http://coolrdpserver.com"; 1296 remote_server1.last_used_server = false; 1297 remote_server1.fields = {}; 1298 RemoteServerField field1 = RemoteServerField (); 1299 field1.type = "username"; 1300 RemoteServerField field2 = RemoteServerField (); 1301 field2.type = "password"; 1302 RemoteServerField field3 = RemoteServerField (); 1303 field3.type = "domain"; 1304 remote_server1.fields = {field1, field2, field3}; 1305 1306 RemoteServer remote_server2 = RemoteServer (); 1307 remote_server2.type = "rdp"; 1308 remote_server2.name = "RDP server with default username, and editable domain"; 1309 remote_server2.url = "http://rdpdefaultusername.com"; 1310 remote_server2.last_used_server = false; 1311 remote_server2.fields = {}; 1312 RemoteServerField field21 = RemoteServerField (); 1313 field21.type = "username"; 1314 field21.default_value = new Variant.string ("alowl"); 1315 RemoteServerField field22 = RemoteServerField (); 1316 field22.type = "password"; 1317 RemoteServerField field23 = RemoteServerField (); 1318 field23.type = "domain"; 1319 field23.default_value = new Variant.string ("PRINTERS"); 1320 field23.properties = new HashTable<string, Variant> (str_hash, str_equal); 1321 field23.properties["domains"] = domains; 1322 remote_server2.fields = {field21, field22, field23}; 1323 1324 RemoteServer remote_server3 = RemoteServer (); 1325 remote_server3.type = "rdp"; 1326 remote_server3.name = "RDP server with default username, and non editable domain"; 1327 remote_server3.url = "http://rdpdefaultusername2.com"; 1328 remote_server3.last_used_server = true; 1329 remote_server3.fields = {}; 1330 RemoteServerField field31 = RemoteServerField (); 1331 field31.type = "username"; 1332 field31.default_value = new Variant.string ("lwola"); 1333 RemoteServerField field32 = RemoteServerField (); 1334 field32.type = "password"; 1335 RemoteServerField field33 = RemoteServerField (); 1336 field33.type = "domain"; 1337 field33.default_value = new Variant.string ("PRINTERS"); 1338 field33.properties = new HashTable<string, Variant> (str_hash, str_equal); 1339 field33.properties["domains"] = domains; 1340 field33.properties["read-only"] = true; 1341 1342 remote_server3.fields = {field31, field32, field33}; 1343 1344 RemoteServer remote_server4 = RemoteServer (); 1345 remote_server4.type = "notsupported"; 1346 remote_server4.name = "Not supported server"; 1347 remote_server4.url = "http://notsupportedserver.com"; 1348 remote_server4.fields = {}; 1349 RemoteServerField field41 = RemoteServerField (); 1350 field41.type = "username"; 1351 RemoteServerField field42 = RemoteServerField (); 1352 field42.type = "password"; 1353 RemoteServerField field43 = RemoteServerField (); 1354 field43.type = "domain"; 1355 1356 remote_server4.fields = {field41, field42, field43}; 1357 1358 server_list.resize (4); 1359 server_list[0] = remote_server1; 1360 server_list[1] = remote_server2; 1361 server_list[2] = remote_server3; 1362 server_list[3] = remote_server4; 1363 } 1364 1365 private void test_fill_remote_login_servers_duplicate_entries (out RemoteServer[] server_list) 1366 { 1367 /* Create two remote servers with same url but different username and domain. */ 1368 server_list = {}; 1369 1370 RemoteServer remote_server2 = RemoteServer (); 1371 remote_server2.type = "rdp"; 1372 remote_server2.name = "RDP server with default username, and editable domain"; 1373 remote_server2.url = "http://rdpdefaultusername.com"; 1374 remote_server2.last_used_server = false; 1375 remote_server2.fields = {}; 1376 RemoteServerField field21 = RemoteServerField (); 1377 field21.type = "username"; 1378 field21.default_value = new Variant.string ("alowl1"); 1379 RemoteServerField field22 = RemoteServerField (); 1380 field22.type = "password"; 1381 field22.default_value = new Variant.string ("duplicate1"); 1382 RemoteServerField field23 = RemoteServerField (); 1383 field23.type = "domain"; 1384 field23.default_value = new Variant.string ("SCANNERS"); 1385 remote_server2.fields = {field21, field22, field23}; 1386 1387 RemoteServer remote_server5 = RemoteServer (); 1388 remote_server5.type = "rdp"; 1389 remote_server5.name = "RDP server with default username, and editable domain"; 1390 remote_server5.url = "http://rdpdefaultusername.com"; 1391 remote_server5.last_used_server = false; 1392 remote_server5.fields = {}; 1393 RemoteServerField field51 = RemoteServerField (); 1394 field51.type = "username"; 1395 field51.default_value = new Variant.string ("alowl2"); 1396 RemoteServerField field52 = RemoteServerField (); 1397 field52.type = "password"; 1398 field52.default_value = new Variant.string ("duplicate2"); 1399 RemoteServerField field53 = RemoteServerField (); 1400 field53.type = "domain"; 1401 field53.default_value = new Variant.string ("PRINTERS"); 1402 remote_server5.fields = {field51, field52, field53}; 1403 1404 server_list.resize (2); 1405 server_list[0] = remote_server2; 1406 server_list[1] = remote_server5; 1407 } 1408 1409 private bool test_key_press_cb (Gdk.EventKey event) 1410 { 1411 if ((event.state & Gdk.ModifierType.CONTROL_MASK) == 0) 1412 return false; 1413 1414 switch (event.keyval) 1415 { 1416 case Gdk.Key.plus: 1417 add_test_entry (); 1418 break; 1419 case Gdk.Key.minus: 1420 remove_test_entry (); 1421 break; 1422 case Gdk.Key.@0: 1423 while (remove_test_entry ()); 1424 offer_guest = false; 1425 break; 1426 case Gdk.Key.equal: 1427 while (add_test_entry ()); 1428 offer_guest = true; 1429 break; 1430 case Gdk.Key.g: 1431 offer_guest = false; 1432 break; 1433 case Gdk.Key.G: 1434 offer_guest = true; 1435 break; 1436 case Gdk.Key.m: 1437 always_show_manual = false; 1438 break; 1439 case Gdk.Key.M: 1440 always_show_manual = true; 1441 break; 1442 } 1443 1444 return false; 1445 } 1446 1447 private bool add_test_entry () 1448 { 1449 var e = test_entries[n_test_entries]; 1450 if (e.username == "") 1451 return false; 1452 1453 var background = e.background; 1454 if (background == "*") 1455 { 1456 var background_index = 0; 1457 for (var i = 0; i < n_test_entries; i++) 1458 { 1459 if (test_entries[i].background == "*") 1460 background_index++; 1461 } 1462 if (test_backgrounds.length () > 0) 1463 background = test_backgrounds.nth_data (background_index % test_backgrounds.length ()); 1464 } 1465 add_user (e.username, e.real_name, background, e.is_active, e.has_messages, e.session); 1466 n_test_entries++; 1467 1468 return true; 1469 } 1470 1471 private bool remove_test_entry () 1472 { 1473 if (n_test_entries == 0) 1474 return false; 1475 1476 remove_entry (test_entries[n_test_entries - 1].username); 1477 n_test_entries--; 1478 1479 return true; 1480 } 1481 1482 private void test_respond (string text) 1483 { 1484 debug ("response %s", text); 1485 switch (get_selected_id ()) 1486 { 1487 case "*other": 1488 if (test_username == null) 1489 { 1490 debug ("username=%s", text); 1491 test_username = text; 1492 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1493 } 1494 else 1495 { 1496 test_is_authenticated = text == "password"; 1497 authentication_complete_cb (); 1498 } 1499 break; 1500 case "two-factor": 1501 if (!test_prompted_sso) 1502 { 1503 if (text == "password") 1504 { 1505 debug ("prompt otp"); 1506 test_prompted_sso = true; 1507 show_prompt_cb ("OTP:", LightDM.PromptType.QUESTION); 1508 } 1509 else 1510 { 1511 test_is_authenticated = false; 1512 authentication_complete_cb (); 1513 } 1514 } 1515 else 1516 { 1517 test_is_authenticated = text == "otp"; 1518 authentication_complete_cb (); 1519 } 1520 break; 1521 case "two-prompts": 1522 if (test_two_prompts_first == null) 1523 test_two_prompts_first = text; 1524 else 1525 { 1526 test_is_authenticated = test_two_prompts_first == "blue" && text == "password"; 1527 authentication_complete_cb (); 1528 } 1529 break; 1530 case "change-password": 1531 if (test_new_password != null) 1532 { 1533 test_is_authenticated = text == test_new_password; 1534 authentication_complete_cb (); 1535 } 1536 else if (test_request_new_password) 1537 { 1538 test_new_password = text; 1539 show_prompt_cb ("Retype new UNIX password: ", LightDM.PromptType.SECRET); 1540 } 1541 else 1542 { 1543 if (text != "password") 1544 { 1545 test_is_authenticated = false; 1546 authentication_complete_cb (); 1547 } 1548 else 1549 { 1550 test_request_new_password = true; 1551 show_message_cb ("You are required to change your password immediately (root enforced)", LightDM.MessageType.ERROR); 1552 show_prompt_cb ("Enter new UNIX password: ", LightDM.PromptType.SECRET); 1553 } 1554 } 1555 break; 1556 case "no-response": 1557 break; 1558 case "locked": 1559 test_is_authenticated = false; 1560 show_message_cb ("Account is locked", LightDM.MessageType.ERROR); 1561 authentication_complete_cb (); 1562 break; 1563 case "messages-after-login": 1564 test_is_authenticated = text == "password"; 1565 if (test_is_authenticated) 1566 show_message_cb ("Congratulations on logging in!", LightDM.MessageType.INFO); 1567 authentication_complete_cb (); 1568 break; 1569 default: 1570 test_is_authenticated = text == "password"; 1571 authentication_complete_cb (); 1572 break; 1573 } 1574 } 1575 1576 protected override void test_start_authentication () 1577 { 1578 test_username = null; 1579 test_is_authenticated = false; 1580 test_prompted_sso = false; 1581 test_two_prompts_first = null; 1582 test_request_new_password = false; 1583 test_new_password = null; 1584 1585 switch (get_selected_id ()) 1586 { 1587 case "*other": 1588 if (authenticate_user != null) 1589 { 1590 test_username = authenticate_user; 1591 authenticate_user = null; 1592 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1593 } 1594 else 1595 show_prompt_cb ("Username:", LightDM.PromptType.QUESTION); 1596 break; 1597 case "*guest": 1598 test_is_authenticated = true; 1599 authentication_complete_cb (); 1600 break; 1601 case "different-prompt": 1602 show_prompt_cb ("Secret word", LightDM.PromptType.SECRET); 1603 break; 1604 case "no-password": 1605 test_is_authenticated = true; 1606 authentication_complete_cb (); 1607 break; 1608 case "auth-error": 1609 show_message_cb ("Authentication Error", LightDM.MessageType.ERROR); 1610 test_is_authenticated = false; 1611 authentication_complete_cb (); 1612 break; 1613 case "info-prompt": 1614 show_message_cb ("Welcome to Slick Greeter", LightDM.MessageType.INFO); 1615 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1616 break; 1617 case "long-info-prompt": 1618 show_message_cb ("Welcome to Slick Greeter\n\nWe like to annoy you with long messages.\nLike this one\n\nThis is the last line of a multiple line message.", LightDM.MessageType.INFO); 1619 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1620 break; 1621 case "wide-info-prompt": 1622 show_message_cb ("Welcome to Slick Greeter, the greeteriest greeter that ever did appear in these fine lands", LightDM.MessageType.INFO); 1623 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1624 break; 1625 case "multi-info-prompt": 1626 show_message_cb ("Welcome to Slick Greeter", LightDM.MessageType.INFO); 1627 show_message_cb ("This is an error", LightDM.MessageType.ERROR); 1628 show_message_cb ("You should have seen three messages", LightDM.MessageType.INFO); 1629 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1630 break; 1631 case "two-prompts": 1632 show_prompt_cb ("Favorite Color (blue):", LightDM.PromptType.QUESTION); 1633 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1634 break; 1635 default: 1636 show_prompt_cb ("Password:", LightDM.PromptType.SECRET); 1637 break; 1638 } 1639 } 1640} 1641