passenger 4.0.7 → 4.0.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data.tar.gz.asc +7 -7
- data/CONTRIBUTORS +2 -0
- data/NEWS +15 -0
- data/build/agents.rb +1 -0
- data/build/misc.rb +2 -0
- data/doc/Users guide Nginx.html +1 -0
- data/doc/Users guide Nginx.txt +1 -0
- data/ext/apache2/Hooks.cpp +2 -1
- data/ext/common/Account.h +8 -14
- data/ext/common/AccountsDatabase.h +0 -4
- data/ext/common/ApplicationPool2/Implementation.cpp +4 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/MessageServer.h +30 -1
- data/ext/common/ResourceLocator.h +4 -0
- data/ext/common/ServerInstanceDir.h +48 -2
- data/ext/common/agents/HelperAgent/Main.cpp +5 -5
- data/ext/common/agents/LoggingAgent/AdminController.h +16 -11
- data/ext/common/agents/LoggingAgent/LoggingServer.h +1 -1
- data/ext/common/agents/LoggingAgent/Main.cpp +231 -180
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/common_library.rb +0 -9
- data/lib/phusion_passenger/message_client.rb +1 -0
- data/lib/phusion_passenger/preloader_shared_helpers.rb +4 -1
- metadata +2 -3
- metadata.gz.asc +7 -7
- data/ext/common/AccountsDatabase.cpp +0 -81
data.tar.gz.asc
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
|
3
3
|
Comment: GPGTools - http://gpgtools.org
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJR28iYAAoJECrHRaUKISqMPf4IAIGf9BCAw6AwVnoumKhaWkim
|
6
|
+
k+hKA1kkPofS9Q7DZPEA5sizgSB1RCW8clalOF5Wb+kCn3KNwfluBENw2Bl974+A
|
7
|
+
HubjUnT58//z4bNqx7cEjBxfVWrs8VwINd8nbtEnjVaZG9Xkh+zinGsBwVbvgBE/
|
8
|
+
kwwklTV25qOPV3E9eLvWprB4i6lZEVCpsgJzn6HHz+mOxy9OS2VEGJQKZcCLU4WD
|
9
|
+
EWiinu8mJmKWGDHAigzNs6xFCfR9i8tRp56y9p5nQrxDqAhYaGdcwPPvD2iNabgh
|
10
|
+
dtnid9XFZeEOG5PtNktJ8P/2VX3ziFKnsvq5qYQMrV/lVQdBDeZDlcTfTHBDgqw=
|
11
|
+
=V08b
|
12
12
|
-----END PGP SIGNATURE-----
|
data/CONTRIBUTORS
CHANGED
@@ -22,6 +22,7 @@ Erik Ogan
|
|
22
22
|
Evan Phoenix
|
23
23
|
Gaspard Bucher
|
24
24
|
Goffert van Gool
|
25
|
+
Gokulnath Manakkattil
|
25
26
|
Gregory Potamianos
|
26
27
|
Hongli Lai (Phusion)
|
27
28
|
Ian Ehlert
|
@@ -56,6 +57,7 @@ Philip M. Gollucci
|
|
56
57
|
Redmar Kerkhoff
|
57
58
|
remi
|
58
59
|
Robin Bowes
|
60
|
+
Ryan Schwartz
|
59
61
|
Ryo Onodera
|
60
62
|
Saimon Moore
|
61
63
|
Sam Pohlenz
|
data/NEWS
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
Release 4.0.8
|
2
|
+
-------------
|
3
|
+
|
4
|
+
* Fixed a problem with graceful web server restarts. When you gracefully
|
5
|
+
restart the web server, it would cause Phusion Passenger internal sockets
|
6
|
+
to be deleted, thus causing Phusion Passenger to go down. This problem
|
7
|
+
was introduced in 4.0.6 during the attempt to fix issue #910.
|
8
|
+
* The PassengerRestartDir/passenger_restart_dir now accepts relative
|
9
|
+
filenames again, just like in Phusion Passenger 3.x. Patch
|
10
|
+
contributed by Ryan Schwartz.
|
11
|
+
* Documentation updates contributed by Gokulnath Manakkattil.
|
12
|
+
* [Enterprise] Fixed a license key checking issue on some operating systems,
|
13
|
+
such as CentOS 6.
|
14
|
+
|
15
|
+
|
1
16
|
Release 4.0.7
|
2
17
|
-------------
|
3
18
|
|
data/build/agents.rb
CHANGED
@@ -112,6 +112,7 @@ logging_agent_libs = COMMON_LIBRARY.only(:base, :logging_agent, 'AgentsBase.o',
|
|
112
112
|
'Utils/Base64.o', 'Utils/MD5.o')
|
113
113
|
dependencies = [
|
114
114
|
'ext/common/agents/LoggingAgent/Main.cpp',
|
115
|
+
'ext/common/agents/LoggingAgent/AdminController.h',
|
115
116
|
'ext/common/agents/LoggingAgent/LoggingServer.h',
|
116
117
|
'ext/common/agents/LoggingAgent/RemoteSender.h',
|
117
118
|
'ext/common/agents/LoggingAgent/DataStoreId.h',
|
data/build/misc.rb
CHANGED
@@ -166,6 +166,8 @@ task :contributors do
|
|
166
166
|
entries.push "Ninh Bui (Phusion)"
|
167
167
|
entries.delete "Tinco Andringa"
|
168
168
|
entries.push "Tinco Andringa (Phusion)"
|
169
|
+
entries.delete "Gokulnath"
|
170
|
+
entries.push "Gokulnath Manakkattil"
|
169
171
|
File.open("CONTRIBUTORS", "w") do |f|
|
170
172
|
f.puts(entries.sort{ |a, b| a.downcase <=> b.downcase }.join("\n"))
|
171
173
|
end
|
data/doc/Users guide Nginx.html
CHANGED
@@ -2886,6 +2886,7 @@ In an <em>if</em> configuration scope.
|
|
2886
2886
|
# The web app under www.bar.com/blog will use JRuby 1.7.1
|
2887
2887
|
passenger_base_uri /blog;
|
2888
2888
|
location /blog {
|
2889
|
+
passenger_enabled on;
|
2889
2890
|
passenger_ruby /usr/local/rvm/wrappers/jruby-1.7.1/ruby;
|
2890
2891
|
}
|
2891
2892
|
}
|
data/doc/Users guide Nginx.txt
CHANGED
data/ext/apache2/Hooks.cpp
CHANGED
@@ -278,7 +278,8 @@ private:
|
|
278
278
|
|
279
279
|
if (!connected) {
|
280
280
|
UPDATE_TRACE_POINT();
|
281
|
-
throw IOException("Cannot connect to the helper agent"
|
281
|
+
throw IOException("Cannot connect to the helper agent at " +
|
282
|
+
agentsStarter.getRequestSocketFilename());
|
282
283
|
}
|
283
284
|
} else {
|
284
285
|
throw;
|
data/ext/common/Account.h
CHANGED
@@ -62,16 +62,12 @@ public:
|
|
62
62
|
ALL = ~0,
|
63
63
|
NONE = 0,
|
64
64
|
|
65
|
-
//
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
INSPECT_BASIC_INFO = 1 << 5,
|
72
|
-
INSPECT_SENSITIVE_INFO = 1 << 6,
|
73
|
-
//INSPECT_BACKEND_ADDRESSES = 1 << 6,
|
74
|
-
//INSPECT_DETACH_KEYS = 1 << 7,
|
65
|
+
// HelperAgent ApplicationPool rights.
|
66
|
+
CLEAR = 1 << 0,
|
67
|
+
DETACH = 1 << 1,
|
68
|
+
SET_PARAMETERS = 1 << 2,
|
69
|
+
INSPECT_BASIC_INFO = 1 << 3,
|
70
|
+
INSPECT_SENSITIVE_INFO = 1 << 4,
|
75
71
|
|
76
72
|
// HelperAgent admin rights.
|
77
73
|
INSPECT_REQUESTS = 1 << 8,
|
@@ -103,14 +99,10 @@ public:
|
|
103
99
|
} else if (*it == "none") {
|
104
100
|
result = NONE;
|
105
101
|
|
106
|
-
} else if (*it == "get") {
|
107
|
-
result |= GET;
|
108
102
|
} else if (*it == "clear") {
|
109
103
|
result |= CLEAR;
|
110
104
|
} else if (*it == "detach") {
|
111
105
|
result |= DETACH;
|
112
|
-
} else if (*it == "get_parameters") {
|
113
|
-
result |= GET_PARAMETERS;
|
114
106
|
} else if (*it == "set_parameters") {
|
115
107
|
result |= SET_PARAMETERS;
|
116
108
|
} else if (*it == "inspect_basic_info") {
|
@@ -118,6 +110,8 @@ public:
|
|
118
110
|
} else if (*it == "inspect_sensitive_info") {
|
119
111
|
result |= INSPECT_SENSITIVE_INFO;
|
120
112
|
|
113
|
+
} else if (*it == "inspect_requests") {
|
114
|
+
result |= INSPECT_REQUESTS;
|
121
115
|
} else if (*it == "inspect_backtraces") {
|
122
116
|
result |= INSPECT_BACKTRACES;
|
123
117
|
|
@@ -51,10 +51,6 @@ private:
|
|
51
51
|
unsigned int uniqueNumber;
|
52
52
|
|
53
53
|
public:
|
54
|
-
static AccountsDatabasePtr createDefault(const ServerInstanceDir::GenerationPtr &generation,
|
55
|
-
bool userSwitching, const string &defaultUser,
|
56
|
-
const string &defaultGroup);
|
57
|
-
|
58
54
|
AccountsDatabase() {
|
59
55
|
uniqueNumber = 0;
|
60
56
|
}
|
@@ -339,9 +339,12 @@ Group::Group(const SuperGroupPtr &_superGroup, const Options &options, const Com
|
|
339
339
|
if (options.restartDir.empty()) {
|
340
340
|
restartFile = options.appRoot + "/tmp/restart.txt";
|
341
341
|
alwaysRestartFile = options.appRoot + "/always_restart.txt";
|
342
|
-
} else {
|
342
|
+
} else if (options.restartDir[0] == '/') {
|
343
343
|
restartFile = options.restartDir + "/restart.txt";
|
344
344
|
alwaysRestartFile = options.restartDir + "/always_restart.txt";
|
345
|
+
} else {
|
346
|
+
restartFile = options.appRoot + "/" + options.restartDir + "/restart.txt";
|
347
|
+
alwaysRestartFile = options.appRoot + "/" + options.restartDir + "/always_restart.txt";
|
345
348
|
}
|
346
349
|
resetOptions(options);
|
347
350
|
|
data/ext/common/Constants.h
CHANGED
data/ext/common/MessageServer.h
CHANGED
@@ -205,9 +205,18 @@ public:
|
|
205
205
|
writeArrayMessage(fd, "SecurityException", "Insufficient rights to execute this command.", NULL);
|
206
206
|
throw SecurityException("Insufficient rights to execute this command.");
|
207
207
|
} else {
|
208
|
-
|
208
|
+
passSecurity();
|
209
209
|
}
|
210
210
|
}
|
211
|
+
|
212
|
+
/** Announce to the client that it has passed the security checks.
|
213
|
+
*
|
214
|
+
* @throws SystemException Something went wrong while communicating with the client.
|
215
|
+
* @throws boost::thread_interrupted
|
216
|
+
*/
|
217
|
+
void passSecurity() {
|
218
|
+
writeArrayMessage(fd, "Passed security", NULL);
|
219
|
+
}
|
211
220
|
};
|
212
221
|
|
213
222
|
/**
|
@@ -218,6 +227,26 @@ public:
|
|
218
227
|
* client is closed.
|
219
228
|
*/
|
220
229
|
class Handler {
|
230
|
+
protected:
|
231
|
+
/** Utility function for checking whether the command name equals `command`,
|
232
|
+
* and whether it has exactly `nargs` arguments (excluding command name).
|
233
|
+
*/
|
234
|
+
bool isCommand(const vector<string> &args, const string &command,
|
235
|
+
unsigned int nargs = 0) const
|
236
|
+
{
|
237
|
+
return args.size() == nargs + 1 && args[0] == command;
|
238
|
+
}
|
239
|
+
|
240
|
+
/** Utility function for checking whether the command name equals `command`,
|
241
|
+
* and whether it has at least `minargs` and at most `maxargs` arguments
|
242
|
+
* (excluding command name), inclusive.
|
243
|
+
*/
|
244
|
+
bool isCommand(const vector<string> &args, const string &command,
|
245
|
+
unsigned int minargs, unsigned int maxargs) const
|
246
|
+
{
|
247
|
+
return args.size() >= minargs + 1 && args.size() <= maxargs + 1 && args[0] == command;
|
248
|
+
}
|
249
|
+
|
221
250
|
public:
|
222
251
|
virtual ~Handler() { }
|
223
252
|
|
@@ -25,6 +25,7 @@
|
|
25
25
|
#ifndef _PASSENGER_RESOURCE_LOCATOR_H_
|
26
26
|
#define _PASSENGER_RESOURCE_LOCATOR_H_
|
27
27
|
|
28
|
+
#include <boost/shared_ptr.hpp>
|
28
29
|
#include <string>
|
29
30
|
#include <Exceptions.h>
|
30
31
|
#include <Utils.h>
|
@@ -32,6 +33,7 @@
|
|
32
33
|
|
33
34
|
namespace Passenger {
|
34
35
|
|
36
|
+
using namespace std;
|
35
37
|
using namespace boost;
|
36
38
|
|
37
39
|
|
@@ -108,6 +110,8 @@ public:
|
|
108
110
|
}
|
109
111
|
};
|
110
112
|
|
113
|
+
typedef shared_ptr<ResourceLocator> ResourceLocatorPtr;
|
114
|
+
|
111
115
|
|
112
116
|
}
|
113
117
|
|
@@ -40,6 +40,7 @@
|
|
40
40
|
#include <string>
|
41
41
|
|
42
42
|
#include <Constants.h>
|
43
|
+
#include <Logging.h>
|
43
44
|
#include <Exceptions.h>
|
44
45
|
#include <Utils.h>
|
45
46
|
#include <Utils/StrIntUtils.h>
|
@@ -49,6 +50,15 @@ namespace Passenger {
|
|
49
50
|
using namespace std;
|
50
51
|
using namespace boost;
|
51
52
|
|
53
|
+
/* TODO: I think we should move away from generation dirs in the future.
|
54
|
+
* That way we can become immune to existing-directory-in-tmp denial of
|
55
|
+
* service attacks. To achieve the same functionality as we do now, each
|
56
|
+
* server instance directory is tagged with the control process's PID
|
57
|
+
* and a creation timestamp. passenger-status should treat the server instance
|
58
|
+
* directory with the most recent creation timestamp as the one to query.
|
59
|
+
* For now, the current code does not lead to an exploit.
|
60
|
+
*/
|
61
|
+
|
52
62
|
class ServerInstanceDir: public noncopyable {
|
53
63
|
public:
|
54
64
|
class Generation: public noncopyable {
|
@@ -221,8 +231,7 @@ private:
|
|
221
231
|
createDirectory(path);
|
222
232
|
break;
|
223
233
|
case FT_DIRECTORY:
|
224
|
-
|
225
|
-
createDirectory(path);
|
234
|
+
verifyDirectoryPermissions(path);
|
226
235
|
break;
|
227
236
|
default:
|
228
237
|
throw RuntimeException("'" + path + "' already exists, and is not a directory");
|
@@ -242,6 +251,43 @@ private:
|
|
242
251
|
throw FileSystemException("Cannot create server instance directory '" +
|
243
252
|
path + "'", e, path);
|
244
253
|
}
|
254
|
+
// verifyDirectoryPermissions() checks for the owner/group so we must make
|
255
|
+
// sure the server instance directory has that owner/group, even when the
|
256
|
+
// parent directory has setgid on.
|
257
|
+
if (chown(path.c_str(), geteuid(), getegid()) == -1) {
|
258
|
+
int e = errno;
|
259
|
+
throw FileSystemException("Cannot change the permissions of the server "
|
260
|
+
"instance directory '" + path + "'", e, path);
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
/**
|
265
|
+
* When reusing an existing server instance directory, check permissions
|
266
|
+
* so that an attacker cannot pre-create a directory with too liberal
|
267
|
+
* permissions.
|
268
|
+
*/
|
269
|
+
void verifyDirectoryPermissions(const string &path) {
|
270
|
+
TRACE_POINT();
|
271
|
+
struct stat buf;
|
272
|
+
|
273
|
+
if (stat(path.c_str(), &buf) == -1) {
|
274
|
+
int e = errno;
|
275
|
+
throw FileSystemException("Cannot stat() " + path, e, path);
|
276
|
+
} else if (buf.st_mode != (S_IFDIR | parseModeString("u=rwx,g=rx,o=rx"))) {
|
277
|
+
throw RuntimeException("Tried to reuse existing server instance directory " +
|
278
|
+
path + ", but it has wrong permissions");
|
279
|
+
} else if (buf.st_uid != geteuid() || buf.st_gid != getegid()) {
|
280
|
+
/* The server instance directory is always created by the Watchdog. Its UID/GID never
|
281
|
+
* changes because:
|
282
|
+
* 1. Disabling user switching only lowers the privilege of the HelperAgent.
|
283
|
+
* 2. For the UID/GID to change, the web server must be completely restarted
|
284
|
+
* (not just graceful reload) so that the control process can change its UID/GID.
|
285
|
+
* This causes the PID to change, so that an entirely new server instance
|
286
|
+
* directory is created.
|
287
|
+
*/
|
288
|
+
throw RuntimeException("Tried to reuse existing server instance directory " +
|
289
|
+
path + ", but it has wrong owner and group");
|
290
|
+
}
|
245
291
|
}
|
246
292
|
|
247
293
|
bool isDirectory(const string &dir, struct dirent *entry) const {
|
@@ -181,17 +181,17 @@ public:
|
|
181
181
|
{
|
182
182
|
SpecificContext *specificContext = (SpecificContext *) _specificContext.get();
|
183
183
|
try {
|
184
|
-
if (args
|
184
|
+
if (isCommand(args, "detach_process", 1)) {
|
185
185
|
processDetachProcess(commonContext, specificContext, args);
|
186
|
-
} else if (args
|
186
|
+
} else if (isCommand(args, "detach_process_by_key", 1)) {
|
187
187
|
processDetachProcessByKey(commonContext, specificContext, args);
|
188
188
|
} else if (args[0] == "inspect") {
|
189
189
|
return processInspect(commonContext, specificContext, args);
|
190
|
-
} else if (args
|
190
|
+
} else if (isCommand(args, "toXml", 1)) {
|
191
191
|
processToXml(commonContext, specificContext, args);
|
192
|
-
} else if (args
|
192
|
+
} else if (isCommand(args, "backtraces", 0)) {
|
193
193
|
processBacktraces(commonContext, specificContext, args);
|
194
|
-
} else if (args
|
194
|
+
} else if (isCommand(args, "requests", 0)) {
|
195
195
|
processRequests(commonContext, specificContext, args);
|
196
196
|
} else {
|
197
197
|
return false;
|
@@ -44,26 +44,25 @@ private:
|
|
44
44
|
|
45
45
|
typedef MessageServer::CommonClientContext CommonClientContext;
|
46
46
|
|
47
|
-
|
47
|
+
LoggingServerPtr server;
|
48
48
|
|
49
49
|
|
50
50
|
/*********************************************
|
51
51
|
* Message handler methods
|
52
52
|
*********************************************/
|
53
53
|
|
54
|
-
void processStatus(CommonClientContext &commonContext, SpecificContext *specificContext,
|
54
|
+
void processStatus(CommonClientContext &commonContext, SpecificContext *specificContext,
|
55
|
+
const vector<string> &args)
|
56
|
+
{
|
55
57
|
TRACE_POINT();
|
58
|
+
commonContext.passSecurity();
|
56
59
|
stringstream stream;
|
57
60
|
server->dump(stream);
|
58
61
|
writeScalarMessage(commonContext.fd, stream.str());
|
59
62
|
}
|
60
63
|
|
61
|
-
bool isCommand(const vector<string> &args, const string &command, unsigned int nargs = 0) const {
|
62
|
-
return args.size() == nargs + 1 && args[0] == command;
|
63
|
-
}
|
64
|
-
|
65
64
|
public:
|
66
|
-
AdminController(const
|
65
|
+
AdminController(const LoggingServerPtr &server) {
|
67
66
|
this->server = server;
|
68
67
|
}
|
69
68
|
|
@@ -76,10 +75,16 @@ public:
|
|
76
75
|
const vector<string> &args)
|
77
76
|
{
|
78
77
|
SpecificContext *specificContext = (SpecificContext *) _specificContext.get();
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
try {
|
79
|
+
if (isCommand(args, "status", 0)) {
|
80
|
+
processStatus(commonContext, specificContext, args);
|
81
|
+
} else {
|
82
|
+
return false;
|
83
|
+
}
|
84
|
+
} catch (const SecurityException &) {
|
85
|
+
/* Client does not have enough rights to perform a certain action.
|
86
|
+
* It has already been notified of this; ignore exception and move on.
|
87
|
+
*/
|
83
88
|
}
|
84
89
|
return true;
|
85
90
|
}
|
@@ -1098,7 +1098,7 @@ public:
|
|
1098
1098
|
LoggingServer(struct ev_loop *loop,
|
1099
1099
|
FileDescriptor fd,
|
1100
1100
|
const AccountsDatabasePtr &accountsDatabase,
|
1101
|
-
const VariantMap &options = VariantMap()
|
1101
|
+
const VariantMap &options = VariantMap())
|
1102
1102
|
: EventedMessageServer(loop, fd, accountsDatabase),
|
1103
1103
|
remoteSender(
|
1104
1104
|
options.get("union_station_gateway_address", false, DEFAULT_UNION_STATION_GATEWAY_ADDRESS),
|
@@ -55,33 +55,128 @@ using namespace oxt;
|
|
55
55
|
using namespace Passenger;
|
56
56
|
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
static
|
58
|
+
/***** Agent options *****/
|
59
|
+
|
60
|
+
static VariantMap agentsOptions;
|
61
|
+
static string passengerRoot;
|
62
|
+
static string socketAddress;
|
63
|
+
static string adminSocketAddress;
|
64
|
+
static string password;
|
65
|
+
static string username;
|
66
|
+
static string groupname;
|
67
|
+
static string adminToolStatusPassword;
|
68
|
+
|
69
|
+
/***** Constants and working objects *****/
|
61
70
|
|
62
71
|
static const int MESSAGE_SERVER_THREAD_STACK_SIZE = 128 * 1024;
|
63
72
|
|
73
|
+
struct WorkingObjects {
|
74
|
+
ResourceLocatorPtr resourceLocator;
|
75
|
+
FileDescriptor serverSocketFd;
|
76
|
+
AccountsDatabasePtr adminAccountsDatabase;
|
77
|
+
MessageServerPtr adminServer;
|
78
|
+
shared_ptr<oxt::thread> adminServerThread;
|
79
|
+
AccountsDatabasePtr accountsDatabase;
|
80
|
+
LoggingServerPtr loggingServer;
|
64
81
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
// so let's try to force it.
|
71
|
-
loop = ev_default_loop(EVBACKEND_EPOLL);
|
72
|
-
if (loop == NULL) {
|
73
|
-
loop = ev_default_loop(EVBACKEND_KQUEUE);
|
82
|
+
~WorkingObjects() {
|
83
|
+
// Stop thread before destroying anything else.
|
84
|
+
if (adminServerThread != NULL) {
|
85
|
+
adminServerThread->interrupt_and_join();
|
86
|
+
}
|
74
87
|
}
|
75
|
-
|
76
|
-
|
88
|
+
};
|
89
|
+
|
90
|
+
static struct ev_loop *eventLoop = NULL;
|
91
|
+
static LoggingServer *loggingServer = NULL;
|
92
|
+
static int exitCode = 0;
|
93
|
+
|
94
|
+
|
95
|
+
/***** Functions *****/
|
96
|
+
|
97
|
+
void
|
98
|
+
feedbackFdBecameReadable(ev::io &watcher, int revents) {
|
99
|
+
/* This event indicates that the watchdog has been killed.
|
100
|
+
* In this case we'll kill all descendant
|
101
|
+
* processes and exit. There's no point in keeping this agent
|
102
|
+
* running because we can't detect when the web server exits,
|
103
|
+
* and because this agent doesn't own the server instance
|
104
|
+
* directory. As soon as passenger-status is run, the server
|
105
|
+
* instance directory will be cleaned up, making this agent's
|
106
|
+
* services inaccessible.
|
107
|
+
*/
|
108
|
+
syscalls::killpg(getpgrp(), SIGKILL);
|
109
|
+
_exit(2); // In case killpg() fails.
|
110
|
+
}
|
111
|
+
|
112
|
+
static string
|
113
|
+
myself() {
|
114
|
+
struct passwd *entry = getpwuid(geteuid());
|
115
|
+
if (entry != NULL) {
|
116
|
+
return entry->pw_name;
|
117
|
+
} else {
|
118
|
+
throw NonExistentUserException(string("The current user, UID ") +
|
119
|
+
toString(geteuid()) + ", doesn't have a corresponding " +
|
120
|
+
"entry in the system's user database. Please fix your " +
|
121
|
+
"system's user database first.");
|
77
122
|
}
|
78
|
-
|
79
|
-
|
123
|
+
}
|
124
|
+
|
125
|
+
static void
|
126
|
+
initializeBareEssentials(int argc, char *argv[]) {
|
127
|
+
agentsOptions = initializeAgent(argc, argv, "PassengerLoggingAgent");
|
128
|
+
curl_global_init(CURL_GLOBAL_ALL);
|
129
|
+
}
|
130
|
+
|
131
|
+
static string
|
132
|
+
findUnionStationGatewayCert(const ResourceLocator &locator,
|
133
|
+
const string &cert)
|
134
|
+
{
|
135
|
+
if (cert.empty()) {
|
136
|
+
return locator.getResourcesDir() + "/union_station_gateway.crt";
|
137
|
+
} else if (cert != "-") {
|
138
|
+
return cert;
|
80
139
|
} else {
|
81
|
-
return
|
140
|
+
return "";
|
82
141
|
}
|
83
142
|
}
|
84
143
|
|
144
|
+
static void
|
145
|
+
initializeOptions(WorkingObjects &wo) {
|
146
|
+
passengerRoot = agentsOptions.get("passenger_root");
|
147
|
+
socketAddress = agentsOptions.get("logging_agent_address");
|
148
|
+
adminSocketAddress = agentsOptions.get("logging_agent_admin_address");
|
149
|
+
password = agentsOptions.get("logging_agent_password");
|
150
|
+
username = agentsOptions.get("analytics_log_user", false, myself());
|
151
|
+
groupname = agentsOptions.get("analytics_log_group", false);
|
152
|
+
adminToolStatusPassword = agentsOptions.get("admin_tool_status_password");
|
153
|
+
|
154
|
+
wo.resourceLocator = make_shared<ResourceLocator>(passengerRoot);
|
155
|
+
agentsOptions.set("union_station_gateway_cert", findUnionStationGatewayCert(
|
156
|
+
*wo.resourceLocator, agentsOptions.get("union_station_gateway_cert", false)));
|
157
|
+
}
|
158
|
+
|
159
|
+
static void
|
160
|
+
initializePrivilegedWorkingObjects(WorkingObjects &wo) {
|
161
|
+
wo.serverSocketFd = createServer(socketAddress.c_str());
|
162
|
+
if (getSocketAddressType(socketAddress) == SAT_UNIX) {
|
163
|
+
int ret;
|
164
|
+
|
165
|
+
do {
|
166
|
+
ret = chmod(parseUnixSocketAddress(socketAddress).c_str(),
|
167
|
+
S_ISVTX |
|
168
|
+
S_IRUSR | S_IWUSR | S_IXUSR |
|
169
|
+
S_IRGRP | S_IWGRP | S_IXGRP |
|
170
|
+
S_IROTH | S_IWOTH | S_IXOTH);
|
171
|
+
} while (ret == -1 && errno == EINTR);
|
172
|
+
}
|
173
|
+
|
174
|
+
wo.adminAccountsDatabase = make_shared<AccountsDatabase>();
|
175
|
+
wo.adminAccountsDatabase->add("_passenger-status", adminToolStatusPassword, false);
|
176
|
+
wo.adminServer = make_shared<MessageServer>(parseUnixSocketAddress(adminSocketAddress),
|
177
|
+
wo.adminAccountsDatabase);
|
178
|
+
}
|
179
|
+
|
85
180
|
static void
|
86
181
|
lowerPrivilege(const string &username, const struct passwd *user, const struct group *group) {
|
87
182
|
int e;
|
@@ -108,24 +203,99 @@ lowerPrivilege(const string &username, const struct passwd *user, const struct g
|
|
108
203
|
}
|
109
204
|
}
|
110
205
|
|
111
|
-
void
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
206
|
+
static void
|
207
|
+
maybeLowerPrivilege() {
|
208
|
+
struct passwd *user;
|
209
|
+
struct group *group;
|
210
|
+
|
211
|
+
/* Sanity check user accounts. */
|
212
|
+
|
213
|
+
user = getpwnam(username.c_str());
|
214
|
+
if (user == NULL) {
|
215
|
+
throw NonExistentUserException(string("The configuration option ") +
|
216
|
+
"'PassengerAnalyticsLogUser' (Apache) or " +
|
217
|
+
"'passenger_analytics_log_user' (Nginx) was set to '" +
|
218
|
+
username + "', but this user doesn't exist. Please fix " +
|
219
|
+
"the configuration option.");
|
220
|
+
}
|
221
|
+
|
222
|
+
if (groupname.empty()) {
|
223
|
+
group = getgrgid(user->pw_gid);
|
224
|
+
if (group == NULL) {
|
225
|
+
throw NonExistentGroupException(string("The configuration option ") +
|
226
|
+
"'PassengerAnalyticsLogGroup' (Apache) or " +
|
227
|
+
"'passenger_analytics_log_group' (Nginx) wasn't set, " +
|
228
|
+
"so PassengerLoggingAgent tried to use the default group " +
|
229
|
+
"for user '" + username + "' - which is GID #" +
|
230
|
+
toString(user->pw_gid) + " - as the group for the analytics " +
|
231
|
+
"log dir, but this GID doesn't exist. " +
|
232
|
+
"You can solve this problem by explicitly " +
|
233
|
+
"setting PassengerAnalyticsLogGroup (Apache) or " +
|
234
|
+
"passenger_analytics_log_group (Nginx) to a group that " +
|
235
|
+
"does exist. In any case, it looks like your system's user " +
|
236
|
+
"database is broken; Phusion Passenger can work fine even " +
|
237
|
+
"with this broken user database, but you should still fix it.");
|
238
|
+
} else {
|
239
|
+
groupname = group->gr_name;
|
240
|
+
}
|
241
|
+
} else {
|
242
|
+
group = getgrnam(groupname.c_str());
|
243
|
+
if (group == NULL) {
|
244
|
+
throw NonExistentGroupException(string("The configuration option ") +
|
245
|
+
"'PassengerAnalyticsLogGroup' (Apache) or " +
|
246
|
+
"'passenger_analytics_log_group' (Nginx) was set to '" +
|
247
|
+
groupname + "', but this group doesn't exist. Please fix " +
|
248
|
+
"the configuration option.");
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
/* Now's a good time to lower the privilege. */
|
253
|
+
if (geteuid() == 0) {
|
254
|
+
lowerPrivilege(username, user, group);
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
static struct ev_loop *
|
259
|
+
createEventLoop() {
|
260
|
+
struct ev_loop *loop;
|
261
|
+
|
262
|
+
// libev doesn't like choosing epoll and kqueue because the author thinks they're broken,
|
263
|
+
// so let's try to force it.
|
264
|
+
loop = ev_default_loop(EVBACKEND_EPOLL);
|
265
|
+
if (loop == NULL) {
|
266
|
+
loop = ev_default_loop(EVBACKEND_KQUEUE);
|
267
|
+
}
|
268
|
+
if (loop == NULL) {
|
269
|
+
loop = ev_default_loop(0);
|
270
|
+
}
|
271
|
+
if (loop == NULL) {
|
272
|
+
throw RuntimeException("Cannot create an event loop");
|
273
|
+
} else {
|
274
|
+
return loop;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
static void
|
279
|
+
initializeUnprivilegedWorkingObjects(WorkingObjects &wo) {
|
280
|
+
eventLoop = createEventLoop();
|
281
|
+
wo.accountsDatabase = make_shared<AccountsDatabase>();
|
282
|
+
wo.accountsDatabase->add("logging", password, false);
|
283
|
+
|
284
|
+
wo.loggingServer = make_shared<LoggingServer>(eventLoop, wo.serverSocketFd,
|
285
|
+
wo.accountsDatabase, agentsOptions);
|
286
|
+
loggingServer = wo.loggingServer.get();
|
287
|
+
|
288
|
+
wo.adminServer->addHandler(make_shared<AdminController>(wo.loggingServer));
|
289
|
+
function<void ()> adminServerFunc = boost::bind(&MessageServer::mainLoop, wo.adminServer.get());
|
290
|
+
wo.adminServerThread = make_shared<oxt::thread>(
|
291
|
+
boost::bind(runAndPrintExceptions, adminServerFunc, true),
|
292
|
+
"AdminServer thread", MESSAGE_SERVER_THREAD_STACK_SIZE
|
293
|
+
);
|
124
294
|
}
|
125
295
|
|
126
296
|
void
|
127
297
|
caughtExitSignal(ev::sig &watcher, int revents) {
|
128
|
-
|
298
|
+
P_INFO("Caught signal, exiting...");
|
129
299
|
ev_break(eventLoop, EVBREAK_ONE);
|
130
300
|
/* We only consider the "exit" command to be a graceful way to shut down
|
131
301
|
* the logging agent, so upon receiving an exit signal we want to return
|
@@ -143,162 +313,43 @@ printInfo(ev::sig &watcher, int revents) {
|
|
143
313
|
cerr << "---------- End LoggingAgent status ----------\n";
|
144
314
|
}
|
145
315
|
|
146
|
-
static
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
} else if (cert != "-") {
|
166
|
-
return cert;
|
167
|
-
} else {
|
168
|
-
return "";
|
316
|
+
static void
|
317
|
+
runMainLoop(WorkingObjects &wo) {
|
318
|
+
ev::io feedbackFdWatcher(eventLoop);
|
319
|
+
ev::sig sigintWatcher(eventLoop);
|
320
|
+
ev::sig sigtermWatcher(eventLoop);
|
321
|
+
ev::sig sigquitWatcher(eventLoop);
|
322
|
+
|
323
|
+
sigintWatcher.set<&caughtExitSignal>();
|
324
|
+
sigintWatcher.start(SIGINT);
|
325
|
+
sigtermWatcher.set<&caughtExitSignal>();
|
326
|
+
sigtermWatcher.start(SIGTERM);
|
327
|
+
sigquitWatcher.set<&printInfo>();
|
328
|
+
sigquitWatcher.start(SIGQUIT);
|
329
|
+
|
330
|
+
P_WARN("PassengerLoggingAgent online, listening at " << socketAddress);
|
331
|
+
if (feedbackFdAvailable()) {
|
332
|
+
feedbackFdWatcher.set<&feedbackFdBecameReadable>();
|
333
|
+
feedbackFdWatcher.start(FEEDBACK_FD, ev::READ);
|
334
|
+
writeArrayMessage(FEEDBACK_FD, "initialized", NULL);
|
169
335
|
}
|
336
|
+
ev_run(eventLoop, 0);
|
170
337
|
}
|
171
338
|
|
172
339
|
int
|
173
340
|
main(int argc, char *argv[]) {
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
string adminSocketAddress = options.get("logging_agent_admin_address");
|
178
|
-
string password = options.get("logging_agent_password");
|
179
|
-
string username = options.get("analytics_log_user", false, myself());
|
180
|
-
string groupname = options.get("analytics_log_group", false);
|
181
|
-
string adminToolStatusPassword = options.get("admin_tool_status_password");
|
182
|
-
|
183
|
-
curl_global_init(CURL_GLOBAL_ALL);
|
184
|
-
|
341
|
+
initializeBareEssentials(argc, argv);
|
342
|
+
P_DEBUG("Starting PassengerLoggingAgent...");
|
343
|
+
|
185
344
|
try {
|
186
|
-
|
187
|
-
|
188
|
-
/* Create all the necessary objects and sockets... */
|
189
|
-
ResourceLocator resourceLocator(passengerRoot);
|
190
|
-
AccountsDatabasePtr accountsDatabase, adminAccountsDatabase;
|
191
|
-
FileDescriptor serverSocketFd;
|
192
|
-
struct passwd *user;
|
193
|
-
struct group *group;
|
194
|
-
int ret;
|
195
|
-
|
196
|
-
options.set("union_station_gateway_cert", findUnionStationGatewayCert(
|
197
|
-
resourceLocator, options.get("union_station_gateway_cert", false)));
|
198
|
-
|
199
|
-
eventLoop = createEventLoop();
|
200
|
-
accountsDatabase = make_shared<AccountsDatabase>();
|
201
|
-
adminAccountsDatabase = make_shared<AccountsDatabase>();
|
202
|
-
serverSocketFd = createServer(socketAddress.c_str());
|
203
|
-
if (getSocketAddressType(socketAddress) == SAT_UNIX) {
|
204
|
-
do {
|
205
|
-
ret = chmod(parseUnixSocketAddress(socketAddress).c_str(),
|
206
|
-
S_ISVTX |
|
207
|
-
S_IRUSR | S_IWUSR | S_IXUSR |
|
208
|
-
S_IRGRP | S_IWGRP | S_IXGRP |
|
209
|
-
S_IROTH | S_IWOTH | S_IXOTH);
|
210
|
-
} while (ret == -1 && errno == EINTR);
|
211
|
-
}
|
212
|
-
|
213
|
-
/* Sanity check user accounts. */
|
214
|
-
|
215
|
-
user = getpwnam(username.c_str());
|
216
|
-
if (user == NULL) {
|
217
|
-
throw NonExistentUserException(string("The configuration option ") +
|
218
|
-
"'PassengerAnalyticsLogUser' (Apache) or " +
|
219
|
-
"'passenger_analytics_log_user' (Nginx) was set to '" +
|
220
|
-
username + "', but this user doesn't exist. Please fix " +
|
221
|
-
"the configuration option.");
|
222
|
-
}
|
223
|
-
|
224
|
-
if (groupname.empty()) {
|
225
|
-
group = getgrgid(user->pw_gid);
|
226
|
-
if (group == NULL) {
|
227
|
-
throw NonExistentGroupException(string("The configuration option ") +
|
228
|
-
"'PassengerAnalyticsLogGroup' (Apache) or " +
|
229
|
-
"'passenger_analytics_log_group' (Nginx) wasn't set, " +
|
230
|
-
"so PassengerLoggingAgent tried to use the default group " +
|
231
|
-
"for user '" + username + "' - which is GID #" +
|
232
|
-
toString(user->pw_gid) + " - as the group for the analytics " +
|
233
|
-
"log dir, but this GID doesn't exist. " +
|
234
|
-
"You can solve this problem by explicitly " +
|
235
|
-
"setting PassengerAnalyticsLogGroup (Apache) or " +
|
236
|
-
"passenger_analytics_log_group (Nginx) to a group that " +
|
237
|
-
"does exist. In any case, it looks like your system's user " +
|
238
|
-
"database is broken; Phusion Passenger can work fine even " +
|
239
|
-
"with this broken user database, but you should still fix it.");
|
240
|
-
} else {
|
241
|
-
groupname = group->gr_name;
|
242
|
-
}
|
243
|
-
} else {
|
244
|
-
group = getgrnam(groupname.c_str());
|
245
|
-
if (group == NULL) {
|
246
|
-
throw NonExistentGroupException(string("The configuration option ") +
|
247
|
-
"'PassengerAnalyticsLogGroup' (Apache) or " +
|
248
|
-
"'passenger_analytics_log_group' (Nginx) was set to '" +
|
249
|
-
groupname + "', but this group doesn't exist. Please fix " +
|
250
|
-
"the configuration option.");
|
251
|
-
}
|
252
|
-
}
|
345
|
+
TRACE_POINT();
|
346
|
+
WorkingObjects wo;
|
253
347
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
/* Now's a good time to lower the privilege. */
|
260
|
-
if (geteuid() == 0) {
|
261
|
-
lowerPrivilege(username, user, group);
|
262
|
-
}
|
263
|
-
|
264
|
-
/* Now setup the actual logging server. */
|
265
|
-
accountsDatabase->add("logging", password, false);
|
266
|
-
LoggingServer server(eventLoop, serverSocketFd,
|
267
|
-
accountsDatabase, options);
|
268
|
-
loggingServer = &server;
|
269
|
-
|
270
|
-
/* Continue setting up the admin server. */
|
271
|
-
adminServer.addHandler(make_shared<AdminController>(&server));
|
272
|
-
function<void ()> adminServerFunc = boost::bind(&MessageServer::mainLoop, &adminServer);
|
273
|
-
oxt::thread adminServerThread(
|
274
|
-
boost::bind(runAndPrintExceptions, adminServerFunc, true),
|
275
|
-
"AdminServer thread", MESSAGE_SERVER_THREAD_STACK_SIZE
|
276
|
-
);
|
277
|
-
|
278
|
-
|
279
|
-
ev::io feedbackFdWatcher(eventLoop);
|
280
|
-
ev::sig sigintWatcher(eventLoop);
|
281
|
-
ev::sig sigtermWatcher(eventLoop);
|
282
|
-
ev::sig sigquitWatcher(eventLoop);
|
283
|
-
|
284
|
-
if (feedbackFdAvailable()) {
|
285
|
-
feedbackFdWatcher.set<&feedbackFdBecameReadable>();
|
286
|
-
feedbackFdWatcher.start(FEEDBACK_FD, ev::READ);
|
287
|
-
writeArrayMessage(FEEDBACK_FD, "initialized", NULL);
|
288
|
-
}
|
289
|
-
sigintWatcher.set<&caughtExitSignal>();
|
290
|
-
sigintWatcher.start(SIGINT);
|
291
|
-
sigtermWatcher.set<&caughtExitSignal>();
|
292
|
-
sigtermWatcher.start(SIGTERM);
|
293
|
-
sigquitWatcher.set<&printInfo>();
|
294
|
-
sigquitWatcher.start(SIGQUIT);
|
295
|
-
|
296
|
-
|
297
|
-
/********** Initialized! Enter main loop... **********/
|
298
|
-
|
299
|
-
P_WARN("PassengerLoggingAgent online, listening at " << socketAddress);
|
300
|
-
ev_run(eventLoop, 0);
|
301
|
-
adminServerThread.interrupt_and_join();
|
348
|
+
initializeOptions(wo);
|
349
|
+
initializePrivilegedWorkingObjects(wo);
|
350
|
+
maybeLowerPrivilege();
|
351
|
+
initializeUnprivilegedWorkingObjects(wo);
|
352
|
+
runMainLoop(wo);
|
302
353
|
P_DEBUG("Logging agent exiting with code " << exitCode << ".");
|
303
354
|
return exitCode;
|
304
355
|
} catch (const tracable_exception &e) {
|
data/lib/phusion_passenger.rb
CHANGED
@@ -30,7 +30,7 @@ module PhusionPassenger
|
|
30
30
|
|
31
31
|
PACKAGE_NAME = 'passenger'
|
32
32
|
# Run 'rake ext/common/Constants.h' after changing this number.
|
33
|
-
VERSION_STRING = '4.0.
|
33
|
+
VERSION_STRING = '4.0.8'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.4.1'
|
36
36
|
NGINX_SHA256_CHECKSUM = 'bca5d1e89751ba29406185e1736c390412603a7e6b604f5b4575281f6565d119'
|
@@ -394,15 +394,6 @@ COMMON_LIBRARY = CommonLibraryBuilder.new do
|
|
394
394
|
Utils/StrIntUtils.h
|
395
395
|
Utils/CachedFileStat.h
|
396
396
|
)
|
397
|
-
define_component 'AccountsDatabase.o',
|
398
|
-
:source => 'AccountsDatabase.cpp',
|
399
|
-
:category => :other,
|
400
|
-
:deps => %w(
|
401
|
-
AccountsDatabase.h
|
402
|
-
RandomGenerator.h
|
403
|
-
Constants.h
|
404
|
-
Utils.h
|
405
|
-
)
|
406
397
|
define_component 'AgentsStarter.o',
|
407
398
|
:source => 'AgentsStarter.cpp',
|
408
399
|
:category => :other,
|
@@ -108,7 +108,10 @@ module PreloaderSharedHelpers
|
|
108
108
|
puts "!> "
|
109
109
|
|
110
110
|
while true
|
111
|
-
|
111
|
+
# We call ::select just in case someone overwrites the global select()
|
112
|
+
# function by including ActionView::Helpers in the wrong place.
|
113
|
+
# https://code.google.com/p/phusion-passenger/issues/detail?id=915
|
114
|
+
ios = Kernel.select([server, STDIN])[0]
|
112
115
|
if ios.include?(server)
|
113
116
|
result, client = accept_and_process_next_client(server)
|
114
117
|
if result == :forked
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passenger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -285,7 +285,6 @@ files:
|
|
285
285
|
- helper-scripts/system-memory-stats.py
|
286
286
|
- helper-scripts/wsgi-loader.py
|
287
287
|
- helper-scripts/wsgi-preloader.py
|
288
|
-
- ext/common/AccountsDatabase.cpp
|
289
288
|
- ext/common/agents/Base.cpp
|
290
289
|
- ext/common/agents/HelperAgent/Main.cpp
|
291
290
|
- ext/common/agents/HelperAgent/RequestHandler.cpp
|
metadata.gz.asc
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
|
3
3
|
Comment: GPGTools - http://gpgtools.org
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJR28iYAAoJECrHRaUKISqMQI4H/07+WJ2+hUyYOccJ6FxrH/7e
|
6
|
+
59ofy0PbGFEctyrfH7+TilJixj+xzKqn9q75q7eBNX8bK8gGD8zX1AwvgILvUWby
|
7
|
+
OU23wRacnuhYbJrRK6aeftCDNDsoLpLGvfYBr05aUE72q4lUGuoE7A9Yc+1JVJPN
|
8
|
+
DEpwf5BhcF0MGCtTZtuujCMBpHP6Dc+i1Ty9vhNYI4lvZgRNEwwU5MDyjH0ZJeyL
|
9
|
+
pK8+h7zhLL4ryS+h+g3HXRjEcvkth2ANaK/UhB74pWpnbqTqyMazpsSSK4XypHgh
|
10
|
+
7ynPAf74eO8qfVZ1uPfwtm+53FXQIl5ix0MGg84osGJW3KUoyG1f5I1aUcAanZs=
|
11
|
+
=dSK/
|
12
12
|
-----END PGP SIGNATURE-----
|
@@ -1,81 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010 Phusion
|
4
|
-
*
|
5
|
-
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
-
*
|
7
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
-
* of this software and associated documentation files (the "Software"), to deal
|
9
|
-
* in the Software without restriction, including without limitation the rights
|
10
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
-
* copies of the Software, and to permit persons to whom the Software is
|
12
|
-
* furnished to do so, subject to the following conditions:
|
13
|
-
*
|
14
|
-
* The above copyright notice and this permission notice shall be included in
|
15
|
-
* all copies or substantial portions of the Software.
|
16
|
-
*
|
17
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
-
* THE SOFTWARE.
|
24
|
-
*/
|
25
|
-
|
26
|
-
#include <sys/types.h>
|
27
|
-
#include <sys/stat.h>
|
28
|
-
#include <unistd.h>
|
29
|
-
#include <pwd.h>
|
30
|
-
#include <grp.h>
|
31
|
-
#include "AccountsDatabase.h"
|
32
|
-
#include "RandomGenerator.h"
|
33
|
-
#include "Exceptions.h"
|
34
|
-
#include "Constants.h"
|
35
|
-
#include "Utils.h"
|
36
|
-
|
37
|
-
namespace Passenger {
|
38
|
-
|
39
|
-
AccountsDatabasePtr
|
40
|
-
AccountsDatabase::createDefault(const ServerInstanceDir::GenerationPtr &generation,
|
41
|
-
bool userSwitching, const string &defaultUser,
|
42
|
-
const string &defaultGroup)
|
43
|
-
{
|
44
|
-
AccountsDatabasePtr database(new AccountsDatabase());
|
45
|
-
struct passwd *defaultUserEntry;
|
46
|
-
struct group *defaultGroupEntry;
|
47
|
-
uid_t defaultUid;
|
48
|
-
gid_t defaultGid;
|
49
|
-
RandomGenerator random;
|
50
|
-
string passengerStatusPassword = random.generateByteString(MESSAGE_SERVER_MAX_PASSWORD_SIZE);
|
51
|
-
|
52
|
-
defaultUserEntry = getpwnam(defaultUser.c_str());
|
53
|
-
if (defaultUserEntry == NULL) {
|
54
|
-
throw NonExistentUserException("Default user '" + defaultUser +
|
55
|
-
"' does not exist.");
|
56
|
-
}
|
57
|
-
defaultUid = defaultUserEntry->pw_uid;
|
58
|
-
defaultGroupEntry = getgrnam(defaultGroup.c_str());
|
59
|
-
if (defaultGroupEntry == NULL) {
|
60
|
-
throw NonExistentGroupException("Default group '" + defaultGroup +
|
61
|
-
"' does not exist.");
|
62
|
-
}
|
63
|
-
defaultGid = defaultGroupEntry->gr_gid;
|
64
|
-
|
65
|
-
// An account for the 'passenger-status' command. Its password is only readable by
|
66
|
-
// root, or (if user switching is turned off) only by the web server's user.
|
67
|
-
database->add("_passenger-status", passengerStatusPassword, false,
|
68
|
-
Account::INSPECT_BASIC_INFO | Account::INSPECT_SENSITIVE_INFO |
|
69
|
-
Account::INSPECT_BACKTRACES);
|
70
|
-
if (geteuid() == 0 && !userSwitching) {
|
71
|
-
createFile(generation->getPath() + "/passenger-status-password.txt",
|
72
|
-
passengerStatusPassword, S_IRUSR, defaultUid, defaultGid);
|
73
|
-
} else {
|
74
|
-
createFile(generation->getPath() + "/passenger-status-password.txt",
|
75
|
-
passengerStatusPassword, S_IRUSR | S_IWUSR);
|
76
|
-
}
|
77
|
-
|
78
|
-
return database;
|
79
|
-
}
|
80
|
-
|
81
|
-
} // namespace Passenger
|