Skip to content

Commit

Permalink
Implemented privilege check for most of the WebDAV methods
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrienCastex committed May 22, 2017
1 parent c65658e commit e25fcbc
Show file tree
Hide file tree
Showing 17 changed files with 483 additions and 404 deletions.
2 changes: 2 additions & 0 deletions lib/server/MethodCallArgs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export declare class MethodCallArgs {
static create(server: WebDAVServer, request: http.IncomingMessage, response: http.ServerResponse, callback: (error: Error, mca: MethodCallArgs) => void): void;
requireCustomPrivilege(privileges: string | string[], resource: IResource, callback: () => void): void;
requirePrivilege(privileges: BasicPrivilege | BasicPrivilege[], resource: IResource, callback: () => void): void;
requireErCustomPrivilege(privileges: string | string[], resource: IResource, callback: (error: Error, can: boolean) => void): void;
requireErPrivilege(privileges: BasicPrivilege | BasicPrivilege[], resource: IResource, callback: (error: Error, can: boolean) => void): void;
askForAuthentication(checkForUser: boolean, callback: (error: Error) => void): void;
accept(regex: RegExp[]): number;
findHeader(name: string, defaultValue?: string): string;
Expand Down
6 changes: 6 additions & 0 deletions lib/server/MethodCallArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ var MethodCallArgs = (function () {
MethodCallArgs.prototype.requirePrivilege = function (privileges, resource, callback) {
this.requireCustomPrivilege(privileges, resource, callback);
};
MethodCallArgs.prototype.requireErCustomPrivilege = function (privileges, resource, callback) {
IPrivilegeManager_1.requirePrivilege(privileges, this, resource, callback);
};
MethodCallArgs.prototype.requireErPrivilege = function (privileges, resource, callback) {
this.requireErCustomPrivilege(privileges, resource, callback);
};
MethodCallArgs.prototype.askForAuthentication = function (checkForUser, callback) {
if (checkForUser && this.user !== null && !this.user.isDefaultUser) {
callback(new Error('Already authenticated'));
Expand Down
14 changes: 8 additions & 6 deletions lib/server/commands/Head.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ function default_1(arg, callback) {
callback();
return;
}
r.read(function (e, c) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
arg.requirePrivilege(['canRead'], r, function () {
r.read(function (e, c) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.MethodNotAllowed);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
callback();
});
});
});
}
Expand Down
40 changes: 21 additions & 19 deletions lib/server/commands/Lock.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,29 @@ function default_1(arg, callback) {
callback();
return;
}
r.setLock(lock_1, function (e) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.Locked);
arg.requirePrivilege(['canSetLock'], r, function () {
r.setLock(lock_1, function (e) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.Locked);
callback();
return;
}
var prop = XML_1.XML.createElement('D:prop', {
'xmlns:D': 'DAV:'
});
var activelock = prop.ele('D:lockdiscovery').ele('D:activelock');
activelock.ele('D:locktype').ele(type_1.value);
activelock.ele('D:lockscope').ele(type_1.value);
activelock.ele('D:locktoken').ele('D:href').add(lock_1.uuid);
activelock.ele('D:lockroot').add(arg.fullUri());
activelock.ele('D:depth').add('infinity');
activelock.ele('D:owner').add(owner_1);
activelock.ele('D:timeout').add('Second-' + lock_1.lockKind.timeout);
arg.response.setHeader('Lock-Token', lock_1.uuid);
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
arg.writeXML(prop);
callback();
return;
}
var prop = XML_1.XML.createElement('D:prop', {
'xmlns:D': 'DAV:'
});
var activelock = prop.ele('D:lockdiscovery').ele('D:activelock');
activelock.ele('D:locktype').ele(type_1.value);
activelock.ele('D:lockscope').ele(type_1.value);
activelock.ele('D:locktoken').ele('D:href').add(lock_1.uuid);
activelock.ele('D:lockroot').add(arg.fullUri());
activelock.ele('D:depth').add('infinity');
activelock.ele('D:owner').add(owner_1);
activelock.ele('D:timeout').add('Second-' + lock_1.lockKind.timeout);
arg.response.setHeader('Lock-Token', lock_1.uuid);
arg.setCode(WebDAVRequest_1.HTTPCodes.OK);
arg.writeXML(prop);
callback();
});
});
}
Expand Down
32 changes: 18 additions & 14 deletions lib/server/commands/Mkcol.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@ function default_1(arg, callback) {
callback();
return;
}
if (!r.fsManager) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
var resource = r.fsManager.newResource(arg.uri, path.basename(arg.uri), IResource_1.ResourceType.Directory, r);
resource.create(function (e) {
if (e) {
arg.requirePrivilege(['canAddChild'], r, function () {
if (!r.fsManager) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
r.addChild(resource, function (e) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.Created);
callback();
var resource = r.fsManager.newResource(arg.uri, path.basename(arg.uri), IResource_1.ResourceType.Directory, r);
arg.requirePrivilege(['canCreate'], resource, function () {
resource.create(function (e) {
if (e) {
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
callback();
return;
}
r.addChild(resource, function (e) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.Created);
callback();
});
});
});
});
});
Expand Down
36 changes: 20 additions & 16 deletions lib/server/commands/Move.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,27 @@ function default_1(arg, callback) {
callback();
return;
}
var override = arg.findHeader('overwrite') === 'T';
var destination = arg.findHeader('destination');
if (!destination) {
arg.setCode(WebDAVRequest_1.HTTPCodes.BadRequest);
callback();
return;
}
destination = destination.substring(destination.indexOf('://') + '://'.length);
destination = destination.substring(destination.indexOf('/'));
destination = new FSManager_1.FSPath(destination);
arg.server.getResourceFromPath(destination.getParent(), function (e, rDest) {
r.moveTo(rDest, destination.fileName(), override, function (e) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.Created);
arg.requirePrivilege(['canMove'], r, function () {
var override = arg.findHeader('overwrite') === 'T';
var destination = arg.findHeader('destination');
if (!destination) {
arg.setCode(WebDAVRequest_1.HTTPCodes.BadRequest);
callback();
return;
}
destination = destination.substring(destination.indexOf('://') + '://'.length);
destination = destination.substring(destination.indexOf('/'));
destination = new FSManager_1.FSPath(destination);
arg.server.getResourceFromPath(destination.getParent(), function (e, rDest) {
arg.requirePrivilege(['canAddChild'], rDest, function () {
r.moveTo(rDest, destination.fileName(), override, function (e) {
if (e)
arg.setCode(WebDAVRequest_1.HTTPCodes.InternalServerError);
else
arg.setCode(WebDAVRequest_1.HTTPCodes.Created);
callback();
});
});
});
});
});
Expand Down
157 changes: 85 additions & 72 deletions lib/server/commands/Propfind.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
var WebDAVRequest_1 = require("../WebDAVRequest");
var IResource_1 = require("../../resource/IResource");
var XML_1 = require("../../helper/XML");
var http = require("http");
function default_1(arg, callback) {
arg.getResource(function (e, resource) {
if (e || !resource) {
Expand Down Expand Up @@ -40,89 +41,101 @@ function default_1(arg, callback) {
function addXMLInfo(resource, multistatus, callback) {
var response = multistatus.ele('D:response');
var propstat = response.ele('D:propstat');
propstat.ele('D:status').add('HTTP/1.1 200 OK');
var prop = propstat.ele('D:prop');
var nb = 7;
function nbOut(error) {
if (nb > 0 && error) {
nb = -1;
callback(error);
arg.requireErPrivilege(['canMove'], resource, function (e, can) {
if (e) {
propstat.ele('D:status').add('HTTP/1.1 ' + WebDAVRequest_1.HTTPCodes.InternalServerError + ' ' + http.STATUS_CODES[WebDAVRequest_1.HTTPCodes.InternalServerError]);
callback();
return;
}
--nb;
if (nb === 0)
if (!can) {
propstat.ele('D:status').add('HTTP/1.1 ' + WebDAVRequest_1.HTTPCodes.Unauthorized + ' ' + http.STATUS_CODES[WebDAVRequest_1.HTTPCodes.Unauthorized]);
callback();
}
resource.creationDate(function (e, ticks) {
if (!e)
prop.ele('D:creationdate').add(arg.dateISO8601(ticks));
nbOut(e);
});
arg.getResourcePath(resource, function (e, path) {
if (!e)
response.ele('D:href').add(arg.fullUri(path).replace(' ', '%20'));
nbOut(e);
});
resource.webName(function (e, name) {
if (!e)
prop.ele('D:displayname').add(name ? name : '');
nbOut(e);
});
var supportedlock = prop.ele('D:supportedlock');
resource.getAvailableLocks(function (e, lockKinds) {
if (e) {
nbOut(e);
return;
}
lockKinds.forEach(function (lockKind) {
var lockentry = supportedlock.ele('D:lockentry');
var lockscope = lockentry.ele('D:lockscope');
lockscope.ele('D:' + lockKind.scope.value.toLowerCase());
var locktype = lockentry.ele('D:locktype');
locktype.ele('D:' + lockKind.type.value.toLowerCase());
propstat.ele('D:status').add('HTTP/1.1 200 OK');
var prop = propstat.ele('D:prop');
var nb = 7;
function nbOut(error) {
if (nb > 0 && error) {
nb = -1;
callback(error);
return;
}
--nb;
if (nb === 0)
callback();
}
resource.creationDate(function (e, ticks) {
if (!e)
prop.ele('D:creationdate').add(arg.dateISO8601(ticks));
nbOut(e);
});
nbOut();
});
resource.getProperties(function (e, properties) {
if (e) {
arg.getResourcePath(resource, function (e, path) {
if (!e)
response.ele('D:href').add(arg.fullUri(path).replace(' ', '%20'));
nbOut(e);
return;
}
for (var name_1 in properties) {
var value = properties[name_1];
prop.ele(name_1).add(value);
}
nbOut();
});
resource.type(function (e, type) {
if (e) {
});
resource.webName(function (e, name) {
if (!e)
prop.ele('D:displayname').add(name ? name : '');
nbOut(e);
return;
}
var resourcetype = prop.ele('D:resourcetype');
if (type.isDirectory)
resourcetype.ele('D:collection');
if (type.isFile) {
nb += 2;
resource.mimeType(function (e, mimeType) {
if (!e)
prop.ele('D:getcontenttype').add(mimeType);
});
var supportedlock = prop.ele('D:supportedlock');
resource.getAvailableLocks(function (e, lockKinds) {
if (e) {
nbOut(e);
return;
}
lockKinds.forEach(function (lockKind) {
var lockentry = supportedlock.ele('D:lockentry');
var lockscope = lockentry.ele('D:lockscope');
lockscope.ele('D:' + lockKind.scope.value.toLowerCase());
var locktype = lockentry.ele('D:locktype');
locktype.ele('D:' + lockKind.type.value.toLowerCase());
});
resource.size(function (e, size) {
if (!e)
prop.ele('D:getcontentlength').add(size);
nbOut();
});
resource.getProperties(function (e, properties) {
if (e) {
nbOut(e);
});
}
nbOut();
});
resource.lastModifiedDate(function (e, lastModifiedDate) {
if (!e) {
prop.ele('D:getetag').add(IResource_1.ETag.createETag(lastModifiedDate));
prop.ele('D:getlastmodified').add(new Date(lastModifiedDate).toUTCString());
}
nbOut(e);
return;
}
for (var name_1 in properties) {
var value = properties[name_1];
prop.ele(name_1).add(value);
}
nbOut();
});
resource.type(function (e, type) {
if (e) {
nbOut(e);
return;
}
var resourcetype = prop.ele('D:resourcetype');
if (type.isDirectory)
resourcetype.ele('D:collection');
if (type.isFile) {
nb += 2;
resource.mimeType(function (e, mimeType) {
if (!e)
prop.ele('D:getcontenttype').add(mimeType);
nbOut(e);
});
resource.size(function (e, size) {
if (!e)
prop.ele('D:getcontentlength').add(size);
nbOut(e);
});
}
nbOut();
});
resource.lastModifiedDate(function (e, lastModifiedDate) {
if (!e) {
prop.ele('D:getetag').add(IResource_1.ETag.createETag(lastModifiedDate));
prop.ele('D:getlastmodified').add(new Date(lastModifiedDate).toUTCString());
}
nbOut(e);
});
});
}
function done(multistatus) {
Expand Down
Loading

0 comments on commit e25fcbc

Please sign in to comment.