berparse.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:10k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include "secutil.h"
  34. typedef enum {
  35.     tagDone, lengthDone, leafDone, compositeDone,
  36.     notDone,
  37.     parseError, parseComplete
  38. } ParseState;
  39. typedef unsigned char Byte;
  40. typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len);
  41. typedef struct {
  42.     SECArb arb;
  43.     int pos; /* length from global start to item start */
  44.     SECArb *parent;
  45. } ParseStackElem;
  46. struct BERParseStr {
  47.     PRArenaPool *his;
  48.     PRArenaPool *mine;
  49.     ParseProc proc;
  50.     int stackDepth;
  51.     ParseStackElem *stackPtr;
  52.     ParseStackElem *stack;
  53.     int pending; /* bytes remaining to complete this part */
  54.     int pos; /* running length of consumed characters */
  55.     ParseState state;
  56.     PRBool keepLeaves;
  57.     PRBool derOnly;
  58.     BERFilterProc filter;
  59.     void *filterArg;
  60.     BERNotifyProc before;
  61.     void *beforeArg;
  62.     BERNotifyProc after;
  63.     void *afterArg;
  64. };
  65. #define UNKNOWN -1
  66. static unsigned char NextChar(BERParse *h, unsigned char **buf, int *len)
  67. {
  68.     unsigned char c = *(*buf)++;
  69.     (*len)--;
  70.     h->pos++;
  71.     if (h->filter)
  72. (*h->filter)(h->filterArg, &c, 1);
  73.     return c;
  74. }
  75. static void ParseTag(BERParse *h, unsigned char **buf, int *len)
  76. {
  77.     SECArb* arb = &(h->stackPtr->arb);
  78.     arb->tag = NextChar(h, buf, len);
  79.     PORT_Assert(h->state == notDone);
  80.   /*
  81.    * NOTE: This does not handle the high-tag-number form
  82.    */
  83.     if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
  84.         PORT_SetError(SEC_ERROR_BAD_DER);
  85. h->state = parseError;
  86. return;
  87.     }
  88.     h->pending = UNKNOWN;
  89.     arb->length = UNKNOWN;
  90.     if (arb->tag & DER_CONSTRUCTED) {
  91. arb->body.cons.numSubs = 0;
  92. arb->body.cons.subs = NULL;
  93.     } else {
  94. arb->body.item.len = UNKNOWN;
  95. arb->body.item.data = NULL;
  96.     }
  97.     h->state = tagDone;
  98. }
  99. static void ParseLength(BERParse *h, unsigned char **buf, int *len)
  100. {
  101.     Byte b;
  102.     SECArb *arb = &(h->stackPtr->arb);
  103.     PORT_Assert(h->state == notDone);
  104.     if (h->pending == UNKNOWN) {
  105. b = NextChar(h, buf, len);
  106. if ((b & 0x80) == 0) { /* short form */
  107.     arb->length = b;
  108.     /*
  109.      * if the tag and the length are both zero bytes, then this
  110.      * should be the marker showing end of list for the
  111.      * indefinite length composite
  112.      */
  113.     if (arb->length == 0 && arb->tag == 0)
  114. h->state = compositeDone;
  115.     else
  116. h->state = lengthDone;
  117.     return;
  118. }
  119. h->pending = b & 0x7f;
  120. /* 0 implies this is an indefinite length */
  121. if (h->pending > 4) {
  122.     PORT_SetError(SEC_ERROR_BAD_DER);
  123.     h->state = parseError;
  124.     return;
  125. }
  126. arb->length = 0;
  127.     }
  128.     while ((*len > 0) && (h->pending > 0)) {
  129. b = NextChar(h, buf, len);
  130. arb->length = (arb->length << 8) + b;
  131. h->pending--;
  132.     }
  133.     if (h->pending == 0) {
  134. if (h->derOnly && (arb->length == 0))
  135.     h->state = parseError;
  136. else
  137.     h->state = lengthDone;
  138.     }
  139.     return;
  140. }
  141. static void ParseLeaf(BERParse *h, unsigned char **buf, int *len)
  142. {
  143.     int count;
  144.     SECArb *arb = &(h->stackPtr->arb);
  145.     PORT_Assert(h->state == notDone);
  146.     PORT_Assert(h->pending >= 0);
  147.     if (*len < h->pending)
  148. count = *len;
  149.     else
  150. count = h->pending;
  151.     if (h->keepLeaves)
  152. memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
  153.     if (h->filter)
  154. (*h->filter)(h->filterArg, *buf, count);
  155.     *buf += count;
  156.     *len -= count;
  157.     arb->body.item.len += count;
  158.     h->pending -= count;
  159.     h->pos += count;
  160.     if (h->pending == 0) {
  161. h->state = leafDone;
  162.     }
  163.     return;
  164. }
  165. static void CreateArbNode(BERParse *h)
  166. {
  167.     SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
  168.     *arb = h->stackPtr->arb;
  169.     /* 
  170.      * Special case closing the root
  171.      */
  172.     if (h->stackPtr == h->stack) {
  173. PORT_Assert(arb->tag & DER_CONSTRUCTED);
  174. h->state = parseComplete;
  175.     } else {
  176. SECArb *parent = h->stackPtr->parent;
  177. parent->body.cons.subs = DS_ArenaGrow(
  178.     h->his, parent->body.cons.subs,
  179.     (parent->body.cons.numSubs) * sizeof(SECArb*),
  180.     (parent->body.cons.numSubs + 1) * sizeof(SECArb*));
  181. parent->body.cons.subs[parent->body.cons.numSubs] = arb;
  182. parent->body.cons.numSubs++;
  183. h->proc = ParseTag;
  184. h->state = notDone;
  185. h->pending = UNKNOWN;
  186.     }
  187.     if (h->after)
  188. (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
  189. }
  190. SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len)
  191. {
  192.     if (h->state == parseError) return PR_TRUE;
  193.     while (len) {
  194.         (*h->proc)(h, &buf, &len);
  195. if (h->state == parseComplete) {
  196.     PORT_SetError(SEC_ERROR_BAD_DER);
  197.     h->state = parseError;
  198.     return PR_TRUE;
  199. }
  200. if (h->state == parseError) return PR_TRUE;
  201. PORT_Assert(h->state != parseComplete);
  202.         if (h->state <= compositeDone) {
  203.     if (h->proc == ParseTag) {
  204. PORT_Assert(h->state == tagDone);
  205. h->proc = ParseLength;
  206. h->state = notDone;
  207.     } else if (h->proc == ParseLength) {
  208. SECArb *arb = &(h->stackPtr->arb);
  209. PORT_Assert(h->state == lengthDone || h->state == compositeDone);
  210. if (h->before)
  211.     (*h->before)(h->beforeArg, arb,
  212.  h->stackPtr - h->stack, PR_TRUE);
  213. /*
  214.  * Check to see if this is the end of an indefinite
  215.  * length composite
  216.  */
  217. if (h->state == compositeDone) {
  218.     SECArb *parent = h->stackPtr->parent;
  219.     PORT_Assert(parent);
  220.     PORT_Assert(parent->tag & DER_CONSTRUCTED);
  221.     if (parent->length != 0) {
  222. PORT_SetError(SEC_ERROR_BAD_DER);
  223. h->state = parseError;
  224. return PR_TRUE;
  225.     }
  226.     /*
  227.      * NOTE: This does not check for an indefinite length
  228.      * composite being contained inside a definite length
  229.      * composite. It is not clear that is legal.
  230.      */
  231.     h->stackPtr--;
  232.     CreateArbNode(h);
  233. } else {
  234.     h->stackPtr->pos = h->pos;
  235.     if (arb->tag & DER_CONSTRUCTED) {
  236. SECArb *parent;
  237. /*
  238.  * Make sure there is room on the stack before we
  239.  * stick anything else there.
  240.  */
  241. PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
  242. if (h->stackPtr - h->stack == h->stackDepth - 1) {
  243.     int newDepth = h->stackDepth * 2;
  244.     h->stack = DS_ArenaGrow(h->mine, h->stack,
  245. sizeof(ParseStackElem) * h->stackDepth,
  246. sizeof(ParseStackElem) * newDepth);
  247.     h->stackPtr = h->stack + h->stackDepth + 1;
  248.     h->stackDepth = newDepth;
  249. }
  250. parent = &(h->stackPtr->arb);
  251. h->stackPtr++;
  252. h->stackPtr->parent = parent;
  253. h->proc = ParseTag;
  254. h->state = notDone;
  255. h->pending = UNKNOWN;
  256.     } else {
  257. if (arb->length < 0) {
  258.     PORT_SetError(SEC_ERROR_BAD_DER);
  259.     h->state = parseError;
  260.     return PR_TRUE;
  261. }
  262. arb->body.item.len = 0;
  263. if (arb->length > 0 && h->keepLeaves) {
  264.     arb->body.item.data =
  265. PORT_ArenaAlloc(h->his, arb->length);
  266. } else {
  267.     arb->body.item.data = NULL;
  268. }
  269. h->proc = ParseLeaf;
  270. h->state = notDone;
  271. h->pending = arb->length;
  272.     }
  273. }
  274.     } else {
  275. ParseStackElem *parent;
  276. PORT_Assert(h->state = leafDone);
  277. PORT_Assert(h->proc == ParseLeaf);
  278. for (;;) {
  279.     CreateArbNode(h);
  280.     if (h->stackPtr == h->stack)
  281. break;
  282.     parent = (h->stackPtr - 1);
  283.     PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
  284.     if (parent->arb.length == 0) /* need explicit end */
  285. break;
  286.     if (parent->pos + parent->arb.length > h->pos)
  287. break;
  288.     if (parent->pos + parent->arb.length < h->pos) {
  289. PORT_SetError(SEC_ERROR_BAD_DER);
  290. h->state = parseError;
  291. return PR_TRUE;
  292.     }
  293.     h->stackPtr = parent;
  294. }
  295.     }
  296. }
  297.     }
  298.     return PR_FALSE;
  299. }
  300. BERParse *BER_ParseInit(PRArenaPool *arena, PRBool derOnly)
  301. {
  302.     BERParse *h;
  303.     PRArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  304.     if (temp == NULL) {
  305. PORT_SetError(SEC_ERROR_NO_MEMORY);
  306. return NULL;
  307.     }
  308.     h = PORT_ArenaAlloc(temp, sizeof(BERParse));
  309.     if (h == NULL) {
  310. PORT_FreeArena(temp, PR_FALSE);
  311. PORT_SetError(SEC_ERROR_NO_MEMORY);
  312. return NULL;
  313.     }
  314.     h->his = arena;
  315.     h->mine = temp;
  316.     h->proc = ParseTag;
  317.     h->stackDepth = 20;
  318.     h->stack = PORT_ArenaZAlloc(h->mine,
  319.       sizeof(ParseStackElem) * h->stackDepth);
  320.     h->stackPtr = h->stack;
  321.     h->state = notDone;
  322.     h->pos = 0;
  323.     h->keepLeaves = PR_TRUE;
  324.     h->before = NULL;
  325.     h->after = NULL;
  326.     h->filter = NULL;
  327.     h->derOnly = derOnly;
  328.     return h;
  329. }
  330. SECArb *BER_ParseFini(BERParse *h)
  331. {
  332.     PRArenaPool *myArena = h->mine;
  333.     SECArb *arb;
  334.     if (h->state != parseComplete) {
  335. arb = NULL;
  336.     } else {
  337. arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
  338. *arb = h->stackPtr->arb;
  339.     }
  340.     PORT_FreeArena(myArena, PR_FALSE);
  341.     return arb;
  342. }
  343. void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance)
  344. {
  345.     h->filter = proc;
  346.     h->filterArg = instance;
  347. }
  348. void BER_SetLeafStorage(BERParse *h, PRBool keep)
  349. {
  350.     h->keepLeaves = keep;
  351. }
  352. void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
  353.       PRBool beforeData)
  354. {
  355.     if (beforeData) {
  356. h->before = proc;
  357. h->beforeArg = instance;
  358.     } else {
  359. h->after = proc;
  360. h->afterArg = instance;
  361.     }
  362. }