Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
13 KiB

  1. // AddCert.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "certmap.h"
  5. // persistence and mapping includes
  6. #include "WrapMaps.h"
  7. #include "wrapmb.h"
  8. #include "ListRow.h"
  9. #include "ChkLstCt.h"
  10. // mapping page includes
  11. #include "brwsdlg.h"
  12. #include "EdtOne11.h"
  13. #include "Ed11Maps.h"
  14. #include "Map11Pge.h"
  15. extern "C"
  16. {
  17. #include <wincrypt.h>
  18. #include <sslsp.h>
  19. }
  20. #include <iismap.hxx>
  21. #include <iiscmr.hxx>
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. #define COL_NUM_NAME 0
  28. #define COL_NUM_NTACCOUNT 1
  29. #define CERT_HEADER "-----BEGIN CERTIFICATE-----"
  30. // the code that reads the certificate file is pretty much lifted from the
  31. // keyring application. Which pretty much lifted it from the setkey application
  32. // defines taken from the old KeyGen utility
  33. #define MESSAGE_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----\r\n"
  34. #define MESSAGE_TRAILER "-----END NEW CERTIFICATE REQUEST-----\r\n"
  35. #define MIME_TYPE "Content-Type: application/x-pkcs10\r\n"
  36. #define MIME_ENCODING "Content-Transfer-Encoding: base64\r\n\r\n"
  37. void uudecode_cert(char *bufcoded, DWORD *pcbDecoded );
  38. //---------------------------------------------------------------------------
  39. // originally from keyring - modified to fit
  40. BOOL CMap11Page::FAddCertificateFile( CString szFile )
  41. {
  42. CFile cfile;
  43. PVOID pData = NULL;
  44. BOOL fSuccess =FALSE;;
  45. // open the file
  46. if ( !cfile.Open( szFile, CFile::modeRead | CFile::shareDenyNone ) )
  47. return FALSE;
  48. // how big is the file - add one so we can zero terminate the buffer
  49. DWORD cbCertificate = cfile.GetLength() + 1;
  50. // make sure the file has some size
  51. if ( !cbCertificate )
  52. {
  53. AfxMessageBox( IDS_ERR_INVALID_CERTIFICATE );
  54. return FALSE;
  55. }
  56. // put the rest of the operation in a try/catch
  57. try
  58. {
  59. PCCERT_CONTEXT pCertContext=NULL; //used to determine whether cert file is binary DER encoded
  60. // allocate space for the data
  61. pData = GlobalAlloc( GPTR, cbCertificate );
  62. if ( !pData ) AfxThrowMemoryException();
  63. // copy in the data from the file to the pointer - will throw and exception
  64. DWORD cbRead = cfile.Read( pData, cbCertificate );
  65. // zero terminate for decoding
  66. ((BYTE*)pData)[cbRead] = 0;
  67. // close the file
  68. cfile.Close();
  69. //certificate file may be either be binary DER file or BASE64 encoded file
  70. // try binary DER encoded first
  71. pCertContext= CertCreateCertificateContext(X509_ASN_ENCODING, (const BYTE *)pData, cbRead);
  72. if(pCertContext != NULL)
  73. {
  74. // we created certificate context only to verify that file is binary DER encoded
  75. // free it now
  76. CertFreeCertificateContext(pCertContext);
  77. pCertContext=NULL;
  78. }
  79. else // now try BASE64 encoded
  80. {
  81. // we don't care about header ----BEGIN CERTIFICATE----- or trailer-----END CERTIFICATE-----,
  82. // uudecode will take care of that
  83. uudecode_cert( (PCHAR)pData, &cbRead );
  84. }
  85. // we now have a pointer to a certificate. Lets keep it clean looking
  86. // call another subroutine to finish the job.
  87. fSuccess = FAddCertificate( (PUCHAR)pData, cbRead );
  88. }catch( CException e )
  89. {
  90. // return failure
  91. fSuccess = FALSE;
  92. // if the pointer was allocated, deallocate it
  93. if ( pData )
  94. {
  95. GlobalFree( pData );
  96. pData = NULL;
  97. }
  98. }
  99. // return success
  100. return fSuccess;
  101. }
  102. #define CERT_HEADER_LEN 17
  103. CHAR CertTag[ 13 ] = { 0x04, 0x0b, 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e' };
  104. //---------------------------------------------------------------------------
  105. // we are passed in a complete certificate. We need to parse out the subject
  106. // and the issuer fields so we can add the mapping. Then add the mapping.
  107. BOOL CMap11Page::FAddCertificate( PUCHAR pCertificate, DWORD cbCertificate )
  108. {
  109. BOOL fSuccess = FALSE;
  110. // thankfully, the certificate is already in the correct format.
  111. // this means that, for now at least, we don't have to do anything
  112. // special to it to store it. However, we should crack it once just
  113. // to see that we can to prove that it is a valid cert.
  114. ASSERT( pCertificate );
  115. if ( !pCertificate ) return FALSE;
  116. // crack the certificate to prove that we can
  117. PX509Certificate p509 = NULL;
  118. fSuccess = SslCrackCertificate( pCertificate, cbCertificate, CF_CERT_FROM_FILE, &p509 );
  119. if ( fSuccess )
  120. {
  121. SslFreeCertificate( p509 );
  122. }
  123. else
  124. {
  125. // we were not able to crack the certificate. Alert the user and fail
  126. AfxMessageBox( IDS_ERR_INVALID_CERTIFICATE );
  127. return FALSE;
  128. }
  129. // by this point we know we have a valid certificate, make the new mapping and fill it in
  130. // make the new mapping object
  131. C11Mapping* pMapping = PNewMapping();
  132. ASSERT( pMapping );
  133. if( !pMapping )
  134. {
  135. AfxThrowMemoryException(); // seems fairly appropriate
  136. return FALSE;
  137. }
  138. // one more thing before we add the certificate. Skip the header if it is there
  139. PUCHAR pCert = pCertificate;
  140. DWORD cbCert = cbCertificate;
  141. if ( memcmp( pCert + 4, CertTag, sizeof( CertTag ) ) == 0 )
  142. {
  143. pCert += CERT_HEADER_LEN;
  144. cbCert -= CERT_HEADER_LEN;
  145. }
  146. // install the certificate into the mapping
  147. fSuccess &= pMapping->SetCertificate( pCert, cbCert );
  148. // by default, the mapping is enabled
  149. fSuccess &= pMapping->SetMapEnabled( TRUE );
  150. // install a default name
  151. CString sz;
  152. sz.LoadString( IDS_DEFAULT_11MAP );
  153. fSuccess &= pMapping->SetMapName( sz );
  154. // install a blank mapping
  155. fSuccess &= pMapping->SetNTAccount( "" );
  156. if ( !fSuccess )
  157. AfxThrowMemoryException(); // seems fairly appropriate
  158. // now edit the newly created mapping object. If the user cancels,
  159. // then do not add it to the mapper object nor the list
  160. if ( !EditOneMapping( pMapping) )
  161. {
  162. DeleteMapping( pMapping );
  163. return FALSE;
  164. }
  165. // add the mapping item to the list control
  166. fSuccess = FAddMappingToList( pMapping );
  167. // one more test for success
  168. if ( !fSuccess )
  169. {
  170. DeleteMapping( pMapping );
  171. ASSERT( FALSE );
  172. }
  173. // mark the mapping to be saved
  174. if ( fSuccess )
  175. MarkToSave( pMapping );
  176. // return the answer
  177. return fSuccess;
  178. }
  179. // ==============================================================
  180. // The function 'uudecode_cert' IS THE SAME function that is
  181. // found in file: Addcert.cpp if we make the following code
  182. // have a FALSE for bAddWrapperAroundCert -- surely we can unify
  183. // these 2 functions. Having 2 functions named 'uudecode_cert'
  184. // was causing me LINKING errors. + we have 2 instances of
  185. // the external tables: uudecode_cert and pr2six
  186. //
  187. // Since I am linking both Addcert.cpp and CKey.cpp I choose to
  188. // leave the defintions intact for CKey.cpp [ and have extended
  189. // uudecode_cert by adding conditional code as shown below] Further
  190. // work needs to be done after identification as to why I need both
  191. // Addcert.cpp and CKey.cpp to pass bAddWrapperAroundCert as a
  192. // parameter so that both files can be supported.
  193. // ==============================================================
  194. // BOOL bAddWrapperAroundCert = TRUE;
  195. // if (bAddWrapperAroundCert) {
  196. // //
  197. // // Now we need to add a new wrapper sequence around the certificate
  198. // // indicating this is a certificate
  199. // //
  200. //
  201. // memmove( beginbuf + sizeof(abCertHeader),
  202. // beginbuf,
  203. // nbytesdecoded );
  204. //
  205. // memcpy( beginbuf,
  206. // abCertHeader,
  207. // sizeof(abCertHeader) );
  208. //
  209. // //
  210. // // The beginning record size is the total number of bytes decoded plus
  211. // // the number of bytes in the certificate header
  212. // //
  213. //
  214. // beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
  215. // beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
  216. //
  217. // nbytesdecoded += sizeof(abCertHeader);
  218. // }
  219. // #ifdef WE_ARE_USING_THE_VERSION_IN__CKey_cpp__NOT_THIS_ONE__ITS_JUST_LIKE_THIS_ONE_WITH_1SMALL_CHANGE
  220. //============================ BASED ON SETKEY
  221. const int pr2six[256]={
  222. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  223. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  224. 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
  225. 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  226. 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  227. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  228. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  229. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  230. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  231. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  232. 64,64,64,64,64,64,64,64,64,64,64,64,64
  233. };
  234. //
  235. // We have to squirt a record into the decoded stream
  236. //
  237. #define CERT_RECORD 13
  238. #define CERT_SIZE_HIBYTE 2 // Index into record of record size
  239. #define CERT_SIZE_LOBYTE 3
  240. unsigned char abCertHeader[] = {0x30, 0x82, // Record
  241. 0x00, 0x00, // Size of cert + buff
  242. 0x04, 0x0b, 0x63, 0x65,// Cert record data
  243. 0x72, 0x74, 0x69, 0x66,
  244. 0x69, 0x63, 0x61, 0x74,
  245. 0x65 };
  246. void uudecode_cert(char *bufcoded, DWORD *pcbDecoded )
  247. {
  248. int nbytesdecoded;
  249. char *bufin = bufcoded;
  250. unsigned char *bufout = (unsigned char *)bufcoded;
  251. unsigned char *pbuf;
  252. int nprbytes;
  253. char * beginbuf = bufcoded;
  254. ASSERT(bufcoded);
  255. ASSERT(pcbDecoded);
  256. /* Strip leading whitespace. */
  257. while(*bufcoded==' ' ||
  258. *bufcoded == '\t' ||
  259. *bufcoded == '\r' ||
  260. *bufcoded == '\n' )
  261. {
  262. bufcoded++;
  263. }
  264. //
  265. // If there is a beginning '---- ....' then skip the first line
  266. //
  267. if ( bufcoded[0] == '-' && bufcoded[1] == '-' )
  268. {
  269. bufin = strchr( bufcoded, '\n' );
  270. if ( bufin )
  271. {
  272. bufin++;
  273. bufcoded = bufin;
  274. }
  275. else
  276. {
  277. bufin = bufcoded;
  278. }
  279. }
  280. else
  281. {
  282. bufin = bufcoded;
  283. }
  284. //
  285. // Strip all cr/lf from the block
  286. //
  287. pbuf = (unsigned char *)bufin;
  288. while ( *pbuf )
  289. {
  290. if ( (*pbuf == ' ') || (*pbuf == '\r') || (*pbuf == '\n') )
  291. {
  292. memmove( (void*)pbuf, pbuf+1, strlen( (char*)pbuf + 1) + 1 );
  293. }
  294. else
  295. {
  296. pbuf++;
  297. }
  298. }
  299. /* Figure out how many characters are in the input buffer.
  300. * If this would decode into more bytes than would fit into
  301. * the output buffer, adjust the number of input bytes downwards.
  302. */
  303. while(pr2six[*(bufin++)] <= 63);
  304. nprbytes = DIFF(bufin - bufcoded) - 1;
  305. nbytesdecoded = ((nprbytes+3)/4) * 3;
  306. bufin = bufcoded;
  307. while (nprbytes > 0) {
  308. *(bufout++) =
  309. (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  310. *(bufout++) =
  311. (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  312. *(bufout++) =
  313. (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  314. bufin += 4;
  315. nprbytes -= 4;
  316. }
  317. if(nprbytes & 03) {
  318. if(pr2six[bufin[-2]] > 63)
  319. nbytesdecoded -= 2;
  320. else
  321. nbytesdecoded -= 1;
  322. }
  323. /*
  324. //
  325. // Now we need to add a new wrapper sequence around the certificate
  326. // indicating this is a certificate
  327. //
  328. memmove( beginbuf + sizeof(abCertHeader),
  329. beginbuf,
  330. nbytesdecoded );
  331. memcpy( beginbuf,
  332. abCertHeader,
  333. sizeof(abCertHeader) );
  334. //
  335. // The beginning record size is the total number of bytes decoded plus
  336. // the number of bytes in the certificate header
  337. //
  338. beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
  339. beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
  340. nbytesdecoded += sizeof(abCertHeader);
  341. */
  342. if ( pcbDecoded )
  343. *pcbDecoded = nbytesdecoded;
  344. }
  345. // ============ END BASED ON SETKEY
  346. //#endif /* WE_ARE_USING_THE_VERSION_IN__CKey_cpp__NOT_THIS_ONE__ITS_JUST_LIKE_THIS_ONE_WITH_1SMALL_CHANGE */