1226031Sstas/*
2226031Sstas * Copyright (c) 2004, 2006, 2008 Kungliga Tekniska H��gskolan
3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4226031Sstas * All rights reserved.
5226031Sstas *
6226031Sstas * Redistribution and use in source and binary forms, with or without
7226031Sstas * modification, are permitted provided that the following conditions
8226031Sstas * are met:
9226031Sstas *
10226031Sstas * 1. Redistributions of source code must retain the above copyright
11226031Sstas *    notice, this list of conditions and the following disclaimer.
12226031Sstas *
13226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
14226031Sstas *    notice, this list of conditions and the following disclaimer in the
15226031Sstas *    documentation and/or other materials provided with the distribution.
16226031Sstas *
17226031Sstas * 3. Neither the name of the Institute nor the names of its contributors
18226031Sstas *    may be used to endorse or promote products derived from this software
19226031Sstas *    without specific prior written permission.
20226031Sstas *
21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31226031Sstas * SUCH DAMAGE.
32226031Sstas */
33226031Sstas
34226031Sstas#ifdef HAVE_CONFIG_H
35226031Sstas#include <config.h>
36226031Sstas#endif
37226031Sstas#include "windlocl.h"
38226031Sstas#include <stdlib.h>
39226031Sstas#include <string.h>
40226031Sstas#include <errno.h>
41226031Sstas
42226031Sstas/**
43226031Sstas * Process a input UCS4 string according a string-prep profile.
44226031Sstas *
45226031Sstas * @param in input UCS4 string to process
46226031Sstas * @param in_len length of the input string
47226031Sstas * @param out output UCS4 string
48226031Sstas * @param out_len length of the output string.
49226031Sstas * @param flags stringprep profile.
50226031Sstas *
51226031Sstas * @return returns 0 on success, an wind error code otherwise
52226031Sstas * @ingroup wind
53226031Sstas */
54226031Sstas
55226031Sstasint
56226031Sstaswind_stringprep(const uint32_t *in, size_t in_len,
57226031Sstas		uint32_t *out, size_t *out_len,
58226031Sstas		wind_profile_flags flags)
59226031Sstas{
60226031Sstas    size_t tmp_len = in_len * 3;
61226031Sstas    uint32_t *tmp;
62226031Sstas    int ret;
63226031Sstas    size_t olen;
64226031Sstas
65226031Sstas    if (in_len == 0) {
66226031Sstas	*out_len = 0;
67226031Sstas	return 0;
68226031Sstas    }
69226031Sstas
70226031Sstas    tmp = malloc(tmp_len * sizeof(uint32_t));
71226031Sstas    if (tmp == NULL)
72226031Sstas	return ENOMEM;
73226031Sstas
74226031Sstas    ret = _wind_stringprep_map(in, in_len, tmp, &tmp_len, flags);
75226031Sstas    if (ret) {
76226031Sstas	free(tmp);
77226031Sstas	return ret;
78226031Sstas    }
79226031Sstas
80226031Sstas    olen = *out_len;
81226031Sstas    ret = _wind_stringprep_normalize(tmp, tmp_len, tmp, &olen);
82226031Sstas    if (ret) {
83226031Sstas	free(tmp);
84226031Sstas	return ret;
85226031Sstas    }
86226031Sstas    ret = _wind_stringprep_prohibited(tmp, olen, flags);
87226031Sstas    if (ret) {
88226031Sstas	free(tmp);
89226031Sstas	return ret;
90226031Sstas    }
91226031Sstas    ret = _wind_stringprep_testbidi(tmp, olen, flags);
92226031Sstas    if (ret) {
93226031Sstas	free(tmp);
94226031Sstas	return ret;
95226031Sstas    }
96226031Sstas
97226031Sstas    /* Insignificant Character Handling for ldap-prep */
98226031Sstas    if (flags & WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE) {
99226031Sstas	ret = _wind_ldap_case_exact_attribute(tmp, olen, out, out_len);
100226031Sstas#if 0
101226031Sstas    } else if (flags & WIND_PROFILE_LDAP_CASE_EXACT_ASSERTION) {
102226031Sstas    } else if (flags & WIND_PROFILE_LDAP_NUMERIC) {
103226031Sstas    } else if (flags & WIND_PROFILE_LDAP_TELEPHONE) {
104226031Sstas#endif
105226031Sstas    } else {
106226031Sstas	memcpy(out, tmp, sizeof(out[0]) * olen);
107226031Sstas	*out_len = olen;
108226031Sstas    }
109226031Sstas    free(tmp);
110226031Sstas
111226031Sstas    return ret;
112226031Sstas}
113226031Sstas
114226031Sstasstatic const struct {
115226031Sstas    const char *name;
116226031Sstas    wind_profile_flags flags;
117226031Sstas} profiles[] = {
118226031Sstas    { "nameprep", WIND_PROFILE_NAME },
119226031Sstas    { "saslprep", WIND_PROFILE_SASL },
120226031Sstas    { "ldapprep", WIND_PROFILE_LDAP }
121226031Sstas};
122226031Sstas
123226031Sstas/**
124226031Sstas * Try to find the profile given a name.
125226031Sstas *
126226031Sstas * @param name name of the profile.
127226031Sstas * @param flags the resulting profile.
128226031Sstas *
129226031Sstas * @return returns 0 on success, an wind error code otherwise
130226031Sstas * @ingroup wind
131226031Sstas */
132226031Sstas
133226031Sstasint
134226031Sstaswind_profile(const char *name, wind_profile_flags *flags)
135226031Sstas{
136226031Sstas    unsigned int i;
137226031Sstas
138226031Sstas    for (i = 0; i < sizeof(profiles)/sizeof(profiles[0]); i++) {
139226031Sstas	if (strcasecmp(profiles[i].name, name) == 0) {
140226031Sstas	    *flags = profiles[i].flags;
141226031Sstas	    return 0;
142226031Sstas	}
143226031Sstas    }
144226031Sstas    return WIND_ERR_NO_PROFILE;
145226031Sstas}
146