summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/hawk/lib/utils.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/hawk/lib/utils.js')
-rwxr-xr-xdeps/npm/node_modules/hawk/lib/utils.js163
1 files changed, 163 insertions, 0 deletions
diff --git a/deps/npm/node_modules/hawk/lib/utils.js b/deps/npm/node_modules/hawk/lib/utils.js
new file mode 100755
index 0000000000..8b192ace66
--- /dev/null
+++ b/deps/npm/node_modules/hawk/lib/utils.js
@@ -0,0 +1,163 @@
+// Load modules
+
+var Sntp = require('sntp');
+var Boom = require('boom');
+
+
+// Declare internals
+
+var internals = {};
+
+
+exports.version = function () {
+
+ return require('../package.json').version;
+};
+
+
+// Extract host and port from request
+
+// $1 $2
+internals.hostHeaderRegex = /^(?:(?:\r\n)?\s)*((?:[^:]+)|(?:\[[^\]]+\]))(?::(\d+))?(?:(?:\r\n)?\s)*$/; // (IPv4, hostname)|(IPv6)
+
+
+exports.parseHost = function (req, hostHeaderName) {
+
+ hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
+ var hostHeader = req.headers[hostHeaderName];
+ if (!hostHeader) {
+ return null;
+ }
+
+ var hostParts = hostHeader.match(internals.hostHeaderRegex);
+ if (!hostParts) {
+ return null;
+ }
+
+ return {
+ name: hostParts[1],
+ port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
+ };
+};
+
+
+// Parse Content-Type header content
+
+exports.parseContentType = function (header) {
+
+ if (!header) {
+ return '';
+ }
+
+ return header.split(';')[0].trim().toLowerCase();
+};
+
+
+// Convert node's to request configuration object
+
+exports.parseRequest = function (req, options) {
+
+ if (!req.headers) {
+ return req;
+ }
+
+ // Obtain host and port information
+
+ if (!options.host || !options.port) {
+ var host = exports.parseHost(req, options.hostHeaderName);
+ if (!host) {
+ return new Error('Invalid Host header');
+ }
+ }
+
+ var request = {
+ method: req.method,
+ url: req.url,
+ host: options.host || host.name,
+ port: options.port || host.port,
+ authorization: req.headers.authorization,
+ contentType: req.headers['content-type'] || ''
+ };
+
+ return request;
+};
+
+
+exports.now = function (localtimeOffsetMsec) {
+
+ return Sntp.now() + (localtimeOffsetMsec || 0);
+};
+
+
+exports.nowSecs = function (localtimeOffsetMsec) {
+
+ return Math.floor(exports.now(localtimeOffsetMsec) / 1000);
+};
+
+
+// Parse Hawk HTTP Authorization header
+
+exports.parseAuthorizationHeader = function (header, keys) {
+
+ keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
+
+ if (!header) {
+ return Boom.unauthorized(null, 'Hawk');
+ }
+
+ var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/); // Header: scheme[ something]
+ if (!headerParts) {
+ return Boom.badRequest('Invalid header syntax');
+ }
+
+ var scheme = headerParts[1];
+ if (scheme.toLowerCase() !== 'hawk') {
+ return Boom.unauthorized(null, 'Hawk');
+ }
+
+ var attributesString = headerParts[2];
+ if (!attributesString) {
+ return Boom.badRequest('Invalid header syntax');
+ }
+
+ var attributes = {};
+ var errorMessage = '';
+ var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
+
+ // Check valid attribute names
+
+ if (keys.indexOf($1) === -1) {
+ errorMessage = 'Unknown attribute: ' + $1;
+ return;
+ }
+
+ // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
+
+ if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
+ errorMessage = 'Bad attribute value: ' + $1;
+ return;
+ }
+
+ // Check for duplicates
+
+ if (attributes.hasOwnProperty($1)) {
+ errorMessage = 'Duplicate attribute: ' + $1;
+ return;
+ }
+
+ attributes[$1] = $2;
+ return '';
+ });
+
+ if (verify !== '') {
+ return Boom.badRequest(errorMessage || 'Bad header format');
+ }
+
+ return attributes;
+};
+
+
+exports.unauthorized = function (message, attributes) {
+
+ return Boom.unauthorized(message, 'Hawk', attributes);
+};