Exemple #1
0
/*
 * upap_rauth - Receive Authenticate.
 */
static void
upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
{
  u_char ruserlen, rpasswdlen;
  char *ruser, *rpasswd;
  int retcode;
  char *msg;
  int msglen;

  UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));

  if (u->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 (u->us_serverstate == UPAPSS_OPEN) {
    upap_sresp(u, UPAP_AUTHACK, id, "", 0);  /* return auth-ack */
    return;
  }
  if (u->us_serverstate == UPAPSS_BADAUTH) {
    upap_sresp(u, UPAP_AUTHNAK, id, "", 0);  /* return auth-nak */
    return;
  }

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

  /*
   * Check the username and password given.
   */
  retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen);
  BZERO(rpasswd, rpasswdlen);

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

  if (retcode == UPAP_AUTHACK) {
    u->us_serverstate = UPAPSS_OPEN;
    auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
  } else {
    u->us_serverstate = UPAPSS_BADAUTH;
    auth_peer_fail(u->us_unit, PPP_PAP);
  }

  if (u->us_reqtimeout > 0) {
    UNTIMEOUT(upap_reqtimeout, u);
  }
}
Exemple #2
0
Fichier : upap.c Projet : 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);
}
Exemple #3
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;
	}
}
Exemple #4
0
/*
 * ChapReceiveResponse - Receive and process response.
 */
static void
ChapReceiveResponse(
    chap_state *cstate,
    u_char *inp,
    int id,
    int len)
{
    u_char *remmd, remmd_len;
    int secret_len, old_state;
    int code;
    char rhostname[256];
    MD5_CTX mdContext;
    unsigned char secret[MAXSECRETLEN];
    u_char hash[MD5_SIGNATURE_SIZE];

    if (cstate->serverstate == CHAPSS_CLOSED ||
	cstate->serverstate == CHAPSS_PENDING) {
	CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate));
	return;
    }

    if (id != cstate->chal_id)
	return;			/* doesn't match ID of last challenge */

    /*
     * If we have received a duplicate or bogus Response,
     * we have to send the same answer (Success/Failure)
     * as we did for the first Response we saw.
     */
    if (cstate->serverstate == CHAPSS_OPEN) {
	ChapSendStatus(cstate, CHAP_SUCCESS);
	return;
    }
    if (cstate->serverstate == CHAPSS_BADAUTH) {
	ChapSendStatus(cstate, CHAP_FAILURE);
	return;
    }

    if (len < 2) {
	CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
	return;
    }
    GETCHAR(remmd_len, inp);		/* get length of MD */
    remmd = inp;			/* get pointer to MD */
    INCPTR(remmd_len, inp);

    len -= sizeof (u_char) + remmd_len;
    if (len < 0) {
	CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
	return;
    }

    UNTIMEOUT(ChapChallengeTimeout, cstate);

    if (len >= sizeof(rhostname))
	len = sizeof(rhostname) - 1;
    BCOPY(inp, rhostname, len);
    rhostname[len] = '\000';

    /*
     * Get secret for authenticating them with us,
     * do the hash ourselves, and compare the result.
     */
    code = CHAP_FAILURE;
    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:		/* 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(hash, &mdContext);

	    /* compare local and remote MDs and send the appropriate status */
	    if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
		code = CHAP_SUCCESS;	/* they are the same! */
	    break;

	default:
	    CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
	}
    }

    BZERO(secret, sizeof(secret));
    ChapSendStatus(cstate, code);

    if (code == CHAP_SUCCESS) {
	old_state = cstate->serverstate;
	cstate->serverstate = CHAPSS_OPEN;
	if (old_state == CHAPSS_INITIAL_CHAL) {
	    auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
	}
	if (cstate->chal_interval != 0)
	    TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
	notice("CHAP peer authentication succeeded for %q", rhostname);

    } else {
	error("CHAP peer authentication failed for remote host %q", rhostname);
	cstate->serverstate = CHAPSS_BADAUTH;
	auth_peer_fail(cstate->unit, PPP_CHAP);
    }
}