diff options
Diffstat (limited to 'src/libradius')
-rw-r--r-- | src/libradius/Makefile.am | 5 | ||||
-rw-r--r-- | src/libradius/Makefile.in | 67 | ||||
-rw-r--r-- | src/libradius/radius_message.c | 89 | ||||
-rw-r--r-- | src/libradius/radius_message.h | 16 | ||||
-rw-r--r-- | src/libradius/radius_socket.c | 51 |
5 files changed, 160 insertions, 68 deletions
diff --git a/src/libradius/Makefile.am b/src/libradius/Makefile.am index 5672f7b84..91ded23e3 100644 --- a/src/libradius/Makefile.am +++ b/src/libradius/Makefile.am @@ -1,5 +1,5 @@ - -INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan ipseclib_LTLIBRARIES = libradius.la libradius_la_SOURCES = \ @@ -8,4 +8,3 @@ libradius_la_SOURCES = \ radius_client.h radius_client.c \ radius_config.h radius_config.c \ radius_mppe.h - diff --git a/src/libradius/Makefile.in b/src/libradius/Makefile.in index 4dabbbdbc..9a530d73d 100644 --- a/src/libradius/Makefile.in +++ b/src/libradius/Makefile.in @@ -62,7 +62,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ $(top_srcdir)/m4/macros/add-plugin.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -102,19 +102,35 @@ libradius_la_LIBADD = am_libradius_la_OBJECTS = radius_message.lo radius_socket.lo \ radius_client.lo radius_config.lo libradius_la_OBJECTS = $(am_libradius_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libradius_la_SOURCES) DIST_SOURCES = $(libradius_la_SOURCES) am__can_run_installinfo = \ @@ -128,6 +144,7 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -140,6 +157,8 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -155,6 +174,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ @@ -163,6 +183,7 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -209,6 +230,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -237,6 +259,7 @@ charon_natt_port = @charon_natt_port@ charon_plugins = @charon_plugins@ charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -314,7 +337,9 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan + ipseclib_LTLIBRARIES = libradius.la libradius_la_SOURCES = \ radius_message.h radius_message.c \ @@ -390,7 +415,7 @@ clean-ipseclibLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libradius.la: $(libradius_la_OBJECTS) $(libradius_la_DEPENDENCIES) $(EXTRA_libradius_la_DEPENDENCIES) - $(LINK) -rpath $(ipseclibdir) $(libradius_la_OBJECTS) $(libradius_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(LINK) -rpath $(ipseclibdir) $(libradius_la_OBJECTS) $(libradius_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -404,25 +429,25 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_socket.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c index e7717ff7a..3905a06c7 100644 --- a/src/libradius/radius_message.c +++ b/src/libradius/radius_message.c @@ -65,6 +65,11 @@ struct private_radius_message_t { * message data, allocated */ rmsg_t *msg; + + /** + * User-Password to encrypt and encode, if any + */ + chunk_t password; }; /** @@ -356,6 +361,15 @@ METHOD(radius_message_t, add, void, { rattr_t *attribute; + if (type == RAT_USER_PASSWORD && !this->password.len) + { + /* store a null-padded password */ + this->password = chunk_alloc(round_up(data.len, HASH_SIZE_MD5)); + memset(this->password.ptr + data.len, 0, this->password.len - data.len); + memcpy(this->password.ptr, data.ptr, data.len); + return; + } + data.len = min(data.len, MAX_RADIUS_ATTRIBUTE_SIZE); this->msg = realloc(this->msg, ntohs(this->msg->length) + sizeof(rattr_t) + data.len); @@ -366,6 +380,67 @@ METHOD(radius_message_t, add, void, this->msg->length = htons(ntohs(this->msg->length) + attribute->length); } +METHOD(radius_message_t, crypt, bool, + private_radius_message_t *this, chunk_t salt, chunk_t in, chunk_t out, + chunk_t secret, hasher_t *hasher) +{ + char b[HASH_SIZE_MD5]; + + /** + * From RFC2548 (encryption): + * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) + * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) + * . . . + * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) + * + * P/C = Plain/Crypted => in/out + * S = secret + * R = authenticator + * A = salt + */ + if (in.len != out.len) + { + return FALSE; + } + if (in.len % HASH_SIZE_MD5 || in.len < HASH_SIZE_MD5) + { + return FALSE; + } + if (out.ptr != in.ptr) + { + memcpy(out.ptr, in.ptr, in.len); + } + /* Preparse seed for first round: + * b(1) = MD5(S + R + A) */ + if (!hasher->get_hash(hasher, secret, NULL) || + !hasher->get_hash(hasher, + chunk_from_thing(this->msg->authenticator), NULL) || + !hasher->get_hash(hasher, salt, b)) + { + return FALSE; + } + while (in.len) + { + /* p(i) = b(i) xor c(1) */ + memxor(out.ptr, b, HASH_SIZE_MD5); + + out = chunk_skip(out, HASH_SIZE_MD5); + if (out.len) + { + /* Prepare seed for next round:: + * b(i) = MD5(S + c(i-1)) */ + if (!hasher->get_hash(hasher, secret, NULL) || + !hasher->get_hash(hasher, + chunk_create(in.ptr, HASH_SIZE_MD5), b)) + { + return FALSE; + } + } + in = chunk_skip(in, HASH_SIZE_MD5); + } + return TRUE; +} + METHOD(radius_message_t, sign, bool, private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret, hasher_t *hasher, signer_t *signer, rng_t *rng, bool msg_auth) @@ -391,6 +466,18 @@ METHOD(radius_message_t, sign, bool, } } + if (this->password.len) + { + /* encrypt password inline */ + if (!crypt(this, chunk_empty, this->password, this->password, + secret, hasher)) + { + return FALSE; + } + add(this, RAT_USER_PASSWORD, this->password); + chunk_clear(&this->password); + } + if (msg_auth) { char buf[HASH_SIZE_MD5]; @@ -540,6 +627,7 @@ METHOD(radius_message_t, get_encoding, chunk_t, METHOD(radius_message_t, destroy, void, private_radius_message_t *this) { + chunk_clear(&this->password); free(this->msg); free(this); } @@ -563,6 +651,7 @@ static private_radius_message_t *radius_message_create_empty() .get_encoding = _get_encoding, .sign = _sign, .verify = _verify, + .crypt = _crypt, .destroy = _destroy, }, ); diff --git a/src/libradius/radius_message.h b/src/libradius/radius_message.h index c49323490..4ce03a44e 100644 --- a/src/libradius/radius_message.h +++ b/src/libradius/radius_message.h @@ -285,6 +285,22 @@ struct radius_message_t { hasher_t *hasher, signer_t *signer); /** + * Perform RADIUS attribute en-/decryption. + * + * Performs en-/decryption by XOring the hash-extended secret into data, + * as specified in RFC 2865 5.2 and used by RFC 2548. + * + * @param salt salt to append to message authenticator, if any + * @param in data to en-/decrypt, multiple of HASH_SIZE_MD5 + * @param out en-/decrypted data, length equal to in + * @param secret RADIUS secret + * @param hasher MD5 hasher + * @return TRUE if en-/decryption successful + */ + bool (*crypt)(radius_message_t *this, chunk_t salt, chunk_t in, chunk_t out, + chunk_t secret, hasher_t *hasher); + + /** * Destroy the message. */ void (*destroy)(radius_message_t *this); diff --git a/src/libradius/radius_socket.c b/src/libradius/radius_socket.c index 7dab968d8..f432151c0 100644 --- a/src/libradius/radius_socket.c +++ b/src/libradius/radius_socket.c @@ -233,54 +233,17 @@ METHOD(radius_socket_t, request, radius_message_t*, static chunk_t decrypt_mppe_key(private_radius_socket_t *this, u_int16_t salt, chunk_t C, radius_message_t *request) { - chunk_t A, R, P, seed; - u_char *c, *p; + chunk_t decrypted; - /** - * From RFC2548 (encryption): - * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) - * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) - * . . . - * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) - */ - - if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5) - { - return chunk_empty; - } - - A = chunk_create((u_char*)&salt, sizeof(salt)); - R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5); - P = chunk_alloca(C.len); - p = P.ptr; - c = C.ptr; - - seed = chunk_cata("cc", R, A); - - while (c < C.ptr + C.len) - { - /* b(i) = MD5(S + c(i-1)) */ - if (!this->hasher->get_hash(this->hasher, this->secret, NULL) || - !this->hasher->get_hash(this->hasher, seed, p)) - { - return chunk_empty; - } - - /* p(i) = b(i) xor c(1) */ - memxor(p, c, HASH_SIZE_MD5); - - /* prepare next round */ - seed = chunk_create(c, HASH_SIZE_MD5); - c += HASH_SIZE_MD5; - p += HASH_SIZE_MD5; - } - - /* remove truncation, first byte is key length */ - if (*P.ptr >= P.len) + decrypted = chunk_alloca(C.len); + if (!request->crypt(request, chunk_from_thing(salt), C, decrypted, + this->secret, this->hasher) || + decrypted.ptr[0] >= decrypted.len) { /* decryption failed? */ return chunk_empty; } - return chunk_clone(chunk_create(P.ptr + 1, *P.ptr)); + /* remove truncation, first byte is key length */ + return chunk_clone(chunk_create(decrypted.ptr + 1, decrypted.ptr[0])); } METHOD(radius_socket_t, decrypt_msk, chunk_t, |