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

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. /*
  34.  * secport.c - portability interfaces for security libraries
  35.  *
  36.  * This file abstracts out libc functionality that libsec depends on
  37.  * 
  38.  * NOTE - These are not public interfaces
  39.  *
  40.  * $Id: secport.c,v 1.4 2000/09/20 17:07:22 relyea%netscape.com Exp $
  41.  */
  42. #include "seccomon.h"
  43. #include "prmem.h"
  44. #include "prerror.h"
  45. #include "plarena.h"
  46. #include "secerr.h"
  47. #include "prmon.h"
  48. #include "nsslocks.h"
  49. #include "secport.h"
  50. #ifdef DEBUG
  51. #define THREADMARK
  52. #endif /* DEBUG */
  53. #ifdef THREADMARK
  54. #include "prthread.h"
  55. #endif /* THREADMARK */
  56. #if defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2)
  57. #include <stdlib.h>
  58. #else
  59. #include "wtypes.h"
  60. #endif
  61. #define SET_ERROR_CODE /* place holder for code to set PR error code. */
  62. #ifdef THREADMARK
  63. typedef struct threadmark_mark_str {
  64.   struct threadmark_mark_str *next;
  65.   void *mark;
  66. } threadmark_mark;
  67. typedef struct threadmark_arena_str {
  68.   PLArenaPool arena;
  69.   PRUint32 magic;
  70.   PRThread *marking_thread;
  71.   threadmark_mark *first_mark;
  72. } threadmark_arena;
  73. #define THREADMARK_MAGIC 0xB8AC9BDD /* In honor of nelsonb */
  74. #endif /* THREADMARK */
  75. /* count of allocation failures. */
  76. unsigned long port_allocFailures;
  77. /* locations for registering Unicode conversion functions.  
  78.  * XXX is this the appropriate location?  or should they be
  79.  *     moved to client/server specific locations?
  80.  */
  81. PORTCharConversionFunc ucs4Utf8ConvertFunc;
  82. PORTCharConversionFunc ucs2Utf8ConvertFunc;
  83. PORTCharConversionWSwapFunc  ucs2AsciiConvertFunc;
  84. void *
  85. PORT_Alloc(size_t bytes)
  86. {
  87.     void *rv;
  88.     /* Always allocate a non-zero amount of bytes */
  89.     rv = (void *)PR_Malloc(bytes ? bytes : 1);
  90.     if (!rv) {
  91. ++port_allocFailures;
  92. PORT_SetError(SEC_ERROR_NO_MEMORY);
  93.     }
  94.     return rv;
  95. }
  96. void *
  97. PORT_Realloc(void *oldptr, size_t bytes)
  98. {
  99.     void *rv;
  100.     rv = (void *)PR_Realloc(oldptr, bytes);
  101.     if (!rv) {
  102. ++port_allocFailures;
  103. PORT_SetError(SEC_ERROR_NO_MEMORY);
  104.     }
  105.     return rv;
  106. }
  107. #ifdef XP_MAC
  108. char *
  109. PORT_Strdup(const char *cp)
  110. {
  111. size_t len = PORT_Strlen(cp);
  112. char *buf;
  113. buf = (char *)PORT_Alloc(len+1);
  114. if (buf == NULL) return;
  115. PORT_Memcpy(buf,cp,len+1);
  116. return buf;
  117. }
  118. #endif
  119. void *
  120. PORT_ZAlloc(size_t bytes)
  121. {
  122.     void *rv;
  123.     /* Always allocate a non-zero amount of bytes */
  124.     rv = (void *)PR_Calloc(1, bytes ? bytes : 1);
  125.     if (!rv) {
  126. ++port_allocFailures;
  127. PORT_SetError(SEC_ERROR_NO_MEMORY);
  128.     }
  129.     return rv;
  130. }
  131. void
  132. PORT_Free(void *ptr)
  133. {
  134.     if (ptr) {
  135. PR_Free(ptr);
  136.     }
  137. }
  138. void
  139. PORT_ZFree(void *ptr, size_t len)
  140. {
  141.     if (ptr) {
  142. memset(ptr, 0, len);
  143. PR_Free(ptr);
  144.     }
  145. }
  146. void
  147. PORT_SetError(int value)
  148. {
  149.     PR_SetError(value, 0);
  150.     return;
  151. }
  152. int
  153. PORT_GetError(void)
  154. {
  155.     return(PR_GetError());
  156. }
  157. /********************* Arena code follows *****************************/
  158. PRMonitor * arenaMonitor;
  159. static void
  160. getArenaLock(void)
  161. {
  162.     if (!arenaMonitor) {
  163. nss_InitMonitor(&arenaMonitor);
  164.     }
  165.     if (arenaMonitor) 
  166. PR_EnterMonitor(arenaMonitor);
  167. }
  168. static void
  169. releaseArenaLock(void)
  170. {
  171.     if (arenaMonitor) 
  172. PR_ExitMonitor(arenaMonitor);
  173. }
  174. PLArenaPool *
  175. PORT_NewArena(unsigned long chunksize)
  176. {
  177.     PLArenaPool *arena;
  178.     
  179.     getArenaLock();
  180. #ifdef THREADMARK
  181.     {
  182.       threadmark_arena *tarena = (threadmark_arena *)
  183.         PORT_ZAlloc(sizeof(threadmark_arena));
  184.       if( (threadmark_arena *)NULL != tarena ) {
  185.        arena = &tarena->arena;
  186.        tarena->magic = THREADMARK_MAGIC;
  187.       } else {
  188.         arena = (PLArenaPool *)NULL;
  189.       }
  190.     }
  191. #else /* THREADMARK */
  192.     arena = (PLArenaPool*)PORT_ZAlloc(sizeof(PLArenaPool));
  193. #endif /* THREADMARK */
  194.     if ( arena != NULL ) {
  195. PL_InitArenaPool(arena, "security", chunksize, sizeof(double));
  196.     }
  197.     releaseArenaLock();
  198.     return(arena);
  199. }
  200. void *
  201. PORT_ArenaAlloc(PLArenaPool *arena, size_t size)
  202. {
  203.     void *p;
  204.     getArenaLock();
  205. #ifdef THREADMARK
  206.     {
  207.       /* Is it one of ours?  Assume so and check the magic */
  208.       threadmark_arena *tarena = (threadmark_arena *)arena;
  209.       if( THREADMARK_MAGIC == tarena->magic ) {
  210.         /* Most likely one of ours.  Is there a thread id? */
  211.         if( (PRThread *)NULL != tarena->marking_thread ) {
  212.           /* Yes.  Has this arena been marked by this thread? */
  213.           if( tarena->marking_thread == PR_GetCurrentThread() ) {
  214.             /* Yup.  Everything's okay. */
  215.             ;
  216.           } else {
  217.             /* Nope.  BZZT!  error */
  218.             releaseArenaLock();
  219.             PORT_SetError(SEC_ERROR_NO_MEMORY);
  220.             PORT_Assert(0);
  221.             return (void *)NULL;
  222.           }
  223.         } /* tid != null */
  224.       } /* tarena */
  225.     } /* scope */
  226. #endif /* THREADMARK */
  227.     PL_ARENA_ALLOCATE(p, arena, size);
  228.     releaseArenaLock();
  229.     if (p == NULL) {
  230. ++port_allocFailures;
  231. PORT_SetError(SEC_ERROR_NO_MEMORY);
  232.     }
  233.     return(p);
  234. }
  235. void *
  236. PORT_ArenaZAlloc(PLArenaPool *arena, size_t size)
  237. {
  238.     void *p;
  239.     getArenaLock();
  240. #ifdef THREADMARK
  241.     {
  242.       /* Is it one of ours?  Assume so and check the magic */
  243.       threadmark_arena *tarena = (threadmark_arena *)arena;
  244.       if( THREADMARK_MAGIC == tarena->magic ) {
  245.         /* Most likely one of ours.  Is there a thread id? */
  246.         if( (PRThread *)NULL != tarena->marking_thread ) {
  247.           /* Yes.  Has this arena been marked by this thread? */
  248.           if( tarena->marking_thread == PR_GetCurrentThread() ) {
  249.             /* Yup.  Everything's okay. */
  250.             ;
  251.           } else {
  252.             /* No, it was a different thread  BZZT!  error */
  253.             releaseArenaLock();
  254.             PORT_SetError(SEC_ERROR_NO_MEMORY);
  255.             PORT_Assert(0);
  256.             return (void *)NULL;
  257.           }
  258.         } /* tid != null */
  259.       } /* tarena */
  260.     } /* scope */
  261. #endif /* THREADMARK */
  262.     PL_ARENA_ALLOCATE(p, arena, size);
  263.     releaseArenaLock();
  264.     if (p == NULL) {
  265. ++port_allocFailures;
  266. PORT_SetError(SEC_ERROR_NO_MEMORY);
  267.     } else {
  268. PORT_Memset(p, 0, size);
  269.     }
  270.     return(p);
  271. }
  272. /* XXX - need to zeroize!! - jsw */
  273. void
  274. PORT_FreeArena(PLArenaPool *arena, PRBool zero)
  275. {
  276.     getArenaLock();
  277.     PL_FinishArenaPool(arena);
  278.     PORT_Free(arena);
  279.     releaseArenaLock();
  280. }
  281. void *
  282. PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize)
  283. {
  284.     PORT_Assert(newsize >= oldsize);
  285.     
  286.     getArenaLock();
  287.     /* Do we do a THREADMARK check here? */
  288.     PL_ARENA_GROW(ptr, arena, oldsize, ( newsize - oldsize ) );
  289.     releaseArenaLock();
  290.     
  291.     return(ptr);
  292. }
  293. void *
  294. PORT_ArenaMark(PLArenaPool *arena)
  295. {
  296.     void * result;
  297.     getArenaLock();
  298. #ifdef THREADMARK
  299.     {
  300.       threadmark_mark *tm, **pw;
  301.       threadmark_arena *tarena = (threadmark_arena *)arena;
  302.       if( THREADMARK_MAGIC == tarena->magic ) {
  303.         /* one of ours */
  304.         if( (PRThread *)NULL == tarena->marking_thread ) {
  305.           /* First mark */
  306.           tarena->marking_thread = PR_GetCurrentThread();
  307.         } else {
  308.           if( PR_GetCurrentThread() != tarena->marking_thread ) {
  309.             releaseArenaLock();
  310.             PORT_SetError(SEC_ERROR_NO_MEMORY);
  311.             PORT_Assert(0);
  312.             return (void *)NULL;
  313.           }
  314.         }
  315.         result = PL_ARENA_MARK(arena);
  316.         PL_ARENA_ALLOCATE(tm, arena, sizeof(threadmark_mark));
  317.         if( (threadmark_mark *)NULL == tm ) {
  318.           releaseArenaLock();
  319.           PORT_SetError(SEC_ERROR_NO_MEMORY);
  320.           return (void *)NULL;
  321.         }
  322.         tm->mark = result;
  323.         tm->next = (threadmark_mark *)NULL;
  324.         pw = &tarena->first_mark;
  325.         while( (threadmark_mark *)NULL != *pw ) {
  326.              pw = &(*pw)->next;
  327.         }
  328.         *pw = tm;
  329.       } else {
  330.         /* a "pure" NSPR arena */
  331.         result = PL_ARENA_MARK(arena);
  332.       }
  333.     }
  334. #else /* THREADMARK */
  335.     result = PL_ARENA_MARK(arena);
  336. #endif /* THREADMARK */
  337.     releaseArenaLock();
  338.     return result;
  339. }
  340. void
  341. PORT_ArenaRelease(PLArenaPool *arena, void *mark)
  342. {
  343.     getArenaLock();
  344. #ifdef THREADMARK
  345.     {
  346.       threadmark_arena *tarena = (threadmark_arena *)arena;
  347.       if( THREADMARK_MAGIC == tarena->magic ) {
  348.         threadmark_mark **pw, *tm;
  349.         if( PR_GetCurrentThread() != tarena->marking_thread ) {
  350.           releaseArenaLock();
  351.           PORT_SetError(SEC_ERROR_NO_MEMORY);
  352.           PORT_Assert(0);
  353.           return /* no error indication available */ ;
  354.         }
  355.         pw = &tarena->first_mark;
  356.         while( ((threadmark_mark *)NULL != *pw) && (mark != (*pw)->mark) ) {
  357.           pw = &(*pw)->next;
  358.         }
  359.         if( (threadmark_mark *)NULL == *pw ) {
  360.           /* bad mark */
  361.           releaseArenaLock();
  362.           PORT_SetError(SEC_ERROR_NO_MEMORY);
  363.           PORT_Assert(0);
  364.           return /* no error indication available */ ;
  365.         }
  366.         tm = *pw;
  367.         *pw = (threadmark_mark *)NULL;
  368.         PL_ARENA_RELEASE(arena, mark);
  369.         if( (threadmark_mark *)NULL == tarena->first_mark ) {
  370.           tarena->marking_thread = (PRThread *)NULL;
  371.         }
  372.       } else {
  373.         PL_ARENA_RELEASE(arena, mark);
  374.       }
  375.     }
  376. #else /* THREADMARK */
  377.     PL_ARENA_RELEASE(arena, mark);
  378. #endif /* THREADMARK */
  379.     releaseArenaLock();
  380. }
  381. void
  382. PORT_ArenaUnmark(PLArenaPool *arena, void *mark)
  383. {
  384. #ifdef THREADMARK
  385.     getArenaLock();
  386.     {
  387.       threadmark_arena *tarena = (threadmark_arena *)arena;
  388.       if( THREADMARK_MAGIC == tarena->magic ) {
  389.         threadmark_mark **pw, *tm;
  390.         if( PR_GetCurrentThread() != tarena->marking_thread ) {
  391.           releaseArenaLock();
  392.           PORT_SetError(SEC_ERROR_NO_MEMORY);
  393.           PORT_Assert(0);
  394.           return /* no error indication available */ ;
  395.         }
  396.         pw = &tarena->first_mark;
  397.         while( ((threadmark_mark *)NULL != *pw) && (mark != (*pw)->mark) ) {
  398.           pw = &(*pw)->next;
  399.         }
  400.         if( (threadmark_mark *)NULL == *pw ) {
  401.           /* bad mark */
  402.           releaseArenaLock();
  403.           PORT_SetError(SEC_ERROR_NO_MEMORY);
  404.           PORT_Assert(0);
  405.           return /* no error indication available */ ;
  406.         }
  407.         tm = *pw;
  408.         *pw = (threadmark_mark *)NULL;
  409.         if( (threadmark_mark *)NULL == tarena->first_mark ) {
  410.           tarena->marking_thread = (PRThread *)NULL;
  411.         }
  412.       } else {
  413.         PL_ARENA_RELEASE(arena, mark);
  414.       }
  415.     }
  416.     releaseArenaLock();
  417. #endif /* THREADMARK */
  418. }
  419. char *
  420. PORT_ArenaStrdup(PLArenaPool *arena, char *str) {
  421.     int len = PORT_Strlen(str)+1;
  422.     char *newstr;
  423.     getArenaLock();
  424.     newstr = (char*)PORT_ArenaAlloc(arena,len);
  425.     releaseArenaLock();
  426.     if (newstr) {
  427.         PORT_Memcpy(newstr,str,len);
  428.     }
  429.     return newstr;
  430. }
  431. /********************** end of arena functions ***********************/
  432. /****************** unicode conversion functions ***********************/
  433. /*
  434.  * NOTE: These conversion functions all assume that the multibyte
  435.  * characters are going to be in NETWORK BYTE ORDER, not host byte
  436.  * order.  This is because the only time we deal with UCS-2 and UCS-4
  437.  * are when the data was received from or is going to be sent out
  438.  * over the wire (in, e.g. certificates).
  439.  */
  440. void
  441. PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc)
  442.     ucs4Utf8ConvertFunc = convFunc;
  443. }
  444. void
  445. PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc)
  446.     ucs2AsciiConvertFunc = convFunc;
  447. }
  448. void
  449. PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc)
  450.     ucs2Utf8ConvertFunc = convFunc;
  451. }
  452. PRBool 
  453. PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
  454.  unsigned int inBufLen, unsigned char *outBuf,
  455.  unsigned int maxOutBufLen, unsigned int *outBufLen)
  456. {
  457.     if(!ucs4Utf8ConvertFunc) {
  458.       return sec_port_ucs4_utf8_conversion_function(toUnicode,
  459.         inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen);
  460.     }
  461.     return (*ucs4Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, 
  462.   maxOutBufLen, outBufLen);
  463. }
  464. PRBool 
  465. PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
  466.  unsigned int inBufLen, unsigned char *outBuf,
  467.  unsigned int maxOutBufLen, unsigned int *outBufLen)
  468. {
  469.     if(!ucs2Utf8ConvertFunc) {
  470.       return sec_port_ucs2_utf8_conversion_function(toUnicode,
  471.         inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen);
  472.     }
  473.     return (*ucs2Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, 
  474.   maxOutBufLen, outBufLen);
  475. }
  476. PRBool 
  477. PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf,
  478.   unsigned int inBufLen, unsigned char *outBuf,
  479.   unsigned int maxOutBufLen, unsigned int *outBufLen,
  480.   PRBool swapBytes)
  481. {
  482.     if(!ucs2AsciiConvertFunc) {
  483. return PR_FALSE;
  484.     }
  485.     return (*ucs2AsciiConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, 
  486.   maxOutBufLen, outBufLen, swapBytes);
  487. }
  488. /* Portable putenv.  Creates/replaces an environment variable of the form
  489.  *  envVarName=envValue
  490.  */
  491. int
  492. NSS_PutEnv(const char * envVarName, const char * envValue)
  493. {
  494.     SECStatus result = SECSuccess;
  495. #ifdef _WIN32
  496.     PRBool      setOK;
  497.     setOK = SetEnvironmentVariable(envVarName, envValue);
  498.     if (!setOK) {
  499.         SET_ERROR_CODE
  500.         result = SECFailure;
  501.     }
  502. #elif  defined(XP_MAC)
  503. result = SECFailure;
  504. #else
  505.     char *          encoded;
  506.     int             putEnvFailed;
  507.     encoded = (char *)PORT_ZAlloc(strlen(envVarName) + 2 + strlen(envValue));
  508.     strcpy(encoded, envVarName);
  509.     strcat(encoded, "=");
  510.     strcat(encoded, envValue);
  511.     putEnvFailed = putenv(encoded); /* adopt. */
  512.     if (putEnvFailed) {
  513.         SET_ERROR_CODE
  514.         result = SECFailure;
  515.         PORT_Free(encoded);
  516.     }
  517. #endif
  518.     return result;
  519. }