Support signing of RADIUS response messages
[strongswan.git] / src / libcharon / plugins / eap_radius / radius_message.c
index 35f3741..9d7bf3e 100644 (file)
@@ -74,7 +74,14 @@ ENUM_BEGIN(radius_message_code_names, RMC_ACCESS_REQUEST, RMC_ACCOUNTING_RESPONS
        "Accounting-Response");
 ENUM_NEXT(radius_message_code_names, RMC_ACCESS_CHALLENGE, RMC_ACCESS_CHALLENGE, RMC_ACCOUNTING_RESPONSE,
        "Access-Challenge");
        "Accounting-Response");
 ENUM_NEXT(radius_message_code_names, RMC_ACCESS_CHALLENGE, RMC_ACCESS_CHALLENGE, RMC_ACCOUNTING_RESPONSE,
        "Access-Challenge");
-ENUM_END(radius_message_code_names, RMC_ACCESS_CHALLENGE);
+ENUM_NEXT(radius_message_code_names, RMC_DISCONNECT_REQUEST, RMC_COA_NAK, RMC_ACCESS_CHALLENGE,
+       "Disconnect-Request",
+       "Disconnect-ACK",
+       "Disconnect-NAK",
+       "CoA-Request",
+       "CoA-ACK",
+       "CoA-NAK");
+ENUM_END(radius_message_code_names, RMC_COA_NAK);
 
 ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
        "User-Name",
 
 ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
        "User-Name",
@@ -272,19 +279,39 @@ METHOD(radius_message_t, add, void,
 }
 
 METHOD(radius_message_t, sign, void,
 }
 
 METHOD(radius_message_t, sign, void,
-       private_radius_message_t *this, rng_t *rng, signer_t *signer)
+       private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret,
+       hasher_t *hasher, signer_t *signer, rng_t *rng)
 {
 {
-       char buf[HASH_SIZE_MD5];
+       if (rng == NULL)
+       {
+               chunk_t msg;
+
+               if (req_auth)
+               {
+                       memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5);
+               }
+               else
+               {
+                       memset(this->msg->authenticator, 0, sizeof(this->msg->authenticator));
+               }
+               msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
+               hasher->get_hash(hasher, msg, NULL);
+               hasher->get_hash(hasher, secret, this->msg->authenticator);
+       }
+       else
+       {
+               char buf[HASH_SIZE_MD5];
 
 
-       /* build Request-Authenticator */
-       rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator);
+               /* build Request-Authenticator */
+               rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator);
 
 
-       /* build Message-Authenticator attribute, using 16 null bytes */
-       memset(buf, 0, sizeof(buf));
-       add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf)));
-       signer->get_signature(signer,
+               /* build Message-Authenticator attribute, using 16 null bytes */
+               memset(buf, 0, sizeof(buf));
+               add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf)));
+               signer->get_signature(signer,
                                chunk_create((u_char*)this->msg, ntohs(this->msg->length)),
                                ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5);
                                chunk_create((u_char*)this->msg, ntohs(this->msg->length)),
                                ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5);
+       }
 }
 
 METHOD(radius_message_t, verify, bool,
 }
 
 METHOD(radius_message_t, verify, bool,
@@ -299,7 +326,14 @@ METHOD(radius_message_t, verify, bool,
 
        /* replace Response by Request Authenticator for verification */
        memcpy(res_auth, this->msg->authenticator, HASH_SIZE_MD5);
 
        /* replace Response by Request Authenticator for verification */
        memcpy(res_auth, this->msg->authenticator, HASH_SIZE_MD5);
-       memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5);
+       if (req_auth)
+       {
+               memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5);
+       }
+       else
+       {
+               memset(this->msg->authenticator, 0, HASH_SIZE_MD5);
+       }
        msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
 
        /* verify Response-Authenticator */
        msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length));
 
        /* verify Response-Authenticator */
@@ -398,7 +432,7 @@ METHOD(radius_message_t, destroy, void,
 /**
  * Generic constructor
  */
 /**
  * Generic constructor
  */
-static private_radius_message_t *radius_message_create()
+static private_radius_message_t *radius_message_create_empty()
 {
        private_radius_message_t *this;
 
 {
        private_radius_message_t *this;
 
@@ -423,9 +457,9 @@ static private_radius_message_t *radius_message_create()
 /**
  * See header
  */
 /**
  * See header
  */
-radius_message_t *radius_message_create_request(radius_message_code_t code)
+radius_message_t *radius_message_create(radius_message_code_t code)
 {
 {
-       private_radius_message_t *this = radius_message_create();
+       private_radius_message_t *this = radius_message_create_empty();
 
        INIT(this->msg,
                .code = code,
 
        INIT(this->msg,
                .code = code,
@@ -439,9 +473,9 @@ radius_message_t *radius_message_create_request(radius_message_code_t code)
 /**
  * See header
  */
 /**
  * See header
  */
-radius_message_t *radius_message_parse_response(chunk_t data)
+radius_message_t *radius_message_parse(chunk_t data)
 {
 {
-       private_radius_message_t *this = radius_message_create();
+       private_radius_message_t *this = radius_message_create_empty();
 
        this->msg = malloc(data.len);
        memcpy(this->msg, data.ptr, data.len);
 
        this->msg = malloc(data.len);
        memcpy(this->msg, data.ptr, data.len);