This commit is contained in:
Andris Reinman 2018-11-14 13:32:40 +02:00
parent 0b7588b960
commit b8f9c8882d
13 changed files with 99 additions and 33 deletions

26
api.js
View file

@ -14,6 +14,7 @@ const tools = require('./lib/tools');
const crypto = require('crypto');
const Gelf = require('gelf');
const os = require('os');
const util = require('util');
const usersRoutes = require('./lib/api/users');
const addressesRoutes = require('./lib/api/addresses');
@ -72,15 +73,22 @@ const serverOptions = {
};
Object.keys(req.params || {}).forEach(key => {
let value = (req.params[key] || '').toString().trim();
let value =
typeof req.params[key] === 'string'
? req.params[key]
: util
.inspect(req.params[key], false, 3)
.toString()
.trim();
if (!value) {
return;
}
if (['password'].includes(key)) {
value = '***';
} else if (value.length > 64) {
value = value.substr(0, 63) + '…';
} else if (value.length > 128) {
value = value.substr(0, 128) + '…';
}
if (key.length > 30) {
@ -95,10 +103,16 @@ const serverOptions = {
if (!body || !['id'].includes(key)) {
return;
}
value = (value || '').toString().trim();
value =
typeof value === 'string'
? value
: util
.inspect(value, false, 3)
.toString()
.trim();
if (value.length > 64) {
value = value.substr(0, 63) + '…';
if (value.length > 128) {
value = value.substr(0, 128) + '…';
}
if (key.length > 30) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
define({ "name": "wildduck", "version": "1.0.0", "description": "WildDuck API docs", "title": "WildDuck API", "url": "https://api.wildduck.email", "sampleUrl": false, "defaultVersion": "0.0.0", "apidoc": "0.3.0", "generator": { "name": "apidoc", "time": "2018-11-12T11:44:06.203Z", "url": "http://apidocjs.com", "version": "0.17.6" } });
define({ "name": "wildduck", "version": "1.0.0", "description": "WildDuck API docs", "title": "WildDuck API", "url": "https://api.wildduck.email", "sampleUrl": false, "defaultVersion": "0.0.0", "apidoc": "0.3.0", "generator": { "name": "apidoc", "time": "2018-11-14T11:21:41.763Z", "url": "http://apidocjs.com", "version": "0.17.6" } });

View file

@ -1 +1 @@
{ "name": "wildduck", "version": "1.0.0", "description": "WildDuck API docs", "title": "WildDuck API", "url": "https://api.wildduck.email", "sampleUrl": false, "defaultVersion": "0.0.0", "apidoc": "0.3.0", "generator": { "name": "apidoc", "time": "2018-11-12T11:44:06.203Z", "url": "http://apidocjs.com", "version": "0.17.6" } }
{ "name": "wildduck", "version": "1.0.0", "description": "WildDuck API docs", "title": "WildDuck API", "url": "https://api.wildduck.email", "sampleUrl": false, "defaultVersion": "0.0.0", "apidoc": "0.3.0", "generator": { "name": "apidoc", "time": "2018-11-14T11:21:41.763Z", "url": "http://apidocjs.com", "version": "0.17.6" } }

View file

@ -343,6 +343,7 @@ class IMAPConnection extends EventEmitter {
if (err && /SSL[23]*_GET_CLIENT_HELLO|ssl[23]*_read_bytes|ssl_bytes_to_cipher_list/i.test(err.message)) {
let message = err.message;
err.message = 'Failed to establish TLS session';
err.code = err.code || 'TLSError';
err.meta = {
protocol: 'imap',
stage: 'starttls',
@ -353,6 +354,7 @@ class IMAPConnection extends EventEmitter {
if (!err || !err.message) {
err = new Error('Socket closed unexpectedly');
err.code = 'SocketError';
err.meta = {
remoteAddress: this.remoteAddress
};

View file

@ -309,6 +309,7 @@ class IMAPServer extends EventEmitter {
if (err && /SSL[23]*_GET_CLIENT_HELLO|ssl[23]*_read_bytes|ssl_bytes_to_cipher_list/i.test(err.message)) {
let message = err.message;
err.message = 'Failed to establish TLS session';
err.code = err.code || 'TLSError';
err.meta = {
protocol: 'imap',
stage: 'connect',
@ -318,6 +319,7 @@ class IMAPServer extends EventEmitter {
}
if (!err || !err.message) {
err = new Error('Socket closed while initiating TLS');
err.code = 'SocketError';
err.report = false;
err.meta = {
protocol: 'imap',

View file

@ -113,6 +113,15 @@ indexes:
key:
user: 1
- collection: asps
type: users # index applies to users database
index:
name: entry_autoexpire
# autoremove log entries after expire seconds
expireAfterSeconds: 0
key:
expires: 1
# Indexes for the authentication log collection
- collection: authlog
type: users # index applies to users database

View file

@ -27,6 +27,7 @@ module.exports = (db, server, userHandler) => {
* }
*
* @apiParam {String} user ID of the User
* @apiParam {Boolean} [showAll=false] If not true then skips entries with a TTL set
*
* @apiSuccess {Boolean} success Indicates successful response
* @apiSuccess {Object[]} results Event listing
@ -81,6 +82,10 @@ module.exports = (db, server, userHandler) => {
.lowercase()
.length(24)
.required(),
showAll: Joi.boolean()
.truthy(['Y', 'true', 'yes', 'on', '1', 1])
.falsy(['N', 'false', 'no', 'off', '0', 0, ''])
.default(false),
sess: Joi.string().max(255),
ip: Joi.string().ip({
version: ['ipv4', 'ipv6'],
@ -88,6 +93,10 @@ module.exports = (db, server, userHandler) => {
})
});
if (req.query.showAll) {
req.params.showAll = req.query.showAll;
}
const result = Joi.validate(req.params, schema, {
abortEarly: false,
convert: true
@ -109,6 +118,7 @@ module.exports = (db, server, userHandler) => {
}
let user = new ObjectID(result.value.user);
let showAll = result.value.showAll;
let userData;
@ -163,16 +173,27 @@ module.exports = (db, server, userHandler) => {
res.json({
success: true,
results: asps.map(asp => ({
id: asp._id,
description: asp.description,
scopes: asp.scopes.includes('*') ? [...consts.SCOPES] : asp.scopes,
lastUse: {
time: asp.used || false,
event: asp.authEvent || false
},
created: asp.created
}))
results: asps
.filter(asp => {
if (showAll) {
return true;
}
if (asp.ttl) {
return false;
}
return true;
})
.map(asp => ({
id: asp._id,
description: asp.description,
scopes: asp.scopes.includes('*') ? [...consts.SCOPES] : asp.scopes,
lastUse: {
time: asp.used || false,
event: asp.authEvent || false
},
expires: asp.expires,
created: asp.created
}))
});
return next();
@ -307,6 +328,7 @@ module.exports = (db, server, userHandler) => {
time: aspData.used || false,
event: aspData.authEvent || false
},
expires: asp.expires,
created: aspData.created
});
@ -329,6 +351,7 @@ module.exports = (db, server, userHandler) => {
* @apiParam {String[]} scopes List of scopes this Password applies to. Special scope "*" indicates that this password can be used for any scope except "master"
* @apiParam {Boolean} [generateMobileconfig] If true then result contains a mobileconfig formatted file with account config
* @apiParam {String} [address] E-mail address to be used as the account address in mobileconfig file. Must be one of the listed identity addresses of the user. Defaults to the main address of the user
* @apiParam {Number} [ttl] TTL in seconds for this password. Every time password is used, TTL is reset to this value
* @apiParam {String} [sess] Session identifier for the logs
* @apiParam {String} [ip] IP address for the logs
*
@ -392,6 +415,7 @@ module.exports = (db, server, userHandler) => {
.truthy(['Y', 'true', 'yes', 'on', '1', 1])
.falsy(['N', 'false', 'no', 'off', '0', 0, ''])
.default(false),
ttl: Joi.number().empty([0, '']),
sess: Joi.string().max(255),
ip: Joi.string().ip({
version: ['ipv4', 'ipv6'],

View file

@ -397,7 +397,7 @@ module.exports = (db, server, userHandler) => {
nextCursor: listing.hasNext ? listing.next : false,
results: (listing.results || []).map(resultData => {
let response = {
id: resultData._id
id: (resultData._id || '').toString()
};
Object.keys(resultData).forEach(key => {
if (!['_id', 'user'].includes(key)) {

View file

@ -102,6 +102,7 @@ class POP3Server extends EventEmitter {
if (err && /SSL[23]*_GET_CLIENT_HELLO|ssl[23]*_read_bytes|ssl_bytes_to_cipher_list/i.test(err.message)) {
let message = err.message;
err.message = 'Failed to establish TLS session';
err.code = err.code || 'TLSError';
err.meta = {
protocol: 'pop3',
stage: 'connect',
@ -112,6 +113,7 @@ class POP3Server extends EventEmitter {
if (!err || !err.message) {
err = new Error('Socket closed while initiating TLS');
err.code = 'SocketError';
err.meta = {
protocol: 'pop3',
stage: 'connect',

View file

@ -835,16 +835,23 @@ class UserHandler {
if (err) {
// don't really care
}
let aspUpdates = {
used: new Date(),
authEvent,
authIp: meta.ip
};
if (asp.ttl) {
// extend temporary password ttl every time it is used
aspUpdates.expires = new Date(Date.now() + asp.ttl * 1000);
}
this.users.collection('asps').findOneAndUpdate(
{
_id: asp._id
},
{
$set: {
used: new Date(),
authEvent,
authIp: meta.ip
}
$set: aspUpdates
},
() => {
authSuccess(
@ -1063,6 +1070,11 @@ class UserHandler {
created: new Date()
};
if (data.ttl) {
passwordData.ttl = data.ttl;
passwordData.expires = new Date(Date.now() + data.ttl * 1000);
}
// register this address as the default address for that user
return this.users.collection('users').findOne(
{
@ -1095,6 +1107,7 @@ class UserHandler {
action: 'create asp',
asp: passwordData._id,
aname: passwordData.description,
temporary: passwordData.ttl ? true : false,
result: 'success',
sess: data.sess,
ip: data.ip

View file

@ -1,6 +1,6 @@
{
"name": "wildduck",
"version": "1.10.9",
"version": "1.10.10",
"description": "IMAP/POP3 server built with Node.js and MongoDB",
"main": "server.js",
"scripts": {
@ -17,12 +17,12 @@
"license": "EUPL-1.1+",
"devDependencies": {
"ajv": "6.5.5",
"apidoc": "0.17.6",
"apidoc": "0.17.7",
"browserbox": "0.9.1",
"chai": "4.2.0",
"eslint": "5.8.0",
"eslint": "5.9.0",
"eslint-config-nodemailer": "1.2.0",
"eslint-config-prettier": "3.1.0",
"eslint-config-prettier": "3.3.0",
"grunt": "1.0.3",
"grunt-cli": "1.3.2",
"grunt-eslint": "21.0.0",
@ -30,7 +30,7 @@
"grunt-shell-spawn": "0.3.10",
"grunt-wait": "0.3.0",
"icedfrisby": "1.5.0",
"mailparser": "2.4.0",
"mailparser": "2.4.2",
"markdown-toc": "1.2.0",
"mocha": "5.2.0",
"request": "2.88.0"
@ -50,13 +50,13 @@
"ioredfour": "1.0.2-ioredis-02",
"ioredis": "4.2.0",
"isemail": "3.2.0",
"joi": "14.0.4",
"joi": "14.0.6",
"js-yaml": "3.12.0",
"key-fingerprint": "1.1.0",
"libbase64": "1.0.3",
"libmime": "4.0.1",
"libqp": "1.1.0",
"mailsplit": "4.2.3",
"mailsplit": "4.2.4",
"mobileconfig": "2.1.0",
"mongo-cursor-pagination": "7.1.0",
"mongodb": "3.1.9",