192 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 1997-2021 Kungliga Tekniska Högskolan
 | 
						|
 * (Royal Institute of Technology, Stockholm, Sweden).
 | 
						|
 * Copyright (c) 2021 Isaac Boukris
 | 
						|
 * All rights reserved.
 | 
						|
 *
 | 
						|
 * Redistribution and use in source and binary forms, with or without
 | 
						|
 * modification, are permitted provided that the following conditions
 | 
						|
 * are met:
 | 
						|
 *
 | 
						|
 * 1. Redistributions of source code must retain the above copyright
 | 
						|
 *    notice, this list of conditions and the following disclaimer.
 | 
						|
 *
 | 
						|
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
						|
 *    notice, this list of conditions and the following disclaimer in the
 | 
						|
 *    documentation and/or other materials provided with the distribution.
 | 
						|
 *
 | 
						|
 * 3. Neither the name of the Institute nor the names of its contributors
 | 
						|
 *    may be used to endorse or promote products derived from this software
 | 
						|
 *    without specific prior written permission.
 | 
						|
 *
 | 
						|
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 | 
						|
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
						|
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
						|
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 | 
						|
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
						|
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
						|
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
						|
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
						|
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
						|
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
						|
 * SUCH DAMAGE.
 | 
						|
 */
 | 
						|
 | 
						|
#include "krb5_locl.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * Usage: mkforwardable server out_ccache
 | 
						|
 *
 | 
						|
 * The default cache contains a ticket to server and the default keytab
 | 
						|
 * contains a key to decrypt it, the ticket is decrypted and the forwardable
 | 
						|
 * flag is added, the ticket is then re-encrypted and stored in out_cache.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
static krb5_context context;
 | 
						|
 | 
						|
static void
 | 
						|
check(krb5_error_code code)
 | 
						|
{
 | 
						|
    const char *errmsg;
 | 
						|
 | 
						|
    if (code == 0)
 | 
						|
	return;
 | 
						|
 | 
						|
    errmsg = krb5_get_error_message(context, code);
 | 
						|
    fprintf(stderr, "%s\n", errmsg);
 | 
						|
    krb5_free_error_message(context, errmsg);
 | 
						|
 | 
						|
    abort();
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
decrypt_ticket_enc_part(EncryptionKey *key,
 | 
						|
			krb5_enctype etype,
 | 
						|
			Ticket *ticket,
 | 
						|
			EncTicketPart *et)
 | 
						|
{
 | 
						|
    krb5_error_code ret;
 | 
						|
    krb5_data plain;
 | 
						|
    size_t len;
 | 
						|
    krb5_crypto crypto;
 | 
						|
 | 
						|
    check(krb5_crypto_init(context, key, etype, &crypto));
 | 
						|
 | 
						|
    ret = krb5_decrypt_EncryptedData (context,
 | 
						|
				      crypto,
 | 
						|
				      KRB5_KU_TICKET,
 | 
						|
				      &ticket->enc_part,
 | 
						|
				      &plain);
 | 
						|
    check(ret);
 | 
						|
 | 
						|
    check(decode_EncTicketPart(plain.data, plain.length, et, &len));
 | 
						|
 | 
						|
    krb5_data_free (&plain);
 | 
						|
    krb5_crypto_destroy(context, crypto);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
encrypt_ticket_enc_part(EncryptionKey *key,
 | 
						|
			krb5_enctype etype,
 | 
						|
			krb5_kvno skvno,
 | 
						|
			EncTicketPart *et,
 | 
						|
			Ticket *ticket)
 | 
						|
{
 | 
						|
    size_t len, size;
 | 
						|
    char *buf;
 | 
						|
    krb5_error_code ret;
 | 
						|
    krb5_crypto crypto;
 | 
						|
 | 
						|
    ASN1_MALLOC_ENCODE(EncTicketPart, buf, len, et, &size, ret);
 | 
						|
    check(ret);
 | 
						|
 | 
						|
    check(krb5_crypto_init(context, key, etype, &crypto));
 | 
						|
    ret = krb5_encrypt_EncryptedData(context,
 | 
						|
				      crypto,
 | 
						|
				      KRB5_KU_TICKET,
 | 
						|
				      buf,
 | 
						|
				      len,
 | 
						|
				      skvno,
 | 
						|
				      &ticket->enc_part);
 | 
						|
    check(ret);
 | 
						|
 | 
						|
    free(buf);
 | 
						|
    krb5_crypto_destroy(context, crypto);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
main(int argc, char **argv)
 | 
						|
{
 | 
						|
    krb5_error_code ret;
 | 
						|
    krb5_keytab kt;
 | 
						|
    krb5_keytab_entry entry;
 | 
						|
    krb5_enctype etype;
 | 
						|
    krb5_creds mc, cred;
 | 
						|
    krb5_ccache ccache;
 | 
						|
    EncTicketPart et;
 | 
						|
    Ticket ticket;
 | 
						|
    size_t size;
 | 
						|
    krb5_kvno kvno = 0;
 | 
						|
 | 
						|
    memset(&cred, 0, sizeof(cred));
 | 
						|
 | 
						|
    if (argc != 3)
 | 
						|
	errx(1, "Usage: mkforwardable server out_ccache");
 | 
						|
 | 
						|
    ret = krb5_init_context(&context);
 | 
						|
    if (ret)
 | 
						|
	errx(1, "krb5_init_context failed: %u", ret);
 | 
						|
 | 
						|
    check(krb5_cc_default(context, &ccache));
 | 
						|
 | 
						|
    krb5_cc_clear_mcred(&mc);
 | 
						|
 | 
						|
    check(krb5_parse_name(context, argv[1], &mc.server));
 | 
						|
 | 
						|
    check(krb5_cc_retrieve_cred(context, ccache, 0, &mc, &cred));
 | 
						|
 | 
						|
    check(decode_Ticket(cred.ticket.data, cred.ticket.length, &ticket, NULL));
 | 
						|
 | 
						|
    etype = ticket.enc_part.etype;
 | 
						|
 | 
						|
    if (ticket.enc_part.kvno != NULL)
 | 
						|
	kvno = *ticket.enc_part.kvno;
 | 
						|
 | 
						|
    check(krb5_kt_default(context, &kt));
 | 
						|
 | 
						|
    check(krb5_kt_get_entry(context, kt, mc.server, kvno, etype, &entry));
 | 
						|
 | 
						|
    decrypt_ticket_enc_part(&entry.keyblock, etype, &ticket, &et);
 | 
						|
 | 
						|
    et.flags.forwardable = 1;
 | 
						|
    cred.flags.b = et.flags;
 | 
						|
 | 
						|
    free_EncryptedData(&ticket.enc_part);
 | 
						|
 | 
						|
    encrypt_ticket_enc_part(&entry.keyblock, etype, kvno, &et, &ticket);
 | 
						|
 | 
						|
    krb5_data_free(&cred.ticket);
 | 
						|
    ASN1_MALLOC_ENCODE(Ticket, cred.ticket.data, cred.ticket.length, &ticket,
 | 
						|
		       &size, ret);
 | 
						|
    check(ret);
 | 
						|
 | 
						|
    krb5_cc_close(context, ccache);
 | 
						|
 | 
						|
    check(krb5_cc_resolve(context, argv[2], &ccache));
 | 
						|
    check(krb5_cc_initialize(context, ccache, cred.client));
 | 
						|
 | 
						|
    check(krb5_cc_store_cred(context, ccache, &cred));
 | 
						|
 | 
						|
    free_Ticket(&ticket);
 | 
						|
    free_EncTicketPart(&et);
 | 
						|
    krb5_cc_close(context, ccache);
 | 
						|
    krb5_free_principal(context, mc.server);
 | 
						|
    krb5_free_cred_contents(context, &cred);
 | 
						|
    krb5_kt_free_entry(context, &entry);
 | 
						|
    krb5_kt_close(context, kt);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 |