launch_daemon: Basic user session implementation.
* Instead of launching Tracker/Deskbar directly, we now launch the Login application. * This will now start a new session for the selected user (the password is currently ignored). * When a user session is started, the launch_daemon forks, and the child then restarts the LaunchDaemon application in user mode. * It then registers itself with its parent, in order to resolve user dependent services. * Added a user launch file that will cause Tracker, and Deskbar to start in the new session.
This commit is contained in:
@@ -41,6 +41,7 @@ SYSTEM_APPS = [ FFilterByBuildFeatures
|
|||||||
CharacterMap
|
CharacterMap
|
||||||
Debugger DeskCalc Devices DiskProbe DiskUsage DriveSetup
|
Debugger DeskCalc Devices DiskProbe DiskUsage DriveSetup
|
||||||
Expander
|
Expander
|
||||||
|
Login
|
||||||
NetworkStatus
|
NetworkStatus
|
||||||
ProcessController
|
ProcessController
|
||||||
ShowImage StyledEdit
|
ShowImage StyledEdit
|
||||||
@@ -277,6 +278,10 @@ SEARCH on $(networkSettingsFiles)
|
|||||||
= [ FDirName $(HAIKU_TOP) data settings network ] ;
|
= [ FDirName $(HAIKU_TOP) data settings network ] ;
|
||||||
AddFilesToHaikuImage system settings network : $(networkSettingsFiles) ;
|
AddFilesToHaikuImage system settings network : $(networkSettingsFiles) ;
|
||||||
|
|
||||||
|
local userLaunchScripts = <data!launch>user ;
|
||||||
|
SEARCH on $(userLaunchScripts) = [ FDirName $(HAIKU_TOP) data launch ] ;
|
||||||
|
AddFilesToHaikuImage home config non-packaged data launch : $(userLaunchScripts) ;
|
||||||
|
|
||||||
# fresh install indicator file for the post install scripts
|
# fresh install indicator file for the post install scripts
|
||||||
SEARCH on <post-install>fresh_install
|
SEARCH on <post-install>fresh_install
|
||||||
= [ FDirName $(HAIKU_TOP) data system settings ] ;
|
= [ FDirName $(HAIKU_TOP) data system settings ] ;
|
||||||
|
|||||||
+2
-8
@@ -71,13 +71,7 @@ service x-vnd.Haiku-power_daemon {
|
|||||||
legacy
|
legacy
|
||||||
}
|
}
|
||||||
|
|
||||||
# The following will be moved into the user launch data
|
job x-vnd.Haiku-Login {
|
||||||
service x-vnd.Be-TRAK {
|
launch /system/apps/Login
|
||||||
launch /system/Tracker
|
|
||||||
legacy
|
|
||||||
}
|
|
||||||
|
|
||||||
service x-vnd.Be-TSKB {
|
|
||||||
launch /system/Deskbar
|
|
||||||
legacy
|
legacy
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
service x-vnd.Be-TRAK {
|
||||||
|
launch /system/Tracker
|
||||||
|
legacy
|
||||||
|
}
|
||||||
|
|
||||||
|
service x-vnd.Be-TSKB {
|
||||||
|
launch /system/Deskbar
|
||||||
|
legacy
|
||||||
|
}
|
||||||
@@ -24,7 +24,9 @@ namespace BPrivate {
|
|||||||
|
|
||||||
// message constants
|
// message constants
|
||||||
enum {
|
enum {
|
||||||
B_GET_LAUNCH_DATA = 'lncd',
|
B_GET_LAUNCH_DATA = 'lnda',
|
||||||
|
B_LAUNCH_SESSION = 'lnse',
|
||||||
|
B_REGISTER_LAUNCH_SESSION = 'lnrs',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,14 @@ public:
|
|||||||
port_id GetPort(const char* signature,
|
port_id GetPort(const char* signature,
|
||||||
const char* name);
|
const char* name);
|
||||||
|
|
||||||
|
status_t StartSession(const char* login,
|
||||||
|
const char* password);
|
||||||
|
|
||||||
|
class Private;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class Private;
|
||||||
|
|
||||||
void _InitMessenger();
|
void _InitMessenger();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _LAUNCH_ROSTER_PRIVATE_H
|
||||||
|
#define _LAUNCH_ROSTER_PRIVATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <LaunchRoster.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BLaunchRoster::Private {
|
||||||
|
public:
|
||||||
|
Private(BLaunchRoster* roster);
|
||||||
|
Private(BLaunchRoster& roster);
|
||||||
|
|
||||||
|
status_t RegisterSession(const BMessenger& target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BLaunchRoster* fRoster;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _LAUNCH_ROSTER_PRIVATE_H
|
||||||
+29
-33
@@ -16,15 +16,16 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#include <LaunchRoster.h>
|
||||||
|
#include <RosterPrivate.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
|
||||||
|
#include "multiuser_utils.h"
|
||||||
|
|
||||||
#include "LoginApp.h"
|
#include "LoginApp.h"
|
||||||
#include "LoginWindow.h"
|
#include "LoginWindow.h"
|
||||||
#include "DesktopWindow.h"
|
#include "DesktopWindow.h"
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
#include <RosterPrivate.h>
|
|
||||||
#include <shadow.h>
|
|
||||||
#include "multiuser_utils.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef B_TRANSLATION_CONTEXT
|
#undef B_TRANSLATION_CONTEXT
|
||||||
#define B_TRANSLATION_CONTEXT "Login App"
|
#define B_TRANSLATION_CONTEXT "Login App"
|
||||||
@@ -80,11 +81,9 @@ LoginApp::MessageReceived(BMessage *message)
|
|||||||
|
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case kAttemptLogin:
|
case kAttemptLogin:
|
||||||
message->PrintToStream();
|
|
||||||
TryLogin(message);
|
TryLogin(message);
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
#ifdef __HAIKU__
|
|
||||||
case kHaltAction:
|
case kHaltAction:
|
||||||
reboot = false;
|
reboot = false;
|
||||||
// FALLTHROUGH
|
// FALLTHROUGH
|
||||||
@@ -111,9 +110,9 @@ LoginApp::MessageReceived(BMessage *message)
|
|||||||
alert->Go();
|
alert->Go();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
BApplication::MessageReceived(message);
|
BApplication::MessageReceived(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,37 +144,31 @@ LoginApp::ArgvReceived(int32 argc, char **argv)
|
|||||||
void
|
void
|
||||||
LoginApp::TryLogin(BMessage *message)
|
LoginApp::TryLogin(BMessage *message)
|
||||||
{
|
{
|
||||||
status_t err;
|
status_t status = B_BAD_VALUE;
|
||||||
|
|
||||||
const char *login;
|
const char *login;
|
||||||
const char *password;
|
const char *password;
|
||||||
BMessage reply(kLoginBad);
|
BMessage reply(kLoginBad);
|
||||||
if (message->FindString("login", &login) == B_OK) {
|
if (message->FindString("login", &login) == B_OK) {
|
||||||
if (message->FindString("password", &password) < B_OK)
|
if (message->FindString("password", &password) < B_OK)
|
||||||
password = NULL;
|
password = NULL;
|
||||||
err = ValidateLogin(login, password);
|
|
||||||
printf(B_TRANSLATE_COMMENT("ValidateLogin: %s\n",
|
|
||||||
"A message returned from the ValidateLogin function. "
|
|
||||||
"It can be \"B_OK\"."), strerror(err));
|
|
||||||
if (err == B_OK) {
|
|
||||||
reply.what = kLoginOk;
|
|
||||||
message->SendReply(&reply);
|
|
||||||
|
|
||||||
if (password == NULL)
|
if (password != NULL) {
|
||||||
return;
|
status = StartUserSession(login, password);
|
||||||
|
if (status == B_OK)
|
||||||
|
Quit();
|
||||||
|
} else
|
||||||
|
status = ValidateLogin(login, password);
|
||||||
|
|
||||||
// start a session
|
fprintf(stderr, "ValidateLogin: %s\n", strerror(status));
|
||||||
//kSetProgress
|
}
|
||||||
StartUserSession(login);
|
|
||||||
} else {
|
|
||||||
reply.AddInt32("error", err);
|
|
||||||
message->SendReply(&reply);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
if (status == B_OK) {
|
||||||
reply.AddInt32("error", EINVAL);
|
reply.what = kLoginOk;
|
||||||
|
message->SendReply(&reply);
|
||||||
|
} else {
|
||||||
|
reply.AddInt32("error", status);
|
||||||
message->SendReply(&reply);
|
message->SendReply(&reply);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,9 +203,12 @@ LoginApp::ValidateLogin(const char *login, const char *password)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
LoginApp::StartUserSession(const char *login)
|
LoginApp::StartUserSession(const char* login, const char* password)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
if (login == NULL || password == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return BLaunchRoster().StartSession(login, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void TryLogin(BMessage *message);
|
void TryLogin(BMessage *message);
|
||||||
status_t ValidateLogin(const char *login, const char *password);
|
status_t ValidateLogin(const char *login, const char *password);
|
||||||
status_t StartUserSession(const char *login);
|
status_t StartUserSession(const char *login, const char *password);
|
||||||
int getpty(char *pty, char *tty);
|
int getpty(char *pty, char *tty);
|
||||||
|
|
||||||
DesktopWindow* fDesktopWindow;
|
DesktopWindow* fDesktopWindow;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <launch.h>
|
#include <launch.h>
|
||||||
#include <LaunchDaemonDefs.h>
|
#include <LaunchDaemonDefs.h>
|
||||||
|
#include <LaunchRosterPrivate.h>
|
||||||
#include <MessengerPrivate.h>
|
#include <MessengerPrivate.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -23,6 +24,45 @@ using namespace BPrivate;
|
|||||||
const BLaunchRoster* be_launch_roster;
|
const BLaunchRoster* be_launch_roster;
|
||||||
|
|
||||||
|
|
||||||
|
BLaunchRoster::Private::Private(BLaunchRoster* roster)
|
||||||
|
:
|
||||||
|
fRoster(roster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BLaunchRoster::Private::Private(BLaunchRoster& roster)
|
||||||
|
:
|
||||||
|
fRoster(&roster)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BLaunchRoster::Private::RegisterSession(const BMessenger& target)
|
||||||
|
{
|
||||||
|
BMessage request(B_REGISTER_LAUNCH_SESSION);
|
||||||
|
status_t status = request.AddInt32("user", getuid());
|
||||||
|
if (status == B_OK)
|
||||||
|
status = request.AddMessenger("target", target);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
BMessage result;
|
||||||
|
status = fRoster->fMessenger.SendMessage(&request, &result);
|
||||||
|
|
||||||
|
// evaluate the reply
|
||||||
|
if (status == B_OK)
|
||||||
|
status = result.what;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
BLaunchRoster::BLaunchRoster()
|
BLaunchRoster::BLaunchRoster()
|
||||||
{
|
{
|
||||||
_InitMessenger();
|
_InitMessenger();
|
||||||
@@ -59,6 +99,8 @@ BLaunchRoster::GetData(const char* signature, BMessage& data)
|
|||||||
|
|
||||||
BMessage request(B_GET_LAUNCH_DATA);
|
BMessage request(B_GET_LAUNCH_DATA);
|
||||||
status_t status = request.AddString("name", signature);
|
status_t status = request.AddString("name", signature);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = request.AddInt32("user", getuid());
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -86,9 +128,8 @@ BLaunchRoster::GetPort(const char* name)
|
|||||||
port_id
|
port_id
|
||||||
BLaunchRoster::GetPort(const char* signature, const char* name)
|
BLaunchRoster::GetPort(const char* signature, const char* name)
|
||||||
{
|
{
|
||||||
BLaunchRoster launchRoster;
|
|
||||||
BMessage data;
|
BMessage data;
|
||||||
status_t status = launchRoster.GetData(signature, data);
|
status_t status = GetData(signature, data);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
BString fieldName;
|
BString fieldName;
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
@@ -104,6 +145,33 @@ BLaunchRoster::GetPort(const char* signature, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BLaunchRoster::StartSession(const char* login, const char* password)
|
||||||
|
{
|
||||||
|
if (login == NULL || password == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
BMessage request(B_LAUNCH_SESSION);
|
||||||
|
status_t status = request.AddInt32("user", getuid());
|
||||||
|
if (status == B_OK)
|
||||||
|
status = request.AddString("login", login);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = request.AddString("password", password);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
BMessage result;
|
||||||
|
status = fMessenger.SendMessage(&request, &result);
|
||||||
|
|
||||||
|
// evaluate the reply
|
||||||
|
if (status == B_OK)
|
||||||
|
status = result.what;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BLaunchRoster::_InitMessenger()
|
BLaunchRoster::_InitMessenger()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ SubDir HAIKU_TOP src servers launch ;
|
|||||||
UsePrivateHeaders app package shared storage support ;
|
UsePrivateHeaders app package shared storage support ;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src bin multiuser ] ;
|
||||||
|
|
||||||
Server launch_daemon
|
Server launch_daemon
|
||||||
:
|
:
|
||||||
LaunchDaemon.cpp
|
LaunchDaemon.cpp
|
||||||
@@ -14,7 +16,7 @@ Server launch_daemon
|
|||||||
InitSharedMemoryDirectoryJob.cpp
|
InitSharedMemoryDirectoryJob.cpp
|
||||||
InitTemporaryDirectoryJob.cpp
|
InitTemporaryDirectoryJob.cpp
|
||||||
:
|
:
|
||||||
be libshared.a [ TargetLibstdc++ ]
|
be libshared.a libmultiuser_utils.a [ TargetLibstdc++ ]
|
||||||
:
|
:
|
||||||
LaunchDaemon.rdef
|
LaunchDaemon.rdef
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -23,8 +25,11 @@
|
|||||||
#include <AppMisc.h>
|
#include <AppMisc.h>
|
||||||
#include <DriverSettingsMessageAdapter.h>
|
#include <DriverSettingsMessageAdapter.h>
|
||||||
#include <LaunchDaemonDefs.h>
|
#include <LaunchDaemonDefs.h>
|
||||||
|
#include <LaunchRosterPrivate.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
#include "multiuser_utils.h"
|
||||||
|
|
||||||
#include "InitRealTimeClockJob.h"
|
#include "InitRealTimeClockJob.h"
|
||||||
#include "InitSharedMemoryDirectoryJob.h"
|
#include "InitSharedMemoryDirectoryJob.h"
|
||||||
#include "InitTemporaryDirectoryJob.h"
|
#include "InitTemporaryDirectoryJob.h"
|
||||||
@@ -65,6 +70,21 @@ const static settings_template kSettingsTemplate[] = {
|
|||||||
typedef std::map<BString, BMessage> PortMap;
|
typedef std::map<BString, BMessage> PortMap;
|
||||||
|
|
||||||
|
|
||||||
|
class Session {
|
||||||
|
public:
|
||||||
|
Session(uid_t user, const BMessenger& target);
|
||||||
|
|
||||||
|
uid_t User() const
|
||||||
|
{ return fUser; }
|
||||||
|
const BMessenger& Target() const
|
||||||
|
{ return fTarget; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uid_t fUser;
|
||||||
|
BMessenger fTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Target : public BJob {
|
class Target : public BJob {
|
||||||
public:
|
public:
|
||||||
Target(const char* name);
|
Target(const char* name);
|
||||||
@@ -135,26 +155,30 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<BString, Job*> JobMap;
|
|
||||||
|
|
||||||
|
|
||||||
class JobFinder {
|
class JobFinder {
|
||||||
public:
|
public:
|
||||||
virtual Job* FindJob(const char* name) const = 0;
|
virtual Job* FindJob(const char* name) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<BString, Job*> JobMap;
|
||||||
|
typedef std::map<uid_t, Session*> SessionMap;
|
||||||
|
|
||||||
|
|
||||||
class LaunchDaemon : public BServer, public JobFinder {
|
class LaunchDaemon : public BServer, public JobFinder {
|
||||||
public:
|
public:
|
||||||
LaunchDaemon(status_t& error);
|
LaunchDaemon(bool userMode, status_t& error);
|
||||||
virtual ~LaunchDaemon();
|
virtual ~LaunchDaemon();
|
||||||
|
|
||||||
virtual Job* FindJob(const char* name) const;
|
virtual Job* FindJob(const char* name) const;
|
||||||
|
Session* FindSession(uid_t user) const;
|
||||||
|
|
||||||
virtual void ReadyToRun();
|
virtual void ReadyToRun();
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uid_t _GetUserID(BMessage* message);
|
||||||
|
|
||||||
void _ReadPaths(const BStringList& paths);
|
void _ReadPaths(const BStringList& paths);
|
||||||
void _ReadEntry(const char* context, BEntry& entry);
|
void _ReadEntry(const char* context, BEntry& entry);
|
||||||
void _ReadDirectory(const char* context,
|
void _ReadDirectory(const char* context,
|
||||||
@@ -166,6 +190,9 @@ private:
|
|||||||
void _LaunchJobs();
|
void _LaunchJobs();
|
||||||
void _AddLaunchJob(Job* job);
|
void _AddLaunchJob(Job* job);
|
||||||
|
|
||||||
|
status_t _StartSession(const char* login,
|
||||||
|
const char* password);
|
||||||
|
|
||||||
void _RetrieveKernelOptions();
|
void _RetrieveKernelOptions();
|
||||||
void _SetupEnvironment();
|
void _SetupEnvironment();
|
||||||
void _InitSystem();
|
void _InitSystem();
|
||||||
@@ -176,9 +203,11 @@ private:
|
|||||||
private:
|
private:
|
||||||
JobMap fJobs;
|
JobMap fJobs;
|
||||||
JobQueue fJobQueue;
|
JobQueue fJobQueue;
|
||||||
|
SessionMap fSessions;
|
||||||
MainWorker* fMainWorker;
|
MainWorker* fMainWorker;
|
||||||
Target* fInitTarget;
|
Target* fInitTarget;
|
||||||
bool fSafeMode;
|
bool fSafeMode;
|
||||||
|
bool fUserMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -508,6 +537,17 @@ Job::Execute()
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
Session::Session(uid_t user, const BMessenger& target)
|
||||||
|
:
|
||||||
|
fUser(user),
|
||||||
|
fTarget(target)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
Target::Target(const char* name)
|
Target::Target(const char* name)
|
||||||
:
|
:
|
||||||
BJob(name)
|
BJob(name)
|
||||||
@@ -525,12 +565,13 @@ Target::Execute()
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
LaunchDaemon::LaunchDaemon(status_t& error)
|
LaunchDaemon::LaunchDaemon(bool userMode, status_t& error)
|
||||||
:
|
:
|
||||||
BServer(kLaunchDaemonSignature, NULL,
|
BServer(kLaunchDaemonSignature, NULL,
|
||||||
create_port(B_LOOPER_PORT_DEFAULT_CAPACITY,
|
create_port(B_LOOPER_PORT_DEFAULT_CAPACITY,
|
||||||
B_LAUNCH_DAEMON_PORT_NAME), false, &error),
|
userMode ? "AppPort" : B_LAUNCH_DAEMON_PORT_NAME), false, &error),
|
||||||
fInitTarget(new Target("init"))
|
fInitTarget(userMode ? NULL : new Target("init")),
|
||||||
|
fUserMode(userMode)
|
||||||
{
|
{
|
||||||
fMainWorker = new MainWorker(fJobQueue);
|
fMainWorker = new MainWorker(fJobQueue);
|
||||||
}
|
}
|
||||||
@@ -555,23 +596,38 @@ LaunchDaemon::FindJob(const char* name) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Session*
|
||||||
|
LaunchDaemon::FindSession(uid_t user) const
|
||||||
|
{
|
||||||
|
SessionMap::const_iterator found = fSessions.find(user);
|
||||||
|
if (found != fSessions.end())
|
||||||
|
return found->second;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LaunchDaemon::ReadyToRun()
|
LaunchDaemon::ReadyToRun()
|
||||||
{
|
{
|
||||||
_RetrieveKernelOptions();
|
_RetrieveKernelOptions();
|
||||||
_SetupEnvironment();
|
_SetupEnvironment();
|
||||||
_InitSystem();
|
if (fUserMode) {
|
||||||
|
BLaunchRoster roster;
|
||||||
|
BLaunchRoster::Private(roster).RegisterSession(this);
|
||||||
|
} else
|
||||||
|
_InitSystem();
|
||||||
|
|
||||||
BStringList paths;
|
BStringList paths;
|
||||||
BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, kLaunchDirectory,
|
BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, kLaunchDirectory,
|
||||||
B_FIND_PATHS_SYSTEM_ONLY, paths);
|
fUserMode ? B_FIND_PATHS_USER_ONLY : B_FIND_PATHS_SYSTEM_ONLY, paths);
|
||||||
_ReadPaths(paths);
|
_ReadPaths(paths);
|
||||||
|
|
||||||
BPathFinder::FindPaths(B_FIND_PATH_SETTINGS_DIRECTORY, kLaunchDirectory,
|
BPathFinder::FindPaths(B_FIND_PATH_SETTINGS_DIRECTORY, kLaunchDirectory,
|
||||||
B_FIND_PATHS_SYSTEM_ONLY, paths);
|
fUserMode ? B_FIND_PATHS_USER_ONLY : B_FIND_PATHS_SYSTEM_ONLY, paths);
|
||||||
_ReadPaths(paths);
|
_ReadPaths(paths);
|
||||||
|
|
||||||
_InitJobs(fInitTarget);
|
_InitJobs(fUserMode ? NULL : fInitTarget);
|
||||||
_LaunchJobs();
|
_LaunchJobs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,9 +638,19 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case B_GET_LAUNCH_DATA:
|
case B_GET_LAUNCH_DATA:
|
||||||
{
|
{
|
||||||
|
uid_t user = _GetUserID(message);
|
||||||
|
if (user < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
BMessage reply((uint32)B_OK);
|
BMessage reply((uint32)B_OK);
|
||||||
Job* job = FindJob(get_leaf(message->GetString("name")));
|
Job* job = FindJob(get_leaf(message->GetString("name")));
|
||||||
if (job == NULL) {
|
if (job == NULL) {
|
||||||
|
Session* session = FindSession(user);
|
||||||
|
if (session != NULL) {
|
||||||
|
// Forward request to user launch_daemon
|
||||||
|
if (session->Target().SendMessage(message) == B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
reply.what = B_NAME_NOT_FOUND;
|
reply.what = B_NAME_NOT_FOUND;
|
||||||
} else {
|
} else {
|
||||||
// If the job has not been launched yet, we'll pass on our
|
// If the job has not been launched yet, we'll pass on our
|
||||||
@@ -610,6 +676,54 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case B_LAUNCH_SESSION:
|
||||||
|
{
|
||||||
|
uid_t user = _GetUserID(message);
|
||||||
|
if (user < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
status_t status = B_OK;
|
||||||
|
const char* login = message->GetString("login");
|
||||||
|
const char* password = message->GetString("password");
|
||||||
|
if (login == NULL || password == NULL)
|
||||||
|
status = B_BAD_VALUE;
|
||||||
|
if (status == B_OK && user != 0) {
|
||||||
|
// Only the root user can start sessions
|
||||||
|
status = B_PERMISSION_DENIED;
|
||||||
|
}
|
||||||
|
if (status == B_OK)
|
||||||
|
status = _StartSession(login, password);
|
||||||
|
|
||||||
|
BMessage reply((uint32)status);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_REGISTER_LAUNCH_SESSION:
|
||||||
|
{
|
||||||
|
uid_t user = _GetUserID(message);
|
||||||
|
if (user < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
BMessenger target;
|
||||||
|
if (message->FindMessenger("target", &target) != B_OK)
|
||||||
|
status = B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
Session* session = new (std::nothrow) Session(user, target);
|
||||||
|
if (session != NULL)
|
||||||
|
fSessions.insert(std::pair<uid_t, Session*>(user, session));
|
||||||
|
else
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage reply((uint32)status);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BServer::MessageReceived(message);
|
BServer::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@@ -617,6 +731,18 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uid_t
|
||||||
|
LaunchDaemon::_GetUserID(BMessage* message)
|
||||||
|
{
|
||||||
|
uid_t user = (uid_t)message->GetInt32("user", -1);
|
||||||
|
if (user < 0) {
|
||||||
|
BMessage reply((uint32)B_BAD_VALUE);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LaunchDaemon::_ReadPaths(const BStringList& paths)
|
LaunchDaemon::_ReadPaths(const BStringList& paths)
|
||||||
{
|
{
|
||||||
@@ -746,7 +872,7 @@ LaunchDaemon::_InitJobs(Target* target)
|
|||||||
strerror(status));
|
strerror(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove jobs that aren't user later on
|
// Remove jobs that won't be used later on
|
||||||
fJobs.erase(remove);
|
fJobs.erase(remove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -772,6 +898,67 @@ LaunchDaemon::_AddLaunchJob(Job* job)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LaunchDaemon::_StartSession(const char* login, const char* password)
|
||||||
|
{
|
||||||
|
Unlock();
|
||||||
|
|
||||||
|
// TODO: enable user/group code and password authentication
|
||||||
|
// The launch_daemon currently cannot talk to the registrar, though
|
||||||
|
/*
|
||||||
|
struct passwd* passwd = getpwnam(login);
|
||||||
|
if (passwd == NULL)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
if (strcmp(passwd->pw_name, login) != 0)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
// TODO: check for auto-login, and ignore password then
|
||||||
|
if (!verify_password(passwd, getspnam(login), password))
|
||||||
|
return B_PERMISSION_DENIED;
|
||||||
|
|
||||||
|
// Check if there is a user session running already
|
||||||
|
uid_t user = passwd->pw_uid;
|
||||||
|
gid_t group = passwd->pw_gid;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (fork() == 0) {
|
||||||
|
if (setsid() < 0)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
debug_printf("session leader...\n");
|
||||||
|
if (initgroups(login, group) == -1) {
|
||||||
|
debug_printf("1.ouch: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
//endgrent();
|
||||||
|
if (setgid(group) != 0) {
|
||||||
|
debug_printf("2.ouch: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (setuid(user) != 0) {
|
||||||
|
debug_printf("3.ouch: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: This leaks the parent application
|
||||||
|
be_app = NULL;
|
||||||
|
|
||||||
|
// TODO: take over system jobs, and reserve their names
|
||||||
|
status_t status;
|
||||||
|
LaunchDaemon* daemon = new LaunchDaemon(true, status);
|
||||||
|
if (status == B_OK)
|
||||||
|
daemon->Run();
|
||||||
|
|
||||||
|
delete daemon;
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
Lock();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LaunchDaemon::_RetrieveKernelOptions()
|
LaunchDaemon::_RetrieveKernelOptions()
|
||||||
{
|
{
|
||||||
@@ -834,16 +1021,8 @@ LaunchDaemon::_IsSafeMode() const
|
|||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
// TODO: remove this again
|
|
||||||
close(STDOUT_FILENO);
|
|
||||||
int fd = open("/dev/dprintf", O_WRONLY);
|
|
||||||
if (fd != STDOUT_FILENO)
|
|
||||||
dup2(fd, STDOUT_FILENO);
|
|
||||||
puts("launch_daemon is alive and kicking.");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
status_t status;
|
status_t status;
|
||||||
LaunchDaemon* daemon = new LaunchDaemon(status);
|
LaunchDaemon* daemon = new LaunchDaemon(false, status);
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
daemon->Run();
|
daemon->Run();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user