Path: blob/main/crypto/heimdal/kuser/kimpersonate.c
34860 views
/*1* Copyright (c) 2000 - 2007 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "kuser_locl.h"34#include <parse_units.h>3536static char *client_principal_str = NULL;37static krb5_principal client_principal;38static char *server_principal_str = NULL;39static krb5_principal server_principal;4041static char *ccache_str = NULL;4243static char *ticket_flags_str = NULL;44static TicketFlags ticket_flags;45static char *keytab_file = NULL;46static char *enctype_string = NULL;47static int expiration_time = 3600;48static struct getarg_strings client_addresses;49static int version_flag = 0;50static int help_flag = 0;51static int use_krb5 = 1;5253static const char *enc_type = "des-cbc-md5";5455/*56*57*/5859static void60encode_ticket (krb5_context context,61EncryptionKey *skey,62krb5_enctype etype,63int skvno,64krb5_creds *cred)65{66size_t len, size;67char *buf;68krb5_error_code ret;69krb5_crypto crypto;70EncryptedData enc_part;71EncTicketPart et;72Ticket ticket;7374memset (&enc_part, 0, sizeof(enc_part));75memset (&ticket, 0, sizeof(ticket));7677/*78* Set up `enc_part'79*/8081et.flags = cred->flags.b;82et.key = cred->session;83et.crealm = cred->client->realm;84copy_PrincipalName(&cred->client->name, &et.cname);85{86krb5_data empty_string;8788krb5_data_zero(&empty_string);89et.transited.tr_type = DOMAIN_X500_COMPRESS;90et.transited.contents = empty_string;91}92et.authtime = cred->times.authtime;93et.starttime = NULL;94et.endtime = cred->times.endtime;95et.renew_till = NULL;96et.caddr = &cred->addresses;97et.authorization_data = NULL; /* XXX allow random authorization_data */9899/*100* Encrypt `enc_part' of ticket with service key101*/102103ASN1_MALLOC_ENCODE(EncTicketPart, buf, len, &et, &size, ret);104if (ret)105krb5_err(context, 1, ret, "EncTicketPart");106107ret = krb5_crypto_init(context, skey, etype, &crypto);108if (ret)109krb5_err(context, 1, ret, "krb5_crypto_init");110ret = krb5_encrypt_EncryptedData (context,111crypto,112KRB5_KU_TICKET,113buf,114len,115skvno,116&ticket.enc_part);117if (ret)118krb5_err(context, 1, ret, "krb5_encrypt_EncryptedData");119120free(buf);121krb5_crypto_destroy(context, crypto);122123/*124* Encode ticket125*/126127ticket.tkt_vno = 5;128ticket.realm = cred->server->realm;129copy_PrincipalName(&cred->server->name, &ticket.sname);130131ASN1_MALLOC_ENCODE(Ticket, buf, len, &ticket, &size, ret);132if(ret)133krb5_err (context, 1, ret, "encode_Ticket");134135krb5_data_copy(&cred->ticket, buf, len);136free(buf);137}138139/*140*141*/142143static int144create_krb5_tickets (krb5_context context, krb5_keytab kt)145{146krb5_error_code ret;147krb5_keytab_entry entry;148krb5_creds cred;149krb5_enctype etype;150krb5_ccache ccache;151152memset (&cred, 0, sizeof(cred));153154ret = krb5_string_to_enctype (context, enc_type, &etype);155if (ret)156krb5_err (context, 1, ret, "krb5_string_to_enctype");157ret = krb5_kt_get_entry (context, kt, server_principal,1580, etype, &entry);159if (ret)160krb5_err (context, 1, ret, "krb5_kt_get_entry");161162/*163* setup cred164*/165166167ret = krb5_copy_principal (context, client_principal, &cred.client);168if (ret)169krb5_err (context, 1, ret, "krb5_copy_principal");170ret = krb5_copy_principal (context, server_principal, &cred.server);171if (ret)172krb5_err (context, 1, ret, "krb5_copy_principal");173krb5_generate_random_keyblock(context, etype, &cred.session);174175cred.times.authtime = time(NULL);176cred.times.starttime = time(NULL);177cred.times.endtime = time(NULL) + expiration_time;178cred.times.renew_till = 0;179krb5_data_zero(&cred.second_ticket);180181ret = krb5_get_all_client_addrs (context, &cred.addresses);182if (ret)183krb5_err (context, 1, ret, "krb5_get_all_client_addrs");184cred.flags.b = ticket_flags;185186187/*188* Encode encrypted part of ticket189*/190191encode_ticket (context, &entry.keyblock, etype, entry.vno, &cred);192193/*194* Write to cc195*/196197if (ccache_str) {198ret = krb5_cc_resolve(context, ccache_str, &ccache);199if (ret)200krb5_err (context, 1, ret, "krb5_cc_resolve");201} else {202ret = krb5_cc_default (context, &ccache);203if (ret)204krb5_err (context, 1, ret, "krb5_cc_default");205}206207ret = krb5_cc_initialize (context, ccache, cred.client);208if (ret)209krb5_err (context, 1, ret, "krb5_cc_initialize");210211ret = krb5_cc_store_cred (context, ccache, &cred);212if (ret)213krb5_err (context, 1, ret, "krb5_cc_store_cred");214215krb5_free_cred_contents (context, &cred);216krb5_cc_close (context, ccache);217218return 0;219}220221/*222*223*/224225static void226setup_env (krb5_context context, krb5_keytab *kt)227{228krb5_error_code ret;229230if (keytab_file)231ret = krb5_kt_resolve (context, keytab_file, kt);232else233ret = krb5_kt_default (context, kt);234if (ret)235krb5_err (context, 1, ret, "resolving keytab");236237if (client_principal_str == NULL)238krb5_errx (context, 1, "missing client principal");239ret = krb5_parse_name (context, client_principal_str, &client_principal);240if (ret)241krb5_err (context, 1, ret, "resolvning client name");242243if (server_principal_str == NULL)244krb5_errx (context, 1, "missing server principal");245ret = krb5_parse_name (context, server_principal_str, &server_principal);246if (ret)247krb5_err (context, 1, ret, "resolvning client name");248249if (ticket_flags_str) {250int ticket_flags_int;251252ticket_flags_int = parse_flags(ticket_flags_str,253asn1_TicketFlags_units(), 0);254if (ticket_flags_int <= 0) {255krb5_warnx (context, "bad ticket flags: `%s'", ticket_flags_str);256print_flags_table (asn1_TicketFlags_units(), stderr);257exit (1);258}259if (ticket_flags_int)260ticket_flags = int2TicketFlags (ticket_flags_int);261}262}263264/*265*266*/267268struct getargs args[] = {269{ "ccache", 0, arg_string, &ccache_str,270"name of kerberos 5 credential cache", "cache-name"},271{ "server", 's', arg_string, &server_principal_str,272"name of server principal", NULL },273{ "client", 'c', arg_string, &client_principal_str,274"name of client principal", NULL },275{ "keytab", 'k', arg_string, &keytab_file,276"name of keytab file", NULL },277{ "krb5", '5', arg_flag, &use_krb5,278"create a kerberos 5 ticket", NULL },279{ "expire-time", 'e', arg_integer, &expiration_time,280"lifetime of ticket in seconds", NULL },281{ "client-addresses", 'a', arg_strings, &client_addresses,282"addresses of client", NULL },283{ "enc-type", 't', arg_string, &enctype_string,284"encryption type", NULL },285{ "ticket-flags", 'f', arg_string, &ticket_flags_str,286"ticket flags for krb5 ticket", NULL },287{ "version", 0, arg_flag, &version_flag, "Print version",288NULL },289{ "help", 0, arg_flag, &help_flag, NULL,290NULL }291};292293static void294usage (int ret)295{296arg_printusage (args,297sizeof(args) / sizeof(args[0]),298NULL,299"");300exit (ret);301}302303int304main (int argc, char **argv)305{306int optidx = 0;307krb5_error_code ret;308krb5_context context;309krb5_keytab kt;310311setprogname (argv[0]);312313ret = krb5_init_context (&context);314if (ret)315errx(1, "krb5_init_context failed: %u", ret);316317if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))318usage(1);319320if (help_flag)321usage(0);322323if (version_flag) {324print_version(NULL);325return 0;326}327328if (enctype_string)329enc_type = enctype_string;330331setup_env(context, &kt);332333if (use_krb5)334create_krb5_tickets(context, kt);335336krb5_kt_close(context, kt);337338return 0;339}340341342