SHA256_PassHash offline password changing problem
#1

So I have a command I've just created where you can change a users password while they're offline. Below is my code where I do that. When I execute the code in-game and go log into the accounts password I changed, it still doesn't change the password at all, it just keeps the same password and won't let me log in.

Код:
CMD:offchangepass(playerid, params[])
{
	new query_1[400], name[MAX_PLAYER_NAME], newpassword[20];

	if(sscanf(params, "s[24]s[20]", name, newpassword))
		return SendClientMessage(playerid, COLOR_GREY, "USAGE: /offchangepass [name] [new password]");
	
	if(isnull(newpassword))
		return SendClientMessage(playerid, COLOR_RED, "[ERROR]: You must enter a new password in.");
	
	new len = strlen(newpassword);
	if(len > MAX_PASSWORD_LENGTH || len < MIN_PASSWORD_LENGTH)
	{
	    new string[144];
	    format(string, sizeof (string), "ERROR: Invalid password length, must be between %i - %i characters.", MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH);
	    return SendClientMessage(playerid, COLOR_RED, string);
	}

        strcat(query_1, "SELECT `"#USER_PASSWORD"`,");
        strcat(query_1, "`"#USER_SALT"`");
	strcat(query_1, " FROM `"#TABLE_USERS"`");
	strcat_format(query_1, sizeof(query_1), " WHERE `"#USER_NAME"` = '%q' COLLATE NOCASE LIMIT 1", name);
	new DBResult:result = db_query(sabdm_database, query_1);

	if(db_num_rows(result))
 	{
                new query[300], string[144];

                SHA256_PassHash(newpassword, USER_SALT, USER_PASSWORD, 65);

		strcat(query, "UPDATE `"#TABLE_USERS"` SET ");
		strcat_format(query, sizeof(query), "`"#USER_PASSWORD"` = '%q'", newpassword);
		strcat_format(query, sizeof(query), " WHERE `"#USER_NAME"` = '%q'", name);
		db_query(sabdm_database, query);
		
		format(string, sizeof(string), "You successfully changed %s's password.", name);
		SendClientMessage(playerid, COLOR_YELLOW_GREEN, string);
	}
	else
	{
                SendClientMessage(playerid, COLOR_RED, "[ERROR]: No user(s) were found using your query.");
	}
	
	db_free_result(result);
	return 1;
}
Reply
#2

First rule: re-generate a new salt every time you change the password.

Set COLLATE NOCASE to the column (player's name) when creating the table or alter the table (if it is already created) and set it to avoid using it in queries all the time.

Isn't USER_SALT and USER_PASSWORD you are using in SHA256_PassHash constants?
Reply
#3

Quote:
Originally Posted by Konstantinos
Посмотреть сообщение
First rule: re-generate a new salt every time you change the password.

Set COLLATE NOCASE to the column (player's name) when creating the table or alter the table (if it is already created) and set it to avoid using it in queries all the time.

Isn't USER_SALT and USER_PASSWORD you are using in SHA256_PassHash constants?
Yeah they're constants used to create the rows for the table too, not sure why I was using it there.

I've done it so it re-generates every time I change the password but have had no luck.
Reply
#4

Assuming you have set COLLATE NOCASE as I told you and you have unique ID for each player, here's an example (modify it to fit your needs):
pawn Код:
CMD:offchangepass(playerid, params[])
{
    new name[MAX_PLAYER_NAME], newpassword[20];

    if (sscanf(params, "s[24]s[20]", name, newpassword)) return SendClientMessage(playerid, COLOR_GREY, "USAGE: /offchangepass [name] [new password]");
    if (!(MIN_PASSWORD_LENGTH <= strlen(newpassword) <= MAX_PASSWORD_LENGTH)) return SendClientMessage(playerid, COLOR_RED, "ERROR: Invalid password length, must be between "#MIN_PASSWORD_LENGTH" - "#MAX_PASSWORD_LENGTH" characters.");

    new query[250] = "SELECT id FROM users WHERE name='%q' LIMIT 1", DBResult: result;
    format(query, sizeof query, query, name);
    result = db_query(sabdm_database, query);

    if (db_num_rows(result))
    {
        new new_salt[/* size_here */], new_password[65];
     
        // re-generate new salt
     
        SHA256_PassHash(newpassword, new_salt, new_password, sizeof new_password);

        format(query, sizeof query, "UPDATE users SET salt='%q',password='%q' WHERE id=%i", new_salt, new_password, db_get_field_int(result));
        db_query(sabdm_database, query);
       
        format(query, sizeof query, "You successfully changed %s's password.", name);
        SendClientMessage(playerid, COLOR_YELLOW_GREEN, query);
    }
    else SendClientMessage(playerid, COLOR_RED, "[ERROR]: No user(s) were found using your query.");
   
    db_free_result(result);
    return 1;
}
If we had a function for the affected rows, you would just do it with 1 query.
Reply
#5

It now says I've changed the password, but when I go to login to the account is still says wrong password.

Here's the updated code:

Код:
CMD:offchangepass(playerid, params[])
{
	new query_1[250], name[MAX_PLAYER_NAME], newpassword[20];

	if(sscanf(params, "s[24]s[20]", name, newpassword))
		return SendClientMessage(playerid, COLOR_GREY, "USAGE: /offchangepass [name] [new password]");
	
	if(isnull(newpassword))
		return SendClientMessage(playerid, COLOR_RED, "[ERROR]: You must enter a new password in.");
	
	new len = strlen(newpassword);
	if(len > MAX_PASSWORD_LENGTH || len < MIN_PASSWORD_LENGTH)
	{
	    new string[144];
	    format(string, sizeof (string), "ERROR: Invalid password length, must be between %i - %i characters.", MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH);
	    return SendClientMessage(playerid, COLOR_RED, string);
	}

        strcat(query_1, "SELECT `"#USER_SQL_ID"`");
	strcat(query_1, " FROM `"#TABLE_USERS"`");
	strcat_format(query_1, sizeof(query_1), " WHERE `"#USER_NAME"` = '%q' LIMIT 1", name);
	new DBResult:result = db_query(sabdm_database, query_1);

	if(db_num_rows(result))
 	{
                new string[144];

                new salt[11], hash[65];
                for(new i; i < 10; i++)
                {
        	        salt[i] = random(79) + 47;
                }
                salt[10] = 0;

                SHA256_PassHash(newpassword, salt, hash, sizeof hash);

		strcat(query_1, "UPDATE `"#TABLE_USERS"` SET ");
		strcat_format(query_1, sizeof(query_1), "`"#USER_SALT"` = '%q',", salt);
		strcat_format(query_1, sizeof(query_1), "`"#USER_PASSWORD"` = '%q'", newpassword);
		strcat_format(query_1, sizeof(query_1), " WHERE `"#USER_SQL_ID"` = '%i' LIMIT 1", name);
		db_query(sabdm_database, query_1);
		
		format(string, sizeof(string), "You successfully changed %s's password.", name);
		SendClientMessage(playerid, COLOR_YELLOW_GREEN, string);

		print(query_1);
	}
	else
	{
        SendClientMessage(playerid, COLOR_RED, "[ERROR]: No user(s) were found using your query.");
	}
	
	db_free_result(result);
	return 1;
}
Reply
#6

Is the row updated in the table? You might as well enable db_logging in server.cfg in case an error occurs.
Debug it to print the new salt and new hashed password from the command. Print salt and password retrieved when you try to login too to see if they match.
Reply
#7

Also make sure you're not re-saving the user's password when they disconnect. If you have a variable that stores the user's password for whatever reason, make sure you either update it when you change the password and aren't re-saving it when it doesn't need to be saved.

Essentially, you could possibly be reverting these changes simply when you relog.
Reply
#8

No errors come up when I enabled db_logging in the server.cfg.

This is what the query prints when I change the password for another account:

Код:
[12:50:35] SELECT `sql_id` FROM `USERS` WHERE `name` = 'Test' LIMIT 1
UPDATE `USERS` SET `salt` = '|Oxq}Ea/_E',`password` = '123456' WHERE `sql_id` = '2' LIMIT 1
The salt and password do not get updated in the database.

Threshold, there is a password and salt variable although I'm not as how I would change them while another player is offline. I've tried several ways before and they never worked either.

I do not save the password when a player disconnects either.
Reply
#9

Looking at your code again more carefully noticed the mistake, I don't know how I missed that the first time.
Код:
strcat(query_1, "UPDATE `"#TABLE_USERS"` SET ");
strcat_format(query_1, sizeof(query_1), "`"#USER_SALT"` = '%q',", salt);
strcat_format(query_1, sizeof(query_1), "`"#USER_PASSWORD"` = '%q'", newpassword);
strcat_format(query_1, sizeof(query_1), " WHERE `"#USER_SQL_ID"` = '%i' LIMIT 1", name);
Should have been hash and db_get_field_int(result) instead.
Reply
#10

All I've done is just change what you said and now this comes up in the console when I execute the command.

Код:
[20:47:02] SELECT `sql_id` FROM `USERS` WHERE `name` = 'Test1' LIMIT 1
[20:47:02] [Warning] db_query: Query failed: near "LIMIT": syntax error
[20:47:02] UPDATE `USERS` SET `salt` = 'Ilh6\WRliD',`password` = '9A8D7097670F7CEC849AE3DEA8BB6F1108767C860C74A85061E66A8E35746B80' WHERE `sql_id` = '2' LIMIT 1
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)