示例#1
0
/*
 * chap_timeout - It's time to send another challenge to the peer.
 * This could be either a retransmission of a previous challenge,
 * or a new challenge to start re-authentication.
 */
static void chap_timeout(void *arg) {
	ppp_pcb *pcb = (ppp_pcb*)arg;
	struct pbuf *p;

	pcb->chap_server.flags &= ~TIMEOUT_PENDING;
	if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) {
		pcb->chap_server.challenge_xmits = 0;
		chap_generate_challenge(pcb);
		pcb->chap_server.flags |= CHALLENGE_VALID;
	} else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) {
		pcb->chap_server.flags &= ~CHALLENGE_VALID;
		pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED;
		auth_peer_fail(pcb, PPP_CHAP);
		return;
	}

	p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE);
	if(NULL == p)
		return;
	if(p->tot_len != p->len) {
		pbuf_free(p);
		return;
	}
	MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen);
	ppp_write(pcb, p);
	++pcb->chap_server.challenge_xmits;
	pcb->chap_server.flags |= TIMEOUT_PENDING;
	TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time);
}
/*
 * fsm_sdata - Send some data.
 *
 * Used for all packets sent to our peer by this module.
 */
void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) {
    ppp_pcb *pcb = f->pcb;
    struct pbuf *p;
    u_char *outp;
    int outlen;

    /* Adjust length to be smaller than MTU */
    if (datalen > pcb->peer_mru - HEADERLEN)
	datalen = pcb->peer_mru - HEADERLEN;
    outlen = datalen + HEADERLEN;

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

    outp = (u_char*)p->payload;
    if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN)  -- was only for fsm_sconfreq() */
	MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen);
    MAKEHEADER(outp, f->protocol);
    PUTCHAR(code, outp);
    PUTCHAR(id, outp);
    PUTSHORT(outlen, outp);
    ppp_write(pcb, p);
}
示例#3
0
文件: upap.c 项目: crvv/lwip
/*
 * upap_sresp - Send a response (ack or nak).
 */
static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
    struct pbuf *p;
    u_char *outp;
    int outlen;

    outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
    p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
    if(NULL == p)
        return;
    if(p->tot_len != p->len) {
        pbuf_free(p);
        return;
    }

    outp = (u_char*)p->payload;
    MAKEHEADER(outp, PPP_PAP);

    PUTCHAR(code, outp);
    PUTCHAR(id, outp);
    PUTSHORT(outlen, outp);
    PUTCHAR(msglen, outp);
    MEMCPY(outp, msg, msglen);

    ppp_write(pcb, p);
}
示例#4
0
文件: upap.c 项目: crvv/lwip
/*
 * upap_sauthreq - Send an Authenticate-Request.
 */
static void upap_sauthreq(ppp_pcb *pcb) {
    struct pbuf *p;
    u_char *outp;
    int outlen;

    outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
             pcb->upap.us_userlen + pcb->upap.us_passwdlen;
    p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
    if(NULL == p)
        return;
    if(p->tot_len != p->len) {
        pbuf_free(p);
        return;
    }

    outp = (u_char*)p->payload;
    MAKEHEADER(outp, PPP_PAP);

    PUTCHAR(UPAP_AUTHREQ, outp);
    PUTCHAR(++pcb->upap.us_id, outp);
    PUTSHORT(outlen, outp);
    PUTCHAR(pcb->upap.us_userlen, outp);
    MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
    INCPTR(pcb->upap.us_userlen, outp);
    PUTCHAR(pcb->upap.us_passwdlen, outp);
    MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);

    ppp_write(pcb, p);

    TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
    ++pcb->upap.us_transmits;
    pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
}
/*
 * fsm_sconfreq - Send a Configure-Request.
 */
static void fsm_sconfreq(fsm *f, int retransmit) {
    ppp_pcb *pcb = f->pcb;
    struct pbuf *p;
    u_char *outp;
    int cilen;

    if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){
	/* Not currently negotiating - reset options */
	if( f->callbacks->resetci )
	    (*f->callbacks->resetci)(f);
	f->nakloops = 0;
	f->rnakloops = 0;
    }

    if( !retransmit ){
	/* New request - reset retransmission counter, use new ID */
	f->retransmits = pcb->settings.fsm_max_conf_req_transmits;
	f->reqid = ++f->id;
    }

    f->seen_ack = 0;

    /*
     * Make up the request packet
     */
    if( f->callbacks->cilen && f->callbacks->addci ){
	cilen = (*f->callbacks->cilen)(f);
	if( cilen > pcb->peer_mru - HEADERLEN )
	    cilen = pcb->peer_mru - HEADERLEN;
    } else
	cilen = 0;

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

    /* send the request to our peer */
    outp = (u_char*)p->payload;
    MAKEHEADER(outp, f->protocol);
    PUTCHAR(CONFREQ, outp);
    PUTCHAR(f->reqid, outp);
    PUTSHORT(cilen + HEADERLEN, outp);
    if (cilen != 0) {
	(*f->callbacks->addci)(f, outp, &cilen);
	LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN);
    }

    ppp_write(pcb, p);

    /* start the retransmit timer */
    --f->retransmits;
    TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time);
}
示例#6
0
/*
 * 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);
}
示例#7
0
/*
 * 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;
	}
}