1 /* 2 * Copyright 2008, François Revol, <revol@free.fr>. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <Alert.h> 8 #include <Screen.h> 9 #include <String.h> 10 #include <View.h> 11 12 #include <stdio.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <pwd.h> 16 17 #include "LoginApp.h" 18 #include "LoginWindow.h" 19 #include "DesktopWindow.h" 20 21 #ifdef __HAIKU__ 22 #include <RosterPrivate.h> 23 #include <shadow.h> 24 #include "multiuser_utils.h" 25 #endif 26 27 28 const char *kLoginAppSig = "application/x-vnd.Haiku-Login"; 29 30 31 LoginApp::LoginApp() 32 : BApplication(kLoginAppSig), 33 fEditShelfMode(false) 34 { 35 } 36 37 38 LoginApp::~LoginApp() 39 { 40 } 41 42 43 void 44 LoginApp::ReadyToRun() 45 { 46 BScreen screen; 47 48 if (fEditShelfMode) { 49 (new BAlert("Info", "You can customize the desktop shown " 50 "behind the Login app by dropping replicants onto it.\n" 51 "\n" 52 "When you are finished just quit the application (Alt-Q).", 53 "Ok"))->Go(NULL); 54 } else { 55 BRect frame(0, 0, 400, 150); 56 frame.OffsetBySelf(screen.Frame().Width()/2 - frame.Width()/2, 57 screen.Frame().Height()/2 - frame.Height()/2); 58 fLoginWindow = new LoginWindow(frame); 59 fLoginWindow->Show(); 60 } 61 62 fDesktopWindow = new DesktopWindow(screen.Frame(), fEditShelfMode); 63 fDesktopWindow->Show(); 64 // TODO: add a shelf with Activity Monitor replicant :) 65 } 66 67 68 void 69 LoginApp::MessageReceived(BMessage *message) 70 { 71 bool reboot = false; 72 73 switch (message->what) { 74 case kAttemptLogin: 75 message->PrintToStream(); 76 TryLogin(message); 77 // TODO 78 break; 79 #ifdef __HAIKU__ 80 case kHaltAction: 81 reboot = false; 82 // FALLTHROUGH 83 case kRebootAction: 84 { 85 BRoster roster; 86 BRoster::Private rosterPrivate(roster); 87 status_t error = rosterPrivate.ShutDown(reboot, false, false); 88 if (error < B_OK) { 89 BString msg("Error: "); 90 msg << strerror(error); 91 (new BAlert("Error", msg.String(), "Ok"))->Go(); 92 } 93 break; 94 } 95 case kSuspendAction: 96 (new BAlert("Error", "Unimplemented", "Ok"))->Go(); 97 break; 98 #endif 99 default: 100 BApplication::MessageReceived(message); 101 } 102 } 103 104 105 void 106 LoginApp::ArgvReceived(int32 argc, char **argv) 107 { 108 int i; 109 for (i = 1; i < argc; i++) { 110 printf("[%d]: %s\n", i, argv[i]); 111 if (argv[i] == BString("--edit")) 112 fEditShelfMode = true; 113 } 114 } 115 116 117 void 118 LoginApp::TryLogin(BMessage *message) 119 { 120 status_t err; 121 const char *login; 122 const char *password; 123 BMessage reply(kLoginBad); 124 if (message->FindString("login", &login) == B_OK) { 125 if (message->FindString("password", &password) < B_OK) 126 password = NULL; 127 err = ValidateLogin(login, password); 128 printf("ValidateLogin: %s\n", strerror(err)); 129 if (err == B_OK) { 130 reply.what = kLoginOk; 131 message->SendReply(&reply); 132 133 if (password == NULL) 134 return; 135 136 // start a session 137 //kSetProgress 138 StartUserSession(login); 139 } else { 140 reply.AddInt32("error", err); 141 message->SendReply(&reply); 142 return; 143 } 144 145 } else { 146 reply.AddInt32("error", EINVAL); 147 message->SendReply(&reply); 148 return; 149 } 150 } 151 152 153 status_t 154 LoginApp::ValidateLogin(const char *login, const char *password) 155 { 156 struct passwd *pwd; 157 158 pwd = getpwnam(login); 159 if (!pwd) 160 return ENOENT; 161 if (strcmp(pwd->pw_name, login)) 162 return ENOENT; 163 164 if (password == NULL) { 165 // we only want to check is login exists. 166 return B_OK; 167 } 168 169 #ifdef __HAIKU__ 170 if (verify_password(pwd, getspnam(login), password)) 171 return B_OK; 172 #else 173 // for testing 174 if (strcmp(crypt(password, pwd->pw_passwd), pwd->pw_passwd) == 0) 175 return B_OK; 176 #endif 177 178 return B_PERMISSION_DENIED; 179 } 180 181 182 status_t 183 LoginApp::StartUserSession(const char *login) 184 { 185 return B_ERROR; 186 } 187 188 189 int 190 LoginApp::getpty(char *pty, char *tty) 191 { 192 static const char major[] = "pqrs"; 193 static const char minor[] = "0123456789abcdef"; 194 uint32 i, j; 195 int32 fd = -1; 196 197 for (i = 0; i < sizeof(major); i++) 198 { 199 for (j = 0; j < sizeof(minor); j++) 200 { 201 sprintf(pty, "/dev/pt/%c%c", major[i], minor[j]); 202 sprintf(tty, "/dev/tt/%c%c", major[i], minor[j]); 203 fd = open(pty, O_RDWR|O_NOCTTY); 204 if (fd >= 0) 205 { 206 return fd; 207 } 208 } 209 } 210 211 return fd; 212 } 213 214 215 216