*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2000 The FreeRADIUS server project
+ * Copyright 2000,2006 The FreeRADIUS server project
* Copyright 2000 Alan DeKok <aland@ox.org>
*/
-static const char rcsid[] =
-"$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <ctype.h>
-#include "radiusd.h"
-
-#include "rad_assert.h"
-
typedef struct xlat_t {
char module[MAX_STRING_LEN];
int length;
/*
* Define all xlat's in the structure.
*/
-static const char *internal_xlat[] = {"check",
- "request",
- "reply",
- "proxy-request",
- "proxy-reply",
- NULL};
+static const char * const internal_xlat[] = {"check",
+ "request",
+ "reply",
+ "proxy-request",
+ "proxy-reply",
+ NULL};
#if REQUEST_MAX_REGEX > 8
#error Please fix the following line
#endif
-static int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /* up to 8 for regex */
+static const int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /* up to 8 for regex */
/*
switch (type) {
case PW_TYPE_STRING :
- strNcpy(out,"_",outlen);
+ strlcpy(out,"_",outlen);
break;
case PW_TYPE_INTEGER :
- strNcpy(out,"0",outlen);
+ strlcpy(out,"0",outlen);
break;
case PW_TYPE_IPADDR :
- strNcpy(out,"?.?.?.?",outlen);
+ strlcpy(out,"?.?.?.?",outlen);
+ break;
+ case PW_TYPE_IPV6ADDR :
+ strlcpy(out,":?:",outlen);
break;
case PW_TYPE_DATE :
- strNcpy(out,"0",outlen);
+ strlcpy(out,"0",outlen);
break;
default :
- strNcpy(out,"unknown_type",outlen);
+ strlcpy(out,"unknown_type",outlen);
}
return strlen(out);
}
*/
da = dict_attrbyname(fmt);
if (!da) {
- int index;
+ int count;
const char *p = strchr(fmt, '[');
char buffer[256];
if (!p) return 0;
if (strlen(fmt) > sizeof(buffer)) return 0;
- strNcpy(buffer, fmt, p - fmt + 1);
+ strlcpy(buffer, fmt, p - fmt + 1);
da = dict_attrbyname(buffer);
if (!da) return 0;
* attributes of that name in the list.
*/
if ((p[1] == '#') && (p[2] == ']')) {
- index = 0;
+ count = 0;
for (vp = pairfind(vps, da->attr);
vp != NULL;
vp = pairfind(vp->next, da->attr)) {
- index++;
+ count++;
}
- snprintf(out, outlen, "%d", index);
+ snprintf(out, outlen, "%d", count);
return strlen(out);
}
/*
* %{Attribute-Name[*]} returns ALL of the
* the attributes, separated by a newline.
- */
+ */
if ((p[1] == '*') && (p[2] == ']')) {
int total = 0;
for (vp = pairfind(vps, da->attr);
vp != NULL;
vp = pairfind(vp->next, da->attr)) {
- index = valuepair2str(out, outlen - 1, vp, da->type, func);
- rad_assert(index <= outlen);
- total += index + 1;
- outlen -= (index + 1);
- out += index;
-
+ count = valuepair2str(out, outlen - 1, vp, da->type, func);
+ rad_assert(count <= outlen);
+ total += count + 1;
+ outlen -= (count + 1);
+ out += count;
+
*(out++) = '\n';
if (outlen == 0) break;
return total;
}
-
- index = atoi(p + 1);
+
+ count = atoi(p + 1);
/*
* Skip the numbers.
for (vp = pairfind(vps, da->attr);
vp != NULL;
vp = pairfind(vp->next, da->attr)) {
- if (index == 0) break;
- index--;
+ if (count == 0) break;
+ count--;
}
/*
/*
* Some "magic" handlers, which are never in VP's, but
* which are in the packet.
+ *
+ * FIXME: We should really do this in a more
+ * intelligent way...
*/
if (packet) {
VALUE_PAIR localvp;
- localvp.strvalue[0] = 0;
+ localvp.vp_strvalue[0] = 0;
switch (da->attr) {
case PW_PACKET_TYPE:
{
DICT_VALUE *dval;
-
+
dval = dict_valbyattr(da->attr, packet->code);
if (dval) {
snprintf(out, outlen, "%s", dval->name);
}
break;
+ case PW_CLIENT_IP_ADDRESS: /* the same as below */
case PW_PACKET_SRC_IP_ADDRESS:
+ if (packet->src_ipaddr.af != AF_INET) {
+ return 0;
+ }
localvp.attribute = da->attr;
- localvp.lvalue = packet->src_ipaddr;
+ localvp.vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
break;
-
+
case PW_PACKET_DST_IP_ADDRESS:
+ if (packet->dst_ipaddr.af != AF_INET) {
+ return 0;
+ }
localvp.attribute = da->attr;
- localvp.lvalue = packet->dst_ipaddr;
+ localvp.vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
break;
-
+
case PW_PACKET_SRC_PORT:
localvp.attribute = da->attr;
- localvp.lvalue = packet->src_port;
+ localvp.vp_integer = packet->src_port;
break;
-
+
case PW_PACKET_DST_PORT:
localvp.attribute = da->attr;
- localvp.lvalue = packet->dst_port;
+ localvp.vp_integer = packet->dst_port;
break;
case PW_PACKET_AUTHENTICATION_VECTOR:
localvp.attribute = da->attr;
- memcpy(localvp.strvalue, packet->vector,
+ memcpy(localvp.vp_strvalue, packet->vector,
sizeof(packet->vector));
localvp.length = sizeof(packet->vector);
break;
*/
case PW_REQUEST_PROCESSING_STAGE:
if (request->component) {
- strNcpy(out, request->component, outlen);
+ strlcpy(out, request->component, outlen);
} else {
- strNcpy(out, "server_core", outlen);
+ strlcpy(out, "server_core", outlen);
+ }
+ return strlen(out);
+
+ case PW_PACKET_SRC_IPV6_ADDRESS:
+ if (packet->src_ipaddr.af != AF_INET6) {
+ return 0;
}
+ localvp.attribute = da->attr;
+ memcpy(localvp.vp_strvalue,
+ &packet->src_ipaddr.ipaddr.ip6addr,
+ sizeof(packet->src_ipaddr.ipaddr.ip6addr));
+ break;
+
+ case PW_PACKET_DST_IPV6_ADDRESS:
+ if (packet->dst_ipaddr.af != AF_INET6) {
+ return 0;
+ }
+ localvp.attribute = da->attr;
+ memcpy(localvp.vp_strvalue,
+ &packet->dst_ipaddr.ipaddr.ip6addr,
+ sizeof(packet->dst_ipaddr.ipaddr.ip6addr));
+ break;
+
+ case PW_SERVER_IDENTITY:
+ if (!request->listener || !request->listener->identity) return 0;
+
+ snprintf(out, outlen, "%s", request->listener->identity);
return strlen(out);
-
+ break;
+
default:
return 0; /* not found */
break;
*/
fmt = fmt; /* -Wunused */
func = func; /* -Wunused FIXME: do escaping? */
-
- regex = request_data_get(request, request,
+
+ regex = request_data_reference(request, request,
REQUEST_DATA_REGEX | *(int *)instance);
if (!regex) return 0;
* Copy UP TO "freespace" bytes, including
* a zero byte.
*/
- strNcpy(out, regex, outlen);
- free(regex); /* was strdup'd */
+ strlcpy(out, regex, outlen);
return strlen(out);
}
#endif /* HAVE_REGEX_H */
+
/*
* Compare two xlat_t structs, based ONLY on the module name.
*/
/*
* find the appropriate registered xlat function.
*/
-static xlat_t *xlat_find(const char *module)
+static const xlat_t *xlat_find(const char *module)
{
- char *p;
xlat_t my_xlat;
- p = my_xlat.module;
- my_xlat.length = 0;
- while (*module && (*module != ':')) {
- *(p++) = *(module++);
- my_xlat.length++;
+ /*
+ * Look for dictionary attributes first.
+ */
+ if ((dict_attrbyname(module) != NULL) ||
+ (strchr(module, '[') != NULL)) {
+ static const xlat_t dict_xlat = {
+ "request",
+ 7,
+ &xlat_inst[1],
+ xlat_packet,
+ TRUE
+ };
+
+ return &dict_xlat;
}
- *p = '\0';
+
+ strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
+ my_xlat.length = strlen(my_xlat.module);
return rbtree_finddata(xlat_root, &my_xlat);
}
/*
* If it already exists, replace the instance.
*/
- strNcpy(my_xlat.module, module, sizeof(my_xlat.module));
+ strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
my_xlat.length = strlen(my_xlat.module);
c = rbtree_finddata(xlat_root, &my_xlat);
if (c) {
memset(c, 0, sizeof(*c));
c->do_xlat = func;
- strNcpy(c->module, module, sizeof(c->module));
+ strlcpy(c->module, module, sizeof(c->module));
c->length = strlen(c->module);
c->instance = instance;
func = func; /* -Wunused */
- strNcpy(my_xlat.module, module, sizeof(my_xlat.module));
+ if (!module) return;
+
+ strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
my_xlat.length = strlen(my_xlat.module);
node = rbtree_find(xlat_root, &my_xlat);
* Decode an attribute name into a string.
*/
static void decode_attribute(const char **from, char **to, int freespace,
- int *open, REQUEST *request,
+ int *open_p, REQUEST *request,
RADIUS_ESCAPE_STRING func)
{
int do_length = 0;
char xlat_name[128];
char *xlat_string = NULL; /* can be large */
+ int free_xlat_string = FALSE;
const char *p;
char *q, *pa;
int found=0, retlen=0;
- int openbraces = *open;
- xlat_t *c;
+ int openbraces = *open_p;
+ const xlat_t *c;
+ int spaces = FALSE;
p = *from;
q = *to;
DEBUG("xlat: Invalid syntax in %s", *from);
/*
- * %{name} is a simple attribute reference, use it.
+ * %{name} is a simple attribute reference,
+ * or regex reference.
*/
} else if (*p == '}') {
openbraces--;
+ rad_assert(openbraces == *open_p);
+
p++;
- rad_assert(openbraces == *open);
+ xlat_string = xlat_name;
+ goto do_xlat;
- if ((retlen = xlat_packet(&xlat_inst[1], request, xlat_name,
- q, freespace, func)) > 0) {
- found = 1;
- }
} else if (p[1] == '-') { /* handle ':- */
p += 2;
- if ((retlen = xlat_packet(&xlat_inst[1], request, xlat_name,
- q, freespace, func)) > 0) {
- found = 1;
- }
-
+ xlat_string = xlat_name;
+ goto do_xlat;
+
} else { /* module name, followed by per-module string */
int stop = 0;
+ int delimitbrace = *open_p;
rad_assert(*p == ':');
p++; /* skip the ':' */
-
+
+ /*
+ * If there's a brace immediately following the colon,
+ * then we've chosen to delimite the per-module string,
+ * so keep track of that.
+ */
+ if (*p == '{') {
+ delimitbrace = openbraces;
+ openbraces++;
+ p++;
+ }
+
xlat_string = rad_malloc(strlen(p) + 1); /* always returns */
+ free_xlat_string = TRUE;
pa = xlat_string;
-
+
/*
* Copy over the rest of the string, which is per-module
* data.
*/
while (*p && !stop) {
switch(*p) {
+
/*
* What the heck is this supposed
* to be doing?
*pa++ = *p++;
break;
+ case ':':
+ if (!spaces && p[1] == '-') {
+ p += 2;
+ stop = 1;
+ break;
+ }
+
/*
* This is pretty hokey... we
* should use the functions in
case '}':
openbraces--;
- if (openbraces == *open) {
+ if (openbraces == delimitbrace) {
p++;
stop=1;
} else {
*pa++ = *p++;
}
break;
-
+
+ case ' ':
+ case '\t':
+ spaces = TRUE;
+ /* FALL-THROUGH */
+
default:
*pa++ = *p++;
break;
}
*pa = '\0';
-
+
+ /*
+ * Now check to see if we're at the end of the string
+ * we were sent. If we're not, check for :-
+ */
+ if (openbraces == delimitbrace) {
+ if (p[0] == ':' && p[1] == '-') {
+ p += 2;
+ }
+ }
+
/*
* Look up almost everything in the new tree of xlat
* functions. This makes it a little quicker...
*/
+ do_xlat:
if ((c = xlat_find(xlat_name)) != NULL) {
if (!c->internal) DEBUG("radius_xlat: Running registered xlat function of module %s for string \'%s\'",
c->module, xlat_string);
q += retlen;
- while((*p != '\0') && (openbraces > 0)) {
+ while((*p != '\0') && (openbraces > *open_p)) {
/*
* Handle escapes outside of the loop.
*/
p++; /* skip the character */
}
}
-
+
done:
- if (xlat_string) free(xlat_string);
+ if (free_xlat_string) free(xlat_string);
- *open = openbraces;
+ *open_p = openbraces;
*from = p;
*to = q;
}
*/
static int xlat_copy(char *out, int outlen, const char *in)
{
- int len = 0;
+ int freespace = outlen;
- while (*in) {
- /*
- * Truncate, if too much.
- */
- if (len >= outlen) {
- break;
- }
+ rad_assert(outlen > 0);
+ while ((*in) && (freespace > 1)) {
/*
* Copy data.
*
* FIXME: Do escaping of bad stuff!
*/
- *out = *in;
+ *(out++) = *(in++);
- out++;
- in++;
- len++;
+ freespace--;
}
-
*out = '\0';
- return len;
+
+ return (outlen - freespace); /* count does not include NUL */
}
/*
int radius_xlat(char *out, int outlen, const char *fmt,
REQUEST *request, RADIUS_ESCAPE_STRING func)
{
- int i, c,freespace;
+ int c, len, freespace;
const char *p;
char *q;
+ char *nl;
VALUE_PAIR *tmp;
struct tm *TM, s_TM;
char tmpdt[40]; /* For temporary storing of dates */
break;
case 'd': /* request day */
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%d",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%d", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'f': /* Framed IP address */
break;
case 'l': /* request timestamp */
snprintf(tmpdt, sizeof(tmpdt), "%lu",
- (unsigned long) request->timestamp);
- strNcpy(q,tmpdt,freespace);
+ (unsigned long) request->received.tv_sec);
+ strlcpy(q,tmpdt,freespace);
q += strlen(q);
p++;
break;
case 'm': /* request month */
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%m",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%m", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'n': /* NAS IP address */
p++;
break;
case 't': /* request timestamp */
- CTIME_R(&request->timestamp, q, freespace);
- q = strchr(q, '\n');
- if (q) {
- *q = '\0';
- } else {
- q += strlen(q);
- }
+ CTIME_R(&request->timestamp, tmpdt, sizeof(tmpdt));
+ nl = strchr(tmpdt, '\n');
+ if (nl) *nl = '\0';
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
p++;
break;
case 'u': /* User name */
p++;
break;
case 'A': /* radacct_dir */
- strNcpy(q,radacct_dir,freespace-1);
+ strlcpy(q,radacct_dir,freespace);
q += strlen(q);
p++;
break;
case 'C': /* ClientName */
- strNcpy(q,client_name(request->packet->src_ipaddr),freespace-1);
+ strlcpy(q,client_name_old(&request->packet->src_ipaddr),freespace);
q += strlen(q);
p++;
break;
case 'D': /* request date */
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%Y%m%d",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%Y%m%d", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'H': /* request hour */
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%H",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%H", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'L': /* radlog_dir */
- strNcpy(q,radlog_dir,freespace-1);
+ strlcpy(q,radlog_dir,freespace);
q += strlen(q);
p++;
break;
p++;
break;
case 'R': /* radius_dir */
- strNcpy(q,radius_dir,freespace-1);
+ strlcpy(q,radius_dir,freespace);
q += strlen(q);
p++;
break;
case 'S': /* request timestamp in SQL format*/
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%Y-%m-%d %H:%M:%S",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%Y-%m-%d %H:%M:%S", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'T': /* request timestamp */
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%Y-%m-%d-%H.%M.%S.000000",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%Y-%m-%d-%H.%M.%S.000000", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'U': /* Stripped User name */
p++;
break;
case 'V': /* Request-Authenticator */
- if (request->packet->verified)
- strNcpy(q,"Verified",freespace-1);
- else
- strNcpy(q,"None",freespace-1);
+ strlcpy(q,"Verified",freespace);
q += strlen(q);
p++;
break;
case 'Y': /* request year */
TM = localtime_r(&request->timestamp, &s_TM);
- strftime(tmpdt,sizeof(tmpdt),"%Y",TM);
- strNcpy(q,tmpdt,freespace);
- q += strlen(q);
+ len = strftime(tmpdt, sizeof(tmpdt), "%Y", TM);
+ if (len > 0) {
+ strlcpy(q, tmpdt, freespace);
+ q += strlen(q);
+ }
p++;
break;
case 'Z': /* Full request pairs except password */
tmp = request->packet->vps;
while (tmp && (freespace > 3)) {
- if (tmp->attribute != PW_PASSWORD) {
+ if (tmp->attribute != PW_USER_PASSWORD) {
*q++ = '\t';
- i = vp_prints(q,freespace-2,tmp);
- q += i;
- freespace -= (i+2);
+ len = vp_prints(q, freespace - 2, tmp);
+ q += len;
+ freespace -= (len + 2);
*q++ = '\n';
}
tmp = tmp->next;