5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 2006 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
22 #include "silcstrutil.h"
24 static unsigned char pem_enc[64] =
25 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27 /* Encodes data into PEM encoding. Returns NULL terminated PEM encoded
30 char *silc_pem_encode(unsigned char *data, SilcUInt32 len)
33 SilcUInt32 bits, c, char_count;
40 pem = silc_calloc(((len * 8 + 5) / 6) + 5, sizeof(*pem));
42 for (i = 0; i < len; i++) {
47 if (char_count == 3) {
48 pem[j++] = pem_enc[bits >> 18];
49 pem[j++] = pem_enc[(bits >> 12) & 0x3f];
50 pem[j++] = pem_enc[(bits >> 6) & 0x3f];
51 pem[j++] = pem_enc[bits & 0x3f];
59 if (char_count != 0) {
60 bits <<= 16 - (8 * char_count);
61 pem[j++] = pem_enc[bits >> 18];
62 pem[j++] = pem_enc[(bits >> 12) & 0x3f];
64 if (char_count == 1) {
68 pem[j++] = pem_enc[(bits >> 6) & 0x3f];
76 /* Same as above but puts newline ('\n') every 72 characters. */
78 char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len)
84 pem = silc_pem_encode(data, data_len);
87 pem2 = silc_calloc(len + (len / 72) + 1, sizeof(*pem2));
89 for (i = 0, j = 0, cols = 1; i < len; i++, cols++) {
104 /* Decodes PEM into data. Returns the decoded data. */
106 unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
110 SilcUInt32 len, c, char_count, bits;
112 static char ialpha[256], decoder[256];
114 for (i = 64 - 1; i >= 0; i--) {
115 ialpha[pem_enc[i]] = 1;
116 decoder[pem_enc[i]] = i;
128 data = silc_calloc(((len * 6) / 8), sizeof(*data));
130 for (i = 0; i < len; i++) {
136 if (c > 127 || !ialpha[c])
142 if (char_count == 4) {
143 data[j++] = bits >> 16;
144 data[j++] = (bits >> 8) & 0xff;
145 data[j++] = bits & 0xff;
159 data[j++] = bits >> 10;
162 data[j++] = bits >> 16;
163 data[j++] = (bits >> 8) & 0xff;
173 /* Concatenates the `src' into `dest'. If `src_len' is more than the
174 size of the `dest' (minus NULL at the end) the `src' will be
177 char *silc_strncat(char *dest, SilcUInt32 dest_size,
178 const char *src, SilcUInt32 src_len)
182 dest[dest_size - 1] = '\0';
184 len = dest_size - 1 - strlen(dest);
187 strncat(dest, src, len);
189 strncat(dest, src, src_len);
195 /* Checks that the 'identifier' string is valid identifier string
196 and does not contain any unassigned or prohibited character. This
197 function is used to check for valid nicknames, channel names,
198 server names, usernames, hostnames, service names, algorithm names,
199 other security property names, and SILC Public Key name. */
201 unsigned char *silc_identifier_check(const unsigned char *identifier,
202 SilcUInt32 identifier_len,
203 SilcStringEncoding identifier_encoding,
204 SilcUInt32 max_allowed_length,
207 unsigned char *utf8s;
208 SilcUInt32 utf8s_len;
209 SilcStringprepStatus status;
211 if (!identifier || !identifier_len)
214 if (max_allowed_length && identifier_len > max_allowed_length)
217 status = silc_stringprep(identifier, identifier_len,
218 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
219 &utf8s, &utf8s_len, SILC_STRING_UTF8);
220 if (status != SILC_STRINGPREP_OK) {
221 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
226 *out_len = utf8s_len;
231 /* Same as above but does not allocate memory, just checks the
232 validity of the string. */
234 SilcBool silc_identifier_verify(const unsigned char *identifier,
235 SilcUInt32 identifier_len,
236 SilcStringEncoding identifier_encoding,
237 SilcUInt32 max_allowed_length)
239 SilcStringprepStatus status;
241 if (!identifier || !identifier_len)
244 if (max_allowed_length && identifier_len > max_allowed_length)
247 status = silc_stringprep(identifier, identifier_len,
248 identifier_encoding, SILC_IDENTIFIER_PREP, 0,
249 NULL, NULL, SILC_STRING_UTF8);
250 if (status != SILC_STRINGPREP_OK) {
251 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
258 unsigned char *silc_channel_name_check(const unsigned char *identifier,
259 SilcUInt32 identifier_len,
260 SilcStringEncoding identifier_encoding,
261 SilcUInt32 max_allowed_length,
264 unsigned char *utf8s;
265 SilcUInt32 utf8s_len;
266 SilcStringprepStatus status;
268 if (!identifier || !identifier_len)
271 if (max_allowed_length && identifier_len > max_allowed_length)
274 status = silc_stringprep(identifier, identifier_len,
275 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
276 &utf8s, &utf8s_len, SILC_STRING_UTF8);
277 if (status != SILC_STRINGPREP_OK) {
278 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
283 *out_len = utf8s_len;
288 /* Same as above but does not allocate memory, just checks the
289 validity of the string. */
291 SilcBool silc_channel_name_verify(const unsigned char *identifier,
292 SilcUInt32 identifier_len,
293 SilcStringEncoding identifier_encoding,
294 SilcUInt32 max_allowed_length)
296 SilcStringprepStatus status;
298 if (!identifier || !identifier_len)
301 if (max_allowed_length && identifier_len > max_allowed_length)
304 status = silc_stringprep(identifier, identifier_len,
305 identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
306 NULL, NULL, SILC_STRING_UTF8);
307 if (status != SILC_STRINGPREP_OK) {
308 SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));