The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
serialize.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 735ca3fe9d000d29d3187c7adba09d61ff9b3d1c $
19  * @file serialize.c
20  * @brief Serialize and deserialise cache entries.
21  *
22  * @author Arran Cudbard-Bell
23  * @copyright 2014 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  * @copyright 2014 The FreeRADIUS server project
25  */
26 RCSID("$Id: 735ca3fe9d000d29d3187c7adba09d61ff9b3d1c $")
27 
28 #include "rlm_cache.h"
29 #include "serialize.h"
30 
31 /** Serialize a cache entry as a humanly readable string
32  *
33  * @param ctx to alloc new string in. Should be a talloc pool a little bigger
34  * than the maximum serialized size of the entry.
35  * @param out Where to write pointer to serialized cache entry.
36  * @param c Cache entry to serialize.
37  * @return
38  * - 0 on success.
39  * - -1 on failure.
40  */
41 int cache_serialize(TALLOC_CTX *ctx, char **out, rlm_cache_entry_t const *c)
42 {
43  TALLOC_CTX *value_pool = NULL;
44  char attr[256]; /* Attr name buffer */
45  map_t *map = NULL;
46 
47  char *to_store = NULL;
48 
49  to_store = talloc_typed_asprintf(ctx, "Cache-Expires = %pV\nCache-Created = %pV\n",
51  if (!to_store) return -1;
52 
53  /*
54  * It's valid to have an empty cache entry (save allocing the pairs pool)
55  */
56  if (map_list_empty(&c->maps)) goto finish;
57 
58  value_pool = talloc_pool(ctx, 512);
59  if (!value_pool) {
60  error:
61  talloc_free(to_store);
62  talloc_free(value_pool);
63  return -1;
64  }
65 
66  while ((map = map_list_next(&c->maps, map))) {
67  char *value;
68  ssize_t slen;
69 
70  slen = tmpl_print(&FR_SBUFF_OUT(attr, sizeof(attr)), map->lhs, TMPL_ATTR_REF_PREFIX_NO, NULL);
71  if (slen < 0) {
72  fr_strerror_printf("Serialized attribute too long. Must be < " STRINGIFY(sizeof(attr)) " "
73  "bytes, needed %zu additional bytes", (size_t)(slen * -1));
74  goto error;
75  }
76 
78  if (!value) goto error;
79 
80  to_store = talloc_asprintf_append_buffer(to_store, "%s %s %s\n", attr,
81  fr_table_str_by_value(fr_tokens_table, map->op, "<INVALID>"),
82  value);
83  if (!to_store) goto error;
84  }
85 finish:
86  talloc_free(value_pool);
87  *out = to_store;
88 
89  return 0;
90 }
91 
92 /** Converts a serialized cache entry back into a structure
93  *
94  * @param[in] c Cache entry to populate (should already be allocated)
95  * @param[in] dict to use for unqualified attributes.
96  * @param[in] in String representation of cache entry.
97  * @param[in] inlen Length of string. May be < 0 in which case strlen will be
98  * used to calculate the length of the string.
99  * @return
100  * - 0 on success.
101  * - -1 on failure.
102  */
104 {
105  char *p, *q;
106 
107  if (inlen < 0) inlen = strlen(in);
108 
109  p = in;
110 
111  while (((size_t)(p - in)) < (size_t)inlen) {
112  map_t *map = NULL;
113  tmpl_rules_t parse_rules = {
114  .attr = {
115  .dict_def = dict,
116  .list_def = request_attr_request,
117  .prefix = TMPL_ATTR_REF_PREFIX_NO
118  }
119  };
120 
121  q = strchr(p, '\n');
122  if (!q) break; /* List should also be terminated with a \n */
123  *q = '\0';
124 
125  if (map_afrom_attr_str(c, &map, p, &parse_rules, &parse_rules) < 0) {
126  fr_strerror_printf("Failed parsing pair: %s", p);
127  error:
128  talloc_free(map);
129  return -1;
130  }
131 
132  if (!tmpl_is_attr(map->lhs)) {
133  fr_strerror_printf("Pair left hand side \"%s\" parsed as %s, needed attribute. "
134  "Check local dictionaries", map->lhs->name,
135  tmpl_type_to_str(map->lhs->type));
136  goto error;
137  }
138 
139  if (!tmpl_is_data_unresolved(map->rhs)) {
140  fr_strerror_printf("Pair right hand side \"%s\" parsed as %s, needed literal. "
141  "Check serialized data quoting", map->rhs->name,
142  tmpl_type_to_str(map->rhs->type));
143  goto error;
144  }
145 
146  /*
147  * Convert literal to a type appropriate for the VP.
148  */
149  if (tmpl_cast_in_place(map->rhs, tmpl_attr_tail_da(map->lhs)->type, tmpl_attr_tail_da(map->lhs)) < 0) goto error;
150 
151  /*
152  * Pull out the special attributes, and set the
153  * relevant cache entry fields.
154  */
155  if (fr_dict_attr_is_top_level(tmpl_attr_tail_da(map->lhs))) switch (tmpl_attr_tail_da(map->lhs)->attr) {
156  case FR_CACHE_CREATED:
157  c->created = tmpl_value(map->rhs)->vb_date;
158  talloc_free(map);
159  goto next;
160 
161  case FR_CACHE_EXPIRES:
162  c->expires = tmpl_value(map->rhs)->vb_date;
163  talloc_free(map);
164  goto next;
165 
166  default:
167  break;
168  }
169 
170  MAP_VERIFY(map);
171 
172  /* It's not a special attribute, add it to the map list */
173  map_list_insert_tail(&c->maps, map);
174 
175  next:
176  p = q + 1;
177  }
178 
179  return 0;
180 }
static fr_dict_t * dict
Definition: fuzzer.c:46
#define RCSID(id)
Definition: build.h:481
#define STRINGIFY(x)
Definition: build.h:195
next
Definition: dcursor.h:178
static bool fr_dict_attr_is_top_level(fr_dict_attr_t const *da)
Return true if this attribute is parented directly off the dictionary root.
Definition: dict.h:754
static fr_slen_t in
Definition: dict.h:821
Test enumeration values.
Definition: dict_test.h:92
int map_afrom_attr_str(TALLOC_CTX *ctx, map_t **out, char const *vp_str, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
Convert a value pair string to valuepair map.
Definition: map.c:1319
talloc_free(reap)
#define MAP_VERIFY(_x)
Definition: map.h:108
@ TMPL_ATTR_REF_PREFIX_NO
Attribute refs have no '&' prefix.
Definition: merged_model.c:230
fr_slen_t tmpl_print(fr_sbuff_t *out, tmpl_t const *vpt, tmpl_attr_prefix_t ar_prefix, fr_sbuff_escape_rules_t const *e_rules)
Definition: merged_model.c:237
long int ssize_t
Definition: merged_model.c:24
fr_dict_attr_t const * request_attr_request
Definition: request.c:45
map_list_t maps
Head of the maps list.
Definition: rlm_cache.h:78
fr_unix_time_t created
When the entry was created.
Definition: rlm_cache.h:75
fr_unix_time_t expires
When the entry expires.
Definition: rlm_cache.h:76
Definition: rlm_cache.h:72
#define FR_SBUFF_OUT(_start, _len_or_end)
int cache_serialize(TALLOC_CTX *ctx, char **out, rlm_cache_entry_t const *c)
Serialize a cache entry as a humanly readable string.
Definition: serialize.c:41
int cache_deserialize(rlm_cache_entry_t *c, fr_dict_t const *dict, char *in, ssize_t inlen)
Converts a serialized cache entry back into a structure.
Definition: serialize.c:103
#define tmpl_value(_tmpl)
Definition: tmpl.h:948
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition: tmpl.h:812
#define tmpl_is_attr(vpt)
Definition: tmpl.h:213
int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv))
Convert tmpl_t of type TMPL_TYPE_DATA_UNRESOLVED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specifie...
#define tmpl_is_data_unresolved(vpt)
Definition: tmpl.h:222
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition: tmpl.h:344
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
Definition: tmpl.h:645
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
Value pair map.
Definition: map.h:77
fr_token_t op
The operator that controls insertion of the dst attribute.
Definition: map.h:82
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition: map.h:78
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition: map.h:79
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition: tmpl.h:285
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:772
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:492
fr_table_num_ordered_t const fr_tokens_table[]
Definition: token.c:33
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:997
static fr_slen_t static e_rules fr_slen_t fr_value_box_aprint_quoted(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_token_t quote) 1(fr_value_box_print_quoted
static size_t char ** out
Definition: value.h:997
#define fr_box_date(_val)
Definition: value.h:324