]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow time_delta to be _unsigned_ when we encode it in the network
authorAlan T. DeKok <aland@freeradius.org>
Wed, 1 Sep 2021 13:53:08 +0000 (09:53 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 1 Sep 2021 13:53:08 +0000 (09:53 -0400)
e.g. for RADIUS, with Session-Timeout

src/lib/util/dict.h
src/lib/util/dict_tokenize.c
src/lib/util/value.c

index ce949be38b7a66ffcf2c180389514978072db389..7525300ee8fa2ab97d541729478c6d8ecf37479c 100644 (file)
@@ -91,6 +91,8 @@ typedef struct {
 
        unsigned int            virtual : 1;                    //!< for dynamic expansion
 
+       unsigned int            is_signed : 1;                  //!< hackity hack for dates and time deltas
+
        /*
         *      @todo - if we want to clean these fields up, make
         *      "subtype" and "type_size" both 4-bit bitfields.  That
index c9fdb50b759cc3dfa97d6ef5fd8cecf607b0048c..130d1359b3068b702b6ba9d72256a3dd52d261a6 100644 (file)
@@ -408,6 +408,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
 
                                case FR_TYPE_INT16:
                                        if (type == FR_TYPE_DATE) goto unknown_type;
+                                       flags->is_signed = true;
                                        FALL_THROUGH;
 
                                case FR_TYPE_UINT16:
@@ -416,6 +417,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
 
                                case FR_TYPE_INT32:
                                        if (type == FR_TYPE_DATE) goto unknown_type;
+                                       flags->is_signed = true;
                                        FALL_THROUGH;
 
                                case FR_TYPE_UINT32:
@@ -424,6 +426,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
 
                                case FR_TYPE_INT64:
                                        if (type == FR_TYPE_DATE) goto unknown_type;
+                                       flags->is_signed = true;
                                        FALL_THROUGH;
 
                                case FR_TYPE_UINT64:
index 5871ba0edcea116c9c4001e55d28a18652da37cf..f19ef33e8ee2762781cdfba9dfac86451068c055 100644 (file)
@@ -1407,7 +1407,7 @@ ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
                if (!value->enumv) {
                        goto delta_seconds;
 
-               } else switch (value->enumv->flags.flag_time_res) {
+               } switch (value->enumv->flags.flag_time_res) {
                delta_seconds:
                case FR_TIME_RES_SEC:
                        date = fr_time_delta_to_sec(value->vb_time_delta);
@@ -1432,34 +1432,62 @@ ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
                if (!value->enumv) {
                        goto delta_size4;
 
-               } else switch (value->enumv->flags.length) {
-               case 2:
-                       if (date < INT16_MIN) {
-                               date = INT16_MIN;
-                       } else if (date > INT16_MAX) {
-                               date = INT16_MAX;
-                       }
-                       FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t)date);
-                       break;
+               } else if (value->enumv->flags.is_signed) {
+                       switch (value->enumv->flags.length) {
+                       case 2:
+                               if (date < INT16_MIN) {
+                                       date = INT16_MIN;
+                               } else if (date > INT16_MAX) {
+                                       date = INT16_MAX;
+                               }
+                               FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t)date);
+                               break;
 
-               delta_size4:
-               case 4:
-                       if (date < INT32_MIN) {
-                               date = INT32_MIN;
-                       } else if (date > INT32_MAX) {
-                               date = INT32_MAX;
+                       delta_size4:
+                       case 4:
+                               if (date < INT32_MIN) {
+                                       date = INT32_MIN;
+                               } else if (date > INT32_MAX) {
+                                       date = INT32_MAX;
+                               }
+                               FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t)date);
+                               break;
+
+                       case 8:
+                               FR_DBUFF_IN_RETURN(&work_dbuff, (int64_t)date);
+                               break;
+
+                       default:
+                               goto unsupported;
                        }
-                       FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t)date);
-                       break;
+               } else {        /* time delta is unsigned! */
+                       switch (value->enumv->flags.length) {
+                       case 2:
+                               if (date < 0) {
+                                       date = 0;
+                               } else if (date > UINT16_MAX) {
+                                       date = UINT16_MAX;
+                               }
+                               FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t)date);
+                               break;
 
-               case 8:
-                       FR_DBUFF_IN_RETURN(&work_dbuff, (int64_t)date);
-                       break;
+                       case 4:
+                               if (date < 0) {
+                                       date = 0;
+                               } else if (date > UINT32_MAX) {
+                                       date = UINT32_MAX;
+                               }
+                               FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)date);
+                               break;
 
-               default:
-                       goto unsupported;
-               }
+                       case 8:
+                               FR_DBUFF_IN_RETURN(&work_dbuff, (uint64_t)date);
+                               break;
 
+                       default:
+                               goto unsupported;
+                       }
+               }
        }
                break;
 
@@ -1754,7 +1782,22 @@ ssize_t fr_value_box_from_network_dbuff(TALLOC_CTX *ctx,
 
                dst->enumv = enumv;
 
-               FR_DBUFF_OUT_UINT64V_RETURN(&date, &work_dbuff, length);
+               if (enumv && enumv->flags.is_signed) {
+                       FR_DBUFF_OUT_INT64V_RETURN(&date, &work_dbuff, length);
+               } else {
+                       uint64_t tmp;
+
+                       /*
+                        *      Else it's an unsigned time delta, but
+                        *      we do have to clamp it at the max
+                        *      value for a signed 64-bit integer.
+                        */
+                       FR_DBUFF_OUT_UINT64V_RETURN(&tmp, &work_dbuff, length);
+
+                       if (tmp > INT64_MAX) tmp = INT64_MAX;
+
+                       date = tmp;
+               }
 
                switch (precision) {
                default: