This is mostly a thought experiment for client/server communication, and I want to know the flaws.
When a user account is created (with U as the username and P as the password,) I generate a random salt (S) and store these values in the database (on the server-side): U, S and H which is computed as H = hash(U+S+P).
When authenticating a user:
- The client first "attempts an authentication" by sending 
Uto the server. - The sever creates a challenge code (
R) for that user and stores it in the database, along with the time this challenge would expire (T) and sendsRandSback to the client. - The client calculates its own version of 
H(by hashingUandSandPtogether; it hasUandP, and receivedSfrom server.) - The client then computes a new value 
GasG = hash(H+R)and sends thisGback to the server (actual "authentication request".) - The server hashes its own 
Htogether withRto reconstructGand authenticates the user iff itsGmatches the value received from client andThas not passed yet. - Whether authentication succeeds or fails, 
Ris removed from the server database. 
The flaws I'm already aware of are these:
- When creating an account, the password is transmitted in plaintext. This can be mitigated using a dedicated account-creation service that employs SSL for creating accounts.
 - Attempting an authentication will result in some resources being allocated on the server. This can be mitigated by allowing only one (or a fixed number) of challenge codes per user.
 - Trying to discover valid usernames and salts by generating many authentication attempts; which the server can foil by sending a random salt and challenge code even when the user does not exist.
 
Here are my specific questions:
- What am I missing? Where is the disaster waiting to happen?!
 - What can I do to make this more secure/better? Other than using SSL and just sending plaintext passwords (plaintext only from the perspective of my application.)
 - I'm thinking of SHA-256 for all hashes. Are there any flaws in the SHA-2 family? Is hashing the values once enough for generating 
HandG? - For generating 
HandG, are other permutations of values better? e.g.P+U+S,R+H, etc. - What conveniences am I denying my users? (Apart from their authentications now needing two round trips to the server.)
 
UPDATE: Ultimately, I want to do this:
After a successful authentication, the server generates a session key K as: K = hash(H+F) where F is a random string. F is sent to the user and K is retained in the database. The client reconstructs K using the received F and encrypts all communications with the server henceforth with a symmetric cipher (e.g. AES) with K as key.