24 RCSID(
"$Id: bb7319ffc1a7c51a2038d6f5b6d47af24abf4657 $")
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/modules.h>
78 char const *username = request->
username->vp_strvalue;
86 AUTH(
"rlm_otp: username [%s] too long", username);
92 AUTH(
"rlm_otp: challenge for [%s] too long", username);
115 switch (otp_request.
pwe.
pwe) {
120 if (
strlcpy(otp_request.
pwe.u.pap.passcode, rvp->vp_strvalue,
121 sizeof(otp_request.
pwe.u.pap.passcode)) >=
122 sizeof(otp_request.
pwe.u.pap.passcode)) {
123 AUTH(
"rlm_otp: passcode for [%s] too long",
131 if (cvp->vp_length > 16) {
132 AUTH(
"rlm_otp: CHAP challenge for [%s] "
133 "too long", username);
138 if (rvp->vp_length != 17) {
139 AUTH(
"rlm_otp: CHAP response for [%s] "
140 "wrong size", username);
145 (void) memcpy(otp_request.
pwe.u.chap.
challenge, cvp->vp_octets,
148 otp_request.
pwe.u.chap.clen = cvp->vp_length;
149 (void) memcpy(otp_request.
pwe.u.chap.response, rvp->vp_octets,
152 otp_request.
pwe.u.chap.rlen = rvp->vp_length;
156 if (cvp->vp_length != 8) {
157 AUTH(
"rlm_otp: MS-CHAP challenge for "
158 "[%s] wrong size", username);
163 if (rvp->vp_length != 50) {
164 AUTH(
"rlm_otp: MS-CHAP response for [%s] "
165 "wrong size", username);
170 cvp->vp_octets, cvp->vp_length);
172 otp_request.
pwe.u.chap.clen = cvp->vp_length;
174 (void) memcpy(otp_request.
pwe.u.chap.response,
175 rvp->vp_octets, rvp->vp_length);
177 otp_request.
pwe.u.chap.rlen = rvp->vp_length;
181 if (cvp->vp_length != 16) {
182 AUTH(
"rlm_otp: MS-CHAP2 challenge for "
183 "[%s] wrong size", username);
188 if (rvp->vp_length != 50) {
189 AUTH(
"rlm_otp: MS-CHAP2 response for [%s] "
190 "wrong size", username);
195 (void) memcpy(otp_request.
pwe.u.chap.
challenge, cvp->vp_octets,
198 otp_request.
pwe.u.chap.clen = cvp->vp_length;
200 (void) memcpy(otp_request.
pwe.u.chap.response, rvp->vp_octets,
202 otp_request.
pwe.u.chap.rlen = rvp->vp_length;
223 rc =
otp_verify(opt, &otp_request, &otp_reply);
225 (void) strcpy(passcode, otp_reply.
passcode);
249 if (!fdp || fdp->
fd == -1) {
253 rc =
otp_write(fdp, (
char const *) request,
sizeof(*request));
254 if (rc !=
sizeof(*request)) {
262 rc =
otp_read(fdp, (
char *) reply,
sizeof(*reply));
263 if (rc !=
sizeof(*reply)) {
273 AUTH(
"rlm_otp: otpd reply for [%s] invalid "
281 AUTH(
"rlm_otp: otpd reply for [%s] invalid "
302 while (nread < len) {
303 n = read(fdp->
fd, &buf[nread], len - nread);
305 if (errno == EINTR) {
308 ERROR(
"rlm_otp: %s: read from otpd: %s",
317 ERROR(
"rlm_otp: %s: otpd disconnect", __func__);
339 nwrote = write(fdp->
fd, &buf[len - nleft], nleft);
341 if (errno == EINTR) {
344 ERROR(
"rlm_otp: %s: write to otpd: %s",
363 struct sockaddr_un sa;
367 sp_len = strlen(path);
368 if (sp_len >
sizeof(sa.sun_path) - 1) {
369 ERROR(
"rlm_otp: %s: rendezvous point name too long",
374 sa.sun_family = AF_UNIX;
375 (void) strcpy(sa.sun_path, path);
378 fd = socket(PF_UNIX, SOCK_STREAM, 0);
380 ERROR(
"rlm_otp: %s: socket: %s", __func__,
385 if (connect(fd, (
struct sockaddr *) &sa,
386 sizeof(sa.sun_family) + sp_len) == -1) {
388 ERROR(
"rlm_otp: %s: connect(%s): %s",
413 for (fdp = otp_fd_head; fdp; fdp = fdp->
next) {
451 (void) close(fdp->
fd);
#define OTP_RC_AUTHINFO_UNAVAIL
uint32_t challenge_delay
Max delay time for response, in seconds.
char challenge[OTP_MAX_CHALLENGE_LEN+1]
USER challenge.
const fr_dict_attr_t * pwattr[8]
char const * otpd_rp
Otpd rendezvous point.
The module is OK, continue.
void * rad_malloc(size_t size)
char passcode[OTP_MAX_PASSCODE_LEN+1]
bool allow_async
C/R mode allowed?
static int otp_write(otp_fd_t *fdp, char const *buf, size_t len)
static otp_fd_t * otp_fd_head
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
static otp_fd_t * otp_getfd(rlm_otp_t const *opt)
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
#define otp_pthread_mutex_trylock(a)
static int otp_read(otp_fd_t *fdp, char *buf, size_t len)
The module considers the request invalid.
int otp_pw_valid(REQUEST *request, int pwe, char const *challenge, rlm_otp_t const *opt, char passcode[OTP_MAX_PASSCODE_LEN+1])
#define OTP_RC_SERVICE_ERR
Reject the request (user is locked out).
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
char username[OTP_MAX_USERNAME_LEN+1]
unsigned int attr
Attribute number.
Immediately reject the request.
int resync
Resync on async auth?
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
static int otprc2rlmrc(int rc)
#define otp_pthread_mutex_unlock(a)
static pthread_mutex_t otp_fd_head_mutex
#define OTP_RC_NEXTPASSCODE
Module succeeded without doing anything.
#define OTP_RC_USER_UNKNOWN
bool allow_sync
Sync auth allowed?
Module failed, don't reply.
bool allow_async
Async auth allowed?
#define otp_pthread_mutex_lock(a)
#define OTP_MAX_CHALLENGE_LEN
#define OTP_MAX_PASSCODE_LEN
RADIUS_PACKET * packet
Incoming request.
static int otp_connect(char const *path)
static void otp_putfd(otp_fd_t *fdp, int disconnect)
bool allow_sync
Useful to override pwdfile card_type settings.
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
struct otp_request_t::@20 pwe
unsigned challenge_delay
Min delay between async auths.
size_t strlcpy(char *dst, char const *src, size_t siz)
#define otp_pthread_mutex_init(a, b)
#define OTP_MAX_USERNAME_LEN
static int otp_verify(rlm_otp_t const *opt, otp_request_t const *request, otp_reply_t *reply)