]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Move akimpersonate to libauth
authorAlexander Chernyakhovsky <achernya@mit.edu>
Tue, 14 May 2013 22:12:08 +0000 (18:12 -0400)
committerRuss Allbery <rra@debian.org>
Mon, 22 Jul 2013 22:25:53 +0000 (15:25 -0700)
Give it its own source file and header, install the header at
depinstall time, and have aklog get the akimpersonate functionality
from libauth.

Keep the linux box copyright from aklog_main.c (but strip the trailing
whitespace), as that block was added with the akimpersonate code.

Remove all calls to afs_com_err() as is fitting for library code,
to let it build.  Do not bother removing curly braces which are
no longer needed; a future cleanup commit will catch that.

src/aklog/aklog_main.c
src/auth/Makefile.in
src/auth/akimpersonate.c [new file with mode: 0644]
src/auth/akimpersonate.h [new file with mode: 0644]
src/libafsauthent/Makefile.in
src/shlibafsauthent/Makefile.in

index ee044e9789579ec49430b5ccbf99145c4aeb8bba..1d9c9058d5a13e84d18e838fe0f3eed80a55cdd5 100644 (file)
@@ -73,6 +73,7 @@
 #ifdef AFS_SUN5_ENV
 #include <sys/ioccom.h>
 #endif
+#include <afs/akimpersonate.h>
 #include <afs/auth.h>
 #include <afs/cellconfig.h>
 #include <afs/vice.h>
@@ -180,108 +181,12 @@ static int get_user_realm(krb5_context, char *);
 #error "Must have either krb5_princ_size or krb5_principal_get_comp_string"
 #endif
 
-#if !defined(HAVE_KRB5_ENCRYPT_TKT_PART) && defined(HAVE_ENCODE_KRB5_ENC_TKT_PART) && defined(HAVE_KRB5_C_ENCRYPT) 
-krb5_error_code
-krb5_encrypt_tkt_part(krb5_context context,
-                     const krb5_keyblock *key,
-                     krb5_ticket *ticket)
-{
-    krb5_data *data = 0;
-    int code;
-    size_t enclen;
-    
-    if ((code = encode_krb5_enc_tkt_part(ticket->enc_part2, &data)))
-       goto Done;
-    if ((code = krb5_c_encrypt_length(context, key->enctype,
-                                     data->length, &enclen)))
-       goto Done;
-    ticket->enc_part.ciphertext.length = enclen;
-    if (!(ticket->enc_part.ciphertext.data = malloc(enclen))) {
-       code = ENOMEM;
-       goto Done;
-    }
-    if ((code = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_KDC_REP_TICKET,
-                              0, data, &ticket->enc_part))) {
-       free(ticket->enc_part.ciphertext.data);
-       ticket->enc_part.ciphertext.data = 0;
-    }
-Done:
-    if (data) {
-       if (data->data)
-           free(data->data);
-       free(data);
-    }
-    return code;
-}
-#endif
-
-#if defined(HAVE_KRB5_CREDS_KEYBLOCK)
-
-#define get_cred_keydata(c) c->keyblock.contents
-#define get_cred_keylen(c) c->keyblock.length
-#define get_creds_enctype(c) c->keyblock.enctype
-
-#elif defined(HAVE_KRB5_CREDS_SESSION)
-
-#define get_cred_keydata(c) c->session.keyvalue.data
-#define get_cred_keylen(c) c->session.keyvalue.length
-#define get_creds_enctype(c) c->session.keytype
-
-#else
-#error "Must have either keyblock or session member of krb5_creds"
-#endif
-
 #if !defined(HAVE_KRB5_524_CONVERT_CREDS) && defined(HAVE_KRB524_CONVERT_CREDS_KDC)
 #define krb5_524_convert_creds krb524_convert_creds_kdc
 #elif !defined(HAVE_KRB5_524_CONVERT_CREDS) && !defined(HAVE_KRB524_CONVERT_CREDS_KDC)
 #define HAVE_NO_KRB5_524
 #endif
 
-#if USING_HEIMDAL
-#define deref_keyblock_enctype(kb)             \
-    ((kb)->keytype)
-
-#define deref_entry_keyblock(entry)            \
-    entry->keyblock
-
-#define deref_session_key(creds)               \
-    creds->session
-
-#define deref_enc_tkt_addrs(tkt)               \
-    tkt->caddr
-
-#define deref_enc_length(enc)                  \
-    ((enc)->cipher.length)
-
-#define deref_enc_data(enc)                    \
-    ((enc)->cipher.data)
-
-#define krb5_free_keytab_entry_contents krb5_kt_free_entry
-
-#else
-#define deref_keyblock_enctype(kb)             \
-    ((kb)->enctype)
-
-#define deref_entry_keyblock(entry)            \
-    entry->key
-
-#define deref_session_key(creds)               \
-    creds->keyblock
-
-#define deref_enc_tkt_addrs(tkt)               \
-    tkt->caddrs
-
-#define deref_enc_length(enc)                  \
-    ((enc)->ciphertext.length)
-
-#define deref_enc_data(enc)                    \
-    ((enc)->ciphertext.data)
-
-#endif
-
-#define deref_entry_enctype(entry)                     \
-    deref_keyblock_enctype(&deref_entry_keyblock(entry))
-
 /*
  * Provide a replacement for strerror if we don't have it
  */
@@ -1552,327 +1457,6 @@ static int isdir(char *path, unsigned char *val)
     }  
 }
 
-static krb5_error_code get_credv5_akimpersonate(krb5_context context,
-                                               char* keytab,
-                                               krb5_principal service_principal,
-                                               krb5_principal client_principal,
-                                               time_t starttime,
-                                               time_t endtime,
-                                               int *allowed_enctypes,
-                                               int *paddress,
-                                               krb5_creds** out_creds /* out */ )
-{
-#if defined(USING_HEIMDAL) || (defined(HAVE_ENCODE_KRB5_ENC_TKT) && defined(HAVE_ENCODE_KRB5_TICKET) && defined(HAVE_KRB5_C_ENCRYPT))
-    krb5_error_code code;
-    krb5_keytab kt = 0;
-    krb5_kt_cursor cursor[1];
-    krb5_keytab_entry entry[1];
-    krb5_ccache cc = 0;
-    krb5_creds *creds = 0;
-    krb5_enctype enctype;
-    krb5_kvno kvno;
-    krb5_keyblock session_key[1];
-#if USING_HEIMDAL
-    Ticket ticket_reply[1];
-    EncTicketPart enc_tkt_reply[1];
-    krb5_address address[30];
-    krb5_addresses faddr[1];
-    int temp_vno[1];
-    time_t temp_time[2];
-#else
-    krb5_ticket ticket_reply[1];
-    krb5_enc_tkt_part enc_tkt_reply[1];
-    krb5_address address[30], *faddr[30];
-#endif
-    krb5_data * temp;
-    int i;
-    static int any_enctype[] = {0};
-    *out_creds = 0;
-    if (!(creds = malloc(sizeof *creds))) {
-        code = ENOMEM;
-        goto cleanup;
-    }
-    if (!allowed_enctypes)
-        allowed_enctypes = any_enctype;
-
-    cc = 0;
-    enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */
-    kvno = 0; /* AKIMPERSONATE_IGNORE_VNO */
-    memset((char*)creds, 0, sizeof *creds);
-    memset((char*)entry, 0, sizeof *entry);
-    memset((char*)session_key, 0, sizeof *session_key);
-    memset((char*)ticket_reply, 0, sizeof *ticket_reply);
-    memset((char*)enc_tkt_reply, 0, sizeof *enc_tkt_reply);
-    code = krb5_kt_resolve(context, keytab, &kt);
-    if (code) {
-        if (keytab)
-            afs_com_err(progname, code, "while resolving keytab %s", keytab);
-        else
-            afs_com_err(progname, code, "while resolving default keytab");
-        goto cleanup;
-    }
-
-    if (service_principal) {
-        for (i = 0; (enctype = allowed_enctypes[i]) || !i; ++i) {
-           code = krb5_kt_get_entry(context,
-                                    kt,
-                                    service_principal,
-                                    kvno,
-                                    enctype,
-                                    entry);
-           if (!code) {
-               if (allowed_enctypes[i])
-                   deref_keyblock_enctype(session_key) = allowed_enctypes[i];
-               break;
-           }
-        }
-        if (code) {
-           afs_com_err(progname, code,"while scanning keytab entries");
-           goto cleanup;
-        }
-    } else {
-        krb5_keytab_entry new[1];
-        int best = -1;
-        memset(new, 0, sizeof *new);
-        if ((code == krb5_kt_start_seq_get(context, kt, cursor))) {
-            afs_com_err(progname, code, "while starting keytab scan");
-            goto cleanup;
-        }
-        while (!(code = krb5_kt_next_entry(context, kt, new, cursor))) {
-            for (i = 0;
-                    allowed_enctypes[i] && allowed_enctypes[i]
-                    != deref_entry_enctype(new); ++i)
-                ;
-            if ((!i || allowed_enctypes[i]) &&
-               (best < 0 || best > i)) {
-                krb5_free_keytab_entry_contents(context, entry);
-                *entry = *new;
-                memset(new, 0, sizeof *new);
-            } else krb5_free_keytab_entry_contents(context, new);
-        }
-        if ((i = krb5_kt_end_seq_get(context, kt, cursor))) {
-            afs_com_err(progname, i, "while ending keytab scan");
-            code = i;
-            goto cleanup;
-        }
-        if (best < 0) {
-            afs_com_err(progname, code, "while scanning keytab");
-            goto cleanup;
-        }
-        deref_keyblock_enctype(session_key) = deref_entry_enctype(entry);
-    }
-
-    /* Make Ticket */
-
-#if USING_HEIMDAL
-    if ((code = krb5_generate_random_keyblock(context,
-                                             deref_keyblock_enctype(session_key), session_key))) {
-        afs_com_err(progname, code, "while making session key");
-        goto cleanup;
-    }
-    enc_tkt_reply->flags.initial = 1;
-    enc_tkt_reply->transited.tr_type = DOMAIN_X500_COMPRESS;
-    enc_tkt_reply->cname = client_principal->name;
-    enc_tkt_reply->crealm = client_principal->realm;
-    enc_tkt_reply->key = *session_key;
-    {
-        static krb5_data empty_string;
-        enc_tkt_reply->transited.contents = empty_string;
-    }
-    enc_tkt_reply->authtime = starttime;
-    enc_tkt_reply->starttime = temp_time;
-    *enc_tkt_reply->starttime = starttime;
-#if 0
-    enc_tkt_reply->renew_till = temp_time + 1;
-    *enc_tkt_reply->renew_till = endtime;
-#endif
-    enc_tkt_reply->endtime = endtime;
-#else
-    if ((code = krb5_c_make_random_key(context,
-                                      deref_keyblock_enctype(session_key), session_key))) {
-        afs_com_err(progname, code, "while making session key");
-        goto cleanup;
-    }
-    enc_tkt_reply->magic = KV5M_ENC_TKT_PART;
-#define DATACAST        (unsigned char *)
-    enc_tkt_reply->flags |= TKT_FLG_INITIAL;
-    enc_tkt_reply->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
-    enc_tkt_reply->session = session_key;
-    enc_tkt_reply->client = client_principal;
-    {
-        static krb5_data empty_string;
-        enc_tkt_reply->transited.tr_contents = empty_string;
-    }
-    enc_tkt_reply->times.authtime = starttime;
-    enc_tkt_reply->times.starttime = starttime; /* krb524init needs this */
-    enc_tkt_reply->times.endtime = endtime;
-#endif  /* USING_HEIMDAL */
-    /* NB:  We will discard address for now--ignoring caddr field               
-       in any case.  MIT branch does what it always did. */
-
-    if (paddress && *paddress) {
-        deref_enc_tkt_addrs(enc_tkt_reply) = faddr;
-#if USING_HEIMDAL
-        faddr->len = 0;
-        faddr->val = address;
-#endif
-        for (i = 0; paddress[i]; ++i) {
-#if USING_HEIMDAL
-            address[i].addr_type = KRB5_ADDRESS_INET;
-            address[i].address.data = (void*)(paddress+i);
-            address[i].address.length = sizeof(paddress[i]);
-#else
-#if !USING_SSL
-            address[i].magic = KV5M_ADDRESS;
-            address[i].addrtype = ADDRTYPE_INET;
-#else
-            address[i].addrtype = AF_INET;
-#endif
-            address[i].contents = (void*)(paddress+i);
-            address[i].length = sizeof(int);
-            faddr[i] = address+i;
-#endif
-        }
-#if USING_HEIMDAL
-        faddr->len = i;
-#else
-        faddr[i] = 0;
-#endif
-    }
-
-#if USING_HEIMDAL
-    ticket_reply->sname = service_principal->name;
-    ticket_reply->realm = service_principal->realm;
-
-    { /* crypto block */
-        krb5_crypto crypto = 0;
-        unsigned char *buf = 0;
-        size_t buf_size, buf_len;
-        char *what;
-
-        ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size,
-                          enc_tkt_reply, &buf_len, code);
-        if(code) {
-            afs_com_err(progname, code, "while encoding ticket");
-            goto cleanup;
-        }
-
-        if(buf_len != buf_size) {
-            afs_com_err(progname, code,
-                   "%d != %d while encoding ticket (internal ASN.1 encoder error",
-                   buf_len, buf_size);
-            goto cleanup;
-        }
-        what = "krb5_crypto_init";
-        code = krb5_crypto_init(context,
-                               &deref_entry_keyblock(entry),
-                               deref_entry_enctype(entry),
-                               &crypto);
-        if(!code) {
-            what = "krb5_encrypt";
-            code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET,
-                                             buf, buf_len, entry->vno, &(ticket_reply->enc_part));
-        }
-        if (buf) free(buf);
-        if (crypto) krb5_crypto_destroy(context, crypto);
-        if(code) {
-            afs_com_err(progname, code, "while %s", what);
-            goto cleanup;
-        }
-    } /* crypto block */
-    ticket_reply->enc_part.etype = deref_entry_enctype(entry);
-    ticket_reply->enc_part.kvno = temp_vno;
-    *ticket_reply->enc_part.kvno = entry->vno;
-    ticket_reply->tkt_vno = 5;
-#else
-    ticket_reply->server = service_principal;
-    ticket_reply->enc_part2 = enc_tkt_reply;
-    if ((code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry), ticket_reply))) {
-        afs_com_err(progname, code, "while making ticket");
-        goto cleanup;
-    }
-    ticket_reply->enc_part.kvno = entry->vno;
-#endif
-
-    /* Construct Creds */
-
-    if ((code = krb5_copy_principal(context, service_principal,
-                                   &creds->server))) {
-        afs_com_err(progname, code, "while copying service principal");
-        goto cleanup;
-    }
-    if ((code = krb5_copy_principal(context, client_principal,
-                                   &creds->client))) {
-        afs_com_err(progname, code, "while copying client principal");
-        goto cleanup;
-    }
-    if ((code = krb5_copy_keyblock_contents(context, session_key,
-                                           &deref_session_key(creds)))) {
-        afs_com_err(progname, code, "while copying session key");
-        goto cleanup;
-    }
-
-#if USING_HEIMDAL
-    creds->times.authtime = enc_tkt_reply->authtime;
-    creds->times.starttime = *(enc_tkt_reply->starttime);
-    creds->times.endtime = enc_tkt_reply->endtime;
-    creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */
-    creds->flags.b = enc_tkt_reply->flags;
-#else
-    creds->times = enc_tkt_reply->times;
-    creds->ticket_flags = enc_tkt_reply->flags;
-#endif
-    if (!deref_enc_tkt_addrs(enc_tkt_reply))
-        ;
-    else if ((code = krb5_copy_addresses(context,
-                                        deref_enc_tkt_addrs(enc_tkt_reply), &creds->addresses))) {
-        afs_com_err(progname, code, "while copying addresses");
-        goto cleanup;
-    }
-
-#if USING_HEIMDAL
-    {
-       size_t creds_tkt_len;
-       ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
-                          ticket_reply, &creds_tkt_len, code);
-       if(code) {
-           afs_com_err(progname, code, "while encoding ticket");
-           goto cleanup;
-       }
-    }
-#else
-    if ((code = encode_krb5_ticket(ticket_reply, &temp))) {
-       afs_com_err(progname, code, "while encoding ticket");
-       goto cleanup;
-    }
-    creds->ticket = *temp;
-    free(temp);
-#endif
-    /* return creds */
-    *out_creds = creds;
-    creds = 0;
-cleanup:
-    if (deref_enc_data(&ticket_reply->enc_part))
-        free(deref_enc_data(&ticket_reply->enc_part));
-    krb5_free_keytab_entry_contents(context, entry);
-    if (client_principal)
-        krb5_free_principal(context, client_principal);
-    if (service_principal)
-        krb5_free_principal(context, service_principal);
-    if (cc)
-        krb5_cc_close(context, cc);
-    if (kt)
-        krb5_kt_close(context, kt);
-    if (creds) krb5_free_creds(context, creds);
-    krb5_free_keyblock_contents(context, session_key);
-out:
-    return code;
-#else
-    return -1;
-#endif
-}
-
-
 static krb5_error_code get_credv5(krb5_context context, 
                                  char *name, char *inst, char *realm,
                                  krb5_creds **creds)
index 552f69b1eeb53a56084f59d5eacce0b15b4492a3..a94aa6fb8bf24cb6585f2208aa6a762b0e879c81 100644 (file)
@@ -9,15 +9,15 @@ srcdir=@srcdir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 
 OBJS= cellconfig.o ktc.o userok.o writeconfig.o authcon.o \
-    acfg_errors.o ktc_errors.o
+    acfg_errors.o ktc_errors.o @MAKE_KRB5@ akimpersonate.o
 KOBJS= cellconfig.o ktc.krb.o userok.o writeconfig.o authcon.o \
-    acfg_errors.o ktc_errors.o
+    acfg_errors.o ktc_errors.o @MAKE_KRB5@ akimpersonate.o
 
 LIBS=libauth.a \
       ${TOP_LIBDIR}/librxkad.a ${TOP_LIBDIR}/libdes.a \
       ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/libsys.a \
       ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a
-INCLS=cellconfig.h auth.h keys.h
+INCLS=cellconfig.h auth.h keys.h akimpersonate.h
 KSRCS=auth.h
 UKSRCS=${KSRCS} cellconfig.h acfg_errors.c keys.h cellconfig.c \
        ktc.c authcon.c ktc_errors.c
@@ -30,6 +30,7 @@ all: \
 depinstall: \
        ${TOP_INCDIR}/afs/keys.h \
        ${TOP_INCDIR}/afs/cellconfig.h \
+       ${TOP_INCDIR}/afs/akimpersonate.h \
        ${TOP_INCDIR}/afs/auth.h \
        ${TOP_INCDIR}/afs/ktc.h
 
@@ -40,6 +41,9 @@ writeconfig.o: writeconfig.c ${INCLS}
 authcon.o: authcon.c ${INCLS}
        ${CCOBJ} ${CFLAGS} -c ${srcdir}/authcon.c @KRB5CFLAGS@
 
+akimpersonate.o: akimpersonate.c ${INCLS}
+       ${CCOBJ} ${CFLAGS} -c ${srcdir}/akimpersonate.c @KRB5CFLAGS@
+
 userok.o: userok.c ${INCLS}
 cellconfig.o: cellconfig.c ${INCLS}
 copyauth.o: copyauth.c ${INCLS} AFS_component_version_number.o
@@ -137,6 +141,9 @@ ${TOP_INCDIR}/afs/cellconfig.h: cellconfig.h
 ${DEST}/include/afs/cellconfig.h: cellconfig.h
        ${INSTALL} $? $@
 
+${TOP_INCDIR}/afs/akimpersonate.h: akimpersonate.h
+       ${INSTALL} $? $@
+
 ${DESTDIR}${includedir}/afs/auth.h: auth.h
        ${INSTALL} $? $@
 
diff --git a/src/auth/akimpersonate.c b/src/auth/akimpersonate.c
new file mode 100644 (file)
index 0000000..dc2f009
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2005, 2006
+ * The Linux Box Corporation
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of the Linux Box
+ * Corporation is not used in any advertising or publicity
+ * pertaining to the use or distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * Linux Box Corporation is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * This software is provided as is, without representation
+ * from the Linux Box Corporation as to its fitness for any
+ * purpose, and without warranty by the Linux Box Corporation
+ * of any kind, either express or implied, including
+ * without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  The
+ * regents of the Linux Box Corporation shall not be liable
+ * for any damages, including special, indirect, incidental, or
+ * consequential damages, with respect to any claim arising
+ * out of or in connection with the use of the software, even
+ * if it has been or is hereafter advised of the possibility of
+ * such damages.
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+#include <afs/stds.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <krb5.h>
+
+#include "akimpersonate.h"
+
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK
+#define USING_MIT 1
+#endif
+#ifdef HAVE_KRB5_CREDS_SESSION
+#define USING_HEIMDAL 1
+#endif
+
+#if USING_HEIMDAL
+#define deref_keyblock_enctype(kb)             \
+    ((kb)->keytype)
+
+#define deref_entry_keyblock(entry)            \
+    entry->keyblock
+
+#define deref_session_key(creds)               \
+    creds->session
+
+#define deref_enc_tkt_addrs(tkt)               \
+    tkt->caddr
+
+#define deref_enc_length(enc)                  \
+    ((enc)->cipher.length)
+
+#define deref_enc_data(enc)                    \
+    ((enc)->cipher.data)
+
+#define krb5_free_keytab_entry_contents krb5_kt_free_entry
+
+#else
+#define deref_keyblock_enctype(kb)             \
+    ((kb)->enctype)
+
+#define deref_entry_keyblock(entry)            \
+    entry->key
+
+#define deref_session_key(creds)               \
+    creds->keyblock
+
+#define deref_enc_tkt_addrs(tkt)               \
+    tkt->caddrs
+
+#define deref_enc_length(enc)                  \
+    ((enc)->ciphertext.length)
+
+#define deref_enc_data(enc)                    \
+    ((enc)->ciphertext.data)
+
+#endif
+
+#define deref_entry_enctype(entry)                     \
+    deref_keyblock_enctype(&deref_entry_keyblock(entry))
+
+#if !defined(HAVE_KRB5_ENCRYPT_TKT_PART) && defined(HAVE_ENCODE_KRB5_ENC_TKT_PART) && defined(HAVE_KRB5_C_ENCRYPT)
+krb5_error_code
+krb5_encrypt_tkt_part(krb5_context context,
+                     const krb5_keyblock *key,
+                     krb5_ticket *ticket)
+{
+    krb5_data *data = 0;
+    int code;
+    size_t enclen;
+
+    if ((code = encode_krb5_enc_tkt_part(ticket->enc_part2, &data)))
+       goto Done;
+    if ((code = krb5_c_encrypt_length(context, key->enctype,
+                                     data->length, &enclen)))
+       goto Done;
+    ticket->enc_part.ciphertext.length = enclen;
+    if (!(ticket->enc_part.ciphertext.data = malloc(enclen))) {
+       code = ENOMEM;
+       goto Done;
+    }
+    if ((code = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_KDC_REP_TICKET,
+                              0, data, &ticket->enc_part))) {
+       free(ticket->enc_part.ciphertext.data);
+       ticket->enc_part.ciphertext.data = 0;
+    }
+Done:
+    if (data) {
+       if (data->data)
+           free(data->data);
+       free(data);
+    }
+    return code;
+}
+#endif
+
+krb5_error_code get_credv5_akimpersonate(krb5_context context,
+                                        char* keytab,
+                                        krb5_principal service_principal,
+                                        krb5_principal client_principal,
+                                        time_t starttime,
+                                        time_t endtime,
+                                        int *allowed_enctypes,
+                                        int *paddress,
+                                        krb5_creds** out_creds /* out */ )
+{
+#if defined(USING_HEIMDAL) || (defined(HAVE_ENCODE_KRB5_ENC_TKT) && defined(HAVE_ENCODE_KRB5_TICKET) && defined(HAVE_KRB5_C_ENCRYPT))
+    krb5_error_code code;
+    krb5_keytab kt = 0;
+    krb5_kt_cursor cursor[1];
+    krb5_keytab_entry entry[1];
+    krb5_ccache cc = 0;
+    krb5_creds *creds = 0;
+    krb5_enctype enctype;
+    krb5_kvno kvno;
+    krb5_keyblock session_key[1];
+#if USING_HEIMDAL
+    Ticket ticket_reply[1];
+    EncTicketPart enc_tkt_reply[1];
+    krb5_address address[30];
+    krb5_addresses faddr[1];
+    int temp_vno[1];
+    time_t temp_time[2];
+#else
+    krb5_ticket ticket_reply[1];
+    krb5_enc_tkt_part enc_tkt_reply[1];
+    krb5_address address[30], *faddr[30];
+#endif
+    krb5_data * temp;
+    int i;
+    static int any_enctype[] = {0};
+    *out_creds = 0;
+    if (!(creds = malloc(sizeof *creds))) {
+        code = ENOMEM;
+        goto cleanup;
+    }
+    if (!allowed_enctypes)
+        allowed_enctypes = any_enctype;
+
+    cc = 0;
+    enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */
+    kvno = 0; /* AKIMPERSONATE_IGNORE_VNO */
+    memset((char*)creds, 0, sizeof *creds);
+    memset((char*)entry, 0, sizeof *entry);
+    memset((char*)session_key, 0, sizeof *session_key);
+    memset((char*)ticket_reply, 0, sizeof *ticket_reply);
+    memset((char*)enc_tkt_reply, 0, sizeof *enc_tkt_reply);
+    code = krb5_kt_resolve(context, keytab, &kt);
+    if (code) {
+        goto cleanup;
+    }
+
+    if (service_principal) {
+        for (i = 0; (enctype = allowed_enctypes[i]) || !i; ++i) {
+           code = krb5_kt_get_entry(context,
+                                    kt,
+                                    service_principal,
+                                    kvno,
+                                    enctype,
+                                    entry);
+           if (!code) {
+               if (allowed_enctypes[i])
+                   deref_keyblock_enctype(session_key) = allowed_enctypes[i];
+               break;
+           }
+        }
+        if (code) {
+           goto cleanup;
+        }
+    } else {
+        krb5_keytab_entry new[1];
+        int best = -1;
+        memset(new, 0, sizeof *new);
+        if ((code == krb5_kt_start_seq_get(context, kt, cursor))) {
+            goto cleanup;
+        }
+        while (!(code = krb5_kt_next_entry(context, kt, new, cursor))) {
+            for (i = 0;
+                    allowed_enctypes[i] && allowed_enctypes[i]
+                    != deref_entry_enctype(new); ++i)
+                ;
+            if ((!i || allowed_enctypes[i]) &&
+               (best < 0 || best > i)) {
+                krb5_free_keytab_entry_contents(context, entry);
+                *entry = *new;
+                memset(new, 0, sizeof *new);
+            } else krb5_free_keytab_entry_contents(context, new);
+        }
+        if ((i = krb5_kt_end_seq_get(context, kt, cursor))) {
+            code = i;
+            goto cleanup;
+        }
+        if (best < 0) {
+            goto cleanup;
+        }
+        deref_keyblock_enctype(session_key) = deref_entry_enctype(entry);
+    }
+
+    /* Make Ticket */
+
+#if USING_HEIMDAL
+    if ((code = krb5_generate_random_keyblock(context,
+                                             deref_keyblock_enctype(session_key), session_key))) {
+        goto cleanup;
+    }
+    enc_tkt_reply->flags.initial = 1;
+    enc_tkt_reply->transited.tr_type = DOMAIN_X500_COMPRESS;
+    enc_tkt_reply->cname = client_principal->name;
+    enc_tkt_reply->crealm = client_principal->realm;
+    enc_tkt_reply->key = *session_key;
+    {
+        static krb5_data empty_string;
+        enc_tkt_reply->transited.contents = empty_string;
+    }
+    enc_tkt_reply->authtime = starttime;
+    enc_tkt_reply->starttime = temp_time;
+    *enc_tkt_reply->starttime = starttime;
+#if 0
+    enc_tkt_reply->renew_till = temp_time + 1;
+    *enc_tkt_reply->renew_till = endtime;
+#endif
+    enc_tkt_reply->endtime = endtime;
+#else
+    if ((code = krb5_c_make_random_key(context,
+                                      deref_keyblock_enctype(session_key), session_key))) {
+        goto cleanup;
+    }
+    enc_tkt_reply->magic = KV5M_ENC_TKT_PART;
+#define DATACAST        (unsigned char *)
+    enc_tkt_reply->flags |= TKT_FLG_INITIAL;
+    enc_tkt_reply->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
+    enc_tkt_reply->session = session_key;
+    enc_tkt_reply->client = client_principal;
+    {
+        static krb5_data empty_string;
+        enc_tkt_reply->transited.tr_contents = empty_string;
+    }
+    enc_tkt_reply->times.authtime = starttime;
+    enc_tkt_reply->times.starttime = starttime; /* krb524init needs this */
+    enc_tkt_reply->times.endtime = endtime;
+#endif  /* USING_HEIMDAL */
+    /* NB:  We will discard address for now--ignoring caddr field
+       in any case.  MIT branch does what it always did. */
+
+    if (paddress && *paddress) {
+        deref_enc_tkt_addrs(enc_tkt_reply) = faddr;
+#if USING_HEIMDAL
+        faddr->len = 0;
+        faddr->val = address;
+#endif
+        for (i = 0; paddress[i]; ++i) {
+#if USING_HEIMDAL
+            address[i].addr_type = KRB5_ADDRESS_INET;
+            address[i].address.data = (void*)(paddress+i);
+            address[i].address.length = sizeof(paddress[i]);
+#else
+#if !USING_SSL
+            address[i].magic = KV5M_ADDRESS;
+            address[i].addrtype = ADDRTYPE_INET;
+#else
+            address[i].addrtype = AF_INET;
+#endif
+            address[i].contents = (void*)(paddress+i);
+            address[i].length = sizeof(int);
+            faddr[i] = address+i;
+#endif
+        }
+#if USING_HEIMDAL
+        faddr->len = i;
+#else
+        faddr[i] = 0;
+#endif
+    }
+
+#if USING_HEIMDAL
+    ticket_reply->sname = service_principal->name;
+    ticket_reply->realm = service_principal->realm;
+
+    { /* crypto block */
+        krb5_crypto crypto = 0;
+        unsigned char *buf = 0;
+        size_t buf_size, buf_len;
+        char *what;
+
+        ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size,
+                          enc_tkt_reply, &buf_len, code);
+        if(code) {
+            goto cleanup;
+        }
+
+        if(buf_len != buf_size) {
+            goto cleanup;
+        }
+        what = "krb5_crypto_init";
+        code = krb5_crypto_init(context,
+                               &deref_entry_keyblock(entry),
+                               deref_entry_enctype(entry),
+                               &crypto);
+        if(!code) {
+            what = "krb5_encrypt";
+            code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET,
+                                             buf, buf_len, entry->vno, &(ticket_reply->enc_part));
+        }
+        if (buf) free(buf);
+        if (crypto) krb5_crypto_destroy(context, crypto);
+        if(code) {
+            goto cleanup;
+        }
+    } /* crypto block */
+    ticket_reply->enc_part.etype = deref_entry_enctype(entry);
+    ticket_reply->enc_part.kvno = temp_vno;
+    *ticket_reply->enc_part.kvno = entry->vno;
+    ticket_reply->tkt_vno = 5;
+#else
+    ticket_reply->server = service_principal;
+    ticket_reply->enc_part2 = enc_tkt_reply;
+    if ((code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry), ticket_reply))) {
+        goto cleanup;
+    }
+    ticket_reply->enc_part.kvno = entry->vno;
+#endif
+
+    /* Construct Creds */
+
+    if ((code = krb5_copy_principal(context, service_principal,
+                                   &creds->server))) {
+        goto cleanup;
+    }
+    if ((code = krb5_copy_principal(context, client_principal,
+                                   &creds->client))) {
+        goto cleanup;
+    }
+    if ((code = krb5_copy_keyblock_contents(context, session_key,
+                                           &deref_session_key(creds)))) {
+        goto cleanup;
+    }
+
+#if USING_HEIMDAL
+    creds->times.authtime = enc_tkt_reply->authtime;
+    creds->times.starttime = *(enc_tkt_reply->starttime);
+    creds->times.endtime = enc_tkt_reply->endtime;
+    creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */
+    creds->flags.b = enc_tkt_reply->flags;
+#else
+    creds->times = enc_tkt_reply->times;
+    creds->ticket_flags = enc_tkt_reply->flags;
+#endif
+    if (!deref_enc_tkt_addrs(enc_tkt_reply))
+        ;
+    else if ((code = krb5_copy_addresses(context,
+                                        deref_enc_tkt_addrs(enc_tkt_reply), &creds->addresses))) {
+        goto cleanup;
+    }
+
+#if USING_HEIMDAL
+    {
+       size_t creds_tkt_len;
+       ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
+                          ticket_reply, &creds_tkt_len, code);
+       if(code) {
+           goto cleanup;
+       }
+    }
+#else
+    if ((code = encode_krb5_ticket(ticket_reply, &temp))) {
+       goto cleanup;
+    }
+    creds->ticket = *temp;
+    free(temp);
+#endif
+    /* return creds */
+    *out_creds = creds;
+    creds = 0;
+cleanup:
+    if (deref_enc_data(&ticket_reply->enc_part))
+        free(deref_enc_data(&ticket_reply->enc_part));
+    krb5_free_keytab_entry_contents(context, entry);
+    if (client_principal)
+        krb5_free_principal(context, client_principal);
+    if (service_principal)
+        krb5_free_principal(context, service_principal);
+    if (cc)
+        krb5_cc_close(context, cc);
+    if (kt)
+        krb5_kt_close(context, kt);
+    if (creds) krb5_free_creds(context, creds);
+    krb5_free_keyblock_contents(context, session_key);
+out:
+    return code;
+#else
+    return -1;
+#endif
+}
diff --git a/src/auth/akimpersonate.h b/src/auth/akimpersonate.h
new file mode 100644 (file)
index 0000000..6b63fec
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __AKIMPERSONATE_H__
+#define __AKIMPERSONATE_H__
+
+#if defined(HAVE_KRB5_CREDS_KEYBLOCK)
+#define get_cred_keydata(c)    ((c)->keyblock.contents)
+#define get_cred_keylen(c)     ((c)->keyblock.length)
+#define get_creds_enctype(c)   ((c)->keyblock.enctype)
+#elif defined(HAVE_KRB5_CREDS_SESSION)
+#define get_cred_keydata(c)    ((c)->session.keyvalue.data)
+#define get_cred_keylen(c)     ((c)->session.keyvalue.length)
+#define get_creds_enctype(c)   ((c)->session.keytype)
+#else
+#error "Must have either keyblock or session member of krb5_creds"
+#endif
+
+/* The caller must include krb5.h to get prototypes for the types used. */
+krb5_error_code
+get_credv5_akimpersonate(krb5_context, char*, krb5_principal, krb5_principal,
+                        time_t, time_t, const int *, krb5_creds**);
+
+#endif
index 9b6d0341916c9c3d521cd2da4b97309ecf41b91f..12b89cc79c454a903b090e5fc068410db7f52b73 100644 (file)
@@ -32,7 +32,7 @@ AUTHOBJS = \
        writeconfig.o \
        authcon.o \
        ktc_errors.o \
-       acfg_errors.o
+       acfg_errors.o @MAKE_KRB5@ akimpersonate.o
 
 KAUTHOBJS = \
        kauth.xdr.o \
@@ -122,6 +122,9 @@ writeconfig.o: ${AUTH}/writeconfig.c
 authcon.o: ${AUTH}/authcon.c
        ${CCRULE} @KRB5CFLAGS@
 
+akimpersonate.o: ${AUTH}/akimpersonate.c
+       ${CCRULE} -I../auth @KRB5CFLAGS@
+
 ktc_errors.o: ${AUTH}/ktc_errors.c
        ${CCRULE}
 
index f0aea618829cd62cb544804c4d092f4c6e30946c..b93b38367e5f6c58efda3813f1ea2a6e0a4ab26f 100644 (file)
@@ -37,7 +37,7 @@ AUTHOBJS = \
        writeconfig.o \
        authcon.o \
        ktc_errors.o \
-       acfg_errors.o
+       acfg_errors.o @MAKE_KRB5@ akimpersonate.o
 
 KAUTHOBJS = \
        kauth.xdr.o \
@@ -152,6 +152,9 @@ writeconfig.o: ${AUTH}/writeconfig.c
 authcon.o: ${AUTH}/authcon.c
        ${CCRULE} @KRB5CFLAGS@
 
+akimpersonate.o: ${AUTH}/akimpersonate.c
+       ${CCRULE} @KRB5CFLAGS@
+
 ktc_errors.o: ${AUTH}/ktc_errors.c
        ${CCRULE}