1*afab4e30Schristos /* $NetBSD: test-normalize.c,v 1.3 2023/06/19 21:41:45 christos Exp $ */
2ca1c9b0cSelric
3ca1c9b0cSelric /*
4ca1c9b0cSelric * Copyright (c) 2004 Kungliga Tekniska Högskolan
5ca1c9b0cSelric * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric * All rights reserved.
7ca1c9b0cSelric *
8ca1c9b0cSelric * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric * modification, are permitted provided that the following conditions
10ca1c9b0cSelric * are met:
11ca1c9b0cSelric *
12ca1c9b0cSelric * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric * notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric *
15ca1c9b0cSelric * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric * notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric * documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric *
19ca1c9b0cSelric * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric * may be used to endorse or promote products derived from this software
21ca1c9b0cSelric * without specific prior written permission.
22ca1c9b0cSelric *
23ca1c9b0cSelric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric * SUCH DAMAGE.
34ca1c9b0cSelric */
35ca1c9b0cSelric
36ca1c9b0cSelric #ifdef HAVE_CONFIG_H
37ca1c9b0cSelric #include <config.h>
38ca1c9b0cSelric #endif
39ca1c9b0cSelric #include <stdio.h>
40ca1c9b0cSelric #include <stdlib.h>
41ca1c9b0cSelric #include <string.h>
42ca1c9b0cSelric #include <err.h>
43ca1c9b0cSelric
44ca1c9b0cSelric #include <krb5/roken.h>
45ca1c9b0cSelric
46ca1c9b0cSelric #include "windlocl.h"
47ca1c9b0cSelric #include "normalize_table.h"
48ca1c9b0cSelric
49ca1c9b0cSelric static size_t
parse_vector(char * buf,uint32_t * v)50ca1c9b0cSelric parse_vector(char *buf, uint32_t *v)
51ca1c9b0cSelric {
52b9d004c6Schristos char *last = NULL;
53ca1c9b0cSelric unsigned ret = 0;
54ca1c9b0cSelric const char *n;
55ca1c9b0cSelric unsigned u;
56ca1c9b0cSelric
57ca1c9b0cSelric for(n = strtok_r(buf, " ", &last);
58ca1c9b0cSelric n != NULL;
59ca1c9b0cSelric n = strtok_r(NULL, " ", &last)) {
60ca1c9b0cSelric if (ret >= MAX_LENGTH_CANON) {
61ca1c9b0cSelric errx(1, "increase MAX_LENGTH_CANON");
62ca1c9b0cSelric }
63ca1c9b0cSelric if (sscanf(n, "%x", &u) != 1) {
64ca1c9b0cSelric errx(1, "failed to parse hex: %s", n);
65ca1c9b0cSelric }
66ca1c9b0cSelric v[ret] = u;
67ca1c9b0cSelric ++ret;
68ca1c9b0cSelric }
69ca1c9b0cSelric return ret;
70ca1c9b0cSelric }
71ca1c9b0cSelric
72ca1c9b0cSelric static void
dump_vector(const char * msg,uint32_t * v,size_t len)73ca1c9b0cSelric dump_vector(const char * msg, uint32_t * v, size_t len)
74ca1c9b0cSelric {
75ca1c9b0cSelric size_t i;
76ca1c9b0cSelric
77ca1c9b0cSelric printf("%s: (%d) ", msg, (int)len);
78ca1c9b0cSelric for (i=0; i < len; i++) {
79ca1c9b0cSelric printf("%s%x", (i > 0? " ":""), v[i]);
80ca1c9b0cSelric }
81ca1c9b0cSelric printf("\n");
82ca1c9b0cSelric }
83ca1c9b0cSelric
84ca1c9b0cSelric static int
test(char * buf,unsigned lineno)85ca1c9b0cSelric test(char *buf, unsigned lineno)
86ca1c9b0cSelric {
87ca1c9b0cSelric char *last;
88ca1c9b0cSelric char *c;
89ca1c9b0cSelric uint32_t in[MAX_LENGTH_CANON];
90ca1c9b0cSelric size_t in_len;
91ca1c9b0cSelric uint32_t out[MAX_LENGTH_CANON];
92ca1c9b0cSelric size_t out_len;
93ca1c9b0cSelric uint32_t *tmp;
94ca1c9b0cSelric size_t norm_len;
95ca1c9b0cSelric int ret;
96ca1c9b0cSelric
97ca1c9b0cSelric c = strtok_r(buf, ";", &last);
98ca1c9b0cSelric if (c == NULL)
99ca1c9b0cSelric return 0;
100ca1c9b0cSelric
101ca1c9b0cSelric in_len = parse_vector(c, in);
102ca1c9b0cSelric if (strtok_r(NULL, ";", &last) == NULL)
103ca1c9b0cSelric return 0;
104ca1c9b0cSelric if (strtok_r(NULL, ";", &last) == NULL)
105ca1c9b0cSelric return 0;
106ca1c9b0cSelric c = strtok_r(NULL, ";", &last);
107ca1c9b0cSelric if (c == NULL)
108ca1c9b0cSelric return 0;
109ca1c9b0cSelric out_len = parse_vector(c, out);
110ca1c9b0cSelric if (strtok_r(NULL, ";", &last) == NULL)
111ca1c9b0cSelric return 0;
112ca1c9b0cSelric c = last;
113ca1c9b0cSelric
114ca1c9b0cSelric norm_len = MAX_LENGTH_CANON;
115ca1c9b0cSelric tmp = malloc(norm_len * sizeof(uint32_t));
116ca1c9b0cSelric if (tmp == NULL && norm_len != 0)
117ca1c9b0cSelric err(1, "malloc");
118ca1c9b0cSelric ret = _wind_stringprep_normalize(in, in_len, tmp, &norm_len);
119ca1c9b0cSelric if (ret) {
120ca1c9b0cSelric printf("wind_stringprep_normalize %s failed\n", c);
121ca1c9b0cSelric free(tmp);
122ca1c9b0cSelric return 1;
123ca1c9b0cSelric }
124ca1c9b0cSelric if (out_len != norm_len) {
125ca1c9b0cSelric printf("%u: wrong out len (%s)\n", lineno, c);
126ca1c9b0cSelric dump_vector("Expected", out, out_len);
127ca1c9b0cSelric dump_vector("Received", tmp, norm_len);
128ca1c9b0cSelric free(tmp);
129ca1c9b0cSelric return 1;
130ca1c9b0cSelric }
131ca1c9b0cSelric if (memcmp(out, tmp, out_len * sizeof(uint32_t)) != 0) {
132ca1c9b0cSelric printf("%u: wrong out data (%s)\n", lineno, c);
133ca1c9b0cSelric dump_vector("Expected", out, out_len);
134ca1c9b0cSelric dump_vector("Received", tmp, norm_len);
135ca1c9b0cSelric free(tmp);
136ca1c9b0cSelric return 1;
137ca1c9b0cSelric }
138ca1c9b0cSelric free(tmp);
139ca1c9b0cSelric return 0;
140ca1c9b0cSelric }
141ca1c9b0cSelric
142ca1c9b0cSelric int
main(int argc,char ** argv)143ca1c9b0cSelric main(int argc, char **argv)
144ca1c9b0cSelric {
145ca1c9b0cSelric FILE *f;
146ca1c9b0cSelric char buf[1024];
147ca1c9b0cSelric char filename[256] = "NormalizationTest.txt";
148ca1c9b0cSelric unsigned failures = 0;
149ca1c9b0cSelric unsigned lineno = 0;
150ca1c9b0cSelric
151ca1c9b0cSelric if (argc > 2)
152ca1c9b0cSelric errx(1, "usage: %s [file]", argv[0]);
153ca1c9b0cSelric else if (argc == 2)
154ca1c9b0cSelric strlcpy(filename, argv[1], sizeof(filename));
155ca1c9b0cSelric
156ca1c9b0cSelric f = fopen(filename, "r");
157ca1c9b0cSelric if (f == NULL) {
158ca1c9b0cSelric const char *srcdir = getenv("srcdir");
159ca1c9b0cSelric if (srcdir != NULL) {
160*afab4e30Schristos char *longname = NULL;
161*afab4e30Schristos
162*afab4e30Schristos if (asprintf(&longname, "%s/%s", srcdir, filename) == -1 ||
163*afab4e30Schristos longname == NULL)
164*afab4e30Schristos errx(1, "Out of memory");
165ca1c9b0cSelric f = fopen(longname, "r");
166*afab4e30Schristos free(longname);
167ca1c9b0cSelric }
168ca1c9b0cSelric if (f == NULL)
169ca1c9b0cSelric err(1, "open %s", filename);
170ca1c9b0cSelric }
171ca1c9b0cSelric while (fgets(buf, sizeof(buf), f) != NULL) {
172ca1c9b0cSelric lineno++;
173ca1c9b0cSelric if (buf[0] == '#')
174ca1c9b0cSelric continue;
175ca1c9b0cSelric if (buf[0] == '@') {
176ca1c9b0cSelric continue;
177ca1c9b0cSelric }
178ca1c9b0cSelric failures += test(buf, lineno);
179ca1c9b0cSelric }
180ca1c9b0cSelric fclose(f);
181ca1c9b0cSelric return failures != 0;
182ca1c9b0cSelric }
183