Blame library/adkrb5.c

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