Exemplo n.º 1
0
/**
 * Check credentials
 */
OPENVPN_EXPORT int
openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
{
  /* get username/password from envp string array */
  const char *username = get_env ("username", envp);
  const char *password = get_env ("password", envp);
  const char *ip = get_env ("untrusted_ip", envp);
  const char *port = get_env ("untrusted_port", envp);

  const int ulen = strlen(username);
  const int pwlen = strlen(password);
  if ( ulen > MAXWORDLEN || ulen == 0 || pwlen > MAXWORDLEN || pwlen == 0) {
	  return OPENVPN_PLUGIN_FUNC_ERROR;
  }

  /* check entered username/password against what we require */
  int ok = otp_verify(username, password);

  if (ok == 1) {
    LOG("OTP-AUTH: authentication succeeded for username '%s', remote %s:%s\n", username, ip, port);
    return OPENVPN_PLUGIN_FUNC_SUCCESS;
  }
  else {
    LOG("OTP-AUTH: authentication failed for username '%s', remote %s:%s\n", username, ip, port);
    return OPENVPN_PLUGIN_FUNC_ERROR;
  }
}
Exemplo n.º 2
0
static int
check_password(struct passwd *pwd, const char *password)
{
    if(pwd->pw_passwd == NULL)
	return 1;
    if(pwd->pw_passwd[0] == '\0'){
#ifdef ALLOW_NULL_PASSWORD
	return password[0] != '\0';
#else
	return 1;
#endif
    }
    if(strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) == 0)
	return 0;
#ifdef KRB5
    if(krb5_verify(pwd, password) == 0) {
	auth = AUTH_KRB5;
	return 0;
    }
#endif
#ifdef OTP
    if (otp_verify (pwd, password) == 0) {
       auth = AUTH_OTP;
       return 0;
    }
#endif
    return 1;
}
Exemplo n.º 3
0
/*
 * Test for passcode validity by asking otpd.
 *
 * If challenge is supplied, it is used to generate the card response
 * against which the passcode will be compared.  If challenge is not
 * supplied, or if the comparison fails, synchronous responses are
 * generated and tested.  NOTE: for async authentications, sync mode
 * responses are still considered valid!  (Assuming module configuration
 * allows sync mode.)
 *
 * Returns one of the RLM_MODULE_* codes.  passcode is filled in.
 * NB: The returned passcode will contain the PIN!  DO NOT LOG!
 */
int otp_pw_valid(REQUEST *request, int pwe, char const *challenge,
		 rlm_otp_t const *opt,
		 char passcode[OTP_MAX_PASSCODE_LEN + 1])
{
	otp_request_t	otp_request;
	otp_reply_t	otp_reply;
	VALUE_PAIR	*cvp, *rvp;
	char const	*username = request->username->vp_strvalue;
	int		rc;

	if (request->username->length > OTP_MAX_USERNAME_LEN) {
		AUTH("rlm_otp: username [%s] too long", username);
		return RLM_MODULE_REJECT;
	}

	/* we already know challenge is short enough */
	otp_request.version = 2;

	strcpy(otp_request.username, username);
	strcpy(otp_request.challenge, challenge);

	otp_request.pwe.pwe = pwe;

	/*
	 *	otp_pwe_present() (done by caller) guarantees that both of
	 *	these exist
	 */
	cvp = pairfind(request->packet->vps, pwattr[pwe - 1]->attr,
		       pwattr[pwe - 1]->vendor, TAG_ANY);

	rvp = pairfind(request->packet->vps, pwattr[pwe]->attr,
		       pwattr[pwe]->vendor, TAG_ANY);

	/* this is just to quiet Coverity */
	if (!rvp || !cvp) {
		return RLM_MODULE_REJECT;
	}

	/*
	 *	Validate available vps based on pwe type.
	 *	Unfortunately (?) otpd must do this also.
	 */
	switch (otp_request.pwe.pwe) {
	case PWE_PAP:
		if (rvp->length >= sizeof(otp_request.pwe.u.pap.passcode)) {
			AUTH("rlm_otp: passcode for [%s] too long",
			       username);

			return RLM_MODULE_REJECT;
		}

		(void) strcpy(otp_request.pwe.u.pap.passcode, rvp->vp_strvalue);
		break;

	case PWE_CHAP:
		if (cvp->length > 16) {
			AUTH("rlm_otp: CHAP challenge for [%s] "
			       "too long", username);

			return RLM_MODULE_INVALID;
		}

		if (rvp->length != 17) {
			AUTH("rlm_otp: CHAP response for [%s] "
			      "wrong size", username);

			return RLM_MODULE_INVALID;
		}

		(void) memcpy(otp_request.pwe.u.chap.challenge, cvp->vp_octets,
			      cvp->length);

		otp_request.pwe.u.chap.clen = cvp->length;
		(void) memcpy(otp_request.pwe.u.chap.response, rvp->vp_octets,
			      rvp->length);

		otp_request.pwe.u.chap.rlen = rvp->length;
		break;

	case PWE_MSCHAP:
		if (cvp->length != 8) {
			AUTH("rlm_otp: MS-CHAP challenge for "
			       "[%s] wrong size", username);

			return RLM_MODULE_INVALID;
		}

		if (rvp->length != 50) {
			AUTH("rlm_otp: MS-CHAP response for [%s] "
			       "wrong size", username);

			return RLM_MODULE_INVALID;
		}
		(void) memcpy(otp_request.pwe.u.chap.challenge,
			      cvp->vp_octets, cvp->length);

		otp_request.pwe.u.chap.clen = cvp->length;

		(void) memcpy(otp_request.pwe.u.chap.response,
			      rvp->vp_octets, rvp->length);

		otp_request.pwe.u.chap.rlen = rvp->length;
		break;

	case PWE_MSCHAP2:
		if (cvp->length != 16) {
			AUTH("rlm_otp: MS-CHAP2 challenge for "
				      "[%s] wrong size", username);

			return RLM_MODULE_INVALID;
		}

		if (rvp->length != 50) {
			AUTH("rlm_otp: MS-CHAP2 response for [%s] "
			       "wrong size", username);

			return RLM_MODULE_INVALID;
		}

		(void) memcpy(otp_request.pwe.u.chap.challenge, cvp->vp_octets,
			      cvp->length);

		otp_request.pwe.u.chap.clen = cvp->length;

		(void) memcpy(otp_request.pwe.u.chap.response, rvp->vp_octets,
			      rvp->length);
		otp_request.pwe.u.chap.rlen = rvp->length;
	break;
	} /* switch (otp_request.pwe.pwe) */

	/*
	 *	last byte must also be a terminator so otpd can verify
	 *	length easily.
	 */
	otp_request.username[OTP_MAX_USERNAME_LEN] = '\0';
	otp_request.challenge[OTP_MAX_CHALLENGE_LEN] = '\0';

	if (otp_request.pwe.pwe == PWE_PAP) {
		otp_request.pwe.u.pap.passcode[OTP_MAX_PASSCODE_LEN] = '\0';
	}

	otp_request.allow_sync = opt->allow_sync;
	otp_request.allow_async = opt->allow_async;
	otp_request.challenge_delay = opt->challenge_delay;
	otp_request.resync = 1;


	rc = otp_verify(opt, &otp_request, &otp_reply);
	if (rc == OTP_RC_OK) {
		(void) strcpy(passcode, otp_reply.passcode);
	}

	return otprc2rlmrc(rc);
}