static void ews_set_threading_data (CamelMessageInfo *mi, EEwsItem *item) { const gchar *references_str, *inreplyto_str; const gchar *message_id; GSList *refs, *irt, *link; guint8 *digest; gchar *msgid; CamelSummaryMessageID tmp_msgid; GArray *references; /* set message id */ message_id = e_ews_item_get_msg_id (item); msgid = camel_header_msgid_decode (message_id); if (msgid) { digest = get_md5_digest ((const guchar *) msgid); memcpy (tmp_msgid.id.hash, digest, sizeof (tmp_msgid.id.hash)); g_free (digest); g_free (msgid); camel_message_info_set_message_id (mi, tmp_msgid.id.id); } /* Process References: header */ references_str = e_ews_item_get_references (item); refs = camel_header_references_decode (references_str); /* Prepend In-Reply-To: contents to References: for summary info */ inreplyto_str = e_ews_item_get_in_replyto (item); irt = camel_header_references_decode (inreplyto_str); if (irt) { refs = g_slist_concat (irt, refs); } if (!refs) return; references = g_array_sized_new (FALSE, FALSE, sizeof (guint64), g_slist_length (refs)); for (link = refs; link; link = g_slist_next (link)) { digest = get_md5_digest ((const guchar *) link->data); memcpy (tmp_msgid.id.hash, digest, sizeof (tmp_msgid.id.hash)); g_free (digest); g_array_append_val (references, tmp_msgid.id.id); } g_slist_free_full (refs, g_free); camel_message_info_take_references (mi, references); }
int send_logout_auth() { if (challenge.empty()) return -1; if (auth_info.empty()) return -1; U31_LOG_INFO("Send Logout Auth." << std::endl); std::vector<uint8_t> pkt_data; /************************ Header *******************/ // Code, Type, EOF, UserName Length + 20 auto length = ((username.length() <= 36) ? username.length() : 36) + 20; pkt_data.insert(pkt_data.end(), { 0x06, 0x01, 0x00, (uint8_t) length }); /********************** MD5A **************************/ // Function_MD5A = MD5(code + type + Challenge + Password) std::vector<uint8_t> md5a_content = { 0x06, 0x01 /* Code, Type */ }; md5a_content.insert(md5a_content.end(), challenge.begin(), challenge.end()); md5a_content.insert(md5a_content.end(), password.begin(), password.end()); login_md5_a = get_md5_digest(md5a_content); pkt_data.insert(pkt_data.end(), login_md5_a.begin(), login_md5_a.end()); /********************** UserName *********************/ std::vector<uint8_t> username_block(36, 0); // fixed length = 36 memcpy(&username_block[0], &username[0], username.length() <= 36 ? username.length() : 36); pkt_data.insert(pkt_data.end(), username_block.begin(), username_block.end()); /********************** Conf *************************/ // 0x20, 0x05 On Windows pkt_data.insert(pkt_data.end(), { 0x00, 0x00 });// On OSX /********************** MAC xor MD5A *****************/ for (int i = 0; i < local_mac.size(); i++) pkt_data.push_back(local_mac[i] ^ login_md5_a[i]); /********************** Auth Info ********************/ pkt_data.insert(pkt_data.end(), auth_info.begin(), auth_info.end()); U31_LOG_SEND_DUMP auto handler_success = [&](std::vector<uint8_t> recv) -> int { U31_LOG_RECV_DUMP("Send Logout Auth"); if (recv[0] != 0x04) // Success return -1; U31_LOG_INFO("Logged out." << std::endl); challenge.clear(); login_md5_a.clear(); auth_info.clear(); total_time = total_flux = balance = online_time = pkt_id = misc3_flux = misc1_flux = 0; return 0; }; U31_HANDLE_ERROR("Send Logout Auth"); U31_AUTO_RETRY("Send Logout Auth"); }
/* * === FUNCTION ====================================================================== * Name: fill_password_md5 * Description: 给RESPONSE_MD5_Challenge报文填充相应的MD5值。 * 只会在接受到REQUEST_MD5_Challenge报文之后才进行,因为需要 * 其中的Key * ===================================================================================== */ void fill_password_md5(uint8_t attach_key[], uint8_t eap_id) { char *psw_key; char *md5; psw_key = malloc(1 + password_length + 16); psw_key[0] = eap_id; memcpy (psw_key + 1, password, password_length); memcpy (psw_key + 1 + password_length, attach_key, 16); md5 = get_md5_digest(psw_key, 1 + password_length + 16); memcpy (eap_response_md5ch + 14 + 10, md5, 16); free (psw_key); }
/* * === FUNCTION ====================================================================== * Name: fill_uname_md5 * Description: 给RESPONSE_MD5_KEEP_ALIVE报文填充相应的MD5值。 * 只会在接受到REQUEST_MD5_KEEP_ALIVE报文之后才进行,因为需要 * 其中的Key * ===================================================================================== */ void fill_uname_md5(uint8_t attach_key[], uint8_t eap_id) { char *uname_key; char *md5; uname_key = malloc(username_length + 4); memcpy (uname_key, username, username_length); memcpy (uname_key + username_length, attach_key, 4); md5 = get_md5_digest(uname_key,username_length + 4); eap_response_md5keep[14+5]=eap_id; memcpy (eap_response_md5keep + 13 + 10, md5, 16); free (uname_key); }
int send_login_auth() { if (challenge.empty()) return -1; U31_LOG_INFO("Send Login Auth." << std::endl); U31_LOG_DBG("username = "******", password = "******"Send Login Auth"); if (recv[0] != 0x04 && recv[0] != 0x05) // Success/Failure return -1; if (recv[0] == 0x05) // Failure { switch (recv[4]) { case 0x01: // Already online U31_LOG_ERR("This account has already been online at IP: " << (int)recv[5] << "." << (int)recv[6] << "." << (int)recv[7] << "." << (int)recv[8] << ", MAC: " << hextostr(&recv[9], 6, ':') << std::endl); break; case 0x03: // Username or password wrong! U31_LOG_ERR("Username or password wrong!" << std::endl); break; case 0x05: // No money U31_LOG_ERR("No money in your account!" << std::endl); break; case 0x0b: // Wrong MAC U31_LOG_ERR("Wrong MAC, should be " << hextostr(&recv[5], 6, ':') << std::endl); break; default: U31_LOG_ERR("Unkown failure: 0x" << std::hex << (int)recv[4] << std::endl); break; } return 1; // Don't retry when failure } U31_LOG_INFO("Gateway return: Success." << std::endl); // Success auth_info.insert(auth_info.end(), recv.begin() + 23, recv.begin() + 23 + 16); // 16 bytes from Success // Captured memcpy(&total_time, &recv[5], 4); memcpy(&total_flux, &recv[9], 4); memcpy(&balance, &recv[13], 4); #ifdef OPENWRT // network order on openwrt total_time = TO_LITTLE_ENDIAN(total_time); total_flux = TO_LITTLE_ENDIAN(total_flux); balance = TO_LITTLE_ENDIAN(balance); #endif U31_LOG_INFO("Login auth succeeded! User info: " << std::endl); U31_LOG_INFO("Used Time: " << total_time << " Minutes, Used Flux: " << (total_flux & 0x0FFFFFFFF) / 1024.0 << " MB, Balance: " << (balance & 0x0FFFFFFFF) / 100.0 << " RMB" << std::endl); return 0; }; U31_HANDLE_ERROR("Send Login Auth"); U31_AUTO_RETRY("Send Login Auth"); }
/* * === FUNCTION ====================================================================== * Name: init_frames * Description: 初始化发送帧的数据 * ===================================================================================== */ void init_frames() { int data_index; /***** EAPOL Header *******/ uint8_t eapol_eth_header[SIZE_ETHERNET]; struct ether_header *eth = (struct ether_header *)eapol_eth_header; memcpy (eth->ether_dhost, muticast_mac, 6); memcpy (eth->ether_shost, local_mac, 6); eth->ether_type = htons (0x888e); /**** EAPol START ****/ uint8_t start_data[4] = {0x01, 0x01, 0x00, 0x00}; memcpy (eapol_start, eapol_eth_header, 14); memcpy (eapol_start + 14, start_data, 4); /****EAPol LOGOFF ****/ uint8_t logoff_data[4] = {0x01, 0x02, 0x00, 0x00}; memcpy (eapol_logoff, eapol_eth_header, 14); memcpy (eapol_logoff + 14, logoff_data, 4); /****DCBA Private Info Tailer ***/ uint8_t local_info_tailer[46] = {0}; local_info_tailer[0] = dhcp_on; struct dcba_tailer *dcba_info_tailer = (struct dcba_tailer *)(local_info_tailer + 1); dcba_info_tailer->local_ip = local_ip; dcba_info_tailer->local_mask = local_mask; dcba_info_tailer->local_gateway = local_gateway; dcba_info_tailer->local_dns = local_dns; char* username_md5 = get_md5_digest(username, username_length); memcpy (dcba_info_tailer->username_md5, username_md5, 16); strncpy ((char*)dcba_info_tailer->client_ver, client_ver, 13); // print_hex (local_info_tailer, 46); /* EAP RESPONSE IDENTITY */ uint8_t eap_resp_iden_head[9] = {0x01, 0x00, 0x00, 5 + 46 + username_length, /* eapol_length */ 0x02, 0x01, 0x00, 5 + username_length, /* eap_length */ 0x01}; eap_response_ident = malloc (14 + 9 + username_length + 46); memset (eap_response_ident, 0, 14 + 9 + username_length + 46); data_index = 0; memcpy (eap_response_ident + data_index, eapol_eth_header, 14); data_index += 14; memcpy (eap_response_ident + data_index, eap_resp_iden_head, 9); data_index += 9; memcpy (eap_response_ident + data_index, username, username_length); data_index += username_length; memcpy (eap_response_ident + data_index, local_info_tailer, 46); // print_hex (eap_response_ident, 14 + 9 + username_length + 46); /** EAP RESPONSE MD5 Challenge **/ uint8_t eap_resp_md5_head[10] = {0x01, 0x00, 0x00, 6 + 16 + username_length + 46, /* eapol-length */ 0x02, 0x02, 0x00, 6 + 16 + username_length, /* eap-length */ 0x04, 0x10}; eap_response_md5ch = malloc (14 + 4 + 6 + 16 + username_length + 46); data_index = 0; memcpy (eap_response_md5ch + data_index, eapol_eth_header, 14); data_index += 14; memcpy (eap_response_md5ch + data_index, eap_resp_md5_head, 10); data_index += 26;// 剩余16位在收到REQ/MD5报文后由fill_password_md5填充 memcpy (eap_response_md5ch + data_index, username, username_length); data_index += username_length; memcpy (eap_response_md5ch + data_index, local_info_tailer, 46); // print_hex (eap_response_md5ch, 14 + 4 + 6 + 16 + username_length + 46); }