- /* generate MD based on negotiated type */
- switch (cstate->chal_type) {
-
- case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
- if (remmd_len != MD5_SIGNATURE_SIZE)
- break; /* it's not even the right length */
- MD5Init(&mdContext);
- MD5Update(&mdContext, &cstate->chal_id, 1);
- MD5Update(&mdContext, secret, secret_len);
- MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
- MD5Final(&mdContext);
-
- /* compare local and remote MDs and send the appropriate status */
- if (bcmp (mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0)
- code = CHAP_SUCCESS; /* they are the same! */
- break;
-
- default:
- CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->chal_type));
+ /* If a plugin will verify the response, let the plugin do it. */
+ if (chap_auth_hook) {
+ code = (*chap_auth_hook) ( (explicit_remote ? remote_name : rhostname),
+ remmd, (int) remmd_len,
+ cstate );
+ } else {
+ if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname),
+ cstate->chal_name, secret, &secret_len, 1)) {
+ warn("No CHAP secret found for authenticating %q", rhostname);
+ } else {
+
+ /* generate MD based on negotiated type */
+ switch (cstate->chal_type) {
+
+ case CHAP_DIGEST_MD5:
+ if (remmd_len != MD5_SIGNATURE_SIZE)
+ break; /* not even the right length */
+ MD5Init(&mdContext);
+ MD5Update(&mdContext, &cstate->chal_id, 1);
+ MD5Update(&mdContext, secret, secret_len);
+ MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
+ MD5Final(hash, &mdContext);
+
+ /* compare MDs and send the appropriate status */
+ if (memcmp(hash, remmd, MD5_SIGNATURE_SIZE) == 0)
+ code = CHAP_SUCCESS; /* they are the same! */
+ break;
+
+#ifdef CHAPMS
+ case CHAP_MICROSOFT:
+ {
+ int response_offset, response_size;
+ MS_ChapResponse *rmd = (MS_ChapResponse *) remmd;
+ MS_ChapResponse md;
+
+ if (remmd_len != MS_CHAP_RESPONSE_LEN)
+ break; /* not even the right length */
+
+ /* Determine which part of response to verify against */
+ if (rmd->UseNT[0]) {
+ response_offset = offsetof(MS_ChapResponse, NTResp);
+ response_size = sizeof(rmd->NTResp);
+ } else {
+#ifdef MSLANMAN
+ response_offset = offsetof(MS_ChapResponse, LANManResp);
+ response_size = sizeof(rmd->LANManResp);
+#else
+ /* Should really propagate this into the error packet. */
+ notice("Peer request for LANMAN auth not supported");
+ break;
+#endif /* MSLANMAN */
+ }
+
+ /* Generate the expected response. */
+ ChapMS(cstate, cstate->challenge, secret, secret_len, &md);
+
+ /* compare MDs and send the appropriate status */
+ if (memcmp((u_char *) &md + response_offset,
+ (u_char *) remmd + response_offset,
+ response_size) == 0)
+ code = CHAP_SUCCESS; /* they are the same! */
+ break;
+ }
+
+ case CHAP_MICROSOFT_V2:
+ {
+ MS_Chap2Response *rmd = (MS_Chap2Response *) remmd;
+ MS_Chap2Response md;
+
+ if (remmd_len != MS_CHAP2_RESPONSE_LEN)
+ break; /* not even the right length */
+
+ /* Generate the expected response and our mutual auth. */
+ ChapMS2(cstate, cstate->challenge, rmd->PeerChallenge,
+ (explicit_remote? remote_name: rhostname),
+ secret, secret_len, &md,
+ cstate->saresponse, MS_CHAP2_AUTHENTICATOR);
+
+ /* compare MDs and send the appropriate status */
+ if (memcmp(md.NTResp, rmd->NTResp, sizeof(md.NTResp)) == 0)
+ code = CHAP_SUCCESS; /* yay! */
+ break;
+ }
+#endif /* CHAPMS */
+
+ default:
+ CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
+ }