Leaked source code of windows server 2003
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.

428 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 <schannel.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 * pException )
  89. {
  90. pException->Delete();
  91. // return failure
  92. fSuccess = FALSE;
  93. // if the pointer was allocated, deallocate it
  94. if ( pData )
  95. {
  96. GlobalFree( pData );
  97. pData = NULL;
  98. }
  99. }
  100. // return success
  101. return fSuccess;
  102. }
  103. #define CERT_HEADER_LEN 17
  104. CHAR CertTag[ 13 ] = { 0x04, 0x0b, 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e' };
  105. //---------------------------------------------------------------------------
  106. // we are passed in a complete certificate. We need to parse out the subject
  107. // and the issuer fields so we can add the mapping. Then add the mapping.
  108. #define CF_CERT_FROM_FILE 2
  109. BOOL CMap11Page::FAddCertificate( PUCHAR pCertificate, DWORD cbCertificate )
  110. {
  111. BOOL fSuccess = FALSE;
  112. // thankfully, the certificate is already in the correct format.
  113. // this means that, for now at least, we don't have to do anything
  114. // special to it to store it. However, we should crack it once just
  115. // to see that we can to prove that it is a valid cert.
  116. ASSERT( pCertificate );
  117. if ( !pCertificate ) return FALSE;
  118. // crack the certificate to prove that we can
  119. PX509Certificate p509 = NULL;
  120. fSuccess = SslCrackCertificate( pCertificate, cbCertificate, CF_CERT_FROM_FILE, &p509 );
  121. if ( fSuccess )
  122. {
  123. SslFreeCertificate( p509 );
  124. }
  125. else
  126. {
  127. // we were not able to crack the certificate. Alert the user and fail
  128. AfxMessageBox( IDS_ERR_INVALID_CERTIFICATE );
  129. return FALSE;
  130. }
  131. // by this point we know we have a valid certificate, make the new mapping and fill it in
  132. // make the new mapping object
  133. C11Mapping* pMapping = PNewMapping();
  134. ASSERT( pMapping );
  135. if( !pMapping )
  136. {
  137. AfxThrowMemoryException(); // seems fairly appropriate
  138. return FALSE;
  139. }
  140. // one more thing before we add the certificate. Skip the header if it is there
  141. PUCHAR pCert = pCertificate;
  142. DWORD cbCert = cbCertificate;
  143. if ( memcmp( pCert + 4, CertTag, sizeof( CertTag ) ) == 0 )
  144. {
  145. pCert += CERT_HEADER_LEN;
  146. cbCert -= CERT_HEADER_LEN;
  147. }
  148. // install the certificate into the mapping
  149. fSuccess &= pMapping->SetCertificate( pCert, cbCert );
  150. // by default, the mapping is enabled
  151. fSuccess &= pMapping->SetMapEnabled( TRUE );
  152. // install a default name
  153. CString sz;
  154. sz.LoadString( IDS_DEFAULT_11MAP );
  155. fSuccess &= pMapping->SetMapName( sz );
  156. // install a blank mapping
  157. fSuccess &= pMapping->SetNTAccount( "" );
  158. if ( !fSuccess )
  159. AfxThrowMemoryException(); // seems fairly appropriate
  160. // now edit the newly created mapping object. If the user cancels,
  161. // then do not add it to the mapper object nor the list
  162. if ( !EditOneMapping( pMapping) )
  163. {
  164. DeleteMapping( pMapping );
  165. return FALSE;
  166. }
  167. // add the mapping item to the list control
  168. fSuccess = FAddMappingToList( pMapping );
  169. // one more test for success
  170. if ( !fSuccess )
  171. {
  172. DeleteMapping( pMapping );
  173. ASSERT( FALSE );
  174. }
  175. // mark the mapping to be saved
  176. if ( fSuccess )
  177. MarkToSave( pMapping );
  178. // return the answer
  179. return fSuccess;
  180. }
  181. // ==============================================================
  182. // The function 'uudecode_cert' IS THE SAME function that is
  183. // found in file: Addcert.cpp if we make the following code
  184. // have a FALSE for bAddWrapperAroundCert -- surely we can unify
  185. // these 2 functions. Having 2 functions named 'uudecode_cert'
  186. // was causing me LINKING errors. + we have 2 instances of
  187. // the external tables: uudecode_cert and pr2six
  188. //
  189. // Since I am linking both Addcert.cpp and CKey.cpp I choose to
  190. // leave the defintions intact for CKey.cpp [ and have extended
  191. // uudecode_cert by adding conditional code as shown below] Further
  192. // work needs to be done after identification as to why I need both
  193. // Addcert.cpp and CKey.cpp to pass bAddWrapperAroundCert as a
  194. // parameter so that both files can be supported.
  195. // ==============================================================
  196. // BOOL bAddWrapperAroundCert = TRUE;
  197. // if (bAddWrapperAroundCert) {
  198. // //
  199. // // Now we need to add a new wrapper sequence around the certificate
  200. // // indicating this is a certificate
  201. // //
  202. //
  203. // memmove( beginbuf + sizeof(abCertHeader),
  204. // beginbuf,
  205. // nbytesdecoded );
  206. //
  207. // memcpy( beginbuf,
  208. // abCertHeader,
  209. // sizeof(abCertHeader) );
  210. //
  211. // //
  212. // // The beginning record size is the total number of bytes decoded plus
  213. // // the number of bytes in the certificate header
  214. // //
  215. //
  216. // beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
  217. // beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
  218. //
  219. // nbytesdecoded += sizeof(abCertHeader);
  220. // }
  221. // #ifdef WE_ARE_USING_THE_VERSION_IN__CKey_cpp__NOT_THIS_ONE__ITS_JUST_LIKE_THIS_ONE_WITH_1SMALL_CHANGE
  222. //============================ BASED ON SETKEY
  223. const int pr2six[256]={
  224. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  225. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  226. 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,
  227. 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  228. 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  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,64,64,64,64,64,64,64,64,64,64,64,
  233. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  234. 64,64,64,64,64,64,64,64,64,64,64,64,64
  235. };
  236. //
  237. // We have to squirt a record into the decoded stream
  238. //
  239. #define CERT_RECORD 13
  240. #define CERT_SIZE_HIBYTE 2 // Index into record of record size
  241. #define CERT_SIZE_LOBYTE 3
  242. unsigned char abCertHeader[] = {0x30, 0x82, // Record
  243. 0x00, 0x00, // Size of cert + buff
  244. 0x04, 0x0b, 0x63, 0x65,// Cert record data
  245. 0x72, 0x74, 0x69, 0x66,
  246. 0x69, 0x63, 0x61, 0x74,
  247. 0x65 };
  248. void uudecode_cert(char *bufcoded, DWORD *pcbDecoded )
  249. {
  250. int nbytesdecoded;
  251. char *bufin = bufcoded;
  252. unsigned char *bufout = (unsigned char *)bufcoded;
  253. unsigned char *pbuf;
  254. int nprbytes;
  255. char * beginbuf = bufcoded;
  256. ASSERT(bufcoded);
  257. ASSERT(pcbDecoded);
  258. /* Strip leading whitespace. */
  259. while(*bufcoded==' ' ||
  260. *bufcoded == '\t' ||
  261. *bufcoded == '\r' ||
  262. *bufcoded == '\n' )
  263. {
  264. bufcoded++;
  265. }
  266. //
  267. // If there is a beginning '---- ....' then skip the first line
  268. //
  269. if ( bufcoded[0] == '-' && bufcoded[1] == '-' )
  270. {
  271. bufin = strchr( bufcoded, '\n' );
  272. if ( bufin )
  273. {
  274. bufin++;
  275. bufcoded = bufin;
  276. }
  277. else
  278. {
  279. bufin = bufcoded;
  280. }
  281. }
  282. else
  283. {
  284. bufin = bufcoded;
  285. }
  286. //
  287. // Strip all cr/lf from the block
  288. //
  289. pbuf = (unsigned char *)bufin;
  290. while ( *pbuf )
  291. {
  292. if ( (*pbuf == ' ') || (*pbuf == '\r') || (*pbuf == '\n') )
  293. {
  294. memmove( (void*)pbuf, pbuf+1, strlen( (char*)pbuf + 1) + 1 );
  295. }
  296. else
  297. {
  298. pbuf++;
  299. }
  300. }
  301. /* Figure out how many characters are in the input buffer.
  302. * If this would decode into more bytes than would fit into
  303. * the output buffer, adjust the number of input bytes downwards.
  304. */
  305. while(pr2six[*(bufin++)] <= 63);
  306. nprbytes = DIFF(bufin - bufcoded) - 1;
  307. nbytesdecoded = ((nprbytes+3)/4) * 3;
  308. bufin = bufcoded;
  309. while (nprbytes > 0) {
  310. *(bufout++) =
  311. (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  312. *(bufout++) =
  313. (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  314. *(bufout++) =
  315. (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  316. bufin += 4;
  317. nprbytes -= 4;
  318. }
  319. if(nprbytes & 03) {
  320. if(pr2six[bufin[-2]] > 63)
  321. nbytesdecoded -= 2;
  322. else
  323. nbytesdecoded -= 1;
  324. }
  325. /*
  326. //
  327. // Now we need to add a new wrapper sequence around the certificate
  328. // indicating this is a certificate
  329. //
  330. memmove( beginbuf + sizeof(abCertHeader),
  331. beginbuf,
  332. nbytesdecoded );
  333. memcpy( beginbuf,
  334. abCertHeader,
  335. sizeof(abCertHeader) );
  336. //
  337. // The beginning record size is the total number of bytes decoded plus
  338. // the number of bytes in the certificate header
  339. //
  340. beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
  341. beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
  342. nbytesdecoded += sizeof(abCertHeader);
  343. */
  344. if ( pcbDecoded )
  345. *pcbDecoded = nbytesdecoded;
  346. }
  347. // ============ END BASED ON SETKEY
  348. //#endif /* WE_ARE_USING_THE_VERSION_IN__CKey_cpp__NOT_THIS_ONE__ITS_JUST_LIKE_THIS_ONE_WITH_1SMALL_CHANGE */