Signed / unsigned fixes and function prototypes
[freeradius.git] / src / main / valuepair.c
index a233147..50f4cb6 100644 (file)
@@ -46,8 +46,8 @@ RCSID("$Id$")
 #endif
 
 struct cmp {
-       int attribute;
-       int otherattr;
+       unsigned int attribute;
+       unsigned int otherattr;
        void *instance; /* module instance */
        RAD_COMPARE_FUNC compare;
        struct cmp *next;
@@ -80,12 +80,19 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
                /*
                 *      Include substring matches.
                 */
-               regcomp(&reg, (char *)check->vp_strvalue,
-                       REG_EXTENDED);
+               compare = regcomp(&reg, check->vp_strvalue, REG_EXTENDED);
+               if (compare != 0) {
+                       char buffer[256];
+                       regerror(compare, &reg, buffer, sizeof(buffer));
+
+                       RDEBUG("Invalid regular expression %s: %s",
+                              check->vp_strvalue, buffer);
+                       return -1;
+               }
                compare = regexec(&reg, value,  REQUEST_MAX_REGEX + 1,
                                  rxmatch, 0);
                regfree(&reg);
-               
+
                /*
                 *      Add %{0}, %{1}, etc.
                 */
@@ -105,21 +112,21 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
                                        free(p);
                                        continue;
                                }
-                               
+
                                /*
                                 *      No previous match
                                 *      to delete, stop.
                                 */
                                break;
                        }
-                       
+
                        /*
                         *      Copy substring into buffer.
                         */
                        memcpy(buffer, value + rxmatch[i].rm_so,
                               rxmatch[i].rm_eo - rxmatch[i].rm_so);
                        buffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';
-                       
+
                        /*
                         *      Copy substring, and add it to
                         *      the request.
@@ -138,7 +145,7 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
        }
 
        if (check->operator == T_OP_REG_NE) {
-               int i, compare;
+               int compare;
                regex_t reg;
                char name[1024];
                char value[1024];
@@ -150,12 +157,20 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
                /*
                 *      Include substring matches.
                 */
-               regcomp(&reg, (char *)check->vp_strvalue,
-                       REG_EXTENDED);
+               compare = regcomp(&reg, (char *)check->vp_strvalue,
+                                 REG_EXTENDED);
+               if (compare != 0) {
+                       char buffer[256];
+                       regerror(compare, &reg, buffer, sizeof(buffer));
+
+                       RDEBUG("Invalid regular expression %s: %s",
+                              check->vp_strvalue, buffer);
+                       return -1;
+               }
                compare = regexec(&reg, value,  REQUEST_MAX_REGEX + 1,
                                  rxmatch, 0);
                regfree(&reg);
-               
+
                if (compare != 0) return 0;
                return -1;
 
@@ -163,6 +178,15 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
 #endif
 
        /*
+        *      Tagged attributes are equal if and only if both the
+        *      tag AND value match.
+        */
+       if (check->flags.has_tag) {
+               ret = ((int) vp->flags.tag) - ((int) check->flags.tag);
+               if (ret != 0) return ret;
+       }
+
+       /*
         *      Not a regular expression, compare the types.
         */
        switch(check->type) {
@@ -182,13 +206,8 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
                                     vp->length);
                        break;
                case PW_TYPE_STRING:
-                       if (check->flags.caseless) {
-                               ret = strcasecmp((char *)vp->vp_strvalue,
-                                                (char *)check->vp_strvalue);
-                       } else {
-                               ret = strcmp((char *)vp->vp_strvalue,
-                                            (char *)check->vp_strvalue);
-                       }
+                       ret = strcmp((char *)vp->vp_strvalue,
+                                    (char *)check->vp_strvalue);
                        break;
                case PW_TYPE_BYTE:
                case PW_TYPE_SHORT:
@@ -205,12 +224,12 @@ int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
                        ret = memcmp(&vp->vp_ipv6addr, &check->vp_ipv6addr,
                                     sizeof(vp->vp_ipv6addr));
                        break;
-                       
+
                case PW_TYPE_IPV6PREFIX:
                        ret = memcmp(&vp->vp_ipv6prefix, &check->vp_ipv6prefix,
                                     sizeof(vp->vp_ipv6prefix));
                        break;
-               
+
                case PW_TYPE_IFID:
                        ret = memcmp(&vp->vp_ifid, &check->vp_ifid,
                                     sizeof(vp->vp_ifid));
@@ -247,9 +266,11 @@ int radius_callback_compare(REQUEST *req, VALUE_PAIR *request,
         *      FIXME: use new RB-Tree code.
         */
        for (c = cmp; c; c = c->next)
-               if (c->attribute == check->attribute)
+               if ((c->attribute == check->attribute) &&
+                   (check->vendor == 0)) {
                        return (c->compare)(c->instance, req, request, check,
                                check_pairs, reply_pairs);
+               }
 
        if (!request) return -1; /* doesn't exist, don't compare it */
 
@@ -258,9 +279,26 @@ int radius_callback_compare(REQUEST *req, VALUE_PAIR *request,
 
 
 /*
+ *     Find a comparison function for two attributes.
+ */
+int radius_find_compare(unsigned int attribute)
+{
+       struct cmp *c;
+
+       for (c = cmp; c; c = c->next) {
+               if (c->attribute == attribute) {
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+
+/*
  *     See what attribute we want to compare with.
  */
-static int otherattr(int attr)
+static int otherattr(unsigned int attr)
 {
        struct cmp      *c;
 
@@ -285,7 +323,7 @@ static int otherattr(int attr)
  *     For example, PW_GROUP in a check item needs to be compared
  *     with PW_USER_NAME in the incoming request.
  */
-int paircompare_register(int attr, int compare_attr, RAD_COMPARE_FUNC fun, void *instance)
+int paircompare_register(unsigned int attr, int compare_attr, RAD_COMPARE_FUNC fun, void *instance)
 {
        struct cmp      *c;
 
@@ -306,7 +344,7 @@ int paircompare_register(int attr, int compare_attr, RAD_COMPARE_FUNC fun, void
 /*
  *     Unregister a function.
  */
-void paircompare_unregister(int attr, RAD_COMPARE_FUNC fun)
+void paircompare_unregister(unsigned int attr, RAD_COMPARE_FUNC fun)
 {
        struct cmp      *c, *last;
 
@@ -377,7 +415,12 @@ int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR
                         *      This hack makes CHAP-Password work..
                         */
                        case PW_USER_PASSWORD:
-                               if (pairfind(request, PW_USER_PASSWORD) == NULL) {
+                               if (check_item->operator == T_OP_CMP_EQ) {
+                                       DEBUG("WARNING: Found User-Password == \"...\".");
+                                       DEBUG("WARNING: Are you sure you don't mean Cleartext-Password?");
+                                       DEBUG("WARNING: See \"man rlm_pap\" for more information.");
+                               }
+                               if (pairfind(request, PW_USER_PASSWORD, 0) == NULL) {
                                        continue;
                                }
                                break;
@@ -392,7 +435,7 @@ int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR
        try_again:
                if (other >= 0) {
                        for (; auth_item != NULL; auth_item = auth_item->next) {
-                               if (auth_item->attribute == other || other == 0)
+                         if (auth_item->attribute == (unsigned int) other || other == 0)
                                        break;
                        }
                }
@@ -406,7 +449,7 @@ int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR
                         *      to not find it, then we succeeded.
                         */
                        if (check_item->operator == T_OP_CMP_FALSE)
-                               return 0;
+                               continue;
                        else
                                return -1;
                }
@@ -552,7 +595,7 @@ void pairxlatmove(REQUEST *req, VALUE_PAIR **to, VALUE_PAIR **from)
                        pairparsevalue(i, buffer);
                }
 
-               found = pairfind(*to, i->attribute);
+               found = pairfind(*to, i->attribute, i->vendor);
                switch (i->operator) {
 
                        /*
@@ -564,7 +607,7 @@ void pairxlatmove(REQUEST *req, VALUE_PAIR **to, VALUE_PAIR **from)
                                if (!i->vp_strvalue[0] ||
                                    (strcmp((char *)found->vp_strvalue,
                                            (char *)i->vp_strvalue) == 0)){
-                                       pairdelete(to, found->attribute);
+                                 pairdelete(to, found->attribute, found->vendor);
 
                                        /*
                                         *      'tailto' may have been
@@ -602,6 +645,7 @@ void pairxlatmove(REQUEST *req, VALUE_PAIR **to, VALUE_PAIR **from)
                                vp = found->next;
                                memcpy(found, i, sizeof(*found));
                                found->next = vp;
+                               tailfrom = i;
                                continue;
                        }
                        break;
@@ -650,20 +694,64 @@ void pairxlatmove(REQUEST *req, VALUE_PAIR **to, VALUE_PAIR **from)
  *     it causes the server to exit!
  */
 VALUE_PAIR *radius_paircreate(REQUEST *request, VALUE_PAIR **vps,
-                             int attribute, int type)
+                             unsigned int attribute, unsigned int vendor, int type)
 {
        VALUE_PAIR *vp;
 
        request = request;      /* -Wunused */
 
-       vp = paircreate(attribute, type);
+       vp = paircreate(attribute, vendor, type);
        if (!vp) {
                radlog(L_ERR, "No memory!");
                rad_assert("No memory" == NULL);
                _exit(1);
        }
 
-       pairadd(vps, vp);
+       if (vps) pairadd(vps, vp);
 
        return vp;
 }
+
+/*
+ *     Create a pair, and add it to a particular list of VPs
+ *
+ *     Note that this function ALWAYS returns.  If we're OOM, then
+ *     it causes the server to exit!
+ */
+VALUE_PAIR *radius_pairmake(REQUEST *request, VALUE_PAIR **vps,
+                           const char *attribute, const char *value,
+                           int operator)
+{
+       VALUE_PAIR *vp;
+
+       request = request;      /* -Wunused */
+
+       vp = pairmake(attribute, value, operator);
+       if (!vp) return NULL;
+
+       if (vps) pairadd(vps, vp);
+
+       return vp;
+}
+
+void debug_pair(VALUE_PAIR *vp)
+{
+       if (!vp || !debug_flag || !fr_log_fp) return;
+
+       fputc('\t', fr_log_fp);
+       vp_print(fr_log_fp, vp);
+       fputc('\n', fr_log_fp);
+}
+
+void debug_pair_list(VALUE_PAIR *vp)
+{
+       if (!vp || !debug_flag || !fr_log_fp) return;
+
+       while (vp) {
+               fputc('\t', fr_log_fp);
+               vp_print(fr_log_fp, vp);
+               fputc('\n', fr_log_fp);
+               vp = vp->next;
+       }
+       fflush(fr_log_fp);
+}