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

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* 
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include <string.h>
  35. #include <assert.h>
  36. #ifdef WIN32
  37. #include <winsock.h>
  38. #endif
  39. #ifdef XP_MAC
  40. #include "macsocket.h"
  41. #endif
  42. #ifdef XP_UNIX
  43. #include "sys/types.h"
  44. #include "netinet/in.h" /* for ntohl & htonl */
  45. #endif
  46. #ifdef XP_OS2_EMX
  47. #include <sys/param.h>
  48. #endif
  49. #ifdef XP_OS2_VACPP
  50. #include <utils.h>
  51. #endif
  52. #ifdef XP_BEOS
  53. #include "ByteOrder.h"
  54. #endif
  55. #include "newproto.h"
  56. char SSMVersionString[] = "1.3";
  57. CMT_Alloc_fn cmt_alloc = malloc;
  58. CMT_Free_fn cmt_free = free;
  59. #define ASSERT(x) assert(x)
  60. #define CM_ntohl ntohl
  61. #define CM_htonl htonl
  62. char* SSM_GetVersionString(void)
  63. {
  64.     char *newString;
  65.     int strLen;
  66.     strLen = strlen(SSMVersionString);
  67.     newString = (char*)malloc(sizeof(char)*(strLen+1));
  68.     if (newString) {
  69.         memcpy(newString,SSMVersionString, strlen(SSMVersionString));
  70.         newString[strLen]='';
  71.     }
  72.     return newString;
  73. }
  74. /*************************************************************
  75.  *
  76.  * CMT_Init
  77.  *
  78.  *
  79.  ************************************************************/
  80. void
  81. CMT_Init(CMT_Alloc_fn allocfn, CMT_Free_fn freefn)
  82. {
  83.     cmt_alloc = allocfn;
  84.     cmt_free = freefn;
  85. }
  86. static CMTStatus
  87. decode_int(unsigned char **curptr, void *dest, CMInt32 *remaining)
  88. {
  89.     CMInt32 datalen = sizeof(CMInt32);
  90.     if (*remaining < datalen)
  91.         return CMTFailure;
  92.     *(CMInt32 *)dest = ntohl(**(CMInt32 **)curptr);
  93.     *remaining -= datalen;
  94.     *curptr += datalen;
  95.     return CMTSuccess;
  96. }
  97. static CMTStatus
  98. decode_string(unsigned char **curptr, CMInt32 *len,
  99.               unsigned char **data, CMInt32 *remaining)
  100. {
  101.     CMTStatus rv;
  102.     CMInt32 datalen;
  103.     rv = decode_int(curptr, len, remaining);
  104.     if (rv != CMTSuccess)
  105.         return CMTFailure;
  106.     /* NULL string */
  107.     if (*len == 0) {
  108.         *data = NULL;
  109.         goto done;
  110.     }
  111.     datalen = (*len + 3) & ~3;
  112.     if (*remaining < datalen)
  113.         return CMTFailure;
  114.     *data = (unsigned char *) cmt_alloc(*len + 1);
  115.     if (*data == NULL)
  116.         return CMTFailure;
  117.     memcpy(*data, *curptr, *len);
  118.     (*data)[*len] = 0;
  119.     *remaining -= datalen;
  120.     *curptr += datalen;
  121. done:
  122.     return CMTSuccess;
  123. }
  124. /*************************************************************
  125.  * CMT_DecodeMessage
  126.  *
  127.  * Decode msg into dest as specified by tmpl.
  128.  *
  129.  ************************************************************/
  130. CMTStatus
  131. CMT_DecodeMessage(CMTMessageTemplate *tmpl, void *dest, CMTItem *msg)
  132. {
  133.     unsigned char *curptr, *destptr, *list;
  134. void ** ptr;
  135.     CMInt32 remaining, len, choiceID = 0, listSize, listCount = 0;
  136.     CMBool inChoice = CM_FALSE, foundChoice = CM_FALSE, inList = CM_FALSE;
  137.     CMInt32 listItemSize = 0;
  138.     CMTStatus rv = CMTSuccess;
  139. CMTMessageTemplate *startOfList, *p;
  140. CMBool inStructList = CM_FALSE;
  141.     curptr = msg->data;
  142.     remaining = msg->len;
  143.     while(tmpl->type != CMT_DT_END) {
  144.         /* XXX Maybe this should be a more formal state machine? */
  145.         if (inChoice) {
  146.             if (tmpl->type == CMT_DT_END_CHOICE) {
  147.                 if (!foundChoice)
  148.                     goto loser;
  149.                 inChoice = CM_FALSE;
  150.                 foundChoice = CM_FALSE;
  151.                 tmpl++;
  152.                 continue;
  153.             }
  154.             if (choiceID != tmpl->choiceID) {
  155.                 tmpl++;
  156.                 continue;  /* Not this option */
  157.             } else {
  158.                 foundChoice = CM_TRUE;
  159.             }
  160.         }
  161.         if (inList) {
  162.             destptr = &list[listCount * listItemSize];
  163.             listCount++;
  164.         } else {
  165. if (inStructList) {
  166. destptr = tmpl->offset + list;
  167. } else {
  168. destptr = tmpl->offset + (unsigned char *)dest;
  169. }
  170.         }
  171.         switch (tmpl->type) {
  172.           case CMT_DT_RID:
  173.           case CMT_DT_INT:
  174.           case CMT_DT_BOOL:
  175.             rv = decode_int(&curptr, destptr, &remaining);
  176.             if (rv != CMTSuccess)
  177.                 goto loser;
  178.             break;
  179.           case CMT_DT_STRING:
  180.             rv = decode_string(&curptr, &len, (unsigned char **)destptr,
  181.                                &remaining);
  182.             if (rv != CMTSuccess)
  183.                 goto loser;
  184.             break;
  185.           case CMT_DT_ITEM:
  186.             rv = decode_string(&curptr, (long *) &((CMTItem *)destptr)->len,
  187.                                &((CMTItem *)destptr)->data, &remaining);
  188.             if (rv != CMTSuccess)
  189.                 goto loser;
  190.             break;
  191.           case CMT_DT_LIST:
  192.             /* XXX This is too complicated */
  193.             rv = decode_int(&curptr, destptr, &remaining);
  194.             if (rv != CMTSuccess)
  195.                 goto loser;
  196.             listSize = *(CMInt32 *)destptr;
  197.             tmpl++;
  198.             if (tmpl->type == CMT_DT_STRING) {
  199.                 listItemSize = sizeof(unsigned char *);
  200.             } else if (tmpl->type == CMT_DT_ITEM) {
  201.                 listItemSize = sizeof(CMTItem);
  202.             } else {
  203.                 listItemSize = sizeof(CMInt32);
  204.             }
  205.             if (listSize == 0) {
  206.                 list = NULL;
  207.             } else {
  208.                 list = (unsigned char *) cmt_alloc(listSize * listItemSize);
  209.             }
  210.             *(void **)(tmpl->offset + (unsigned char *)dest) = list;
  211.             inList = CM_TRUE;
  212.             listCount = 0;
  213.             break;
  214.           case CMT_DT_STRUCT_LIST:
  215.             /* XXX This is too complicated */
  216.             rv = decode_int(&curptr, destptr, &remaining);
  217.             if (rv != CMTSuccess)
  218.                 goto loser;
  219.             listSize = *(CMInt32 *)destptr;
  220.             tmpl++;
  221. if (tmpl->type != CMT_DT_STRUCT_PTR) {
  222. goto loser;
  223. }
  224. ptr = (void**)(tmpl->offset + (unsigned char *)dest);
  225. startOfList = tmpl;
  226. p = tmpl;
  227. listItemSize = 0;
  228. while (p->type != CMT_DT_END_STRUCT_LIST) {
  229. if (p->type == CMT_DT_STRING) {
  230. listItemSize += sizeof(unsigned char *);
  231. } else if (p->type == CMT_DT_ITEM) {
  232. listItemSize += sizeof(CMTItem);
  233. } else if (p->type == CMT_DT_INT) {
  234.                 listItemSize += sizeof(CMInt32);
  235.         }
  236. p++;
  237. }
  238.             if (listSize == 0) {
  239.                 list = NULL;
  240.             } else {
  241.                 list = (unsigned char *) cmt_alloc(listSize * listItemSize);
  242.             }
  243.             *ptr = list;
  244.             inStructList = CM_TRUE;
  245.             listCount = 0;
  246.             break;
  247.   case CMT_DT_END_STRUCT_LIST:
  248. listCount++;
  249. if (listCount == listSize) {
  250. inStructList = CM_FALSE;
  251. } else {
  252. list += listItemSize;
  253. tmpl = startOfList;
  254. }
  255. break;
  256.           case CMT_DT_CHOICE:
  257.             rv = decode_int(&curptr, destptr, &remaining);
  258.             if (rv != CMTSuccess)
  259.                 goto loser;
  260.             choiceID = *(CMInt32 *)destptr;
  261.             inChoice = CM_TRUE;
  262.             foundChoice = CM_FALSE;
  263.             break;
  264.           case CMT_DT_END_CHOICE: /* Loop should exit before we see these. */
  265.           case CMT_DT_END:
  266.           default:
  267.             ASSERT(0);
  268.             break;
  269.         }
  270.         if (inList) {
  271.             if (listCount == listSize) {
  272.                 inList = CM_FALSE;
  273.                 tmpl++;
  274.             }
  275.         } else {
  276.             tmpl++;
  277.         }
  278.     }
  279. loser:
  280.     /* Free the data buffer */
  281.     if (msg->data) {
  282.         cmt_free(msg->data);
  283.         msg->data = NULL;
  284.     }
  285.     return rv;
  286. }
  287. static CMTStatus
  288. calc_msg_len(CMTMessageTemplate *tmpl, void *src, CMInt32 *len_out)
  289. {
  290.     CMInt32 len = 0, choiceID = 0, listSize, listItemSize, listCount;
  291.     unsigned char *srcptr, *list;
  292.     CMBool inChoice = CM_FALSE, inList = CM_FALSE, foundChoice = CM_FALSE;
  293. CMTMessageTemplate *startOfList, *p;
  294. CMBool inStructList = CM_FALSE;
  295.     while(tmpl->type != CMT_DT_END) {
  296.         if (inChoice) {
  297.             if (tmpl->type == CMT_DT_END_CHOICE) {
  298.                 if (!foundChoice)
  299.                     goto loser;
  300.                 inChoice = CM_FALSE;
  301.                 foundChoice = CM_FALSE;
  302.                 tmpl++;
  303.                 continue;
  304.             }
  305.             if (choiceID != tmpl->choiceID) {
  306.                 tmpl++;
  307.                 continue;  /* Not this option */
  308.             } else {
  309.                 foundChoice = CM_TRUE;
  310.             }
  311.         }
  312.         if (inList) {
  313.             srcptr = &list[listCount * listItemSize];
  314.             listCount++;
  315.         } else if (inStructList) {
  316. srcptr = tmpl->offset + list;
  317. } else {
  318.             srcptr = tmpl->offset + (unsigned char *)src;
  319.         }
  320.         switch(tmpl->type) {
  321.           case CMT_DT_RID:
  322.           case CMT_DT_INT:
  323.           case CMT_DT_BOOL:
  324.             len += sizeof(CMInt32);
  325.             break;
  326.           case CMT_DT_STRING:
  327.             len += sizeof(CMInt32);
  328.             /* Non NULL string */
  329.             if (*(char**)srcptr) {
  330.                 len += (strlen(*(char**)srcptr) + 4) & ~3;
  331.             }
  332.             break;
  333.           case CMT_DT_ITEM:
  334.             len += sizeof(CMInt32);
  335.             len += (((CMTItem *)srcptr)->len + 3) & ~3;
  336.             break;
  337.           case CMT_DT_LIST:
  338.             len += sizeof(CMInt32);
  339.             listSize = *(CMInt32 *)srcptr;
  340.             tmpl++;
  341.             if (tmpl->type == CMT_DT_STRING) {
  342.                 listItemSize = sizeof(unsigned char *);
  343.             } else if (tmpl->type == CMT_DT_ITEM) {
  344.                 listItemSize = sizeof(CMTItem);
  345.             } else {
  346.                 listItemSize = sizeof(CMInt32);
  347.             }
  348.             list = *(unsigned char **)(tmpl->offset + (unsigned char *)src);
  349.             listCount = 0;
  350.             inList = CM_TRUE;
  351.             break;
  352.   case CMT_DT_STRUCT_LIST:
  353. len += sizeof(CMInt32);
  354. listSize = *(CMInt32 *)srcptr;
  355. tmpl++;
  356. if (tmpl->type != CMT_DT_STRUCT_PTR) {
  357. goto loser;
  358. }
  359. list = *(unsigned char**)(tmpl->offset + (unsigned char*)src);
  360. startOfList = tmpl;
  361. p = tmpl;
  362. listItemSize = 0;
  363. while (p->type != CMT_DT_END_STRUCT_LIST) {
  364. if (p->type == CMT_DT_STRING) {
  365. listItemSize += sizeof(unsigned char *);
  366. } else if (p->type == CMT_DT_ITEM) {
  367. listItemSize += sizeof(CMTItem);
  368. } else if (p->type == CMT_DT_INT) {
  369. listItemSize += sizeof(CMInt32);
  370. }
  371. p++;
  372. }
  373. listCount = 0;
  374. inStructList = CM_TRUE;
  375. break;
  376.   case CMT_DT_END_STRUCT_LIST:
  377. listCount++;
  378. if (listCount == listSize) {
  379. inStructList = CM_FALSE;
  380. } else {
  381. list += listItemSize;
  382. tmpl = startOfList;
  383. }
  384. break;
  385.           case CMT_DT_CHOICE:
  386.             len += sizeof(CMInt32);
  387.             choiceID = *(CMInt32 *)srcptr;
  388.             inChoice = CM_TRUE;
  389.             foundChoice = CM_FALSE;
  390.             break;
  391.           case CMT_DT_END_CHOICE: /* Loop should exit before we see these. */
  392.           case CMT_DT_END:
  393.           default:
  394.             ASSERT(0);
  395.             break;
  396.         }
  397.         if (inList) {
  398.             if (listCount == listSize) {
  399.                 inList = CM_FALSE;
  400.                 tmpl++;
  401.             }
  402.         } else {
  403.             tmpl++;
  404.         }
  405.     }
  406.     *len_out = len;
  407.     return CMTSuccess;
  408. loser:
  409.     return CMTFailure;
  410. }
  411. static CMTStatus
  412. encode_int(unsigned char **curptr, void *src, CMInt32 *remaining)
  413. {
  414.     CMInt32 datalen = sizeof(CMInt32);
  415.     if (*remaining < datalen)
  416.         return CMTFailure;
  417.     **(CMInt32 **)curptr = CM_htonl(*(CMInt32 *)src);
  418.     *remaining -= datalen;
  419.     *curptr += datalen;
  420.     return CMTSuccess;
  421. }
  422. static CMTStatus
  423. encode_string(unsigned char **curptr, CMInt32 len,
  424.               unsigned char *data, CMInt32 *remaining)
  425. {
  426.     CMTStatus rv;
  427.     CMInt32 datalen;
  428.     rv = encode_int(curptr, &len, remaining);
  429.     if (rv != CMTSuccess)
  430.         return CMTFailure;
  431.     /* NULL string */
  432.     if (len == 0) {
  433.         goto done;
  434.     }
  435.     datalen = (len + 3) & ~3;
  436.     if (*remaining < datalen)
  437.         return CMTFailure;
  438.     memcpy(*curptr, data, len);
  439.     *remaining -= datalen;
  440.     *curptr += datalen;
  441. done:
  442.     return CMTSuccess;
  443. }
  444. /*************************************************************
  445.  * CMT_EncodeMessage
  446.  *
  447.  * Encode src into msg as specified by tmpl.
  448.  *
  449.  ************************************************************/
  450. CMTStatus
  451. CMT_EncodeMessage(CMTMessageTemplate *tmpl, CMTItem *msg, void *src)
  452. {
  453.     CMInt32 choiceID = 0, listSize, listItemSize, listCount, remaining;
  454.     unsigned char *srcptr, *curptr, *list;
  455.     CMBool inChoice = CM_FALSE, inList = CM_FALSE, foundChoice = CM_FALSE;
  456.     CMTStatus rv = CMTSuccess;
  457. CMTMessageTemplate *startOfList, *p;
  458. CMBool inStructList = CM_FALSE;
  459.     rv = calc_msg_len(tmpl, src, (long *) &msg->len);
  460.     if (rv != CMTSuccess)
  461.         goto loser;
  462.     curptr = msg->data = (unsigned char *) cmt_alloc(msg->len);
  463.     if(msg->data == NULL)
  464.         goto loser;
  465.     remaining = msg->len;
  466.     while(tmpl->type != CMT_DT_END) {
  467.         if (inChoice) {
  468.             if (tmpl->type == CMT_DT_END_CHOICE) {
  469.                 if (!foundChoice)
  470.                     goto loser;
  471.                 inChoice = CM_FALSE;
  472.                 foundChoice = CM_FALSE;
  473.                 tmpl++;
  474.                 continue;
  475.             }
  476.             if (choiceID != tmpl->choiceID) {
  477.                 tmpl++;
  478.                 continue;  /* Not this option */
  479.             } else {
  480.                 foundChoice = CM_TRUE;
  481.             }
  482.         }
  483.         if (inList) {
  484.             srcptr = &list[listCount * listItemSize];
  485.             listCount++;
  486.         } else {
  487. if (inStructList) {
  488. srcptr = tmpl->offset + list;
  489. } else {
  490. srcptr = tmpl->offset + (unsigned char *)src;
  491. }
  492.         }
  493.         switch(tmpl->type) {
  494.           case CMT_DT_RID:
  495.           case CMT_DT_INT:
  496.           case CMT_DT_BOOL:
  497.             rv = encode_int(&curptr, srcptr, &remaining);
  498.             if (rv != CMTSuccess)
  499.                 goto loser;
  500.             break;
  501.           case CMT_DT_STRING:
  502.              if (*(char**)srcptr) {
  503.                  /* Non NULL string */
  504.                  rv = encode_string(&curptr, (long) strlen(*(char**)srcptr), 
  505.                                   *(unsigned char**)srcptr, &remaining);
  506.              } else {
  507.                  /* NULL string */
  508.                  rv = encode_string(&curptr, 0L, *(unsigned char**)srcptr, &remaining);
  509.              }
  510.              if (rv != CMTSuccess)
  511.                 goto loser;
  512.              break;
  513.           case CMT_DT_ITEM:
  514.             rv = encode_string(&curptr, ((CMTItem *)srcptr)->len,
  515.                                ((CMTItem *)srcptr)->data, &remaining);
  516.             if (rv != CMTSuccess)
  517.                 goto loser;
  518.             break;
  519.           case CMT_DT_LIST:
  520.             rv = encode_int(&curptr, srcptr, &remaining);
  521.             if (rv != CMTSuccess)
  522.                 goto loser;
  523.             listSize = *(CMInt32 *)srcptr;
  524.             tmpl++;
  525.             if (tmpl->type == CMT_DT_STRING) {
  526.                 listItemSize = sizeof(unsigned char *);
  527.             } else if (tmpl->type == CMT_DT_ITEM) {
  528.                 listItemSize = sizeof(CMTItem);
  529.             } else {
  530.                 listItemSize = sizeof(CMInt32);
  531.             }
  532.             list = *(unsigned char **)(tmpl->offset + (unsigned char *)src);
  533.             listCount = 0;
  534.             inList = CM_TRUE;
  535.             break;
  536.   case CMT_DT_STRUCT_LIST:
  537.             rv = encode_int(&curptr, srcptr, &remaining);
  538.             if (rv != CMTSuccess)
  539.                 goto loser;
  540.             listSize = *(CMInt32 *)srcptr;
  541. tmpl++;
  542. if (tmpl->type != CMT_DT_STRUCT_PTR) {
  543. goto loser;
  544. }
  545. list = *(unsigned char**)(tmpl->offset + (unsigned char*)src);
  546. startOfList = tmpl;
  547. p = tmpl;
  548. listItemSize = 0;
  549. while (p->type != CMT_DT_END_STRUCT_LIST) {
  550. if (p->type == CMT_DT_STRING) {
  551. listItemSize += sizeof(unsigned char *);
  552. } else if (p->type == CMT_DT_ITEM) {
  553. listItemSize += sizeof(CMTItem);
  554. } else if (p->type == CMT_DT_INT) {
  555. listItemSize += sizeof(CMInt32);
  556. }
  557. p++;
  558. }
  559. listCount = 0;
  560. inStructList = CM_TRUE;
  561. break;
  562.   case CMT_DT_END_STRUCT_LIST:
  563. listCount++;
  564. if (listCount == listSize) {
  565. inStructList = CM_FALSE;
  566. } else {
  567. list += listItemSize;
  568. tmpl = startOfList;
  569. }
  570. break;
  571.           case CMT_DT_CHOICE:
  572.             rv = encode_int(&curptr, srcptr, &remaining);
  573.             if (rv != CMTSuccess)
  574.                 goto loser;
  575.             choiceID = *(CMInt32 *)srcptr;
  576.             inChoice = CM_TRUE;
  577.             foundChoice = CM_FALSE;
  578.             break;
  579.           case CMT_DT_END_CHOICE: /* Loop should exit before we see these. */
  580.           case CMT_DT_END:
  581.           default:
  582.             ASSERT(0);
  583.             break;
  584.         }
  585.         if (inList) {
  586.             if (listCount == listSize) {
  587.                 inList = CM_FALSE;
  588.                 tmpl++;
  589.             }
  590.         } else {
  591.             tmpl++;
  592.         }
  593.     }
  594.     return CMTSuccess;
  595. loser:
  596.     return CMTFailure;
  597. }