/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* tests/s4u2proxy.c - S4U2Proxy test harness */2/*3* Copyright (C) 2015 by the Massachusetts Institute of Technology.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9*10* * Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in15* the documentation and/or other materials provided with the16* distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS21* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE22* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,23* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES24* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR25* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,27* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED29* OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132/*33* Usage: s4u2proxy evccname targetname [ad-type ad-contents]34*35* evccname contains an evidence ticket. The default ccache contains a TGT for36* the intermediate service. The default keytab contains a key for the37* intermediate service. An S4U2Proxy request is made to get a ticket from38* evccname's default principal to the target service. The resulting cred is39* stored in the default ccache.40*/4142#include <k5-int.h>4344static krb5_context ctx;4546static void47check(krb5_error_code code)48{49const char *errmsg;5051if (code) {52errmsg = krb5_get_error_message(ctx, code);53fprintf(stderr, "%s\n", errmsg);54krb5_free_error_message(ctx, errmsg);55exit(1);56}57}5859static krb5_authdata **60make_request_authdata(int type, const char *contents)61{62krb5_authdata *ad;63krb5_authdata **req_authdata;6465ad = malloc(sizeof(*ad));66assert(ad != NULL);67ad->magic = KV5M_AUTHDATA;68ad->ad_type = type;69ad->length = strlen(contents);70ad->contents = (unsigned char *)strdup(contents);71assert(ad->contents != NULL);7273req_authdata = malloc(2 * sizeof(*req_authdata));74assert(req_authdata != NULL);75req_authdata[0] = ad;76req_authdata[1] = NULL;7778return req_authdata;79}8081int82main(int argc, char **argv)83{84krb5_context context;85krb5_ccache defcc, evcc;86krb5_principal client_name, int_name, target_name;87krb5_keytab defkt;88krb5_creds mcred, ev_cred, *new_cred;89krb5_ticket *ev_ticket;90krb5_authdata **req_authdata = NULL;9192if (argc == 5) {93req_authdata = make_request_authdata(atoi(argv[3]), argv[4]);94argc -= 2;95}9697assert(argc == 3);98check(krb5_init_context(&context));99100/* Open the default ccache, evidence ticket ccache, and default keytab. */101check(krb5_cc_default(context, &defcc));102check(krb5_cc_resolve(context, argv[1], &evcc));103check(krb5_kt_default(context, &defkt));104105/* Determine the client name, intermediate name, and target name. */106check(krb5_cc_get_principal(context, evcc, &client_name));107check(krb5_cc_get_principal(context, defcc, &int_name));108check(krb5_parse_name(context, argv[2], &target_name));109110/* Retrieve and decrypt the evidence ticket. */111memset(&mcred, 0, sizeof(mcred));112mcred.client = client_name;113mcred.server = int_name;114check(krb5_cc_retrieve_cred(context, evcc, 0, &mcred, &ev_cred));115check(krb5_decode_ticket(&ev_cred.ticket, &ev_ticket));116check(krb5_server_decrypt_ticket_keytab(context, defkt, ev_ticket));117118/* Make an S4U2Proxy request for the target service. */119mcred.client = client_name;120mcred.server = target_name;121mcred.authdata = req_authdata;122check(krb5_get_credentials_for_proxy(context, KRB5_GC_NO_STORE |123KRB5_GC_CANONICALIZE, defcc,124&mcred, ev_ticket, &new_cred));125126assert(data_eq(new_cred->second_ticket, ev_cred.ticket));127assert(new_cred->second_ticket.length != 0);128129/* Store the new cred in the default ccache. */130check(krb5_cc_store_cred(context, defcc, new_cred));131132assert(req_authdata == NULL || new_cred->authdata != NULL);133134krb5_cc_close(context, defcc);135krb5_cc_close(context, evcc);136krb5_kt_close(context, defkt);137krb5_free_principal(context, client_name);138krb5_free_principal(context, int_name);139krb5_free_principal(context, target_name);140krb5_free_cred_contents(context, &ev_cred);141krb5_free_ticket(context, ev_ticket);142krb5_free_creds(context, new_cred);143krb5_free_authdata(context, req_authdata);144krb5_free_context(context);145return 0;146}147148149