summaryrefslogtreecommitdiff
path: root/src/node/db/SecurityManager.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/node/db/SecurityManager.js')
-rw-r--r--src/node/db/SecurityManager.js280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/node/db/SecurityManager.js b/src/node/db/SecurityManager.js
new file mode 100644
index 00000000..a092453a
--- /dev/null
+++ b/src/node/db/SecurityManager.js
@@ -0,0 +1,280 @@
+/**
+ * Controls the security of pad access
+ */
+
+/*
+ * 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+var ERR = require("async-stacktrace");
+var db = require("./DB").db;
+var async = require("async");
+var authorManager = require("./AuthorManager");
+var padManager = require("./PadManager");
+var sessionManager = require("./SessionManager");
+var settings = require("../utils/Settings")
+var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
+
+/**
+ * This function controlls the access to a pad, it checks if the user can access a pad.
+ * @param padID the pad the user wants to access
+ * @param sesssionID the session the user has (set via api)
+ * @param token the token of the author (randomly generated at client side, used for public pads)
+ * @param password the password the user has given to access this pad, can be null
+ * @param callback will be called with (err, {accessStatus: grant|deny|wrongPassword|needPassword, authorID: a.xxxxxx})
+ */
+exports.checkAccess = function (padID, sessionID, token, password, callback)
+{
+ var statusObject;
+
+ // a valid session is required (api-only mode)
+ if(settings.requireSession)
+ {
+ // no sessionID, access is denied
+ if(!sessionID)
+ {
+ callback(null, {accessStatus: "deny"});
+ return;
+ }
+ }
+ // a session is not required, so we'll check if it's a public pad
+ else
+ {
+ // it's not a group pad, means we can grant access
+ if(padID.indexOf("$") == -1)
+ {
+ //get author for this token
+ authorManager.getAuthor4Token(token, function(err, author)
+ {
+ if(ERR(err, callback)) return;
+
+ // assume user has access
+ statusObject = {accessStatus: "grant", authorID: author};
+ // user can't create pads
+ if(settings.editOnly)
+ {
+ // check if pad exists
+ padManager.doesPadExists(padID, function(err, exists)
+ {
+ if(ERR(err, callback)) return;
+
+ // pad doesn't exist - user can't have access
+ if(!exists) statusObject.accessStatus = "deny";
+ // grant or deny access, with author of token
+ callback(null, statusObject);
+ });
+ }
+ // user may create new pads - no need to check anything
+ else
+ {
+ // grant access, with author of token
+ callback(null, statusObject);
+ }
+ })
+
+ //don't continue
+ return;
+ }
+ }
+
+ var groupID = padID.split("$")[0];
+ var padExists = false;
+ var validSession = false;
+ var sessionAuthor;
+ var tokenAuthor;
+ var isPublic;
+ var isPasswordProtected;
+ var passwordStatus = password == null ? "notGiven" : "wrong"; // notGiven, correct, wrong
+
+ async.series([
+ //get basic informations from the database
+ function(callback)
+ {
+ async.parallel([
+ //does pad exists
+ function(callback)
+ {
+ padManager.doesPadExists(padID, function(err, exists)
+ {
+ if(ERR(err, callback)) return;
+ padExists = exists;
+ callback();
+ });
+ },
+ //get informations about this session
+ function(callback)
+ {
+ sessionManager.getSessionInfo(sessionID, function(err, sessionInfo)
+ {
+ //skip session validation if the session doesn't exists
+ if(err && err.message == "sessionID does not exist")
+ {
+ callback();
+ return;
+ }
+
+ if(ERR(err, callback)) return;
+
+ var now = Math.floor(new Date().getTime()/1000);
+
+ //is it for this group? and is validUntil still ok? --> validSession
+ if(sessionInfo.groupID == groupID && sessionInfo.validUntil > now)
+ {
+ validSession = true;
+ }
+
+ sessionAuthor = sessionInfo.authorID;
+
+ callback();
+ });
+ },
+ //get author for token
+ function(callback)
+ {
+ //get author for this token
+ authorManager.getAuthor4Token(token, function(err, author)
+ {
+ if(ERR(err, callback)) return;
+ tokenAuthor = author;
+ callback();
+ });
+ }
+ ], callback);
+ },
+ //get more informations of this pad, if avaiable
+ function(callback)
+ {
+ //skip this if the pad doesn't exists
+ if(padExists == false)
+ {
+ callback();
+ return;
+ }
+
+ padManager.getPad(padID, function(err, pad)
+ {
+ if(ERR(err, callback)) return;
+
+ //is it a public pad?
+ isPublic = pad.getPublicStatus();
+
+ //is it password protected?
+ isPasswordProtected = pad.isPasswordProtected();
+
+ //is password correct?
+ if(isPasswordProtected && password && pad.isCorrectPassword(password))
+ {
+ passwordStatus = "correct";
+ }
+
+ callback();
+ });
+ },
+ function(callback)
+ {
+ //- a valid session for this group is avaible AND pad exists
+ if(validSession && padExists)
+ {
+ //- the pad is not password protected
+ if(!isPasswordProtected)
+ {
+ //--> grant access
+ statusObject = {accessStatus: "grant", authorID: sessionAuthor};
+ }
+ //- the pad is password protected and password is correct
+ else if(isPasswordProtected && passwordStatus == "correct")
+ {
+ //--> grant access
+ statusObject = {accessStatus: "grant", authorID: sessionAuthor};
+ }
+ //- the pad is password protected but wrong password given
+ else if(isPasswordProtected && passwordStatus == "wrong")
+ {
+ //--> deny access, ask for new password and tell them that the password is wrong
+ statusObject = {accessStatus: "wrongPassword"};
+ }
+ //- the pad is password protected but no password given
+ else if(isPasswordProtected && passwordStatus == "notGiven")
+ {
+ //--> ask for password
+ statusObject = {accessStatus: "needPassword"};
+ }
+ else
+ {
+ throw new Error("Ops, something wrong happend");
+ }
+ }
+ //- a valid session for this group avaible but pad doesn't exists
+ else if(validSession && !padExists)
+ {
+ //--> grant access
+ statusObject = {accessStatus: "grant", authorID: sessionAuthor};
+ //--> deny access if user isn't allowed to create the pad
+ if(settings.editOnly) statusObject.accessStatus = "deny";
+ }
+ // there is no valid session avaiable AND pad exists
+ else if(!validSession && padExists)
+ {
+ //-- its public and not password protected
+ if(isPublic && !isPasswordProtected)
+ {
+ //--> grant access, with author of token
+ statusObject = {accessStatus: "grant", authorID: tokenAuthor};
+ }
+ //- its public and password protected and password is correct
+ else if(isPublic && isPasswordProtected && passwordStatus == "correct")
+ {
+ //--> grant access, with author of token
+ statusObject = {accessStatus: "grant", authorID: tokenAuthor};
+ }
+ //- its public and the pad is password protected but wrong password given
+ else if(isPublic && isPasswordProtected && passwordStatus == "wrong")
+ {
+ //--> deny access, ask for new password and tell them that the password is wrong
+ statusObject = {accessStatus: "wrongPassword"};
+ }
+ //- its public and the pad is password protected but no password given
+ else if(isPublic && isPasswordProtected && passwordStatus == "notGiven")
+ {
+ //--> ask for password
+ statusObject = {accessStatus: "needPassword"};
+ }
+ //- its not public
+ else if(!isPublic)
+ {
+ //--> deny access
+ statusObject = {accessStatus: "deny"};
+ }
+ else
+ {
+ throw new Error("Ops, something wrong happend");
+ }
+ }
+ // there is no valid session avaiable AND pad doesn't exists
+ else
+ {
+ //--> deny access
+ statusObject = {accessStatus: "deny"};
+ }
+
+ callback();
+ }
+ ], function(err)
+ {
+ if(ERR(err, callback)) return;
+ callback(null, statusObject);
+ });
+}