- u_char *outp;
- int outlen, msglen;
- char msg[256];
-
- if (code == CHAP_SUCCESS)
- sprintf(msg, "Welcome to %s.", hostname);
- else
- sprintf(msg, "I don't like you. Go 'way.");
- msglen = strlen(msg);
-
- outlen = CHAP_HEADERLEN + msglen;
- outp = outpacket_buf;
-
- MAKEHEADER(outp, CHAP); /* paste in a header */
-
- PUTCHAR(code, outp);
- PUTCHAR(cstate->chal_id, outp);
- PUTSHORT(outlen, outp);
- BCOPY(msg, outp, msglen);
- output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN);
-
- CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code,
- cstate->chal_id));
+ int response_len, ok, mlen;
+ unsigned char *response, *p;
+ char *name = NULL;
+ chap_verify_hook_fn *verifier;
+ char rname[MAXNAMELEN+1];
+
+ if ((ss->flags & LOWERUP) == 0)
+ return;
+ if (id != ss->challenge[PPP_HDRLEN+1] || len < 2)
+ return;
+ if (ss->flags & CHALLENGE_VALID) {
+ response = pkt;
+ GETCHAR(response_len, pkt);
+ len -= response_len + 1; /* length of name */
+ name = (char *)pkt + response_len;
+ if (len < 0)
+ return;
+
+ if (ss->flags & TIMEOUT_PENDING) {
+ ss->flags &= ~TIMEOUT_PENDING;
+ UNTIMEOUT(chap_server_timeout, ss);
+ }
+
+ if (explicit_remote) {
+ name = remote_name;
+ } else {
+ /* Null terminate and clean remote name. */
+ slprintf(rname, sizeof(rname), "%.*v", len, name);
+ name = rname;
+
+ /* strip the MS domain name */
+ if (chapms_strip_domain && strrchr(rname, '\\')) {
+ char tmp[MAXNAMELEN+1];
+
+ strcpy(tmp, strrchr(rname, '\\') + 1);
+ strcpy(rname, tmp);
+ }
+ }
+
+ if (chap_verify_hook)
+ verifier = chap_verify_hook;
+ else
+ verifier = chap_verify_response;
+ ok = (*verifier)(name, ss->name, id, ss->digest,
+ ss->challenge + PPP_HDRLEN + CHAP_HDRLEN,
+ response, ss->message, sizeof(ss->message));
+ if (!ok || !auth_number()) {
+ ss->flags |= AUTH_FAILED;
+ warn("Peer %q failed CHAP authentication", name);
+ }
+ } else if ((ss->flags & AUTH_DONE) == 0)
+ return;
+
+ /* send the response */
+ p = outpacket_buf;
+ MAKEHEADER(p, PPP_CHAP);
+ mlen = strlen(ss->message);
+ len = CHAP_HDRLEN + mlen;
+ p[0] = (ss->flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
+ p[1] = id;
+ p[2] = len >> 8;
+ p[3] = len;
+ if (mlen > 0)
+ memcpy(p + CHAP_HDRLEN, ss->message, mlen);
+ output(0, outpacket_buf, PPP_HDRLEN + len);
+
+ if (ss->flags & CHALLENGE_VALID) {
+ ss->flags &= ~CHALLENGE_VALID;
+ if (!(ss->flags & AUTH_DONE) && !(ss->flags & AUTH_FAILED)) {
+ /*
+ * Auth is OK, so now we need to check session restrictions
+ * to ensure everything is OK, but only if we used a
+ * plugin, and only if we're configured to check. This
+ * allows us to do PAM checks on PPP servers that
+ * authenticate against ActiveDirectory, and use AD for
+ * account info (like when using Winbind integrated with
+ * PAM).
+ */
+ if (session_mgmt &&
+ session_check(name, NULL, devnam, NULL) == 0) {
+ ss->flags |= AUTH_FAILED;
+ warn("Peer %q failed CHAP Session verification", name);
+ }
+ }
+ if (ss->flags & AUTH_FAILED) {
+ auth_peer_fail(0, PPP_CHAP);
+ } else {
+ if ((ss->flags & AUTH_DONE) == 0)
+ auth_peer_success(0, PPP_CHAP,
+ ss->digest->code,
+ name, strlen(name));
+ if (chap_rechallenge_time) {
+ ss->flags |= TIMEOUT_PENDING;
+ TIMEOUT(chap_server_timeout, ss,
+ chap_rechallenge_time);
+ }
+ }
+ ss->flags |= AUTH_DONE;
+ }