📄 tncc.c
字号:
char *pos, *pos2; unsigned char *decoded; pos = os_strstr(start, "<Base64>"); if (pos == NULL) return NULL; pos += 8; pos2 = os_strstr(pos, "</Base64>"); if (pos2 == NULL) return NULL; *pos2 = '\0'; decoded = base64_decode((unsigned char *) pos, os_strlen(pos), decoded_len); *pos2 = '<'; if (decoded == NULL) { wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); } return decoded;}static enum tncc_process_res tncc_get_recommendation(char *start){ char *pos, *pos2, saved; int recom; pos = os_strstr(start, "<TNCCS-Recommendation "); if (pos == NULL) return TNCCS_RECOMMENDATION_ERROR; pos += 21; pos = os_strstr(pos, " type="); if (pos == NULL) return TNCCS_RECOMMENDATION_ERROR; pos += 6; if (*pos == '"') pos++; pos2 = pos; while (*pos2 != '\0' && *pos2 != '"' && *pos2 != '>') pos2++; if (*pos2 == '\0') return TNCCS_RECOMMENDATION_ERROR; saved = *pos2; *pos2 = '\0'; wpa_printf(MSG_DEBUG, "TNC: TNCCS-Recommendation: '%s'", pos); recom = TNCCS_RECOMMENDATION_ERROR; if (os_strcmp(pos, "allow") == 0) recom = TNCCS_RECOMMENDATION_ALLOW; else if (os_strcmp(pos, "none") == 0) recom = TNCCS_RECOMMENDATION_NONE; else if (os_strcmp(pos, "isolate") == 0) recom = TNCCS_RECOMMENDATION_ISOLATE; *pos2 = saved; return recom;}enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc, const u8 *msg, size_t len){ char *buf, *start, *end, *pos, *pos2, *payload; unsigned int batch_id; unsigned char *decoded; size_t decoded_len; enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION; int recommendation_msg = 0; buf = os_malloc(len + 1); if (buf == NULL) return TNCCS_PROCESS_ERROR; os_memcpy(buf, msg, len); buf[len] = '\0'; start = os_strstr(buf, "<TNCCS-Batch "); end = os_strstr(buf, "</TNCCS-Batch>"); if (start == NULL || end == NULL || start > end) { os_free(buf); return TNCCS_PROCESS_ERROR; } start += 13; while (*start == ' ') start++; *end = '\0'; pos = os_strstr(start, "BatchId="); if (pos == NULL) { os_free(buf); return TNCCS_PROCESS_ERROR; } pos += 8; if (*pos == '"') pos++; batch_id = atoi(pos); wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", batch_id); if (batch_id != tncc->last_batchid + 1) { wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " "%u (expected %u)", batch_id, tncc->last_batchid + 1); os_free(buf); return TNCCS_PROCESS_ERROR; } tncc->last_batchid = batch_id; while (*pos != '\0' && *pos != '>') pos++; if (*pos == '\0') { os_free(buf); return TNCCS_PROCESS_ERROR; } pos++; payload = start; /* * <IMC-IMV-Message> * <Type>01234567</Type> * <Base64>foo==</Base64> * </IMC-IMV-Message> */ while (*start) { char *endpos; unsigned int type; pos = os_strstr(start, "<IMC-IMV-Message>"); if (pos == NULL) break; start = pos + 17; end = os_strstr(start, "</IMC-IMV-Message>"); if (end == NULL) break; *end = '\0'; endpos = end; end += 18; if (tncc_get_type(start, &type) < 0) { *endpos = '<'; start = end; continue; } wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); decoded = tncc_get_base64(start, &decoded_len); if (decoded == NULL) { *endpos = '<'; start = end; continue; } tncc_send_to_imcs(tncc, type, decoded, decoded_len); os_free(decoded); start = end; } /* * <TNCC-TNCS-Message> * <Type>01234567</Type> * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML> * <Base64>foo==</Base64> * </TNCC-TNCS-Message> */ start = payload; while (*start) { unsigned int type; char *xml, *xmlend, *endpos; pos = os_strstr(start, "<TNCC-TNCS-Message>"); if (pos == NULL) break; start = pos + 19; end = os_strstr(start, "</TNCC-TNCS-Message>"); if (end == NULL) break; *end = '\0'; endpos = end; end += 20; if (tncc_get_type(start, &type) < 0) { *endpos = '<'; start = end; continue; } wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", type); /* Base64 OR XML */ decoded = NULL; xml = NULL; xmlend = NULL; pos = os_strstr(start, "<XML>"); if (pos) { pos += 5; pos2 = os_strstr(pos, "</XML>"); if (pos2 == NULL) { *endpos = '<'; start = end; continue; } xmlend = pos2; xml = pos; } else { decoded = tncc_get_base64(start, &decoded_len); if (decoded == NULL) { *endpos = '<'; start = end; continue; } } if (decoded) { wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: TNCC-TNCS-Message Base64", decoded, decoded_len); os_free(decoded); } if (xml) { wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: TNCC-TNCS-Message XML", (unsigned char *) xml, xmlend - xml); } if (type == TNC_TNCCS_RECOMMENDATION && xml) { /* * <TNCCS-Recommendation type="allow"> * </TNCCS-Recommendation> */ *xmlend = '\0'; res = tncc_get_recommendation(xml); *xmlend = '<'; recommendation_msg = 1; } start = end; } os_free(buf); if (recommendation_msg) tncc_notify_recommendation(tncc, res); return res;}#ifdef CONFIG_NATIVE_WINDOWSstatic int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive){ HKEY hk, hk2; LONG ret; DWORD i; struct tnc_if_imc *imc, *last; int j; last = tncc->imc; while (last && last->next) last = last->next; ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS, &hk); if (ret != ERROR_SUCCESS) return 0; for (i = 0; ; i++) { TCHAR name[255], *val; DWORD namelen, buflen; namelen = 255; ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL, NULL); if (ret == ERROR_NO_MORE_ITEMS) break; if (ret != ERROR_SUCCESS) { wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x", (unsigned int) ret); break; } if (namelen >= 255) namelen = 255 - 1; name[namelen] = '\0'; wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name); ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2); if (ret != ERROR_SUCCESS) { wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR "'", name); continue; } ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL, &buflen); if (ret != ERROR_SUCCESS) { wpa_printf(MSG_DEBUG, "TNC: Could not read Path from " "IMC key '" TSTR "'", name); RegCloseKey(hk2); continue; } val = os_malloc(buflen); if (val == NULL) { RegCloseKey(hk2); continue; } ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, (LPBYTE) val, &buflen); if (ret != ERROR_SUCCESS) { os_free(val); RegCloseKey(hk2); continue; } RegCloseKey(hk2); wpa_unicode2ascii_inplace(val); wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val); for (j = 0; j < TNC_MAX_IMC_ID; j++) { if (tnc_imc[j] == NULL) break; } if (j >= TNC_MAX_IMC_ID) { wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); os_free(val); continue; } imc = os_zalloc(sizeof(*imc)); if (imc == NULL) { os_free(val); break; } imc->imcID = j; wpa_unicode2ascii_inplace(name); imc->name = os_strdup((char *) name); imc->path = os_strdup((char *) val); os_free(val); if (last == NULL) tncc->imc = imc; else last->next = imc; last = imc; tnc_imc[imc->imcID] = imc; } RegCloseKey(hk); return 0;}static int tncc_read_config(struct tncc_data *tncc){ if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 || tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0) return -1; return 0;}#else /* CONFIG_NATIVE_WINDOWS */static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error){ struct tnc_if_imc *imc; char *pos, *pos2; int i; for (i = 0; i < TNC_MAX_IMC_ID; i++) { if (tnc_imc[i] == NULL) break; } if (i >= TNC_MAX_IMC_ID) { wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); return NULL; } imc = os_zalloc(sizeof(*imc)); if (imc == NULL) { *error = 1; return NULL; } imc->imcID = i; pos = start; wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos); if (pos + 1 >= end || *pos != '"') { wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " "(no starting quotation mark)", start); os_free(imc); return NULL; } pos++; pos2 = pos; while (pos2 < end && *pos2 != '"') pos2++; if (pos2 >= end) { wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " "(no ending quotation mark)", start); os_free(imc); return NULL; } *pos2 = '\0'; wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); imc->name = os_strdup(pos); pos = pos2 + 1; if (pos >= end || *pos != ' ') { wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " "(no space after name)", start); os_free(imc); return NULL; } pos++; wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos); imc->path = os_strdup(pos); tnc_imc[imc->imcID] = imc; return imc;}static int tncc_read_config(struct tncc_data *tncc){ char *config, *end, *pos, *line_end; size_t config_len; struct tnc_if_imc *imc, *last; last = NULL; config = os_readfile(TNC_CONFIG_FILE, &config_len); if (config == NULL) { wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " "file '%s'", TNC_CONFIG_FILE); return -1; } end = config + config_len; for (pos = config; pos < end; pos = line_end + 1) { line_end = pos; while (*line_end != '\n' && *line_end != '\r' && line_end < end) line_end++; *line_end = '\0'; if (os_strncmp(pos, "IMC ", 4) == 0) { int error = 0; imc = tncc_parse_imc(pos + 4, line_end, &error); if (error) return -1; if (imc) { if (last == NULL) tncc->imc = imc; else last->next = imc; last = imc; } } } os_free(config); return 0;}#endif /* CONFIG_NATIVE_WINDOWS */struct tncc_data * tncc_init(void){ struct tncc_data *tncc; struct tnc_if_imc *imc; tncc = os_zalloc(sizeof(*tncc)); if (tncc == NULL) return NULL; /* TODO: * move loading and Initialize() to a location that is not * re-initialized for every EAP-TNC session (?) */ if (tncc_read_config(tncc) < 0) { wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); goto failed; } for (imc = tncc->imc; imc; imc = imc->next) { if (tncc_load_imc(imc)) { wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'", imc->name); goto failed; } } return tncc;failed: tncc_deinit(tncc); return NULL;}void tncc_deinit(struct tncc_data *tncc){ struct tnc_if_imc *imc, *prev; imc = tncc->imc; while (imc) { tncc_unload_imc(imc); prev = imc; imc = imc->next; os_free(prev); } os_free(tncc);}static struct wpabuf * tncc_build_soh(void){ struct wpabuf *buf; u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end; u8 correlation_id[24]; int ver = 2; if (os_get_random(correlation_id, sizeof(correlation_id))) return NULL; wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID", correlation_id, sizeof(correlation_id)); buf = wpabuf_alloc(200); if (buf == NULL) return NULL; /* Vendor-Specific TLV (Microsoft) - SoH */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ tlv_len = wpabuf_put(buf, 2); /* Length */ wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */ tlv_len2 = wpabuf_put(buf, 2); /* Length */ /* SoH Header */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */ outer_len = wpabuf_put(buf, 2); wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ wpabuf_put_be16(buf, ver); /* Inner Type */ inner_len = wpabuf_put(buf, 2); if (ver == 2) { /* SoH Mode Sub-Header */ /* Outer Type */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */ wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ /* Value: */ wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */ wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */ } /* SSoH TLV */ /* System-Health-Id */ wpabuf_put_be16(buf, 0x0002); /* Type */ wpabuf_put_be16(buf, 4); /* Length */ wpabuf_put_be32(buf, 79616); /* Vendor-Specific Attribute */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); ssoh_len = wpabuf_put(buf, 2); wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ /* TODO: MS-Machine-Inventory */ /* TODO: MS-Quarantine-State */ /* MS-Packet-Info */ wpabuf_put_u8(buf, 0x03); wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */ /* TODO: MS-MachineName */ /* MS-CorrelationId */ wpabuf_put_u8(buf, 0x06); wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); end = wpabuf_put(buf, 0); WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2); /* TODO: SoHReportEntry TLV (zero or more) */ /* Update length fields */ end = wpabuf_put(buf, 0); WPA_PUT_BE16(tlv_len, end - tlv_len - 2); WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2); WPA_PUT_BE16(outer_len, end - outer_len - 2); WPA_PUT_BE16(inner_len, end - inner_len - 2); return buf;}struct wpabuf * tncc_process_soh_request(const u8 *data, size_t len){ const u8 *pos; wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len); if (len < 12) return NULL; /* SoH Request */ pos = data; /* TLV Type */ if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV) return NULL; pos += 2; /* Length */ if (WPA_GET_BE16(pos) < 8) return NULL; pos += 2; /* Vendor_Id */ if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT) return NULL; pos += 4; /* TLV Type */ if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */) return NULL; wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received"); return tncc_build_soh();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -