a_mbstr.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:11k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* a_mbstr.c */
  2. /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
  3.  * project 1999.
  4.  */
  5. /* ====================================================================
  6.  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  *
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer. 
  14.  *
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in
  17.  *    the documentation and/or other materials provided with the
  18.  *    distribution.
  19.  *
  20.  * 3. All advertising materials mentioning features or use of this
  21.  *    software must display the following acknowledgment:
  22.  *    "This product includes software developed by the OpenSSL Project
  23.  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24.  *
  25.  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26.  *    endorse or promote products derived from this software without
  27.  *    prior written permission. For written permission, please contact
  28.  *    licensing@OpenSSL.org.
  29.  *
  30.  * 5. Products derived from this software may not be called "OpenSSL"
  31.  *    nor may "OpenSSL" appear in their names without prior written
  32.  *    permission of the OpenSSL Project.
  33.  *
  34.  * 6. Redistributions of any form whatsoever must retain the following
  35.  *    acknowledgment:
  36.  *    "This product includes software developed by the OpenSSL Project
  37.  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38.  *
  39.  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  51.  * ====================================================================
  52.  *
  53.  * This product includes cryptographic software written by Eric Young
  54.  * (eay@cryptsoft.com).  This product includes software written by Tim
  55.  * Hudson (tjh@cryptsoft.com).
  56.  *
  57.  */
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include "cryptlib.h"
  61. #include <openssl/asn1.h>
  62. static int traverse_string(const unsigned char *p, int len, int inform,
  63.  int (*rfunc)(unsigned long value, void *in), void *arg);
  64. static int in_utf8(unsigned long value, void *arg);
  65. static int out_utf8(unsigned long value, void *arg);
  66. static int type_str(unsigned long value, void *arg);
  67. static int cpy_asc(unsigned long value, void *arg);
  68. static int cpy_bmp(unsigned long value, void *arg);
  69. static int cpy_univ(unsigned long value, void *arg);
  70. static int cpy_utf8(unsigned long value, void *arg);
  71. static int is_printable(unsigned long value);
  72. /* These functions take a string in UTF8, ASCII or multibyte form and
  73.  * a mask of permissible ASN1 string types. It then works out the minimal
  74.  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
  75.  * and creates a string of the correct type with the supplied data.
  76.  * Yes this is horrible: it has to be :-(
  77.  * The 'ncopy' form checks minimum and maximum size limits too.
  78.  */
  79. int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
  80. int inform, unsigned long mask)
  81. {
  82. return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
  83. }
  84. int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
  85. int inform, unsigned long mask, 
  86. long minsize, long maxsize)
  87. {
  88. int str_type;
  89. int ret;
  90. char free_out;
  91. int outform, outlen;
  92. ASN1_STRING *dest;
  93. unsigned char *p;
  94. int nchar;
  95. char strbuf[32];
  96. int (*cpyfunc)(unsigned long,void *) = NULL;
  97. if(len == -1) len = strlen((const char *)in);
  98. if(!mask) mask = DIRSTRING_TYPE;
  99. /* First do a string check and work out the number of characters */
  100. switch(inform) {
  101. case MBSTRING_BMP:
  102. if(len & 1) {
  103. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
  104.  ASN1_R_INVALID_BMPSTRING_LENGTH);
  105. return -1;
  106. }
  107. nchar = len >> 1;
  108. break;
  109. case MBSTRING_UNIV:
  110. if(len & 3) {
  111. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
  112.  ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
  113. return -1;
  114. }
  115. nchar = len >> 2;
  116. break;
  117. case MBSTRING_UTF8:
  118. nchar = 0;
  119. /* This counts the characters and does utf8 syntax checking */
  120. ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
  121. if(ret < 0) {
  122. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
  123.  ASN1_R_INVALID_UTF8STRING);
  124. return -1;
  125. }
  126. break;
  127. case MBSTRING_ASC:
  128. nchar = len;
  129. break;
  130. default:
  131. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
  132. return -1;
  133. }
  134. if((minsize > 0) && (nchar < minsize)) {
  135. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
  136. BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
  137. ERR_add_error_data(2, "minsize=", strbuf);
  138. return -1;
  139. }
  140. if((maxsize > 0) && (nchar > maxsize)) {
  141. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
  142. BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
  143. ERR_add_error_data(2, "maxsize=", strbuf);
  144. return -1;
  145. }
  146. /* Now work out minimal type (if any) */
  147. if(traverse_string(in, len, inform, type_str, &mask) < 0) {
  148. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
  149. return -1;
  150. }
  151. /* Now work out output format and string type */
  152. outform = MBSTRING_ASC;
  153. if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
  154. else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
  155. else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
  156. else if(mask & B_ASN1_BMPSTRING) {
  157. str_type = V_ASN1_BMPSTRING;
  158. outform = MBSTRING_BMP;
  159. } else if(mask & B_ASN1_UNIVERSALSTRING) {
  160. str_type = V_ASN1_UNIVERSALSTRING;
  161. outform = MBSTRING_UNIV;
  162. } else {
  163. str_type = V_ASN1_UTF8STRING;
  164. outform = MBSTRING_UTF8;
  165. }
  166. if(!out) return str_type;
  167. if(*out) {
  168. free_out = 0;
  169. dest = *out;
  170. if(dest->data) {
  171. dest->length = 0;
  172. OPENSSL_free(dest->data);
  173. dest->data = NULL;
  174. }
  175. dest->type = str_type;
  176. } else {
  177. free_out = 1;
  178. dest = ASN1_STRING_type_new(str_type);
  179. if(!dest) {
  180. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
  181. ERR_R_MALLOC_FAILURE);
  182. return -1;
  183. }
  184. *out = dest;
  185. }
  186. /* If both the same type just copy across */
  187. if(inform == outform) {
  188. if(!ASN1_STRING_set(dest, in, len)) {
  189. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,ERR_R_MALLOC_FAILURE);
  190. return -1;
  191. }
  192. return str_type;
  193. /* Work out how much space the destination will need */
  194. switch(outform) {
  195. case MBSTRING_ASC:
  196. outlen = nchar;
  197. cpyfunc = cpy_asc;
  198. break;
  199. case MBSTRING_BMP:
  200. outlen = nchar << 1;
  201. cpyfunc = cpy_bmp;
  202. break;
  203. case MBSTRING_UNIV:
  204. outlen = nchar << 2;
  205. cpyfunc = cpy_univ;
  206. break;
  207. case MBSTRING_UTF8:
  208. outlen = 0;
  209. traverse_string(in, len, inform, out_utf8, &outlen);
  210. cpyfunc = cpy_utf8;
  211. break;
  212. }
  213. if(!(p = OPENSSL_malloc(outlen + 1))) {
  214. if(free_out) ASN1_STRING_free(dest);
  215. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,ERR_R_MALLOC_FAILURE);
  216. return -1;
  217. }
  218. dest->length = outlen;
  219. dest->data = p;
  220. p[outlen] = 0;
  221. traverse_string(in, len, inform, cpyfunc, &p);
  222. return str_type;
  223. }
  224. /* This function traverses a string and passes the value of each character
  225.  * to an optional function along with a void * argument.
  226.  */
  227. static int traverse_string(const unsigned char *p, int len, int inform,
  228.  int (*rfunc)(unsigned long value, void *in), void *arg)
  229. {
  230. unsigned long value;
  231. int ret;
  232. while(len) {
  233. if(inform == MBSTRING_ASC) {
  234. value = *p++;
  235. len--;
  236. } else if(inform == MBSTRING_BMP) {
  237. value = *p++ << 8;
  238. value |= *p++;
  239. len -= 2;
  240. } else if(inform == MBSTRING_UNIV) {
  241. value = ((unsigned long)*p++) << 24;
  242. value |= ((unsigned long)*p++) << 16;
  243. value |= *p++ << 8;
  244. value |= *p++;
  245. len -= 4;
  246. } else {
  247. ret = UTF8_getc(p, len, &value);
  248. if(ret < 0) return -1;
  249. len -= ret;
  250. p += ret;
  251. }
  252. if(rfunc) {
  253. ret = rfunc(value, arg);
  254. if(ret <= 0) return ret;
  255. }
  256. }
  257. return 1;
  258. }
  259. /* Various utility functions for traverse_string */
  260. /* Just count number of characters */
  261. static int in_utf8(unsigned long value, void *arg)
  262. {
  263. int *nchar;
  264. nchar = arg;
  265. (*nchar)++;
  266. return 1;
  267. }
  268. /* Determine size of output as a UTF8 String */
  269. static int out_utf8(unsigned long value, void *arg)
  270. {
  271. int *outlen;
  272. outlen = arg;
  273. *outlen += UTF8_putc(NULL, -1, value);
  274. return 1;
  275. }
  276. /* Determine the "type" of a string: check each character against a
  277.  * supplied "mask".
  278.  */
  279. static int type_str(unsigned long value, void *arg)
  280. {
  281. unsigned long types;
  282. types = *((unsigned long *)arg);
  283. if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
  284. types &= ~B_ASN1_PRINTABLESTRING;
  285. if((types & B_ASN1_IA5STRING) && (value > 127))
  286. types &= ~B_ASN1_IA5STRING;
  287. if((types & B_ASN1_T61STRING) && (value > 0xff))
  288. types &= ~B_ASN1_T61STRING;
  289. if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
  290. types &= ~B_ASN1_BMPSTRING;
  291. if(!types) return -1;
  292. *((unsigned long *)arg) = types;
  293. return 1;
  294. }
  295. /* Copy one byte per character ASCII like strings */
  296. static int cpy_asc(unsigned long value, void *arg)
  297. {
  298. unsigned char **p, *q;
  299. p = arg;
  300. q = *p;
  301. *q = (unsigned char) value;
  302. (*p)++;
  303. return 1;
  304. }
  305. /* Copy two byte per character BMPStrings */
  306. static int cpy_bmp(unsigned long value, void *arg)
  307. {
  308. unsigned char **p, *q;
  309. p = arg;
  310. q = *p;
  311. *q++ = (unsigned char) ((value >> 8) & 0xff);
  312. *q = (unsigned char) (value & 0xff);
  313. *p += 2;
  314. return 1;
  315. }
  316. /* Copy four byte per character UniversalStrings */
  317. static int cpy_univ(unsigned long value, void *arg)
  318. {
  319. unsigned char **p, *q;
  320. p = arg;
  321. q = *p;
  322. *q++ = (unsigned char) ((value >> 24) & 0xff);
  323. *q++ = (unsigned char) ((value >> 16) & 0xff);
  324. *q++ = (unsigned char) ((value >> 8) & 0xff);
  325. *q = (unsigned char) (value & 0xff);
  326. *p += 4;
  327. return 1;
  328. }
  329. /* Copy to a UTF8String */
  330. static int cpy_utf8(unsigned long value, void *arg)
  331. {
  332. unsigned char **p;
  333. int ret;
  334. p = arg;
  335. /* We already know there is enough room so pass 0xff as the length */
  336. ret = UTF8_putc(*p, 0xff, value);
  337. *p += ret;
  338. return 1;
  339. }
  340. /* Return 1 if the character is permitted in a PrintableString */
  341. static int is_printable(unsigned long value)
  342. {
  343. int ch;
  344. if(value > 0x7f) return 0;
  345. ch = (int) value;
  346. /* Note: we can't use 'isalnum' because certain accented 
  347.  * characters may count as alphanumeric in some environments.
  348.  */
  349. #ifndef CHARSET_EBCDIC
  350. if((ch >= 'a') && (ch <= 'z')) return 1;
  351. if((ch >= 'A') && (ch <= 'Z')) return 1;
  352. if((ch >= '0') && (ch <= '9')) return 1;
  353. if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
  354. #else /*CHARSET_EBCDIC*/
  355. if((ch >= os_toascii['a']) && (ch <= os_toascii['z'])) return 1;
  356. if((ch >= os_toascii['A']) && (ch <= os_toascii['Z'])) return 1;
  357. if((ch >= os_toascii['0']) && (ch <= os_toascii['9'])) return 1;
  358. if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch])) return 1;
  359. #endif /*CHARSET_EBCDIC*/
  360. return 0;
  361. }