int make_send_message(struct sip_msg* msg, int index, VALUE_PAIR **send) { pv_value_t pt; map_list *mp = sets[index]->parsed; for (; mp; mp = mp->next) { pv_get_spec_value(msg, mp->pv, &pt); if (pt.flags & PV_VAL_INT) { //LM_DBG("%.*s---->%d---->%d---->%d\n",mp->name.len, mp->name.s, // pt.ri, mp->value, pt.flags); if (!rc_avpair_add(rh, send, ATTRID(mp->value), &pt.ri, -1, VENDOR(mp->value))) return -1; } else if (pt.flags & PV_VAL_STR) { //LM_DBG("%.*s----->%.*s---->%d---->%d---->%d\n",mp->name.len, // mp->name.s, pt.rs.len, pt.rs.s, mp->value, pt.flags, pt.rs.len); if (rc_dict_getattr(rh,mp->value)->type == PW_TYPE_IPADDR) { uint32_t ipaddr=rc_get_ipaddr(pt.rs.s); if (!rc_avpair_add(rh, send, ATTRID(mp->value), &ipaddr, -1, VENDOR(mp->value))) return -1; } else { if (!rc_avpair_add(rh, send, ATTRID(mp->value), pt.rs.s, pt.rs.len, VENDOR(mp->value))) return -1; } } } return 0; }
static int rc_is_myname(char *hostname) { struct in6_addr addr; struct in6_addr **paddr; struct hostent *hp; int res; //rc_log(LOG_NOTICE,"rc_is_myname(%s)", hostname); if (rc_good_ipaddr(hostname) == 0) { if (rc_get_ipaddr(hostname, &addr) == 0) { //rc_log(LOG_NOTICE,"rc_is_myname(%s) return false", hostname); return -1; } return rc_ipaddr_local(&addr); } if ((hp = rc_gethostbyname(hostname)) == NULL) return -1; for (paddr = (struct in6_addr**)hp->h_addr_list; *paddr; paddr++) { addr = **(struct in6_addr **)paddr; res = rc_ipaddr_local(&addr); if (res == 0 || res == -1) { //rc_log(LOG_NOTICE,"rc_is_myname(%s) return %d", hostname, res); return res; } } //rc_log(LOG_NOTICE,"rc_is_myname(%s) return 1", hostname); return 1; }
UINT4 rc_own_ipaddress(void) { static UINT4 this_host_ipaddr = 0; if (!this_host_ipaddr) { if ((this_host_ipaddr = rc_get_ipaddr (hostname)) == 0) { error("rc_own_ipaddress: couldn't get own IP address"); return 0; } } return this_host_ipaddr; }
static int find_match (struct in6_addr *ip_addr, char *hostname) { struct in6_addr addr; char **paddr; struct hostent *hp; //rc_log(LOG_NOTICE,"find_match(%x:%x:%x:%x:%x:%x:%x:%x/%s)\n", NIP6ADDR(ip_addr), hostname); if (rc_good_ipaddr (hostname) == 0) { if (rc_get_ipaddr(hostname, &addr) == 0) { //rc_log(LOG_NOTICE,"find_match %x:%x:%x:%x:%x:%x:%x:%x/%s Success@1\n", NIP6ADDR(ip_addr), hostname); return 0; } if (IN6_ARE_ADDR_EQUAL(ip_addr, &addr)) { //rc_log(LOG_NOTICE,"find_match %x:%x:%x:%x:%x:%x:%x:%x/%s Success@2\n", NIP6ADDR(ip_addr), hostname); return 0; } //rc_log(LOG_NOTICE,"find_match %x:%x:%x:%x:%x:%x:%x:%x/%s Failed@3\n", NIP6ADDR(ip_addr), hostname); return -1; } if ((hp = rc_gethostbyname(hostname)) == NULL) { //rc_log(LOG_NOTICE,"find_match %x:%x:%x:%x:%x:%x:%x:%x/%s Failed@4\n", NIP6ADDR(ip_addr), hostname); return -1; } for (paddr = hp->h_addr_list; *paddr; paddr++) { addr = ** (struct in6_addr **) paddr; //rc_log(LOG_NOTICE,"find_match Compare %x:%x:%x:%x:%x:%x:%x:%x/%x:%x:%x:%x:%x:%x:%x:%x\n", NIP6ADDR(ip_addr), NIP6ADDR(&addr)); if (IN6_ARE_ADDR_EQUAL(ip_addr, &addr)) { //rc_log(LOG_NOTICE,"find_match %x:%x:%x:%x:%x:%x:%x:%x/%s Success@5\n", NIP6ADDR(ip_addr), hostname); return 0; } } //rc_log(LOG_NOTICE,"find_match %x:%x:%x:%x:%x:%x:%x:%x/%s Failed@6\n", NIP6ADDR(ip_addr), hostname); return -1; }
int rc_find_server (char *server_name, UINT4 *ip_addr, char *secret) { UINT4 myipaddr = 0; int len; int result; FILE *clientfd; char *h; char *s; char *host2; char buffer[128]; char hostnm[AUTH_ID_LEN + 1]; /* Get the IP address of the authentication server */ if ((*ip_addr = rc_get_ipaddr (server_name)) == (UINT4) 0) return (-1); if ((clientfd = fopen (rc_conf_str("servers"), "r")) == (FILE *) NULL) { errorlog("rc_find_server: couldn't open file: %m: %s", rc_conf_str("servers")); return (-1); } myipaddr = rc_own_ipaddress(); result = 0; while (fgets (buffer, sizeof (buffer), clientfd) != (char *) NULL) { if (*buffer == '#') continue; if ((h = strtok (buffer, " \t\n")) == NULL) /* first hostname */ continue; memset (hostnm, '\0', AUTH_ID_LEN); len = strlen (h); if (len > AUTH_ID_LEN) { len = AUTH_ID_LEN; } strncpy (hostnm, h, (size_t) len); hostnm[AUTH_ID_LEN] = '\0'; if ((s = strtok (NULL, " \t\n")) == NULL) /* and secret field */ continue; memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (s); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, s, (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; if (!strchr (hostnm, '/')) /* If single name form */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } else /* <name1>/<name2> "paired" form */ { strtok (hostnm, "/"); if (find_match (&myipaddr, hostnm) == 0) { /* If we're the 1st name, target is 2nd */ host2 = strtok (NULL, " "); if (find_match (ip_addr, host2) == 0) { result++; break; } } else /* If we were 2nd name, target is 1st name */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } } } fclose (clientfd); if (result == 0) { memset (buffer, '\0', sizeof (buffer)); memset (secret, '\0', sizeof (secret)); errorlog("rc_find_server: couldn't find RADIUS server %s in %s", server_name, rc_conf_str("servers")); return (-1); } return 0; }
/* Radius implementation for the avp_add callback */ int rad_avp_add(aaa_conn* rh, aaa_message* message, aaa_map* name, void* value, int val_length, int vendor) { uint32_t int4_val; str s; if (!rh) { LM_ERR("invalid aaa connection argument\n"); return -1; } if (!message) { LM_ERR("invalid message argument\n"); return -1; } if (!name) { LM_ERR("invalid name argument\n"); return -1; } if (!value) { LM_ERR("invalid value argument\n"); return -1; } if (vendor) vendor = VENDOR(vendor); /* check if this might be a string, we might have to do some conversions */ if (val_length > -1) { if (name->type == PW_TYPE_IPADDR) { char ipstr[val_length + 1]; memcpy( ipstr, value, val_length); ipstr[val_length] = 0; int4_val = rc_get_ipaddr((char*)&ipstr); LM_DBG("detected TYPE_IPADDR attribute %s = %s (%u)\n", name->name, ipstr, (unsigned int)int4_val); value = (void *)&int4_val; val_length = -1; } else if (name->type == PW_TYPE_INTEGER) { LM_DBG("detected TYPE_INTEGER attribute %s = %s\n", name->name, (char*)value); s.s = (char*)value; s.len = val_length; if (str2int( &s, (unsigned int*)(void*)&int4_val) != 0 ) { LM_ERR("error converting string to integer"); return -1; } value = (void*)&int4_val; val_length = -1; } } if (rc_avpair_add (rh, (VALUE_PAIR**)(void*)&message->avpair, name->value, value, val_length, vendor)) { return 0; } LM_ERR("failure\n"); return -1; }
int rc_find_server (rc_handle *rh, const char *server_name, uint32_t *ip_addr, char *secret) { int i; size_t len; int result = 0; FILE *clientfd; char *h; char *s; char buffer[128]; char hostnm[AUTH_ID_LEN + 1]; char *buffer_save; char *hostnm_save; SERVER *authservers; SERVER *acctservers; /* Lookup the IP address of the radius server */ if ((*ip_addr = rc_get_ipaddr (server_name)) == (uint32_t) 0) return -1; /* Check to see if the server secret is defined in the rh config */ if( (authservers = rc_conf_srv(rh, "authserver")) != NULL ) { for( i = 0; i < authservers->max; i++ ) { if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) && (authservers->secret[i] != NULL) ) { memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (authservers->secret[i]); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, authservers->secret[i], (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; return 0; } } } if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL ) { for( i = 0; i < acctservers->max; i++ ) { if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) && (acctservers->secret[i] != NULL) ) { memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (acctservers->secret[i]); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, acctservers->secret[i], (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; return 0; } } } /* We didn't find it in the rh_config or the servername is too long so look for a * servers file to define the secret(s) */ if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL) { rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers")); return -1; } while (fgets (buffer, sizeof (buffer), clientfd) != NULL) { if (*buffer == '#') continue; if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */ continue; memset (hostnm, '\0', AUTH_ID_LEN); len = strlen (h); if (len > AUTH_ID_LEN) { len = AUTH_ID_LEN; } strncpy (hostnm, h, (size_t) len); hostnm[AUTH_ID_LEN] = '\0'; if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */ continue; memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (s); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, s, (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; if (!strchr (hostnm, '/')) /* If single name form */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } else /* <name1>/<name2> "paired" form */ { strtok_r(hostnm, "/", &hostnm_save); if (rc_is_myname(hostnm) == 0) { /* If we're the 1st name, target is 2nd */ if (find_match (ip_addr, hostnm_save) == 0) { result++; break; } } else /* If we were 2nd name, target is 1st name */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } } } fclose (clientfd); if (result == 0) { memset (buffer, '\0', sizeof (buffer)); memset (secret, '\0', sizeof (secret)); rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s", server_name, rc_conf_str(rh, "servers")); return -1; } return 0; }
int rc_avpair_parse (char *buffer, VALUE_PAIR **first_pair) { int mode; char attrstr[AUTH_ID_LEN]; char valstr[AUTH_ID_LEN]; DICT_ATTR *attr = NULL; DICT_VALUE *dval; VALUE_PAIR *pair; VALUE_PAIR *link; struct tm *tm; time_t timeval; mode = PARSE_MODE_NAME; while (*buffer != '\n' && *buffer != '\0') { if (*buffer == ' ' || *buffer == '\t') { buffer++; continue; } switch (mode) { case PARSE_MODE_NAME: /* Attribute Name */ rc_fieldcpy (attrstr, &buffer); if ((attr = rc_dict_findattr (attrstr)) == (DICT_ATTR *) NULL) { error("rc_avpair_parse: unknown attribute"); if (*first_pair) { rc_avpair_free(*first_pair); *first_pair = (VALUE_PAIR *) NULL; } return (-1); } mode = PARSE_MODE_EQUAL; break; case PARSE_MODE_EQUAL: /* Equal sign */ if (*buffer == '=') { mode = PARSE_MODE_VALUE; buffer++; } else { error("rc_avpair_parse: missing or misplaced equal sign"); if (*first_pair) { rc_avpair_free(*first_pair); *first_pair = (VALUE_PAIR *) NULL; } return (-1); } break; case PARSE_MODE_VALUE: /* Value */ rc_fieldcpy (valstr, &buffer); if ((pair = (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR))) == (VALUE_PAIR *) NULL) { novm("rc_avpair_parse"); if (*first_pair) { rc_avpair_free(*first_pair); *first_pair = (VALUE_PAIR *) NULL; } return (-1); } strcpy (pair->name, attr->name); pair->attribute = attr->value; pair->type = attr->type; pair->vendorcode = attr->vendorcode; switch (pair->type) { case PW_TYPE_STRING: strcpy ((char *)pair->strvalue, valstr); pair->lvalue = strlen(valstr); break; case PW_TYPE_INTEGER: if (isdigit (*valstr)) { pair->lvalue = atoi (valstr); } else { if ((dval = rc_dict_findval (valstr)) == (DICT_VALUE *) NULL) { error("rc_avpair_parse: unknown attribute value: %s", valstr); if (*first_pair) { rc_avpair_free(*first_pair); *first_pair = (VALUE_PAIR *) NULL; } free (pair); return (-1); } else { pair->lvalue = dval->value; } } break; case PW_TYPE_IPADDR: pair->lvalue = rc_get_ipaddr(valstr); break; case PW_TYPE_DATE: timeval = time (0); tm = localtime (&timeval); tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; rc_str2tm (valstr, tm); #ifdef TIMELOCAL pair->lvalue = (UINT4) timelocal (tm); #else /* TIMELOCAL */ pair->lvalue = (UINT4) mktime (tm); #endif /* TIMELOCAL */ break; default: error("rc_avpair_parse: unknown attribute type %d", pair->type); if (*first_pair) { rc_avpair_free(*first_pair); *first_pair = (VALUE_PAIR *) NULL; } free (pair); return (-1); } pair->next = (VALUE_PAIR *) NULL; if (*first_pair == (VALUE_PAIR *) NULL) { *first_pair = pair; } else { link = *first_pair; while (link->next != (VALUE_PAIR *) NULL) { link = link->next; } link->next = pair; } mode = PARSE_MODE_NAME; break; default: mode = PARSE_MODE_NAME; break; } } return (0); }
int radius_auth(switch_channel_t *channel, char* called_number, char* username, char* password , char* auth_result/*, char* biling_model, char* credit_amount, char* currency, char* preffered_lang*/) { int result = OK_RC; VALUE_PAIR *send = NULL; VALUE_PAIR *received = NULL; VALUE_PAIR *service_vp; DICT_ATTR *pda; CONFIG_VSAS* PCONFIGVSAS = NULL; char *default_realm = NULL; rc_handle *rh = NULL; int attrid =0; char msg[STR_LENGTH * 10 + 1]; char username_realm[STR_LENGTH + 1]; char value[STR_LENGTH + 1]; int integer; memset(msg, 0, STR_LENGTH * 10); memset(username_realm, 0, STR_LENGTH); send = NULL; do { #if EMBENDED_CONFIG CONFIG_CLIENT* PCONFIGCLIENT = CONFIGCLIENT; rh = rc_new(); if (rh == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Failed to allocate initial structure.\n"); result = ERROR_RC; break; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "allocate initial structure.\n"); /* Initialize the config structure */ rh = rc_config_init(rh); if (rh == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,"ERROR: Failed to initialze configuration.\n"); result = ERROR_RC; break; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"initialzed configuration.\n"); while(PCONFIGCLIENT) { //if (rc_add_config(rh, "auth_order", "radius", "config", 0) != 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "set %s := %s.\n", PCONFIGCLIENT->name, PCONFIGCLIENT->value); if (rc_add_config(rh, PCONFIGCLIENT->name, PCONFIGCLIENT->value, "config", 0) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Unable to set %s := %s.\n", PCONFIGCLIENT->name, PCONFIGCLIENT->value); result = ERROR_RC; break; } PCONFIGCLIENT = PCONFIGCLIENT->pNext; } if (result == ERROR_RC) break; #else if ((rh = rc_read_config(!rc_config_file ? RC_CONFIG_FILE : rc_config_file)) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error loading radius config file\n"); result = ERROR_RC; break; } #endif if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error loading radius dictionary\n"); result = ERROR_RC; break; } default_realm = rc_conf_str(rh, "default_realm"); if (default_realm == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "default_realm is null object.\n"); result = ERROR_RC; break; } strncpy(username_realm, username, sizeof(username_realm)); if ((strchr(username_realm, '@') == NULL) && default_realm && (*default_realm != '\0')) { strncat(username_realm, "@", sizeof(username_realm)-strlen(username_realm)-1); strncat(username_realm, default_realm, sizeof(username_realm)-strlen(username_realm)-1); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: User-Name: %s\n", username); if (rc_avpair_add(rh, &send, PW_USER_NAME, username_realm, -1, 0)== NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An Error occured during rc_avpair_add : username\n"); result = ERROR_RC; break; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: User-Password: %s\n", password); if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, password, -1, 0) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An Error occured during rc_avpair_add : password\n"); result = ERROR_RC; break; } if (!called_number || strcmp(called_number, "") == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: Called-station-Id is empty, ignoring...\n"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: Called-station-Id: %s\n", called_number); if (rc_avpair_add(rh, &send, 30, called_number, -1, 0) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An Error occured during rc_avpair_add : Called-station-Id\n"); result = ERROR_RC; break; } } PCONFIGVSAS = CONFIGVSAS; while(PCONFIGVSAS) { if (PCONFIGVSAS->direction == 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Handle attribute: %s\n", PCONFIGVSAS->name ); memset(value, 0, STR_LENGTH); GetValue(channel, PCONFIGVSAS, value); if (PCONFIGVSAS->pec != 0) attrid = PCONFIGVSAS->id | (PCONFIGVSAS->pec << 16); else attrid = PCONFIGVSAS->id ; pda = rc_dict_getattr(rh, attrid); if (pda == NULL) { result = ERROR_RC; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute: key:%s, not found in dictionary\n", PCONFIGVSAS->name); break; } if (PCONFIGVSAS->pec != 0 && rc_dict_getvend(rh, PCONFIGVSAS->pec) == NULL) { result = ERROR_RC; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown vendor specific id: key:%s, id:%dnot found in dictionary\n", PCONFIGVSAS->name, PCONFIGVSAS->pec); break; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... dictionary data: id:%d, vendor id:%d, attr type:%d, attr name:%s (%d)\n", PCONFIGVSAS->id, PCONFIGVSAS->pec, pda->type, pda->name, attrid); switch(pda->type) { case PW_TYPE_STRING: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: key:%s, value:%s (%s) as string\n", PCONFIGVSAS->name, PCONFIGVSAS->value, value); if (rc_avpair_add(rh, &send, PCONFIGVSAS->id, value, -1, PCONFIGVSAS->pec) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An Error occured during rc_avpair_add : %s\n", PCONFIGVSAS->name); result = ERROR_RC; break; } break; //case PW_TYPE_DATE: case PW_TYPE_INTEGER: integer = atoi(value); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: key:%s, value:%s (%d) as integer\n", PCONFIGVSAS->name, PCONFIGVSAS->value, integer); if (rc_avpair_add(rh, &send, PCONFIGVSAS->id, &integer, -1, PCONFIGVSAS->pec) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An Error occured during rc_avpair_add : %s\n", PCONFIGVSAS->name); result = ERROR_RC; break; } break; case PW_TYPE_IPADDR: integer = rc_get_ipaddr(value); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "... radius: key:%s, value:%s (%d) as ipaddr\n", PCONFIGVSAS->name, PCONFIGVSAS->value, integer); if (rc_avpair_add(rh, &send, PCONFIGVSAS->id, &integer, -1, PCONFIGVSAS->pec) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An Error occured during rc_avpair_add : %s\n", PCONFIGVSAS->name); result = ERROR_RC; break; } break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute type: key:%s, type %d\n", PCONFIGVSAS->name, pda->type); break; } } PCONFIGVSAS = PCONFIGVSAS->pNext; } if (result != ERROR_RC) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sending radius packet ...\n" ); result = rc_auth(rh, 0, send, &received, msg); if (result == OK_RC) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RADIUS Authentication OK\n"); strcpy(auth_result, "OK"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, " RADIUS Authentication failure (RC=%d)\n", result); strcpy(auth_result, "NOK"); } PCONFIGVSAS = CONFIGVSAS; while(PCONFIGVSAS) { if (PCONFIGVSAS->direction == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Handle attribute: %s\n", PCONFIGVSAS->name ); if ((service_vp = rc_avpair_get(received, PCONFIGVSAS->id, PCONFIGVSAS->pec)) != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\tattribute (%s) found in radius packet\n", PCONFIGVSAS->name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\tset variable %s := %s\n", PCONFIGVSAS->value, service_vp->strvalue); switch_channel_set_variable(channel, PCONFIGVSAS->value, service_vp->strvalue); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\tNo found out attribute id: %d, pec:%d, (%s)\n", PCONFIGVSAS->id, PCONFIGVSAS->pec, PCONFIGVSAS->name ); } } PCONFIGVSAS = PCONFIGVSAS->pNext; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "abort sending radius packet.\n" ); break; } } while(1 == 0); if (result == ERROR_RC) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An error occured during RADIUS Authentication(RC=%d)\n", result); } free_radius_auth_value_pair(send, received, rh); return result; }
int rc_send_server (rc_handle *rh, SEND_DATA *data, char *msg) { int sockfd; struct sockaddr_in sinlocal; struct sockaddr_in sinremote; AUTH_HDR *auth, *recv_auth; uint32_t auth_ipaddr, nas_ipaddr; char *server_name; /* Name of server to query */ socklen_t salen; int result = 0; int total_length; int length; int retry_max; size_t secretlen; char secret[MAX_SECRET_LENGTH + 1]; unsigned char vector[AUTH_VECTOR_LEN]; char recv_buffer[BUFFER_LEN]; char send_buffer[BUFFER_LEN]; int retries; VALUE_PAIR *vp; struct pollfd pfd; double start_time, timeout; server_name = data->server; if (server_name == NULL || server_name[0] == '\0') return ERROR_RC; if ((vp = rc_avpair_get(data->send_pairs, PW_SERVICE_TYPE, 0)) && \ (vp->lvalue == PW_ADMINISTRATIVE)) { strcpy(secret, MGMT_POLL_SECRET); if ((auth_ipaddr = rc_get_ipaddr(server_name)) == 0) return ERROR_RC; } else { if(data->secret != NULL) { strncpy(secret, data->secret, MAX_SECRET_LENGTH); } /* else { */ if (rc_find_server (rh, server_name, &auth_ipaddr, secret) != 0) { rc_log(LOG_ERR, "rc_send_server: unable to find server: %s", server_name); return ERROR_RC; } /*}*/ } DEBUG(LOG_ERR, "DEBUG: rc_send_server: creating socket to: %s", server_name); sockfd = socket (AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { memset (secret, '\0', sizeof (secret)); rc_log(LOG_ERR, "rc_send_server: socket: %s", strerror(errno)); return ERROR_RC; } memset((char *)&sinlocal, '\0', sizeof(sinlocal)); sinlocal.sin_family = AF_INET; sinlocal.sin_addr.s_addr = htonl(rc_own_bind_ipaddress(rh)); sinlocal.sin_port = htons((unsigned short) 0); if (bind(sockfd, SA(&sinlocal), sizeof(sinlocal)) < 0) { close (sockfd); memset (secret, '\0', sizeof (secret)); rc_log(LOG_ERR, "rc_send_server: bind: %s: %s", server_name, strerror(errno)); return ERROR_RC; } retry_max = data->retries; /* Max. numbers to try for reply */ retries = 0; /* Init retry cnt for blocking call */ memset ((char *)&sinremote, '\0', sizeof(sinremote)); sinremote.sin_family = AF_INET; sinremote.sin_addr.s_addr = htonl (auth_ipaddr); sinremote.sin_port = htons ((unsigned short) data->svc_port); /* * Fill in NAS-IP-Address (if needed) */ if (rc_avpair_get(data->send_pairs, PW_NAS_IP_ADDRESS, 0) == NULL) { if (sinlocal.sin_addr.s_addr == htonl(INADDR_ANY)) { if (rc_get_srcaddr(SA(&sinlocal), SA(&sinremote)) != 0) { close (sockfd); memset (secret, '\0', sizeof (secret)); return ERROR_RC; } } nas_ipaddr = ntohl(sinlocal.sin_addr.s_addr); rc_avpair_add(rh, &(data->send_pairs), PW_NAS_IP_ADDRESS, &nas_ipaddr, 0, 0); } /* Build a request */ auth = (AUTH_HDR *) send_buffer; auth->code = data->code; auth->id = data->seq_nbr; if (data->code == PW_ACCOUNTING_REQUEST) { total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN; auth->length = htons ((unsigned short) total_length); memset((char *) auth->vector, 0, AUTH_VECTOR_LEN); secretlen = strlen (secret); memcpy ((char *) auth + total_length, secret, secretlen); rc_md5_calc (vector, (unsigned char *) auth, total_length + secretlen); memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); } else { rc_random_vector (vector); memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN; auth->length = htons ((unsigned short) total_length); } DEBUG(LOG_ERR, "DEBUG: local %s : 0, remote %s : %u\n", inet_ntoa(sinlocal.sin_addr), inet_ntoa(sinremote.sin_addr), data->svc_port); for (;;) { sendto (sockfd, (char *) auth, (unsigned int) total_length, (int) 0, SA(&sinremote), sizeof (struct sockaddr_in)); pfd.fd = sockfd; pfd.events = POLLIN; pfd.revents = 0; start_time = rc_getctime(); for (timeout = data->timeout; timeout > 0; timeout -= rc_getctime() - start_time) { result = poll(&pfd, 1, timeout * 1000); if (result != -1 || errno != EINTR) break; } if (result == -1) { rc_log(LOG_ERR, "rc_send_server: poll: %s", strerror(errno)); memset (secret, '\0', sizeof (secret)); close (sockfd); return ERROR_RC; } if (result == 1 && (pfd.revents & POLLIN) != 0) break; /* * Timed out waiting for response. Retry "retry_max" times * before giving up. If retry_max = 0, don't retry at all. */ if (retries++ >= retry_max) { rc_log(LOG_ERR, "rc_send_server: no reply from RADIUS server %s:%u, %s", rc_ip_hostname (auth_ipaddr), data->svc_port, inet_ntoa(sinremote.sin_addr)); close (sockfd); memset (secret, '\0', sizeof (secret)); return TIMEOUT_RC; } } salen = sizeof(sinremote); length = recvfrom (sockfd, (char *) recv_buffer, (int) sizeof (recv_buffer), (int) 0, SA(&sinremote), &salen); if (length <= 0) { rc_log(LOG_ERR, "rc_send_server: recvfrom: %s:%d: %s", server_name,\ data->svc_port, strerror(errno)); close (sockfd); memset (secret, '\0', sizeof (secret)); return ERROR_RC; } recv_auth = (AUTH_HDR *)recv_buffer; if (length < AUTH_HDR_LEN || length < ntohs(recv_auth->length)) { rc_log(LOG_ERR, "rc_send_server: recvfrom: %s:%d: reply is too short", server_name, data->svc_port); close(sockfd); memset(secret, '\0', sizeof(secret)); return ERROR_RC; } result = rc_check_reply (recv_auth, BUFFER_LEN, secret, vector, data->seq_nbr); length = ntohs(recv_auth->length) - AUTH_HDR_LEN; if (length > 0) { data->receive_pairs = rc_avpair_gen(rh, NULL, recv_auth->data, length, 0); } else { data->receive_pairs = NULL; } close (sockfd); memset (secret, '\0', sizeof (secret)); if (result != OK_RC) return result; *msg = '\0'; vp = data->receive_pairs; while (vp) { if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE, 0))) { strcat(msg, vp->strvalue); strcat(msg, "\n"); vp = vp->next; } } if ((recv_auth->code == PW_ACCESS_ACCEPT) || (recv_auth->code == PW_PASSWORD_ACK) || (recv_auth->code == PW_ACCOUNTING_RESPONSE)) { result = OK_RC; } else if ((recv_auth->code == PW_ACCESS_REJECT) || (recv_auth->code == PW_PASSWORD_REJECT)) { result = REJECT_RC; } else { result = BADRESP_RC; } return result; }