des.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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. /* from /usr/project/iplanet/ws/ds5.ke/ns/svrcore/pkcs7/tstarchive.c */
  39. #include <string.h>
  40. #include <stdio.h>
  41. #include <ldap.h>
  42. #include <nspr.h>
  43. #include <nss.h>
  44. #include <secmod.h>
  45. /*
  46. #include <secasn1.h>
  47. #include <secpkcs7.h>
  48. */
  49. #include <key.h>
  50. #include <certdb.h>
  51. #include <cert.h>
  52. #include <svrcore.h>
  53. #include <secmodt.h>
  54. #include <prtypes.h>
  55. #include <seccomon.h>
  56. #include <pk11func.h>
  57. #define NEED_TOK_DES /* see slap.h - defines tokDes and ptokDes */
  58. #include "rever.h"
  59. #include <slap.h>
  60. #include "slapi-plugin.h"
  61. #include <uuid.h>
  62. struct pk11MechItem
  63. {
  64. CK_MECHANISM_TYPE type;
  65. const char *mechName;
  66. };
  67. static const struct pk11MechItem mymech = { CKM_DES_CBC, "DES CBC encryption" };
  68. static Slapi_Mutex *mylock = NULL;
  69. struct pk11ContextStore
  70. {
  71. PK11SlotInfo *slot;
  72. const struct pk11MechItem *mech;
  73. PK11SymKey *key;
  74. SECItem *params;
  75. int length;
  76. unsigned char *crypt;
  77. };
  78. static int encode_path(char *inPlain, char **outCipher, char *path);
  79. static int decode_path(char *inCipher, char **outPlain, char *path);
  80. static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path);
  81. static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out);
  82. static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len);
  83. static void freeDes(struct pk11ContextStore *out);
  84. void
  85. init_des_plugin()
  86. {
  87. mylock = slapi_new_mutex();
  88. }
  89. int
  90. encode(char *inPlain, char **outCipher)
  91. {
  92. return encode_path(inPlain, outCipher, NULL);
  93. }
  94. static int
  95. encode_path(char *inPlain, char **outCipher, char *path)
  96. {
  97. struct pk11ContextStore *context = NULL;
  98. int err;
  99. unsigned char *cipher = NULL;
  100. char *tmp = NULL;
  101. char *base = NULL;
  102. *outCipher = NULL;
  103. err = 1;
  104. if ( genKey(&context, tokDes, path) == SVRCORE_Success )
  105. {
  106. /* Try an encryption */
  107. if ( cryptPassword(context, inPlain, &cipher) == SVRCORE_Success )
  108. {
  109. base = BTOA_DataToAscii(cipher, context->length);
  110. if ( base != NULL )
  111. {
  112. tmp = slapi_ch_malloc( 3 + strlen(REVER_SCHEME_NAME) + strlen(base));
  113. if ( tmp != NULL )
  114. {
  115. sprintf( tmp, "%c%s%c%s", PWD_HASH_PREFIX_START, REVER_SCHEME_NAME, PWD_HASH_PREFIX_END, base);
  116. *outCipher = tmp;
  117. tmp = NULL;
  118. err = 0;
  119. }
  120. PORT_Free(base);
  121. }
  122. }
  123. }
  124. freeDes(context);
  125. slapi_ch_free((void **) &context);
  126. return(err);
  127. }
  128. int
  129. decode(char *inCipher, char **outPlain)
  130. {
  131. return decode_path(inCipher, outPlain, NULL);
  132. }
  133. static int
  134. decode_path(char *inCipher, char **outPlain, char *path)
  135. {
  136. struct pk11ContextStore *context = NULL;
  137. char *plain= NULL;
  138. int err;
  139. unsigned char *base = NULL;
  140. int len = 0;
  141. *outPlain = NULL;
  142. err = 1;
  143. if ( genKey(&context, tokDes, path) == SVRCORE_Success )
  144. {
  145. /* it seems that there is memory leak in that function: bug 400170 */
  146. base = ATOB_AsciiToData(inCipher, (unsigned int*)&len);
  147. if ( base != NULL )
  148. {
  149. if ( decryptPassword(context, base, &plain, len) == SVRCORE_Success )
  150. {
  151. *outPlain = plain;
  152. err = 0;
  153. }
  154. }
  155. }
  156. PORT_Free(base);
  157. freeDes(context);
  158. slapi_ch_free((void **) &context);
  159. return(err);
  160. }
  161. static void freeDes(struct pk11ContextStore *out)
  162. {
  163. if (out)
  164. {
  165. if (out->slot)
  166. slapd_pk11_freeSlot(out->slot);
  167. if (out->key)
  168. slapd_pk11_freeSymKey(out->key);
  169. if (out->params)
  170. SECITEM_FreeItem(out->params,PR_TRUE);
  171. if (out->crypt)
  172. free(out->crypt);
  173. }
  174. }
  175. static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path)
  176. {
  177. SVRCOREError err = SVRCORE_Success;
  178. struct pk11ContextStore *store = NULL;
  179. SECItem *pwitem = NULL;
  180. SECItem *result = NULL;
  181. SECAlgorithmID *algid = NULL;
  182. SECOidTag algoid;
  183. SECItem *salt = NULL;
  184. CK_MECHANISM pbeMech;
  185. CK_MECHANISM cryptoMech;
  186. char *instancedir = NULL;
  187. char *iv = NULL;
  188. store = (struct pk11ContextStore*)slapi_ch_malloc(sizeof(*store));
  189. if (store == NULL)
  190. {
  191. return (err = SVRCORE_NoMemory_Error);
  192. }
  193. *out = store;
  194. /* Low-level init */
  195. store->slot = NULL;
  196. store->key = NULL;
  197. store->params = NULL;
  198. store->crypt = NULL;
  199. /* Use the tokenName to find a PKCS11 slot */
  200. store->slot = slapd_pk11_findSlotByName((char *)token);
  201. if (store->slot == NULL)
  202. {
  203. return (err = SVRCORE_NoSuchToken_Error);
  204. }
  205. /* Generate a key and parameters to do the encryption */
  206. store->mech = &mymech;
  207. /* Generate a unique id, used as salt for the key generation */
  208. if ( path == NULL )
  209. {
  210. instancedir = config_get_instancedir();
  211. if ( instancedir == NULL )
  212. {
  213. return (err = SVRCORE_System_Error);
  214. }
  215. }
  216. else
  217. {
  218. instancedir = slapi_ch_strdup(path);
  219. }
  220. if ( slapi_uniqueIDGenerateFromNameString (&iv, NULL, instancedir, strlen(instancedir)) != UID_SUCCESS )
  221. {
  222. slapi_ch_free((void**)&instancedir);
  223. return (err = SVRCORE_System_Error);
  224. }
  225. slapi_ch_free((void**)&instancedir);
  226. pwitem = (SECItem *) PORT_Alloc(sizeof(SECItem));
  227. if (pwitem == NULL)
  228. {
  229. return (err = SVRCORE_NoMemory_Error);
  230. }
  231. pwitem->type = siBuffer;
  232. pwitem->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
  233. if (pwitem->data == NULL)
  234. {
  235. return (err = SVRCORE_NoMemory_Error);
  236. }
  237. strcpy((char*)pwitem->data, iv);
  238. pwitem->len = strlen(iv) + 1;
  239. algoid = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
  240. salt = (SECItem *) PORT_Alloc(sizeof(SECItem));
  241. if (salt == NULL)
  242. {
  243. return (err = SVRCORE_NoMemory_Error);
  244. }
  245. salt->type = siBuffer;
  246. salt->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
  247. if ( salt->data == NULL )
  248. {
  249. return (err = SVRCORE_NoMemory_Error);
  250. }
  251. strcpy((char*)salt->data, iv);
  252. salt->len = strlen(iv) + 1;
  253. slapi_ch_free((void**)&iv);
  254. algid = slapd_pk11_createPBEAlgorithmID(algoid, 2, salt);
  255. slapi_lock_mutex(mylock);
  256. store->key = slapd_pk11_pbeKeyGen(store->slot, algid, pwitem, 0, 0);
  257. if (store->key == 0)
  258. {
  259. slapi_unlock_mutex(mylock);
  260. return (err = SVRCORE_System_Error);
  261. }
  262. slapi_unlock_mutex(mylock);
  263. pbeMech.mechanism = slapd_pk11_algtagToMechanism(algoid);
  264. result = slapd_pk11_paramFromAlgid(algid);
  265. secoid_destroyAlgorithmID(algid, PR_TRUE);
  266. pbeMech.pParameter = result->data;
  267. pbeMech.ulParameterLen = result->len;
  268. if(slapd_pk11_mapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem,
  269. PR_FALSE) != CKR_OK)
  270. {
  271. SECITEM_FreeItem(result, PR_TRUE);
  272. return (err = SVRCORE_System_Error);
  273. }
  274. SECITEM_FreeItem(result, PR_TRUE);
  275. SECITEM_FreeItem(pwitem, PR_TRUE);
  276. SECITEM_FreeItem(salt, PR_TRUE);
  277. store->params = (SECItem *) PORT_Alloc(sizeof(SECItem));
  278. if (store->params == NULL)
  279. {
  280. return (err = SVRCORE_System_Error);
  281. }
  282. store->params->type = store->mech->type;
  283. store->params->data = (unsigned char *)PORT_Alloc(cryptoMech.ulParameterLen);
  284. if (store->params->data == NULL)
  285. {
  286. return (err = SVRCORE_System_Error);
  287. }
  288. memcpy(store->params->data, (unsigned char *)cryptoMech.pParameter, cryptoMech.ulParameterLen);
  289. store->params->len = cryptoMech.ulParameterLen;
  290. PORT_Free(cryptoMech.pParameter);
  291. return (err);
  292. }
  293. static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len)
  294. {
  295. SVRCOREError err = SVRCORE_Success;
  296. unsigned char *plain = NULL;
  297. unsigned char *cipher_with_padding = NULL;
  298. SECStatus rv;
  299. PK11Context *ctx = 0;
  300. int outLen = 0;
  301. int blocksize = 0;
  302. blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
  303. store->length = len;
  304. /* store->length is the max. length of the returned clear text -
  305. must be >= length of crypted bytes - also must be a multiple
  306. of blocksize */
  307. if (blocksize != 0)
  308. {
  309. store->length += blocksize - (store->length % blocksize);
  310. }
  311. /* plain will hold the returned clear text */
  312. plain = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  313. store->length+1);
  314. if (!plain)
  315. {
  316. return (err = SVRCORE_NoMemory_Error);
  317. }
  318. /* create a buffer holding the original cipher bytes, padded with
  319. zeros to a multiple of blocksize - do not need +1 since buffer is not
  320. a string */
  321. cipher_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  322. store->length);
  323. if (!cipher_with_padding)
  324. {
  325. return (err = SVRCORE_NoMemory_Error);
  326. }
  327. memcpy(cipher_with_padding, cipher, len);
  328. ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_DECRYPT,
  329. store->key, store->params);
  330. if (!ctx)
  331. {
  332. return (err = SVRCORE_System_Error);
  333. }
  334. /* warning - there is a purify UMR in the NSS des code - you may see it when the
  335. password is not a multiple of 8 bytes long */
  336. rv = slapd_pk11_cipherOp(ctx, plain, &outLen, store->length,
  337. cipher_with_padding, store->length);
  338. if (rv)
  339. {
  340. err = SVRCORE_System_Error;
  341. }
  342. rv = slapd_pk11_finalize(ctx);
  343. /* we must do the finalize, but we only want to set the err return
  344. code if it is not already set */
  345. if (rv && (SVRCORE_Success == err))
  346. err = SVRCORE_System_Error;
  347. if (err == SVRCORE_Success)
  348. *out = (char *)plain;
  349. slapi_ch_free((void **)&cipher_with_padding);
  350. /* We should free the PK11Context... Something like : */
  351. slapd_pk11_destroyContext(ctx, PR_TRUE);
  352. return err;
  353. }
  354. static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out)
  355. {
  356. SVRCOREError err = SVRCORE_Success;
  357. SECStatus rv;
  358. PK11Context *ctx = 0;
  359. int outLen = 0;
  360. int blocksize = 0;
  361. unsigned char *clear_with_padding = NULL; /* clear with padding up to blocksize */
  362. blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
  363. store->length = strlen(clear);
  364. /* the size of the clear text buffer passed to the des encryption functions
  365. must be a multiple of blocksize (usually 8 bytes) - we allocate a buffer
  366. of this size, copy the clear text password into it, and pad the rest with
  367. zeros */
  368. if (blocksize != 0)
  369. {
  370. store->length += blocksize - (store->length % blocksize);
  371. }
  372. /* store->crypt will hold the crypted password - it must be >= clear length */
  373. store->crypt = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  374. store->length+1);
  375. if (!store->crypt)
  376. {
  377. return (err = SVRCORE_NoMemory_Error);
  378. }
  379. /* create a buffer big enough to hold the clear text password and padding */
  380. clear_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  381. store->length+1);
  382. if (!clear_with_padding)
  383. {
  384. return (err = SVRCORE_NoMemory_Error);
  385. }
  386. /* copy the clear text password into the buffer - the calloc insures the
  387. remainder is zero padded */
  388. strcpy((char *)clear_with_padding, clear);
  389. ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_ENCRYPT,
  390. store->key, store->params);
  391. if (!ctx)
  392. {
  393. return (err = SVRCORE_System_Error);
  394. }
  395. rv = slapd_pk11_cipherOp(ctx, store->crypt, &outLen, store->length,
  396. clear_with_padding, store->length);
  397. if (rv)
  398. {
  399. err = SVRCORE_System_Error;
  400. }
  401. rv = slapd_pk11_finalize(ctx);
  402. /* we must do the finalize, but we only want to set the err return
  403. code if it is not already set */
  404. if (rv && (SVRCORE_Success == err))
  405. err = SVRCORE_System_Error;
  406. if (err == SVRCORE_Success)
  407. *out = store->crypt;
  408. slapi_ch_free((void **)&clear_with_padding);
  409. /* We should free the PK11Context... Something like : */
  410. slapd_pk11_destroyContext(ctx, PR_TRUE);
  411. return err;
  412. }
  413. char *
  414. migrateCredentials(char *oldpath, char *newpath, char *oldcred)
  415. {
  416. char *plain = NULL;
  417. char *cipher = NULL;
  418. init_des_plugin();
  419. slapd_pk11_configurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 );
  420. NSS_NoDB_Init(NULL);
  421. if ( decode_path(oldcred, &plain, oldpath) == 0 )
  422. {
  423. if ( encode_path(plain, &cipher, newpath) != 0 )
  424. return(NULL);
  425. else
  426. return(cipher);
  427. }
  428. else
  429. return(NULL);
  430. }