Blame library/adkrb5.c

Packit Service 6d40f9
/*
Packit Service 6d40f9
 * adcli
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * Copyright (C) 2012 Red Hat Inc.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * This program is free software; you can redistribute it and/or modify
Packit Service 6d40f9
 * it under the terms of the GNU Lesser General Public License as
Packit Service 6d40f9
 * published by the Free Software Foundation; either version 2.1 of
Packit Service 6d40f9
 * the License, or (at your option) any later version.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * This program is distributed in the hope that it will be useful, but
Packit Service 6d40f9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 6d40f9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 6d40f9
 * Lesser General Public License for more details.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * You should have received a copy of the GNU Lesser General Public
Packit Service 6d40f9
 * License along with this program; if not, write to the Free Software
Packit Service 6d40f9
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
Packit Service 6d40f9
 * MA 02110-1301 USA
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * Author: Stef Walter <stefw@gnome.org>
Packit Service 6d40f9
 */
Packit Service 6d40f9
Packit Service 6d40f9
#include "config.h"
Packit Service 6d40f9
Packit Service 6d40f9
#include "adcli.h"
Packit Service 6d40f9
#include "adprivate.h"
Packit Service 6d40f9
Packit Service 6d40f9
#include <gssapi/gssapi_krb5.h>
Packit Service 6d40f9
#include <krb5/krb5.h>
Packit Service 6d40f9
Packit Service 6d40f9
#include <assert.h>
Packit Service 6d40f9
#include <ctype.h>
Packit Service 6d40f9
#include <errno.h>
Packit Service 6d40f9
#include <stdio.h>
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_build_principal (krb5_context k5,
Packit Service 6d40f9
                             const char *user,
Packit Service 6d40f9
                             const char *realm,
Packit Service 6d40f9
                             krb5_principal *principal)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 2560e3
	char *name = NULL;
Packit Service 6d40f9
Packit Service 2560e3
	/* Use user if user contains a @-character and add @realm otherwise */
Packit Service 2560e3
	if (strchr (user, '@') == NULL) {
Packit Service 2560e3
		if (asprintf (&name, "%s@%s", user, realm) < 0) {
Packit Service 2560e3
			return_val_if_reached (ENOMEM);
Packit Service 2560e3
		}
Packit Service 2560e3
	}
Packit Service 6d40f9
Packit Service 2560e3
	code = krb5_parse_name (k5, name != NULL ? name : user, principal);
Packit Service 6d40f9
	return_val_if_fail (code == 0, code);
Packit Service 6d40f9
Packit Service 6d40f9
	free (name);
Packit Service 6d40f9
	return 0;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_keytab_clear (krb5_context k5,
Packit Service 6d40f9
                          krb5_keytab keytab,
Packit Service 6d40f9
                          krb5_boolean (* match_func) (krb5_context,
Packit Service 6d40f9
                                                       krb5_keytab_entry *,
Packit Service 6d40f9
                                                       void *),
Packit Service 6d40f9
                          void *match_data)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_kt_cursor cursor;
Packit Service 6d40f9
	krb5_keytab_entry entry;
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
Packit Service 6d40f9
	code = krb5_kt_start_seq_get (k5, keytab, &cursor);
Packit Service 6d40f9
	if (code == KRB5_KT_END || code == ENOENT)
Packit Service 6d40f9
		return 0;
Packit Service 6d40f9
	else if (code != 0)
Packit Service 6d40f9
		return code;
Packit Service 6d40f9
Packit Service 6d40f9
	for (;;) {
Packit Service 6d40f9
		code = krb5_kt_next_entry (k5, keytab, &entry, &cursor);
Packit Service 6d40f9
		if (code != 0)
Packit Service 6d40f9
			break;
Packit Service 6d40f9
Packit Service 6d40f9
		/* See if we should remove this entry */
Packit Service 6d40f9
		if (!match_func (k5, &entry, match_data)) {
Packit Service 6d40f9
			krb5_free_keytab_entry_contents (k5, &entry);
Packit Service 6d40f9
			continue;
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		/*
Packit Service 6d40f9
		 * Here we close the cursor, remove the entry and then
Packit Service 6d40f9
		 * start all over again from the beginning. Dumb but works.
Packit Service 6d40f9
		 */
Packit Service 6d40f9
Packit Service 6d40f9
		code = krb5_kt_end_seq_get (k5, keytab, &cursor);
Packit Service 6d40f9
		return_val_if_fail (code == 0, code);
Packit Service 6d40f9
Packit Service 6d40f9
		code = krb5_kt_remove_entry (k5, keytab, &entry);
Packit Service 6d40f9
		krb5_free_keytab_entry_contents (k5, &entry);
Packit Service 6d40f9
Packit Service 6d40f9
		if (code != 0)
Packit Service 6d40f9
			return code;
Packit Service 6d40f9
Packit Service 6d40f9
		code = krb5_kt_start_seq_get (k5, keytab, &cursor);
Packit Service 6d40f9
		return_val_if_fail (code == 0, code);
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (code == KRB5_KT_END)
Packit Service 6d40f9
		code = 0;
Packit Service 6d40f9
Packit Service 6d40f9
	krb5_kt_end_seq_get (k5, keytab, &cursor);
Packit Service 6d40f9
	return code;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static krb5_boolean
Packit Service 6d40f9
match_all_entries (krb5_context k5,
Packit Service 6d40f9
                   krb5_keytab_entry *entry,
Packit Service 6d40f9
                   void *data)
Packit Service 6d40f9
{
Packit Service 6d40f9
	return TRUE;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_keytab_clear_all (krb5_context k5,
Packit Service 6d40f9
                              krb5_keytab keytab)
Packit Service 6d40f9
{
Packit Service 6d40f9
	return _adcli_krb5_keytab_clear (k5, keytab,
Packit Service 6d40f9
	                                 match_all_entries,
Packit Service 6d40f9
	                                 NULL);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_keytab_enumerate (krb5_context k5,
Packit Service 6d40f9
		              krb5_keytab keytab,
Packit Service 6d40f9
                              krb5_boolean (* match_func) (krb5_context,
Packit Service 6d40f9
                                                           krb5_keytab_entry *,
Packit Service 6d40f9
                                                           void *),
Packit Service 6d40f9
                              void *match_data)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_kt_cursor cursor;
Packit Service 6d40f9
	krb5_keytab_entry entry;
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
Packit Service 6d40f9
	code = krb5_kt_start_seq_get (k5, keytab, &cursor);
Packit Service 6d40f9
	if (code == KRB5_KT_END || code == ENOENT)
Packit Service 6d40f9
		return 0;
Packit Service 6d40f9
	else if (code != 0)
Packit Service 6d40f9
		return code;
Packit Service 6d40f9
Packit Service 6d40f9
	for (;;) {
Packit Service 6d40f9
		code = krb5_kt_next_entry (k5, keytab, &entry, &cursor);
Packit Service 6d40f9
		if (code != 0)
Packit Service 6d40f9
			break;
Packit Service 6d40f9
Packit Service 6d40f9
		/* See if we should continue */
Packit Service 6d40f9
		if (!match_func (k5, &entry, match_data))
Packit Service 6d40f9
			break;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (code == KRB5_KT_END)
Packit Service 6d40f9
		code = 0;
Packit Service 6d40f9
Packit Service 6d40f9
	krb5_kt_end_seq_get (k5, keytab, &cursor);
Packit Service 6d40f9
	return code;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
adcli_result
Packit Service 6d40f9
_adcli_krb5_init_context (krb5_context *k5)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
Packit Service 6d40f9
	code = krb5_init_context (k5);
Packit Service 6d40f9
	if (code == ENOMEM) {
Packit Service 6d40f9
		return_unexpected_if_reached ();
Packit Service 6d40f9
Packit Service 6d40f9
	} else if (code != 0) {
Packit Service 6d40f9
		_adcli_err ("Failed to create kerberos context: %s",
Packit Service 6d40f9
		            krb5_get_error_message (NULL, code));
Packit Service 6d40f9
		return ADCLI_ERR_UNEXPECTED;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	return ADCLI_SUCCESS;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
adcli_result
Packit Service 6d40f9
_adcli_krb5_open_keytab (krb5_context k5,
Packit Service 6d40f9
                         const char *keytab_name,
Packit Service 6d40f9
		         krb5_keytab *keytab)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
Packit Service 6d40f9
	if (keytab_name && strcmp (keytab_name, "") != 0) {
Packit Service 6d40f9
		code = krb5_kt_resolve (k5, keytab_name, keytab);
Packit Service 6d40f9
		if (code != 0) {
Packit Service 6d40f9
			_adcli_err ("Failed to open keytab: %s: %s",
Packit Service 6d40f9
			            keytab_name, krb5_get_error_message (k5, code));
Packit Service 6d40f9
			return ADCLI_ERR_FAIL;
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
	} else {
Packit Service 6d40f9
		code = krb5_kt_default (k5, keytab);
Packit Service 6d40f9
		if (code != 0) {
Packit Service 6d40f9
			_adcli_err ("Failed to open default keytab: %s",
Packit Service 6d40f9
			            krb5_get_error_message (k5, code));
Packit Service 6d40f9
			return ADCLI_ERR_FAIL;
Packit Service 6d40f9
		}
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	return ADCLI_SUCCESS;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 005b26
typedef struct {
Packit Service 005b26
	krb5_kvno kvno;
Packit Service 005b26
	krb5_enctype enctype;
Packit Service 005b26
	int matched;
Packit Service 005b26
} match_enctype_kvno;
Packit Service 005b26
Packit Service 005b26
static krb5_boolean
Packit Service 005b26
match_enctype_and_kvno (krb5_context k5,
Packit Service 005b26
                        krb5_keytab_entry *entry,
Packit Service 005b26
                        void *data)
Packit Service 005b26
{
Packit Service 005b26
	krb5_boolean similar = FALSE;
Packit Service 005b26
	match_enctype_kvno *closure = data;
Packit Service 005b26
	krb5_error_code code;
Packit Service 005b26
Packit Service 005b26
	assert (closure->enctype);
Packit Service 005b26
Packit Service 005b26
	code = krb5_c_enctype_compare (k5, closure->enctype, entry->key.enctype,
Packit Service 005b26
	                               &similar);
Packit Service 005b26
Packit Service 005b26
	if (code == 0 && entry->vno == closure->kvno && similar) {
Packit Service 005b26
		closure->matched = 1;
Packit Service 005b26
		return 1;
Packit Service 005b26
	}
Packit Service 005b26
Packit Service 005b26
	return 0;
Packit Service 005b26
}
Packit Service 005b26
Packit Service 005b26
static krb5_error_code
Packit Service 005b26
_adcli_krb5_get_keyblock (krb5_context k5,
Packit Service 005b26
                          krb5_keytab keytab,
Packit Service 005b26
                          krb5_keyblock *keyblock,
Packit Service 005b26
                          krb5_boolean (* match_func) (krb5_context,
Packit Service 005b26
                                                       krb5_keytab_entry *,
Packit Service 005b26
                                                       void *),
Packit Service 005b26
                          void *match_data)
Packit Service 005b26
{
Packit Service 005b26
	krb5_kt_cursor cursor;
Packit Service 005b26
	krb5_keytab_entry entry;
Packit Service 005b26
	krb5_error_code code;
Packit Service 005b26
Packit Service 005b26
	code = krb5_kt_start_seq_get (k5, keytab, &cursor);
Packit Service 005b26
	if (code == KRB5_KT_END || code == ENOENT)
Packit Service 005b26
		return 0;
Packit Service 005b26
	else if (code != 0)
Packit Service 005b26
		return code;
Packit Service 005b26
Packit Service 005b26
	for (;;) {
Packit Service 005b26
		code = krb5_kt_next_entry (k5, keytab, &entry, &cursor);
Packit Service 005b26
		if (code != 0)
Packit Service 005b26
			break;
Packit Service 005b26
Packit Service 005b26
		/* See if we should remove this entry */
Packit Service 005b26
		if (!match_func (k5, &entry, match_data)) {
Packit Service 005b26
			krb5_free_keytab_entry_contents (k5, &entry);
Packit Service 005b26
			continue;
Packit Service 005b26
		}
Packit Service 005b26
Packit Service 005b26
		code = krb5_copy_keyblock_contents (k5, &entry.key, keyblock);
Packit Service 005b26
		krb5_free_keytab_entry_contents (k5, &entry);
Packit Service 005b26
		break;
Packit Service 005b26
Packit Service 005b26
Packit Service 005b26
	}
Packit Service 005b26
Packit Service 005b26
	if (code == KRB5_KT_END)
Packit Service 005b26
		code = 0;
Packit Service 005b26
Packit Service 005b26
	krb5_kt_end_seq_get (k5, keytab, &cursor);
Packit Service 005b26
	return code;
Packit Service 005b26
}
Packit Service 005b26
Packit Service 005b26
krb5_error_code
Packit Service 005b26
_adcli_krb5_keytab_copy_entries (krb5_context k5,
Packit Service 005b26
                                 krb5_keytab keytab,
Packit Service 005b26
                                 krb5_principal principal,
Packit Service 005b26
                                 krb5_kvno kvno,
Packit Service 005b26
                                 krb5_enctype *enctypes)
Packit Service 005b26
{
Packit Service 005b26
	krb5_keytab_entry entry;
Packit Service 005b26
	krb5_error_code code;
Packit Service 005b26
	int i;
Packit Service 005b26
	match_enctype_kvno closure;
Packit Service 005b26
Packit Service 005b26
	for (i = 0; enctypes[i] != 0; i++) {
Packit Service 005b26
Packit Service 005b26
		closure.kvno = kvno;
Packit Service 005b26
		closure.enctype = enctypes[i];
Packit Service 005b26
		closure.matched = 0;
Packit Service 005b26
Packit Service 005b26
		memset (&entry, 0, sizeof (entry));
Packit Service 005b26
Packit Service 005b26
		code = _adcli_krb5_get_keyblock (k5, keytab, &entry.key,
Packit Service 005b26
		                                 match_enctype_and_kvno, &closure);
Packit Service c4915f
		if (code != 0 || closure.matched == 0) {
Packit Service c4915f
			return code != 0 ? code : ENOKEY;
Packit Service 005b26
		}
Packit Service 005b26
Packit Service 005b26
		entry.principal = principal;
Packit Service 005b26
		entry.vno = kvno;
Packit Service 005b26
Packit Service 005b26
		code = krb5_kt_add_entry (k5, keytab, &entry);
Packit Service 005b26
Packit Service 005b26
		entry.principal = NULL;
Packit Service 005b26
		krb5_free_keytab_entry_contents (k5, &entry);
Packit Service 005b26
Packit Service 005b26
		if (code != 0)
Packit Service 005b26
			return code;
Packit Service 005b26
	}
Packit Service 005b26
Packit Service 005b26
	return 0;
Packit Service 005b26
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_keytab_add_entries (krb5_context k5,
Packit Service 6d40f9
                                krb5_keytab keytab,
Packit Service 6d40f9
                                krb5_principal principal,
Packit Service 6d40f9
                                krb5_kvno kvno,
Packit Service 6d40f9
                                krb5_data *password,
Packit Service 6d40f9
                                krb5_enctype *enctypes,
Packit Service 6d40f9
                                krb5_data *salt)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_keytab_entry entry;
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	for (i = 0; enctypes[i] != 0; i++) {
Packit Service 6d40f9
		memset (&entry, 0, sizeof(entry));
Packit Service 6d40f9
Packit Service 6d40f9
		code = krb5_c_string_to_key (k5, enctypes[i], password, salt, &entry.key);
Packit Service 6d40f9
		if (code != 0)
Packit Service 6d40f9
			return code;
Packit Service 6d40f9
Packit Service 6d40f9
		entry.principal = principal;
Packit Service 6d40f9
		entry.vno = kvno;
Packit Service 6d40f9
Packit Service 6d40f9
		code = krb5_kt_add_entry (k5, keytab, &entry);
Packit Service 6d40f9
Packit Service 6d40f9
		entry.principal = NULL;
Packit Service 6d40f9
		krb5_free_keytab_entry_contents (k5, &entry);
Packit Service 6d40f9
Packit Service 6d40f9
		if (code != 0)
Packit Service 6d40f9
			return code;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	return 0;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_keytab_test_salt (krb5_context k5,
Packit Service 6d40f9
                              krb5_keytab scratch,
Packit Service 6d40f9
                              krb5_principal principal,
Packit Service 6d40f9
                              krb5_kvno kvno,
Packit Service 6d40f9
                              krb5_data *password,
Packit Service 6d40f9
                              krb5_enctype *enctypes,
Packit Service 6d40f9
                              krb5_data *salt)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
	krb5_creds creds;
Packit Service 6d40f9
Packit Service 6d40f9
	code = _adcli_krb5_keytab_clear_all (k5, scratch);
Packit Service 6d40f9
	return_val_if_fail (code == 0, code);
Packit Service 6d40f9
Packit Service 6d40f9
	code = _adcli_krb5_keytab_add_entries (k5, scratch, principal, kvno,
Packit Service 6d40f9
	                                       password, enctypes, salt);
Packit Service 6d40f9
	return_val_if_fail (code == 0, code);
Packit Service 6d40f9
Packit Service 6d40f9
	memset(&creds, 0, sizeof (creds));
Packit Service 6d40f9
	code = krb5_get_init_creds_keytab (k5, &creds, principal, scratch, 0, NULL, NULL);
Packit Service 6d40f9
Packit Service 6d40f9
	krb5_free_cred_contents (k5, &creds);
Packit Service 6d40f9
Packit Service 6d40f9
	return code;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_keytab_discover_salt (krb5_context k5,
Packit Service 6d40f9
                                  krb5_principal principal,
Packit Service 6d40f9
                                  krb5_kvno kvno,
Packit Service 6d40f9
                                  krb5_data *password,
Packit Service 6d40f9
                                  krb5_enctype *enctypes,
Packit Service 6d40f9
                                  krb5_data *salts,
Packit Service 6d40f9
                                  int *discovered)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_keytab scratch;
Packit Service 6d40f9
	krb5_error_code code;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	/* TODO: This should be a unique name */
Packit Service 6d40f9
Packit Service 6d40f9
	code = krb5_kt_resolve (k5, "MEMORY:adcli-discover-salt", &scratch);
Packit Service 6d40f9
	return_val_if_fail (code == 0, code);
Packit Service 6d40f9
Packit Service 6d40f9
	for (i = 0; salts[i].data != NULL; i++) {
Packit Service 6d40f9
		code = _adcli_krb5_keytab_test_salt (k5, scratch, principal, kvno,
Packit Service bc2650
		                                     password, enctypes, &salts[i]);
Packit Service 6d40f9
		if (code == 0) {
Packit Service 6d40f9
			*discovered = i;
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		} else if (code != KRB5_PREAUTH_FAILED && code != KRB5KDC_ERR_PREAUTH_FAILED) {
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		}
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	krb5_kt_close (k5, scratch);
Packit Service 6d40f9
	return code;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
krb5_error_code
Packit Service 6d40f9
_adcli_krb5_w2k3_salt (krb5_context k5,
Packit Service 6d40f9
                       krb5_principal principal,
Packit Service 6d40f9
                       const char *host_netbios,
Packit Service 6d40f9
                       krb5_data *salt)
Packit Service 6d40f9
{
Packit Service 6d40f9
	krb5_data *realm;
Packit Service 6d40f9
	size_t size = 0;
Packit Service 6d40f9
	size_t host_length = 0;
Packit Service 6d40f9
	size_t at = 0;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	/*
Packit Service 6d40f9
	 * The format for the w2k3 computer account salt is:
Packit Service 6d40f9
	 * REALM | "host" | SAM-Account-Name-Without-$ | "." | realm
Packit Service 6d40f9
	 */
Packit Service 6d40f9
Packit Service 6d40f9
	realm = krb5_princ_realm (k5, principal);
Packit Service 6d40f9
	host_length = strlen (host_netbios);
Packit Service 6d40f9
Packit Service 6d40f9
	size += realm->length;
Packit Service 6d40f9
	size += 4; /* "host" */
Packit Service 6d40f9
	size += host_length;
Packit Service 6d40f9
	size += 1; /* "." */
Packit Service 6d40f9
	size += realm->length;
Packit Service 6d40f9
Packit Service 6d40f9
	salt->data = malloc (size);
Packit Service 6d40f9
	return_val_if_fail (salt->data != NULL, ENOMEM);
Packit Service 6d40f9
Packit Service 6d40f9
	/* Upper case realm */
Packit Service 6d40f9
	for (i = 0; i < realm->length; i++)
Packit Service 6d40f9
		salt->data[at + i] = toupper (realm->data[i]);
Packit Service 6d40f9
	at += realm->length;
Packit Service 6d40f9
Packit Service 6d40f9
	/* The string "host" */
Packit Service 6d40f9
	memcpy (salt->data + at, "host", 4);
Packit Service 6d40f9
	at += 4;
Packit Service 6d40f9
Packit Service 6d40f9
	/* The netbios name in lower case */
Packit Service 6d40f9
	for (i = 0; i < host_length; i++)
Packit Service 6d40f9
		salt->data[at + i] = tolower (host_netbios[i]);
Packit Service 6d40f9
	at += host_length;
Packit Service 6d40f9
Packit Service 6d40f9
	/* The dot */
Packit Service 6d40f9
	memcpy (salt->data + at, ".", 1);
Packit Service 6d40f9
	at += 1;
Packit Service 6d40f9
Packit Service 6d40f9
	/* Lower case realm */
Packit Service 6d40f9
	for (i = 0; i < realm->length; i++)
Packit Service 6d40f9
		salt->data[at + i] = tolower (realm->data[i]);
Packit Service 6d40f9
	at += realm->length;
Packit Service 6d40f9
Packit Service 6d40f9
	assert (at == size);
Packit Service 6d40f9
	salt->length = size;
Packit Service 6d40f9
	return 0;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
/* for msDs-supportedEncryptionTypes  bit defines */
Packit Service 6d40f9
#define MS_KERB_ENCTYPE_DES_CBC_CRC             0x01
Packit Service 6d40f9
#define MS_KERB_ENCTYPE_DES_CBC_MD5             0x02
Packit Service 6d40f9
#define MS_KERB_ENCTYPE_RC4_HMAC_MD5            0x04
Packit Service 6d40f9
#define MS_KERB_ENCTYPE_AES128_CTC_HMAC_SHA1_96 0x08
Packit Service 6d40f9
#define MS_KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x10
Packit Service 6d40f9
Packit Service 6d40f9
krb5_enctype *
Packit Service 6d40f9
_adcli_krb5_parse_enctypes (const char *value)
Packit Service 6d40f9
{
Packit Service 6d40f9
	const int max_enctypes = 5;
Packit Service 6d40f9
	char *end = NULL;
Packit Service 6d40f9
	krb5_enctype *enctypes;
Packit Service 6d40f9
	int types;
Packit Service 6d40f9
	int at;
Packit Service 6d40f9
Packit Service 6d40f9
	types = strtoul (value, &end, 10);
Packit Service 6d40f9
	if (end == NULL || *end != '\0')
Packit Service 6d40f9
		return NULL;
Packit Service 6d40f9
Packit Service 6d40f9
	enctypes = calloc (max_enctypes + 1, sizeof (krb5_enctype));
Packit Service 6d40f9
	return_val_if_fail (enctypes != NULL, NULL);
Packit Service 6d40f9
Packit Service 6d40f9
	at = 0;
Packit Service 6d40f9
	if (types & MS_KERB_ENCTYPE_DES_CBC_CRC)
Packit Service 6d40f9
		enctypes[at++] = ENCTYPE_DES_CBC_CRC;
Packit Service 6d40f9
	if (types & MS_KERB_ENCTYPE_DES_CBC_MD5)
Packit Service 6d40f9
		enctypes[at++] = ENCTYPE_DES_CBC_MD5;
Packit Service 6d40f9
	if (types & MS_KERB_ENCTYPE_RC4_HMAC_MD5)
Packit Service 6d40f9
		enctypes[at++] = ENCTYPE_ARCFOUR_HMAC;
Packit Service 6d40f9
	if (types & MS_KERB_ENCTYPE_AES128_CTC_HMAC_SHA1_96)
Packit Service 6d40f9
		enctypes[at++] = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
Packit Service 6d40f9
	if (types & MS_KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96)
Packit Service 6d40f9
		enctypes[at++] = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
Packit Service 6d40f9
Packit Service 6d40f9
	assert (at <= max_enctypes);
Packit Service 6d40f9
	enctypes[at] = 0;
Packit Service 6d40f9
	return enctypes;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
char *
Packit Service 6d40f9
_adcli_krb5_format_enctypes (krb5_enctype *enctypes)
Packit Service 6d40f9
{
Packit Service 6d40f9
	char *value;
Packit Service 6d40f9
	int types;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	types = 0;
Packit Service 6d40f9
	for (i = 0; enctypes[i] != 0; i++) {
Packit Service 6d40f9
		switch (enctypes[i]) {
Packit Service 6d40f9
		case ENCTYPE_DES_CBC_CRC:
Packit Service 6d40f9
			types |= MS_KERB_ENCTYPE_DES_CBC_CRC;
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		case ENCTYPE_DES_CBC_MD5:
Packit Service 6d40f9
			types |= MS_KERB_ENCTYPE_DES_CBC_MD5;
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		case ENCTYPE_ARCFOUR_HMAC:
Packit Service 6d40f9
			types |= MS_KERB_ENCTYPE_RC4_HMAC_MD5;
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
Packit Service 6d40f9
			types |= MS_KERB_ENCTYPE_AES128_CTC_HMAC_SHA1_96;
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
Packit Service 6d40f9
			types |= MS_KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96;
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		default:
Packit Service 6d40f9
			break;
Packit Service 6d40f9
		}
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (types == 0)
Packit Service 6d40f9
		return NULL;
Packit Service 6d40f9
Packit Service 6d40f9
	if (asprintf (&value, "%d", types) < 0)
Packit Service 6d40f9
		return_val_if_reached (NULL);
Packit Service 6d40f9
Packit Service 6d40f9
	return value;
Packit Service 6d40f9
}