Ejemplo n.º 1
0
 private static int? HighestAuthority(AccountModel account, String permission) {
     return account != null ? account.Group.Permissions.Where(perm => perm.Name == permission).Select(perm => perm.Authority).FirstOrDefault() : null;
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Checks if an initiator can act on a command against a target, falling back to a guest authority if either account is missing.
        /// </summary>
        /// <param name="initiatorAccount">Who is initiating the action</param>
        /// <param name="commandName">What action is being taken</param>
        /// <param name="targetAccount">Who the action is being taken against</param>
        /// <param name="guestAuthority">The fallback authority to use if neither initiator or target is passed or does not have an authority defined for the command.</param>
        /// <returns>A command result describing if the action can be taken</returns>
        private static ICommandResult CheckPermissions(AccountModel initiatorAccount, String commandName, AccountModel targetAccount, int? guestAuthority) {
            ICommandResult result = null;

            int? initiatorAuthority = SecurityController.HighestAuthority(initiatorAccount, commandName) ?? guestAuthority;
            int? targetAuthority = SecurityController.HighestAuthority(targetAccount, commandName) ?? guestAuthority;

            if (initiatorAuthority.HasValue == true && initiatorAuthority.Value > 0) {
                if (targetAuthority.HasValue == true && targetAuthority.Value > 0) {
                    if (initiatorAuthority.Value > targetAuthority.Value) {
                        // The initiator "out ranks" the target. Good to go.
                        result = new CommandResult() {
                            Success = true,
                            CommandResultType = CommandResultType.Success
                        };
                    }
                    else {
                        // The initiator has some permission, but not more than the target.
                        // The cannot execute the command, but we give some further details about it here.
                        result = new CommandResult() {
                            Success = false,
                            CommandResultType = CommandResultType.InsufficientAuthority
                        };
                    }
                }
                else {
                    // The target does not have any permission, so we're good to go.
                    result = new CommandResult() {
                        Success = true,
                        CommandResultType = CommandResultType.Success
                    };
                }
            }
            else {
                // The account has zero authority.
                result = new CommandResult() {
                    Success = false,
                    CommandResultType = CommandResultType.InsufficientPermissions
                };
            }

            return result;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// The underlying check permissions object.
        /// </summary>
        /// <param name="command"></param>
        /// <param name="initiatorAccount"></param>
        /// <param name="commandName"></param>
        /// <param name="targetAccount"></param>
        /// <returns></returns>
        protected ICommandResult DispatchPermissionsCheck(ICommand command, AccountModel initiatorAccount, String commandName, AccountModel targetAccount = null) {
            ICommandResult result = null;

            var guestAuthority = this.Groups.Where(group => group.IsGuest)
                .SelectMany(group => group.Permissions)
                .Where(permission => permission.Name == commandName)
                .Select(permission => permission.Authority)
                .FirstOrDefault();

            if (command.Origin == CommandOrigin.Local) {
                // All good.
                result = new CommandResult() {
                    Success = true,
                    CommandResultType = CommandResultType.Success
                };
            }
            else if (command.Origin == CommandOrigin.Plugin) {
                if (command.Authentication.Username == null && command.Authentication.Uid == null && command.Authentication.GameType == CommonProtocolType.None) {
                    // The plugin has not provided additional details on who has executed it.
                    result = new CommandResult() {
                        Success = true,
                        CommandResultType = CommandResultType.Success
                    };
                }
                else {
                    // The plugin has supplied us with details on who has initiated the command.
                    result = SecurityController.CheckPermissions(initiatorAccount, commandName, targetAccount, guestAuthority);
                }
            }
            else if (command.Origin == CommandOrigin.Remote) {
                result = SecurityController.CheckPermissions(initiatorAccount, commandName, targetAccount, guestAuthority);
            }
            else {
                result = new CommandResult() {
                    Success = false,
                    CommandResultType = CommandResultType.InsufficientPermissions
                };
            }

            return result;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates a new account if the specified name is unique.
        /// </summary>
        public ICommandResult SecurityGroupAddAccount(ICommand command, Dictionary<String, ICommandParameter> parameters) { // , String groupName, String username) {
            ICommandResult result = null;

            String groupName = parameters["groupName"].First<String>();
            String username = parameters["username"].First<String>();

            if (this.DispatchPermissionsCheck(command, command.Name).Success == true) {
                GroupModel group = this.Groups.FirstOrDefault(g => g.Name == groupName);

                if (group != null) {
                    if (group.IsGuest == false) {
                        if (username.Length > 0) {
                            AccountModel account = this.Groups.SelectMany(g => g.Accounts).FirstOrDefault(a => String.Compare(a.Username, username, StringComparison.OrdinalIgnoreCase) == 0);

                            // If the account does not exist in any other group yet..
                            if (account == null) {
                                account = new AccountModel() {
                                    Username = username,
                                    Group = group,
                                };

                                group.Accounts.Add(account);

                                result = new CommandResult() {
                                    Success = true,
                                    CommandResultType = CommandResultType.Success,
                                    Message = String.Format(@"Account ""{0}"" added to group ""{1}"".", account.Username, group.Name),
                                    Scope = new CommandData() {
                                        Groups = new List<GroupModel>() {
                                        group
                                    }
                                    },
                                    Now = new CommandData() {
                                        Accounts = new List<AccountModel>() {
                                        account
                                    }
                                    }
                                };

                                if (this.Shared.Events != null) {
                                    this.Shared.Events.Log(GenericEvent.ConvertToGenericEvent(result, GenericEventType.SecurityAccountAdded));
                                }
                            }
                            // Else the account exists already, relocate it.
                            else {
                                GroupModel existingGroup = account.Group;

                                // Remove it from the other group
                                account.Group.Accounts.Remove(account);

                                // Add the account to this group.
                                account.Group = group;
                                group.Accounts.Add(account);

                                result = new CommandResult() {
                                    Success = true,
                                    CommandResultType = CommandResultType.Success,
                                    Message = String.Format(@"Account ""{0}"" added to group ""{1}"".", account.Username, group.Name),
                                    Scope = new CommandData() {
                                        Accounts = new List<AccountModel>() {
                                        account
                                    }
                                    },
                                    Then = new CommandData() {
                                        Groups = new List<GroupModel>() {
                                        existingGroup
                                    }
                                    },
                                    Now = new CommandData() {
                                        Groups = new List<GroupModel>() {
                                        group
                                    }
                                    }
                                };

                                if (this.Shared.Events != null) {
                                    this.Shared.Events.Log(GenericEvent.ConvertToGenericEvent(result, GenericEventType.SecurityAccountAdded));
                                }
                            }
                        }
                        else {
                            result = new CommandResult() {
                                Success = false,
                                CommandResultType = CommandResultType.InvalidParameter,
                                Message = "An account username must not be zero length"
                            };
                        }
                    }
                    else {
                        result = new CommandResult() {
                            Success = false,
                            CommandResultType = CommandResultType.InvalidParameter,
                            Message = "Cannot add an account to a guest group"
                        };
                    }
                }
                else {
                    result = new CommandResult() {
                        Message = String.Format(@"Group with name ""{0}"" does not exists.", groupName),
                        Success = false,
                        CommandResultType = CommandResultType.DoesNotExists
                    };
                }
            }
            else {
                result = CommandResult.InsufficientPermissions;
            }

            return result;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Helper for creating an access token.
        /// </summary>
        /// <param name="account">The account to create the access token for</param>
        /// <param name="identifier">The identifying peice of information to mixin with the token</param>
        /// <returns>An access token for transport, or null if the user can't have tokens or something went wrong while making the token.</returns>
        protected AccessTokenTransportModel GenerateAccessToken(AccountModel account, String identifier) {
            AccessTokenTransportModel accessTokenTransport = null;

            var accessToken = new AccessTokenModel() {
                Account = account,
                ExpiredWindowSeconds = this.Shared.Variables.Get(CommonVariableNames.SecurityMaximumAccessTokenLastTouchedLengthSeconds, 172800)
            };

            var token = accessToken.Generate(identifier);

            if (String.IsNullOrEmpty(token) == false) {
                // Save the token hash for future authentication.
                this.Tunnel(CommandBuilder.SecurityAccountAppendAccessToken(account.Username, accessToken.Id, accessToken.TokenHash, accessToken.LastTouched).SetOrigin(CommandOrigin.Local));

                accessTokenTransport = new AccessTokenTransportModel() {
                    Id = accessToken.Id,
                    Token = token
                };
            }

            return accessTokenTransport;
        }
Ejemplo n.º 6
0
 public void Dispose() {
     this.ProtocolType = CommonProtocolType.None;
     this.Uid = null;
     this.Account = null;
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Fetches a player in the current game connection that is
        /// asociated with the account executing this command.
        /// 
        /// This is used so an account over a layer can issue a command like
        /// "kick me", but we only know "me" from the context of the account
        /// issuing the command. We use this to fetch the player in the game
        /// so we know who to kick.
        /// </summary>
        /// <param name="command"></param>
        /// <param name="speaker"></param>
        /// <returns></returns>
        protected PlayerModel GetAccountNetworkPlayer(ICommand command, AccountModel speaker) {
            PlayerModel player = this.Connection.ProtocolState.Players.Values.FirstOrDefault(p => p.Uid == command.Authentication.Uid);

            if (speaker != null) {
                AccountPlayerModel accountPlayer = speaker.Players.FirstOrDefault(p => p.ProtocolType == this.Connection.ConnectionModel.ProtocolType.Type);

                if (accountPlayer != null) {
                    player = this.Connection.ProtocolState.Players.Values.FirstOrDefault(p => p.Uid == accountPlayer.Uid);
                }
            }

            return player;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Runs through the various parsers for all of the text commands.
        /// </summary>
        /// <remarks>
        /// This method may fire multiple events to execute multiple commands
        /// when more than one parser is included in the future. This is expected
        /// behaviour.
        /// </remarks>
        /// <param name="speakerNetworkPlayer"></param>
        /// <param name="speakerAccount"></param>
        /// <param name="prefix"></param>
        /// <param name="text"></param>
        /// <returns>The generated event, if any.</returns>
        protected ICommandResult Parse(PlayerModel speakerNetworkPlayer, AccountModel speakerAccount, String prefix, String text) {
            List<ITextCommandParser> parsers = new List<ITextCommandParser>() {
                this.BuildFuzzyParser(speakerNetworkPlayer, speakerAccount),
                this.BuildRouteParser(speakerNetworkPlayer, speakerAccount)
            };

            return parsers.Select(parser => parser.Parse(prefix, text)).FirstOrDefault(result => result != null);
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Fetches a route text parser
 /// </summary>
 /// <param name="speaker">The player executing the command</param>
 /// <param name="speakerAccount">The account executing the command</param>
 /// <returns>The route parser, provided a language could be found.</returns>
 protected ITextCommandParser BuildRouteParser(PlayerModel speaker, AccountModel speakerAccount) {
     return new RouteParser() {
         Connection = this.Connection,
         TextCommands = this.TextCommands.Where(textCommand => textCommand.Parser == TextCommandParserType.Any || textCommand.Parser == TextCommandParserType.Route).ToList(),
         SpeakerPlayer = speaker,
         SpeakerAccount = speakerAccount
     };
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Fetches a fuzzy text parser
        /// </summary>
        /// <param name="speaker">The player executing the command</param>
        /// <param name="speakerAccount">The account executing the command</param>
        /// <returns>The fuzzy parser, provided a language could be found.</returns>
        protected ITextCommandParser BuildFuzzyParser(PlayerModel speaker, AccountModel speakerAccount) {
            LanguageConfig selectedLanguage = null;

            if (speakerAccount != null && speakerAccount.PreferredLanguageCode != String.Empty) {
                selectedLanguage = this.Shared.Languages.FindOptimalLanguageConfig(speakerAccount.PreferredLanguageCode);
            }
            else {
                selectedLanguage = this.Shared.Languages.Default;
            }

            return new FuzzyParser() {
                Connection = this.Connection,
                TextCommands = this.TextCommands.Where(textCommand => textCommand.Parser == TextCommandParserType.Any || textCommand.Parser == TextCommandParserType.Fuzzy).ToList(),
                Document = selectedLanguage.Config.Document,
                SpeakerPlayer = speaker,
                SpeakerAccount = speakerAccount
            };
        }