Changeset 706:4ffbc9f1e922 in freeDiameter for extensions/app_radgw/rgw_clients.c
- Timestamp:
- Feb 9, 2011, 3:26:58 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/app_radgw/rgw_clients.c
r554 r706 86 86 int is_local; /* true if the RADIUS client runs on the same host -- we use Diameter Identity in that case */ 87 87 enum rgw_cli_type type; /* is it a proxy ? */ 88 char *fqdn;88 DiamId_t fqdn; /* malloc'd here */ 89 89 size_t fqdn_len; 90 char *realm; 91 char **aliases; 90 DiamId_t realm; /* references another string, do not free */ 91 size_t realm_len; 92 struct { 93 os0_t name; 94 size_t len; 95 } *aliases; /* Received aliases */ 92 96 size_t aliases_nb; 93 97 … … 210 214 { 211 215 struct rgw_client *tmp = NULL; 212 char buf[255]; 216 DiamId_t fqdn; 217 size_t fqdn_len; 213 218 int ret, i; 214 219 int loc = 0; … … 220 225 loc = 1; 221 226 } else { 227 char buf[255]; 222 228 223 229 /* Search FQDN for the client */ … … 227 233 return EINVAL; 228 234 } 235 fqdn = &buf[0]; 236 CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&fqdn, &fqdn_len, 1), 237 { 238 TRACE_DEBUG(INFO, "Unable to use resolved peer name '%s' as DiameterIdentity: %s", buf, strerror(ret)); 239 return ret; 240 } ); 229 241 } 230 242 … … 246 258 } else { 247 259 /* Copy the fqdn */ 248 CHECK_MALLOC( tmp->fqdn = strdup(buf) ); 249 tmp->fqdn_len = strlen(tmp->fqdn); 260 tmp->fqdn = fqdn; 261 tmp->fqdn_len = fqdn_len; 262 250 263 /* Find an appropriate realm */ 251 tmp->realm = strchr( tmp->fqdn, '.');252 if (tmp->realm) 264 tmp->realm = strchr(fqdn, '.'); 265 if (tmp->realm) { 253 266 tmp->realm += 1; 254 if ((!tmp->realm) || (*tmp->realm == '\0')) /* in case the fqdn was "localhost." for example, if it is possible... */ 267 tmp->realm_len = tmp->fqdn_len - (tmp->realm - fqdn); 268 } 269 if ((!tmp->realm) || (*tmp->realm == '\0')) { /* in case the fqdn was "localhost." for example, if it is possible... */ 255 270 tmp->realm = fd_g_config->cnf_diamrlm; 271 tmp->realm_len = fd_g_config->cnf_diamrlm_len; 272 } 256 273 } 257 274 … … 282 299 /* Free the data */ 283 300 for (idx = 0; idx < client->aliases_nb; idx++) 284 free(client->aliases[idx] );301 free(client->aliases[idx].name); 285 302 free(client->aliases); 286 303 free(client->fqdn); … … 532 549 int valid_nas_info = 0; 533 550 struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL; 534 char * oh_str = NULL; 535 char * or_str = NULL; 536 char * rr_str = NULL; 551 size_t nas_id_len; 552 char * oh_str = NULL; size_t oh_strlen; int oh_free = 0; 553 char * or_str = NULL; size_t or_strlen; 554 char * rr_str = NULL; size_t rr_strlen; 537 555 char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */ 538 556 … … 555 573 if ((attr->type == RADIUS_ATTR_NAS_IDENTIFIER) && (attr_len > 0)) { 556 574 nas_id = attr; 575 nas_id_len = attr_len; 557 576 continue; 558 577 } … … 568 587 569 588 /* Get information on this peer */ 570 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );589 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 571 590 572 591 goto diameter; … … 619 638 return EINVAL; 620 639 } else { 640 int ret; 641 sSS ss; 621 642 /* the peer is configured as a proxy, or running on localhost, so accept the message */ 622 sSS ss;623 643 624 644 /* In that case, the cli will be stored as Route-Record and the NAS-IP-Address as origin */ 625 645 if (!cli->is_local) { 626 646 rr_str = cli->fqdn; 647 rr_strlen = cli->fqdn_len; 627 648 } 628 649 … … 641 662 { 642 663 if (cli->is_local) { 643 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );664 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 644 665 goto diameter; 645 666 } … … 648 669 return EINVAL; 649 670 } ); 671 672 oh_str = &buf[0]; 673 CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1), 674 { 675 if (cli->is_local) { 676 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 677 goto diameter; 678 } 679 680 TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret)); 681 return ret; 682 } ); 683 oh_free = 1; 650 684 651 oh_str = &buf[0];652 685 or_str = strchr(oh_str, '.'); 653 686 if (or_str) { … … 655 688 if (*or_str == '\0') 656 689 or_str = NULL; /* Discard this realm, we will use the local realm later */ 690 else 691 or_strlen = oh_strlen - (or_str - oh_str); 657 692 } 658 693 } 659 694 } else { 660 695 /* The attribute matches the source address, just use this in origin-host */ 661 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );696 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 662 697 } 663 698 … … 668 703 if (cli->is_local) { 669 704 /* Simple: we use our own configuration */ 670 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );705 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 671 706 goto diameter; 672 707 } … … 697 732 698 733 /* first, check if the nas_id is the fqdn of the peer or a known alias */ 699 if ( (cli->fqdn_len == (nas_id->length - sizeof(struct radius_attr_hdr)))700 && (!strncasecmp((char *)(nas_id + 1), cli->fqdn, nas_id->length - sizeof(struct radius_attr_hdr)))) {734 if (!fd_os_almostcasecmp(nas_id + 1, nas_id_len, 735 cli->fqdn, cli->fqdn_len)) { 701 736 TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client"); 702 737 found = 1; 703 738 } else { 704 739 for (idx = 0; idx < cli->aliases_nb; idx++) { 705 if ( ((nas_id->length - sizeof(struct radius_attr_hdr)) == strlen(cli->aliases[idx]))706 && (!strncasecmp((char *)(nas_id + 1), cli->aliases[idx], nas_id->length - sizeof(struct radius_attr_hdr)))) {740 if (!fd_os_cmp(nas_id + 1, nas_id_len, 741 cli->aliases[idx].name, cli->aliases[idx].len)) { 707 742 TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache"); 708 743 found = 1; … … 714 749 if (found) { 715 750 /* The NAS-Identifier matches the source IP */ 716 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );751 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 717 752 718 753 goto diameter; … … 720 755 721 756 /* Attempt DNS resolution of the identifier */ 722 ASSERT( nas_id ->length - sizeof(struct radius_attr_hdr)< sizeof(buf) );723 memcpy(buf, nas_id + 1, nas_id ->length - sizeof(struct radius_attr_hdr));757 ASSERT( nas_id_len < sizeof(buf) ); 758 memcpy(buf, nas_id + 1, nas_id_len); 724 759 buf[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0'; 725 760 … … 745 780 if (cli->type == RGW_CLI_NAS) { 746 781 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.", 747 nas_id ->length - sizeof(struct radius_attr_hdr), nas_id + 1);782 nas_id_len, nas_id + 1); 748 783 return EINVAL; 749 784 } else { … … 751 786 if (!cli->is_local) { 752 787 rr_str = cli->fqdn; 788 rr_strlen = cli->fqdn_len; 753 789 } 754 790 oh_str = &buf[0]; /* The canonname resolved */ 791 CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1), 792 { 793 TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret)); 794 return ret; 795 } ); 796 oh_free = 1; 755 797 or_str = strchr(oh_str, '.'); 756 798 if (or_str) { … … 758 800 if (*or_str == '\0') 759 801 or_str = NULL; /* Discard this realm, we will use the local realm later */ 802 else 803 or_strlen = oh_strlen - (or_str - oh_str); 760 804 } 761 805 } 762 806 } else { 763 807 /* It is a valid alias, save it */ 764 CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(char *)) ); 765 CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1] = malloc( 1 + nas_id->length - sizeof(struct radius_attr_hdr) )); 766 memcpy( cli->aliases[cli->aliases_nb + 1], nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr)); 767 *(cli->aliases[cli->aliases_nb + 1] + nas_id->length - sizeof(struct radius_attr_hdr)) = '\0'; 808 CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(cli->aliases[0])) ); 809 810 CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1].name = os0dup(nas_id + 1, nas_id_len ) ); 811 cli->aliases[cli->aliases_nb + 1].len = nas_id_len; 812 768 813 cli->aliases_nb ++; 769 TRACE_DEBUG(FULL, "Saved valid alias for client: '% s' -> '%s'", cli->aliases[cli->aliases_nb + 1], cli->fqdn);770 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );814 TRACE_DEBUG(FULL, "Saved valid alias for client: '%.*s' -> '%s'", nas_id_len, nas_id + 1, cli->fqdn); 815 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 771 816 } 772 817 } else { … … 774 819 TRACE_DEBUG(INFO, "NAS-Identifier '%s' cannot be resolved: %s. Ignoring...", buf, gai_strerror(ret)); 775 820 /* Assume this is a valid identifier for the client */ 776 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &o r_str) );821 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) ); 777 822 } 778 823 } … … 781 826 diameter: 782 827 ASSERT(oh_str); /* If it is not defined here, there is a bug... */ 783 if (!or_str) 828 if (!or_str) { 784 829 or_str = fd_g_config->cnf_diamrlm; /* Use local realm in that case */ 830 or_strlen = fd_g_config->cnf_diamrlm_len; 831 } 785 832 786 833 /* Create an empty Diameter message so that extensions can store their AVPs */ … … 791 838 memset(&avp_val, 0, sizeof(avp_val)); 792 839 avp_val.os.data = (unsigned char *)oh_str; 793 avp_val.os.len = strlen(oh_str);840 avp_val.os.len = oh_strlen; 794 841 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) ); 795 842 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) ); … … 799 846 memset(&avp_val, 0, sizeof(avp_val)); 800 847 avp_val.os.data = (unsigned char *)or_str; 801 avp_val.os.len = strlen(or_str);848 avp_val.os.len = or_strlen; 802 849 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) ); 803 850 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) ); … … 807 854 memset(&avp_val, 0, sizeof(avp_val)); 808 855 avp_val.os.data = (unsigned char *)rr_str; 809 avp_val.os.len = strlen(rr_str);856 avp_val.os.len = rr_strlen; 810 857 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) ); 811 858 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) ); 812 859 } 813 860 861 if (oh_free) 862 free(oh_str); 863 814 864 /* Done! */ 815 865 return 0; 816 866 } 817 867 818 int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm)819 { 820 TRACE_ENTRY("%p %p %p ", cli, fqdn, realm);821 CHECK_PARAMS(cli && fqdn );868 int rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen) 869 { 870 TRACE_ENTRY("%p %p %p %p %p", cli, fqdn, fqdnlen, realm, realmlen); 871 CHECK_PARAMS(cli && fqdn && fqdnlen); 822 872 823 873 if (cli->is_local) { 824 874 *fqdn = fd_g_config->cnf_diamid; 875 *fqdnlen = fd_g_config->cnf_diamid_len; 825 876 if (realm) 826 877 *realm= fd_g_config->cnf_diamrlm; 878 if (realmlen) 879 *realmlen= fd_g_config->cnf_diamrlm_len; 827 880 } else { 828 881 *fqdn = cli->fqdn; 882 *fqdnlen = cli->fqdn_len; 829 883 if (realm) 830 884 *realm= cli->realm; 885 if (realmlen) 886 *realmlen= cli->realm_len; 831 887 } 832 888
Note: See TracChangeset
for help on using the changeset viewer.