+/*
+ * Send an MS SoH request
+ */
+static int eappeap_soh(EAP_HANDLER *handler, tls_session_t *tls_session)
+{
+ uint8_t tlv_packet[20];
+
+ tlv_packet[0] = 254; /* extended type */
+
+ tlv_packet[1] = 0;
+ tlv_packet[2] = 0x01; /* ms vendor */
+ tlv_packet[3] = 0x37;
+
+ tlv_packet[4] = 0; /* ms soh eap */
+ tlv_packet[5] = 0;
+ tlv_packet[6] = 0;
+ tlv_packet[7] = 0x21;
+
+ tlv_packet[8] = 0; /* vendor-spec tlv */
+ tlv_packet[9] = 7;
+
+ tlv_packet[10] = 0;
+ tlv_packet[11] = 8; /* payload len */
+
+ tlv_packet[12] = 0; /* ms vendor */
+ tlv_packet[13] = 0;
+ tlv_packet[14] = 0x01;
+ tlv_packet[15] = 0x37;
+
+ tlv_packet[16] = 0;
+ tlv_packet[17] = 2;
+ tlv_packet[18] = 0;
+ tlv_packet[19] = 0;
+
+ (tls_session->record_plus)(&tls_session->clean_in, tlv_packet, 20);
+ tls_handshake_send(handler->request, tls_session);
+ return 1;
+}
+
+static VALUE_PAIR* eapsoh_verify(REQUEST *request, const uint8_t *data, unsigned int data_len) {
+
+ VALUE_PAIR *vp;
+ uint8_t eap_type_base;
+ uint32_t eap_vendor;
+ uint32_t eap_type;
+ int rv;
+
+ vp = pairmake("SoH-Supported", "no", T_OP_EQ);
+ if (data && data[0] == PW_EAP_NAK) {
+ RDEBUG("SoH - client NAKed");
+ goto done;
+ }
+
+ if (!data || data_len < 8) {
+ RDEBUG("SoH - eap payload too short");
+ goto done;
+ }
+
+ eap_type_base = *data++;
+ if (eap_type_base != 254) {
+ RDEBUG("SoH - response is not extended EAP: %i", eap_type_base);
+ goto done;
+ }
+
+ eap_vendor = soh_pull_be_24(data); data += 3;
+ if (eap_vendor != 0x137) {
+ RDEBUG("SoH - extended eap vendor %08x is not Microsoft", eap_vendor);
+ goto done;
+ }
+
+ eap_type = soh_pull_be_32(data); data += 4;
+ if (eap_type != 0x21) {
+ RDEBUG("SoH - response eap type %08x is not EAP-SoH", eap_type);
+ goto done;
+ }
+
+
+ rv = soh_verify(request, vp, data, data_len - 8);
+ if (rv<0) {
+ RDEBUG("SoH - error decoding payload");
+ } else {
+ vp->vp_integer = 1;
+ }
+done:
+ return vp;
+}