My understanding of the standard best practice way to handle passwords is:
Establish a secure encrypted connection between client and server.
Client sends password in plaintext over this encrypted connection.
Server gets plaintext password.
Server adds a salt to it (and possibly a pepper) and hashes it.
Server stores it (in case of registration) or compares it with the corresponding stored hash (in case of login).
The hashing, plus salting, etc., ensures that, even in a password database leak, in theory, everything is secure. Due to the salts we can't match the passwords with each other to figure out which are the same, etc.
However, another common issue with password database leaks (which is also solved here) is when a less secure service's database leaks, but many people used the same password for other services. This is still handled by salts, peppers, etc. (as much as possible).
However, I am concerned about step 3 -- briefly the password exists in plaintext in memory on the server. If even one sysadmin is malicious, or if the server is compromised, the plaintext passwords may leak. Of course, if the server is compromised, all bets are off on this service being secure. However, in case that users used the same password as they would for another service (as many people do), they are affected by this.
My question is why isn't the standard practice to have the user also hash the password with salt (+ pepper, potentially) and send that hash over? Then, even if the server is compromised, this leaks no information about the user's original password. Then, in order to protect this service if only the database leaks, we can still do the hashing with salting, etc. on the server side as well and store that.
I am considering this in the context of the client being a binary executable, not a web app. So the client code is shipped separately, not from the same server as the one processing login requests.