1/*
2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of KTH nor the names of its contributors may be
18 *    used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32
33#include "krb5_locl.h"
34#include <getarg.h>
35
36static void
37test_int8(krb5_context context, krb5_storage *sp)
38{
39    krb5_error_code ret;
40    int i;
41    int8_t val[] = {
42	0, 1, -1, 128, -127
43    }, v;
44
45    krb5_storage_truncate(sp, 0);
46
47    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
48
49	ret = krb5_store_int8(sp, val[i]);
50	if (ret)
51	    krb5_err(context, 1, ret, "krb5_store_int8");
52	krb5_storage_seek(sp, 0, SEEK_SET);
53	ret = krb5_ret_int8(sp, &v);
54	if (ret)
55	    krb5_err(context, 1, ret, "krb5_ret_int8");
56	if (v != val[i])
57	    krb5_errx(context, 1, "store and ret mismatch");
58    }
59}
60
61static void
62test_int16(krb5_context context, krb5_storage *sp)
63{
64    krb5_error_code ret;
65    int i;
66    int16_t val[] = {
67	0, 1, -1, 32768, -32767
68    }, v;
69
70    krb5_storage_truncate(sp, 0);
71
72    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
73
74	ret = krb5_store_int16(sp, val[i]);
75	if (ret)
76	    krb5_err(context, 1, ret, "krb5_store_int16");
77	krb5_storage_seek(sp, 0, SEEK_SET);
78	ret = krb5_ret_int16(sp, &v);
79	if (ret)
80	    krb5_err(context, 1, ret, "krb5_ret_int16");
81	if (v != val[i])
82	    krb5_errx(context, 1, "store and ret mismatch");
83    }
84}
85
86static void
87test_int32(krb5_context context, krb5_storage *sp)
88{
89    krb5_error_code ret;
90    int i;
91    int32_t val[] = {
92	0, 1, -1, 2147483647, -2147483646
93    }, v;
94
95    krb5_storage_truncate(sp, 0);
96
97    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
98
99	ret = krb5_store_int32(sp, val[i]);
100	if (ret)
101	    krb5_err(context, 1, ret, "krb5_store_int32");
102	krb5_storage_seek(sp, 0, SEEK_SET);
103	ret = krb5_ret_int32(sp, &v);
104	if (ret)
105	    krb5_err(context, 1, ret, "krb5_ret_int32");
106	if (v != val[i])
107	    krb5_errx(context, 1, "store and ret mismatch");
108    }
109}
110
111static void
112test_uint8(krb5_context context, krb5_storage *sp)
113{
114    krb5_error_code ret;
115    int i;
116    uint8_t val[] = {
117	0, 1, 255
118    }, v;
119
120    krb5_storage_truncate(sp, 0);
121
122    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
123
124	ret = krb5_store_uint8(sp, val[i]);
125	if (ret)
126	    krb5_err(context, 1, ret, "krb5_store_uint8");
127	krb5_storage_seek(sp, 0, SEEK_SET);
128	ret = krb5_ret_uint8(sp, &v);
129	if (ret)
130	    krb5_err(context, 1, ret, "krb5_ret_uint8");
131	if (v != val[i])
132	    krb5_errx(context, 1, "store and ret mismatch");
133    }
134}
135
136static void
137test_uint16(krb5_context context, krb5_storage *sp)
138{
139    krb5_error_code ret;
140    int i;
141    uint16_t val[] = {
142	0, 1, 65535
143    }, v;
144
145    krb5_storage_truncate(sp, 0);
146
147    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
148
149	ret = krb5_store_uint16(sp, val[i]);
150	if (ret)
151	    krb5_err(context, 1, ret, "krb5_store_uint16");
152	krb5_storage_seek(sp, 0, SEEK_SET);
153	ret = krb5_ret_uint16(sp, &v);
154	if (ret)
155	    krb5_err(context, 1, ret, "krb5_ret_uint16");
156	if (v != val[i])
157	    krb5_errx(context, 1, "store and ret mismatch");
158    }
159}
160
161static void
162test_uint32(krb5_context context, krb5_storage *sp)
163{
164    krb5_error_code ret;
165    int i;
166    uint32_t val[] = {
167	0, 1, 4294967295UL
168    }, v;
169
170    krb5_storage_truncate(sp, 0);
171
172    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
173
174	ret = krb5_store_uint32(sp, val[i]);
175	if (ret)
176	    krb5_err(context, 1, ret, "krb5_store_uint32");
177	krb5_storage_seek(sp, 0, SEEK_SET);
178	ret = krb5_ret_uint32(sp, &v);
179	if (ret)
180	    krb5_err(context, 1, ret, "krb5_ret_uint32");
181	if (v != val[i])
182	    krb5_errx(context, 1, "store and ret mismatch");
183    }
184}
185
186
187static void
188test_storage(krb5_context context, krb5_storage *sp)
189{
190    test_int8(context, sp);
191    test_int16(context, sp);
192    test_int32(context, sp);
193    test_uint8(context, sp);
194    test_uint16(context, sp);
195    test_uint32(context, sp);
196}
197
198
199static void
200test_truncate(krb5_context context, krb5_storage *sp, int fd)
201{
202    struct stat sb;
203
204    krb5_store_string(sp, "hej");
205    krb5_storage_truncate(sp, 2);
206
207    if (fstat(fd, &sb) != 0)
208	krb5_err(context, 1, errno, "fstat");
209    if (sb.st_size != 2)
210	krb5_errx(context, 1, "length not 2");
211
212    krb5_storage_truncate(sp, 1024);
213
214    if (fstat(fd, &sb) != 0)
215	krb5_err(context, 1, errno, "fstat");
216    if (sb.st_size != 1024)
217	krb5_errx(context, 1, "length not 2");
218}
219
220static void
221check_too_large(krb5_context context, krb5_storage *sp)
222{
223    uint32_t too_big_sizes[] = { INT_MAX, INT_MAX / 2, INT_MAX / 4, INT_MAX / 8 + 1};
224    krb5_error_code ret;
225    krb5_data data;
226    size_t n;
227
228    for (n = 0; n < sizeof(too_big_sizes) / sizeof(too_big_sizes); n++) {
229	krb5_storage_truncate(sp, 0);
230	krb5_store_uint32(sp, too_big_sizes[n]);
231	krb5_storage_seek(sp, 0, SEEK_SET);
232	ret = krb5_ret_data(sp, &data);
233	if (ret != HEIM_ERR_TOO_BIG)
234	    errx(1, "not too big: %lu", (unsigned long)n);
235    }
236}
237
238/*
239 *
240 */
241
242static int version_flag = 0;
243static int help_flag	= 0;
244
245static struct getargs args[] = {
246    {"version",	0,	arg_flag,	&version_flag,
247     "print version", NULL },
248    {"help",	0,	arg_flag,	&help_flag,
249     NULL, NULL }
250};
251
252static void
253usage (int ret)
254{
255    arg_printusage (args,
256		    sizeof(args)/sizeof(*args),
257		    NULL,
258		    "");
259    exit (ret);
260}
261
262int
263main(int argc, char **argv)
264{
265    krb5_context context;
266    krb5_error_code ret;
267    int fd, optidx = 0;
268    krb5_storage *sp;
269    const char *fn = "test-store-data";
270
271    setprogname(argv[0]);
272
273    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
274	usage(1);
275
276    if (help_flag)
277	usage (0);
278
279    if(version_flag){
280	print_version(NULL);
281	exit(0);
282    }
283
284    argc -= optidx;
285    argv += optidx;
286
287    ret = krb5_init_context (&context);
288    if (ret)
289	errx (1, "krb5_init_context failed: %d", ret);
290
291    /*
292     * Test encoding/decoding of primotive types on diffrent backends
293     */
294
295    sp = krb5_storage_emem();
296    if (sp == NULL)
297	krb5_errx(context, 1, "krb5_storage_emem: no mem");
298
299    test_storage(context, sp);
300    check_too_large(context, sp);
301    krb5_storage_free(sp);
302
303
304    fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0600);
305    if (fd < 0)
306	krb5_err(context, 1, errno, "open(%s)", fn);
307
308    sp = krb5_storage_from_fd(fd);
309    close(fd);
310    if (sp == NULL)
311	krb5_errx(context, 1, "krb5_storage_from_fd: %s no mem", fn);
312
313    test_storage(context, sp);
314    krb5_storage_free(sp);
315    unlink(fn);
316
317    /*
318     * test truncate behavior
319     */
320
321    fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0600);
322    if (fd < 0)
323	krb5_err(context, 1, errno, "open(%s)", fn);
324
325    sp = krb5_storage_from_fd(fd);
326    if (sp == NULL)
327	krb5_errx(context, 1, "krb5_storage_from_fd: %s no mem", fn);
328
329    test_truncate(context, sp, fd);
330    krb5_storage_free(sp);
331    close(fd);
332    unlink(fn);
333
334    krb5_free_context(context);
335
336    return 0;
337}
338