summaryrefslogblamecommitdiff
path: root/src/clients/kcpytkt/kcpytkt.c
blob: 0b8802261e9e8f30f61df3bf806c482c56a97606 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                               
                     
 

           
 

                                                                        


            


                                                                       
 

                            

               
                                                 


                                 
                                               





















                                                             
                          





                                                                             


                                                                               


                         
                       
                                       

                                   
                            






                                                              
                           










                                                                         
                              




























                                                                   
                         

                                                                        
             


















                                                                     
                                                    




                                                                  
                                                      


                                                                  

                                                         

















                                                     
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <krb5.h>
#include "k5-platform.h"

static char *prog;
static int quiet = 0;

static void
xusage()
{
    fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] "
            "dest_ccache service1 service2 ...\n", prog);
    exit(1);
}

static void
do_kcpytkt(int argc, char *argv[], char *fromccachestr, char *etypestr,
           int flags);

int
main(int argc, char *argv[])
{
    int option;
    char *etypestr = NULL, *fromccachestr = NULL;
    int flags = 0;

    prog = strrchr(argv[0], '/');
    prog = (prog != NULL) ? prog + 1 : argv[0];

    while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) {
        switch (option) {
        case 'c':
            fromccachestr = optarg;
            break;
        case 'e':
            etypestr = optarg;
            break;
        case 'f':
            flags = atoi(optarg);
            break;
        case 'q':
            quiet = 1;
            break;
        case 'h':
        default:
            xusage();
            break;
        }
    }

    if (argc - optind < 2)
        xusage();

    do_kcpytkt(argc - optind, argv + optind, fromccachestr, etypestr, flags);
    return 0;
}

static void
do_kcpytkt(int count, char *names[], const char *fromccachestr, char *etypestr,
           int flags)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_enctype etype;
    krb5_ccache fromccache, destccache;
    krb5_principal me;
    krb5_creds in_creds, out_creds;
    int i, errors, retflags;
    char *princ;

    ret = krb5_init_context(&context);
    if (ret) {
        com_err(prog, ret, "while initializing krb5 library");
        exit(1);
    }
    if (etypestr != NULL) {
        ret = krb5_string_to_enctype(etypestr, &etype);
        if (ret) {
            com_err(prog, ret, "while converting etype");
            exit(1);
        }
        retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES;
    } else {
        etype = 0;
        retflags = KRB5_TC_MATCH_SRV_NAMEONLY;
    }

    if (fromccachestr != NULL)
        ret = krb5_cc_resolve(context, fromccachestr, &fromccache);
    else
        ret = krb5_cc_default(context, &fromccache);
    if (ret) {
        com_err(prog, ret, "while opening source ccache");
        exit(1);
    }

    ret = krb5_cc_get_principal(context, fromccache, &me);
    if (ret) {
        com_err(prog, ret, "while getting client principal name");
        exit(1);
    }

    ret = krb5_cc_resolve(context, names[0], &destccache);
    if (ret) {
        com_err(prog, ret, "while opening destination cache");
        exit(1);
    }

    errors = 0;

    for (i = 1; i < count; i++) {
        memset(&in_creds, 0, sizeof(in_creds));

        in_creds.client = me;

        ret = krb5_parse_name(context, names[i], &in_creds.server);
        if (ret) {
            if (!quiet) {
                fprintf(stderr, "%s: %s while parsing principal name\n",
                        names[i], error_message(ret));
            }
            errors++;
            continue;
        }

        ret = krb5_unparse_name(context, in_creds.server, &princ);
        if (ret) {
            fprintf(stderr, "%s: %s while printing principal name\n",
                    names[i], error_message(ret));
            errors++;
            continue;
        }

        in_creds.keyblock.enctype = etype;

        ret = krb5_cc_retrieve_cred(context, fromccache, retflags,
                                    &in_creds, &out_creds);
        if (ret) {
            fprintf(stderr, "%s: %s while retrieving credentials\n",
                    princ, error_message(ret));
            krb5_free_unparsed_name(context, princ);
            errors++;
            continue;
        }

        ret = krb5_cc_store_cred(context, destccache, &out_creds);
        krb5_free_principal(context, in_creds.server);
        if (ret) {
            fprintf(stderr, "%s: %s while removing credentials\n",
                    princ, error_message(ret));
            krb5_free_cred_contents(context, &out_creds);
            krb5_free_unparsed_name(context, princ);
            errors++;
            continue;
        }

        krb5_free_unparsed_name(context, princ);
        krb5_free_cred_contents(context, &out_creds);
    }

    krb5_free_principal(context, me);
    krb5_cc_close(context, fromccache);
    krb5_cc_close(context, destccache);
    krb5_free_context(context);

    if (errors)
        exit(1);

    exit(0);
}