Navigation


Changeset 442:02e3976b9163 in freeDiameter


Ignore:
Timestamp:
Jul 28, 2010, 5:51:29 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Attempt at fixing a problem with NAS-Identifier RADIUS attribute handling

File:
1 edited

Legend:

Unmodified
Added
Removed
  • extensions/app_radgw/rgw_clients.c

    r403 r442  
    6767        /* The FQDN, realm, and optional aliases */
    6868        char                    *fqdn;
     69        size_t                   fqdn_len;
    6970        char                    *realm;
    7071        char                    **aliases;
     
    109110        /* Copy the fqdn */
    110111        CHECK_MALLOC( tmp->fqdn = strdup(buf) );
     112        tmp->fqdn_len = strlen(tmp->fqdn);
    111113        /* Find an appropriate realm */
    112114        tmp->realm = strchr(tmp->fqdn, '.');
     
    370372        /* Now check the nas_id */
    371373        if (nas_id) {
     374                char * str;
     375                int found, ret;
     376                struct addrinfo hint, *res, *ptr;
     377               
    372378                /*
    373379                        In RADIUS it would be possible for a rogue NAS to forge the NAS-
     
    386392                        found, then an error is logged, but no other action is taken.
    387393                */
    388        
    389                 /* copy the alias */
    390                 char * str;
    391                 int found, ret;
    392                 struct addrinfo hint, *res;
    393                 CHECK_MALLOC( str = malloc(nas_id->length - sizeof(struct radius_attr_hdr) + 1) );
    394                 memcpy(str, nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr));
    395                 str[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0';
    396                
    397                 /* Check if this alias is already in the aliases list */
    398                 if (!strcasecmp(str, cli->fqdn)) {
     394               
     395                /* first, check if the nas_id is the fqdn of the peer or a known alias */
     396                if ((cli->fqdn_len == (nas_id->length - sizeof(struct radius_attr_hdr)))
     397                && (!strncasecmp((char *)(nas_id + 1), cli->fqdn, nas_id->length - sizeof(struct radius_attr_hdr)))) {
    399398                        TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the NAS");
    400399                        found = 1;
    401400                } else {
    402401                        for (idx = 0; idx < cli->aliases_nb; idx++) {
    403                                 if (!strcasecmp(str, cli->aliases[idx])) {
     402                                if (((nas_id->length - sizeof(struct radius_attr_hdr)) == strlen(cli->aliases[idx]))
     403                                && (!strncasecmp((char *)(nas_id + 1), cli->aliases[idx], nas_id->length - sizeof(struct radius_attr_hdr)))) {
    404404                                        TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache");
    405405                                        found = 1;
     
    410410               
    411411                if (found) {
    412                         free(str);
    413412                        msg->valid_nas_info |= 2;
    414413                        goto end;
    415414                }
     415               
     416                /* copy the identifier, we try to DNS resolve it */
     417                CHECK_MALLOC( str = malloc(nas_id->length - sizeof(struct radius_attr_hdr) + 1) );
     418                memcpy(str, nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr));
     419                str[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0';
    416420               
    417421                /* Now check if this alias is valid for this peer */
     
    420424                hint.ai_flags  = AI_CANONNAME;
    421425                ret = getaddrinfo(str, NULL, &hint, &res);
    422                 if (ret) {
    423                         TRACE_DEBUG(INFO, "Error while resolving NAS-Identifier value '%s': %s. Discarding message...", str, gai_strerror(ret));
    424                         free(str);
    425                         return EINVAL;
    426                 }
    427                 if (strcasecmp(cli->fqdn, res->ai_canonname)) {
    428                         TRACE_DEBUG(INFO, "The NAS-Identifier value is not valid: '%s' resolved to '%s', expected '%s'. Discarding...", str, res->ai_canonname, cli->fqdn);
    429                         free(str);
     426                if (ret == 0) {
     427                        /* The name was resolved correctly, it must match the IP of the client: */
     428                        for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {
     429                                if (cli->sa->sa_family != ptr->ai_family)
     430                                        continue;
     431                                if (memcmp(cli->sa, ptr->ai_addr, sSAlen(cli->sa)))
     432                                        continue;
     433                               
     434                                /* It matches: the alias is valid */
     435                                found = 1;
     436                                break;
     437                        }
    430438                        freeaddrinfo(res);
    431                         return EINVAL;
     439                       
     440                        if (!found) {
     441                                TRACE_DEBUG(INFO, "The NAS-Identifier value '%s' resolves to a different IP from the NAS's, discarding the message.", str);
     442                                free(str);
     443                                return EINVAL;
     444                        }
     445                } else {
     446                        /* Error resolving the name */
     447                        TRACE_DEBUG(INFO, "Error while resolving NAS-Identifier value '%s': %s. Ignoring...", str, gai_strerror(ret));
    432448                }
    433449               
    434450                /* It is a valid alias, save it */
    435                 freeaddrinfo(res);
    436451                CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(char *)) );
    437452                cli->aliases[cli->aliases_nb + 1] = str;
Note: See TracChangeset for help on using the changeset viewer.