X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_otp%2Fotp_pw_valid.c;h=914b6e98445e3b848a24e2b5d48008378d721a91;hb=fe4b8e632116c09c62e8480adec1b6e921a5f79c;hp=4611b3a5f101ce257f5465f1412c4024fc4dd09e;hpb=fd9beb53d8c269eb21a8fad31a2f7b375198b6b1;p=freeradius.git diff --git a/src/modules/rlm_otp/otp_pw_valid.c b/src/modules/rlm_otp/otp_pw_valid.c index 4611b3a..914b6e9 100644 --- a/src/modules/rlm_otp/otp_pw_valid.c +++ b/src/modules/rlm_otp/otp_pw_valid.c @@ -18,12 +18,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * - * Copyright 2006 TRI-D Systems, Inc. + * Copyright 2006,2007 TRI-D Systems, Inc. */ -static const char rcsid[] = "$Id$"; +#include +RCSID("$Id$") -#include #include #include @@ -31,14 +31,10 @@ static const char rcsid[] = "$Id$"; #include "otp.h" #include "otp_pw_valid.h" -#include +#ifdef HAVE_PTHREAD_H #include -#include -#include -#include -#include +#endif #include -#include /* transform otpd return codes into rlm return codes */ @@ -46,13 +42,15 @@ static int otprc2rlmrc(int rc) { switch (rc) { - case OTP_RC_OK: return RLM_MODULE_OK; - case OTP_RC_USER_UNKNOWN: return RLM_MODULE_REJECT; - case OTP_RC_AUTHINFO_UNAVAIL: return RLM_MODULE_REJECT; - case OTP_RC_AUTH_ERR: return RLM_MODULE_REJECT; - case OTP_RC_MAXTRIES: return RLM_MODULE_USERLOCK; - case OTP_RC_SERVICE_ERR: return RLM_MODULE_FAIL; - default: return RLM_MODULE_FAIL; + case OTP_RC_OK: return RLM_MODULE_OK; + case OTP_RC_USER_UNKNOWN: return RLM_MODULE_REJECT; + case OTP_RC_AUTHINFO_UNAVAIL: return RLM_MODULE_REJECT; + case OTP_RC_AUTH_ERR: return RLM_MODULE_REJECT; + case OTP_RC_MAXTRIES: return RLM_MODULE_USERLOCK; + case OTP_RC_NEXTPASSCODE: return RLM_MODULE_USERLOCK; + case OTP_RC_IPIN: return RLM_MODULE_REJECT; + case OTP_RC_SERVICE_ERR: return RLM_MODULE_FAIL; + default: return RLM_MODULE_FAIL; } } @@ -83,19 +81,22 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge, int rc; if (request->username->length > OTP_MAX_USERNAME_LEN) { - (void) radlog(L_AUTH, "rlm_otp: username [%s] too long\n", username); + (void) radlog(L_AUTH, "rlm_otp: username [%s] too long", username); return RLM_MODULE_REJECT; } /* we already know challenge is short enough */ - otp_request.version = 1; + otp_request.version = 2; (void) strcpy(otp_request.username, username); (void) 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]); - rvp = pairfind(request->packet->vps, pwattr[pwe]); + cvp = pairfind(request->packet->vps, pwattr[pwe - 1]->attr, pwattr[pwe - 1]->vendor); + rvp = pairfind(request->packet->vps, pwattr[pwe]->attr, pwattr[pwe]->vendor); + /* this is just to quiet Coverity */ + if (!rvp || !cvp) + return RLM_MODULE_REJECT; /* * Validate available vps based on pwe type. @@ -104,69 +105,75 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge, switch (otp_request.pwe.pwe) { case PWE_PAP: if (rvp->length > OTP_MAX_PASSCODE_LEN) { - (void) radlog(L_AUTH, "rlm_otp: passcode for [%s] too long\n", - username); + (void) radlog(L_AUTH, "rlm_otp: passcode for [%s] too long", username); return RLM_MODULE_REJECT; } - (void) strcpy(otp_request.pwe.passcode, rvp->vp_strvalue); + (void) strcpy(otp_request.pwe.u.pap.passcode, rvp->vp_strvalue); break; case PWE_CHAP: if (cvp->length > 16) { - (void) radlog(L_AUTH, "rlm_otp: CHAP challenge for [%s] too long\n", + (void) radlog(L_AUTH, "rlm_otp: CHAP challenge for [%s] too long", username); return RLM_MODULE_INVALID; } if (rvp->length != 17) { - (void) radlog(L_AUTH, "rlm_otp: CHAP response for [%s] wrong size\n", + (void) radlog(L_AUTH, "rlm_otp: CHAP response for [%s] wrong size", username); return RLM_MODULE_INVALID; } - (void) memcpy(otp_request.pwe.challenge, cvp->vp_strvalue, cvp->length); - otp_request.pwe.clen = cvp->length; - (void) memcpy(otp_request.pwe.response, rvp->vp_strvalue, rvp->length); - otp_request.pwe.rlen = rvp->length; + (void) memcpy(otp_request.pwe.u.chap.challenge, cvp->vp_strvalue, + cvp->length); + otp_request.pwe.u.chap.clen = cvp->length; + (void) memcpy(otp_request.pwe.u.chap.response, rvp->vp_strvalue, + rvp->length); + otp_request.pwe.u.chap.rlen = rvp->length; break; case PWE_MSCHAP: if (cvp->length != 8) { - (void) radlog(L_AUTH, "rlm_otp: MS-CHAP challenge for [%s] wrong size\n", + (void) radlog(L_AUTH, "rlm_otp: MS-CHAP challenge for [%s] wrong size", username); return RLM_MODULE_INVALID; } if (rvp->length != 50) { - (void) radlog(L_AUTH, "rlm_otp: MS-CHAP response for [%s] wrong size\n", + (void) radlog(L_AUTH, "rlm_otp: MS-CHAP response for [%s] wrong size", username); return RLM_MODULE_INVALID; } - (void) memcpy(otp_request.pwe.challenge, cvp->vp_strvalue, cvp->length); - otp_request.pwe.clen = cvp->length; - (void) memcpy(otp_request.pwe.response, rvp->vp_strvalue, rvp->length); - otp_request.pwe.rlen = rvp->length; + (void) memcpy(otp_request.pwe.u.chap.challenge, cvp->vp_strvalue, + cvp->length); + otp_request.pwe.u.chap.clen = cvp->length; + (void) memcpy(otp_request.pwe.u.chap.response, rvp->vp_strvalue, + rvp->length); + otp_request.pwe.u.chap.rlen = rvp->length; break; case PWE_MSCHAP2: if (cvp->length != 16) { - (void) radlog(L_AUTH, "rlm_otp: MS-CHAP2 challenge for [%s] wrong size\n", + (void) radlog(L_AUTH, "rlm_otp: MS-CHAP2 challenge for [%s] wrong size", username); return RLM_MODULE_INVALID; } if (rvp->length != 50) { - (void) radlog(L_AUTH, "rlm_otp: MS-CHAP2 response for [%s] wrong size\n", + (void) radlog(L_AUTH, "rlm_otp: MS-CHAP2 response for [%s] wrong size", username); return RLM_MODULE_INVALID; } - (void) memcpy(otp_request.pwe.challenge, cvp->vp_strvalue, cvp->length); - otp_request.pwe.clen = cvp->length; - (void) memcpy(otp_request.pwe.response, rvp->vp_strvalue, rvp->length); - otp_request.pwe.rlen = rvp->length; + (void) memcpy(otp_request.pwe.u.chap.challenge, cvp->vp_strvalue, + cvp->length); + otp_request.pwe.u.chap.clen = cvp->length; + (void) memcpy(otp_request.pwe.u.chap.response, rvp->vp_strvalue, + 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'; - otp_request.pwe.passcode[OTP_MAX_PASSCODE_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; @@ -199,8 +206,8 @@ retry: if (!fdp || fdp->fd == -1) return -1; - if ((rc = otp_write(fdp, (const char *) request, sizeof(*request))) != 0) { - if (rc == EPIPE) + if ((rc = otp_write(fdp, (const char *) request, sizeof(*request))) != sizeof(*request)) { + if (rc == 0) goto retry; /* otpd disconnect */ /*TODO: pause */ else return -1; @@ -218,15 +225,18 @@ retry: (void) radlog(L_AUTH, "rlm_otp: otpd reply for [%s] invalid " "(version %d != 1)", request->username, reply->version); + otp_putfd(fdp, 1); return -1; } if (reply->passcode[OTP_MAX_PASSCODE_LEN] != '\0') { (void) radlog(L_AUTH, "rlm_otp: otpd reply for [%s] invalid (passcode)", request->username); + otp_putfd(fdp, 1); return -1; } + otp_putfd(fdp, 0); return reply->rc; } @@ -247,13 +257,13 @@ otp_read(otp_fd_t *fdp, char *buf, size_t len) } else { (void) radlog(L_ERR, "rlm_otp: %s: read from otpd: %s", __func__, strerror(errno)); - otp_putfd(fdp); + otp_putfd(fdp, 1); return -1; } } if (!n) { (void) radlog(L_ERR, "rlm_otp: %s: otpd disconnect", __func__); - otp_putfd(fdp); + otp_putfd(fdp, 1); return 0; } nread += n; @@ -274,12 +284,12 @@ otp_write(otp_fd_t *fdp, const char *buf, size_t len) while (nleft) { if ((nwrote = write(fdp->fd, &buf[len - nleft], nleft)) == -1) { - if (errno == EINTR || errno == EPIPE) { + if (errno == EINTR) { continue; } else { (void) radlog(L_ERR, "rlm_otp: %s: write to otpd: %s", __func__, strerror(errno)); - otp_putfd(fdp); + otp_putfd(fdp, 1); return errno; } } @@ -306,7 +316,7 @@ otp_connect(const char *path) } sa.sun_family = AF_UNIX; (void) strcpy(sa.sun_path, path); - + /* connect to otpd */ if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { (void) radlog(L_ERR, "rlm_otp: %s: socket: %s", __func__, strerror(errno)); @@ -366,12 +376,15 @@ otp_getfd(const otp_option_t *opt) return fdp; } -/* disconnect from otpd */ +/* release fd, and optionally disconnect from otpd */ static void -otp_putfd(otp_fd_t *fdp) +otp_putfd(otp_fd_t *fdp, int disconnect) { - (void) close(fdp->fd); - fdp->fd = -1; + if (disconnect) { + (void) close(fdp->fd); + fdp->fd = -1; + } + /* make connection available to another thread */ otp_pthread_mutex_unlock(&fdp->mutex); }