2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "radius_client.h"
17 #include "radius_config.h"
23 #include <utils/host.h>
24 #include <utils/linked_list.h>
25 #include <threading/condvar.h>
26 #include <threading/mutex.h>
28 typedef struct private_radius_client_t private_radius_client_t
;
31 * Private data of an radius_client_t object.
33 struct private_radius_client_t
{
36 * Public radius_client_t interface.
38 radius_client_t
public;
41 * Selected RADIUS server configuration
43 radius_config_t
*config
;
46 * RADIUS servers State attribute
51 * EAP MSK, from MPPE keys
57 * Save the state attribute to include in further request
59 static void save_state(private_radius_client_t
*this, radius_message_t
*msg
)
61 enumerator_t
*enumerator
;
65 enumerator
= msg
->create_enumerator(msg
);
66 while (enumerator
->enumerate(enumerator
, &type
, &data
))
68 if (type
== RAT_STATE
)
70 free(this->state
.ptr
);
71 this->state
= chunk_clone(data
);
72 enumerator
->destroy(enumerator
);
76 enumerator
->destroy(enumerator
);
77 /* no state attribute found, remove state */
78 chunk_free(&this->state
);
81 METHOD(radius_client_t
, request
, radius_message_t
*,
82 private_radius_client_t
*this, radius_message_t
*req
)
84 char virtual[] = {0x00,0x00,0x00,0x05};
85 radius_socket_t
*socket
;
86 radius_message_t
*res
;
89 /* we add the "Virtual" NAS-Port-Type, as we SHOULD include one */
90 req
->add(req
, RAT_NAS_PORT_TYPE
, chunk_create(virtual, sizeof(virtual)));
91 /* add our NAS-Identifier */
92 req
->add(req
, RAT_NAS_IDENTIFIER
,
93 this->config
->get_nas_identifier(this->config
));
94 /* add State attribute, if server sent one */
97 req
->add(req
, RAT_STATE
, this->state
);
99 socket
= this->config
->get_socket(this->config
);
100 DBG1(DBG_CFG
, "sending RADIUS %N to server '%s'", radius_message_code_names
,
101 req
->get_code(req
), this->config
->get_name(this->config
));
103 res
= socket
->request(socket
, req
);
106 DBG1(DBG_CFG
, "received RADIUS %N from server '%s'",
107 radius_message_code_names
, res
->get_code(res
),
108 this->config
->get_name(this->config
));
109 data
= res
->get_encoding(res
);
110 DBG3(DBG_CFG
, "%B", &data
);
112 save_state(this, res
);
113 if (res
->get_code(res
) == RMC_ACCESS_ACCEPT
)
115 chunk_clear(&this->msk
);
116 this->msk
= socket
->decrypt_msk(socket
, req
, res
);
118 this->config
->put_socket(this->config
, socket
, TRUE
);
121 this->config
->put_socket(this->config
, socket
, FALSE
);
125 METHOD(radius_client_t
, get_msk
, chunk_t
,
126 private_radius_client_t
*this)
131 METHOD(radius_client_t
, destroy
, void,
132 private_radius_client_t
*this)
134 this->config
->destroy(this->config
);
135 chunk_clear(&this->msk
);
136 free(this->state
.ptr
);
143 radius_client_t
*radius_client_create(radius_config_t
*config
)
145 private_radius_client_t
*this;
156 return &this->public;