Commit 0912690e authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Large UNTESTED commit with the following changes:

  * Improved DiameterIdentity handling (esp. interationalization issues),
    and improve efficiency of some string operations in peers, sessions,
    and dictionary modules (closes #7)
  * Cleanup in the session module to free only unreferenced sessions (#16)
  * Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
  * Improved peer state machine algorithm to counter SCTP multistream race
    condition.
parent 7b856e3a
......@@ -4,7 +4,7 @@ freediameter (1.1.0) UNRELEASED; urgency=low
framework now contained in the libfdcore library.
libfreeDiameter renamed as libfdproto.
This closes #15.
* API version bumped to version 4 accordingly.
* API version bumped to version 4.
* Improved fd_dict_new() when the same object already exists.
* Improvements to dict_legacy_xml extension.
* Cleanups in links to shared libraries
......@@ -12,8 +12,15 @@ freediameter (1.1.0) UNRELEASED; urgency=low
to RADIUS (closes #25)
* Allow default signals such as SIGTSTP (ctrl-z) to be used with
freeDiameterd
-- Sebastien Decugis <sdecugis@nict.go.jp> Tue, 18 Jan 2011 15:13:00 +0900
* Improved DiameterIdentity handling (esp. interationalization issues),
and improve efficiency of some string operations in peers, sessions,
and dictionary modules (closes #7)
* Cleanup in the session module to free only unreferenced sessions (#16)
* Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
* Improved peer state machine algorithm to counter SCTP multistream race
condition.
-- Sebastien Decugis <sdecugis@nict.go.jp> Mon, 07 Feb 2011 17:24:20 +0900
freediameter (1.0.4) UNRELEASED; urgency=low
......
......@@ -104,7 +104,7 @@ del l1
############# Hash ############
hex(fd_hash("hello world")) # It accepts binary data
hex(fd_os_hash("hello world")) # It accepts binary data
############# Dictionary ############
......
......@@ -210,6 +210,7 @@ TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key
# ConnectTo = "202.249.37.5";
# ConnectTo = "2001:200:903:2::202:1";
# TLS_Prio = "NORMAL";
# Realm = "realm.net"; # Reject the peer if it does not advertise this realm.
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; } ;
......
......@@ -85,10 +85,14 @@ struct rgw_client {
/* The FQDN, realm, and optional aliases */
int is_local; /* true if the RADIUS client runs on the same host -- we use Diameter Identity in that case */
enum rgw_cli_type type; /* is it a proxy ? */
char *fqdn;
DiamId_t fqdn; /* malloc'd here */
size_t fqdn_len;
char *realm;
char **aliases;
DiamId_t realm; /* references another string, do not free */
size_t realm_len;
struct {
os0_t name;
size_t len;
} *aliases; /* Received aliases */
size_t aliases_nb;
/* The secret key data. */
......@@ -209,7 +213,8 @@ static void * dupl_th(void * arg) {
static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, unsigned char ** key, size_t keylen, enum rgw_cli_type type )
{
struct rgw_client *tmp = NULL;
char buf[255];
DiamId_t fqdn;
size_t fqdn_len;
int ret, i;
int loc = 0;
......@@ -219,6 +224,7 @@ static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, u
/* The client is local */
loc = 1;
} else {
char buf[255];
/* Search FQDN for the client */
ret = getnameinfo( *ip_port, sizeof(struct sockaddr_storage), &buf[0], sizeof(buf), NULL, 0, 0 );
......@@ -226,6 +232,12 @@ static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, u
TRACE_DEBUG(INFO, "Unable to resolve peer name: %s", gai_strerror(ret));
return EINVAL;
}
fqdn = &buf[0];
CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&fqdn, &fqdn_len, 1),
{
TRACE_DEBUG(INFO, "Unable to use resolved peer name '%s' as DiameterIdentity: %s", buf, strerror(ret));
return ret;
} );
}
/* Create the new object */
......@@ -245,14 +257,19 @@ static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, u
tmp->is_local = 1;
} else {
/* Copy the fqdn */
CHECK_MALLOC( tmp->fqdn = strdup(buf) );
tmp->fqdn_len = strlen(tmp->fqdn);
tmp->fqdn = fqdn;
tmp->fqdn_len = fqdn_len;
/* Find an appropriate realm */
tmp->realm = strchr(tmp->fqdn, '.');
if (tmp->realm)
tmp->realm = strchr(fqdn, '.');
if (tmp->realm) {
tmp->realm += 1;
if ((!tmp->realm) || (*tmp->realm == '\0')) /* in case the fqdn was "localhost." for example, if it is possible... */
tmp->realm_len = tmp->fqdn_len - (tmp->realm - fqdn);
}
if ((!tmp->realm) || (*tmp->realm == '\0')) { /* in case the fqdn was "localhost." for example, if it is possible... */
tmp->realm = fd_g_config->cnf_diamrlm;
tmp->realm_len = fd_g_config->cnf_diamrlm_len;
}
}
/* move the sa info reference */
......@@ -281,7 +298,7 @@ static void client_unlink(struct rgw_client * client)
/* Free the data */
for (idx = 0; idx < client->aliases_nb; idx++)
free(client->aliases[idx]);
free(client->aliases[idx].name);
free(client->aliases);
free(client->fqdn);
free(client->sa);
......@@ -531,9 +548,10 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
int idx;
int valid_nas_info = 0;
struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL;
char * oh_str = NULL;
char * or_str = NULL;
char * rr_str = NULL;
size_t nas_id_len;
char * oh_str = NULL; size_t oh_strlen; int oh_free = 0;
char * or_str = NULL; size_t or_strlen;
char * rr_str = NULL; size_t rr_strlen;
char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */
struct avp *avp = NULL;
......@@ -554,6 +572,7 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
if ((attr->type == RADIUS_ATTR_NAS_IDENTIFIER) && (attr_len > 0)) {
nas_id = attr;
nas_id_len = attr_len;
continue;
}
......@@ -567,7 +586,7 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
TRACE_DEBUG(FULL, "The message does not contain any NAS identification attribute.");
/* Get information on this peer */
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
goto diameter;
}
......@@ -618,12 +637,14 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
TRACE_DEBUG(INFO, "Message received with a NAS-IP-Address or NAS-IPv6-Address different \nfrom the sender's. Please configure as Proxy if this is expected.\n Message discarded.");
return EINVAL;
} else {
/* the peer is configured as a proxy, or running on localhost, so accept the message */
int ret;
sSS ss;
/* the peer is configured as a proxy, or running on localhost, so accept the message */
/* In that case, the cli will be stored as Route-Record and the NAS-IP-Address as origin */
if (!cli->is_local) {
rr_str = cli->fqdn;
rr_strlen = cli->fqdn_len;
}
/* We must DNS-reverse the NAS-IP*-Address */
......@@ -640,25 +661,39 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
CHECK_SYS_DO( getnameinfo( (sSA *)&ss, sSAlen(&ss), &buf[0], sizeof(buf), NULL, 0, NI_NAMEREQD),
{
if (cli->is_local) {
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
goto diameter;
}
TRACE_DEBUG(INFO, "The NAS-IP*-Address cannot be DNS reversed in order to create the Origin-Host AVP; rejecting the message (translation is impossible).");
return EINVAL;
} );
oh_str = &buf[0];
CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
{
if (cli->is_local) {
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
goto diameter;
}
TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
return ret;
} );
oh_free = 1;
or_str = strchr(oh_str, '.');
if (or_str) {
or_str ++; /* move after the first dot */
if (*or_str == '\0')
or_str = NULL; /* Discard this realm, we will use the local realm later */
else
or_strlen = oh_strlen - (or_str - oh_str);
}
}
} else {
/* The attribute matches the source address, just use this in origin-host */
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
}
goto diameter; /* we ignore the nas_id in that case */
......@@ -667,7 +702,7 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
/* We don't have a NAS-IP*-Address attribute if we are here */
if (cli->is_local) {
/* Simple: we use our own configuration */
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
goto diameter;
}
......@@ -696,14 +731,14 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
*/
/* first, check if the nas_id is the fqdn of the peer or a known alias */
if ((cli->fqdn_len == (nas_id->length - sizeof(struct radius_attr_hdr)))
&& (!strncasecmp((char *)(nas_id + 1), cli->fqdn, nas_id->length - sizeof(struct radius_attr_hdr)))) {
if (!fd_os_almostcasecmp(nas_id + 1, nas_id_len,
cli->fqdn, cli->fqdn_len)) {
TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client");
found = 1;
} else {
for (idx = 0; idx < cli->aliases_nb; idx++) {
if (((nas_id->length - sizeof(struct radius_attr_hdr)) == strlen(cli->aliases[idx]))
&& (!strncasecmp((char *)(nas_id + 1), cli->aliases[idx], nas_id->length - sizeof(struct radius_attr_hdr)))) {
if (!fd_os_cmp(nas_id + 1, nas_id_len,
cli->aliases[idx].name, cli->aliases[idx].len)) {
TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache");
found = 1;
break;
......@@ -713,14 +748,14 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
if (found) {
/* The NAS-Identifier matches the source IP */
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
goto diameter;
}
/* Attempt DNS resolution of the identifier */
ASSERT( nas_id->length - sizeof(struct radius_attr_hdr) < sizeof(buf) );
memcpy(buf, nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr));
ASSERT( nas_id_len < sizeof(buf) );
memcpy(buf, nas_id + 1, nas_id_len);
buf[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0';
/* Now check if this alias is valid for this peer */
......@@ -744,44 +779,56 @@ int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client
if (!found) {
if (cli->type == RGW_CLI_NAS) {
TRACE_DEBUG(INFO, "The NAS-Identifier value '%.*s' resolves to a different IP than the client's, discarding the message. \nConfigure this client as a Proxy if this message should be valid.",
nas_id->length - sizeof(struct radius_attr_hdr), nas_id + 1);
nas_id_len, nas_id + 1);
return EINVAL;
} else {
/* This identifier matches a different IP, assume it is a proxied message */
if (!cli->is_local) {
rr_str = cli->fqdn;
rr_strlen = cli->fqdn_len;
}
oh_str = &buf[0]; /* The canonname resolved */
CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
{
TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
return ret;
} );
oh_free = 1;
or_str = strchr(oh_str, '.');
if (or_str) {
or_str ++; /* move after the first dot */
if (*or_str == '\0')
or_str = NULL; /* Discard this realm, we will use the local realm later */
else
or_strlen = oh_strlen - (or_str - oh_str);
}
}
} else {
/* It is a valid alias, save it */
CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(char *)) );
CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1] = malloc( 1 + nas_id->length - sizeof(struct radius_attr_hdr) ));
memcpy( cli->aliases[cli->aliases_nb + 1], nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr));
*(cli->aliases[cli->aliases_nb + 1] + nas_id->length - sizeof(struct radius_attr_hdr)) = '\0';
CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(cli->aliases[0])) );
CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1].name = os0dup(nas_id + 1, nas_id_len ) );
cli->aliases[cli->aliases_nb + 1].len = nas_id_len;
cli->aliases_nb ++;
TRACE_DEBUG(FULL, "Saved valid alias for client: '%s' -> '%s'", cli->aliases[cli->aliases_nb + 1], cli->fqdn);
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
TRACE_DEBUG(FULL, "Saved valid alias for client: '%.*s' -> '%s'", nas_id_len, nas_id + 1, cli->fqdn);
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
}
} else {
/* Error resolving the name */
TRACE_DEBUG(INFO, "NAS-Identifier '%s' cannot be resolved: %s. Ignoring...", buf, gai_strerror(ret));
/* Assume this is a valid identifier for the client */
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
}
}
/* Now, let's create the empty Diameter message with Origin-Host, -Realm, and Route-Record if needed. */
diameter:
ASSERT(oh_str); /* If it is not defined here, there is a bug... */
if (!or_str)
if (!or_str) {
or_str = fd_g_config->cnf_diamrlm; /* Use local realm in that case */
or_strlen = fd_g_config->cnf_diamrlm_len;
}
/* Create an empty Diameter message so that extensions can store their AVPs */
CHECK_FCT( fd_msg_new ( NULL, MSGFL_ALLOC_ETEID, diam ) );
......@@ -790,7 +837,7 @@ diameter:
CHECK_FCT( fd_msg_avp_new ( cache_orig_host, 0, &avp ) );
memset(&avp_val, 0, sizeof(avp_val));
avp_val.os.data = (unsigned char *)oh_str;
avp_val.os.len = strlen(oh_str);
avp_val.os.len = oh_strlen;
CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
......@@ -798,7 +845,7 @@ diameter:
CHECK_FCT( fd_msg_avp_new ( cache_orig_realm, 0, &avp ) );
memset(&avp_val, 0, sizeof(avp_val));
avp_val.os.data = (unsigned char *)or_str;
avp_val.os.len = strlen(or_str);
avp_val.os.len = or_strlen;
CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
......@@ -806,28 +853,37 @@ diameter:
CHECK_FCT( fd_msg_avp_new ( cache_route_record, 0, &avp ) );
memset(&avp_val, 0, sizeof(avp_val));
avp_val.os.data = (unsigned char *)rr_str;
avp_val.os.len = strlen(rr_str);
avp_val.os.len = rr_strlen;
CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
}
if (oh_free)
free(oh_str);
/* Done! */
return 0;
}
int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm)
int rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen)
{
TRACE_ENTRY("%p %p %p", cli, fqdn, realm);
CHECK_PARAMS(cli && fqdn);
TRACE_ENTRY("%p %p %p %p %p", cli, fqdn, fqdnlen, realm, realmlen);
CHECK_PARAMS(cli && fqdn && fqdnlen);
if (cli->is_local) {
*fqdn = fd_g_config->cnf_diamid;
*fqdnlen = fd_g_config->cnf_diamid_len;
if (realm)
*realm= fd_g_config->cnf_diamrlm;
if (realmlen)
*realmlen= fd_g_config->cnf_diamrlm_len;
} else {
*fqdn = cli->fqdn;
*fqdnlen = cli->fqdn_len;
if (realm)
*realm= cli->realm;
if (realmlen)
*realmlen= cli->realm_len;
}
return 0;
......
......@@ -58,7 +58,7 @@ struct rgw_client;
int rgw_clients_getkey(struct rgw_client * cli, unsigned char **key, size_t *key_len);
char * rgw_clients_id(struct rgw_client *cli);
int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm);
int rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen);
/* Each plugin must provide the following structure. */
extern struct rgw_api {
......
......@@ -147,8 +147,9 @@ static void * server_thread(void * param)
/* parse the message, loop if message is invalid */
CHECK_FCT_DO( rgw_msg_parse(&buf[0], len, &msg),
{
char * cliname = NULL;
CHECK_FCT_DO( rgw_clients_get_origin(nas_info, &cliname, NULL), );
DiamId_t cliname = NULL;
size_t clisz;
CHECK_FCT_DO( rgw_clients_get_origin(nas_info, &cliname, &clisz, NULL, NULL), );
TRACE_DEBUG(INFO, "Discarding invalid RADIUS message from '%s'", cliname);
rgw_clients_dispose(&nas_info);
continue;
......
......@@ -305,9 +305,9 @@ static int acct_rad_req( struct rgwp_config * cs, struct session ** session, str
const char * prefix = "Diameter/";
size_t pref_len;
uint8_t * si = NULL;
os0_t si = NULL;
size_t si_len = 0;
uint8_t * un = NULL;
os0_t un = NULL;
size_t un_len = 0;
TRACE_ENTRY("%p %p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw, cli);
......@@ -486,7 +486,7 @@ static int acct_rad_req( struct rgwp_config * cs, struct session ** session, str
/* Create the Session-Id AVP if needed */
if (!*session) {
CHECK_FCT( fd_sess_fromsid ( (char *)/* cast should be removed later */si, si_len, session, NULL) );
CHECK_FCT( fd_sess_fromsid ( si, si_len, session, NULL) );
TRACE_DEBUG(FULL, "[acct.rgwx] Translating new accounting message for session '%.*s'...", si_len, si);
......@@ -662,13 +662,13 @@ static int acct_rad_req( struct rgwp_config * cs, struct session ** session, str
char buf[32];
char * attr_val, *auth_val;
attr_val = (char *)(attr + 1);
auth_val = attr_val + strlen(CLASS_AAI_PREFIX);
if ( (attr->length > sizeof(struct radius_attr_hdr) + strlen(CLASS_AAI_PREFIX) )
&& (attr->length < sizeof(struct radius_attr_hdr) + strlen(CLASS_AAI_PREFIX) + sizeof(buf))
&& ! strncmp(attr_val, CLASS_AAI_PREFIX, strlen(CLASS_AAI_PREFIX))) {
auth_val = attr_val + CONSTSTRLEN(CLASS_AAI_PREFIX);
if ( (attr->length > sizeof(struct radius_attr_hdr) + CONSTSTRLEN(CLASS_AAI_PREFIX) )
&& (attr->length < sizeof(struct radius_attr_hdr) + CONSTSTRLEN(CLASS_AAI_PREFIX) + sizeof(buf))
&& ! strncmp(attr_val, CLASS_AAI_PREFIX, CONSTSTRLEN(CLASS_AAI_PREFIX))) {
memset(buf, 0, sizeof(buf));
memcpy(buf, auth_val, attr->length - sizeof(struct radius_attr_hdr) - strlen(CLASS_AAI_PREFIX));
memcpy(buf, auth_val, attr->length - sizeof(struct radius_attr_hdr) - CONSTSTRLEN(CLASS_AAI_PREFIX));
if (sscanf(buf, "%u", &auth_appl) == 1) {
TRACE_DEBUG(ANNOYING, "Found Class attribute with '%s' prefix (attr #%d), AAI:%u.", CLASS_AAI_PREFIX, idx, auth_appl);
}
......@@ -1300,8 +1300,10 @@ static int acct_diam_ans( struct rgwp_config * cs, struct session * session, str
if (st->send_str) {
struct msg * str = NULL;
struct msg_hdr * hdr = NULL;
char * fqdn;
char * realm;
DiamId_t fqdn;
size_t fqdn_len;
DiamId_t realm;
size_t realm_len;
union avp_value avp_val;
/* Create a new STR message */
......@@ -1322,13 +1324,13 @@ static int acct_diam_ans( struct rgwp_config * cs, struct session * session, str
CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
/* Get information on the NAS */
CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) );
CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdn_len, &realm, &realm_len) );
/* Add the Origin-Host as next AVP */
CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_Host, 0, &avp ) );
memset(&avp_val, 0, sizeof(avp_val));
avp_val.os.data = (unsigned char *)fqdn;
avp_val.os.len = strlen(fqdn);
avp_val.os.len = fqdn_len;
CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
......@@ -1336,7 +1338,7 @@ static int acct_diam_ans( struct rgwp_config * cs, struct session * session, str
CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_Realm, 0, &avp ) );
memset(&avp_val, 0, sizeof(avp_val));
avp_val.os.data = (unsigned char *)realm;
avp_val.os.len = strlen(realm);
avp_val.os.len = realm_len;
CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
......
......@@ -238,13 +238,13 @@ static int auth_rad_req( struct rgwp_config * cs, struct session ** session, str
int got_empty_eap = 0;
const char * prefix = "Diameter/";
size_t pref_len;
uint8_t * dh = NULL;
os0_t dh = NULL;
size_t dh_len = 0;
uint8_t * dr = NULL;
os0_t dr = NULL;
size_t dr_len = 0;
uint8_t * si = NULL;
os0_t si = NULL;
size_t si_len = 0;
uint8_t * un = NULL;
os0_t un = NULL;
size_t un_len = 0;
size_t nattr_used = 0;
struct avp ** avp_tun = NULL, *avp = NULL;
......@@ -292,7 +292,7 @@ static int auth_rad_req( struct rgwp_config * cs, struct session ** session, str
to the NAS-IP-Address attribute (preferred if available),
and/or to the NAS-Identifier attribute. (Note that the RADIUS
NAS-Identifier is not required to be an FQDN.)
-> done in rgw_msg_create_base.
-> done in rgw_clients_create_origin.
- The response MUST have an Origin-AAA-Protocol AVP added,
indicating the protocol of origin of the message.
......@@ -452,27 +452,30 @@ static int auth_rad_req( struct rgwp_config * cs, struct session ** session, str
/* Create the session if it is not already done */
if (*session == NULL) {
char * sess_str = NULL;
os0_t sess_str = NULL;
size_t sess_strlen;
if (si_len) {
/* We already have the Session-Id, just use it */
CHECK_FCT( fd_sess_fromsid ( (char *) /* this cast will be removed later */ si, si_len, session, NULL) );
CHECK_FCT( fd_sess_fromsid ( si, si_len, session, NULL) );
} else {
/* Create a new Session-Id string */
char * fqdn;
char * realm;
DiamId_t fqdn;
size_t fqdnlen;
DiamId_t realm;
size_t realmlen;
/* Get information on the RADIUS client */
CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) );
CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdnlen, &realm, &realmlen) );
/* If we have a user name, create the new session with it */
if (un) {
int len;
/* If not found, create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */
/* If not found, create a new Session-Id. Our format is: {fqdn;hi32;lo32;username;diamid} */
CHECK_MALLOC( sess_str = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) );
len = sprintf(sess_str, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
CHECK_FCT( fd_sess_new(session, fqdn, sess_str, len) );
len = sprintf((char *)sess_str, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
CHECK_FCT( fd_sess_new(session, fqdn, fqdnlen, sess_str, len) );
free(sess_str);
} else {
/* We don't have enough information to create the Session-Id, the RADIUS message is probably invalid */
......@@ -482,14 +485,14 @@ static int auth_rad_req( struct rgwp_config * cs, struct session ** session, str
}
/* Now, add the Session-Id AVP at beginning of Diameter message */
CHECK_FCT( fd_sess_getsid(*session, &sess_str) );
CHECK_FCT( fd_sess_getsid(*session, &sess_str, &sess_strlen) );
TRACE_DEBUG(FULL, "[auth.rgwx] Translating new message for session '%s'...", sess_str);
/* Add the Session-Id AVP as first AVP */
CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) );
value.os.data = (unsigned char *)sess_str;
value.os.len = strlen(sess_str);
value.os.data = sess_str;
value.os.len = sess_strlen;
CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
}
......@@ -563,18 +566,18 @@ static int auth_rad_req( struct rgwp_config * cs, struct session ** session, str
/* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
#define CONV2DIAM_STR( _dictobj_ ) \
CHECK_PARAMS( attr->length >= 2 ); \
CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) ); \
/* Create the AVP with the specified dictionary model */ \
CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \
value.os.len = attr->length - 2; \
value.os.data = (unsigned char *)(attr + 1); \
value.os.len = attr->length - sizeof(struct radius_attr_hdr); \
value.os.data = (os0_t)(attr + 1); \
CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); \
/* Add the AVP in the Diameter message. */ \
CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); \
/* Same thing, for scalar AVPs of 32 bits */
#define CONV2DIAM_32B( _dictobj_ ) \
CHECK_PARAMS( attr->length == 6 ); \
CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint32_t) );\
CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \
{ \
uint8_t * v = (uint8_t *)(attr + 1); \
......@@ -588,7 +591,7 @@ static int auth_rad_req( struct rgwp_config * cs, struct session ** session, str
/* And the 64b version */