Commit graph

44 commits

Author SHA1 Message Date
DannyS712
b1cd3ad252 BotPasswordStore: accept UserIdentity objects
Now that CentralIdLookup doesn't require full User objects

Bug: T265769
Follow-up: I67bf4f2442269b8aa1002868ede9a71a5ca43a84
Change-Id: I953333116f6cd6dc095914929914a970cc190292
2021-07-21 18:50:25 +00:00
DannyS712
de051140d8 Move BotPassword lookup methods to BotPasswordStore
I was considering adding a separate service for the creation/fetching
of BotPassword instances (probably BotPasswordLookup or
BotPasswordFactory) but since it would need to access the same
bot password database that BotPasswordStore uses, it would either
need to duplicate the logic, or have a store injected, which would
reduce the benefits of having separate services.

The following methods were moved:
* newFromUser (also renamed to getByUser)
* newFromCentralId (also renamed to getByCentralId)
* newUnsaved

Additionally, BotPassword::__construct() is made public, though
marked as @internal

Bug: T265769
Change-Id: I2a5f46a8fbdf3867517eeb006d886b943fa85af1
2021-07-18 00:53:48 +00:00
DannyS712
2f802e82c8 Deprecate unused BotPassword methods
BotPassword::invalidateAllPasswordsForCentralId() and
BotPassword::removeAllPasswordsForCentralId() are no
longer used following introduction of BotPasswordStore.

Bug: T265769
Change-Id: I77589032a8b771d1e111e8adbee3600f181fedbc
2021-07-15 04:19:07 +00:00
DannyS712
abf5f78f65 Add BotPasswordStore service
Does not (yet) handle looking up bot passwords
in the database, just inserting/updating/removing
them.

Bug: T265769
Change-Id: I20e3aaee63ec182483489681282dae52fe41ec90
2021-07-14 21:45:55 +00:00
James D. Forrester
f2f9345e39 Replace uses of DB_MASTER with DB_PRIMARY in documentation and local variables
This is just a start.

Bug: T254646
Change-Id: I9213aad4660e27afe7ff9e5d2e730cbf03911068
2021-05-14 12:40:34 -07:00
Thiemo Kreuz
6805f39a30 Remove unused default values from class properties
In all these cases the property is unconditionally set in
the constructor. The extra initialisation is effectively
dead code and an extra source of errors and confusion.

Change-Id: Icae13390d5ca5c14e2754f3be4eb956dd7f54ac4
2021-05-12 13:44:28 +02:00
James D. Forrester
df5eb22f83 Replace uses of DB_MASTER with DB_PRIMARY
Just an auto-replace from codesniffer for now.

Change-Id: I5240dc9ac5929d291b0ef1c743ea2bfd3f428266
2021-04-29 09:24:31 -07:00
Reedy
76249a28d2 Validate max length of bp_restrictions and bp_grants
Bug: T260631
Bug: T260633
Change-Id: Ifc35e01c711f1394f45748f693e7a46695b2d471
2020-12-05 02:10:01 +00:00
jenkins-bot
1976283835 Merge "Update a lot of unspecific "array" types in PHPDocs" 2020-11-13 21:48:24 +00:00
Umherirrender
9fb6d107ba Improve docs about @param/@return object $row to stdClass
Change-Id: I743d992db703f2b46b6e3abf80c14d026c6599f4
2020-11-13 00:08:21 +01:00
Thiemo Kreuz
b0130ca649 Update a lot of unspecific "array" types in PHPDocs
This includes fixing some mistakes, as well as removing
redundant text that doesn't add new information, either because
it literally repeats what the code already says, or is actually
duplicated.

Change-Id: I3a8dd8ce57192deda8916cc444c87d7ab1a36515
2020-10-28 11:01:33 +01:00
Thiemo Kreuz
1fc8d79ac6 Remove documentation that literally repeats the code
For example, documenting the method getUser() with "get the User
object" does not add any information that's not already there.
But I have to read the text first to understand that it doesn't
document anything that's not already obvious from the code.

Some of this is from a time when we had a PHPCS sniff that was
complaining when a line like `@param User $user` doesn't end
with some descriptive text. Some users started adding text like
`@param User $user The User` back then. Let's please remove
this.

Change-Id: I0ea8d051bc732466c73940de9259f87ffb86ce7a
2020-10-27 19:20:26 +00:00
DannyS712
8565969f3f Cleanup BotPassword class to prepare for refactor
The class is not stable to extend, so convert things
from protected to private.

Will be followed by a patch introducing a new
BotPasswordStore service.

Bug: T265769
Change-Id: I318131685fcec80816bd7b59ed27baa6511da3c6
2020-10-22 02:45:09 +00:00
Alex Dean
8c8654cce0 Add a maintenance script to create bot passwords.
This is useful in testing environments where we want to spin up new mediawiki
instances and configure them programatically.

Change-Id: Ice94b67cb8775786a754de51010e78211954b2b0
2020-08-21 07:25:33 +00:00
Tim Starling
68c433bd23 Hooks::run() call site migration
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.

General principles:
* Use DI if it is already used. We're not changing the way state is
  managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
  is a service, it's a more generic interface, it is the only
  thing that provides isRegistered() which is needed in some cases,
  and a HookRunner can be efficiently constructed from it
  (confirmed by benchmark). Because HookContainer is needed
  for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
  SpecialPage and ApiBase have getHookContainer() and getHookRunner()
  methods in the base class, and classes that extend that base class
  are not expected to know or care where the base class gets its
  HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
  getHookRunner() methods, getting them from the global service
  container. The point of this is to ease migration to DI by ensuring
  that call sites ask their local friendly base class rather than
  getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
  methods did not seem warranted, there is a private HookRunner property
  which is accessed directly. Very rarely (two cases), there is a
  protected property, for consistency with code that conventionally
  assumes protected=private, but in cases where the class might actually
  be overridden, a protected accessor is preferred over a protected
  property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
  global code. In a few cases it was used for objects with broken
  construction schemes, out of horror or laziness.

Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore

Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router

setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine

Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
2020-05-30 14:23:28 +00:00
Reedy
988174411c Fix even more PSR12.Properties.ConstantVisibility.NotFound
Change-Id: If1335359b545c36fc979676c3e88d87628f9389e
2020-05-16 00:51:31 +01:00
Daimona Eaytoy
c659bc6308 Unsuppress another phan issue (part 7)
Bug: T231636
Depends-On: I2cd24e73726394e3200a570c45d5e86b6849bfa9
Depends-On: I4fa3e6aad872434ca397325ed7a83f94973661d0
Change-Id: Ie6233561de78457cae5e4e44e220feec2d1272d8
2019-09-03 17:19:21 +00:00
Umherirrender
0c2a404873 Use IDatabase as return type for BotPassword::getDB
There is no guarantee that this is a maintenance able connection,
but drop, create or alter is also not needed in this case

Change-Id: I7dd294b3d28ef8c4e416e826f38ed39f824b2f8f
2019-06-18 21:40:09 +02:00
Thiemo Kreuz
37b3383e8b Remove comments literally repeating the next line of code
I would argue that these comments do not add any information that
would not be there already. Having them adds mental overhead, because
one needs to read both the comment and the next line of code first to
understand they say the exact same. I don't find this helpful, but
more distracting.

Change-Id: I39c98f25225947ebffdcc2fd8f0243e7a6c070d7
2019-02-27 17:28:40 +00:00
Max Semenik
7a7976ba7a Password: replace equals() with verify()
So far, our key derivation code assumed that it has control over
the salt used by the derivation routines, however I want to add Argon2
support and it doesn't work this way: password_hash() generates the
salt itself, and the only way to verify a password is by using
password_verify(). Current way the things are done doesn't support it
because it relies on the result of password hashing with parameters we
provide to be deterministic.

Therefore, I'm deprecating Password::equals(), as well as whole concept
of comparing Password objects - it's used only in tests anyway. It's
getting replaced with verify() that only accepts password strings.
Uses of old function are fixed with exception of a few calls in tests
that will be addressed in my Argon2 patch.

Change-Id: I2b2be9a422ee0f773490eac316ad81505c3f8571
2019-01-24 13:40:40 -08:00
Gergő Tisza
07a27f19cf Include bot password app ID in audit data
Authentication audit logs should indicate whether a login is via the
normal password or a bot password (and which one). For failed logins
it could be included in the error message, and it usually is, but
for successful ones there is no message, so we'll send the app ID as
a new AuthManagerLoginAuthenticateAudit parameter.

Bug: T194338
Change-Id: I8aab48177b81a8e80dae118e6476a8f6a32089f1
Depends-On: Id482d2e2205960a0facd334e456d3a23bcad0ece
2018-12-13 19:18:17 +00:00
Brad Jorsch
0c1b6605ee Have BotPassword::login() call AuthManagerLoginAuthenticateAudit
To facilitate logging all authentications, even ones not via
AuthManager, BotPassword::login() should call the
AuthManagerLoginAuthenticateAudit hook.

Bug: T194338
Change-Id: I27b75c56e060fcb8f71d84ddc2eb8e1533fef33a
2018-12-11 15:33:39 -05:00
Aryeh Gregor
1496fd4b4e Improve ApiLogin test coverage
Coverage is 100% except for one session-related bit that seems a bit
involved to test right now.  It looks like it will be easier once
SessionManager becomes a service.

I removed the third parameter from the return value of
canonicalizeLoginData, since af37a4c7 made it always return true.

I also removed three lines of dead code from ApiLogin.php.

Change-Id: Ia0073eddd27c82827518e0031e3c313f83cfd7cc
2018-10-10 11:11:43 +03:00
Brian Wolff
9c0ba336ff SECURITY: Do not allow botpassword login if account locked.
Reported by Rxy

Bug: T194605
Change-Id: Ib41005e69ab4db6f849837de12f0d41398b58f9a
2018-09-20 22:26:11 +01:00
Kunal Mehta
fb73286fba Add PasswordFactory to MediaWikiServices
Instead of having basically every caller do:
 $pf = new PasswordFactory();
 $pf->init( RequestContext::getMain()->getConfig() );
Just create a single PasswordFactory via MediaWikiServices and pass that
around. Things that want to use their own config can still pass settings
via the new constructor.

This will eventually let us remove the init() function, removing the
only hard dependency upon MediaWiki, to make it easier to librarize
(T89742).

Change-Id: I0fc7520dc023b11a7fa66083eff7b88ebfe49c7b
2018-08-02 14:46:35 +01:00
Bartosz Dziewoński
485f66f174 Use PHP 7 '??' operator instead of '?:' with 'isset()' where convenient
Find: /isset\(\s*([^()]+?)\s*\)\s*\?\s*\1\s*:\s*/
Replace with: '\1 ?? '

(Everywhere except includes/PHPVersionCheck.php)
(Then, manually fix some line length and indentation issues)

Then manually reviewed the replacements for cases where confusing
operator precedence would result in incorrect results
(fixing those in I478db046a1cc162c6767003ce45c9b56270f3372).

Change-Id: I33b421c8cb11cdd4ce896488c9ff5313f03a38cf
2018-05-30 18:06:13 -07:00
Brad Jorsch
ff6b4cb35c BotPasswords: Indicate when a password needs reset
Certain things, such as changing the account's main login credentials,
causes all bot passwords to be invalidated. This state should be
indicated in Special:BotPasswords, and the API when login fails.

Bug: T193829
Change-Id: Ib12929fed861742c9f2f76702c9ac3254e8a5d97
2018-05-04 09:48:23 -04:00
Umherirrender
554f9c857c Replace wfGetLBFactory
@deprecated since 1.27

Change-Id: I11a7253cebe525948a55cebee183e6de128fdc39
2018-02-27 20:02:48 +00:00
Brad Jorsch
25390162c7 SECURITY: Add throttling for BotPasswords authentication attempts
ApiLogin which will currently always try an AuthManager login which will
by default throttle via ThrottlePreAuthenticationProvider, but this only
happens after the BotPassword is checked so it's still possible to keep
trying to break the bot password.

There's a potential odd-behavior mode here: if the main account username
and password looks like a BotPasswords username and password, a
successful main account login will increment the BotPasswords throttle
for the user and not reset it after the successful main account login.
That seems such an odd edge case I say let's not worry about it.

Bug: T165846
Change-Id: Ie60f0e05c2a94722b91bc3a80c80346e28b443f4
2017-11-15 00:58:44 +00:00
Kunal Mehta
d1cf48a397 build: Update mediawiki/mediawiki-codesniffer to 0.10.1
And auto-fix all errors.

The `<exclude-pattern>` stanzas are now included in the default ruleset
and don't need to be repeated.

Change-Id: I928af549dc88ac2c6cb82058f64c7c7f3111598a
2017-07-22 18:24:09 -07:00
Aaron Schulz
d735dc562d Move Database and subclasses to Rdbms namespace
Change-Id: I52bef87512f9ddd155d1f4cc0052f6b7a0db5b42
2017-04-12 10:43:57 -07:00
Aaron Schulz
30f4b3c103 Replace DatabaseBase => Database in more places
Change-Id: If37a7909056bf2c31a8228cbc84f0fbbf5f1c517
2016-09-28 15:53:02 -07:00
Gergő Tisza
af37a4c77d Fix login API for users with @ in their usernames
An @ in the username caused the password to be treated as a bot password,
but apparently some real usernames still contain it. Try both logins
instead. Security considerations are the same as for the other bot
password syntax: the length check makes sure we do not provide any
information on a timing side channel about the password unless it is
extremely long.

Change-Id: I58f42544a08c3208c41f54cfae932632d9c5affa
2016-09-14 01:47:52 +00:00
jenkins-bot
fc7d715b4b Merge "Allow putting the app ID in the password for bot passwords" 2016-09-13 00:38:14 +00:00
Gergő Tisza
4f29c96197 Allow putting the app ID in the password for bot passwords
Bot passwords allow backwards-compatible login (with grants, for API
usage only) with "<real username>@<botname>" for username plus a
random-generated password.
This doesn't work well with some bot frameworks (including Pywikibot,
the most popular one) which assume that the text that goes into the
username field of the login API is the username that they will be
logged in with afterwards (and so the @-postfix causes all kinds of
errors).

Since the goal of bot passwords is compatibility with old unmaintained
API clients, this patch adds an alternative format which does not
cause problems with old bots: use the username normally, and use
"<botname>@<random-generated password>" as password. Since this is
technically a valid normal password, there is some ambiguity, but
bot passwords have a distintive format so it's easy to check and it is
extremely unlikely that someone would use the exact same format for
their normal password; and if the bot password login fails we can
simply retry it as a normal password, just in case.

Bug: T142304
Change-Id: Ib59a6fbe0e65d80d5e7d19ff37cec5e011c00539
2016-09-07 21:01:55 +00:00
Aaron Schulz
950cf6016c Rename DB_SLAVE constant to DB_REPLICA
This is more consistent with LoadBalancer, modern, and inclusive
of master/master mysql, NDB cluster, and MariaDB galera cluster.

The old constant is an alias now.

Change-Id: I0b37299ecb439cc446ffbe8c341365d1eef45849
2016-09-05 22:55:53 -07:00
Brad Jorsch
6c0abf937a Use ::class in place of string constants
This takes advantage of namespacing, and avoids having
double-backslashes all over the place.

Change-Id: I450fe4e9b1c4cf4e24fced3932fe796cbbadf3a3
2016-03-28 14:53:45 -04:00
Reedy
b5656b6953 Many more function case mismatches
Change-Id: I5d3a5eb8adea1ecbf136415bb9fd7a162633ccca
2016-03-19 00:20:58 +00:00
Kunal Mehta
6e9b4f0e9c Convert all array() syntax to []
Per wikitech-l consensus:
 https://lists.wikimedia.org/pipermail/wikitech-l/2016-February/084821.html

Notes:
* Disabled CallTimePassByReference due to false positives (T127163)

Change-Id: I2c8ce713ce6600a0bb7bf67537c87044c7a45c4b
2016-02-17 01:33:00 -08:00
Thiemo Mättig
e5159debbb Remove unused imports from Session classes
Change-Id: Ia3cdd923728870f5eff0bd90fd2f6605047291c0
2016-02-10 18:09:02 +01:00
Brad Jorsch
2257fe4228 Revert "Remove SessionManager, temporarily"
This reverts commit 823db5d63dd5200d04c63da50ba6bf16f928e70b.

Change-Id: Ibb3e023e4eb6715295586dea87d0725c344a8271
2016-02-03 21:44:59 +00:00
Brad Jorsch
5083e810eb Remove SessionManager, temporarily
The plan here is to take it out of 1.27.0-wmf.12 and put it back in
1.27.0-wmf.13.

Since BotPasswords depends on SessionManager, that's getting temporarily
removed too.

This reverts the following commits:
* 6acd424e0d SessionManager: Notify AuthPlugin before calling hooks
* 4d1ad32d8a Close a loophole in CookieSessionProvider
* fcdd643a46 SessionManager: Don't save non-persisted sessions to backend storage
* 058aec4c76 MessageCache: Don't get a ParserOptions for $wgUser before the end of Setup.php
* b5c0c03bb7 SessionManager: Save user name to metadata even if the user doesn't exist locally
* 13f2f09a19 SECURITY: Fix User::setToken() call on User::newSystemUser
* 305bc75b27 SessionManager: Don't generate user tokens when checking the tokens
* 7c4bd85d21 RequestContext::exportSession() should only export persisted session IDs
* 296ccfd4a9 SessionManager: Save 'persisted' flag in session metadata
* 94ba53f677 Move CSRF token handling into MediaWiki\Session\Session
* 46a565d6b0 Avoid false "added in both Session and $_SESSION" when value is null
* c00d0b5d94 Log backtrace for "User::loadFromSession called before the end of Setup.php"
* 4eeff5b559 Use $wgSecureCookie to decide whether to actually mark secure cookies as 'secure'
* 7491b52f70 Call session_cache_limiter() before starting a session
* 2c34aeea72 SessionManager: Abstract forceHTTPS cookie setting
* 9aa53627a5 Ignore auth cookies with value 'deleted'
* 43f904b51a SessionManager: Kill getPersistedSessionId()
* 50c5256352 SessionManager: Add SessionBackend::setProviderMetadata()
* f640d40315 SessionManager: Notify AuthPlugin when auto-creating accounts
* 70b05d1ac1 Add checks of $wgEnableBotPasswords in more places
* bfed32eb78 Do not raise a PHP warning when session write fails
* 722a7331ad Only check LoggedOut timestamp on the user loaded from session
* 4f5057b84b SessionManager: Change behavior of getSessionById()
* 66e82e614e Fix typo in [[MediaWiki:Botpasswords-editexisting/en]]
* f9fd9516d9 Add "bot passwords"
* d7716f1df0 Add missing argument for wfDebugLog
* a73c5b7395 Add SessionManager

Change-Id: I2389a8133e25ab929e9f27f41fa9a05df8147a50
2016-02-01 22:06:49 +00:00
Brad Jorsch
70b05d1ac1 Add checks of $wgEnableBotPasswords in more places
Bug: T124335
Change-Id: I3c13e7c7b84d5b72437f9ebdba35aad29b403b9c
2016-01-21 15:06:02 -05:00
Brad Jorsch
f9fd9516d9 Add "bot passwords"
Bot passwords are something like OAuth-lite, or Google's application
passwords: the bot can use API action=login to log in with the special
username and password, and will then be allowed to use the API with a
restricted set of rights.

This is intended to provide an easy migration path for legacy bots and
for bots on wikis without OAuth, since AuthManager is going to greatly
complicate non-interactive authentication. If OAuth is available, an
owner-only consumer would be a better choice.

Bug: T121113
Change-Id: Iaa4015e00edbfbfaedcc8b2d27a2d3fd25009159
Depends-On: I7e15331efb162275c4116bcae61f19d6b884cbe3
2016-01-12 22:37:44 +00:00