This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
+#include "smb_krb5.h"
#ifdef HAVE_KRB5
/**********************************************************************
**********************************************************************/
-static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
- krb5_kvno kvno, const char *princ_s,
- krb5_enctype *enctypes, krb5_data password )
+int smb_krb5_kt_add_entry_ext(krb5_context context,
+ krb5_keytab keytab,
+ krb5_kvno kvno,
+ const char *princ_s,
+ krb5_enctype *enctypes,
+ krb5_data password,
+ bool no_salt,
+ bool keep_old_entries)
{
krb5_error_code ret = 0;
krb5_kt_cursor cursor;
ret = smb_krb5_parse_name(context, princ_s, &princ);
if (ret) {
- DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
goto out;
}
/* Seek and delete old keytab entries */
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
if (ret != KRB5_KT_END && ret != ENOENT ) {
- DEBUG(3,("smb_krb5_kt_add_entry: Will try to delete old keytab entries\n"));
+ DEBUG(3,("smb_krb5_kt_add_entry_ext: Will try to delete old keytab entries\n"));
while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
- BOOL compare_name_ok = False;
+ bool compare_name_ok = False;
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+ ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &ktprinc);
if (ret) {
- DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_unparse_name failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_unparse_name failed (%s)\n",
error_message(ret)));
goto out;
}
#endif
if (!compare_name_ok) {
- DEBUG(10,("smb_krb5_kt_add_entry: ignoring keytab entry principal %s, kvno = %d\n",
+ DEBUG(10,("smb_krb5_kt_add_entry_ext: ignoring keytab entry principal %s, kvno = %d\n",
ktprinc, kt_entry.vno));
}
- SAFE_FREE(ktprinc);
+ TALLOC_FREE(ktprinc);
if (compare_name_ok) {
if (kt_entry.vno == kvno - 1) {
- DEBUG(5,("smb_krb5_kt_add_entry: Saving previous (kvno %d) entry for principal: %s.\n",
+ DEBUG(5,("smb_krb5_kt_add_entry_ext: Saving previous (kvno %d) entry for principal: %s.\n",
kvno - 1, princ_s));
- } else {
-
- DEBUG(5,("smb_krb5_kt_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
+ } else if (!keep_old_entries) {
+ DEBUG(5,("smb_krb5_kt_add_entry_ext: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
princ_s, kt_entry.vno));
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
ZERO_STRUCT(cursor);
if (ret) {
- DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: 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,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_remove_entry failed (%s)\n",
error_message(ret)));
goto out;
}
- DEBUG(5,("smb_krb5_kt_add_entry: removed old entry for principal: %s (kvno %d).\n",
+ DEBUG(5,("smb_krb5_kt_add_entry_ext: removed old entry for principal: %s (kvno %d).\n",
princ_s, kt_entry.vno));
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
if (ret) {
- DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_start_seq failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: 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,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_remove_entry 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,("smb_krb5_kt_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
goto out;
}
}
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
ZERO_STRUCT(cursor);
if (ret) {
- DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
goto out;
}
}
for (i = 0; enctypes[i]; i++) {
krb5_keyblock *keyp;
-#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
-#error krb5_keytab_entry has no key or keyblock member
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
- keyp = &kt_entry.key;
-#endif
-#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
- keyp = &kt_entry.keyblock;
-#endif
- if (create_kerberos_key_from_string(context, princ, &password, keyp, enctypes[i])) {
+ keyp = KRB5_KT_KEY(&kt_entry);
+
+ if (create_kerberos_key_from_string(context, princ, &password, keyp, enctypes[i], no_salt)) {
continue;
}
kt_entry.principal = princ;
kt_entry.vno = kvno;
- DEBUG(3,("smb_krb5_kt_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
+ DEBUG(3,("smb_krb5_kt_add_entry_ext: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
princ_s, enctypes[i], kt_entry.vno));
ret = krb5_kt_add_entry(context, keytab, &kt_entry);
krb5_free_keyblock_contents(context, keyp);
ZERO_STRUCT(kt_entry);
if (ret) {
- DEBUG(1,("smb_krb5_kt_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry_ext: adding entry to keytab failed (%s)\n", error_message(ret)));
goto out;
}
}
return (int)ret;
}
+static int smb_krb5_kt_add_entry(krb5_context context,
+ krb5_keytab keytab,
+ krb5_kvno kvno,
+ const char *princ_s,
+ krb5_enctype *enctypes,
+ krb5_data password)
+{
+ return smb_krb5_kt_add_entry_ext(context,
+ keytab,
+ kvno,
+ princ_s,
+ enctypes,
+ password,
+ false,
+ false);
+}
/**********************************************************************
Adds a single service principal, i.e. 'host' to the system keytab
ret = -1;
goto out;
}
+ ZERO_STRUCT(password);
password.data = password_s;
password.length = strlen(password_s);
if (strchr_m(srvPrinc, '@')) {
/* It's a fully-named principal. */
- asprintf(&princ_s, "%s", srvPrinc);
+ if (asprintf(&princ_s, "%s", srvPrinc) == -1) {
+ ret = -1;
+ goto out;
+ }
} else if (srvPrinc[strlen(srvPrinc)-1] == '$') {
/* It's the machine account, as used by smbclient clients. */
- asprintf(&princ_s, "%s@%s", srvPrinc, lp_realm());
+ if (asprintf(&princ_s, "%s@%s", srvPrinc, lp_realm()) == -1) {
+ ret = -1;
+ goto out;
+ }
} else {
/* It's a normal service principal. Add the SPN now so that we
* can obtain credentials for it and double-check the salt value
* used to generate the service's keys. */
- asprintf(&princ_s, "%s/%s@%s", srvPrinc, my_fqdn, lp_realm());
- asprintf(&short_princ_s, "%s/%s@%s", srvPrinc, machine_name, lp_realm());
+ if (asprintf(&princ_s, "%s/%s@%s", srvPrinc, my_fqdn, lp_realm()) == -1) {
+ ret = -1;
+ goto out;
+ }
+ if (asprintf(&short_princ_s, "%s/%s@%s", srvPrinc, machine_name, lp_realm()) == -1) {
+ ret = -1;
+ goto out;
+ }
/* According to http://support.microsoft.com/kb/326985/en-us,
certain principal names are automatically mapped to the host/...
}
}
- kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
+ kvno = (krb5_kvno) ads_get_machine_kvno(ads, global_myname());
if (kvno == -1) { /* -1 indicates failure, everything else is OK */
- DEBUG(1,("ads_keytab_add_entry: ads_get_kvno failed to determine the system's kvno.\n"));
+ DEBUG(1,("ads_keytab_add_entry: ads_get_machine_kvno failed to determine the system's kvno.\n"));
ret = -1;
goto out;
}
goto out;
}
- kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
+ kvno = (krb5_kvno) ads_get_machine_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;
}
}
- TALLOC_FREE( ctx );
-
/* Now loop through the keytab and update any other existing entries... */
- kvno = (krb5_kvno) ads_get_kvno(ads, machine_name);
+ kvno = (krb5_kvno) ads_get_machine_kvno(ads, machine_name);
if (kvno == -1) {
- DEBUG(1,("ads_keytab_create_default: ads_get_kvno failed to determine the system's kvno.\n"));
+ DEBUG(1,("ads_keytab_create_default: ads_get_machine_kvno failed to determine the system's kvno.\n"));
+ TALLOC_FREE(ctx);
return -1;
}
ret = krb5_init_context(&context);
if (ret) {
DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret)));
+ TALLOC_FREE(ctx);
return ret;
}
- ret = krb5_kt_default(context, &keytab);
+
+ ret = smb_krb5_open_keytab(context, NULL, True, &keytab);
if (ret) {
- DEBUG(1,("ads_keytab_create_default: krb5_kt_default failed (%s)\n",error_message(ret)));
+ DEBUG(1,("ads_keytab_create_default: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
goto done;
}
if (!found) {
goto done;
}
- oldEntries = SMB_MALLOC_ARRAY(char *, found );
+ oldEntries = talloc_array(ctx, 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;
char *p;
/* This returns a malloc'ed string in ktprinc. */
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+ ret = smb_krb5_unparse_name(oldEntries, context, kt_entry.principal, &ktprinc);
if (ret) {
DEBUG(1,("smb_krb5_unparse_name failed (%s)\n", error_message(ret)));
goto done;
break;
}
if (!strcmp(oldEntries[i], ktprinc)) {
- SAFE_FREE(ktprinc);
+ TALLOC_FREE(ktprinc);
break;
}
}
if (i == found) {
- SAFE_FREE(ktprinc);
+ TALLOC_FREE(ktprinc);
}
}
smb_krb5_kt_free_entry(context, &kt_entry);
ret = 0;
for (i = 0; oldEntries[i]; i++) {
ret |= ads_keytab_add_entry(ads, oldEntries[i]);
- SAFE_FREE(oldEntries[i]);
+ TALLOC_FREE(oldEntries[i]);
}
krb5_kt_end_seq_get(context, keytab, &cursor);
}
done:
- SAFE_FREE(oldEntries);
+ TALLOC_FREE(oldEntries);
+ TALLOC_FREE(ctx);
{
krb5_keytab_entry zero_kt_entry;
char *etype_s = NULL;
krb5_enctype enctype = 0;
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &princ_s);
+ ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &princ_s);
if (ret) {
goto out;
}
ret = smb_krb5_enctype_to_string(context, enctype, &etype_s);
if (ret) {
- SAFE_FREE(princ_s);
- goto out;
+ if (asprintf(&etype_s, "UNKNOWN: %d\n", enctype) == -1)
+ {
+ TALLOC_FREE(princ_s);
+ goto out;
+ }
}
printf("%3d %s\t\t %s\n", kt_entry.vno, etype_s, princ_s);
- SAFE_FREE(princ_s);
+ TALLOC_FREE(princ_s);
SAFE_FREE(etype_s);
ret = smb_krb5_kt_free_entry(context, &kt_entry);