passenger 5.1.1 → 5.1.2

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.

Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +13 -0
  3. data/CONTRIBUTING.md +4 -8
  4. data/CONTRIBUTORS +1 -0
  5. data/INSTALL.md +1 -1
  6. data/README.md +2 -2
  7. data/build/misc.rb +1 -0
  8. data/build/packaging.rb +3 -3
  9. data/dev/ci/run_travis.sh +81 -20
  10. data/src/agent/Core/CoreMain.cpp +1 -1
  11. data/src/agent/Core/SecurityUpdateChecker.h +120 -3
  12. data/src/cxx_supportlib/Constants.h +2 -2
  13. data/src/cxx_supportlib/Crypto.cpp +14 -22
  14. data/src/cxx_supportlib/Crypto.h +1 -1
  15. data/src/cxx_supportlib/Utils/DateParsing.h +1 -1
  16. data/src/helper-scripts/node-loader.js +60 -59
  17. data/src/nodejs_supportlib/phusion_passenger/line_reader.js +9 -9
  18. data/src/nodejs_supportlib/phusion_passenger/log_express.js +3 -3
  19. data/src/nodejs_supportlib/phusion_passenger/log_mongodb.js +8 -9
  20. data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +10 -10
  21. data/src/nodejs_supportlib/phusion_passenger/ustrouter_connector.js +20 -18
  22. data/src/ruby_supportlib/phusion_passenger.rb +1 -1
  23. data/src/ruby_supportlib/phusion_passenger/admin_tools/memory_stats.rb +1 -1
  24. data/src/ruby_supportlib/phusion_passenger/config/install_standalone_runtime_command.rb +27 -7
  25. data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +15 -3
  26. data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
  27. data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +1 -1
  28. data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/libs.rb +4 -1
  29. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +16 -10
  30. metadata +2 -2
@@ -80,7 +80,7 @@
80
80
  #define PASSENGER_API_VERSION_MAJOR 0
81
81
  #define PASSENGER_API_VERSION_MINOR 3
82
82
  #define PASSENGER_DEFAULT_USER "nobody"
83
- #define PASSENGER_VERSION "5.1.1"
83
+ #define PASSENGER_VERSION "5.1.2"
84
84
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
85
85
  #define PROCESS_SHUTDOWN_TIMEOUT 60
86
86
  #define PROCESS_SHUTDOWN_TIMEOUT_DISPLAY "1 minute"
@@ -95,7 +95,7 @@
95
95
  #define SERVER_KIT_MAX_SERVER_ENDPOINTS 4
96
96
  #define SERVER_TOKEN_NAME "Phusion_Passenger"
97
97
  #define SHORT_PROGRAM_NAME "Passenger"
98
- #define SUPPORT_URL "https://www.phusionpassenger.com/documentation_and_support"
98
+ #define SUPPORT_URL "https://www.phusionpassenger.com/support"
99
99
  #define USER_NAMESPACE_DIRNAME ".passenger"
100
100
 
101
101
  #endif /* _PASSENGER_CONSTANTS_H_ */
@@ -56,29 +56,15 @@ Crypto::~Crypto() {
56
56
  CFDictionaryRef Crypto::createQueryDict(const char *label) {
57
57
  if (kSecClassIdentity != NULL) {
58
58
  const size_t size = 5L;
59
- CFTypeRef keys[size];
60
- CFTypeRef values[size];
61
- CFDictionaryRef queryDict;
62
- CFStringRef cfLabel = CFStringCreateWithCString(NULL, label,
63
- kCFStringEncodingUTF8);
64
-
65
- /* Set up our search criteria and expected results: */
66
- values[0] = kSecClassIdentity; /* we want a certificate and a key */
67
- keys[0] = kSecClass;
68
- values[1] = kCFBooleanTrue; /* we need a reference */
69
- keys[1] = kSecReturnRef;
70
- values[2] = kSecMatchLimitOne; /* one is enough, thanks */
71
- keys[2] = kSecMatchLimit;
72
- /* identity searches need a SecPolicyRef in order to work */
73
- values[3] = SecPolicyCreateSSL(false, NULL);
74
- keys[3] = kSecMatchPolicy;
75
- values[4] = cfLabel;
76
- keys[4] = kSecMatchSubjectWholeString;
77
- queryDict = CFDictionaryCreate(NULL, (const void **) keys,
78
- (const void **) values, size,
59
+ CFStringRef cfLabel = CFStringCreateWithCString(NULL, label, kCFStringEncodingUTF8);
60
+ SecPolicyRef policy = SecPolicyCreateSSL(false, NULL);
61
+ CFTypeRef keys[] = {kSecClass, kSecReturnRef, kSecMatchLimit, kSecMatchPolicy, kSecMatchSubjectWholeString};
62
+ CFTypeRef values[] = {kSecClassIdentity, kCFBooleanTrue, kSecMatchLimitOne, policy, cfLabel};
63
+
64
+ CFDictionaryRef queryDict = CFDictionaryCreate(NULL, keys, values, size,
79
65
  &kCFCopyStringDictionaryKeyCallBacks,
80
66
  &kCFTypeDictionaryValueCallBacks);
81
- CFRelease(values[3]);
67
+ CFRelease(policy);
82
68
  CFRelease(cfLabel);
83
69
 
84
70
  return queryDict;
@@ -114,6 +100,9 @@ OSStatus Crypto::copyIdentityFromPKCS12File(const char *cPath,
114
100
  const char *cPassword,
115
101
  const char *cLabel) {
116
102
  OSStatus status = errSecItemNotFound;
103
+ if (strlen(cPath) == 0) {
104
+ return errSecMissingValue;
105
+ }
117
106
  CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL,
118
107
  (const UInt8 *) cPath, strlen(cPath), false);
119
108
  CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
@@ -129,6 +118,9 @@ OSStatus Crypto::copyIdentityFromPKCS12File(const char *cPath,
129
118
  }
130
119
 
131
120
  SecAccessRef access = createAccess(cLabel);
121
+ if (access == NULL) {
122
+ return status;
123
+ }
132
124
  CFTypeRef cKeys[] = {kSecImportExportPassphrase, kSecImportExportAccess};
133
125
  CFTypeRef cValues[] = {password, access};
134
126
  CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, 2L, NULL, NULL);
@@ -242,7 +234,7 @@ bool Crypto::generateRandomChars(unsigned char *rndChars, int rndLen) {
242
234
  CFSTR("Have you tried turning it off and on again?") };
243
235
 
244
236
  CFErrorRef error = CFErrorCreateWithUserInfoKeysAndValues(NULL, kCFErrorDomainOSStatus, errNum, userInfoKeys, userInfoValues, numKeys);
245
- logFreeErrorExtended("SecVerifyTransformCreate", error);
237
+ logFreeErrorExtended("generateRandomChars failed", error);
246
238
  return false;
247
239
  }
248
240
  for (int i = 0; i < rndLen; i++) {
@@ -88,7 +88,6 @@ private:
88
88
  OSStatus copyIdentityFromPKCS12File(const char *cPath, const char *cPassword, const char *cLabel);
89
89
  CFDataRef genIV(size_t iv_size);
90
90
  bool getKeyBytes(SecKeyRef cryptokey, void **target, size_t &len);
91
- bool generateRandomChars(unsigned char *rndChars, int rndLen);
92
91
  bool memoryBridge(CFDataRef input, void **target, size_t &len);
93
92
  bool innerMemoryBridge(void *input, void **target, size_t len);
94
93
  #else
@@ -110,6 +109,7 @@ public:
110
109
  */
111
110
  bool preAuthKey(const char *path, const char *passwd, const char *cLabel);
112
111
  void killKey(const char *cLabel);
112
+ bool generateRandomChars(unsigned char *rndChars, int rndLen);
113
113
  #endif
114
114
 
115
115
  /**
@@ -84,7 +84,7 @@ parsedDateToTimestamp(struct tm &tm, int zone) {
84
84
  // tmUsingLocalTZ now contains tm interpreted as being in our local timezone instead of the intended UTC
85
85
  // Example: 10 UTC interpreted as 10 GMT+1 instead of 11 GMT+1
86
86
 
87
- #if !defined(sun) && !defined(__sun)
87
+ #if !defined(sun) && !defined(__sun) && !defined(BOOST_OS_MACOS)
88
88
  // tm_gmtoff = "seconds east of UTC", so the example 10 GMT+1 would now be corrected to (10+1) GMT+1
89
89
  timeUsingLocalTZ += tm.tm_gmtoff;
90
90
  #else
@@ -28,7 +28,6 @@ module.paths.unshift(__dirname + "/../src/nodejs_supportlib");
28
28
  var EventEmitter = require('events').EventEmitter;
29
29
  var os = require('os');
30
30
  var fs = require('fs');
31
- var net = require('net');
32
31
  var http = require('http');
33
32
  var util = require('util');
34
33
 
@@ -86,28 +85,30 @@ var vm = require('vm');
86
85
  var orig_func = vm.runInThisContext;
87
86
  vm.runInThisContext = function() {
88
87
  try {
89
- var scriptPath = arguments['1'];
90
- if (typeof scriptPath == 'object') {
91
- scriptPath = scriptPath['filename'];
92
- }
93
- if (scriptPath.indexOf('meteorhacks_cluster') != -1) {
94
- console.trace(badPackageError("Meteorhacks cluster package"));
95
- return (function() {
96
- Package['meteorhacks:cluster'] = {
97
- Cluster: {
98
- _publicServices : {},
99
- _registeredServices : {},
100
- _discoveryBackends : { mongodb: {} },
101
- connect : function(){return false;},
102
- allowPublicAccess : function(){return false;},
103
- discoverConnection : function(){return false;},
104
- register : function(){return false;},
105
- _isPublicService : function(){return false;},
106
- registerDiscoveryBackend : function(){return false;},
107
- _blockCallAgain : function(){return false;}
108
- }
109
- };
110
- });
88
+ if (arguments.length > 1) {
89
+ var scriptPath = arguments['1'];
90
+ if (typeof scriptPath == 'object') {
91
+ scriptPath = scriptPath['filename'];
92
+ }
93
+ if (scriptPath.indexOf('meteorhacks_cluster') != -1) {
94
+ console.trace(badPackageError("Meteorhacks cluster package"));
95
+ return (function() {
96
+ Package['meteorhacks:cluster'] = {
97
+ Cluster: {
98
+ _publicServices : {},
99
+ _registeredServices : {},
100
+ _discoveryBackends : { mongodb: {} },
101
+ connect : function(){return false;},
102
+ allowPublicAccess : function(){return false;},
103
+ discoverConnection : function(){return false;},
104
+ register : function(){return false;},
105
+ _isPublicService : function(){return false;},
106
+ registerDiscoveryBackend : function(){return false;},
107
+ _blockCallAgain : function(){return false;}
108
+ }
109
+ };
110
+ });
111
+ }
111
112
  }
112
113
  } catch (e) {
113
114
  meteorClusterErrCount++;
@@ -196,9 +197,9 @@ function setupEnvironment(options) {
196
197
  var logLevel = passengerToWinstonLogLevel(PhusionPassenger.options.log_level);
197
198
  var winston = require("vendor-copy/winston");
198
199
  var logger = new (winston.Logger)({
199
- transports: [
200
- new (winston.transports.Console)({ level: logLevel, debugStdout: true })
201
- ]
200
+ transports: [
201
+ new (winston.transports.Console)({ level: logLevel, debugStdout: true })
202
+ ]
202
203
  });
203
204
 
204
205
  process.title = 'Passenger NodeApp: ' + options.app_root;
@@ -300,6 +301,38 @@ function addListenerAtBeginning(emitter, event, callback) {
300
301
  }
301
302
  }
302
303
 
304
+ function doListen(server, listenTries, callback) {
305
+ function errorHandler(error) {
306
+ if (error.errno == 'EADDRINUSE') {
307
+ if (listenTries == 100) {
308
+ server.emit('error', new Error(
309
+ 'Phusion Passenger could not find suitable socket address to bind on'));
310
+ } else {
311
+ // Try again with another socket path.
312
+ listenTries++;
313
+ doListen(server, listenTries, callback);
314
+ }
315
+ } else {
316
+ server.emit('error', error);
317
+ }
318
+ }
319
+
320
+ var socketPath = PhusionPassenger.options.socket_path = generateServerSocketPath();
321
+ server.once('error', errorHandler);
322
+ server.originalListen(socketPath, function() {
323
+ server.removeListener('error', errorHandler);
324
+ doneListening(server, callback);
325
+ process.nextTick(finalizeStartup);
326
+ });
327
+ }
328
+
329
+ function doneListening(server, callback) {
330
+ if (callback) {
331
+ server.once('listening', callback);
332
+ }
333
+ server.emit('listening');
334
+ }
335
+
303
336
  function installServer() {
304
337
  var server = this;
305
338
  if (!PhusionPassenger._appInstalled) {
@@ -319,39 +352,7 @@ function installServer() {
319
352
  });
320
353
 
321
354
  var listenTries = 0;
322
- doListen(extractCallback(arguments));
323
-
324
- function doListen(callback) {
325
- function errorHandler(error) {
326
- if (error.errno == 'EADDRINUSE') {
327
- if (listenTries == 100) {
328
- server.emit('error', new Error(
329
- 'Phusion Passenger could not find suitable socket address to bind on'));
330
- } else {
331
- // Try again with another socket path.
332
- listenTries++;
333
- doListen(callback);
334
- }
335
- } else {
336
- server.emit('error', error);
337
- }
338
- }
339
-
340
- var socketPath = PhusionPassenger.options.socket_path = generateServerSocketPath();
341
- server.once('error', errorHandler);
342
- server.originalListen(socketPath, function() {
343
- server.removeListener('error', errorHandler);
344
- doneListening(callback);
345
- process.nextTick(finalizeStartup);
346
- });
347
- }
348
-
349
- function doneListening(callback) {
350
- if (callback) {
351
- server.once('listening', callback);
352
- }
353
- server.emit('listening');
354
- }
355
+ doListen(server, listenTries, extractCallback(arguments));
355
356
 
356
357
  return server;
357
358
  } else {
@@ -62,7 +62,7 @@ function LineReader(stream) {
62
62
  }
63
63
 
64
64
  function onData(data) {
65
- var index, line, callback;
65
+ var index, line;
66
66
 
67
67
  if (self.buffer == undefined) {
68
68
  // Already closed.
@@ -100,19 +100,19 @@ LineReader.prototype.close = function() {
100
100
  this._pause();
101
101
  this.buffer = undefined;
102
102
  this.lines = undefined;
103
- }
103
+ };
104
104
 
105
105
  LineReader.prototype.isClosed = function() {
106
106
  return this.buffer === undefined;
107
- }
107
+ };
108
108
 
109
109
  LineReader.prototype.endReached = function() {
110
110
  return this.eof;
111
- }
111
+ };
112
112
 
113
113
  LineReader.prototype.lineBufferIsFull = function() {
114
114
  return this.lines.length > 0;
115
- }
115
+ };
116
116
 
117
117
  LineReader.prototype.readLine = function(callback) {
118
118
  if (this.lines.length > 0) {
@@ -128,7 +128,7 @@ LineReader.prototype.readLine = function(callback) {
128
128
  } else {
129
129
  this.callbacks.push(callback);
130
130
  }
131
- }
131
+ };
132
132
 
133
133
  LineReader.prototype._autoPauseOrResume = function() {
134
134
  if (this.buffer != undefined) {
@@ -138,20 +138,20 @@ LineReader.prototype._autoPauseOrResume = function() {
138
138
  this._resume();
139
139
  }
140
140
  }
141
- }
141
+ };
142
142
 
143
143
  LineReader.prototype._pause = function() {
144
144
  if (!this.paused) {
145
145
  this.paused = true;
146
146
  this.stream.pause();
147
147
  }
148
- }
148
+ };
149
149
 
150
150
  LineReader.prototype._resume = function() {
151
151
  if (this.paused) {
152
152
  this.paused = false;
153
153
  this.stream.resume();
154
154
  }
155
- }
155
+ };
156
156
 
157
157
  exports.LineReader = LineReader;
@@ -67,11 +67,11 @@ exports.initPreLoad = function() {
67
67
  }
68
68
 
69
69
  return express.application.useOrig.apply(this, arguments);
70
- }
70
+ };
71
71
  } catch (e) {
72
72
  log.error("Unable to instrument Express due to error: " + e);
73
73
  }
74
- }
74
+ };
75
75
 
76
76
  exports.initPostLoad = function() {
77
77
  if (!express) {
@@ -86,7 +86,7 @@ exports.initPostLoad = function() {
86
86
  } catch (e) {
87
87
  log.error("Unable to instrument Express error flow due to error: " + e);
88
88
  }
89
- }
89
+ };
90
90
 
91
91
  function logRequest(req, res, next) {
92
92
  log.verbose("==== Instrumentation [Express] ==== REQUEST [" + req.method + " " + req.url + "] attach");
@@ -65,9 +65,8 @@ function instrumentCollectionMethod(origParent, functionName, newFn) {
65
65
  }
66
66
 
67
67
  function collectionFn(origArguments, databaseName, collectionName, functionName, originalFn) {
68
- var friendlyName = databaseName + "." + collectionName + "." + functionName + "(..)";
69
68
  var query = "";
70
- for (i = 0; i < origArguments.length; i++) {
69
+ for (var i = 0; i < origArguments.length; i++) {
71
70
  if (typeof(origArguments[i]) != 'function') { // mongoskin
72
71
  query += (i > 0 ? "," : "") + JSON.stringify(origArguments[i]);
73
72
  }
@@ -111,13 +110,13 @@ exports.initPreLoad = function() {
111
110
  wrapRepairCLSMongoskinUtils(appRoot);
112
111
 
113
112
  try {
114
- for (i = 0; i < collectionMethods.length; i++) {
113
+ for (var i = 0; i < collectionMethods.length; i++) {
115
114
  instrumentCollectionMethod(mongodb.Collection.prototype, collectionMethods[i], collectionFn);
116
115
  }
117
116
  } catch (e) {
118
117
  log.error("Unable to instrument MongoDB due to error: " + e);
119
118
  }
120
- }
119
+ };
121
120
 
122
121
  function wrapRepairCLSMongo14() {
123
122
  try {
@@ -139,7 +138,7 @@ function wrapRepairCLSMongo14() {
139
138
  } else {
140
139
  this._passenger_wrapped__executeQueryCommand.apply(this, arguments);
141
140
  }
142
- }
141
+ };
143
142
 
144
143
  mongodb.Db.prototype._passenger_wrapped__executeInsertCommand = mongodb.Db.prototype._executeInsertCommand;
145
144
  mongodb.Db.prototype._executeInsertCommand = function() {
@@ -154,7 +153,7 @@ function wrapRepairCLSMongo14() {
154
153
  } else {
155
154
  this._passenger_wrapped__executeInsertCommand.apply(this, arguments);
156
155
  }
157
- }
156
+ };
158
157
  log.verbose("Using MongoDB 1.4.x continuation-local-storage workaround");
159
158
  } catch (e) {
160
159
  log.error("Not using MongoDB continuation-local-storage workaround: " + e);
@@ -185,10 +184,10 @@ function wrapRepairCLSMongoskinUtils(appRoot) {
185
184
  skinClass.prototype.open = function(callback) {
186
185
  // Finally we can bind the callback so that when the emitter calls it, the cls is mapped correctly.
187
186
  return skinClass.prototype._passenger_wrapped_open.call(this, ustReporter.getCLSWrappedCallback(callback));
188
- }
187
+ };
189
188
 
190
189
  return skinClass;
191
- }
190
+ };
192
191
  log.verbose("Using mongoskin continuation-local-storage workaround");
193
192
  } catch (e) {
194
193
  log.error("Not using mongoskin continuation-local-storage workaround (probably an unsupported version): " + e);
@@ -199,5 +198,5 @@ exports.initPostLoad = function() {
199
198
  //if (!mongodb) {
200
199
  // return;
201
200
  //}
202
- }
201
+ };
203
202
 
@@ -45,14 +45,14 @@ var appRoot;
45
45
  */
46
46
  exports.getPassengerLogger = function() {
47
47
  return log;
48
- }
48
+ };
49
49
 
50
50
  /**
51
51
  * @return the application root path, needed for instrumenting an application's node modules.
52
52
  */
53
53
  exports.getApplicationRoot = function() {
54
54
  return appRoot;
55
- }
55
+ };
56
56
 
57
57
  /**
58
58
  * @return timestamp in microseconds to be used as the start or end timestamp for timed logging (monotonic clock, not wall clock).
@@ -60,7 +60,7 @@ exports.getApplicationRoot = function() {
60
60
  exports.nowTimestamp = function() {
61
61
  var secAndUsec = process.hrtime();
62
62
  return Math.round((secAndUsec[0] * 1e6) + (secAndUsec[1] / 1e3));
63
- }
63
+ };
64
64
 
65
65
  /**
66
66
  * All Activity logs will be dropped unless they are done after this method, from within an execution chain starting with the callback. So it is
@@ -102,28 +102,28 @@ exports.attachToRequest = function(request, response, callback) {
102
102
  } catch (e) {
103
103
  log.error("Dropping Union Station request log due to error:\n" + e.stack);
104
104
  }
105
- }
105
+ };
106
106
 
107
107
  /**
108
108
  * Log a timed block, described by activityName, with an optional message to display (e.g. in a mouseover).
109
109
  */
110
110
  exports.logTimedActivityGeneric = function(activityName, tBegin, tEnd, message) {
111
111
  logTimedActivity(activityName, tBegin, tEnd, "generic", message ? { "message": message } : undefined);
112
- }
112
+ };
113
113
 
114
114
  /**
115
115
  * Log a timed mongo database interaction block, described by activityName, with an optional query to display (e.g. in a mouseover).
116
116
  */
117
117
  exports.logTimedActivityMongo = function(activityName, tBegin, tEnd, query) {
118
118
  logTimedActivity(activityName, tBegin, tEnd, "mongo", query ? { "query": query } : undefined);
119
- }
119
+ };
120
120
 
121
121
  /**
122
122
  * Log a timed SQL database interaction block, described by activityName, with an optional query to display (e.g. in a mouseover).
123
123
  */
124
124
  exports.logTimedActivitySQL = function(activityName, tBegin, tEnd, query) {
125
125
  logTimedActivity(activityName, tBegin, tEnd, "sql", query ? { "query": query } : undefined);
126
- }
126
+ };
127
127
 
128
128
  /**
129
129
  * Internal, base for the public logTimedActivity...()
@@ -198,7 +198,7 @@ exports.logException = function(name, message, trace) {
198
198
  } catch (e) {
199
199
  log.error("Dropping Union Station exception log due to error:\n" + e.stack);
200
200
  }
201
- }
201
+ };
202
202
 
203
203
  /**
204
204
  * Get the current request transaction id necessary to append logs to it. This is normally done automatically, but some modules break automatic attachment
@@ -215,7 +215,7 @@ exports.getCurrentTxnId = getCurrentTxnId;
215
215
  */
216
216
  exports.getCLSWrappedCallback = function(origCallback) {
217
217
  return reqNamespace.bind(origCallback);
218
- }
218
+ };
219
219
 
220
220
  /**
221
221
  * For internal use. Called by Passenger loader, no need to call from anywhere else.
@@ -224,4 +224,4 @@ exports.init = function(logger, applicationRoot, ustLogger) {
224
224
  log = logger;
225
225
  appRoot = applicationRoot;
226
226
  ustLog = ustLogger;
227
- }
227
+ };