KFW Network Identity Manager (Beta 2)
[krb5.git] / src / windows / identity / kcreddb / buf.c
1 /*\r
2  * Copyright (c) 2005 Massachusetts Institute of Technology\r
3  *\r
4  * Permission is hereby granted, free of charge, to any person\r
5  * obtaining a copy of this software and associated documentation\r
6  * files (the "Software"), to deal in the Software without\r
7  * restriction, including without limitation the rights to use, copy,\r
8  * modify, merge, publish, distribute, sublicense, and/or sell copies\r
9  * of the Software, and to permit persons to whom the Software is\r
10  * furnished to do so, subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be\r
13  * included in all copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
22  * SOFTWARE.\r
23  */\r
24 \r
25 /* $Id$ */\r
26 \r
27 #include<kcreddbinternal.h>\r
28 #include<assert.h>\r
29 \r
30 void kcdb_buf_new(kcdb_buf * buf, khm_size n_fields)\r
31 {\r
32     buf->buffer = PMALLOC(KCDB_BUF_CBBUF_INITIAL);\r
33     buf->cb_buffer = KCDB_BUF_CBBUF_INITIAL;\r
34     buf->cb_used = 0;\r
35 \r
36     if(n_fields == KCDB_BUF_DEFAULT)\r
37         n_fields = KCDB_BUF_FIELDS_INITIAL;\r
38 \r
39     assert(n_fields < KCDB_BUF_MAX_SLOTS);\r
40 \r
41     buf->n_fields = n_fields;\r
42     buf->nc_fields = UBOUNDSS(n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);\r
43     buf->fields = PMALLOC(sizeof(buf->fields[0]) * buf->n_fields);\r
44     ZeroMemory(buf->fields, sizeof(buf->fields[0]) * buf->n_fields);\r
45 }\r
46 \r
47 void kcdb_buf_delete(kcdb_buf * buf)\r
48 {\r
49     buf->cb_buffer = 0;\r
50     buf->cb_used = 0;\r
51     if(buf->buffer)\r
52         PFREE(buf->buffer);\r
53     buf->buffer = NULL;\r
54 \r
55     buf->n_fields = 0;\r
56     buf->nc_fields = 0;\r
57     if(buf->fields)\r
58         PFREE(buf->fields);\r
59     buf->fields = NULL;\r
60 }\r
61 \r
62 static void kcdb_buf_assert_size(kcdb_buf * buf, khm_size cbsize)\r
63 {\r
64     khm_size new_size;\r
65     void * new_buf;\r
66 \r
67     /* should be less than or equal to the max signed 32 bit int */\r
68     assert(cbsize <= KHM_INT32_MAX);\r
69     if(cbsize <= buf->cb_buffer)\r
70         return;\r
71 \r
72     new_size = UBOUNDSS(cbsize, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH);\r
73 \r
74     assert(new_size > buf->cb_buffer && new_size > 0);\r
75 \r
76     new_buf = PMALLOC(new_size);\r
77     assert(new_buf != NULL);\r
78 \r
79     memcpy(new_buf, buf->buffer, buf->cb_used);\r
80     PFREE(buf->buffer);\r
81     buf->buffer = new_buf;\r
82 }\r
83 \r
84 void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize)\r
85 {\r
86     khm_size cbnew;\r
87     khm_ssize cbdelta;\r
88     khm_size cbold;\r
89     kcdb_buf_field * f;\r
90 \r
91     cbnew = UBOUND32(cbsize);\r
92 \r
93     assert(slot <= KCDB_BUF_APPEND);\r
94 \r
95     if(slot == KCDB_BUF_APPEND) {\r
96         slot = kcdb_buf_slot_by_id(buf, id);\r
97         if(slot == KCDB_BUF_INVALID_SLOT)\r
98             slot = buf->n_fields;\r
99     }\r
100 \r
101     assert(slot < KCDB_BUF_MAX_SLOTS);\r
102 \r
103     if((slot + 1) > buf->nc_fields) {\r
104         kcdb_buf_field * nf;\r
105         khm_size ns;\r
106 \r
107         ns = UBOUNDSS((slot + 1), KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);\r
108 \r
109         nf = PMALLOC(sizeof(buf->fields[0]) * ns);\r
110         memcpy(nf, buf->fields, sizeof(buf->fields[0]) * buf->n_fields);\r
111 \r
112         if(ns > buf->n_fields)\r
113             memset(&(nf[buf->n_fields]), 0, sizeof(buf->fields[0]) * (ns - buf->n_fields));\r
114 \r
115         PFREE(buf->fields);\r
116         buf->fields = nf;\r
117         buf->nc_fields = ns;\r
118     }\r
119 \r
120     if((slot + 1) > buf->n_fields)\r
121         buf->n_fields = slot + 1;\r
122 \r
123     f = &(buf->fields[slot]);\r
124 \r
125     if(f->flags & KCDB_CREDF_FLAG_ALLOCD) {\r
126         /* there's already an allocation.  we have to resize it to\r
127            accomodate the new size */\r
128         cbold = UBOUND32(f->cbsize);\r
129         /* demote before substraction */\r
130         cbdelta = ((khm_ssize) cbnew) - (khm_ssize) cbold;\r
131 \r
132         if(cbnew > cbold) {\r
133             kcdb_buf_assert_size(buf, buf->cb_used + cbdelta);\r
134         }\r
135 \r
136         if(buf->cb_used > f->offset + cbold) {\r
137             int i;\r
138 \r
139             memmove(\r
140                 ((BYTE *) buf->buffer) + (f->offset + cbnew),\r
141                 ((BYTE *) buf->buffer) + (f->offset + cbold),\r
142                 buf->cb_used - (f->offset + cbold));\r
143 \r
144             for(i=0; i < (int) buf->n_fields; i++) {\r
145                 if(i != slot && \r
146                     (buf->fields[i].flags & KCDB_CREDF_FLAG_ALLOCD) &&\r
147                     buf->fields[i].offset > f->offset) \r
148                 {\r
149                     buf->fields[i].offset = \r
150                         (khm_ui_4)(((khm_ssize) buf->fields[i].offset) + cbdelta);\r
151                 }\r
152             }\r
153         }\r
154 \r
155         /* demote integer before adding signed quantity */\r
156         buf->cb_used = (khm_size)(((khm_ssize) buf->cb_used) + cbdelta);\r
157 \r
158         f->cbsize = (khm_ui_4) cbsize;\r
159 \r
160     } else {\r
161         kcdb_buf_assert_size(buf, buf->cb_used + cbnew);\r
162         f->offset = (khm_ui_4) buf->cb_used;\r
163         f->cbsize = (khm_ui_4) cbsize;\r
164         buf->cb_used += cbnew;\r
165     }\r
166 \r
167     if(cbsize == 0) {\r
168         f->flags &= ~KCDB_CREDF_FLAG_ALLOCD;\r
169         f->flags &= ~KCDB_CREDF_FLAG_DATA;\r
170         f->id = KCDB_BUFF_ID_INVALID;\r
171     } else {\r
172         f->flags |= KCDB_CREDF_FLAG_ALLOCD;\r
173         f->id = id;\r
174     }\r
175 }\r
176 \r
177 void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src)\r
178 {\r
179     khm_size cb_buf;\r
180     khm_size nc_fields;\r
181 \r
182     cb_buf = UBOUNDSS(src->cb_used, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH);\r
183 #if 0\r
184         /* replaced by UBOUNDSS() above */\r
185         (src->cb_used <= kcdb_cred_initial_size)? kcdb_cred_initial_size:\r
186         kcdb_cred_initial_size + \r
187             (((src->cb_used - (kcdb_cred_initial_size + 1)) / kcdb_cred_growth_factor + 1) * kcdb_cred_growth_factor);\r
188 #endif\r
189 \r
190     kcdb_buf_delete(dest);\r
191 \r
192     dest->cb_buffer = cb_buf;\r
193     dest->cb_used = src->cb_used;\r
194     dest->buffer = PMALLOC(cb_buf);\r
195     memcpy(dest->buffer, src->buffer, src->cb_used);\r
196 \r
197     nc_fields = UBOUNDSS(src->n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH);\r
198     dest->nc_fields = nc_fields;\r
199     dest->n_fields = src->n_fields;\r
200     dest->fields = PMALLOC(nc_fields * sizeof(dest->fields[0]));\r
201     memcpy(dest->fields, src->fields, src->n_fields * sizeof(dest->fields[0]));\r
202     if(dest->n_fields < dest->nc_fields)\r
203         memset(&(dest->fields[dest->n_fields]), 0, (src->nc_fields - src->n_fields) * sizeof(dest->fields[0]));\r
204 }\r
205 \r
206 void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src)\r
207 {\r
208     void * dest;\r
209     kcdb_buf_alloc(buf, slot, id, cb_src);\r
210     if(slot == KCDB_BUF_APPEND) {\r
211         slot = kcdb_buf_slot_by_id(buf, id);\r
212         if(slot == KCDB_BUF_INVALID_SLOT) {\r
213 #ifdef DEBUG\r
214             assert(FALSE);\r
215 #else\r
216             return;\r
217 #endif\r
218         }\r
219     }\r
220     if(kcdb_buf_exist(buf, slot)) {\r
221         dest = kcdb_buf_get(buf, slot);\r
222         memcpy(dest, src, cb_src);\r
223 \r
224         buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA;\r
225     }\r
226 }\r
227 \r
228 int kcdb_buf_exist(kcdb_buf * buf, khm_size slot)\r
229 {\r
230     if(slot >= buf->n_fields)\r
231         return 0;\r
232     return (buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD);\r
233 }\r
234 \r
235 int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot)\r
236 {\r
237     if(slot >= buf->n_fields)\r
238         return 0;\r
239     return (buf->fields[slot].flags & KCDB_CREDF_FLAG_DATA);\r
240 }\r
241 \r
242 void * kcdb_buf_get(kcdb_buf * buf, khm_size slot)\r
243 {\r
244     if(slot >= buf->n_fields || \r
245         !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))\r
246         return NULL;\r
247     return (((BYTE *) buf->buffer) + buf->fields[slot].offset);\r
248 }\r
249 \r
250 khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot)\r
251 {\r
252     if(slot >= buf->n_fields || \r
253         !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))\r
254         return 0;\r
255     return (buf->fields[slot].cbsize);\r
256 }\r
257 \r
258 void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot)\r
259 {\r
260     if(slot >= buf->n_fields || \r
261         !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD))\r
262         return;\r
263 \r
264     (buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA);\r
265 }\r
266 \r
267 khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id)\r
268 {\r
269     int i;\r
270 \r
271     for(i=0; i < (int) buf->n_fields; i++) {\r
272         if(buf->fields[i].id == id)\r
273             break;\r
274     }\r
275 \r
276     if(i < (int) buf->n_fields)\r
277         return i;\r
278     else\r
279         return KCDB_BUF_INVALID_SLOT;\r
280 }\r
281 \r
282 /* API for accessing generic buffers */\r
283 \r
284 KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr(\r
285     khm_handle  record, \r
286     khm_int32   attr_id, \r
287     khm_int32 * attr_type, \r
288     void *      buffer, \r
289     khm_size *  pcb_buf)\r
290 {\r
291     if(kcdb_cred_is_active_cred(record))\r
292         return kcdb_cred_get_attr(record, attr_id, attr_type, buffer, pcb_buf);\r
293     else if(kcdb_is_active_identity(record))\r
294         return kcdb_identity_get_attr(record, attr_id, attr_type, buffer, pcb_buf);\r
295     else\r
296         return KHM_ERROR_INVALID_PARAM;\r
297 }\r
298 \r
299 KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib(\r
300     khm_handle  record,\r
301     wchar_t *   attr_name,\r
302     khm_int32 * attr_type,\r
303     void *      buffer,\r
304     khm_size *  pcb_buf)\r
305 {\r
306     if(kcdb_cred_is_active_cred(record))\r
307         return kcdb_cred_get_attrib(record, attr_name, attr_type, buffer, pcb_buf);\r
308     else if(kcdb_is_active_identity(record))\r
309         return kcdb_identity_get_attrib(record, attr_name, attr_type, buffer, pcb_buf);\r
310     else\r
311         return KHM_ERROR_INVALID_PARAM;\r
312 }\r
313 \r
314 KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr_string(\r
315     khm_handle  record,\r
316     khm_int32   attr_id,\r
317     wchar_t *   buffer,\r
318     khm_size *  pcbbuf,\r
319     khm_int32  flags)\r
320 {\r
321     if(kcdb_cred_is_active_cred(record))\r
322         return kcdb_cred_get_attr_string(record, attr_id, buffer, pcbbuf, flags);\r
323     else if(kcdb_is_active_identity(record))\r
324         return kcdb_identity_get_attr_string(record, attr_id, buffer, pcbbuf, flags);\r
325     else\r
326         return KHM_ERROR_INVALID_PARAM;\r
327 }\r
328 \r
329 KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib_string(\r
330     khm_handle  record,\r
331     wchar_t *   attr_name,\r
332     wchar_t *   buffer,\r
333     khm_size *  pcbbuf,\r
334     khm_int32   flags)\r
335 {\r
336     if(kcdb_cred_is_active_cred(record))\r
337         return kcdb_cred_get_attrib_string(record, attr_name, buffer, pcbbuf, flags);\r
338     else if(kcdb_is_active_identity(record))\r
339         return kcdb_identity_get_attrib_string(record, attr_name, buffer, pcbbuf, flags);\r
340     else\r
341         return KHM_ERROR_INVALID_PARAM;\r
342 }\r
343 \r
344 KHMEXP khm_int32 KHMAPI kcdb_buf_set_attr(\r
345     khm_handle  record,\r
346     khm_int32   attr_id,\r
347     void *      buffer,\r
348     khm_size    cbbuf)\r
349 {\r
350     if(kcdb_cred_is_active_cred(record))\r
351         return kcdb_cred_set_attr(record, attr_id, buffer, cbbuf);\r
352     else if(kcdb_is_active_identity(record))\r
353         return kcdb_identity_set_attr(record, attr_id, buffer, cbbuf);\r
354     else\r
355         return KHM_ERROR_INVALID_PARAM;\r
356 }\r
357 \r
358 KHMEXP khm_int32 KHMAPI kcdb_buf_set_attrib(\r
359     khm_handle  record,\r
360     wchar_t *   attr_name,\r
361     void *      buffer,\r
362     khm_size    cbbuf)\r
363 {\r
364     if(kcdb_cred_is_active_cred(record))\r
365         return kcdb_cred_set_attrib(record, attr_name, buffer, cbbuf);\r
366     else if(kcdb_is_active_identity(record))\r
367         return kcdb_identity_set_attrib(record, attr_name, buffer, cbbuf);\r
368     else\r
369         return KHM_ERROR_INVALID_PARAM;\r
370 }\r
371 \r
372 KHMEXP khm_int32 KHMAPI kcdb_buf_hold(khm_handle  record)\r
373 {\r
374     if(kcdb_cred_is_active_cred(record))\r
375         return kcdb_cred_hold(record);\r
376     else if(kcdb_is_active_identity(record))\r
377         return kcdb_identity_hold(record);\r
378     else\r
379         return KHM_ERROR_INVALID_PARAM;\r
380 }\r
381 \r
382 KHMEXP khm_int32 KHMAPI kcdb_buf_release(khm_handle record)\r
383 {\r
384     if(kcdb_cred_is_active_cred(record))\r
385         return kcdb_cred_release(record);\r
386     else if(kcdb_is_active_identity(record))\r
387         return kcdb_identity_release(record);\r
388     else\r
389         return KHM_ERROR_INVALID_PARAM;\r
390 }\r
391 \r