📄 kerberos_keytab.c
字号:
char keytab_name[MAX_KEYTAB_NAME_LEN]; ZERO_STRUCT(kt_entry); ZERO_STRUCT(cursor); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("ads_keytab_flush: could not krb5_init_context: %s\n",error_message(ret))); return ret; }#ifdef HAVE_WRFILE_KEYTAB keytab_name[0] = 'W'; keytab_name[1] = 'R'; ret = krb5_kt_default_name(context, (char *) &keytab_name[2], MAX_KEYTAB_NAME_LEN - 4);#else ret = krb5_kt_default_name(context, (char *) &keytab_name[0], MAX_KEYTAB_NAME_LEN - 2);#endif if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret))); goto out; } DEBUG(3,("ads_keytab_flush: Using default keytab: %s\n", (char *) &keytab_name)); ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab); if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret))); goto out; } ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab); if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret))); goto out; } kvno = (krb5_kvno) ads_get_kvno(ads, global_myname()); if (kvno == -1) { /* -1 indicates a failure */ DEBUG(1,("ads_keytab_flush: Error determining the system's kvno.\n")); goto out; } ret = krb5_kt_start_seq_get(context, keytab, &cursor); if (ret != KRB5_KT_END && ret != ENOENT) { while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) { ret = krb5_kt_end_seq_get(context, keytab, &cursor); ZERO_STRUCT(cursor); if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_end_seq_get() failed (%s)\n",error_message(ret))); goto out; } ret = krb5_kt_remove_entry(context, keytab, &kt_entry); if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret))); goto out; } ret = krb5_kt_start_seq_get(context, keytab, &cursor); if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_start_seq failed (%s)\n",error_message(ret))); goto out; } ret = smb_krb5_kt_free_entry(context, &kt_entry); ZERO_STRUCT(kt_entry); if (ret) { DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret))); goto out; } } } /* Ensure we don't double free. */ ZERO_STRUCT(kt_entry); ZERO_STRUCT(cursor); if (!ADS_ERR_OK(ads_clear_service_principal_names(ads, global_myname()))) { DEBUG(1,("ads_keytab_flush: Error while clearing service principal listings in LDAP.\n")); goto out; }out: { krb5_keytab_entry zero_kt_entry; ZERO_STRUCT(zero_kt_entry); if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) { smb_krb5_kt_free_entry(context, &kt_entry); } } { krb5_kt_cursor zero_csr; ZERO_STRUCT(zero_csr); if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) { krb5_kt_end_seq_get(context, keytab, &cursor); } } if (keytab) { krb5_kt_close(context, keytab); } if (context) { krb5_free_context(context); } return ret;}/********************************************************************** Adds all the required service principals to the system keytab.***********************************************************************/int ads_keytab_create_default(ADS_STRUCT *ads){ krb5_error_code ret = 0; krb5_context context = NULL; krb5_keytab keytab = NULL; krb5_kt_cursor cursor; krb5_keytab_entry kt_entry; krb5_kvno kvno; fstring my_fqdn, my_Fqdn, my_name, my_NAME, my_host_realm; char *p_fqdn; int i, found = 0; char **oldEntries = NULL, *princ_s[26]; memset(princ_s, '\0', sizeof(princ_s)); ret = ads_keytab_add_entry(ads, "host"); if (ret) { DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'host'.\n")); return ret; } ret = ads_keytab_add_entry(ads, "cifs"); if (ret) { DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'cifs'.\n")); return ret; } fstrcpy(my_name, global_myname()); strlower_m(my_name); fstrcpy(my_NAME, global_myname()); strupper_m(my_NAME); my_fqdn[0] = '\0'; name_to_fqdn(my_fqdn, global_myname()); strlower_m(my_fqdn); p_fqdn = strchr_m(my_fqdn, '.'); fstrcpy(my_Fqdn, my_NAME); if (p_fqdn) { fstrcat(my_Fqdn, p_fqdn); } fstrcpy(my_host_realm, my_name); fstrcat(my_host_realm, "."); fstrcat(my_host_realm, lp_realm()); strlower_m(my_host_realm); asprintf(&princ_s[0], "%s$@%s", my_name, lp_realm()); asprintf(&princ_s[1], "%s$@%s", my_NAME, lp_realm()); asprintf(&princ_s[2], "host/%s@%s", my_name, lp_realm()); asprintf(&princ_s[3], "host/%s@%s", my_NAME, lp_realm()); asprintf(&princ_s[4], "host/%s@%s", my_fqdn, lp_realm()); asprintf(&princ_s[5], "host/%s@%s", my_Fqdn, lp_realm()); asprintf(&princ_s[6], "HOST/%s@%s", my_name, lp_realm()); asprintf(&princ_s[7], "HOST/%s@%s", my_NAME, lp_realm()); asprintf(&princ_s[8], "HOST/%s@%s", my_fqdn, lp_realm()); asprintf(&princ_s[9], "HOST/%s@%s", my_Fqdn, lp_realm()); asprintf(&princ_s[10], "cifs/%s@%s", my_name, lp_realm()); asprintf(&princ_s[11], "cifs/%s@%s", my_NAME, lp_realm()); asprintf(&princ_s[12], "cifs/%s@%s", my_fqdn, lp_realm()); asprintf(&princ_s[13], "cifs/%s@%s", my_Fqdn, lp_realm()); asprintf(&princ_s[14], "CIFS/%s@%s", my_name, lp_realm()); asprintf(&princ_s[15], "CIFS/%s@%s", my_NAME, lp_realm()); asprintf(&princ_s[16], "CIFS/%s@%s", my_fqdn, lp_realm()); asprintf(&princ_s[17], "CIFS/%s@%s", my_Fqdn, lp_realm()); asprintf(&princ_s[18], "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm()); asprintf(&princ_s[19], "CIFS/%s.%s@%s", my_name, lp_realm(), lp_realm()); asprintf(&princ_s[20], "host/%s.%s@%s", my_name, lp_realm(), lp_realm()); asprintf(&princ_s[21], "HOST/%s.%s@%s", my_name, lp_realm(), lp_realm()); /* when dnsdomain == realm, don't add duplicate principal */ if (!strequal(my_host_realm, my_fqdn)) { asprintf(&princ_s[22], "cifs/%s@%s", my_host_realm, lp_realm()); asprintf(&princ_s[23], "CIFS/%s@%s", my_host_realm, lp_realm()); asprintf(&princ_s[24], "host/%s@%s", my_host_realm, lp_realm()); asprintf(&princ_s[25], "HOST/%s@%s", my_host_realm, lp_realm()); } for (i = 0; i < sizeof(princ_s) / sizeof(princ_s[0]); i++) { if (princ_s[i] != NULL) { ret = ads_keytab_add_entry(ads, princ_s[i]); if (ret != 0) { DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding '%s'.\n", princ_s[i])); } SAFE_FREE(princ_s[i]); } } kvno = (krb5_kvno) ads_get_kvno(ads, global_myname()); if (kvno == -1) { DEBUG(1,("ads_keytab_create_default: ads_get_kvno failed to determine the system's kvno.\n")); return -1; } DEBUG(3,("ads_keytab_create_default: Searching for keytab entries to preserve and update.\n")); /* Now loop through the keytab and update any other existing entries... */ ZERO_STRUCT(kt_entry); ZERO_STRUCT(cursor); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret))); return ret; } ret = krb5_kt_default(context, &keytab); if (ret) { DEBUG(1,("ads_keytab_create_default: krb5_kt_default failed (%s)\n",error_message(ret))); goto done; } ret = krb5_kt_start_seq_get(context, keytab, &cursor); if (ret != KRB5_KT_END && ret != ENOENT ) { while ((ret = krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) == 0) { smb_krb5_kt_free_entry(context, &kt_entry); ZERO_STRUCT(kt_entry); found++; } } krb5_kt_end_seq_get(context, keytab, &cursor); ZERO_STRUCT(cursor); /* * Hmmm. There is no "rewind" function for the keytab. This means we have a race condition * where someone else could add entries after we've counted them. Re-open asap to minimise * the race. JRA. */ DEBUG(3, ("ads_keytab_create_default: Found %d entries in the keytab.\n", found)); if (!found) { goto done; } oldEntries = SMB_MALLOC_ARRAY(char *, found ); if (!oldEntries) { DEBUG(1,("ads_keytab_create_default: Failed to allocate space to store the old keytab entries (malloc failed?).\n")); ret = -1; goto done; } memset(oldEntries, '\0', found * sizeof(char *)); ret = krb5_kt_start_seq_get(context, keytab, &cursor); if (ret != KRB5_KT_END && ret != ENOENT ) { while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) { if (kt_entry.vno != kvno) { char *ktprinc = NULL; char *p; /* This returns a malloc'ed string in ktprinc. */ ret = krb5_unparse_name(context, kt_entry.principal, &ktprinc); if (ret) { DEBUG(1,("krb5_unparse_name failed (%s)\n", error_message(ret))); goto done; } /* * From looking at the krb5 source they don't seem to take locale * or mb strings into account. Maybe this is because they assume utf8 ? * In this case we may need to convert from utf8 to mb charset here ? JRA. */ p = strchr_m(ktprinc, '@'); if (p) { *p = '\0'; } p = strchr_m(ktprinc, '/'); if (p) { *p = '\0'; } for (i = 0; i < found; i++) { if (!oldEntries[i]) { oldEntries[i] = ktprinc; break; } if (!strcmp(oldEntries[i], ktprinc)) { krb5_free_unparsed_name(context, ktprinc); break; } } if (i == found) { krb5_free_unparsed_name(context, ktprinc); } } smb_krb5_kt_free_entry(context, &kt_entry); ZERO_STRUCT(kt_entry); } ret = 0; for (i = 0; oldEntries[i]; i++) { ret |= ads_keytab_add_entry(ads, oldEntries[i]); krb5_free_unparsed_name(context, oldEntries[i]); } krb5_kt_end_seq_get(context, keytab, &cursor); } ZERO_STRUCT(cursor);done: SAFE_FREE(oldEntries); { krb5_keytab_entry zero_kt_entry; ZERO_STRUCT(zero_kt_entry); if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) { smb_krb5_kt_free_entry(context, &kt_entry); } } { krb5_kt_cursor zero_csr; ZERO_STRUCT(zero_csr); if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) { krb5_kt_end_seq_get(context, keytab, &cursor); } } if (keytab) { krb5_kt_close(context, keytab); } if (context) { krb5_free_context(context); } return ret;}#endif /* HAVE_KRB5 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -