예제 #1
0
/** Add a module failure message VALUE_PAIR to the request
 */
void module_failure_msg(REQUEST *request, char const *fmt, ...)
{
	va_list ap;
	char *p;
	VALUE_PAIR *vp;

	if (!fmt || !request->packet) {
		va_start(ap, fmt);
		va_end(ap);
		return;
	}

	va_start(ap, fmt);
	vp = paircreate(request->packet, PW_MODULE_FAILURE_MESSAGE, 0);
	if (!vp) {
		va_end(ap);
		return;
	}

	p = talloc_vasprintf(vp, fmt, ap);

	if (request->module && *request->module) {
		pairsprintf(vp, "%s: %s", request->module, p);
	} else {
		pairsprintf(vp, "%s", p);
	}
	talloc_free(p);
	pairadd(&request->packet->vps, vp);
}
예제 #2
0
/** Add a module failure message VALUE_PAIR to the request
 */
void vmodule_failure_msg(REQUEST *request, char const *fmt, va_list ap)
{
	char *p;
	VALUE_PAIR *vp;
	va_list aq;

	if (!fmt || !request->packet) {
		return;
	}

	/*
	 *  If we don't copy the original ap we get a segfault from vasprintf. This is apparently
	 *  due to ap sometimes being implemented with a stack offset which is invalidated if
	 *  ap is passed into another function. See here:
	 *  http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
	 *
	 *  I don't buy that explanation, but doing a va_copy here does prevent SEGVs seen when
	 *  running unit tests which generate errors under CI.
	 */
	va_copy(aq, ap);
	p = talloc_vasprintf(request, fmt, aq);
	va_end(aq);

	MEM(vp = pairmake_packet("Module-Failure-Message", NULL, T_OP_ADD));
	if (request->module && (request->module[0] != '\0')) {
		pairsprintf(vp, "%s: %s", request->module, p);
	} else {
		pairsprintf(vp, "%s", p);
	}
	talloc_free(p);
}
예제 #3
0
/** Add a module failure message VALUE_PAIR to the request
 */
void vmodule_failure_msg(REQUEST *request, char const *fmt, va_list ap)
{
	char *p;
	VALUE_PAIR *vp;
	va_list aq;

	if (!fmt || !request->packet) {
		return;
	}

	vp = paircreate(request->packet, PW_MODULE_FAILURE_MESSAGE, 0);
	if (!vp) {
		return;
	}

	/*
	 *  If we don't copy the original ap we get a segfault from vasprintf. This is apparently
	 *  due to ap sometimes being implemented with a stack offset which is invalidated if
	 *  ap is passed into another function. See here:
	 *  http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
	 *
	 *  I don't buy that explanation, but doing a va_copy here does prevent SEGVs seen when
	 *  running unit tests which generate errors under CI.
	 */
	va_copy(aq, ap);
	p = talloc_vasprintf(vp, fmt, aq);
	talloc_set_type(p, char);
	va_end(aq);
	if (request->module && *request->module) {
		pairsprintf(vp, "%s: %s", request->module, p);
	} else {
		pairsprintf(vp, "%s", p);
	}
	talloc_free(p);
	pairadd(&request->packet->vps, vp);
}
예제 #4
0
/**
 * @brief Parse the MS-SOH response in data and update sohvp.
 *
 * Note that sohvp might still have been updated in event of a failure.
 *
 * @param request Current request
 * @param data MS-SOH blob
 * @param data_len length of MS-SOH blob
 *
 * @return 0 on success, -1 on failure
 *
 */
int soh_verify(REQUEST *request, uint8_t const *data, unsigned int data_len) {

	VALUE_PAIR *vp;
	eap_soh hdr;
	soh_response resp;
	soh_mode_subheader mode;
	soh_tlv tlv;
	int curr_shid=-1, curr_shid_c=-1, curr_hc=-1;

	rad_assert(request->packet != NULL);

	hdr.tlv_type = soh_pull_be_16(data); data += 2;
	hdr.tlv_len = soh_pull_be_16(data); data += 2;
	hdr.tlv_vendor = soh_pull_be_32(data); data += 4;

	if (hdr.tlv_type != 7 || hdr.tlv_vendor != 0x137) {
		RDEBUG("SoH payload is %i %08x not a ms-vendor packet", hdr.tlv_type, hdr.tlv_vendor);
		return -1;
	}

	hdr.soh_type = soh_pull_be_16(data); data += 2;
	hdr.soh_len = soh_pull_be_16(data); data += 2;
	if (hdr.soh_type != 1) {
		RDEBUG("SoH tlv %04x is not a response", hdr.soh_type);
		return -1;
	}

	/* FIXME: check for sufficient data */
	resp.outer_type = soh_pull_be_16(data); data += 2;
	resp.outer_len = soh_pull_be_16(data); data += 2;
	resp.vendor = soh_pull_be_32(data); data += 4;
	resp.inner_type = soh_pull_be_16(data); data += 2;
	resp.inner_len = soh_pull_be_16(data); data += 2;


	if (resp.outer_type!=7 || resp.vendor != 0x137) {
		RDEBUG("SoH response outer type %i/vendor %08x not recognised", resp.outer_type, resp.vendor);
		return -1;
	}
	switch (resp.inner_type) {
	case 1:
		/* no mode sub-header */
		RDEBUG("SoH without mode subheader");
		break;

	case 2:
		mode.outer_type = soh_pull_be_16(data); data += 2;
		mode.outer_len = soh_pull_be_16(data); data += 2;
		mode.vendor = soh_pull_be_32(data); data += 4;
		memcpy(mode.corrid, data, 24); data += 24;
		mode.intent = data[0];
		mode.content_type = data[1];
		data += 2;

		if (mode.outer_type != 7 || mode.vendor != 0x137 || mode.content_type != 0) {
			RDEBUG3("SoH mode subheader outer type %i/vendor %08x/content type %i invalid", mode.outer_type, mode.vendor, mode.content_type);
			return -1;
		}
		RDEBUG3("SoH with mode subheader");
		break;

	default:
		RDEBUG("SoH invalid inner type %i", resp.inner_type);
		return -1;
	}

	/* subtract off the relevant amount of data */
	if (resp.inner_type==2) {
		data_len = resp.inner_len - 34;
	} else {
		data_len = resp.inner_len;
	}

	/* TLV
	 * MS-SOH 2.2.1
	 * See also 2.2.3
	 *
	 * 1 bit mandatory
	 * 1 bit reserved
	 * 14 bits tlv type
	 * 2 bytes tlv length
	 * N bytes payload
	 *
	 */
	while (data_len >= 4) {
		tlv.tlv_type = soh_pull_be_16(data); data += 2;
		tlv.tlv_len = soh_pull_be_16(data); data += 2;

		data_len -= 4;

		switch (tlv.tlv_type) {
		case 2:
			/* System-Health-Id TLV
			 * MS-SOH 2.2.3.1
			 *
			 * 3 bytes IANA/SMI vendor code
			 * 1 byte component (i.e. within vendor, which SoH component
			 */
			curr_shid = soh_pull_be_24(data);
			curr_shid_c = data[3];
			RDEBUG2("SoH System-Health-ID vendor %08x component=%i", curr_shid, curr_shid_c);
			break;

		case 7:
			/* Vendor-Specific packet
			 * MS-SOH 2.2.3.3
			 *
			 * 4 bytes vendor, supposedly ignored by NAP
			 * N bytes payload; for Microsoft component#0 this is the MS TV stuff
			 */
			if (curr_shid==0x137 && curr_shid_c==0) {
				RDEBUG2("SoH MS type-value payload");
				eapsoh_mstlv(request, data + 4, tlv.tlv_len - 4);
			} else {
				RDEBUG2("SoH unhandled vendor-specific TLV %08x/component=%i %i bytes payload",
					curr_shid, curr_shid_c, tlv.tlv_len);
			}
			break;

		case 8:
			/* Health-Class
			 * MS-SOH 2.2.3.5.6
			 *
			 * 1 byte integer
			 */
			RDEBUG2("SoH Health-Class %i", data[0]);
			curr_hc = data[0];
			break;

		case 9:
			/* Software-Version
			 * MS-SOH 2.2.3.5.7
			 *
			 * 1 byte integer
			 */
			RDEBUG2("SoH Software-Version %i", data[0]);
			break;

		case 11:
			/* Health-Class status
			 * MS-SOH 2.2.3.5.9
			 *
			 * variable data; for the MS System Health vendor, these are 4-byte
			 * integers which are a really, really dumb format:
			 *
			 *  28 bits ignore
			 *  1 bit - 1==product snoozed
			 *  1 bit - 1==microsoft product
			 *  1 bit - 1==product up-to-date
			 *  1 bit - 1==product enabled
			 */
			RDEBUG2("SoH Health-Class-Status - current shid=%08x component=%i", curr_shid, curr_shid_c);

			if (curr_shid == 0x137 && curr_shid_c == 128) {
				char const *s, *t;
				uint32_t hcstatus = soh_pull_be_32(data);

				RDEBUG2("SoH Health-Class-Status microsoft DWORD=%08x", hcstatus);

				vp = pairmake_packet("SoH-MS-Windows-Health-Status", NULL, T_OP_EQ);
				if (!vp) return 0;

				switch (curr_hc) {
				case 4:
					/* security updates */
					s = "security-updates";
					switch (hcstatus) {
					case 0xff0005:
						pairsprintf(vp, "%s ok all-installed", s);
						break;

					case 0xff0006:
						pairsprintf(vp, "%s warn some-missing", s);
						break;

					case 0xff0008:
						pairsprintf(vp, "%s warn never-started", s);
						break;

					case 0xc0ff000c:
						pairsprintf(vp, "%s error no-wsus-srv", s);
						break;

					case 0xc0ff000d:
						pairsprintf(vp, "%s error no-wsus-clid", s);
						break;

					case 0xc0ff000e:
						pairsprintf(vp, "%s warn wsus-disabled", s);
						break;

					case 0xc0ff000f:
						pairsprintf(vp, "%s error comm-failure", s);
						break;

					case 0xc0ff0010:
						pairsprintf(vp, "%s warn needs-reboot", s);
						break;

					default:
						pairsprintf(vp, "%s error %08x", s, hcstatus);
						break;
					}
					break;

				case 3:
					/* auto updates */
					s = "auto-updates";
					switch (hcstatus) {
					case 1:
						pairsprintf(vp, "%s warn disabled", s);
						break;

					case 2:
						pairsprintf(vp, "%s ok action=check-only", s);
						break;

					case 3:
						pairsprintf(vp, "%s ok action=download", s);
						break;

					case 4:
						pairsprintf(vp, "%s ok action=install", s);
						break;

					case 5:
						pairsprintf(vp, "%s warn unconfigured", s);
						break;

					case 0xc0ff0003:
						pairsprintf(vp, "%s warn service-down", s);
						break;

					case 0xc0ff0018:
						pairsprintf(vp, "%s warn never-started", s);
						break;

					default:
						pairsprintf(vp, "%s error %08x", s, hcstatus);
						break;
					}
					break;

				default:
					/* other - firewall, antivirus, antispyware */
					s = healthclass2str(curr_hc);
					if (s) {
						/* bah. this is vile. stupid microsoft
						 */
						if (hcstatus & 0xff000000) {
							/* top octet non-zero means an error
							 * FIXME: is this always correct? MS-WSH 2.2.8 is unclear
							 */
							t = clientstatus2str(hcstatus);
							if (t) {
								pairsprintf(vp, "%s error %s", s, t);
							} else {
								pairsprintf(vp, "%s error %08x", s, hcstatus);
							}
						} else {
							pairsprintf(vp,
									"%s ok snoozed=%i microsoft=%i up2date=%i enabled=%i",
									s,
									hcstatus & 0x8 ? 1 : 0,
									hcstatus & 0x4 ? 1 : 0,
									hcstatus & 0x2 ? 1 : 0,
									hcstatus & 0x1 ? 1 : 0
									);
						}
					} else {
						pairsprintf(vp, "%i unknown %08x", curr_hc, hcstatus);
					}
					break;
				}
			} else {
				vp = pairmake_packet("SoH-MS-Health-Other", NULL, T_OP_EQ);
				if (!vp) return 0;

				/* FIXME: what to do with the payload? */
				pairsprintf(vp, "%08x/%i ?", curr_shid, curr_shid_c);
			}
			break;

		default:
			RDEBUG("SoH Unknown TLV %i len=%i", tlv.tlv_type, tlv.tlv_len);
			break;
		}

		data += tlv.tlv_len;
		data_len -= tlv.tlv_len;
	}

	return 0;
}