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.

882 lines
21 KiB

  1. /*++
  2. KEYTAB.C
  3. Implementation of the actual keytab routines.
  4. Copyright (C) 1997 Microsoft Corporation
  5. Created 01-10-1997 DavidCHR
  6. --*/
  7. #include "master.h"
  8. #include "keytab.h"
  9. #include "keytypes.h"
  10. #include "defs.h"
  11. /* declaring KEYTAB_ALLOC and KEYTAB_FREE lets me hook into these
  12. routines whenever I want. when it's done, I'll just #def them. */
  13. PVOID
  14. KEYTAB_ALLOC ( KTLONG32 numBytes ) {
  15. return malloc(numBytes);
  16. }
  17. VOID
  18. KEYTAB_FREE ( PVOID toFree ) {
  19. free(toFree);
  20. }
  21. PKTENT
  22. CloneKeyEntry( PKTENT pEntry ) {
  23. KTLONG32 i;
  24. PKTENT p=NULL;
  25. BOOL ret=FALSE;
  26. p = (PKTENT) KEYTAB_ALLOC( sizeof( KTENT ) );
  27. BREAK_IF( p == NULL,
  28. "Failed to alloc base key struct",
  29. cleanup );
  30. memcpy( p, pEntry, sizeof(KTENT) );
  31. p->Components = NULL; // initialize these in case of failure.
  32. p->KeyData = NULL;
  33. p->Realm = (PCHAR) KEYTAB_ALLOC( p->szRealm );
  34. BREAK_IF( p->Realm == NULL, "Failed to alloc realm data", cleanup );
  35. memcpy( p->Realm, pEntry->Realm, p->szRealm );
  36. p->Components = (PKTCOMPONENT) KEYTAB_ALLOC( p->cEntries *
  37. sizeof(KTCOMPONENT) );
  38. BREAK_IF( p->Components == NULL, "Failed to alloc components", cleanup );
  39. for ( i = 0 ; i < p->cEntries ; i++ ) {
  40. p->Components[i].szComponentData =
  41. pEntry->Components[i].szComponentData;
  42. memcpy( p ->Components[i].Component,
  43. pEntry->Components[i].Component,
  44. p ->Components[i].szComponentData );
  45. }
  46. p->KeyData = (PK5_OCTET) KEYTAB_ALLOC ( p->KeyLength );
  47. BREAK_IF( p->KeyData == NULL, "Failed to alloc keydata", cleanup );
  48. memcpy( p->KeyData, pEntry->KeyData, p->KeyLength );
  49. return p;
  50. cleanup:
  51. FreeKeyEntry(p);
  52. return NULL;
  53. }
  54. /* base linklist operations */
  55. BOOL
  56. AddEntryToKeytab( PKTFILE Keytab,
  57. PKTENT Entry,
  58. BOOL copy ) {
  59. PKTENT p;
  60. if (copy) {
  61. p = CloneKeyEntry( Entry );
  62. } else {
  63. p = Entry;
  64. }
  65. if (p == NULL ) {
  66. return FALSE;
  67. }
  68. if ( NULL == Keytab->FirstKeyEntry ) {
  69. Keytab->FirstKeyEntry = Keytab->LastKeyEntry = p;
  70. } else {
  71. Keytab->LastKeyEntry->nextEntry = p;
  72. Keytab->LastKeyEntry = p;
  73. }
  74. return TRUE;
  75. }
  76. BOOL
  77. RemoveEntryFromKeytab( PKTFILE Keytab,
  78. PKTENT Entry,
  79. BOOL dealloc ) {
  80. if ( (NULL == Keytab) || ( NULL == Entry ) ) {
  81. return FALSE;
  82. }
  83. if ( Keytab->FirstKeyEntry == Entry ) {
  84. // removing the first key
  85. Keytab->FirstKeyEntry = Entry->nextEntry;
  86. if ( Entry->nextEntry == NULL ) {
  87. // we're the ONLY entry.
  88. Keytab->LastKeyEntry = NULL;
  89. }
  90. } else {
  91. BOOL found=FALSE;
  92. PKTENT p;
  93. // scroll through the keys, looking for this one.
  94. // not very efficient, but keytabs shouldn't get very big.
  95. for (p = Keytab->FirstKeyEntry;
  96. p != NULL;
  97. p = p->nextEntry ) {
  98. if (p->nextEntry == Entry) {
  99. found = TRUE;
  100. p->nextEntry = Entry->nextEntry;
  101. break;
  102. }
  103. }
  104. if (!found) {
  105. // wasn't in the linklist.
  106. return FALSE;
  107. }
  108. if (Entry->nextEntry == NULL ) {
  109. // removing the last key entry.
  110. Keytab->LastKeyEntry = p;
  111. }
  112. }
  113. if (dealloc) {
  114. FreeKeyEntry(Entry);
  115. }
  116. return TRUE;
  117. }
  118. VOID
  119. FreeKeyEntry( PKTENT pEntry) {
  120. KTLONG32 i;
  121. if (pEntry != NULL) {
  122. if (pEntry->Realm != NULL ) {
  123. KEYTAB_FREE(pEntry->Realm);
  124. }
  125. if (pEntry->KeyData != NULL) {
  126. KEYTAB_FREE(pEntry->KeyData);
  127. }
  128. if (pEntry->Components != NULL) {
  129. for (i = 0; i < pEntry->cEntries ; i++ ) {
  130. if ( pEntry->Components[i].Component != NULL ) {
  131. KEYTAB_FREE(pEntry->Components[i].Component);
  132. }
  133. }
  134. KEYTAB_FREE(pEntry->Components);
  135. }
  136. KEYTAB_FREE(pEntry );
  137. }
  138. }
  139. VOID
  140. FreeKeyTab( PKTFILE pktf ) {
  141. PKTENT pEntry=NULL;
  142. PKTENT next=NULL;
  143. if (pktf != NULL) {
  144. for (pEntry = pktf->FirstKeyEntry ;
  145. pEntry != NULL;
  146. pEntry = next ) {
  147. KTLONG32 i;
  148. next = pEntry->nextEntry; /* must do this, because we're freeing
  149. as we go */
  150. FreeKeyEntry( pEntry );
  151. KEYTAB_FREE(pEntry );
  152. }
  153. KEYTAB_FREE(pktf);
  154. }
  155. }
  156. /* These macros make this somewhat LESS painful */
  157. #define READ(readwhat, errormsg, statusmsg) { \
  158. debug(statusmsg); \
  159. BREAK_IF( !Read(hFile, &(readwhat), sizeof(readwhat), 1), \
  160. errormsg, cleanup); \
  161. debug("ok\n"); \
  162. }
  163. #define READSTRING(readwhat, howlong, errormsg, statusmsg) { \
  164. debug(statusmsg); \
  165. BREAK_IF( !Read(hFile, readwhat, sizeof(CHAR), howlong), \
  166. errormsg, cleanup); \
  167. debug("ok\n"); \
  168. }
  169. #define WRITE(writewhat, description) { \
  170. debug("writing %hs...", description); \
  171. BREAK_IF( !Write(hFile, &(writewhat), sizeof(writewhat), 1), \
  172. "error writing " description, cleanup); \
  173. debug("ok\n"); \
  174. }
  175. #define WRITE_STRING(writewhat, howlong, description) { \
  176. debug("writing %hs...", description); \
  177. BREAK_IF( !Write(hFile, writewhat, sizeof(CHAR), howlong), \
  178. "error writing " description, cleanup); \
  179. debug("ok\n"); \
  180. }
  181. #define WRITE_X( size, marshaller, writewhat, description ) { \
  182. K5_INT##size k5_marshaller_variable; \
  183. k5_marshaller_variable = marshaller( writewhat );\
  184. WRITE( k5_marshaller_variable, description );\
  185. }
  186. // NBO-- Network Byte Order
  187. #define WRITE_NBO( writewhat, description) {\
  188. switch( sizeof( writewhat ) ) {\
  189. case 1: /* marshall a char? */\
  190. debug("marshalling a char(?)...");\
  191. WRITE( writewhat, description );\
  192. break;\
  193. case 2:\
  194. debug( #writewhat ": marshalling a short...");\
  195. WRITE_X( 16, htons, ((unsigned short)writewhat), description);\
  196. break;\
  197. case 4:\
  198. debug( #writewhat ": marshalling a long...");\
  199. WRITE_X( 32, htonl, writewhat, description);\
  200. break;\
  201. default:\
  202. fprintf(stderr, "Not written: argument is of unhandled size (%d)\n",\
  203. sizeof(writewhat));\
  204. }}
  205. /* Write:
  206. helper function to write raw bytes to disk. Takes:
  207. hFile: handle to a file open for writing.
  208. source: pointer to data to be written to the file
  209. szSource: size of one data element in Source
  210. numSources: number of data elements in Source
  211. (basically, it tries to write szSource * numSources of raw bytes
  212. from source to the file at hFile).
  213. returns TRUE if it succeeds, and FALSE otherwise.
  214. */
  215. BOOL
  216. Write( IN HANDLE hFile,
  217. IN PVOID source,
  218. IN KTLONG32 szSource,
  219. IN KTLONG32 numSources /* =1 */ ) {
  220. #ifdef WINNT /* Windows NT implementation of the file write call */
  221. KTLONG32 temp;
  222. KTLONG32 i;
  223. temp = szSource * numSources;
  224. debug("(writing %d bytes: ", temp );
  225. for (i = 0; i < temp ; i++ ) {
  226. unsigned char byte;
  227. byte = ((PCHAR) source)[i];
  228. debug("%02x", byte );
  229. }
  230. debug(")");
  231. return WriteFile( hFile, source, temp, &temp, NULL );
  232. #else
  233. ssize_t bytesToWrite, bytesWritten;
  234. bytesToWrite = szSource * numSources;
  235. bytesWritten = write( hFile, (const void *)source,
  236. bytesToWrite );
  237. if( bytesWritten == -1 ) {
  238. debug("WARNING: nothing written to the file! Errno = 0x%x / %d\n",
  239. errno , errno );
  240. return FALSE;
  241. }
  242. if ( bytesWritten != bytesToWrite ) {
  243. debug("WARNING: not all bytes made it to the file (?)\n"
  244. " errno = 0x%x / %d\n", errno, errno );
  245. return FALSE;
  246. }
  247. return TRUE;
  248. #endif
  249. }
  250. /* Read:
  251. Semantics and return are the same as for "Write", except that
  252. target is filled with szTarget*numTargets bytes from hFile, and that
  253. hFile must be open for read access.
  254. */
  255. BOOL
  256. Read( IN HANDLE hFile,
  257. OUT PVOID target,
  258. IN KTLONG32 szTarget,
  259. IN KTLONG32 numTargets/* =1 */) {
  260. BOOL ret = FALSE;
  261. #ifdef WINNT /* the SetFilePointer shinanigens are me trying to check on
  262. how many bytes have ACTUALLY been read/written from the
  263. file */
  264. KTLONG32 temp;
  265. KTLONG32 filepos;
  266. LONG zero=0L;
  267. filepos = SetFilePointer( hFile, 0, &zero, FILE_CURRENT);
  268. debug("reading %d bytes from pos 0x%x...", szTarget * numTargets,
  269. filepos);
  270. ret = ReadFile( hFile,
  271. target,
  272. (szTarget*numTargets),
  273. &temp,
  274. NULL );
  275. if ( !ret ) {
  276. debug( "ReadFile failed: 0x%x\n",
  277. GetLastError() );
  278. } else if ( !temp ) {
  279. debug( "ReadFile read zero bytes. Assuming EOF\n" );
  280. SetLastError( ERROR_HANDLE_EOF );
  281. ret = FALSE;
  282. } else {
  283. temp = SetFilePointer( hFile, 0, &zero, FILE_CURRENT);
  284. if ( filepos == temp ) {
  285. debug("WARNING! file position has not changed!");
  286. SetLastError( ERROR_NO_DATA );
  287. return FALSE;
  288. }
  289. }
  290. #else /* UNIX IMPLEMENTATION-- since read() returns the number of bytes
  291. that we actually read from the file, the
  292. SetFilePointer (fseek) nonsense is not
  293. required. */
  294. ssize_t bytesRead;
  295. ssize_t bytesToRead;
  296. bytesToRead = szTarget * numTargets;
  297. bytesRead = read( hFile, target, bytesToRead );
  298. if ( bytesRead == -1 ) {
  299. debug("WARNING! An error occurred while writing to the file!\n"
  300. "ERRNO: 0x%x / %d.\n", errno, errno );
  301. }
  302. ret = (bytesRead == bytesToRead );
  303. #endif
  304. return ret;
  305. }
  306. BOOL
  307. ReadKeytabFromFile( PKTFILE *ppktfile, // free with FreeKeyTab when done
  308. PCHAR filename ) {
  309. PKTFILE ktfile=NULL;
  310. HANDLE hFile = NULL;
  311. BOOL ret=FALSE;
  312. KTLONG32 i;
  313. BREAK_IF( ppktfile == NULL,
  314. "passed a NULL save-pointer",
  315. cleanup );
  316. debug("Opening keytab file \"%hs\"...", filename);
  317. #ifdef WINNT
  318. hFile = CreateFileA( filename,
  319. GENERIC_READ,
  320. FILE_SHARE_READ,
  321. NULL,
  322. OPEN_EXISTING,
  323. FILE_ATTRIBUTE_NORMAL,
  324. NULL );
  325. BREAK_IF ( (NULL == hFile) || ( INVALID_HANDLE_VALUE == hFile ),
  326. "Failed to open file!", cleanup );
  327. #else
  328. hFile = open( filename, O_RDONLY,
  329. /* file mask is 0x550: read-write by user and group */
  330. S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP );
  331. BREAK_IF( hFile == -1,
  332. "Failed to open file!", cleanup );
  333. #endif
  334. debug("ok!\n");
  335. ktfile = (PKTFILE) KEYTAB_ALLOC (sizeof(KTFILE));
  336. /* Prefix bug 439480 resulted from the below BREAK_IF
  337. being interchanged with initialization code. Duhhh. */
  338. BREAK_IF( ktfile == NULL,
  339. "Failed to allocate ktfile",
  340. cleanup );
  341. ktfile->FirstKeyEntry = ktfile->LastKeyEntry = NULL;
  342. READ( ktfile->Version, "Failed to read KTVNO",
  343. "reading KTVNO");
  344. /* Version number is stored in network byte order */
  345. ktfile->Version = ntohs( ktfile->Version);
  346. debug("Keytab version 0x%x\n", ktfile->Version );
  347. do {
  348. PKTENT entry=NULL;
  349. entry = (PKTENT) KEYTAB_ALLOC(sizeof(KTENT));
  350. // PREFIX bug 439481: not checking the result of KEYTAB_ALLOC.
  351. BREAK_IF( !entry,
  352. "Unable to alloc a new KTENT.",
  353. cleanup );
  354. entry->Realm = NULL;
  355. entry->Components = NULL;
  356. entry->KeyData = NULL;
  357. entry->nextEntry = NULL;
  358. #if 1
  359. if ( !Read( hFile,
  360. &(entry->keySize),
  361. sizeof( entry->keySize ),
  362. 1 ) ) {
  363. if ( GetLastError() != ERROR_HANDLE_EOF ) {
  364. fprintf( stderr,
  365. "\n ** Failed to read Keytab %hs's leading bytes: 0x%x\n",
  366. filename,
  367. GetLastError() );
  368. } else {
  369. ret = TRUE;
  370. }
  371. break;
  372. }
  373. #else
  374. BREAK_IF( !Read( hFile, &(entry->keySize), sizeof(entry->keySize), 1),
  375. "Failed to read leading bytes (probably done)",
  376. no_more_entries );
  377. #endif
  378. entry->keySize = htonl(entry->keySize);
  379. debug("trash bytes: 0x%x\n", entry->keySize );
  380. /* Quickly perform linklist operation on the new node */
  381. if (NULL == ktfile->FirstKeyEntry) {
  382. ktfile->FirstKeyEntry = ktfile->LastKeyEntry = entry;
  383. } else {
  384. ktfile->LastKeyEntry->nextEntry = entry;
  385. ktfile->LastKeyEntry = entry;
  386. }
  387. READ( entry->cEntries,
  388. "Failed to read key's number of components",
  389. "reading key components...");
  390. entry->cEntries = ntohs( entry->cEntries );
  391. debug("components number %d\n", entry->cEntries );
  392. READ( entry->szRealm,
  393. "Failed to read key's realm size",
  394. "reading key realm size...");
  395. entry->szRealm = ntohs( entry->szRealm );
  396. debug("realm size %d\n", entry->szRealm);
  397. entry->Realm = (PCHAR) KEYTAB_ALLOC( ( entry->szRealm +1 )
  398. * sizeof(CHAR) );
  399. BREAK_IF ( !entry->Realm,
  400. "Could not allocate key's realm storage",
  401. cleanup );
  402. READSTRING( entry->Realm, entry->szRealm,
  403. "Could not read key's realmname",
  404. "reading realmname...");
  405. entry->Realm[ entry->szRealm ] = '\0';
  406. debug("realm: \"%hs\"\n", entry->Realm );
  407. entry->Components = (PKTCOMPONENT) KEYTAB_ALLOC (entry->cEntries *
  408. sizeof(KTCOMPONENT));
  409. BREAK_IF( !entry->Components,
  410. "Could not allocate key components!",
  411. cleanup );
  412. for (i = 0 ; i < entry->cEntries ; i++ ) {
  413. READ( entry->Components[i].szComponentData,
  414. "Failed to read component size for one entry",
  415. "reading key component size...");
  416. entry->Components[i].szComponentData =
  417. ntohs( entry->Components[i].szComponentData );
  418. debug("Component size: %d\n",
  419. entry->Components[i].szComponentData );
  420. entry->Components[i].Component = (PCHAR) KEYTAB_ALLOC (
  421. ( entry->Components[i].szComponentData +1 ) *
  422. sizeof(CHAR) );
  423. entry->Components[i].Component[
  424. entry->Components[i].szComponentData ] = '\0';
  425. BREAK_IF( !entry->Components[i].Component,
  426. "Could not allocate entry component storage",
  427. cleanup );
  428. READSTRING( entry->Components[i].Component,
  429. entry->Components[i].szComponentData,
  430. "Failed to read component data",
  431. "reading component data...");
  432. debug("Component data: \"%hs\"\n",
  433. entry->Components[i].Component );
  434. }
  435. READ( entry->PrincType,
  436. "Failed to read principal type",
  437. "reading principal type...");
  438. entry->PrincType = ntohl( entry->PrincType ); // in network byte order
  439. debug("princtype: %d\n", entry->PrincType);
  440. READ( entry->TimeStamp,
  441. "Failed to read entry timestamp",
  442. "reading timestamp...");
  443. entry->TimeStamp = ntohl( entry->TimeStamp ); // also network bytes.
  444. debug("Timestamp 0x%x\n", entry->TimeStamp );
  445. READ( entry->Version,
  446. "Failed to read kvno",
  447. "reading kvno...");
  448. // kvno is in host order already.
  449. READ( entry->KeyType,
  450. "Failed to read entry encryption type",
  451. "reading encryption type...");
  452. entry->KeyType = ntohs( entry->KeyType );
  453. READ( entry->KeyLength,
  454. "Failed to read entry keylength",
  455. "reading keylength... ");
  456. #if 1
  457. entry->KeyLength = ntohs ( entry->KeyLength );
  458. #else // I used to think this was 32-bit.
  459. entry->KeyLength = ntohl ( entry->KeyLength );
  460. #endif
  461. debug("KeyLength is %d\n", entry->KeyLength);
  462. entry->KeyData = (PK5_OCTET) KEYTAB_ALLOC (entry->KeyLength *
  463. sizeof(K5_OCTET));
  464. BREAK_IF( !entry->KeyData,
  465. "Could not allocate entry keydata storage",
  466. cleanup );
  467. READSTRING( entry->KeyData, entry->KeyLength,
  468. "Failed to read entry key data",
  469. "reading key data")
  470. } while (1);
  471. cleanup:
  472. #ifdef WINNT
  473. if ((hFile != NULL) && ( hFile != INVALID_HANDLE_VALUE)) {
  474. CloseHandle(hFile);
  475. }
  476. #else
  477. if (hFile != -1 ) {
  478. close(hFile);
  479. }
  480. #endif
  481. if (ret) {
  482. *ppktfile = ktfile;
  483. } else {
  484. FreeKeyTab( ktfile );
  485. }
  486. return ret;
  487. }
  488. /* define this macro only for DisplayKeytab.
  489. It's a convenience routine to print this field only if the option
  490. is set. */
  491. #define PRINTFIELD( option, format, value ) { if (options & option) { fprintf(stream, format, value); } }
  492. /* DisplayKeytab:
  493. prints out the keytab, using options to define which fields we want
  494. to actually see. (see keytab.hxx for what to put in "options") */
  495. VOID
  496. DisplayKeytab( FILE *stream,
  497. PKTFILE ktfile,
  498. KTLONG32 options) {
  499. KTLONG32 i;
  500. PKTENT ent;
  501. if (options == 0L) {
  502. return;
  503. }
  504. PRINTFIELD(KT_KTVNO, "Keytab version: 0x%x\n", ktfile->Version);
  505. for (ent = ktfile->FirstKeyEntry ;
  506. ent != NULL;
  507. ent = ent->nextEntry ) {
  508. PRINTFIELD( KT_RESERVED, "keysize %d ", ent->keySize );
  509. for (i = 0 ; i < ent->cEntries ; i++ ) {
  510. PRINTFIELD( KT_COMPONENTS,
  511. (i == 0 ? "%hs" : "/%hs"),
  512. ent->Components[i].Component );
  513. }
  514. PRINTFIELD( KT_REALM, "@%hs", ent->Realm );
  515. PRINTFIELD( KT_PRINCTYPE, " ptype %d", ent->PrincType );
  516. PRINTFIELD( KT_PRINCTYPE, " (%hs)", LookupTable( ent->PrincType, &K5PType_Strings ).string);
  517. PRINTFIELD( KT_VNO, " vno %d", ent->Version );
  518. PRINTFIELD( KT_KEYTYPE, " etype 0x%x", ent->KeyType );
  519. PRINTFIELD( KT_KEYTYPE, " (%hs)", LookupTable( ent->KeyType,
  520. &K5EType_Strings ).string );
  521. PRINTFIELD( KT_KEYLENGTH, " keylength %d", ent->KeyLength );
  522. if (options & KT_KEYDATA ) {
  523. fprintf(stream, " (0x" );
  524. for ( i = 0 ; i < ent->KeyLength ; i++ ) {
  525. fprintf(stream, "%02x", ent->KeyData[i] );
  526. }
  527. fprintf(stream, ")" );
  528. }
  529. fprintf(stream, "\n");
  530. }
  531. }
  532. #undef PRINTFIELD // we only need it for that function
  533. /* computes the length of a kerberos keytab for the keySize field */
  534. K5_INT32
  535. ComputeKeytabLength( PKTENT p ) {
  536. K5_INT32 ret=0L;
  537. KTLONG32 i;
  538. // these are the variables within this level
  539. ret = p->szRealm + p->KeyLength;
  540. // these are static
  541. ret += ( sizeof( p->cEntries ) + sizeof(p->szRealm) +
  542. sizeof( p->PrincType ) + sizeof( p->TimeStamp ) +
  543. sizeof( p->Version ) + sizeof (p->KeyLength ) +
  544. sizeof( p->KeyType ) );
  545. for (i = 0 ; i < p->cEntries; i++ ) {
  546. ret += ( p->Components[i].szComponentData +
  547. sizeof(p->Components[i].szComponentData) );
  548. }
  549. debug("ComputeKeytabLength: returning %d\n", ret);
  550. return ret;
  551. }
  552. /* This depends very much on the same keytab model that
  553. the other functions do */
  554. BOOL
  555. WriteKeytabToFile( PKTFILE ktfile,
  556. PCHAR filename ) {
  557. HANDLE hFile = NULL;
  558. BOOL ret=FALSE;
  559. KTLONG32 i;
  560. PKTENT entry;
  561. BREAK_IF( ktfile == NULL,
  562. "passed a NULL save-pointer",
  563. cleanup );
  564. debug("opening keytab file \"%hs\" for write...", filename);
  565. #ifdef WINNT
  566. hFile = CreateFileA( filename,
  567. GENERIC_WRITE,
  568. 0L,
  569. NULL,
  570. CREATE_ALWAYS,
  571. FILE_ATTRIBUTE_NORMAL,
  572. NULL );
  573. BREAK_IF( ( hFile == INVALID_HANDLE_VALUE ),
  574. "Failed to create file!", cleanup );
  575. #else
  576. hFile = open( filename, O_WRONLY | O_CREAT | O_TRUNC,
  577. /* file mask is 0x550: read-write by user and group */
  578. S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP );
  579. BREAK_IF( hFile == -1,
  580. "Failed to create file!", cleanup );
  581. #endif
  582. debug("ok\n");
  583. WRITE_NBO( ktfile->Version, "KTFVNO" );
  584. for( entry = ktfile->FirstKeyEntry ;
  585. entry != NULL ;
  586. entry = entry->nextEntry ) {
  587. WRITE_NBO( entry->keySize, "key size (in bytes)");
  588. WRITE_NBO( entry->cEntries, "number of components" );
  589. WRITE_NBO( entry->szRealm, "Realm length" );
  590. WRITE_STRING( entry->Realm, entry->szRealm, "Realm data" );
  591. for (i = 0 ; i < entry->cEntries ; i++ ) {
  592. WRITE_NBO( entry->Components[i].szComponentData,
  593. "component datasize");
  594. WRITE_STRING( entry->Components[i].Component,
  595. entry->Components[i].szComponentData,
  596. "component data");
  597. }
  598. WRITE_NBO( entry->PrincType, "Principal Type");
  599. WRITE_NBO( entry->TimeStamp, "Timestamp" );
  600. WRITE( entry->Version, "Key Version Number" );
  601. WRITE_NBO( entry->KeyType, "Key Encryption Type" );
  602. #if 0 // eh?
  603. /* again, this is a kludge to get around the keylength
  604. problem we can't explain */
  605. #endif
  606. ASSERT( sizeof( entry->KeyLength ) == 2 );
  607. WRITE_NBO(entry->KeyLength, "key length" );
  608. WRITE_STRING( entry->KeyData,
  609. entry->KeyLength,
  610. "key data itself" );
  611. }
  612. ret = TRUE;
  613. cleanup:
  614. CloseHandle(hFile);
  615. return ret;
  616. }