📄 handle_bnet.c
字号:
{ char const *username; t_account *account; if (!(username = packet_get_str_const(packet, sizeof(t_client_changepassreq), UNCHECKED_NAME_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CHANGEPASSREQ (missing or too long username)", conn_get_socket(c)); return -1; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change requested for \"%s\"", conn_get_socket(c), username); if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_changepassack)); packet_set_type(rpacket, SERVER_CHANGEPASSACK); /* fail if logged in or no account */ if (connlist_find_connection_by_accountname(username) || !(account = accountlist_find_account(username))) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (no such account)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } else if (account_get_auth_changepass(account) == 0) { /* default to true */ eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (no change access)", conn_get_socket(c), username); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_changepassreq.sessionkey)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] password change for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_changepassreq.sessionkey)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } else { struct { bn_int ticks; bn_int sessionkey; bn_int passhash1[5]; } temp; char const *oldstrhash1; t_hash oldpasshash1; t_hash oldpasshash2; t_hash trypasshash2; t_hash newpasshash1; if ((oldstrhash1 = account_get_pass(account))) { bn_int_set(&temp.ticks, bn_int_get(packet->u.client_changepassreq.ticks)); bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_changepassreq.sessionkey)); if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) { bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1); account_set_pass(account, hash_get_str(newpasshash1)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (bad previous password)", conn_get_socket(c), account_get_name(account)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS); } else { hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */ bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */ bnhash_to_hash(packet->u.client_changepassreq.oldpassword_hash2, &trypasshash2); if (hash_eq(trypasshash2, oldpasshash2) == 1) { bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1); account_set_pass(account, hash_get_str(newpasshash1)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (previous password)", conn_get_socket(c), account_get_name(account)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (wrong password)", conn_get_socket(c), account_get_name(account)); conn_increment_passfail_count(c); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL); } } } else { bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1); account_set_pass(account, hash_get_str(newpasshash1)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (no previous password)", conn_get_socket(c), account_get_name(account)); bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS); } } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0;}static int _client_echoreply(t_connection * c, t_packet const *const packet){ if (packet_get_size(packet) < sizeof(t_client_echoreply)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ECHOREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_echoreply), packet_get_size(packet)); return -1; } { unsigned int now; unsigned int then; now = get_ticks(); then = bn_int_get(packet->u.client_echoreply.ticks); if (!now || !then || now < then) eventlog(eventlog_level_warn, __FUNCTION__, "[%d] bad timing in echo reply: now=%u then=%u", conn_get_socket(c), now, then); else conn_set_latency(c, now - then); } return 0;}static int _client_authreq1(t_connection * c, t_packet const *const packet){ t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_authreq1)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_authreq1), packet_get_size(packet)); return -1; } { char verstr[16]; char const *exeinfo; char const *versiontag; int failed; failed = 0; if (bn_int_get(packet->u.client_authreq1.archtag) != conn_get_archtag(c)) failed = 1; if (bn_int_get(packet->u.client_authreq1.clienttag) != conn_get_clienttag(c)) failed = 1; if (!(exeinfo = packet_get_str_const(packet, sizeof(t_client_authreq1), MAX_EXEINFO_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ1 (missing or too long exeinfo)", conn_get_socket(c)); exeinfo = "badexe"; failed = 1; } conn_set_versionid(c, bn_int_get(packet->u.client_authreq1.versionid)); conn_set_checksum(c, bn_int_get(packet->u.client_authreq1.checksum)); conn_set_gameversion(c, bn_int_get(packet->u.client_authreq1.gameversion)); strcpy(verstr, vernum_to_verstr(bn_int_get(packet->u.client_authreq1.gameversion))); conn_set_clientver(c, verstr); conn_set_clientexe(c, exeinfo); eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_AUTHREQ1 archtag=0x%08x clienttag=0x%08x verstr=%s exeinfo=\"%s\" versionid=0x%08lx gameversion=0x%08lx checksum=0x%08lx", conn_get_socket(c), bn_int_get(packet->u.client_authreq1.archtag), bn_int_get(packet->u.client_authreq1.clienttag), verstr, exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c)); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_authreply1)); packet_set_type(rpacket, SERVER_AUTHREPLY1); if (!conn_get_versioncheck(c) && prefs_get_skip_versioncheck()) eventlog(eventlog_level_info, __FUNCTION__, "[%d] skip versioncheck enabled and client did not request validation", conn_get_socket(c)); else switch (versioncheck_validate(conn_get_versioncheck(c), conn_get_archtag(c), conn_get_clienttag(c), exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) { case -1: /* failed test... client has been modified */ if (!prefs_get_allow_bad_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test (marking untrusted)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test, allowing anyway", conn_get_socket(c)); break; case 0: /* not listed in table... can't tell if client has been modified */ if (!prefs_get_allow_unknown_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client (marking untrusted)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client, allowing anyway", conn_get_socket(c)); break; /* 1 == test passed... client seems to be ok */ } versiontag = versioncheck_get_versiontag(conn_get_versioncheck(c)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] client matches versiontag \"%s\"", conn_get_socket(c), versiontag); if (failed) { conn_set_state(c, conn_state_untrusted); if (bn_int_get(packet->u.client_progident.clienttag) == CLIENTTAG_DIABLO2XP_UINT) bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_D2XP_MESSAGE_BADVERSION); else bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_BADVERSION); packet_append_string(rpacket, ""); } else { char *mpqfilename; mpqfilename = autoupdate_check(conn_get_archtag(c), conn_get_clienttag(c), conn_get_gamelang(c), versiontag); /* Only handle updates when there is an update file available. */ if (mpqfilename != NULL) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] an upgrade for version %s is available \"%s\"", conn_get_socket(c), versioncheck_get_versiontag(conn_get_versioncheck(c)), mpqfilename); if (bn_int_get(packet->u.client_progident.clienttag) == CLIENTTAG_DIABLO2XP_UINT) bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_D2XP_MESSAGE_UPDATE); else bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_UPDATE); packet_append_string(rpacket, mpqfilename); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no upgrade for %s is available", conn_get_socket(c), versioncheck_get_versiontag(conn_get_versioncheck(c))); if (bn_int_get(packet->u.client_progident.clienttag) == CLIENTTAG_DIABLO2XP_UINT) bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_D2XP_MESSAGE_OK); else bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_OK); packet_append_string(rpacket, ""); } if (mpqfilename) xfree((void *) mpqfilename); } packet_append_string(rpacket, ""); /* FIXME: what's the second string for? */ conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0;}static int _client_authreq109(t_connection * c, t_packet const *const packet){ t_packet *rpacket; if (packet_get_size(packet) < sizeof(t_client_authreq_109)) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_authreq_109), packet_get_size(packet)); return 0; } { char verstr[16]; char const *exeinfo; char const *versiontag; int failed; char const *owner; unsigned int count; unsigned int pos; failed = 0; count = bn_int_get(packet->u.client_authreq_109.cdkey_number); pos = sizeof(t_client_authreq_109) + (count * sizeof(t_cdkey_info)); if (!(exeinfo = packet_get_str_const(packet, pos, MAX_EXEINFO_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 (missing or too long exeinfo)", conn_get_socket(c)); exeinfo = "badexe"; failed = 1; } conn_set_clientexe(c, exeinfo); pos += strlen(exeinfo) + 1; if (!(owner = packet_get_str_const(packet, pos, MAX_OWNER_STR))) { eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 (missing or too long owner)", conn_get_socket(c)); owner = ""; /* maybe owner was missing, use empty string */ } conn_set_owner(c, owner); conn_set_checksum(c, bn_int_get(packet->u.client_authreq_109.checksum)); conn_set_gameversion(c, bn_int_get(packet->u.client_authreq_109.gameversion)); strcpy(verstr, vernum_to_verstr(bn_int_get(packet->u.client_authreq_109.gameversion))); conn_set_clientver(c, verstr); conn_set_clientexe(c, exeinfo); eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_AUTHREQ_109 ticks=0x%08x, verstr=%s exeinfo=\"%s\" versionid=0x%08lx gameversion=0x%08lx checksum=0x%08lx", conn_get_socket(c), bn_int_get(packet->u.client_authreq_109.ticks), verstr, exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c)); if ((rpacket = packet_create(packet_class_bnet))) { packet_set_size(rpacket, sizeof(t_server_authreply_109)); packet_set_type(rpacket, SERVER_AUTHREPLY_109); if (!conn_get_versioncheck(c) && prefs_get_skip_versioncheck()) eventlog(eventlog_level_info, __FUNCTION__, "[%d] skip versioncheck enabled and client did not request validation", conn_get_socket(c)); else switch (versioncheck_validate(conn_get_versioncheck(c), conn_get_archtag(c), conn_get_clienttag(c), exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) { case -1: /* failed test... client has been modified */ if (!prefs_get_allow_bad_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test (closing connection)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test, allowing anyway", conn_get_socket(c)); break; case 0: /* not listed in table... can't tell if client has been modified */ if (!prefs_get_allow_unknown_version()) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client (closing connection)", conn_get_socket(c)); failed = 1; } else eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client, allowing anyway", conn_get_socket(c)); break; /* 1 == test passed... client seems to be ok */ } versiontag = versioncheck_get_versiontag(conn_get_versioncheck(c)); eventlog(eventlog_level_info, __FUNCTION__, "[%d] client matches versiontag \"%s\"", conn_get_socket(c), versiontag); if (failed) { conn_set_state(c, conn_state_untrusted); bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_BADVERSION); packet_append_string(rpacket, ""); } else { char *mpqfilename; mpqfilename = autoupdate_check(conn_get_archtag(c), conn_get_clienttag(c), conn_get_gamelang(c), versiontag); /* Only handle updates when there is an update file available. */ if (mpqfilename != NULL) { eventlog(eventlog_level_info, __FUNCTION__, "[%d] an upgrade for %s is available \"%s\"", conn_get_socket(c), versiontag, mpqfilename); bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_UPDATE); packet_append_string(rpacket, mpqfilename); } else { eventlog(eventlog_level_info, __FUNCTION__, "[%d] no upgrade for %s is available", conn_get_socket(c), versiontag); bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_OK); packet_append_string(rpacket, ""); } if (mpqfilename) xfree((void *) mpqfilename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -