+ p = msg;
+ q = p + sizeof(msg); /* points 1 byte past msg */
+
+ if (code == CHAP_SUCCESS) {
+#ifdef CHAPMS
+ if (cstate->chal_type == CHAP_MICROSOFT_V2) {
+ /*
+ * Per RFC 2759, success message must be formatted as
+ * "S=<auth_string> M=<message>"
+ * where
+ * <auth_string> is the Authenticator Response (mutual auth)
+ * <message> is a text message
+ *
+ * However, some versions of Windows (win98 tested) do not know
+ * about the M=<message> part (required per RFC 2759) and flag
+ * it as an error (reported incorrectly as an encryption error
+ * to the user). Since the RFC requires it, and it can be
+ * useful information, we supply it if the peer is a conforming
+ * system. Luckily (?), win98 sets the Flags field to 0x04
+ * (contrary to RFC requirements) so we can use that to
+ * distinguish between conforming and non-conforming systems.
+ *
+ * Special thanks to Alex Swiridov <say@real.kharkov.ua> for
+ * help debugging this.
+ */
+ slprintf(p, q - p, "S=");
+ p += 2;
+ slprintf(p, q - p, "%s", cstate->saresponse);
+ p += strlen(cstate->saresponse);
+ if (cstate->resp_flags != 0)
+ goto msgdone;
+ slprintf(p, q - p, " M=");
+ p += 3;
+ }
+#endif /* CHAPMS */
+
+ slprintf(p, q - p, "Welcome to %s.", hostname);
+ } else {
+#ifdef CHAPMS
+ if ((cstate->chal_type == CHAP_MICROSOFT_V2) ||
+ (cstate->chal_type == CHAP_MICROSOFT)) {
+ /*
+ * Failure message must be formatted as
+ * "E=e R=r C=c V=v M=m"
+ * where
+ * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE)
+ * r = retry (we use 1, ok to retry)
+ * c = challenge to use for next response, we reuse previous
+ * v = Change Password version supported, we use 0
+ * m = text message
+ *
+ * The M=m part is only for MS-CHAPv2, but MS-CHAP should ignore
+ * any extra text according to RFC 2433. So we'll go the easy
+ * (read: lazy) route and include it always. Neither win2k nor
+ * win98 (others untested) display the message to the user anyway.
+ * They also both ignore the E=e code.
+ *
+ * Note that it's safe to reuse the same challenge as we don't
+ * actually accept another response based on the error message
+ * (and no clients try to resend a response anyway).
+ *
+ * Basically, this whole bit is useless code, even the small
+ * implementation here is only because of overspecification.
+ */
+ int i;
+
+ slprintf(p, q - p, "E=691 R=1 C=");
+ p += 12;
+ for (i = 0; i < cstate->chal_len; i++)
+ sprintf(p + i * 2, "%02X", cstate->challenge[i]);
+ p += cstate->chal_len * 2;
+ slprintf(p, q - p, " V=0 M=");
+ p += 7;
+ }
+#endif /* CHAPMS */
+
+ slprintf(p, q - p, "I don't like you. Go 'way.");
+ }
+#ifdef CHAPMS
+msgdone:
+#endif