コード例 #1
0
ファイル: chap-md5.c プロジェクト: ragunath3252/lwip-port
static int chap_md5_verify_response(int id, char *name,
                                    unsigned char *secret, int secret_len,
                                    unsigned char *challenge, unsigned char *response,
                                    char *message, int message_space) {
    md5_context ctx;
    unsigned char idbyte = id;
    unsigned char hash[MD5_HASH_SIZE];
    int challenge_len, response_len;
    LWIP_UNUSED_ARG(name);

    challenge_len = *challenge++;
    response_len = *response++;
    if (response_len == MD5_HASH_SIZE) {
        /* Generate hash of ID, secret, challenge */
        md5_starts(&ctx);
        md5_update(&ctx, &idbyte, 1);
        md5_update(&ctx, secret, secret_len);
        md5_update(&ctx, challenge, challenge_len);
        md5_finish(&ctx, hash);

        /* Test if our hash matches the peer's response */
        if (memcmp(hash, response, MD5_HASH_SIZE) == 0) {
            ppp_slprintf(message, message_space, "Access granted");
            return 1;
        }
    }
    ppp_slprintf(message, message_space, "Access denied");
    return 0;
}
コード例 #2
0
ファイル: lwip_chap_ms.c プロジェクト: 0xc0170/mbed
static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name,
		       const unsigned char *secret, int secret_len,
		       const unsigned char *challenge, const unsigned char *response,
		       char *message, int message_space) {
	unsigned char md[MS_CHAP_RESPONSE_LEN];
	int diff;
	int challenge_len, response_len;
	LWIP_UNUSED_ARG(id);
	LWIP_UNUSED_ARG(name);

	challenge_len = *challenge++;	/* skip length, is 8 */
	response_len = *response++;
	if (response_len != MS_CHAP_RESPONSE_LEN)
		goto bad;

#ifndef MSLANMAN
	if (!response[MS_CHAP_USENT]) {
		/* Should really propagate this into the error packet. */
		ppp_notice("Peer request for LANMAN auth not supported");
		goto bad;
	}
#endif

	/* Generate the expected response. */
	ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md);

#ifdef MSLANMAN
	/* Determine which part of response to verify against */
	if (!response[MS_CHAP_USENT])
		diff = memcmp(&response[MS_CHAP_LANMANRESP],
			      &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN);
	else
#endif
		diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP],
			      MS_CHAP_NTRESP_LEN);

	if (diff == 0) {
		ppp_slprintf(message, message_space, "Access granted");
		return 1;
	}

 bad:
	/* See comments below for MS-CHAP V2 */
	ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0",
		 challenge_len, challenge);
	return 0;
}
コード例 #3
0
ファイル: chap-new.c プロジェクト: netsec-ethz/scion-lwip
/*
 * chap_respond - Generate and send a response to a challenge.
 */
static void chap_respond(ppp_pcb *pcb, int id,
	     unsigned char *pkt, int len) {
	int clen, nlen;
	int secret_len;
	struct pbuf *p;
	u_char *outp;
	char rname[MAXNAMELEN+1];
	char secret[MAXSECRETLEN+1];

	p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE);
	if(NULL == p)
		return;
	if(p->tot_len != p->len) {
		pbuf_free(p);
		return;
	}

	if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED))
		return;		/* not ready */
	if (len < 2 || len < pkt[0] + 1)
		return;		/* too short */
	clen = pkt[0];
	nlen = len - (clen + 1);

	/* Null terminate and clean remote name. */
	ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1);

#if PPP_REMOTENAME
	/* Microsoft doesn't send their name back in the PPP packet */
	if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0))
		strlcpy(rname, pcb->settings.remote_name, sizeof(rname));
#endif /* PPP_REMOTENAME */

	/* get secret for authenticating ourselves with the specified host */
	if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) {
		secret_len = 0;	/* assume null secret if can't find one */
		ppp_warn("No CHAP secret found for authenticating us to %q", rname);
	}

	outp = (u_char*)p->payload;
	MAKEHEADER(outp, PPP_CHAP);
	outp += CHAP_HDRLEN;

	pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt,
				  secret, secret_len, pcb->chap_client.priv);
	memset(secret, 0, secret_len);

	clen = *outp;
	nlen = strlen(pcb->chap_client.name);
	memcpy(outp + clen + 1, pcb->chap_client.name, nlen);

	outp = (u_char*)p->payload + PPP_HDRLEN;
	len = CHAP_HDRLEN + clen + 1 + nlen;
	outp[0] = CHAP_RESPONSE;
	outp[1] = id;
	outp[2] = len >> 8;
	outp[3] = len;

	pbuf_realloc(p, PPP_HDRLEN + len);
	ppp_write(pcb, p);
}
コード例 #4
0
ファイル: chap-new.c プロジェクト: netsec-ethz/scion-lwip
/*
 * chap_handle_response - check the response to our challenge.
 */
static void  chap_handle_response(ppp_pcb *pcb, int id,
		     unsigned char *pkt, int len) {
	int response_len, ok, mlen;
	const unsigned char *response;
	unsigned char *outp;
	struct pbuf *p;
	const char *name = NULL;	/* initialized to shut gcc up */
#if 0 /* UNUSED */
	int (*verifier)(const char *, const char *, int, const struct chap_digest_type *,
		const unsigned char *, const unsigned char *, char *, int);
#endif /* UNUSED */
	char rname[MAXNAMELEN+1];
	char message[256];

	if ((pcb->chap_server.flags & LOWERUP) == 0)
		return;
	if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2)
		return;
	if (pcb->chap_server.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 (pcb->chap_server.flags & TIMEOUT_PENDING) {
			pcb->chap_server.flags &= ~TIMEOUT_PENDING;
			UNTIMEOUT(chap_timeout, pcb);
		}
#if PPP_REMOTENAME
		if (pcb->settings.explicit_remote) {
			name = pcb->remote_name;
		} else
#endif /* PPP_REMOTENAME */
		{
			/* Null terminate and clean remote name. */
			ppp_slprintf(rname, sizeof(rname), "%.*v", len, name);
			name = rname;
		}

#if 0 /* UNUSED */
		if (chap_verify_hook)
			verifier = chap_verify_hook;
		else
			verifier = chap_verify_response;
		ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest,
				 pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN,
				 response, pcb->chap_server.message, sizeof(pcb->chap_server.message));
#endif /* UNUSED */
		ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest,
                    pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN,
                    response, message, sizeof(message));
#if 0 /* UNUSED */
		if (!ok || !auth_number()) {
#endif /* UNUSED */
		if (!ok) {
			pcb->chap_server.flags |= AUTH_FAILED;
			ppp_warn("Peer %q failed CHAP authentication", name);
		}
	} else if ((pcb->chap_server.flags & AUTH_DONE) == 0)
		return;

	/* send the response */
	mlen = strlen(message);
	len = CHAP_HDRLEN + mlen;
	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE);
	if(NULL == p)
		return;
	if(p->tot_len != p->len) {
		pbuf_free(p);
		return;
	}

	outp = (unsigned char *)p->payload;
	MAKEHEADER(outp, PPP_CHAP);

	outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
	outp[1] = id;
	outp[2] = len >> 8;
	outp[3] = len;
	if (mlen > 0)
		memcpy(outp + CHAP_HDRLEN, message, mlen);
	ppp_write(pcb, p);

	if (pcb->chap_server.flags & CHALLENGE_VALID) {
		pcb->chap_server.flags &= ~CHALLENGE_VALID;
		if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) {

#if 0 /* UNUSED */
		    /*
		     * 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) {
			pcb->chap_server.flags |= AUTH_FAILED;
			ppp_warn("Peer %q failed CHAP Session verification", name);
		    }
#endif /* UNUSED */

		}
		if (pcb->chap_server.flags & AUTH_FAILED) {
			auth_peer_fail(pcb, PPP_CHAP);
		} else {
			if ((pcb->chap_server.flags & AUTH_DONE) == 0)
				auth_peer_success(pcb, PPP_CHAP,
						  pcb->chap_server.digest->code,
						  name, strlen(name));
			if (pcb->settings.chap_rechallenge_time) {
				pcb->chap_server.flags |= TIMEOUT_PENDING;
				TIMEOUT(chap_timeout, pcb,
					pcb->settings.chap_rechallenge_time);
			}
		}
		pcb->chap_server.flags |= AUTH_DONE;
	}
}
コード例 #5
0
ファイル: lwip_chap_ms.c プロジェクト: 0xc0170/mbed
static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name,
			const unsigned char *secret, int secret_len,
			const unsigned char *challenge, const unsigned char *response,
			char *message, int message_space) {
	unsigned char md[MS_CHAP2_RESPONSE_LEN];
	char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
	int challenge_len, response_len;
	LWIP_UNUSED_ARG(id);

	challenge_len = *challenge++;	/* skip length, is 16 */
	response_len = *response++;
	if (response_len != MS_CHAP2_RESPONSE_LEN)
		goto bad;	/* not even the right length */

	/* Generate the expected response and our mutual auth. */
	ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name,
		(const char *)secret, secret_len, md,
		(unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);

	/* compare MDs and send the appropriate status */
	/*
	 * 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 <*****@*****.**> for
	 * help debugging this.
	 */
	if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP],
		   MS_CHAP2_NTRESP_LEN) == 0) {
		if (response[MS_CHAP2_FLAGS])
			ppp_slprintf(message, message_space, "S=%s", saresponse);
		else
			ppp_slprintf(message, message_space, "S=%s M=%s",
				 saresponse, "Access granted");
		return 1;
	}

 bad:
	/*
	 * 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.  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.
	 */
	ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s",
		 challenge_len, challenge, "Access denied");
	return 0;
}
コード例 #6
0
ファイル: upap.c プロジェクト: crvv/lwip
/*
 * upap_rauth - Receive Authenticate.
 */
static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) {
    u_char ruserlen, rpasswdlen;
    char *ruser;
    char *rpasswd;
    char rhostname[256];
    int retcode;
    const char *msg;
    int msglen;

    if (pcb->upap.us_serverstate < UPAPSS_LISTEN)
        return;

    /*
     * If we receive a duplicate authenticate-request, we are
     * supposed to return the same status as for the first request.
     */
    if (pcb->upap.us_serverstate == UPAPSS_OPEN) {
        upap_sresp(pcb, UPAP_AUTHACK, id, "", 0);	/* return auth-ack */
        return;
    }
    if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) {
        upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0);	/* return auth-nak */
        return;
    }

    /*
     * Parse user/passwd.
     */
    if (len < 1) {
        UPAPDEBUG(("pap_rauth: rcvd short packet."));
        return;
    }
    GETCHAR(ruserlen, inp);
    len -= sizeof (u_char) + ruserlen + sizeof (u_char);
    if (len < 0) {
        UPAPDEBUG(("pap_rauth: rcvd short packet."));
        return;
    }
    ruser = (char *) inp;
    INCPTR(ruserlen, inp);
    GETCHAR(rpasswdlen, inp);
    if (len < rpasswdlen) {
        UPAPDEBUG(("pap_rauth: rcvd short packet."));
        return;
    }

    rpasswd = (char *) inp;

    /*
     * Check the username and password given.
     */
    retcode = UPAP_AUTHNAK;
    if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) {
        retcode = UPAP_AUTHACK;
    }
    BZERO(rpasswd, rpasswdlen);

#if 0 /* UNUSED */
    /*
     * Check remote number authorization.  A plugin may have filled in
     * the remote number or added an allowed number, and rather than
     * return an authenticate failure, is leaving it for us to verify.
     */
    if (retcode == UPAP_AUTHACK) {
        if (!auth_number()) {
            /* We do not want to leak info about the pap result. */
            retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */
            warn("calling number %q is not authorized", remote_number);
        }
    }

    msglen = strlen(msg);
    if (msglen > 255)
        msglen = 255;
#endif /* UNUSED */

    upap_sresp(pcb, retcode, id, msg, msglen);

    /* Null terminate and clean remote name. */
    ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser);

    if (retcode == UPAP_AUTHACK) {
        pcb->upap.us_serverstate = UPAPSS_OPEN;
        ppp_notice("PAP peer authentication succeeded for %q", rhostname);
        auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen);
    } else {
        pcb->upap.us_serverstate = UPAPSS_BADAUTH;
        ppp_warn("PAP peer authentication failed for %q", rhostname);
        auth_peer_fail(pcb, PPP_PAP);
    }

    if (pcb->settings.pap_req_timeout > 0)
        UNTIMEOUT(upap_reqtimeout, pcb);
}