1178825Sdfr/*
2233294Sstas * Copyright (c) 2006 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17178825Sdfr * 3. Neither the name of KTH nor the names of its contributors may be
18178825Sdfr *    used to endorse or promote products derived from this software without
19178825Sdfr *    specific prior written permission.
20178825Sdfr *
21178825Sdfr * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22178825Sdfr * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24178825Sdfr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25178825Sdfr * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26178825Sdfr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27178825Sdfr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28178825Sdfr * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29178825Sdfr * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30178825Sdfr * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31178825Sdfr * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32178825Sdfr
33178825Sdfr#include "krb5_locl.h"
34178825Sdfr#include <getarg.h>
35178825Sdfr
36178825Sdfrstatic void
37178825Sdfrtest_int8(krb5_context context, krb5_storage *sp)
38178825Sdfr{
39178825Sdfr    krb5_error_code ret;
40178825Sdfr    int i;
41178825Sdfr    int8_t val[] = {
42178825Sdfr	0, 1, -1, 128, -127
43178825Sdfr    }, v;
44178825Sdfr
45233294Sstas    krb5_storage_truncate(sp, 0);
46233294Sstas
47178825Sdfr    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
48178825Sdfr
49178825Sdfr	ret = krb5_store_int8(sp, val[i]);
50178825Sdfr	if (ret)
51178825Sdfr	    krb5_err(context, 1, ret, "krb5_store_int8");
52178825Sdfr	krb5_storage_seek(sp, 0, SEEK_SET);
53178825Sdfr	ret = krb5_ret_int8(sp, &v);
54178825Sdfr	if (ret)
55178825Sdfr	    krb5_err(context, 1, ret, "krb5_ret_int8");
56178825Sdfr	if (v != val[i])
57178825Sdfr	    krb5_errx(context, 1, "store and ret mismatch");
58178825Sdfr    }
59178825Sdfr}
60178825Sdfr
61178825Sdfrstatic void
62178825Sdfrtest_int16(krb5_context context, krb5_storage *sp)
63178825Sdfr{
64178825Sdfr    krb5_error_code ret;
65178825Sdfr    int i;
66178825Sdfr    int16_t val[] = {
67178825Sdfr	0, 1, -1, 32768, -32767
68178825Sdfr    }, v;
69178825Sdfr
70233294Sstas    krb5_storage_truncate(sp, 0);
71233294Sstas
72178825Sdfr    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
73178825Sdfr
74178825Sdfr	ret = krb5_store_int16(sp, val[i]);
75178825Sdfr	if (ret)
76178825Sdfr	    krb5_err(context, 1, ret, "krb5_store_int16");
77178825Sdfr	krb5_storage_seek(sp, 0, SEEK_SET);
78178825Sdfr	ret = krb5_ret_int16(sp, &v);
79178825Sdfr	if (ret)
80178825Sdfr	    krb5_err(context, 1, ret, "krb5_ret_int16");
81178825Sdfr	if (v != val[i])
82178825Sdfr	    krb5_errx(context, 1, "store and ret mismatch");
83178825Sdfr    }
84178825Sdfr}
85178825Sdfr
86178825Sdfrstatic void
87178825Sdfrtest_int32(krb5_context context, krb5_storage *sp)
88178825Sdfr{
89178825Sdfr    krb5_error_code ret;
90178825Sdfr    int i;
91178825Sdfr    int32_t val[] = {
92178825Sdfr	0, 1, -1, 2147483647, -2147483646
93178825Sdfr    }, v;
94178825Sdfr
95233294Sstas    krb5_storage_truncate(sp, 0);
96233294Sstas
97178825Sdfr    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
98178825Sdfr
99178825Sdfr	ret = krb5_store_int32(sp, val[i]);
100178825Sdfr	if (ret)
101178825Sdfr	    krb5_err(context, 1, ret, "krb5_store_int32");
102178825Sdfr	krb5_storage_seek(sp, 0, SEEK_SET);
103178825Sdfr	ret = krb5_ret_int32(sp, &v);
104178825Sdfr	if (ret)
105178825Sdfr	    krb5_err(context, 1, ret, "krb5_ret_int32");
106178825Sdfr	if (v != val[i])
107178825Sdfr	    krb5_errx(context, 1, "store and ret mismatch");
108178825Sdfr    }
109178825Sdfr}
110178825Sdfr
111178825Sdfrstatic void
112178825Sdfrtest_uint8(krb5_context context, krb5_storage *sp)
113178825Sdfr{
114178825Sdfr    krb5_error_code ret;
115178825Sdfr    int i;
116178825Sdfr    uint8_t val[] = {
117178825Sdfr	0, 1, 255
118178825Sdfr    }, v;
119178825Sdfr
120233294Sstas    krb5_storage_truncate(sp, 0);
121233294Sstas
122178825Sdfr    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
123178825Sdfr
124178825Sdfr	ret = krb5_store_uint8(sp, val[i]);
125178825Sdfr	if (ret)
126178825Sdfr	    krb5_err(context, 1, ret, "krb5_store_uint8");
127178825Sdfr	krb5_storage_seek(sp, 0, SEEK_SET);
128178825Sdfr	ret = krb5_ret_uint8(sp, &v);
129178825Sdfr	if (ret)
130178825Sdfr	    krb5_err(context, 1, ret, "krb5_ret_uint8");
131178825Sdfr	if (v != val[i])
132178825Sdfr	    krb5_errx(context, 1, "store and ret mismatch");
133178825Sdfr    }
134178825Sdfr}
135178825Sdfr
136178825Sdfrstatic void
137178825Sdfrtest_uint16(krb5_context context, krb5_storage *sp)
138178825Sdfr{
139178825Sdfr    krb5_error_code ret;
140178825Sdfr    int i;
141178825Sdfr    uint16_t val[] = {
142178825Sdfr	0, 1, 65535
143178825Sdfr    }, v;
144178825Sdfr
145233294Sstas    krb5_storage_truncate(sp, 0);
146233294Sstas
147178825Sdfr    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
148178825Sdfr
149178825Sdfr	ret = krb5_store_uint16(sp, val[i]);
150178825Sdfr	if (ret)
151178825Sdfr	    krb5_err(context, 1, ret, "krb5_store_uint16");
152178825Sdfr	krb5_storage_seek(sp, 0, SEEK_SET);
153178825Sdfr	ret = krb5_ret_uint16(sp, &v);
154178825Sdfr	if (ret)
155178825Sdfr	    krb5_err(context, 1, ret, "krb5_ret_uint16");
156178825Sdfr	if (v != val[i])
157178825Sdfr	    krb5_errx(context, 1, "store and ret mismatch");
158178825Sdfr    }
159178825Sdfr}
160178825Sdfr
161178825Sdfrstatic void
162178825Sdfrtest_uint32(krb5_context context, krb5_storage *sp)
163178825Sdfr{
164178825Sdfr    krb5_error_code ret;
165178825Sdfr    int i;
166178825Sdfr    uint32_t val[] = {
167178825Sdfr	0, 1, 4294967295UL
168178825Sdfr    }, v;
169178825Sdfr
170233294Sstas    krb5_storage_truncate(sp, 0);
171233294Sstas
172178825Sdfr    for (i = 0; i < sizeof(val[0])/sizeof(val); i++) {
173178825Sdfr
174178825Sdfr	ret = krb5_store_uint32(sp, val[i]);
175178825Sdfr	if (ret)
176178825Sdfr	    krb5_err(context, 1, ret, "krb5_store_uint32");
177178825Sdfr	krb5_storage_seek(sp, 0, SEEK_SET);
178178825Sdfr	ret = krb5_ret_uint32(sp, &v);
179178825Sdfr	if (ret)
180178825Sdfr	    krb5_err(context, 1, ret, "krb5_ret_uint32");
181178825Sdfr	if (v != val[i])
182178825Sdfr	    krb5_errx(context, 1, "store and ret mismatch");
183178825Sdfr    }
184178825Sdfr}
185178825Sdfr
186178825Sdfr
187178825Sdfrstatic void
188233294Sstastest_storage(krb5_context context, krb5_storage *sp)
189178825Sdfr{
190178825Sdfr    test_int8(context, sp);
191178825Sdfr    test_int16(context, sp);
192178825Sdfr    test_int32(context, sp);
193178825Sdfr    test_uint8(context, sp);
194178825Sdfr    test_uint16(context, sp);
195178825Sdfr    test_uint32(context, sp);
196233294Sstas}
197178825Sdfr
198233294Sstas
199233294Sstasstatic void
200233294Sstastest_truncate(krb5_context context, krb5_storage *sp, int fd)
201233294Sstas{
202233294Sstas    struct stat sb;
203233294Sstas
204233294Sstas    krb5_store_string(sp, "hej");
205233294Sstas    krb5_storage_truncate(sp, 2);
206233294Sstas
207233294Sstas    if (fstat(fd, &sb) != 0)
208233294Sstas	krb5_err(context, 1, errno, "fstat");
209233294Sstas    if (sb.st_size != 2)
210233294Sstas	krb5_errx(context, 1, "length not 2");
211233294Sstas
212233294Sstas    krb5_storage_truncate(sp, 1024);
213233294Sstas
214233294Sstas    if (fstat(fd, &sb) != 0)
215233294Sstas	krb5_err(context, 1, errno, "fstat");
216233294Sstas    if (sb.st_size != 1024)
217233294Sstas	krb5_errx(context, 1, "length not 2");
218178825Sdfr}
219178825Sdfr
220233294Sstasstatic void
221233294Sstascheck_too_large(krb5_context context, krb5_storage *sp)
222233294Sstas{
223233294Sstas    uint32_t too_big_sizes[] = { INT_MAX, INT_MAX / 2, INT_MAX / 4, INT_MAX / 8 + 1};
224233294Sstas    krb5_error_code ret;
225233294Sstas    krb5_data data;
226233294Sstas    size_t n;
227233294Sstas
228233294Sstas    for (n = 0; n < sizeof(too_big_sizes) / sizeof(too_big_sizes); n++) {
229233294Sstas	krb5_storage_truncate(sp, 0);
230233294Sstas	krb5_store_uint32(sp, too_big_sizes[n]);
231233294Sstas	krb5_storage_seek(sp, 0, SEEK_SET);
232233294Sstas	ret = krb5_ret_data(sp, &data);
233233294Sstas	if (ret != HEIM_ERR_TOO_BIG)
234233294Sstas	    errx(1, "not too big: %lu", (unsigned long)n);
235233294Sstas    }
236233294Sstas}
237233294Sstas
238178825Sdfr/*
239178825Sdfr *
240178825Sdfr */
241178825Sdfr
242178825Sdfrstatic int version_flag = 0;
243178825Sdfrstatic int help_flag	= 0;
244178825Sdfr
245178825Sdfrstatic struct getargs args[] = {
246178825Sdfr    {"version",	0,	arg_flag,	&version_flag,
247178825Sdfr     "print version", NULL },
248178825Sdfr    {"help",	0,	arg_flag,	&help_flag,
249178825Sdfr     NULL, NULL }
250178825Sdfr};
251178825Sdfr
252178825Sdfrstatic void
253178825Sdfrusage (int ret)
254178825Sdfr{
255178825Sdfr    arg_printusage (args,
256178825Sdfr		    sizeof(args)/sizeof(*args),
257178825Sdfr		    NULL,
258178825Sdfr		    "");
259178825Sdfr    exit (ret);
260178825Sdfr}
261178825Sdfr
262178825Sdfrint
263178825Sdfrmain(int argc, char **argv)
264178825Sdfr{
265178825Sdfr    krb5_context context;
266178825Sdfr    krb5_error_code ret;
267233294Sstas    int fd, optidx = 0;
268233294Sstas    krb5_storage *sp;
269233294Sstas    const char *fn = "test-store-data";
270178825Sdfr
271178825Sdfr    setprogname(argv[0]);
272178825Sdfr
273178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
274178825Sdfr	usage(1);
275233294Sstas
276178825Sdfr    if (help_flag)
277178825Sdfr	usage (0);
278178825Sdfr
279178825Sdfr    if(version_flag){
280178825Sdfr	print_version(NULL);
281178825Sdfr	exit(0);
282178825Sdfr    }
283178825Sdfr
284178825Sdfr    argc -= optidx;
285178825Sdfr    argv += optidx;
286178825Sdfr
287178825Sdfr    ret = krb5_init_context (&context);
288178825Sdfr    if (ret)
289178825Sdfr	errx (1, "krb5_init_context failed: %d", ret);
290178825Sdfr
291233294Sstas    /*
292233294Sstas     * Test encoding/decoding of primotive types on diffrent backends
293233294Sstas     */
294178825Sdfr
295233294Sstas    sp = krb5_storage_emem();
296233294Sstas    if (sp == NULL)
297233294Sstas	krb5_errx(context, 1, "krb5_storage_emem: no mem");
298233294Sstas
299233294Sstas    test_storage(context, sp);
300233294Sstas    check_too_large(context, sp);
301233294Sstas    krb5_storage_free(sp);
302233294Sstas
303233294Sstas
304233294Sstas    fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0600);
305233294Sstas    if (fd < 0)
306233294Sstas	krb5_err(context, 1, errno, "open(%s)", fn);
307233294Sstas
308233294Sstas    sp = krb5_storage_from_fd(fd);
309233294Sstas    close(fd);
310233294Sstas    if (sp == NULL)
311233294Sstas	krb5_errx(context, 1, "krb5_storage_from_fd: %s no mem", fn);
312233294Sstas
313233294Sstas    test_storage(context, sp);
314233294Sstas    krb5_storage_free(sp);
315233294Sstas    unlink(fn);
316233294Sstas
317233294Sstas    /*
318233294Sstas     * test truncate behavior
319233294Sstas     */
320233294Sstas
321233294Sstas    fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0600);
322233294Sstas    if (fd < 0)
323233294Sstas	krb5_err(context, 1, errno, "open(%s)", fn);
324233294Sstas
325233294Sstas    sp = krb5_storage_from_fd(fd);
326233294Sstas    if (sp == NULL)
327233294Sstas	krb5_errx(context, 1, "krb5_storage_from_fd: %s no mem", fn);
328233294Sstas
329233294Sstas    test_truncate(context, sp, fd);
330233294Sstas    krb5_storage_free(sp);
331233294Sstas    close(fd);
332233294Sstas    unlink(fn);
333233294Sstas
334178825Sdfr    krb5_free_context(context);
335178825Sdfr
336178825Sdfr    return 0;
337178825Sdfr}
338