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.

1160 lines
31 KiB

  1. #define UNICODE
  2. #define INC_OLE2
  3. #include <windows.h>
  4. #include <activeds.h>
  5. #include <ntsecapi.h>
  6. #include <stdio.h> // printf
  7. #include <stdlib.h> // strtoul
  8. #include <assert.h>
  9. #define SECURITY_WIN32
  10. #include <security.h> // General definition of a Security Support Provider
  11. #include <shlwapi.h>
  12. typedef int krb5_int32;
  13. typedef short krb5_int16;
  14. typedef unsigned int krb5_kvno;
  15. typedef unsigned char krb5_octet;
  16. typedef unsigned int krb5_enctype;
  17. typedef krb5_int32 krb5_deltat;
  18. typedef krb5_int32 krb5_flags;
  19. typedef krb5_int32 krb5_timestamp;
  20. typedef krb5_int32 krb5_error_code;
  21. typedef char FAR * krb5_principal;
  22. typedef void FAR * krb5_pointer;
  23. /*
  24. * Note --- these structures cannot be modified without changing the
  25. * database version number in libkdb.a, but should be expandable by
  26. * adding new tl_data types.
  27. */
  28. typedef struct _krb5_tl_data {
  29. struct _krb5_tl_data* tl_data_next; /* NOT saved */
  30. krb5_int16 tl_data_type;
  31. krb5_int16 tl_data_length;
  32. krb5_octet * tl_data_contents;
  33. } krb5_tl_data;
  34. /*
  35. * If this ever changes up the version number and make the arrays be as
  36. * big as necessary.
  37. *
  38. * Currently the first type is the enctype and the second is the salt type.
  39. */
  40. typedef struct _krb5_key_data {
  41. krb5_int16 key_data_ver; /* Version */
  42. krb5_int16 key_data_kvno; /* Key Version */
  43. krb5_int16 key_data_type[2]; /* Array of types */
  44. krb5_int16 key_data_length[2]; /* Array of lengths */
  45. krb5_octet * key_data_contents[2]; /* Array of pointers */
  46. } krb5_key_data;
  47. #define KRB5_KDB_V1_KEY_DATA_ARRAY 2 /* # of array elements */
  48. typedef struct _krb5_db_entry_new {
  49. krb5_int16 len;
  50. krb5_flags attributes;
  51. krb5_deltat max_life;
  52. krb5_deltat max_renewable_life;
  53. krb5_timestamp expiration; /* When the client expires */
  54. krb5_timestamp pw_expiration; /* When its passwd expires */
  55. krb5_timestamp last_success; /* Last successful passwd */
  56. krb5_timestamp last_failed; /* Last failed passwd attempt */
  57. krb5_kvno fail_auth_count; /* # of failed passwd attempt */
  58. krb5_int16 n_tl_data;
  59. krb5_int16 n_key_data;
  60. krb5_int16 e_length; /* Length of extra data */
  61. krb5_octet * e_data; /* Extra data to be saved */
  62. krb5_principal princ; /* Length, data */
  63. krb5_tl_data * tl_data; /* Linked list */
  64. krb5_key_data * key_data; /* Array */
  65. } krb5_db_entry;
  66. typedef struct _krb5_keyblock {
  67. krb5_enctype enctype;
  68. int length;
  69. krb5_octet FAR *contents;
  70. } krb5_keyblock;
  71. krb5_keyblock mkey;
  72. /* Strings */
  73. static const char k5_dump_header[] = "kdb5_util load_dump version 4\n";
  74. /* Message strings */
  75. static const char regex_err[] = "%s: regular expression error - %s\n";
  76. static const char regex_merr[] = "%s: regular expression match error - %s\n";
  77. static const char pname_unp_err[] = "%s: cannot unparse principal name (%s)\n";
  78. static const char mname_unp_err[] = "%s: cannot unparse modifier name (%s)\n";
  79. static const char nokeys_err[] = "%s: cannot find any standard key for %s\n";
  80. static const char sdump_tl_inc_err[] = "%s: tagged data list inconsistency for %s (counted %d, stored %d)\n";
  81. static const char stand_fmt_name[] = "Kerberos version 5";
  82. static const char old_fmt_name[] = "Kerberos version 5 old format";
  83. static const char b6_fmt_name[] = "Kerberos version 5 beta 6 format";
  84. static const char ofopen_error[] = "%s: cannot open %s for writing (%s)\n";
  85. static const char oflock_error[] = "%s: cannot lock %s (%s)\n";
  86. static const char dumprec_err[] = "%s: error performing %s dump (%s)\n";
  87. static const char dumphdr_err[] = "%s: error dumping %s header (%s)\n";
  88. static const char trash_end_fmt[] = "%s(%d): ignoring trash at end of line: ";
  89. static const char read_name_string[] = "name string";
  90. static const char read_key_type[] = "key type";
  91. static const char read_key_data[] = "key data";
  92. static const char read_pr_data1[] = "first set of principal attributes";
  93. static const char read_mod_name[] = "modifier name";
  94. static const char read_pr_data2[] = "second set of principal attributes";
  95. static const char read_salt_data[] = "salt data";
  96. static const char read_akey_type[] = "alternate key type";
  97. static const char read_akey_data[] = "alternate key data";
  98. static const char read_asalt_type[] = "alternate salt type";
  99. static const char read_asalt_data[] = "alternate salt data";
  100. static const char read_exp_data[] = "expansion data";
  101. static const char store_err_fmt[] = "%s(%d): cannot store %s(%s)\n";
  102. static const char add_princ_fmt[] = "%s\n";
  103. static const char parse_err_fmt[] = "%s(%d): cannot parse %s (%s)\n";
  104. static const char read_err_fmt[] = "%s(%d): cannot read %s\n";
  105. static const char no_mem_fmt[] = "%s(%d): no memory for buffers\n";
  106. static const char rhead_err_fmt[] = "%s(%d): cannot match size tokens\n";
  107. static const char err_line_fmt[] = "%s: error processing line %d of %s\n";
  108. static const char head_bad_fmt[] = "%s: dump header bad in %s\n";
  109. static const char read_bytecnt[] = "record byte count";
  110. static const char read_encdata[] = "encoded data";
  111. static const char n_name_unp_fmt[] = "%s(%s): cannot unparse name\n";
  112. static const char n_dec_cont_fmt[] = "%s(%s): cannot decode contents\n";
  113. static const char read_nint_data[] = "principal static attributes";
  114. static const char read_tcontents[] = "tagged data contents";
  115. static const char read_ttypelen[] = "tagged data type and length";
  116. static const char read_kcontents[] = "key data contents";
  117. static const char read_ktypelen[] = "key data type and length";
  118. static const char read_econtents[] = "extra data contents";
  119. static const char k5beta_fmt_name[] = "Kerberos version 5 old format";
  120. static const char standard_fmt_name[] = "Kerberos version 5 format";
  121. static const char no_name_mem_fmt[] = "%s: cannot get memory for temporary name\n";
  122. static const char ctx_err_fmt[] = "%s: cannot initialize Kerberos context\n";
  123. static const char stdin_name[] = "standard input";
  124. static const char restfail_fmt[] = "%s: %s restore failed\n";
  125. static const char close_err_fmt[] = "%s: cannot close database (%s)\n";
  126. static const char dbinit_err_fmt[] = "%s: cannot initialize database (%s)\n";
  127. static const char dblock_err_fmt[] = "%s: cannot initialize database lock (%s)\n";
  128. static const char dbname_err_fmt[] = "%s: cannot set database name to %s (%s)\n";
  129. static const char dbdelerr_fmt[] = "%s: cannot delete bad database %s (%s)\n";
  130. static const char dbunlockerr_fmt[] = "%s: cannot unlock database %s (%s)\n";
  131. static const char dbrenerr_fmt[] = "%s: cannot rename database %s to %s (%s)\n";
  132. static const char dbcreaterr_fmt[] = "%s: cannot create database %s (%s)\n";
  133. static const char dfile_err_fmt[] = "%s: cannot open %s (%s)\n";
  134. static const char oldoption[] = "-old";
  135. static const char b6option[] = "-b6";
  136. static const char verboseoption[] = "-verbose";
  137. static const char updateoption[] = "-update";
  138. static const char ovoption[] = "-ov";
  139. static const char dump_tmptrail[] = "~";
  140. #define ENCTYPE_NULL 0x0000
  141. #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */
  142. #define ENCTYPE_DES_CBC_MD4 0x0002 /* DES cbc mode with RSA-MD4 */
  143. #define ENCTYPE_DES_CBC_MD5 0x0003 /* DES cbc mode with RSA-MD5 */
  144. #define ENCTYPE_DES_CBC_RAW 0x0004 /* DES cbc mode raw */
  145. #define ENCTYPE_DES3_CBC_SHA 0x0005 /* DES-3 cbc mode with NIST-SHA */
  146. #define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */
  147. #define ENCTYPE_RC4_MD4 -128
  148. #define ENCTYPE_RC4_PLAIN2 -129
  149. #define ENCTYPE_RC4_LM -130
  150. #define ENCTYPE_RC4_SHA -131
  151. #define ENCTYPE_DES_PLAIN -132
  152. #define ENCTYPE_RC4_HMAC_OLD -133
  153. #define ENCTYPE_RC4_PLAIN_OLD -134
  154. #define ENCTYPE_RC4_HMAC_OLD_EXP -135
  155. #define ENCTYPE_RC4_PLAIN_OLD_EXP -136
  156. #define ENCTYPE_DES_CBC_MD5_EXP -137
  157. #define ENCTYPE_DES_PLAIN_EXP -138
  158. #define ENCTYPE_RC4_PLAIN -140
  159. #define ENCTYPE_RC4_PLAIN_EXP -141
  160. #define ENCTYPE_UNKNOWN 0x01ff
  161. /* Salt types */
  162. #define KRB5_KDB_SALTTYPE_NORMAL 0
  163. #define KRB5_KDB_SALTTYPE_V4 1
  164. #define KRB5_KDB_SALTTYPE_NOREALM 2
  165. #define KRB5_KDB_SALTTYPE_ONLYREALM 3
  166. #define KRB5_KDB_SALTTYPE_SPECIAL 4
  167. #define KRB5_KDB_SALTTYPE_AFS3 5
  168. /* Attributes */
  169. #define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
  170. #define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002
  171. #define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004
  172. #define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008
  173. #define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010
  174. #define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020
  175. #define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040
  176. #define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080
  177. #define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100
  178. #define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200
  179. #define KRB5_KDB_DISALLOW_SVR 0x00001000
  180. #define KRB5_KDB_PWCHANGE_SERVICE 0x00002000
  181. #define KRB5_KDB_SUPPORT_DESMD5 0x00004000
  182. #define KRB5_KDB_NEW_PRINC 0x00008000
  183. //
  184. // SALT flags for encryption, from rfc1510 update 3des enctype
  185. //
  186. #define KERB_ENC_TIMESTAMP_SALT 1
  187. #define KERB_TICKET_SALT 2
  188. #define KERB_AS_REP_SALT 3
  189. #define KERB_TGS_REQ_SESSKEY_SALT 4
  190. #define KERB_TGS_REQ_SUBKEY_SALT 5
  191. #define KERB_TGS_REQ_AP_REQ_AUTH_CKSUM_SALT 6
  192. #define KERB_TGS_REQ_AP_REQ_AUTH_SALT 7
  193. #define KERB_TGS_REP_SALT 8
  194. #define KERB_TGS_REP_SUBKEY_SALT 9
  195. #define KERB_AP_REQ_AUTH_CKSUM_SALT 10
  196. #define KERB_AP_REQ_AUTH_SALT 11
  197. #define KERB_AP_REP_SALT 12
  198. #define KERB_PRIV_SALT 13
  199. #define KERB_CRED_SALT 14
  200. #define KERB_SAFE_SALT 15
  201. #define KERB_NON_KERB_SALT 16
  202. #define KERB_NON_KERB_CKSUM_SALT 17
  203. #define KERB_KERB_ERROR_SALT 18
  204. #define KERB_KDC_ISSUED_CKSUM_SALT 19
  205. #define KERB_MANDATORY_TKT_EXT_CKSUM_SALT 20
  206. #define KERB_AUTH_DATA_TKT_EXT_CKSUM_SALT 21
  207. LPSTR
  208. get_error_text(DWORD dwError)
  209. {
  210. PCHAR pBuf = NULL;
  211. DWORD cMsgLen = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
  212. FORMAT_MESSAGE_ALLOCATE_BUFFER | 40,
  213. NULL,
  214. dwError,
  215. MAKELANGID(0, SUBLANG_ENGLISH_US),
  216. (LPSTR) &pBuf,
  217. 128,
  218. NULL);
  219. if (!cMsgLen) {
  220. pBuf = (LPSTR)malloc(30);
  221. sprintf(pBuf, "(%d)", dwError);
  222. }
  223. return(pBuf);
  224. }
  225. void
  226. print_salt_string(
  227. int stype,
  228. int len,
  229. char *str
  230. )
  231. {
  232. int i;
  233. switch (stype) {
  234. case KRB5_KDB_SALTTYPE_NORMAL:
  235. printf("Normal\n");
  236. break;
  237. case KRB5_KDB_SALTTYPE_V4:
  238. printf("V4\n");
  239. break;
  240. case KRB5_KDB_SALTTYPE_NOREALM:
  241. printf("No Realm : \"%*s\"\n", len, str);
  242. break;
  243. case KRB5_KDB_SALTTYPE_ONLYREALM:
  244. printf("Only Realm : \"%*s\"\n", len, str);
  245. break;
  246. case KRB5_KDB_SALTTYPE_AFS3:
  247. printf("AFS3 : \"%*s\"\n", len, str);
  248. break;
  249. case KRB5_KDB_SALTTYPE_SPECIAL:
  250. printf("Special [%d]:", len);
  251. goto dump;
  252. default:
  253. printf("salttype %d [%d]:", stype, len);
  254. dump:;
  255. for (i=0; i < len; i++)
  256. printf(" %02x", str[i]);
  257. printf("\n");
  258. break;
  259. }
  260. }
  261. char *
  262. etype_string(
  263. int enctype
  264. )
  265. {
  266. static char buf[32];
  267. switch (enctype) {
  268. case ENCTYPE_DES_CBC_CRC:
  269. return "DES-CBC-CRC";
  270. break;
  271. case ENCTYPE_DES_CBC_MD4:
  272. return "DES-CBC-MD4";
  273. break;
  274. case ENCTYPE_DES_CBC_MD5:
  275. return "DES-CBC-MD5";
  276. break;
  277. case ENCTYPE_DES3_CBC_SHA:
  278. return "DES3-CBC-SHA";
  279. break;
  280. case ENCTYPE_RC4_MD4:
  281. return "RC4-MD4";
  282. break;
  283. case ENCTYPE_RC4_PLAIN2:
  284. return "RC4-PLAIN2";
  285. break;
  286. case ENCTYPE_RC4_LM:
  287. return "RC4-LM";
  288. break;
  289. case ENCTYPE_RC4_SHA:
  290. return "RC4-SHA";
  291. break;
  292. case ENCTYPE_DES_PLAIN:
  293. return "DES-PLAIN";
  294. break;
  295. case ENCTYPE_RC4_HMAC_OLD:
  296. return "RC4-HMAC-OLD";
  297. break;
  298. case ENCTYPE_RC4_PLAIN_OLD:
  299. return "RC4-PLAIN-OLD";
  300. break;
  301. case ENCTYPE_RC4_HMAC_OLD_EXP:
  302. return "RC4-HMAC-OLD-EXP";
  303. break;
  304. case ENCTYPE_RC4_PLAIN_OLD_EXP:
  305. return "RC4-PLAIN-OLD-EXP";
  306. break;
  307. case ENCTYPE_DES_CBC_MD5_EXP:
  308. return "DES-CBC-MD5-40bit";
  309. break;
  310. case ENCTYPE_DES_PLAIN_EXP:
  311. return "DES-PLAIN-40bit";
  312. break;
  313. case ENCTYPE_RC4_PLAIN:
  314. return "RC4-PLAIN";
  315. break;
  316. case ENCTYPE_RC4_PLAIN_EXP:
  317. return "RC4-PLAIN-EXP";
  318. break;
  319. default:
  320. sprintf(buf, "etype %d", enctype);
  321. return buf;
  322. break;
  323. }
  324. }
  325. void
  326. print_tl_data(
  327. int n_data,
  328. krb5_tl_data *tl_data
  329. )
  330. {
  331. krb5_tl_data *tlp;
  332. int i;
  333. if (n_data) {
  334. printf("\ttl_data:\n");
  335. for (tlp = tl_data; tlp; tlp = tlp->tl_data_next) {
  336. printf("\t\ttype=%d len=%d ",
  337. tlp->tl_data_type, tlp->tl_data_length);
  338. for (i = 0; i < tlp->tl_data_length; i++)
  339. printf(" %02x", tlp->tl_data_contents[i]);
  340. printf("\n");
  341. }
  342. }
  343. }
  344. int
  345. decrypt_key(
  346. krb5_keyblock *key,
  347. void *indata,
  348. int inlen,
  349. void *outdata,
  350. int *outlen
  351. )
  352. {
  353. #define SEC_SUCCESS(Status) ((Status) >= 0)
  354. static const UCHAR iVec[8] = {0};
  355. static HANDLE lsaHandle = NULL;
  356. static ULONG packageId = 0;
  357. NTSTATUS Status, SubStatus;
  358. LSA_STRING Name;
  359. PKERB_DECRYPT_REQUEST DecryptRequest;
  360. ULONG OutLen, DecryptReqLength;
  361. PUCHAR OutBuf;
  362. int retval = 0;
  363. if (!lsaHandle) {
  364. Status = LsaConnectUntrusted(&lsaHandle);
  365. if (!SEC_SUCCESS(Status)) {
  366. fprintf(stderr, "Failed to create LsaHandle - 0x%x\n", Status);
  367. exit(3);
  368. }
  369. Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
  370. Name.Length = (USHORT)strlen(Name.Buffer);
  371. Name.MaximumLength = Name.Length + 1;
  372. Status = LsaLookupAuthenticationPackage(lsaHandle,
  373. &Name,
  374. &packageId);
  375. if (!SEC_SUCCESS(Status)) {
  376. LsaDeregisterLogonProcess(lsaHandle);
  377. fprintf(stderr, "Failed to register LsaHandle - 0x%x\n", Status);
  378. exit(3);
  379. }
  380. }
  381. DecryptReqLength =
  382. sizeof(KERB_DECRYPT_REQUEST) + key->length + 8 + inlen;
  383. DecryptRequest = (PKERB_DECRYPT_REQUEST)LocalAlloc(LMEM_ZEROINIT, DecryptReqLength);
  384. DecryptRequest->MessageType = KerbDecryptDataMessage;
  385. DecryptRequest->LogonId.LowPart = 0;
  386. DecryptRequest->LogonId.HighPart = 0;
  387. DecryptRequest->Flags = 0;
  388. DecryptRequest->KeyUsage = KERB_TICKET_SALT;
  389. DecryptRequest->CryptoType = key->enctype;
  390. DecryptRequest->Key.KeyType = key->enctype;
  391. DecryptRequest->Key.Length = key->length;
  392. DecryptRequest->Key.Value = (PUCHAR) (DecryptRequest + 1);
  393. memcpy(DecryptRequest->Key.Value, key->contents, key->length);
  394. DecryptRequest->InitialVectorSize = 8;
  395. DecryptRequest->InitialVector = (PUCHAR)
  396. ((PUCHAR)DecryptRequest->Key.Value + DecryptRequest->Key.Length);
  397. memcpy(DecryptRequest->InitialVector, iVec, 8);
  398. DecryptRequest->EncryptedDataSize = inlen;
  399. DecryptRequest->EncryptedData = (PUCHAR)
  400. ((PUCHAR)DecryptRequest->InitialVector + DecryptRequest->InitialVectorSize);
  401. memcpy(DecryptRequest->EncryptedData, indata, inlen);
  402. Status = LsaCallAuthenticationPackage(lsaHandle,
  403. packageId,
  404. DecryptRequest,
  405. DecryptReqLength,
  406. (PVOID *)&OutBuf,
  407. &OutLen,
  408. &SubStatus);
  409. if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) {
  410. fprintf(stderr, "Decrypt: LsaCallAuthPackage failed: %s\n",
  411. get_error_text(SubStatus));
  412. exit(4);
  413. }
  414. if ((long)OutLen > *outlen) {
  415. fprintf(stderr, "Decrypt: outbuf too small (%d < %d)\n",
  416. OutLen, *outlen);
  417. *outlen = OutLen;
  418. retval = -1;
  419. }
  420. else if (outdata) {
  421. *outlen = OutLen;
  422. memcpy(outdata, OutBuf, OutLen);
  423. }
  424. LsaFreeReturnBuffer(OutBuf);
  425. return(retval);
  426. }
  427. void
  428. print_key_data(
  429. int n_key_data,
  430. krb5_key_data *kd
  431. )
  432. {
  433. int n, i;
  434. krb5_keyblock key;
  435. krb5_octet *ptr;
  436. int tmplen;
  437. for (n = 0; n < n_key_data; n++) {
  438. ptr = kd[n].key_data_contents[0];
  439. key.enctype = kd[n].key_data_type[0];
  440. key.length = *(short *)ptr;
  441. ptr += 2;
  442. printf("\tkey[%d]: ver=%d kvno=%d\n",
  443. n, kd[n].key_data_ver,
  444. kd[n].key_data_kvno);
  445. printf("\t\tetype=%s [%d]: ",
  446. etype_string(key.enctype),
  447. key.enctype);
  448. printf(" keylength=%d ", key.length);
  449. printf("\n\t\tEncrypted key: ");
  450. for (i = 0; i < kd[n].key_data_length[0]; i++)
  451. printf(" %02x", kd[n].key_data_contents[0][i]);
  452. if (mkey.length) {
  453. // First get the length needed
  454. decrypt_key(&mkey, ptr, (kd[n].key_data_length[0] - 2),
  455. NULL, &tmplen);
  456. key.contents = (krb5_octet *)malloc(tmplen);
  457. assert(key.contents != 0);
  458. // Now decrypt it
  459. decrypt_key(&mkey, ptr, (kd[n].key_data_length[0] - 2),
  460. key.contents, &tmplen);
  461. printf("\n\t\tDecrypted key: ");
  462. for (i = 0; i < key.length; i++)
  463. printf(" %02x", key.contents[i]);
  464. }
  465. printf("\n\t\tsalt=");
  466. print_salt_string(kd[n].key_data_type[1], kd[n].key_data_length[1],
  467. (char *)kd[n].key_data_contents[1]);
  468. }
  469. }
  470. int
  471. ds_put_principal(
  472. IADs *ds,
  473. krb5_db_entry &dbentry
  474. )
  475. {
  476. // Check for accounts that we can't import
  477. if ((strncmp(dbentry.princ, "K/M", 3) == 0) ||
  478. (strncmp(dbentry.princ, "krbtgt/", 7) == 0) ||
  479. (strncmp(dbentry.princ, "kadmin/", 7) == 0)) {
  480. return -1;
  481. }
  482. char *cp;
  483. char *SAMName = StrDupA(dbentry.princ);
  484. // Zap the realm
  485. if (cp = strrchr(SAMName, '@'))
  486. *cp = '\0';
  487. // Check if this princ has an instance - likely SPN
  488. if (cp = strchr(SAMName, '/')) {
  489. // We don't do anything with SPN's right now
  490. return (-1);
  491. }
  492. printf(add_princ_fmt, SAMName);
  493. // Search for the entry in the domain
  494. // If this is to be an SPN; create the base account
  495. // (or use an existing one)
  496. // Now create the user
  497. return 0;
  498. }
  499. /*
  500. * Read a string of bytes while counting the number of lines passed.
  501. */
  502. static int
  503. read_string(
  504. FILE *f,
  505. char *buf,
  506. int len,
  507. int *lp
  508. )
  509. {
  510. int c;
  511. int i, retval;
  512. retval = 0;
  513. for (i=0; i<len; i++) {
  514. c = fgetc(f);
  515. if (c < 0) {
  516. retval = 1;
  517. break;
  518. }
  519. if (c == '\n')
  520. (*lp)++;
  521. buf[i] = (char) c;
  522. }
  523. buf[len] = '\0';
  524. return(retval);
  525. }
  526. /*
  527. * Read a string of two character representations of bytes.
  528. */
  529. static int
  530. read_octet_string(
  531. FILE *f,
  532. krb5_octet *buf,
  533. int len
  534. )
  535. {
  536. int c;
  537. int i, retval;
  538. retval = 0;
  539. for (i=0; i<len; i++) {
  540. if (fscanf(f, "%02x", &c) != 1) {
  541. retval = 1;
  542. break;
  543. }
  544. buf[i] = (krb5_octet) c;
  545. }
  546. return(retval);
  547. }
  548. /*
  549. * Find the end of an old format record.
  550. */
  551. static void
  552. find_record_end(
  553. FILE *f,
  554. const char *fn,
  555. int lineno
  556. )
  557. {
  558. int ch;
  559. if (((ch = fgetc(f)) != ';') || ((ch = fgetc(f)) != '\n')) {
  560. fprintf(stderr, trash_end_fmt, fn, lineno);
  561. while (ch != '\n') {
  562. putc(ch, stderr);
  563. ch = fgetc(f);
  564. }
  565. putc(ch, stderr);
  566. }
  567. }
  568. /*
  569. * process_k5beta6_record() - Handle a dump record in krb5b6 format.
  570. *
  571. * Returns -1 for end of file, 0 for success and 1 for failure.
  572. */
  573. static int
  574. process_k5beta6_record(
  575. const char *fname,
  576. IADs *ds,
  577. FILE *filep,
  578. int verbose,
  579. int *linenop
  580. )
  581. {
  582. int retval;
  583. krb5_db_entry dbentry;
  584. krb5_int32 t1, t2, t3, t4, t5, t6, t7, t8, t9;
  585. int nread;
  586. int error;
  587. int i, j;
  588. char *name;
  589. krb5_key_data *kp, *kdatap;
  590. krb5_tl_data **tlp, *tl;
  591. krb5_octet *op;
  592. krb5_error_code kret;
  593. const char *try2read;
  594. try2read = (char *) NULL;
  595. memset((char *) &dbentry, 0, sizeof(dbentry));
  596. (*linenop)++;
  597. retval = 1;
  598. name = (char *) NULL;
  599. kp = (krb5_key_data *) NULL;
  600. op = (krb5_octet *) NULL;
  601. error = 0;
  602. kret = 0;
  603. nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5);
  604. if (nread == 5) {
  605. /* Get memory for flattened principal name */
  606. if (!(name = (char *) malloc((size_t) t2 + 1)))
  607. error++;
  608. /* Get memory for and form tagged data linked list */
  609. tlp = &dbentry.tl_data;
  610. for (i=0; i<t3; i++) {
  611. if ((*tlp = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) {
  612. memset(*tlp, 0, sizeof(krb5_tl_data));
  613. tlp = &((*tlp)->tl_data_next);
  614. dbentry.n_tl_data++;
  615. }
  616. else {
  617. error++;
  618. break;
  619. }
  620. }
  621. /* Get memory for key list */
  622. if (t4 && !(kp = (krb5_key_data *) malloc((size_t)
  623. (t4*sizeof(krb5_key_data)))))
  624. error++;
  625. /* Get memory for extra data */
  626. if (t5 && !(op = (krb5_octet *) malloc((size_t) t5)))
  627. error++;
  628. if (!error) {
  629. dbentry.len = (krb5_int16)t1;
  630. dbentry.n_key_data = (krb5_int16)t4;
  631. dbentry.e_length = (krb5_int16)t5;
  632. if (kp) {
  633. memset(kp, 0, (size_t) (t4*sizeof(krb5_key_data)));
  634. dbentry.key_data = kp;
  635. kp = (krb5_key_data *) NULL;
  636. }
  637. if (op) {
  638. memset(op, 0, (size_t) t5);
  639. dbentry.e_data = op;
  640. op = (krb5_octet *) NULL;
  641. }
  642. /* Read in and parse the principal name */
  643. if (!read_string(filep, name, t2, linenop)) {
  644. dbentry.princ = StrDupA(name);
  645. /* Get the fixed principal attributes */
  646. nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
  647. &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9);
  648. if (nread == 8) {
  649. dbentry.attributes = (krb5_flags) t2;
  650. dbentry.max_life = (krb5_deltat) t3;
  651. dbentry.max_renewable_life = (krb5_deltat) t4;
  652. dbentry.expiration = (krb5_timestamp) t5;
  653. dbentry.pw_expiration = (krb5_timestamp) t6;
  654. dbentry.last_success = (krb5_timestamp) t7;
  655. dbentry.last_failed = (krb5_timestamp) t8;
  656. dbentry.fail_auth_count = (krb5_kvno) t9;
  657. } else {
  658. try2read = read_nint_data;
  659. error++;
  660. }
  661. /*
  662. * Get the tagged data.
  663. *
  664. * Really, this code ought to discard tl data types
  665. * that it knows are special to the current version
  666. * and were not supported in the previous version.
  667. * But it's a pain to implement that here, and doing
  668. * it at dump time has almost as good an effect, so
  669. * that's what I did. [krb5-admin/89/
  670. */
  671. if (!error && dbentry.n_tl_data) {
  672. for (tl = dbentry.tl_data; tl; tl = tl->tl_data_next) {
  673. nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
  674. if (nread == 2) {
  675. tl->tl_data_type = (krb5_int16) t1;
  676. tl->tl_data_length = (krb5_int16) t2;
  677. if (tl->tl_data_length) {
  678. if (!(tl->tl_data_contents =
  679. (krb5_octet *) malloc((size_t) t2+1)) ||
  680. read_octet_string(filep,
  681. tl->tl_data_contents,
  682. t2)) {
  683. try2read = read_tcontents;
  684. error++;
  685. break;
  686. }
  687. }
  688. else {
  689. /* Should be a null field */
  690. nread = fscanf(filep, "%d", &t9);
  691. if ((nread != 1) || (t9 != -1)) {
  692. error++;
  693. try2read = read_tcontents;
  694. break;
  695. }
  696. }
  697. }
  698. else {
  699. try2read = read_ttypelen;
  700. error++;
  701. break;
  702. }
  703. }
  704. }
  705. /* Get the key data */
  706. if (!error && dbentry.n_key_data) {
  707. for (i=0; !error && (i<dbentry.n_key_data); i++) {
  708. kdatap = &dbentry.key_data[i];
  709. nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
  710. if (nread == 2) {
  711. kdatap->key_data_ver = (krb5_int16) t1;
  712. kdatap->key_data_kvno = (krb5_int16) t2;
  713. for (j=0; j<t1; j++) {
  714. nread = fscanf(filep, "%d\t%d\t", &t3, &t4);
  715. if (nread == 2) {
  716. kdatap->key_data_type[j] = (krb5_int16)t3;
  717. kdatap->key_data_length[j] = (krb5_int16)t4;
  718. if (t4) {
  719. if (!(kdatap->key_data_contents[j] =
  720. (krb5_octet *)
  721. malloc((size_t) t4+1)) ||
  722. read_octet_string(filep,
  723. kdatap->key_data_contents[j],
  724. t4)) {
  725. try2read = read_kcontents;
  726. error++;
  727. break;
  728. }
  729. }
  730. else {
  731. /* Should be a null field */
  732. nread = fscanf(filep, "%d", &t9);
  733. if ((nread != 1) || (t9 != -1)) {
  734. error++;
  735. try2read = read_kcontents;
  736. break;
  737. }
  738. }
  739. }
  740. else {
  741. try2read = read_ktypelen;
  742. error++;
  743. break;
  744. }
  745. }
  746. }
  747. }
  748. }
  749. /* Get the extra data */
  750. if (!error && dbentry.e_length) {
  751. if (read_octet_string(filep,
  752. dbentry.e_data,
  753. (int) dbentry.e_length)) {
  754. try2read = read_econtents;
  755. error++;
  756. }
  757. }
  758. else {
  759. nread = fscanf(filep, "%d", &t9);
  760. if ((nread != 1) || (t9 != -1)) {
  761. error++;
  762. try2read = read_econtents;
  763. }
  764. }
  765. /* Finally, find the end of the record. */
  766. if (!error)
  767. find_record_end(filep, fname, *linenop);
  768. /*
  769. * We have either read in all the data or choked.
  770. */
  771. if (!error) {
  772. retval = 0;
  773. if (verbose == 2) {
  774. printf("%s\n", dbentry.princ);
  775. printf("\tattr=0x%x\n", dbentry.attributes);
  776. printf("\tmax_life=%d, max_renewable_life=%d\n",
  777. dbentry.max_life, dbentry.max_renewable_life);
  778. printf("\texpiration=%d, pw_exp=%d\n",
  779. dbentry.expiration, dbentry.pw_expiration);
  780. printf("\te_length=%d n_tl_data=%d, n_key_data=%d\n",
  781. dbentry.e_length, dbentry.n_tl_data,
  782. dbentry.n_key_data);
  783. print_tl_data(dbentry.n_tl_data, dbentry.tl_data);
  784. print_key_data(dbentry.n_key_data, dbentry.key_data);
  785. }
  786. if ((kret = ds_put_principal(ds,
  787. dbentry))) {
  788. fprintf(stderr, store_err_fmt,
  789. fname, *linenop,
  790. name, ""/*error_message(kret)*/);
  791. }
  792. else
  793. {
  794. retval = 0;
  795. }
  796. }
  797. else {
  798. fprintf(stderr, read_err_fmt, fname, *linenop, try2read);
  799. }
  800. }
  801. else {
  802. if (kret)
  803. fprintf(stderr, parse_err_fmt,
  804. fname, *linenop, name, ""/*error_message(kret)*/);
  805. else
  806. fprintf(stderr, no_mem_fmt, fname, *linenop);
  807. }
  808. }
  809. else {
  810. fprintf(stderr, rhead_err_fmt, fname, *linenop);
  811. }
  812. if (op)
  813. free(op);
  814. if (kp)
  815. free(kp);
  816. if (name)
  817. free(name);
  818. if (dbentry.princ)
  819. free(dbentry.princ);
  820. }
  821. else {
  822. if (nread == EOF)
  823. retval = -1;
  824. }
  825. return(retval);
  826. }
  827. int process_k5beta7_policy(
  828. const char *fname,
  829. IADs *ds,
  830. FILE *filep,
  831. int verbose,
  832. int *linenop,
  833. void *pol_db
  834. )
  835. {
  836. char namebuf[1024];
  837. int nread;
  838. struct krb5_policy {
  839. char *name;
  840. int pw_min_life;
  841. int pw_max_life;
  842. int pw_min_length;
  843. int pw_min_classes;
  844. int pw_history_num;
  845. int policy_refcnt;
  846. } rec;
  847. (*linenop)++;
  848. rec.name = namebuf;
  849. nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d", rec.name,
  850. &rec.pw_min_life, &rec.pw_max_life,
  851. &rec.pw_min_length, &rec.pw_min_classes,
  852. &rec.pw_history_num, &rec.policy_refcnt);
  853. if (nread == EOF)
  854. return -1;
  855. else if (nread != 7) {
  856. fprintf(stderr, "cannot parse policy on line %d (%d read)\n",
  857. *linenop, nread);
  858. return 1;
  859. }
  860. #if 0
  861. if (ret = osa_adb_create_policy(pol_db, &rec)) {
  862. if (ret == OSA_ADB_DUP &&
  863. (ret = osa_adb_put_policy(pol_db, &rec))) {
  864. fprintf(stderr, "cannot create policy on line %d: %s\n",
  865. *linenop, error_message(ret));
  866. return 1;
  867. }
  868. }
  869. #else
  870. fprintf(stderr, "Policy %s : min_life=%d max_life=%d min_len=%d min_classes=%d histnum=%d refcnt=%d\n",
  871. rec.name,
  872. rec.pw_min_life, rec.pw_max_life,
  873. rec.pw_min_length, rec.pw_min_classes,
  874. rec.pw_history_num, rec.policy_refcnt);
  875. #endif
  876. if (verbose)
  877. fprintf(stderr, "created policy %s - \n", rec.name);
  878. return 0;
  879. }
  880. /*
  881. * process_k5beta7_record() - Handle a dump record in krb5b6 format.
  882. *
  883. * Returns -1 for end of file, 0 for success and 1 for failure.
  884. */
  885. static int
  886. process_k5beta7_record(
  887. const char *fname,
  888. IADs *ds,
  889. FILE *filep,
  890. int verbose,
  891. int *linenop,
  892. void *pol_db
  893. )
  894. {
  895. int nread;
  896. char rectype[100];
  897. nread = fscanf(filep, "%100s\t", rectype);
  898. if (nread == EOF)
  899. return -1;
  900. else if (nread != 1)
  901. return 1;
  902. if (strcmp(rectype, "princ") == 0)
  903. process_k5beta6_record(fname, ds, filep, verbose,
  904. linenop);
  905. else if (strcmp(rectype, "policy") == 0)
  906. process_k5beta7_policy(fname, ds, filep, verbose,
  907. linenop, pol_db);
  908. else {
  909. fprintf(stderr, "unknown record type \"%s\" on line %d\n",
  910. rectype, *linenop);
  911. return 1;
  912. }
  913. return 0;
  914. }
  915. /*
  916. * restore_dump() - Restore the database from a standard dump file.
  917. */
  918. static int
  919. restore_dump(
  920. const char *programname,
  921. const char *dumpfile,
  922. IADs *ds,
  923. FILE *f,
  924. FILE *k,
  925. int verbose
  926. )
  927. {
  928. int error;
  929. int lineno;
  930. char buf[2*sizeof(k5_dump_header)];
  931. short enctype;
  932. int i;
  933. int pol_db;
  934. if (k) {
  935. /*
  936. * Read the master key file
  937. */
  938. if (fread(&enctype, 2, 1, k) != 1) {
  939. perror("Unable to read master key file");
  940. exit(2);
  941. }
  942. mkey.enctype = enctype;
  943. if (fread((krb5_pointer) &mkey.length,
  944. sizeof(mkey.length), 1, k) != 1) {
  945. perror("Cannot read master key length");
  946. exit(2);
  947. }
  948. if (!mkey.length || mkey.length < 0) {
  949. fprintf(stderr, "Bad stored master key.\n");
  950. exit(2);
  951. }
  952. if (!(mkey.contents = (krb5_octet *)malloc(mkey.length))) {
  953. fprintf(stderr, "Read mkey memory allocation failure.\n");
  954. exit(2);
  955. }
  956. if (fread(mkey.contents,
  957. sizeof(mkey.contents[0]), mkey.length, k) != mkey.length) {
  958. memset(mkey.contents, 0, mkey.length);
  959. perror("Cannot read master key");
  960. exit(2);
  961. }
  962. fclose(k);
  963. printf("Master key: etype=%s [%d]: ",
  964. etype_string(mkey.enctype), mkey.enctype);
  965. for (i = 0; i < mkey.length; i++)
  966. printf(" %02x", mkey.contents[i]);
  967. printf("\n");
  968. }
  969. /*
  970. * Get/check the header.
  971. */
  972. error = 0;
  973. if (fgets(buf, sizeof(buf), f) == NULL) {
  974. return(1);
  975. }
  976. if (!strcmp(buf, k5_dump_header)) {
  977. lineno = 1;
  978. /*
  979. * Process the records.
  980. */
  981. while (!(error = process_k5beta7_record(dumpfile,
  982. ds,
  983. f,
  984. verbose,
  985. &lineno, (void *)&pol_db)))
  986. ;
  987. if (error != -1)
  988. fprintf(stderr, err_line_fmt, programname, lineno, dumpfile);
  989. else
  990. error = 0;
  991. /*
  992. * Close the input file.
  993. */
  994. if (f != stdin)
  995. fclose(f);
  996. }
  997. else {
  998. printf("buf=\"%s\"\n", buf);
  999. fprintf(stderr, head_bad_fmt, programname, dumpfile);
  1000. error++;
  1001. }
  1002. return(error);
  1003. }
  1004. void __cdecl
  1005. main(int argc, char *argv[])
  1006. {
  1007. FILE *kdbFile, *mkeyFile = NULL;
  1008. int retval;
  1009. IADs *pDS;
  1010. int n = 1;
  1011. int verbose = 1;
  1012. HRESULT hr;
  1013. if (argc < 2 || argc > 5) {
  1014. printf("Usage: %s [-m <mkey>] <dumpfile>\n", argv[0]);
  1015. exit(1);
  1016. }
  1017. if (argc == 4) {
  1018. if (strcmp(argv[1], "-m") == 0) {
  1019. mkeyFile = fopen(argv[2], "rb");
  1020. if (!mkeyFile) {
  1021. perror("Unable to open master key file");
  1022. exit(1);
  1023. }
  1024. n = 3;
  1025. }
  1026. }
  1027. kdbFile = fopen(argv[n], "rb");
  1028. if (!kdbFile) {
  1029. perror("Unable to open dump file");
  1030. exit(1);
  1031. }
  1032. // need to open DS and pass that in
  1033. hr = CoInitialize(NULL);
  1034. if (FAILED(hr)) {
  1035. fprintf(stderr, "Unable to init com - %s\n", get_error_text(hr));
  1036. exit(2);
  1037. }
  1038. hr = ADsGetObject(TEXT("LDAP://rootDSE"), IID_IADs,
  1039. (void **)&pDS);
  1040. if (FAILED(hr)) {
  1041. fprintf(stderr, "Unable to bind to DS - %s\n", get_error_text(hr));
  1042. exit(2);
  1043. }
  1044. retval = restore_dump(argv[0], argv[1], pDS, kdbFile, mkeyFile, verbose);
  1045. fclose(kdbFile);
  1046. exit(retval);
  1047. }