szgzwf

http://www.etsec.com.cn

导航

radius soure code

/*   The radiusAAA plugin is a GPL plugin for partysip.   Copyright (C) 2002  Aymeric MOIZARD - <jack@atosc.org>   Radius client code is taken from XTRADIUS - Cistron project.   Remix by Oleksandr Kapitanenko, Porta Software Ltd. - <kapitan@portaone.com>     The radiusAAA plugin is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.     The radiusAAA plugin is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.

  You should have received a copy of the GNU General Public License   along with Foobar; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#define _GNU_SOURCE /* needed for asprintf */

#include <partysip/partysip.h> #include "radiusAAA.h" #include <osip/smsg.h> #include <ppl/ppl_uinfo.h> #include <ppl/ppl_dns.h>

#ifdef HAVE_CTYPE_H #include <ctype.h> #endif

/* Radius client stuff */ char            *radius_dir = RADIUS_DIR; char            *radlog_dir = NULL; int             debug_flag = 0; int             sockfd;

int             i_send_buffer[2048]; int             i_recv_buffer[2048]; char            *send_buffer = (char *)i_send_buffer; char            *recv_buffer = (char *)i_recv_buffer; char            vector[AUTH_VECTOR_LEN];

struct  sockaddr_in     *sin; UINT4                   auth_ipaddr; #define MAXPWNAM        32 #define MAXPASS         16

static DICT_ATTR        *dictionary_attributes; static DICT_VALUE       *dictionary_values; static DICT_VENDOR      *dictionary_vendors;

static int              vendorno = 1;

#ifdef NOCASE #define DICT_STRCMP strcasecmp #else #define DICT_STRCMP strcmp #endif

radiusAAA_ctx_t *radiusAAA_context = NULL;

extern psp_plugin_t PPL_DECLARE_DATA radiusAAA_plugin;

/*  *      Find the pair with the mathing attribute  */ VALUE_PAIR * pairfind_by_name(VALUE_PAIR *first, char *name) {         while(first && strcmp(first->name,name) != 0 )                 first = first->next;         return first; }

/*  *      Release the memory used by a list of attribute-value  *      pairs.  */ void pairfree(VALUE_PAIR *pair) {         VALUE_PAIR      *next;            while(pair != NULL) {                 next = pair->next;                 free(pair);                 pair = next;         } }

/*  *      Free an AUTHREQ struct.  */ void authfree(AUTH_REQ *authreq) {         pairfree(authreq->request);         pairfree(authreq->proxy_pairs);         pairfree(authreq->server_reply);         memset(authreq, 0, sizeof(AUTH_REQ));         free(authreq); }

/*  *      Write a whole list of A/V pairs.  */ void print_attr_list(VALUE_PAIR *pair) {         while(pair) {                 print_attr_val(pair);                 pair = pair->next;         } }

/*  *      Write a printable version of the attribute-value pair  */ void print_attr_val(VALUE_PAIR *request) {         DICT_VALUE      *dict_valget();         DICT_VALUE      *dval;         char            buffer[32];         u_char          *ptr;  char            *sptr;         char            decoded[3257];  // buffer for decoding sublist: ~(256-2)/3 * (6+32)+1 + 32 +5         char            sub_attr_val[256];         int             sub_attr_code, sub_attr_length;

        strcpy(decoded,"");         switch(request->type) {

                        /* Sub attributes */                         case PW_TYPE_SUB_LIST:                                 ptr = (u_char *)request->strvalue;                                 sptr = (char *)decoded;                                 sptr += sprintf(sptr, "%s = \"", request->name);                                 while( *ptr != '\0' ) {                                    if( ptr != (u_char *)request->strvalue ) sptr += sprintf(sptr, "; ");                                    sub_attr_code = (int)*ptr;                                    sub_attr_length = (int)*(ptr+1);                                    strncpy( sub_attr_val, ptr+2, sub_attr_length-2);                                    *(sub_attr_val+sub_attr_length-2) = '\0';                                    dval = dict_valget( sub_attr_code, request->name);                                    if(dval != (DICT_VALUE *)NULL) {                                       sptr += sprintf(sptr, "%s = \"%s\"", dval->name, sub_attr_val);                                    } else {                                       sptr += sprintf(sptr, "Unknown-Sub-Attr-%d = \"%s\"", sub_attr_code, sub_attr_val);                                    }                                    ptr += sub_attr_length;                                 }                                 sptr += sprintf(sptr, "\"");                                        break;                         /* Cisco VoIP vsa support */                         case PW_TYPE_CISCO_AVPAIR:                                 ptr = (u_char *)request->strvalue;                                 if( (ptr=(u_char *)strchr((u_char *)request->strvalue,'=')) == NULL ) ptr = (u_char *)request->strvalue;                                 else ptr++;                                 sprintf(decoded,"%s = \"%s\"", request->name, ptr);                                 break;                         case PW_TYPE_STRING:                                 if( (request->attribute==0x40001 || request->attribute==0x30001) && (ptr=(u_char *)strchr((u_char *)request->strvalue,'='))!=NULL ) {                                         *ptr++='\0';                                         sprintf(decoded,"%s = \"%s\"", request->strvalue, ptr);                                         *--ptr='=';                                 } else                                         sprintf(decoded,"%s = \"%s\"", request->name, request->strvalue);                                 break;                         case PW_TYPE_INTEGER:                                 dval = dict_valget(request->lvalue, request->name);                                 if(dval != (DICT_VALUE *)NULL)                                         sprintf(decoded,"%s = \"%s\"", request->name, dval->name);                                 else                                         sprintf(decoded,"%s = \"%ld\"", request->name, (long)request->lvalue);                                 break;

                        case PW_TYPE_IPADDR:                                 ipaddr2str(buffer, request->lvalue);                                 sprintf(decoded,"%s = \"%s\"", request->name, buffer);                                 break;

                        case PW_TYPE_DATE:                                 strftime(buffer, sizeof(buffer), "%b %e %Y",                                         localtime((time_t *)&request->lvalue));                                 sprintf(decoded,"%s = \"%s\"", request->name, buffer);                                 break;                         default:                                 sprintf(decoded, "Unknown type %d", request->type);                                 break;         }         OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                     "radiusAAA plugin: Received attribute: %s\n", decoded)); }

/*  *      Like strncpy, but always adds \0  */ char *strNcpy(char *dest, char *src, int n) {         if (n > 0)                 strncpy(dest, src, n);         else                 n = 1;         dest[n - 1] = 0;

        return dest; }

/*  *      Return an IP address in host long notation from  *      one supplied in standard dot notation.  */ UINT4 ipstr2long(char *ip_str) {         char    buf[6];         char    *ptr;         int     i;         int     count;         UINT4   ipaddr;         int     cur_byte;           ipaddr = (UINT4)0;         for(i = 0;i < 4;i++) {                 ptr = buf;                 count = 0;                 *ptr = '\0';                 while(*ip_str != '.' && *ip_str != '\0' && count < 4) {                         if(!isdigit(*ip_str)) {                                 return((UINT4)0);                         }                           *ptr++ = *ip_str++;                         count++;                 }                 if(count >= 4 || count == 0) {                         return((UINT4)0);                 }                 *ptr = '\0';                 cur_byte = atoi(buf);                 if(cur_byte < 0 || cur_byte > 255) {                         return((UINT4)0);                 }                 ip_str++;                 ipaddr = ipaddr << 8 | (UINT4)cur_byte;         }         return(ipaddr); }

/*  *      Check for valid IP address in standard dot notation.  */ int good_ipaddr(char *addr) {          int     dot_count;         int     digit_count;                 dot_count = 0;         digit_count = 0;         while(*addr != '\0' && *addr != ' ') {                 if(*addr == '.') {                         dot_count++;                         digit_count = 0;                 }                 else if(!isdigit(*addr)) {                         dot_count = 5;                 }                 else {                         digit_count++;                         if(digit_count > 3) {                                 dot_count = 5;                         }                 }                 addr++;         }         if(dot_count != 3) {                 return(-1);         }         else {                 return(0);         } }

/*  *      Return an IP address in host long notation from a host  *      name or address in dot notation.        */ UINT4 get_ipaddr(char *host) {         struct hostent  *hp;         UINT4           ipstr2long();                 if(good_ipaddr(host) == 0) {                 return(ipstr2long(host));         }         else if((hp = gethostbyname(host)) == (struct hostent *)NULL) {                 return((UINT4)0);         }         return(ntohl(*(UINT4 *)hp->h_addr)); }

/*  *      Return an IP address in standard dot notation for the  *      provided address in host long notation.  */ void ipaddr2str(char *buffer, UINT4 ipaddr) {         int     addr_byte[4];         int     i;         UINT4   xbyte;           for(i = 0;i < 4;i++) {                 xbyte = ipaddr >> (i*8);                 xbyte = xbyte & (UINT4)0x000000FF;                 addr_byte[i] = xbyte;           }         sprintf(buffer, "%u.%u.%u.%u", addr_byte[3], addr_byte[2],                 addr_byte[1], addr_byte[0]); }

/*  *      Free the dictionary_attributes and dictionary_values lists.  */ static void dict_free(void) {         DICT_ATTR       *dattr, *anext;         DICT_VALUE      *dval, *vnext;         DICT_VENDOR     *dvend, *enext;

        for (dattr = dictionary_attributes; dattr; dattr = anext) {                 anext = dattr->next;                 free(dattr);         }         for (dval = dictionary_values; dval; dval = vnext) {                 vnext = dval->next;                 free(dval);         }         for (dvend = dictionary_vendors; dvend; dvend = enext) {                 enext = dvend->next;                 free(dvend);         }         dictionary_attributes = NULL;         dictionary_values = NULL;         dictionary_vendors = NULL;         vendorno = 1; }

/*  *      Add vendor to the list.  */ static int addvendor(char *name, int value) {         DICT_VENDOR *vval;

        if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) ==             (DICT_VENDOR *)NULL) {

                OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "radiusAAA plugin: out of memory\n"));                 return(-1);         }         strNcpy(vval->vendorname, name, sizeof(vval->vendorname));         vval->vendorpec  = value;         vval->vendorcode = vendorno++;

        /* Insert at front. */         vval->next = dictionary_vendors;         dictionary_vendors = vval;

        return 0; }

/*  *      Get the internal code of the vendor based on its PEC.  */ int dict_vendorcode(int pec) {         DICT_VENDOR     *v;

        for (v = dictionary_vendors; v; v = v->next)                 if (v->vendorpec == pec)                         break;

        return v ? v->vendorcode : 0; }

/*  *      Initialize the dictionary.  Read all ATTRIBUTES into  *       the dictionary_attributes list.  Read all VALUES into  *       the dictionary_values list.  */ int dict_init(char *fn) {         FILE    *dictfd;         char    dummystr[64];         char    namestr[64];         char    valstr[64];         char    attrstr[64];         char    typestr[64];         char    vendorstr[64];         int     line_no;         DICT_ATTR       *attr;         DICT_VALUE      *dval;         DICT_VENDOR     *v;         char    buffer[256];         int     value;         int     type;         int     vendor;         int     is_attrib; #ifdef ATTRIB_NMC         int     vendor_usr_seen = 0;         int     is_nmc = 0; #endif

        if (fn == NULL) dict_free();

        if (fn) {                 if (fn[0] == '/')                         strNcpy(buffer, fn, sizeof(buffer));                 else                         sprintf(buffer, "%.127s/%.127s", radius_dir, fn);         } else                 sprintf(buffer, "%.200s/%.50s", radius_dir, RADIUS_DICTIONARY);

        if((dictfd = fopen(buffer, "r")) == (FILE *)NULL) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "radiusAAA plugin: Couldn't open dictionary: %s\n", buffer));                  return(-1);         }

        line_no = 0;         while(fgets(buffer, sizeof(buffer), dictfd) != (char *)NULL) {                 line_no++;

                /* Skip empty space */                 if (*buffer == '#' || strlen(buffer) == strspn(buffer, " \t\n\0") )                         continue;

                if (strncasecmp(buffer, "$INCLUDE", 8) == 0) {

                        /* Read the $INCLUDE line */                         if(sscanf(buffer, "%63s%63s", dummystr, valstr) != 2) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid filename on line %d of dictionary\n", line_no));                                 return(-1);                         }                         if (dict_init(valstr) < 0)                                 return -1;                         continue;                 }

                is_attrib = 0;                 if (strncmp(buffer, "ATTRIBUTE", 9) == 0)                         is_attrib = 1; #ifdef ATTRIB_NMC                 is_nmc = 0;                 if (strncmp(buffer, "ATTRIB_NMC", 10) == 0)                         is_attrib = is_nmc = 1; #endif                 if (is_attrib) {                         /* Read the ATTRIBUTE line */                         vendor = 0;                         vendorstr[0] = 0;                         if(sscanf(buffer, "%63s%63s%63s%63s%63s", dummystr,                                 namestr, valstr, typestr, vendorstr) < 4) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid attribute on line %d of dictionary\n", line_no));                                 return(-1);                         }

#ifdef ATTRIB_NMC                         /*                          *      Convert ATTRIB_NMC into our format.                          *      We might need to add USR to the list of                          *      vendors first.                          */                         if (is_nmc && vendorstr[0] == 0) {                                 if (!vendor_usr_seen) {                                         if (addvendor("USR", VENDORPEC_USR) < 0)                                                 return -1;                                         vendor_usr_seen = 1;                                 }                                 strcpy(vendorstr, "USR");                         } #endif

                        /*                          * Validate all entries                          */                         if(strlen(namestr) > 31) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                              "radiusAAA plugin: Invalid name length on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        if(!isdigit(*valstr)) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid value on line %d of dictionary\n", line_no));                                 return(-1);                         }                         if (valstr[0] != '0')                                 value = atoi(valstr);                         else                                 sscanf(valstr, "%i", &value);

                        if(strcmp(typestr, "string") == 0) {                                 type = PW_TYPE_STRING;                         }                         else if(strcmp(typestr, "integer") == 0) {                                 type = PW_TYPE_INTEGER;                         }                         else if(strcmp(typestr, "ipaddr") == 0) {                                 type = PW_TYPE_IPADDR;                         }                         else if(strcmp(typestr, "date") == 0) {                                 type = PW_TYPE_DATE;                         }                         /* Cisco VoIP vsa support */                                 else if(strcmp(typestr, "avpair") == 0) {                                 type = PW_TYPE_CISCO_AVPAIR;                         }                         /* Sub-attribute list */                         else if(strcmp(typestr, "sublist") == 0) {                                 type = PW_TYPE_SUB_LIST;                         }                         else {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid type on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        for (v = dictionary_vendors; v; v = v->next) {                                 if (strcmp(vendorstr, v->vendorname) == 0)                                         vendor = v->vendorcode;                         }                         if (vendorstr[0] && !vendor) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: unknown vendor %s on line %d of dictionary\n", vendorstr, line_no));                                 return -1;                         }

#ifdef COMPAT_1543                         /*                          *      Convert old values 221,1036-1039 to the new                          *      ones, in case the dictionary is still the                          *      one from 1.5.4.3                          *                          *      XXX - this is a HACK !!                          */                         switch (value) {                                 case 221:                                         value = PW_HUNTGROUP_NAME;                                         break;                                 case 1036:                                         value = PW_FALL_THROUGH;                                         break;                                 case 1037:                                         value = PW_ADD_PORT_TO_IP_ADDRESS;                                         break;                                 case 1038:                                         value = PW_EXEC_PROGRAM;                                         break;                                 case 1039:                                         value = PW_EXEC_PROGRAM_WAIT;                                         break;                         } #endif                         /* Create a new attribute for the list */                         if((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) ==                                         (DICT_ATTR *)NULL) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: out of memory\n"));                                 return(-1);                         }                         strNcpy(attr->name, namestr, sizeof(attr->name));                         attr->value = value;                         attr->type = type;                         if (vendor)                                 attr->value |= (vendor << 16);

                        /*                          *      Add to the front of the list, so that                          *      values at the end of the file override                          *      those in the begin.                          */                         attr->next = dictionary_attributes;                         dictionary_attributes = attr;

                }                 else if (strncmp(buffer, "VALUE", 5) == 0) {

                        /* Read the VALUE line */                         if(sscanf(buffer, "%63s%63s%63s%63s", dummystr, attrstr,                                                 namestr, valstr) != 4) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid value entry on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        /*                          * Validate all entries                          */                         if(strlen(attrstr) > 31) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid attribute length on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        if(strlen(namestr) > 31) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid name length on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        if(!isdigit(*valstr)) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid value on line %d of dictionary\n", line_no));                                 return(-1);                         }                         value = atoi(valstr);

                        /* Create a new VALUE entry for the list */                         if((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) ==                                         (DICT_VALUE *)NULL) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: out of memory\n"));                                 return(-1);                         }                         strNcpy(dval->attrname, attrstr, sizeof(dval->attrname));                         strNcpy(dval->name, namestr, sizeof(dval->name));                         dval->value = value;

                        /* Insert at front. */                         dval->next = dictionary_values;                         dictionary_values = dval;                 }                 else if(strncmp(buffer, "VENDOR", 6) == 0) {

                        /* Read the VENDOR line */                         if(sscanf(buffer, "%63s%63s%63s", dummystr, attrstr,                                                 valstr) != 3) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid vendor entry on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        /*                          * Validate all entries                          */                         if(strlen(attrstr) > 31) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid attribute length on line %d of dictionary\n", line_no));                                 return(-1);                         }

                        if(!isdigit(*valstr)) {                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                             "radiusAAA plugin: Invalid value on line %d of dictionary\n", line_no));                                 return(-1);                         }                         value = atoi(valstr);

                        /* Create a new VENDOR entry for the list */                         if (addvendor(attrstr, value) < 0)                                 return -1; #ifdef ATTRIB_NMC                         if (value == VENDORPEC_USR)                                 vendor_usr_seen = 1; #endif                 }         }         fclose(dictfd);         return(0); }

/*************************************************************************  *       *      Function: dict_attrget  *  *      Purpose: Return the full attribute structure based on the  *               attribute id number.  *  *************************************************************************/

DICT_ATTR       * dict_attrget(attribute)  int     attribute; {         DICT_ATTR       *attr;

        attr = dictionary_attributes;         while(attr != (DICT_ATTR *)NULL) {                 if(attr->value == attribute) {                         return(attr);                 }                 attr = attr->next;         }         return((DICT_ATTR *)NULL); }

/*************************************************************************  *       *      Function: dict_valget  *  *      Purpose: Return the full value structure based on the     *               actual value and the associated attribute name.  *  *************************************************************************/

DICT_VALUE      * dict_valget(value, attrname)  UINT4   value; char    *attrname; {         DICT_VALUE      *val;                 val = dictionary_values;         while(val != (DICT_VALUE *)NULL) {                    if(DICT_STRCMP(val->attrname, attrname) == 0 &&                                                 val->value == value) {                         return(val);                 }                 val = val->next;         }         return((DICT_VALUE *)NULL); }

int radiusAAA_ctx_init () {   config_element_t        *elem;   char                    *p;   struct  servent         *svp;   struct  sockaddr        salocal;   u_short                 local_port;   char                    nasname[256];

  radiusAAA_context = (radiusAAA_ctx_t *) smalloc (sizeof (radiusAAA_ctx_t));   if (radiusAAA_context == NULL)     return -1;

  elem = psp_config_get_sub_element ("server", "radiusAAA", NULL);   if (elem == NULL || elem->value == NULL) {     OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                              "radiusAAA plugin: server is mandatory\n"));     radiusAAA_ctx_free ();     return -1;   } else {     if ( (p = strchr(elem->value, ':') ) != NULL) {        *p++ = 0;        radiusAAA_context->svc_port = satoi(p);     } else {        radiusAAA_context->svc_port = 0;     }     radiusAAA_context->server = elem->value;   }   OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,      "radiusAAA plugin: server: %s\n",      radiusAAA_context->server));

  elem = psp_config_get_sub_element ("key", "radiusAAA", NULL);                         if (elem == NULL || elem->value == NULL) {     OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                               "radiusAAA plugin: key is mandatory\n"));     radiusAAA_ctx_free ();     return -1;   } else {     radiusAAA_context->key = elem->value;   }

  elem = psp_config_get_sub_element ("retransmit", "radiusAAA", NULL);   if (elem == NULL || elem->value == NULL) {     radiusAAA_context->retransmit = 5;   } else {     radiusAAA_context->retransmit = atoi(elem->value);   }

  elem = psp_config_get_sub_element ("timeout", "radiusAAA", NULL);   if (elem == NULL || elem->value == NULL) {     radiusAAA_context->timeout = 3;   } else {     radiusAAA_context->timeout = atoi(elem->value);   }

  elem = psp_config_get_sub_element ("dictionary_directory", "radiusAAA", NULL);   if (elem == NULL || elem->value == NULL) {     OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                               "radiusAAA plugin: dictionary_directory is mandatory\n"));     radiusAAA_ctx_free ();     return -1;   } else {     radiusAAA_context->dictionary = elem->value;     radius_dir = elem->value;   }

  gethostname(nasname, sizeof(nasname));   radiusAAA_context->nas_ipaddr = get_ipaddr(nasname);

  if( dict_init(NULL) == -1 ) return -1;

        /*          *      Open a connection to the server.          */         if (radiusAAA_context->svc_port == 0) {                 svp = getservbyname ("radius", "udp");                 if (svp == (struct servent *) 0)                         radiusAAA_context->svc_port = PW_AUTH_UDP_PORT;                 else                         radiusAAA_context->svc_port = ntohs((u_short) svp->s_port);         }

        /* Get the IP address of the authentication server */         if((auth_ipaddr = get_ipaddr(radiusAAA_context->server)) == 0) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                               "radiusAAA plugin: Couldn't find host %s\n", radiusAAA_context->server));                 radiusAAA_ctx_free ();                 return -1;         }

        sockfd = socket (AF_INET, SOCK_DGRAM, 0);         if (sockfd < 0) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                               "radiusAAA plugin: socket"));                                                     radiusAAA_ctx_free ();                 return -1;         }

        sin = (struct sockaddr_in *) &salocal;         memset (sin, 0, sizeof (salocal));         sin->sin_family = AF_INET;         sin->sin_addr.s_addr = INADDR_ANY;

        local_port = 1025;         do {                 local_port++;                 sin->sin_port = htons((u_short)local_port);         } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) &&                                                 local_port < 64000);         if (local_port >= 64000) {                 close(sockfd);                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                               "radiusAAA plugin: failed to bind\n"));                                                     radiusAAA_ctx_free ();                 return -1;         }

  return 0; }

void radiusAAA_ctx_free () {   if (radiusAAA_context == NULL)     return;

  sfree (radiusAAA_context);   radiusAAA_context = NULL; }

/*  *      Generate a random vector.  */ static void random_vector(char *vector) {         int     randno;         int     i;                 srand(time(0));         for(i = 0;i < AUTH_VECTOR_LEN;) {                 randno = rand();                 memcpy(vector, &randno, sizeof(int));                 vector += sizeof(int);                 i += sizeof(int);         } }

/*  *      Receive UDP client requests, build an authorization request  *      structure, and attach attribute-value pairs contained in  *      the request to the new structure.  */ AUTH_REQ *radrecv(UINT4 host, u_short udp_port, u_char *buffer, int length) {         u_char          *ptr;         char            hn[16];         AUTH_HDR        *auth;         int             totallen;         int             attribute;         int             attrlen;         DICT_ATTR       *attr;         UINT4           lvalue;         VALUE_PAIR      *first_pair;         VALUE_PAIR      *prev;         VALUE_PAIR      *pair;         AUTH_REQ        *authreq;         int             vendorlen;         UINT4           vendorcode;         UINT4           vendorpec;

        /*          *      Pre-allocate the new request data structure          */

        if((authreq = (AUTH_REQ *)smalloc(sizeof(AUTH_REQ))) ==                                                 (AUTH_REQ *)NULL) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "radiusAAA plugin: smalloc error\n"));                 return NULL;         }

        auth = (AUTH_HDR *)buffer;         totallen = ntohs(auth->length);

        ipaddr2str(hn, ntohl(host));         OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                           "radiusAAA plugin: Reply from host %s code=%d, id=%d, length=%d\n", hn, auth->code, auth->id, totallen));

        /*          *      Fill header fields          */         authreq->ipaddr = host;         authreq->udp_port = udp_port;         authreq->id = auth->id;         authreq->code = auth->code;         memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);         authreq->proxy_pairs = NULL;         authreq->server_reply = NULL;         authreq->timestamp = time(NULL);

        /*          *      Extract attribute-value pairs          */         ptr = (u_char *)auth->data;         length -= AUTH_HDR_LEN;         first_pair = (VALUE_PAIR *)NULL;         prev = (VALUE_PAIR *)NULL;

        vendorcode = 0;         vendorlen  = 0;

        while(length > 0) {

                if (vendorlen > 0) {                         attribute = *ptr++ | (vendorcode << 16);                         attrlen   = *ptr++;                 } else {                         attribute = *ptr++;                         attrlen   = *ptr++;                 }                 if (attrlen < 2) {                         length = 0;                         continue;                 }                 attrlen -= 2;                 length  -= 2;

                /*                  *      This could be a Vendor-Specific attribute.                  *                  */                 if (vendorlen <= 0 &&                     attribute == PW_VENDOR_SPECIFIC && attrlen > 6) {                         memcpy(&lvalue, ptr, 4);                         vendorpec = ntohl(lvalue);                         if ((vendorcode = dict_vendorcode(vendorpec))                             != 0) { #ifdef ATTRIB_NMC                                 if (vendorpec == VENDORPEC_USR) {                                         ptr += 4;                                         memcpy(&lvalue, ptr, 4);                                         attribute = (ntohl(lvalue) & 0xFFFF) |                                                         (vendorcode << 16);                                         ptr += 4;                                         attrlen -= 8;                                         length -= 8;                                 } else #endif                                 {                                         ptr += 4;                                         vendorlen = attrlen - 4;                                         attribute = *ptr++ | (vendorcode << 16);                                         attrlen   = *ptr++;                                         attrlen -= 2;                                         length -= 6;                                 }                         }                 }

                if ((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==                                         (VALUE_PAIR *)NULL) {                         OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                     "radiusAAA plugin: malloc error\n"));                         exit(1);                 }                 memset(pair, 0, sizeof(VALUE_PAIR));

                if ((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {                         OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                     "radiusAAA plugin: Received unknown attribute %d\n", attribute));                         sprintf(pair->name, "Unknown-Attr-%d", attribute);                         pair->type = PW_TYPE_STRING;                 } else {                         strcpy(pair->name, attr->name);                         pair->type = attr->type;                 }

                if ( attrlen >= AUTH_STRING_LEN-1 ) {                         OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                     "radiusAAA plugin: attribute %d too long, %d >= %d\n", attribute, attrlen, AUTH_STRING_LEN));                         free(pair);                 }                 else if ( attrlen > length ) {                         OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                                     "radiusAAA plugin: attribute %d longer as buffer left, %d > %d\n", attribute, attrlen, length));                         free(pair);                 }                 else {                         pair->attribute = attribute;                         pair->length = attrlen;                         pair->next = (VALUE_PAIR *)NULL;                         pair->operator = PW_OPERATOR_EQUAL;                         pair->strvalue[0] = '\0';

                        switch (pair->type) {

                        case PW_TYPE_STRING:                         case PW_TYPE_CISCO_AVPAIR:                         case PW_TYPE_SUB_LIST:                                 /* attrlen always < AUTH_STRING_LEN */                                 memset(pair->strvalue, 0, AUTH_STRING_LEN);                                 memcpy(pair->strvalue, ptr, attrlen);                                 if(first_pair == (VALUE_PAIR *)NULL) {                                         first_pair = pair;                                 }                                 else {                                         prev->next = pair;                                 }                                 prev = pair;                                 break;

                        case PW_TYPE_INTEGER:                         case PW_TYPE_IPADDR:                                 memcpy(&lvalue, ptr, sizeof(UINT4));                                 pair->lvalue = ntohl(lvalue);                                 if(first_pair == (VALUE_PAIR *)NULL) {                                         first_pair = pair;                                 }                                 else {                                         prev->next = pair;                                 }                                 prev = pair;                                 break;

                        default:                                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                                             "radiusAAA plugin: %s (Unknown Type %d)\n", attr->name,attr->type));                                 free(pair);                                 break;                         }

                }                 ptr += attrlen;                 length -= attrlen;                 if (vendorlen > 0) vendorlen -= (attrlen + 2);         }         authreq->request = first_pair;         return(authreq); }

/*  *      Receive and print the result.  */ AUTH_REQ *result_recv(UINT4 host, u_short udp_port, char *buffer, int length) {         AUTH_HDR        *auth;         int             totallen;         char            reply_digest[AUTH_VECTOR_LEN];         char            calc_digest[AUTH_VECTOR_LEN];         int             secretlen;         MD5_CTX         Md5Ctx;         AUTH_REQ        *authreq;

        auth = (AUTH_HDR *)buffer;         totallen = ntohs(auth->length);                                 if(totallen != length) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "radiusAAA plugin: Received invalid reply length from server (want %d/ got %d)\n", totallen, length));                 return NULL;         }

        /* Verify the reply digest */         memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);         memcpy(auth->vector, vector, AUTH_VECTOR_LEN);         secretlen = strlen(radiusAAA_context->key);         memcpy(buffer + length, radiusAAA_context->key, secretlen);         ppl_MD5Init (&Md5Ctx);         ppl_MD5Update (&Md5Ctx, (unsigned char *)auth, length + secretlen);         ppl_MD5Final ((unsigned char *) calc_digest, &Md5Ctx);

        if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "radiusAAA plugin: Received invalid reply digest from server\n"));                 return NULL;         }

        authreq = radrecv(host, udp_port, (u_char *)buffer, length);         print_attr_list(authreq->request);         return authreq; }

/*  *      Encode Attribute.  */ int encodeAttribute( char **ptr, int attribute_code, char *attribute_value) { int length;                                             *(*ptr)++ = attribute_code;         length = strlen( attribute_value );         if(length > MAXPWNAM) length = MAXPWNAM;         *(*ptr)++ = length + 2;         memcpy(*ptr, attribute_value, length);         (*ptr) += length;         return length + 2; }

/*  *      Encode DigestAttribute with one subattribute.  */ int encodeDigestAttribute( char **ptr, int sub_attribute_code, char *sub_attribute_value) { int length;

        *(*ptr)++ = PW_DIGEST_ATTRIBUTES;         length = strlen( sub_attribute_value );         if(length > MAXPWNAM) length = MAXPWNAM;         *(*ptr)++ = length + 2 + 2;         *(*ptr)++ = sub_attribute_code;         *(*ptr)++ = length + 2;         memcpy(*ptr, sub_attribute_value, length);         (*ptr) += length;         return length + 2 + 2; }

/*  *      Encode Vendor Specific Attribute.  */     int encodeVendorSpecificAttribute( char **ptr, int vendor_code, int attribute_code, char *attribute_value) { int length; UINT4 ui;         length = strlen( attribute_value );         *(*ptr)++ = PW_VENDOR_SPECIFIC;         *(*ptr)++ = length + 2 + 4 + 2;         ui = htonl(vendor_code);         memcpy(*ptr, &ui, sizeof(UINT4));         (*ptr) += 4;         *(*ptr)++ = attribute_code;         *(*ptr)++ = length + 2;         memcpy(*ptr, attribute_value, length);         (*ptr) += length;         return length + 2 + 4 + 2; }

AUTH_REQ *radiusAAA_validate_credential_for_user (sip_t *request, char *user, proxy_authorization_t * p_auth, char *method) {   /* find the pending_auth element */   char *response;   char *nonce;   char *opaque;   char *realm;

  /* char *qop; */   char *uri;

  char *pszResponse, *pszRealm, *pszNonce, *pszURI, *pszQop;

  /* Radius client stuff */   AUTH_HDR                *auth;   char                    *ptr;   struct  sockaddr        saremote;   int                     result = -1; #ifdef __linux   socklen_t               salen; #else   int                     salen; #endif   struct timeval          tv;   fd_set                  readfds;   u_short                 total_length;   int                     i;   UINT4                   ui;   AUTH_REQ                *authreq;   char                    *call_id;

  nonce = proxy_authorization_getnonce (p_auth);   opaque = proxy_authorization_getopaque (p_auth);   if (opaque == NULL || nonce == NULL)     return NULL;

  realm = proxy_authorization_getrealm (p_auth);   if (realm == NULL)     return NULL;   response = proxy_authorization_getresponse (p_auth);   if (response == NULL)     return NULL;   uri = proxy_authorization_geturi (p_auth);   if (uri == NULL)     return NULL;

    /* Create radius Access Request */         /*          *      Build an authentication request          */         auth = (AUTH_HDR *)send_buffer;         auth->code = PW_AUTHENTICATION_REQUEST;         auth->id = getpid() % 256;         random_vector(vector);         memcpy(auth->vector, vector, AUTH_VECTOR_LEN);         total_length = AUTH_HDR_LEN;         ptr = (char *)auth->data;

        /*          *      NAS IP Address          */         *ptr++ = PW_NAS_IP_ADDRESS;         *ptr++ = 6;         ui = htonl(radiusAAA_context->nas_ipaddr);         memcpy(ptr, &ui, sizeof(UINT4));         ptr += 4;         total_length += 6;

        /*          *      NAS Port Type - Virtual                                                            */

        *ptr++ = PW_NAS_PORT_TYPE;         *ptr++ = 6;         ui = htonl(5);         memcpy(ptr, &ui, sizeof(UINT4));         ptr += 4;         total_length += 6;

        /*          *      User Name          */         total_length += encodeAttribute(&ptr, PW_USER_NAME, user);          if (!MSG_IS_REGISTER (request)) {         /*          *      Calling Station Id          */         total_length += encodeAttribute(&ptr, PW_CALLING_STATION_ID, request->from->url->username );         /*          *      Called Station Id          */         total_length += encodeAttribute(&ptr, PW_CALLED_STATION_ID, request->to->url->username );      }

        /*          *      Cisco AVpair call-id          */         call_id = NULL; /* to avoid a warning */           if (request->call_id->host==NULL)    asprintf( &call_id, "call-id=%s", request->call_id->number );  else    asprintf( &call_id, "call-id=%s@%s", request->call_id->number,       request->call_id->host );  total_length += encodeVendorSpecificAttribute(&ptr, 9, 1, call_id);  free(call_id);              /*          *      Digest Responce          */         pszResponse = sgetcopy_unquoted_string (response);         total_length += encodeAttribute(&ptr, PW_DIGEST_RESPONCE, pszResponse);

        /*          *      Digest Attributes          *          */

        pszRealm = sgetcopy_unquoted_string (realm);         total_length += encodeDigestAttribute( &ptr, PW_DA_REALM, pszRealm);

        pszNonce = sgetcopy_unquoted_string (nonce);         total_length += encodeDigestAttribute( &ptr, PW_DA_NONCE, pszNonce);

        total_length += encodeDigestAttribute( &ptr, PW_DA_METHOD, method);

        pszURI = sgetcopy_unquoted_string (uri);         total_length += encodeDigestAttribute( &ptr, PW_DA_URI, pszURI);

        total_length += encodeDigestAttribute( &ptr, PW_DA_ALGORITHM, "MD5");

        total_length += encodeDigestAttribute( &ptr, PW_DA_USER_NAME, user);

        pszQop = NULL;

        auth->length = htons(total_length);

    sfree (pszRealm);     sfree (pszNonce);     sfree (pszURI);     sfree (pszQop);     sfree (pszResponse);

        /*          *      Send the request we've built.          */         sin = (struct sockaddr_in *) &saremote;         memset (sin, 0, sizeof (saremote));         sin->sin_family = AF_INET;         sin->sin_addr.s_addr = htonl(auth_ipaddr);         sin->sin_port = htons(radiusAAA_context->svc_port);

        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                               "radiusAAA plugin: Sending request to server %s, port %d.\n",                               radiusAAA_context->server, radiusAAA_context->svc_port));

        for (i = 0; i < radiusAAA_context->retransmit; i++) {                 if (i > 0) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                                        "radiusAAA plugin: resending request\n"));                 sendto(sockfd, (char *)auth, total_length, 0,                         &saremote, sizeof(struct sockaddr_in));

                tv.tv_sec = radiusAAA_context->timeout;                 tv.tv_usec = 0;                 FD_ZERO(&readfds);                 FD_SET(sockfd, &readfds);                 if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0) continue;                 salen = sizeof (saremote);                 result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer),                         0, &saremote, &salen);                 if (result >= 0) break;                 sleep(tv.tv_sec);         }

        if ( result <= 0 || i >= radiusAAA_context->retransmit ) {                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "radiusAAA plugin: no answer from radius server\n"));                 return NULL;         }         authreq = result_recv(sin->sin_addr.s_addr, sin->sin_port, recv_buffer, result);

        if( authreq == NULL ) return NULL;         switch(authreq->code) {         case PW_AUTHENTICATION_ACK:                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                           "radius plugin: Access granted.\n"));                 return authreq;         default:                 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                           "radius plugin: Access denied.\n"));                 return NULL;         } }

char * radiusAAA_ctx_find_private_user (proxy_authorization_t * p_auth) {   char *realm = psp_config_get_element ("serverrealm");   char *username;   char *qusername;

  if (0 != strcmp (p_auth->realm, realm))     {       OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,                               "radiusAAA plugin: authentication header belongs to another proxy!\nlocal:%s remote:%s\n",                               realm, p_auth->uri));       return NULL;              /* this header is not for me */     }

  /* search for a user context */   qusername = proxy_authorization_getusername (p_auth);   if (qusername == NULL) return NULL;   username = sgetcopy_unquoted_string (qusername);

  return username; }

/* HOOK METHODS */

/*   This method returns:   -2 if plugin consider this request should be totally discarded!   -1 on error   0  nothing has been done   1  things has been done on psp_req element */ int cb_radiusAAA_validate_credentials (psp_req_t * psp_req) {   char *user, *ptr;   proxy_authorization_t *p_auth;   authorization_t *h_auth;   int pos;   AUTH_REQ                *authreq;   VALUE_PAIR *namepair;   location_t *loc;   url_t *url;   int i;

  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                           "radiusAAA plugin: Processing authentication in request!\n"));

  if (!MSG_IS_REGISTER (psp_req->request))     {       /* default OUTPUT */       psp_req_set_uas_status (psp_req, 407);       psp_req_set_mode (psp_req, PSP_UAS_MODE);       psp_req_set_state (psp_req, PSP_MANDATE);

      /* ANY proxy_authorization for us? */       msg_getproxy_authorization (psp_req->request, 0, &p_auth);       pos = 0;       while (p_auth != NULL)    /* find the proxy_authorization for this proxy */         {           user = radiusAAA_ctx_find_private_user (p_auth);           if (user != NULL)             {               authreq = radiusAAA_validate_credential_for_user (psp_req->request,          user, p_auth,          psp_req->request->          strtline->sipmethod);               if (authreq == NULL)                 {                   OSIP_TRACE (osip_trace                               (__FILE__, __LINE__, OSIP_WARNING, NULL,                                "radiusAAA plugin: Bad credential for user!\n"));                   /* may be we should answer 403 forbidden, because we have                      detected that somebody tried to login! */                   return 0;                 }

              psp_req_set_state (psp_req, PSP_CONTINUE);               /* remove the proxy_authorization header! */               list_remove (psp_req->request->proxy_authorizations, pos);               proxy_authorization_free (p_auth);               sfree (p_auth);

              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                                       "radiusAAA plugin: Valid credential for user!\n"));               psp_req_set_mode (psp_req, PSP_SFULL_MODE);               psp_req_set_state (psp_req, PSP_CONTINUE);

              namepair = pairfind_by_name(authreq->request, "h323-redirect-number" );               if (namepair != NULL) {                  ptr = namepair->strvalue;                  if( (ptr=strchr((u_char *)namepair->strvalue,'=')) == NULL ) ptr = namepair->strvalue;                  else ptr++;                  url_init(&url);                  i = url_parse(url, ptr);                  if (i!=0) {                     url_free(url);                     sfree(url);                     OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL,                                 "ls_localdb plugin: Could not create url!\n"));                  }                  i = location_init (&loc, url, 3600);                  /* bad configuration?->should be checked in plugin_init so this will never happen */                  if (i != 0) {                     /* This can only happen in case we don't have enough memory */                     /* url_free(url); */                     /* dangerous? I prefer to leave a memory leak */                     /* sfree(url); */                     /* as we may never enter this code */                     OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL,                                 "ls_localdb plugin: Could not create location info!\n"));                     psp_req_set_uas_status (psp_req, 400);                     psp_req_set_mode (psp_req, PSP_UAS_MODE);                     psp_req_set_state (psp_req, PSP_MANDATE);                     return -1;            /* error case (process can continue...) */                  }                  ADD_ELEMENT (psp_req->locations, loc);

                 psp_req_set_uas_status (psp_req, 302);                  psp_req_set_mode (psp_req, PSP_UAS_MODE);                  psp_req_set_state (psp_req, PSP_MANDATE);               }               authfree(authreq);

              return 0;         /* do nothing.. */             }           pos++;           msg_getproxy_authorization (psp_req->request, pos, &p_auth);         }       OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                               "radiusAAA plugin: Bad credential for user!\n"));       return 0;     }

  /* for REGISTER */   /* default OUTPUT */   psp_req_set_uas_status (psp_req, 401);   psp_req_set_mode (psp_req, PSP_UAS_MODE);   psp_req_set_state (psp_req, PSP_MANDATE);

  /* ANY authorization for us? */   msg_getauthorization (psp_req->request, 0, &h_auth);   pos = 0;   while (h_auth != NULL)        /* find the authorization for this proxy */     {       user = radiusAAA_ctx_find_private_user (h_auth);       if (user != NULL)         {           authreq = radiusAAA_validate_credential_for_user (psp_req->request,             user, h_auth,             psp_req->request->strtline->             sipmethod);           if (authreq == NULL)             {               OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                                       "radiusAAA plugin: Bad credential for user!\n"));               /* may be we should answer 403 forbidden, because we have                  detected that somebody tried to login! */               return 0;             }

          authfree(authreq);           /* remove the authorization header! */           list_remove (psp_req->request->authorizations, pos);           authorization_free (h_auth);           sfree (h_auth);

          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                                   "radiusAAA plugin: Valid credential for user!\n"));           psp_req_set_mode (psp_req, PSP_SFULL_MODE);           psp_req_set_state (psp_req, PSP_CONTINUE);           return 0;             /* do nothing.. */         }       pos++;       msg_getauthorization (psp_req->request, pos, &h_auth);     }

  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,                           "radiusAAA plugin: Bad credential for user!\n"));   return 0; }

int cb_radiusAAA_add_credentials (psp_req_t * psp_req)   /* HOOK MIDDLE */ {   char *nonce;   char *opaque;

  /*  char *qop; */   char *realm;   proxy_authenticate_t *p_auth;   www_authenticate_t *w_auth;   int status = psp_req_get_uas_status (psp_req);

  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,                           "radiusAAA plugin: check if we need to add credentials in this 4xx!\n"));

  if (status != 407 && status != 401)     {       psp_req_set_state (psp_req, PSP_CONTINUE);       return 0;     }

  /* The request DOES not contains any credential */   /* We have to challenge user */

  /* we just have to challenge the users */   {     MD5_CTX Md5Ctx;     HASH HTMP;     HASHHEX HTMPHex;     int time_stamp;     char *now;     int i;

    /* build a nonce string */     nonce = (char *) smalloc (HASHHEXLEN + 1 + 2);      /* +2 for the quotes */     now = (char *) smalloc (30);     time_stamp = ppl_time ();     sprintf (now, "%i", time_stamp);     ppl_MD5Init (&Md5Ctx);     ppl_MD5Update (&Md5Ctx, (unsigned char *) now, strlen (now));     sfree (now);     ppl_MD5Update (&Md5Ctx, (unsigned char *) ":", 1);     now = psp_config_get_element ("magicstring");     ppl_MD5Update (&Md5Ctx, (unsigned char *) now, strlen (now));     ppl_MD5Update (&Md5Ctx, (unsigned char *) ":", 1);     ppl_MD5Update (&Md5Ctx, (unsigned char *) psp_req->request->cseq->number,                    strlen (psp_req->request->cseq->number));     ppl_MD5Update (&Md5Ctx, (unsigned char *) ":", 1);     ppl_MD5Update (&Md5Ctx,                    (unsigned char *) psp_req->request->call_id->number,                    strlen (psp_req->request->call_id->number));     ppl_MD5Final ((unsigned char *) HTMP, &Md5Ctx);     ppl_md5_hash_to_hex (HTMP, HTMPHex);     sprintf (nonce, "\"%s\"", HTMPHex);

    /* build an opaque string */     opaque = (char *) smalloc (HASHHEXLEN + 1 + 2);     /* +2 is for the quotes */     now = (char *) smalloc (30);     time_stamp = ppl_time ();     sprintf (now, "%i", time_stamp);     ppl_MD5Init (&Md5Ctx);     ppl_MD5Update (&Md5Ctx, (unsigned char *) now, strlen (now));     sfree (now);     ppl_MD5Update (&Md5Ctx, (unsigned char *) ":", 1);     ppl_MD5Final ((unsigned char *) HTMP, &Md5Ctx);     ppl_md5_hash_to_hex (HTMP, HTMPHex);     sprintf (opaque, "\"%s\"", HTMPHex);

    /*    qop = smalloc(9);        sprintf(qop, "\"auth\""); */

    realm = sgetcopy (psp_config_get_element ("serverrealm"));

    /* store data in a radiusAAA_ctx_t context */

    if (status == 407)       {         i = proxy_authenticate_init (&p_auth);         if (i != 0)           return -1;         proxy_authenticate_setauth_type (p_auth, sgetcopy ("Digest"));         /*      proxy_authenticate_setqop_options(p_auth, qop); */         proxy_authenticate_setnonce (p_auth, nonce);         proxy_authenticate_setopaque (p_auth, opaque);         proxy_authenticate_setrealm (p_auth, realm);

        list_add (psp_req->response->proxy_authenticates, p_auth, -1);

        psp_req_set_state (psp_req, PSP_CONTINUE);         return 0;     } else if (status == 401)       {         i = www_authenticate_init (&w_auth);         if (i != 0)           return -1;         www_authenticate_setauth_type (w_auth, sgetcopy ("Digest"));         /*      www_authenticate_setqop_options(w_auth, qop); */         www_authenticate_setnonce (w_auth, nonce);         www_authenticate_setopaque (w_auth, opaque);         www_authenticate_setrealm (w_auth, realm);

        list_add (psp_req->response->www_authenticates, w_auth, -1);

        psp_req_set_state (psp_req, PSP_CONTINUE);         return 0;       }   }   psp_req_set_state (psp_req, PSP_CONTINUE);   return 0; }

posted on 2012-11-04 21:07  szgzwf  阅读(308)  评论(0)    收藏  举报