Merge tag 'release_3_0_4_rc1' into tr-upgrade
authorSam Hartman <hartmans@debian.org>
Wed, 18 Jun 2014 19:36:13 +0000 (15:36 -0400)
committerSam Hartman <hartmans@debian.org>
Wed, 18 Jun 2014 19:36:13 +0000 (15:36 -0400)
Conflicts:
share/dictionary.freeradius.internal
src/main/listen.c
src/main/realms.c
src/main/tls.c
src/main/tls_listen.c
src/modules/rlm_realm/rlm_realm.c

12 files changed:
1  2 
share/dictionary.freeradius.internal
src/include/radius.h
src/include/realms.h
src/include/tls-h
src/main/realms.c
src/main/tls.c
src/main/tls_listen.c
src/modules/rlm_eap/libeap/eap_chbind.c
src/modules/rlm_eap/libeap/eapcommon.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c
src/modules/rlm_realm/rlm_realm.c
src/modules/rlm_realm/trustrouter_integ.c

@@@ -488,9 -505,10 +512,11 @@@ ATTRIBUTE        TLS-Client-Cert-X509v3-Extend
  ATTRIBUTE     TLS-Client-Cert-X509v3-Subject-Key-Identifier 1928      string
  ATTRIBUTE     TLS-Client-Cert-X509v3-Authority-Key-Identifier 1929    string
  ATTRIBUTE     TLS-Client-Cert-X509v3-Basic-Constraints 1930   string
- ATTRIBUTE     TLS-PSK-Identity                        1931    string
+ ATTRIBUTE     TLS-Client-Cert-Subject-Alt-Name-Dns    1931    string
+ ATTRIBUTE     TLS-Client-Cert-Subject-Alt-Name-Upn    1932    string
++ATTRIBUTE     TLS-PSK-Identity                        1933    string
  
- # 1932 - 1939: reserved for future cert attributes
 -# 1933 - 1939: reserved for future cert attributes
++# 1934 - 1939: reserved for future cert attributes
  
  #
  #     Range:  1940-2099
@@@ -138,120 -144,11 +144,12 @@@ typedef enum 
  #define PW_DIGEST_RESPONSE            206
  #define PW_DIGEST_ATTRIBUTES          207
  
- #define PW_FALL_THROUGH                       500
- #define PW_RELAX_FILTER                       501
- #define PW_EXEC_PROGRAM                       502
- #define PW_EXEC_PROGRAM_WAIT          503
- #define PW_AUTH_TYPE                  1000
- #define PW_PREFIX                     1003
- #define PW_SUFFIX                     1004
- #define PW_GROUP                      1005
- #define PW_CRYPT_PASSWORD             1006
- #define PW_CONNECT_RATE                       1007
- #define PW_ADD_PREFIX                 1008
- #define PW_ADD_SUFFIX                 1009
- #define PW_EXPIRATION                 1010
- #define PW_AUTZ_TYPE                  1011
- #define PW_ACCT_TYPE                  1012
- #define PW_SESSION_TYPE                       1013
- #define PW_POST_AUTH_TYPE             1014
- #define PW_PRE_PROXY_TYPE             1015
- #define PW_POST_PROXY_TYPE            1016
- #define PW_PRE_ACCT_TYPE              1017
- #define PW_EAP_TYPE                   1018
- #define PW_EAP_TLS_REQUIRE_CLIENT_CERT        1019
- #define PW_EAP_MD5_PASSWORD           1022
- #define PW_CLIENT_SHORTNAME           1024
- #define PW_LOAD_BALANCE_KEY           1025
- #define PW_RAW_ATTRIBUTE              1026
- #define PW_TNC_VLAN_ACCESS            1027
- #define PW_TNC_VLAN_ISOLATE           1028
- #define PW_USER_CATEGORY              1029
- #define PW_GROUP_NAME                 1030
- #define PW_HUNTGROUP_NAME             1031
- #define PW_SIMULTANEOUS_USE           1034
- #define PW_STRIP_USER_NAME            1035
- #define PW_HINT                               1040
- #define PAM_AUTH_ATTR                 1041
- #define PW_LOGIN_TIME                 1042
- #define PW_STRIPPED_USER_NAME         1043
- #define PW_CURRENT_TIME                       1044
- #define PW_REALM                      1045
- #define PW_NO_SUCH_ATTRIBUTE          1046
- #define PW_PACKET_TYPE                        1047
- #define PW_PROXY_TO_REALM             1048
- #define PW_REPLICATE_TO_REALM         1049
- #define PW_ACCT_SESSION_START_TIME    1050
- #define PW_ACCT_UNIQUE_SESSION_ID     1051
- #define PW_CLIENT_IP_ADDRESS          1052
- #define PW_LDAP_USERDN                        1053
- #define PW_NS_MTA_MD5_PASSWORD                1054
- #define PW_SQL_USER_NAME              1055
- #define PW_LM_PASSWORD                        1057
- #define PW_NT_PASSWORD                        1058
- #define PW_SMB_ACCOUNT_CTRL           1059
- #define PW_SMB_ACCOUNT_CTRL_TEXT      1061
- #define PW_USER_PROFILE                       1062
- #define PW_DIGEST_REALM                       1063
- #define PW_DIGEST_NONCE                       1064
- #define PW_DIGEST_METHOD              1065
- #define PW_DIGEST_URI                 1066
- #define PW_DIGEST_QOP                 1067
- #define PW_DIGEST_ALGORITHM           1068
- #define PW_DIGEST_BODY_DIGEST         1069
- #define PW_DIGEST_CNONCE              1070
- #define PW_DIGEST_NONCE_COUNT         1071
- #define PW_DIGEST_USER_NAME           1072
- #define PW_POOL_NAME                  1073
- #define PW_LDAP_GROUP                 1074
- #define PW_MODULE_SUCCESS_MESSAGE     1075
- #define PW_MODULE_FAILURE_MESSAGE     1076
- #if 0 /* no longer used */
- #define PW_X99_FAST                   1077
- #endif
- #define PW_REWRITE_RULE                       1078
- #define PW_SQL_GROUP                  1079
- #define PW_RESPONSE_PACKET_TYPE               1080
- #define PW_DIGEST_HA1                 1081
- #define PW_MS_CHAP_USE_NTLM_AUTH      1082
- #define PW_MS_CHAP_USER_NAME          1083
- #define PW_PACKET_SRC_IP_ADDRESS      1084
- #define PW_PACKET_DST_IP_ADDRESS      1085
- #define PW_PACKET_SRC_PORT            1086
- #define PW_PACKET_DST_PORT            1087
- #define PW_PACKET_AUTHENTICATION_VECTOR       1088
- #define PW_TIME_OF_DAY                        1089
- #define PW_REQUEST_PROCESSING_STAGE   1090
- #define PW_SHA_PASSWORD                       1093
- #define PW_SSHA_PASSWORD              1094
- #define PW_MD5_PASSWORD                       1095
- #define PW_SMD5_PASSWORD              1096
- #define PW_PACKET_SRC_IPV6_ADDRESS    1097
- #define PW_PACKET_DST_IPV6_ADDRESS    1098
- #define PW_VIRTUAL_SERVER             1099
- #define PW_CLEARTEXT_PASSWORD         1100
- #define PW_PASSWORD_WITH_HEADER               1101
- #define PW_SEND_COA_REQUEST           1107
- #define PW_MODULE_RETURN_CODE         1108
- #define PW_PACKET_ORIGINAL_TIMESTAMP  1109
- #define PW_HOME_SERVER_POOL           1111
- #define PW_FREERADIUS_CLIENT_IP_ADDRESS               1120
- #define PW_FREERADIUS_CLIENT_IPV6_ADDRESS     1121
- #define PW_RECV_COA_TYPE              1131
- #define PW_SEND_COA_TYPE              1132
- #define PW_MSCHAP_PASSWORD            1133
- #define PW_PACKET_TRANSMIT_COUNTER    1134
- #define PW_CACHED_SESSION_POLICY      1135
- #define PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS   1143
- #define PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS 1144
- #define PW_OTP_CHALLENGE              1145
- #define PW_EAP_SESSION_ID             1146
+ /*
+  *    All internal attributes are now defined in this file.
+  */
+ #include <freeradius-devel/attributes.h>
  
 +#define PW_CHBIND_RESPONSE_CODE               1147
  /*
   *    Integer Translations
   */
@@@ -150,19 -157,15 +157,19 @@@ int realms_init(CONF_SECTION *config)
  void realms_free(void);
  REALM *realm_find(char const *name); /* name is from a packet */
  REALM *realm_find2(char const *name); /* ... with name taken from realm_find */
-   int realms_home_server_add(home_server *home, CONF_SECTION *cs, int dual);
++  int realms_home_server_add(home_server_t *home, CONF_SECTION *cs, int dual);
 +  int realms_pool_add(home_pool_t *pool, CONF_SECTION *cs);
 +  int realms_realm_add( REALM *r, CONF_SECTION *cs);
 +
  
- void home_server_update_request(home_server *home, REQUEST *request);
- home_server *home_server_ldb(char const *realmname, home_pool_t *pool, REQUEST *request);
- home_server *home_server_find(fr_ipaddr_t *ipaddr, int port, int proto);
+ void home_server_update_request(home_server_t *home, REQUEST *request);
+ home_server_t *home_server_ldb(char const *realmname, home_pool_t *pool, REQUEST *request);
+ home_server_t *home_server_find(fr_ipaddr_t *ipaddr, uint16_t port, int proto);
  #ifdef WITH_COA
- home_server *home_server_byname(char const *name, int type);
+ home_server_t *home_server_byname(char const *name, int type);
  #endif
  #ifdef WITH_STATS
- home_server *home_server_bynumber(int number);
+ home_server_t *home_server_bynumber(int number);
  #endif
  home_pool_t *home_pool_byname(char const *name, int type);
  
Simple merge
@@@ -391,176 -344,6 +344,180 @@@ static void null_free(UNUSED void *data
  {
  }
  
- int realms_home_server_add(home_server *home, CONF_SECTION *cs, int dual)
 +
-       if (home->max_outstanding < 8) home->max_outstanding = 8;
-       if (home->max_outstanding > 65536*16) home->max_outstanding = 65536*16;
-       if (home->ping_interval < 6) home->ping_interval = 6;
-       if (home->ping_interval > 120) home->ping_interval = 120;
++int realms_home_server_add(home_server_t *home, CONF_SECTION *cs, int dual)
 +{
 +        CONF_SECTION *parent = NULL;
 +      const char * name2 = home->name;
 +      
 +      /*
 +       *      Make sure that this is set.
 +       */
 +      if (home->src_ipaddr.af == AF_UNSPEC) {
 +              home->src_ipaddr.af = home->ipaddr.af;
 +      }
 +
 +      hs_srcipaddr = NULL;
 +
 +      if (rbtree_finddata(home_servers_byname, home) != NULL) {
 +              cf_log_err_cs(cs,
 +                         "Duplicate home server name %s.", name2);
 +              goto error;
 +      }
 +
 +      if (!home->server &&
 +          (rbtree_finddata(home_servers_byaddr, home) != NULL)) {
 +              cf_log_err_cs(cs,
 +                         "Duplicate home server IP %s.", name2);
 +              goto error;
 +      }
 +
 +      if (!rbtree_insert(home_servers_byname, home)) {
 +              cf_log_err_cs(cs,
 +                         "Internal error %d adding home server %s.",
 +                         __LINE__, name2);
 +              goto error;
 +      }
 +
 +      if (!home->server &&
 +          !rbtree_insert(home_servers_byaddr, home)) {
 +              rbtree_deletebydata(home_servers_byname, home);
 +              cf_log_err_cs(cs,
 +                         "Internal error %d adding home server %s.",
 +                         __LINE__, name2);
 +              goto error;
 +      }
 +
 +#ifdef WITH_STATS
 +      home->number = home_server_max_number++;
 +      if (!rbtree_insert(home_servers_bynumber, home)) {
 +              rbtree_deletebydata(home_servers_byname, home);
 +              if (home->ipaddr.af != AF_UNSPEC) {
 +                      rbtree_deletebydata(home_servers_byname, home);
 +              }
 +              cf_log_err_cs(cs,
 +                         "Internal error %d adding home server %s.",
 +                         __LINE__, name2);
 +              goto error;
 +      }
 +#endif
 +
-       if (home->response_window < 1) home->response_window = 1;
-       if (home->response_window > 60) home->response_window = 60;
-       if (home->response_window > mainconfig.max_request_time) home->response_window = mainconfig.max_request_time;
++      FR_INTEGER_BOUND_CHECK("max_outstanding", home->max_outstanding, >=, 8);
++      FR_INTEGER_BOUND_CHECK("max_outstanding", home->max_outstanding, <=, 65536*16);
 +
-       if (home->zombie_period < 1) home->zombie_period = 1;
-       if (home->zombie_period > 120) home->zombie_period = 120;
++      FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, >=, 6);
++      FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, <=, 120);
 +
-       if (home->zombie_period < home->response_window) {
-               home->zombie_period = home->response_window;
++      FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, >=, 0, 1000);
++      FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0);
++      FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=,
++                              main_config.max_request_time, 0);
 +
-       if (home->num_pings_to_alive < 3) home->num_pings_to_alive = 3;
-       if (home->num_pings_to_alive > 10) home->num_pings_to_alive = 10;
++      /*
++       *      Track the minimum response window, so that we can
++       *      correctly set the timers in process.c
++       */
++      if (timercmp(&main_config.init_delay, &home->response_window, >)) {
++              main_config.init_delay = home->response_window;
 +      }
 +
-       if (home->ping_timeout < 3) home->ping_timeout = 3;
-       if (home->ping_timeout > 10) home->ping_timeout = 10;
++      FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, >=, 1);
++      FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, <=, 120);
++      FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, >=, (uint32_t) home->response_window.tv_sec);
++
++      FR_INTEGER_BOUND_CHECK("num_pings_to_alive", home->num_pings_to_alive, >=, 3);
++      FR_INTEGER_BOUND_CHECK("num_pings_to_alive", home->num_pings_to_alive, <=, 10);
 +
-       if (home->revive_interval < 60) home->revive_interval = 60;
-       if (home->revive_interval > 3600) home->revive_interval = 3600;
++      FR_INTEGER_BOUND_CHECK("ping_timeout", home->ping_timeout, >=, 3);
++      FR_INTEGER_BOUND_CHECK("ping_timeout", home->ping_timeout, <=, 10);
 +
-       if (home->coa_irt < 1) home->coa_irt = 1;
-       if (home->coa_irt > 5) home->coa_irt = 5;
++      FR_INTEGER_BOUND_CHECK("revive_interval", home->revive_interval, >=, 60);
++      FR_INTEGER_BOUND_CHECK("revive_interval", home->revive_interval, <=, 3600);
 +
 +#ifdef WITH_COA
-       if (home->coa_mrc < 0) home->coa_mrc = 0;
-       if (home->coa_mrc > 20 ) home->coa_mrc = 20;
++      FR_INTEGER_BOUND_CHECK("coa_irt", home->coa_irt, >=, 1);
++      FR_INTEGER_BOUND_CHECK("coa_irt", home->coa_irt, <=, 5);
 +
-       if (home->coa_mrt < 0) home->coa_mrt = 0;
-       if (home->coa_mrt > 30 ) home->coa_mrt = 30;
++      FR_INTEGER_BOUND_CHECK("coa_mrc", home->coa_mrc, <=, 20);
 +
-       if (home->coa_mrd < 5) home->coa_mrd = 5;
-       if (home->coa_mrd > 60 ) home->coa_mrd = 60;
++      FR_INTEGER_BOUND_CHECK("coa_mrt", home->coa_mrt, <=, 30);
 +
-       if (home->limit.max_connections > 1024) home->limit.max_connections = 1024;
++      FR_INTEGER_BOUND_CHECK("coa_mrd", home->coa_mrd, >=, 5);
++      FR_INTEGER_BOUND_CHECK("coa_mrd", home->coa_mrd, <=, 60);
 +#endif
 +
-       if (parent && strcmp(cf_section_name1(parent), "server") == 0) {
++      FR_INTEGER_BOUND_CHECK("max_connections", home->limit.max_connections, <=, 1024);
 +
 +#ifdef WITH_TCP
 +      /*
 +       *      UDP sockets can't be connection limited.
 +       */
 +      if (home->proto != IPPROTO_TCP) home->limit.max_connections = 0;
 +#endif
 +
 +      if ((home->limit.idle_timeout > 0) && (home->limit.idle_timeout < 5))
 +              home->limit.idle_timeout = 5;
 +      if ((home->limit.lifetime > 0) && (home->limit.lifetime < 5))
 +              home->limit.lifetime = 5;
 +      if ((home->limit.lifetime > 0) && (home->limit.idle_timeout > home->limit.lifetime))
 +              home->limit.idle_timeout = 0;
 +
 +      parent = cf_item_parent(cf_sectiontoitem(cs));
-               home_server *home2 = rad_malloc(sizeof(*home2));
++      if (strcmp(cf_section_name1(parent), "server") == 0) {
 +              home->parent_server = cf_section_name2(parent);
 +      }
 +
 +      if (dual) {
-               
++              home_server_t *home2 = talloc(home, home_server_t);
 +
 +              memcpy(home2, home, sizeof(*home2));
 +
 +              home2->type = HOME_TYPE_ACCT;
 +              home2->port++;
 +              home2->ping_user_password = NULL;
 +              home2->cs = cs;
 +              home2->parent_server = home->parent_server;
 +
 +              if (!rbtree_insert(home_servers_byname, home2)) {
 +                      cf_log_err_cs(cs,
 +                                 "Internal error %d adding home server %s.",
 +                                 __LINE__, name2);
 +                      free(home2);
 +                      return 0;
 +              }
++
 +              if (!home->server &&
 +                  !rbtree_insert(home_servers_byaddr, home2)) {
 +                      rbtree_deletebydata(home_servers_byname, home2);
 +                      cf_log_err_cs(cs,
 +                                 "Internal error %d adding home server %s.",
 +                                 __LINE__, name2);
 +                      free(home2);
 +                      return 0;
 +              }
 +
 +#ifdef WITH_STATS
 +              home2->number = home_server_max_number++;
 +              if (!rbtree_insert(home_servers_bynumber, home2)) {
 +                      rbtree_deletebydata(home_servers_byname, home2);
 +                      if (!home2->server) {
 +                              rbtree_deletebydata(home_servers_byname, home2);
 +                      }
 +                      cf_log_err_cs(cs,
 +                                 "Internal error %d adding home server %s.",
 +                                 __LINE__, name2);
 +                      free(home2);
 +                      return 0;
 +              }
 +#endif
 +      }
 +
 +      return 1;
 + error:
 +      return 0;
 +}
 +
 +
  static int home_server_add(realm_config_t *rc, CONF_SECTION *cs)
  {
        char const *name2;
diff --cc src/main/tls.c
Simple merge
@@@ -72,6 -72,8 +72,9 @@@ static void tls_socket_close(rad_listen
  {
        listen_socket_t *sock = listener->data;
  
+       SSL_shutdown(sock->ssn->ssl);
++
        listener->status = RAD_LISTEN_STATUS_EOL;
        listener->tls = NULL; /* parent owns this! */
  
index 06b1121,0000000..61b63d4
mode 100644,000000..100644
--- /dev/null
@@@ -1,244 -1,0 +1,244 @@@
-   int rcode = PW_AUTHENTICATION_REJECT;
 +/*
 + * eap_chbind.c
 + *
 + * Version:     $Id$
 + *
 + * Copyright (c) 2012, JANET(UK)
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + *
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + *
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * 3. Neither the name of JANET(UK) nor the names of its contributors
 + *    may be used to endorse or promote products derived from this software
 + *    without specific prior written permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +
 +RCSID("$Id$")
 +
 +#include "eap_chbind.h"
 +
 +#define MAX_PACKET_LEN                4096
 +
 +/*
 + * Process any channel bindings included in the request.
 + */
 +CHBIND_REQ *chbind_allocate(void)
 +{
 +  CHBIND_REQ *ret;
 +  ret = malloc(sizeof *ret);
 +  if (0 != ret)
 +    memset(ret, 0, sizeof *ret);
 +  return ret;
 +}
 +
 +void chbind_free(CHBIND_REQ *chbind)
 +{
 +  /* free the chbind response, if allocated by chbind_process */
 +  if (chbind->chbind_resp)
 +    free(chbind->chbind_resp);
 +
 +  free(chbind);
 +}
 +
 +int chbind_process(REQUEST *req, CHBIND_REQ *chbind_req)
 +{
-     return PW_AUTHENTICATION_REJECT;  /* Is this the right response? */
++  int rcode = PW_CODE_AUTHENTICATION_REJECT;
 +  REQUEST *fake = NULL;
 +  VALUE_PAIR *vp = NULL;
 +  uint8_t *attr_data;
 +  size_t datalen = 0;
 +
 +  /* check input parameters */
 +  rad_assert((req != NULL) && 
 +           (chbind_req != NULL) &&
 +           (chbind_req->chbind_req_pkt != NULL));
 +  if (chbind_req->chbind_req_len < 4)
-                         return PW_AUTHENTICATION_ACK;
++    return PW_CODE_AUTHENTICATION_REJECT;  /* Is this the right response? */
 +
 +  /* Set-up NULL response for cases where channel bindings can't be processed */
 +  chbind_req->chbind_resp = NULL;
 +  chbind_req->chbind_resp_len = 0;
 +
 +  /* Set-up the fake request */
 +  fake = request_alloc_fake(req);
 +  rad_assert(fake->packet->vps == NULL);
 +  pairmake(fake, &fake->packet->vps, "Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
 +  
 +  /* Add the username to the fake request */
 +  if (chbind_req->username) {
 +    uint8_t *octets = NULL;
 +    vp = paircreate(fake, PW_USER_NAME, 0);
 +    rad_assert(vp);
 +    octets = talloc_array(vp, uint8_t, chbind_req->username_len+1);
 +    rad_assert(octets);
 +    memcpy(octets, chbind_req->username, chbind_req->username_len);
 +    vp->vp_octets = octets;
 +    vp->length = chbind_req->username_len;
 +
 +    pairadd(&fake->packet->vps, vp);
 +    fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
 +  }
 +
 +  /* Copy the request state into the fake request */
 +  /*xxx vp = paircopy(req->state);
 +  if (vp)
 +  pairadd(&fake->packet->vps, vp);*/
 +
 +  /* Add the channel binding attributes to the fake packet */
 +  if (0 != (datalen = chbind_get_data((CHBIND_PACKET_T *)chbind_req->chbind_req_pkt, 
 +                                    chbind_req->chbind_req_len, 
 +                                    CHBIND_NSID_RADIUS, &attr_data))) {
 +        while(datalen > 0) {
 +                int mylen = rad_attr2vp(NULL, NULL, NULL, attr_data, datalen, &vp);
 +                if (mylen <= 0) {
 +                        /* If radaddr2vp fails, return NULL string for 
 +                           channel binding response */
 +                        request_free(&fake);
-   rcode = rad_authenticate(fake);
++                        return PW_CODE_AUTHENTICATION_ACK;
 +                }
 +                /* TODO: need to account for the possibility of rad_attr2vp generating 
 +                   multiple vps */
 +                if (vp)
 +                        pairadd(&fake->packet->vps, vp);
 +                attr_data += mylen;
 +                datalen -= mylen;
 +        }
 +  }
 +
 +  /* Set virtual server based on configuration for channel bindings,
 +     this is hard-coded to "chbind" for now */
 +  fake->server = "chbind";
 +
 +  /* Call rad_authenticate */
 +  if ((debug_flag > 0) && fr_log_fp) {
 +        DEBUG("prcoessing chbind request");
 +
 +        debug_pair_list(fake->packet->vps);
 +
 +        fprintf(fr_log_fp, "server %s {\n",
 +          (fake->server == NULL) ? "" : fake->server);
 +  }
-       rcode = PW_AUTHENTICATION_ACK;
++  rcode = rad_virtual_server(fake);
 +
 +  switch(rcode) {
 +    /* If rad_authenticate succeeded, build a reply */
 +  case RLM_MODULE_OK:
 +  case RLM_MODULE_HANDLED:
 +    if ((chbind_req->chbind_resp = chbind_build_response(fake, &chbind_req->chbind_resp_len)) != NULL)
-       rcode = PW_AUTHENTICATION_REJECT;
++      rcode = PW_CODE_AUTHENTICATION_ACK;
 +    else
-     rcode = PW_AUTHENTICATION_REJECT;
++      rcode = PW_CODE_AUTHENTICATION_REJECT;
 +    break;
 +  
 +  /* If we got any other response from rad_authenticate, it maps to a reject */
 +  default:
++    rcode = PW_CODE_AUTHENTICATION_REJECT;
 +    break;
 +  }
 +
 +  request_free(&fake);
 +
 +  return rcode;
 +}
 +
 +/*
 + * Parse channel binding packet to obtain data for a specific NSID.
 + * See http://tools.ietf.org/html/draft-ietf-emu-chbind-13#section-5.3.2:
 + */ 
 +
 +size_t chbind_get_data(CHBIND_PACKET_T *chbind_packet,
 +                         size_t chbind_packet_len,
 +                         int desired_nsid,
 +                         uint8_t **radbuf_data)
 +{
 +  size_t chbind_data_len = chbind_packet_len-1;
 +  size_t pos=0;
 +  if (chbind_packet->code != CHBIND_CODE_REQUEST)
 +    return 0;
 +  while (pos + 3 < chbind_data_len) {
 +    size_t len = (chbind_packet->data[pos] << 8) + 
 +      chbind_packet->data[pos + 1];
 +    uint8_t nsid = chbind_packet->data[pos + 2];
 +    if (pos + 3 > chbind_data_len + len) {
 +      /* malformed packet; warn here */
 +      return 0;
 +    }
 +    if (nsid == desired_nsid) {
 +      *radbuf_data = &chbind_packet->data[pos+3];
 +      return len;
 +    }
 +    pos += 3 + len;
 +  }
 +  /* didn't find any data matching nsid */
 +  if (pos != chbind_data_len) {
 +    /* warn about malformed packet */
 +  }
 +
 +  return 0;
 +}
 +
 +uint8_t *chbind_build_response(REQUEST *req, size_t *resp_len)
 +{
 +  uint8_t *resp;
 +  uint16_t pos, len = 0;
 +  VALUE_PAIR *vp = NULL;
 +
 +  *resp_len = 0;
 +  resp = malloc(MAX_PACKET_LEN + 4);
 +  rad_assert(resp);
 +
 +  /* Set-up the chbind header fields (except length, computed later) */
 +  vp = pairfind(req->config_items, PW_CHBIND_RESPONSE_CODE, 0, TAG_ANY);
 +  if (vp)
 +    resp[0] = vp->vp_integer;
 +  else resp[0] = 3; /*failure*/
 +  
 +
 +  resp[3] = CHBIND_NSID_RADIUS;
 +
 +  if ((debug_flag > 0) && fr_log_fp) {
 +        DEBUG("Sending chbind response: code %i\n", (int )(resp[0]));
 +        debug_pair_list(req->reply->vps);
 +        DEBUG("end chbind response\n");
 +  }
 +  /* Encode the chbind attributes into the response */
 +  for (vp = req->reply->vps, pos = 4; 
 +       (vp != NULL) && (pos < MAX_PACKET_LEN + 4); 
 +       pos += len) {
 +    len = rad_vp2attr(NULL, NULL, NULL, (const VALUE_PAIR **) &vp, &resp[pos], (MAX_PACKET_LEN + 4) - pos);
 +  }
 +
 +  len = pos-4; /*length covers ns-specific only*/
 +  /* Write the length field into the header */
 +  resp[1] = (uint8_t)(len >> 8);
 +  resp[2] = (uint8_t)(len & 0x00FF);
 +  
 +  /* Output the length of the entire response (attrs + header) */
 +  /* If there are no attributes, only send the code*/
 +  if (req->reply->vps)
 +    *resp_len = len + 4;
 +  else *resp_len = 1;
 +  return resp;
 +}
  RCSID("$Id$")
  
  #include "eap_ttls.h"
 +#include "eap_chbind.h"
  
  /*
-  *    0                  1               2               3
+  *    0                   1                   2                   3
   *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *   |                           AVP Code                         |
+  *   |                           AVP Code                            |
   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *   |V M r r r r r r|                  AVP Length               |
+  *   |V M r r r r r r|                  AVP Length                   |
   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *   |                        Vendor-ID (opt)                 |
+  *   |                        Vendor-ID (opt)                        |
   *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   *   |    Data ...
   *   +-+-+-+-+-+-+-+-+
@@@ -952,11 -920,7 +947,9 @@@ int eapttls_process(eap_handler_t *hand
        uint8_t const *data;
        size_t data_len;
        REQUEST *request = handler->request;
 +      eap_chbind_packet_t *chbind_packet;
 +      size_t chbind_len;
  
-       rad_assert(request != NULL);
        /*
         *      Just look at the buffer directly, without doing
         *      record_minus.
        }
  
        /*
-               if (chbind_rcode != PW_AUTHENTICATION_ACK)
 +       *      Process channel binding here.
 +       */
 +      chbind_len = eap_chbind_vp2packet(fake->packet->vps, &chbind_packet);
 +      if (chbind_len > 0) {
 +              int chbind_rcode;
 +              CHBIND_REQ *req = chbind_allocate();
 +
 +              RDEBUG("received chbind request");
 +              req->chbind_req_pkt = (uint8_t *)chbind_packet;
 +              req->chbind_req_len = chbind_len;
 +              if (fake->username) {
 +                      req->username = fake->username->vp_octets;
 +                      req->username_len = fake->username->length;
 +              } else {
 +                      req->username = NULL;
 +                      req->username_len = 0;
 +              }
 +              chbind_rcode = chbind_process(request, req);
 +
 +              /* free the chbind packet; we're done with it */
 +              free(chbind_packet);
 +
 +              /* encapsulate response here */
 +              if (req->chbind_resp_len > 0) {
 +                      RDEBUG("sending chbind response");
 +                      pairadd(&fake->reply->vps,
 +                              eap_chbind_packet2vp(fake, (eap_chbind_packet_t *)req->chbind_resp,
 +                                                    req->chbind_resp_len));
 +              } else {
 +                      RDEBUG("no chbind response");
 +              }
 +
 +              /* clean up chbind req */
 +              chbind_free(req);
 +
++              if (chbind_rcode != PW_CODE_AUTHENTICATION_ACK)
 +                      return chbind_rcode;
 +      }
 +
 +      /*
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */
@@@ -31,37 -29,18 +31,32 @@@ RCSID("$Id$"
  #define  REALM_FORMAT_SUFFIX   1
  
  typedef struct realm_config_t {
-   int         format;
-   char                *formatstring;
-   char                *delim;
-   bool                ignore_default;
-   bool                ignore_null;
-   char                *default_community;
-   char                *rp_realm;
-   char                *trust_router;
-   unsigned int        tr_port;
+       int             format;
+       char const      *format_string;
+       char const      *delim;
+       bool            ignore_default;
+       bool            ignore_null;
++      char            const *default_community;
++      char            const *rp_realm;
++      char const              *trust_router;
++      unsigned int    tr_port;
  } realm_config_t;
  
 +#define stringify(s) #s
 +
  static CONF_PARSER module_config[] = {
-   { "format", PW_TYPE_STRING_PTR,
-     offsetof(realm_config_t,formatstring), NULL, "suffix" },
-   { "delimiter", PW_TYPE_STRING_PTR,
-     offsetof(realm_config_t,delim), NULL, "@" },
-   { "ignore_default", PW_TYPE_BOOLEAN,
-     offsetof(realm_config_t,ignore_default), NULL, "no" },
-   { "ignore_null", PW_TYPE_BOOLEAN,
-     offsetof(realm_config_t,ignore_null), NULL, "no" },
-   { "default_community", PW_TYPE_STRING_PTR,
-     offsetof(realm_config_t,default_community), NULL, "none" },
-   { "rp_realm", PW_TYPE_STRING_PTR,
-     offsetof(realm_config_t,rp_realm), NULL, "none" },
-   { "trust_router", PW_TYPE_STRING_PTR,
-     offsetof(realm_config_t,trust_router), NULL, "none" },
-   { "tr_port", PW_TYPE_INTEGER,
-     offsetof(realm_config_t,tr_port), NULL, "0" },
-   //    offsetof(realm_config_t,tr_port), NULL, (stringify(TID_PORT)) },
+   { "format", FR_CONF_OFFSET(PW_TYPE_STRING, realm_config_t, format_string), "suffix" },
+   { "delimiter", FR_CONF_OFFSET(PW_TYPE_STRING, realm_config_t, delim), "@" },
+   { "ignore_default", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, realm_config_t, ignore_default), "no" },
+   { "ignore_null", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, realm_config_t, ignore_null), "no" },
++{ "default_community", FR_CONF_OFFSET(PW_TYPE_STRING,
++    realm_config_t,default_community),  "none" },
++{ "rp_realm", FR_CONF_OFFSET(PW_TYPE_STRING,
++    realm_config_t,rp_realm),  "none" },
++{ "trust_router", FR_CONF_OFFSET(PW_TYPE_STRING,
++    realm_config_t,trust_router),  "none" },
++{ "tr_port", FR_CONF_OFFSET(PW_TYPE_INTEGER,
++    realm_config_t,tr_port),  "0" },
    { NULL, -1, 0, NULL, NULL }    /* end the list */
  };
  
@@@ -352,14 -329,10 +347,13 @@@ static int mod_instantiate(CONF_SECTIO
  {
        struct realm_config_t *inst = instance;
  
-       if (strcasecmp(inst->formatstring, "suffix") == 0) {
 +      /* initialize the trust router integration code */
 +      if (tr_init() < 0)
 +             return -1;
+       if (strcasecmp(inst->format_string, "suffix") == 0) {
             inst->format = REALM_FORMAT_SUFFIX;
  
-       } else if (strcasecmp(inst->formatstring, "prefix") == 0) {
+       } else if (strcasecmp(inst->format_string, "prefix") == 0) {
             inst->format = REALM_FORMAT_PREFIX;
  
        } else {
@@@ -477,9 -450,8 +471,9 @@@ static rlm_rcode_t mod_realm_recv_coa(U
        realm = realm_find(vp->vp_strvalue + 1);
        if (!realm) return RLM_MODULE_NOTFOUND;
  
 +
        if (!realm->coa_pool) {
-               RDEBUG2("CoA realm is LOCAL.");
+               RDEBUG2("CoA realm is LOCAL");
                return RLM_MODULE_OK;
        }
  
index 5d9626e,0000000..83b37b6
mode 100644,000000..100644
--- /dev/null
@@@ -1,233 -1,0 +1,231 @@@
-                                           home_server *hs,
 +#include <trust_router/tid.h>
 +#include <freeradius-devel/radiusd.h>
 +#include <freeradius-devel/modules.h>
 +#include "trustrouter_integ.h"
 +#include <trust_router/tr_dh.h>
 +#include <freeradius-devel/realms.h>
 +
 +static TIDC_INSTANCE *global_tidc = NULL;
 +
 +
 +struct resp_opaque {
 +  REALM *output_realm;
 +  TID_RC result;
 +  char err_msg[1024];
 +};
 +
 +
 +int tr_init(void) 
 +{
 +  if (NULL == (global_tidc = tidc_create())) {
 +    fprintf(stderr, "tr_init: Error creating global TIDC instance.\n");
 +    return -1;
 +  }
 +  if (NULL == (global_tidc->client_dh = tr_create_dh_params(NULL, 0))) {
 +    fprintf(stderr, "tr_init: Error creating client DH params.\n");
 +    return 1;
 +  }
 +  return 0;
 +}
 +
 +static fr_tls_server_conf_t *construct_tls( TIDC_INSTANCE *inst,
-   home_server *hs = NULL;
++                                          home_server_t *hs,
 +                                          TID_SRVR_BLK *server)
 +{
 +  fr_tls_server_conf_t *tls = talloc_zero( hs, fr_tls_server_conf_t);
 +  unsigned char *key_buf = NULL;
 +  ssize_t keylen;
 +  char *hexbuf = NULL;
 +  int i;
 +
 +  if (tls == NULL)
 +    goto error;
 +  keylen = tr_compute_dh_key(&key_buf, server->aaa_server_dh->pub_key,
 +                           inst->client_dh);
 +  if (keylen <= 0) {
 +    DEBUG2("DH error");
 +    goto error;
 +  }
 +  hexbuf = rad_malloc(keylen*2 + 1);
 +  if (hexbuf == NULL)
 +    goto error;
 +  tr_bin_to_hex(key_buf, keylen, hexbuf,
 +           2*keylen + 1);
 +  tls->psk_password = hexbuf;
 +  tls->psk_identity = tr_name_strdup(server->key_name);
 +
 +  fprintf (stderr, "construct_tls: Client key generated (key name = %s):\n", tls->psk_identity);
 +  for (i = 0; i < keylen; i++) {
 +    printf("%.2x", key_buf[i]); 
 +  }
 +  printf("\n");
 +
 +  tls->cipher_list = strdup("PSK");
 +  tls->fragment_size = 4200;
 +  tls->ctx = tls_init_ctx(tls, 1);
 +  if (tls->ctx == NULL)
 +    goto error;
 +  memset(key_buf, 0, keylen);
 +  free(key_buf);
 +    return tls;
 + error:
 +    if (key_buf) {
 +      memset(key_buf, 0, keylen);
 +      free(key_buf);
 +    }
 +    if (hexbuf) {
 +      memset(hexbuf, 0, keylen*2);
 +      free(hexbuf);
 +    }
 +    if (tls)
 +      talloc_free(tls);
 +    return NULL;
 +}
 +  
 +static void tr_response_func( TIDC_INSTANCE *inst,
 +                           UNUSED TID_REQ *req, TID_RESP *resp,
 +                           void *cookie)
 +{
-     pool = rad_malloc(sizeof(*pool) + num_servers *sizeof(home_server *));
++  home_server_t *hs = NULL;
 +  TID_SRVR_BLK *server;
 +  home_pool_t *pool = NULL;
 +  REALM *nr = NULL;
 +  char home_pool_name[256];
 +  int pool_added = 0;
 +  fr_ipaddr_t home_server_ip;
 +  struct resp_opaque  *opaque = (struct resp_opaque *) cookie;
 +  size_t num_servers = 0;
 +
 +  /*xxx There's a race if this is called in two threads for the
 +    same realm. Imagine if the home pool is not found in either
 +    thread, is inserted in one thread and then the second
 +    thread's insert fails. The second thread will fail. Probably
 +    not a huge deal because a retransmit will make the world
 +    great again.*/
 +  if (resp->result != TID_SUCCESS) {
 +    size_t err_msg_len;
 +    opaque->result = resp->result;
 +    memset(opaque->err_msg, 0, sizeof(opaque->err_msg));
 +    if (resp->err_msg) {
 +      err_msg_len = resp->err_msg->len+1;
 +      if (err_msg_len > sizeof(opaque->err_msg))
 +      err_msg_len = sizeof(opaque->err_msg);
 +      strlcpy(opaque->err_msg, resp->err_msg->buf, err_msg_len);
 +    }
 +    return;
 +  }
 +  server = resp->servers;
 +  while (server) {
 +    num_servers++;
 +    server = server->next;
 +  }
 +  strlcpy(home_pool_name, "hp-", sizeof(home_pool_name));
 +  tr_name_strlcat(home_pool_name, resp->realm, sizeof(home_pool_name));
 +  pool = home_pool_byname(home_pool_name, HOME_TYPE_AUTH);
 +  if (pool == NULL) {
 +    size_t i = 0;
-     memset(pool, 0, sizeof(*pool));
++    pool = talloc_zero_size(NULL, sizeof(*pool) + num_servers *sizeof(home_server_t *));
 +                
 +    if (pool == NULL) goto error;
-       hs = talloc_zero(NULL, home_server);
 +    pool->type = HOME_POOL_CLIENT_PORT_BALANCE;
 +    pool->server_type = HOME_TYPE_AUTH;
 +    pool->name = strdup(home_pool_name);
 +    if (pool->name == NULL) goto error;
 +    pool->num_home_servers = num_servers;
 +
 +    server = resp->servers;
 +    while (server) {
 +      home_server_ip.af = AF_INET;
 +      home_server_ip.scope = 0;
 +      home_server_ip.ipaddr.ip4addr = server->aaa_server_addr;
 +        
 +      hs = home_server_find( &home_server_ip, 2083,
 +                           IPPROTO_TCP);
 +      if (hs) {
 +      DEBUG2("Found existing home_server %s", hs->name);
 +      } else {
 +      char nametemp[INET_ADDRSTRLEN];
 +      inet_ntop(home_server_ip.af, &home_server_ip.ipaddr, nametemp, sizeof(nametemp));
-       memset(hs, 0, sizeof(*hs));
++      hs = talloc_zero(pool, home_server_t);
 +      if (!hs) return;
 +      hs->type = HOME_TYPE_AUTH;
 +      hs->ipaddr = home_server_ip;
 +        hs->src_ipaddr.af = home_server_ip.af;
 +      hs->name = strdup(nametemp);
 +      hs->hostname = strdup(nametemp);
 +        hs->port = 2083;
 +      hs->proto = IPPROTO_TCP;
 +      hs->secret = strdup("radsec");
 +      hs->tls = construct_tls(inst, hs, server);
 +      if (hs->tls == NULL) goto error;
 +      if (!realms_home_server_add(hs, NULL, 0))
 +        goto error;
 +      }
 +      pool->servers[i++] = hs;
 +      hs = NULL;
 +      server = server->next;
 +    }
 +                      
 +    if (!realms_pool_add(pool, NULL)) goto error;
 +    pool_added = 1;
 +  }
 +              
 +  nr = rad_malloc(sizeof (REALM));
 +  if (nr == NULL) goto error;
 +  memset(nr, 0, sizeof(REALM));
 +  nr->name = tr_name_strdup(resp->realm);
 +  nr->auth_pool = pool;
 +  if (!realms_realm_add(nr, NULL)) goto error;
 +  opaque->output_realm = nr;
 +              
 +              
 +  return;
 +              
 + error:
 +  if (hs)
 +    free(hs);
 +  if (pool && (!pool_added)) {
 +    if (pool->name)
 +      free((char *) pool->name);
 +    free(pool);
 +  }
 +  if (nr)
 +    free(nr);
 +  return;
 +}
 +              
 +
 +REALM *tr_query_realm(const char *q_realm,
 +                    const char  *q_community,
 +                    const char *q_rprealm,
 +                    const char *q_trustrouter,
 +                    unsigned int q_trport)
 +{
 +  int conn = 0;
 +  int rc;
 +  gss_ctx_id_t gssctx;
 +  struct resp_opaque *cookie;
 +
 +  /* clear the cookie structure */
 +  cookie = malloc(sizeof(struct resp_opaque));
 +  memset (cookie, 0, sizeof(struct resp_opaque));
 +
 +  /* Set-up TID connection */
 +  printf("Openning TIDC connection to %s:%u", q_trustrouter, q_trport);
 +  if (-1 == (conn = tidc_open_connection(global_tidc, (char *)q_trustrouter, q_trport, &gssctx))) {
 +    /* Handle error */
 +    printf("Error in tidc_open_connection.\n");
 +    return NULL;
 +  };
 +
 +  /* Send a TID request */
 +  if (0 > (rc = tidc_send_request(global_tidc, conn, gssctx, (char *)q_rprealm, 
 +                                (char *) q_realm, (char *)q_community, 
 +                                &tr_response_func, cookie))) {
 +    /* Handle error */
 +    printf("Error in tidc_send_request, rc = %d.\n", rc);
 +    return NULL;
 +  }
 +
 +  return cookie->output_realm;
 +}