sha_pwd.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * slapd hashed password routines
  40. *
  41. */
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <sys/types.h>
  45. #include "pwdstorage.h"
  46. #if defined(NET_SSL)
  47. #include <sechash.h>
  48. #endif /* NET_SSL */
  49. #define SHA_SALT_LENGTH 8 /* number of bytes of data in salt */
  50. #define NOT_FIRST_TIME (time_t)1 /* not the first logon */
  51. static char *hasherrmsg = "pw_cmp: %s userPassword \"%s\" is the wrong length or is not properly encoded BASE64\n";
  52. static char *plugin_name = "NSPwdStoragePlugin";
  53. #define DS40B1_SALTED_SHA_LENGTH 18
  54. /* Directory Server 4.0 Beta 1 implemented a scheme that stored
  55. * 8 bytes of salt plus the first 10 bytes of the SHA-1 digest.
  56. * It's obsolescent now, but we still handle such stored values.
  57. */
  58. int
  59. sha_pw_cmp (char *userpwd, char *dbpwd, unsigned int shaLen )
  60. {
  61. /*
  62. * SHA passwords are stored in the database as shaLen bytes of
  63. * hash, followed by zero or more bytes of salt, all BASE64 encoded.
  64. */
  65. int result = 1; /* failure */
  66. unsigned char userhash[MAX_SHA_HASH_SIZE];
  67. unsigned char quick_dbhash[MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH + 3];
  68. unsigned char *dbhash = quick_dbhash;
  69. struct berval salt;
  70. int hash_len; /* must be a signed valued -- see below */
  71. unsigned int secOID;
  72. char *schemeName;
  73. /* Determine which algorithm we're using */
  74. switch (shaLen) {
  75. case SHA1_LENGTH:
  76. schemeName = SHA1_SCHEME_NAME;
  77. secOID = SEC_OID_SHA1;
  78. break;
  79. case SHA256_LENGTH:
  80. schemeName = SHA256_SCHEME_NAME;
  81. secOID = SEC_OID_SHA256;
  82. break;
  83. case SHA384_LENGTH:
  84. schemeName = SHA384_SCHEME_NAME;
  85. secOID = SEC_OID_SHA384;
  86. break;
  87. case SHA512_LENGTH:
  88. schemeName = SHA512_SCHEME_NAME;
  89. secOID = SEC_OID_SHA512;
  90. break;
  91. default:
  92. /* An unknown shaLen was passed in. We shouldn't get here. */
  93. goto loser;
  94. }
  95. /*
  96. * Decode hash stored in database.
  97. *
  98. * Note that ldif_base64_decode() returns a value less than zero to
  99. * indicate that a decoding error occurred, so it is critical that
  100. * hash_len be a signed value.
  101. */
  102. hash_len = (((strlen(dbpwd) + 3) / 4) * 3); /* maybe less */
  103. if ( hash_len > sizeof(quick_dbhash) ) { /* get more space: */
  104. dbhash = (unsigned char*) slapi_ch_malloc( hash_len );
  105. if ( dbhash == NULL ) goto loser;
  106. }
  107. hash_len = ldif_base64_decode( dbpwd, dbhash );
  108. if ( hash_len >= shaLen ) {
  109. salt.bv_val = (void*)(dbhash + shaLen);
  110. salt.bv_len = hash_len - shaLen;
  111. } else if ( hash_len == DS40B1_SALTED_SHA_LENGTH ) {
  112. salt.bv_val = (void*)dbhash;
  113. salt.bv_len = 8;
  114. } else { /* unsupported, invalid BASE64 (hash_len < 0), or similar */
  115. slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, hasherrmsg, schemeName, dbpwd );
  116. goto loser;
  117. }
  118. /* hash the user's key */
  119. if ( sha_salted_hash( userhash, userpwd, &salt, secOID ) != SECSuccess ) {
  120. slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "sha_pw_cmp: sha_salted_hash() failed\n");
  121. goto loser;
  122. }
  123. /* the proof is in the comparison... */
  124. result = ( hash_len == DS40B1_SALTED_SHA_LENGTH ) ?
  125. ( memcmp( userhash, dbhash + 8, hash_len - 8 )) :
  126. ( memcmp( userhash, dbhash, shaLen ));
  127. loser:
  128. if ( dbhash && dbhash != quick_dbhash ) slapi_ch_free( (void**)&dbhash );
  129. return result;
  130. }
  131. char *
  132. sha_pw_enc( char *pwd, unsigned int shaLen )
  133. {
  134. unsigned char hash[MAX_SHA_HASH_SIZE];
  135. char *enc;
  136. char *schemeName;
  137. unsigned int schemeNameLen;
  138. unsigned int secOID;
  139. /* Determine which algorithm we're using */
  140. switch (shaLen) {
  141. case SHA1_LENGTH:
  142. schemeName = SHA1_SCHEME_NAME;
  143. schemeNameLen = SHA1_NAME_LEN;
  144. secOID = SEC_OID_SHA1;
  145. break;
  146. case SHA256_LENGTH:
  147. schemeName = SHA256_SCHEME_NAME;
  148. schemeNameLen = SHA256_NAME_LEN;
  149. secOID = SEC_OID_SHA256;
  150. break;
  151. case SHA384_LENGTH:
  152. schemeName = SHA384_SCHEME_NAME;
  153. schemeNameLen = SHA384_NAME_LEN;
  154. secOID = SEC_OID_SHA384;
  155. break;
  156. case SHA512_LENGTH:
  157. schemeName = SHA512_SCHEME_NAME;
  158. schemeNameLen = SHA512_NAME_LEN;
  159. secOID = SEC_OID_SHA512;
  160. break;
  161. default:
  162. /* An unknown shaLen was passed in. We shouldn't get here. */
  163. return( NULL );
  164. }
  165. /* hash the user's key */
  166. if ( sha_salted_hash( hash, pwd, NULL, secOID ) != SECSuccess ) {
  167. return( NULL );
  168. }
  169. if (( enc = slapi_ch_malloc( 3 + schemeNameLen +
  170. LDIF_BASE64_LEN( shaLen ))) == NULL ) {
  171. return( NULL );
  172. }
  173. sprintf( enc, "%c%s%c", PWD_HASH_PREFIX_START, schemeName,
  174. PWD_HASH_PREFIX_END );
  175. (void)ldif_base64_encode( hash, enc + 2 + schemeNameLen,
  176. shaLen, -1 );
  177. return( enc );
  178. }
  179. /*
  180. * Wrapper password comparison functions
  181. */
  182. int
  183. sha1_pw_cmp (char *userpwd, char *dbpwd )
  184. {
  185. return sha_pw_cmp( userpwd, dbpwd, SHA1_LENGTH );
  186. }
  187. int
  188. sha256_pw_cmp (char *userpwd, char *dbpwd )
  189. {
  190. return sha_pw_cmp( userpwd, dbpwd, SHA256_LENGTH );
  191. }
  192. int
  193. sha384_pw_cmp (char *userpwd, char *dbpwd )
  194. {
  195. return sha_pw_cmp( userpwd, dbpwd, SHA384_LENGTH );
  196. }
  197. int
  198. sha512_pw_cmp (char *userpwd, char *dbpwd )
  199. {
  200. return sha_pw_cmp( userpwd, dbpwd, SHA512_LENGTH );
  201. }
  202. /*
  203. * Wrapper password encryption functions
  204. */
  205. char *
  206. sha1_pw_enc( char *pwd )
  207. {
  208. return sha_pw_enc( pwd, SHA1_LENGTH );
  209. }
  210. char *
  211. sha256_pw_enc( char *pwd )
  212. {
  213. return sha_pw_enc( pwd, SHA256_LENGTH );
  214. }
  215. char *
  216. sha384_pw_enc( char *pwd )
  217. {
  218. return sha_pw_enc( pwd, SHA384_LENGTH );
  219. }
  220. char *
  221. sha512_pw_enc( char *pwd )
  222. {
  223. return sha_pw_enc( pwd, SHA512_LENGTH );
  224. }