* Copyright 1990,1991 by the Massachusetts Institute of Technology
* For distribution and copying rights, see the file "mit-copyright.h"
*/
+/*
+ * 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.
+ */
-#if !defined(lint) && !defined(SABER)
-static char *rcsid =
- "$Id$";
-#endif /* lint || SABER */
+#include <afsconfig.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
-#ifndef WINDOWS
#include <sys/param.h>
#include <sys/errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pwd.h>
-#endif /* WINDOWS */
-
-/* on AIX AFS has an unresolved reference to osi_audit. We will define
- * it here as extern. It also trys to call the ntohl and htonl routines
- * as routines rather then macros. We need a real routine here.
- * We do this before the ntohl and htonl macros are defined in net/in.h
- */
-int osi_audit()
- { return(0);}
-
-#if 0
-#ifdef _AIX
-u_long htonl(u_long x)
- { return(x);}
-
-u_long ntohl(u_long x)
- { return(x);}
-#endif
-
-#include <netinet/in.h>
-/* #include <krb.h> */
-#endif /* 0 */
-
-#include <krb5.h>
-
-#ifdef WINDOWS
#include <afs/stds.h>
-#include <afs/auth.h>
-#include <rx/rxkad.h>
-#include <afs/dirpath.h>
+#include <krb5.h>
+#include <com_err.h>
-#else /* !WINDOWS */
-#include <afs/stds.h>
+#ifndef HAVE_KERBEROSV_HEIM_ERR_H
#include <afs/com_err.h>
+#endif
#include <afs/param.h>
#ifdef AFS_SUN5_ENV
#include <sys/ioccom.h>
#endif
+
+/* Prevent inclusion of des.h to avoid conflicts with des types */
+#define NO_DES_H_INCLUDE
+
#include <afs/auth.h>
#include <afs/cellconfig.h>
#include <afs/vice.h>
#include <afs/ptserver.h>
#include <afs/ptuser.h>
#include <afs/dirpath.h>
-#endif /* WINDOWS */
#include "aklog.h"
#include "linked_list.h"
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK
+#define USING_MIT 1
+#endif
+#ifdef HAVE_KRB5_CREDS_SESSION
+#define USING_HEIMDAL 1
+#endif
+
#define AFSKEY "afs"
#define AFSINST ""
#define AFS_TRY_FULL_PRINC 1
#endif /* AFS_TRY_FULL_PRINC */
+#define AKLOG_TRYAGAIN -1
#define AKLOG_SUCCESS 0
#define AKLOG_USAGE 1
#define AKLOG_SOMETHINGSWRONG 2
static char linkedcell2[MAXCELLCHARS+1];
static krb5_ccache _krb425_ccache = NULL;
-#ifdef WINDOWS
-
-/* libafsconf.dll */
-extern long cm_GetRootCellName();
-extern long cm_SearchCellFile();
-
-static long cm_SearchCellFile_CallBack();
-
-#else /* !WINDOWS */
-
/*
* Why doesn't AFS provide these prototypes?
*/
* Other prototypes
*/
-extern char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
+extern char *afs_realm_of_cell(krb5_context, struct afsconf_cell *, int);
static int isdir(char *, unsigned char *);
static krb5_error_code get_credv5(krb5_context context, char *, char *,
char *, krb5_creds **);
static int get_user_realm(krb5_context, char *);
+#define TRYAGAIN(x) (x == AKLOG_TRYAGAIN || \
+ x == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || \
+ x == KRB5KRB_ERR_GENERIC)
+
#if defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
#define get_princ_str(c, p, n) krb5_princ_component(c, p, n)->data
#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)
+extern krb5_error_code encode_krb5_enc_tkt_part (const krb5_enc_tkt_part *rep, krb5_data **code);
+
+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
#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)
-#error "You must have one of krb5_524_convert_creds or krb524_convert_creds_kdc available"
+#define HAVE_NO_KRB5_524
#endif
-#endif /* WINDOWS */
+#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
static int zsubs = FALSE; /* Are we keeping track of zephyr subs? */
static int hosts = FALSE; /* Are we keeping track of hosts? */
static int noprdb = FALSE; /* Skip resolving name to id? */
-static int linked = FALSE; /* try for both AFS nodes */
-static int afssetpag = FALSE; /* setpag for AFS */
+static int linked = FALSE; /* try for both AFS nodes */
+static int afssetpag = FALSE; /* setpag for AFS */
static int force = FALSE; /* Bash identical tokens? */
static int do524 = FALSE; /* Should we do 524 instead of rxkad2b? */
+static char *keytab = NULL; /* keytab for akimpersonate */
+static char *client = NULL; /* client principal for akimpersonate */
static linked_list zsublist; /* List of zephyr subscriptions */
static linked_list hostlist; /* List of host addresses */
static linked_list authedcells; /* List of cells already logged to */
+/* A com_error bodge. The idea here is that this routine lets us lookup
+ * things in the system com_err, if the AFS one just tells us the error
+ * is unknown
+ */
+
+void
+redirect_errors(const char *who, afs_int32 code, const char *fmt, va_list ap)
+{
+ if (who) {
+ fputs(who, stderr);
+ fputs(": ", stderr);
+ }
+ if (code) {
+ const char *str = afs_error_message(code);
+ if (strncmp(str, "unknown", strlen("unknown")) == 0) {
+ str = error_message(code);
+ }
+ fputs(str, stderr);
+ fputs(" ", stderr);
+ }
+ if (fmt) {
+ vfprintf(stderr, fmt, ap);
+ }
+ putc('\n', stderr);
+ fflush(stderr);
+}
+
/* ANL - CMU lifetime convert routine */
/* for K5.4.1 don't use this for now. Need to see if it is needed */
/* maybe needed in the krb524d module as well */
}
-static char *copy_string(char *string)
-{
- char *new_string;
-
- if ((new_string = (char *)calloc(strlen(string) + 1, sizeof(char))))
- (void) strcpy(new_string, string);
-
- return (new_string);
-}
-
-
static int get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell, char *linkedcell)
{
int status = AKLOG_SUCCESS;
struct afsconf_dir *configdir;
memset(local_cell, 0, sizeof(local_cell));
- memset((char *)cellconfig, 0, sizeof(*cellconfig));
-
-#ifndef WINDOWS
+ memset(cellconfig, 0, sizeof(*cellconfig));
if (!(configdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
fprintf(stderr,
(void) afsconf_Close(configdir);
-#else /* WINDOWS */
- /*
- * We'll try to mimic the GetCellInfo call here and fill in as much
- * of the afsconf_cell structure as we can.
- */
- if (cm_GetRootCellName(local_cell)) {
- fprintf(stderr, "%s: can't get local cellname\n", progname);
- exit(AKLOG_AFS);
- }
-
- if ((cell == NULL) || (cell[0] == 0))
- cell = local_cell;
-
- strcpy(cellconfig->name, cell);
-
- /* No way of figuring this out as far as I can tell */
- linkedcell[0] = '\0';
-
- /* Initialize server info */
- cellconfig->numServers = 0;
- cellconfig->hostName[0][0] = "\0";
-
- /*
- * Get servers of cell. cm_SearchCellFile_CallBack() gets call with
- * each server.
- */
- status = (int) cm_SearchCellFile(cell, NULL, &cm_SearchCellFile_CallBack,
- cellconfig /* rock */);
-
- switch(status) {
- case 0:
- break;
-
- case -1:
- fprintf(stderr, "%s: GetWindowsDirectory() failed.\n", progname);
- break;
-
- case -2:
- fprintf(stderr, "%s: Couldn't open afsdcells.ini for reading\n",
- progname);
- break;
-
- case -3:
- fprintf(stderr, "%s: Couldn't find any servers for cell %s\n",
- progname, cell);
- break;
-
- case -4:
- fprintf(stderr, "%s: Badly formatted line in afsdcells.ini (does not begin with a \">\" or contain \"#\"\n",
- progname);
- break;
-
- default:
- fprintf(stderr, "%s cm_SearchCellFile returned unknown error %d\n",
- status);
- }
-
- if (status) {
- exit(AKLOG_AFS);
- }
-
- status = AKLOG_SUCCESS;
-
-
-#endif /* WINDOWS */
-
return(status);
}
-
-#ifdef WINDOWS
-/*
- * Callback function for cm_SearchCellFile() in get_cellconfig() above.
- * This function gets called once for each server that is found for the cell.
- */
-static long
-cm_SearchCellFile_CallBack(void *rock /* cellconfig */,
- struct sockaddr_in *addr, /* Not used */
- char *server)
-{
- struct afsconf_cell *cellconfig = rock;
-
-
- /*
- * Save server name and increment count of servers
- */
- strcpy(cellconfig->hostName[cellconfig->numServers++], server);
-
- return (long) 0;
-}
-
-
-#endif /* WINDOWS */
-
-
/*
* Log to a cell. If the cell has already been logged to, return without
* doing anything. Otherwise, log to it and mark that it has been logged
char username[BUFSIZ]; /* To hold client username structure */
afs_int32 viceId; /* AFS uid of user */
- char name[ANAME_SZ]; /* Name of afs key */
- char primary_instance[INST_SZ]; /* Instance of afs key */
- char secondary_instance[INST_SZ]; /* Backup instance to try */
- int try_secondary = 0; /* Flag to indicate if we try second */
char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
- char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
+ char *realm_from_princ = 0 ; /* Calculated realm data */
+ char *realm_of_cell = 0; /* Pointer to realm we're using */
+ int retry; /* round, and round we go ... */
+
char local_cell[MAXCELLCHARS+1];
char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */
static char lastcell[MAXCELLCHARS+1] = { 0 };
-#ifndef WINDOWS
static char confname[512] = { 0 };
-#endif
krb5_creds *v5cred = NULL;
struct ktc_principal aserver;
struct ktc_principal aclient;
struct ktc_token atoken, btoken;
-#ifdef ALLOW_REGISTER
- afs_int32 id;
-#endif /* ALLOW_REGISTER */
-
- memset(name, 0, sizeof(name));
- memset(primary_instance, 0, sizeof(primary_instance));
- memset(secondary_instance, 0, sizeof(secondary_instance));
memset(realm_of_user, 0, sizeof(realm_of_user));
- memset(realm_of_cell, 0, sizeof(realm_of_cell));
-#ifndef WINDOWS
if (confname[0] == '\0') {
strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
confname[sizeof(confname) - 2] = '\0';
}
-#endif /* WINDOWS */
/* NULL or empty cell returns information on local cell */
if ((status = get_cellconfig(cell, &ak_cellconfig,
cell_to_use, ak_cellconfig.hostName[0]);
}
- /*
- * Find out which realm we're supposed to authenticate to. If one
- * is not included, use the kerberos realm found in the credentials
- * cache.
- */
-
- if (realm && realm[0]) {
- strcpy(realm_of_cell, realm);
- if (dflag) {
- printf("We were told to authenticate to realm %s.\n", realm);
- }
- }
- else {
- char *realm = afs_realm_of_cell(context, &ak_cellconfig);
-
- if (!realm) {
- fprintf(stderr,
- "%s: Couldn't figure out realm for cell %s.\n",
- progname, cell_to_use);
- exit(AKLOG_MISC);
- }
-
- strcpy(realm_of_cell, realm);
-
- if (dflag) {
- printf("We've deduced that we need to authenticate to"
- " realm %s.\n", realm_of_cell);
- }
- }
-
- /* We use the afs.<cellname> convention here...
- *
- * Doug Engert's original code had principals of the form:
- *
- * "afsx/cell@realm"
- *
- * in the KDC, so the name wouldn't conflict with DFS. Since we're
- * not using DFS, I changed it just to look for the following
- * principals:
- *
- * afs/<cell>@<realm>
- * afs@<realm>
- *
- * Because people are transitioning from afs@realm to afs/cell,
- * we configure things so that if the first one isn't found, we
- * try the second one. You can select which one you prefer with
- * a configure option.
- */
-
- strcpy(name, AFSKEY);
-
- if (AFS_TRY_FULL_PRINC || strcasecmp(cell_to_use, realm_of_cell) != 0) {
- strncpy(primary_instance, cell_to_use, sizeof(primary_instance));
- primary_instance[sizeof(primary_instance)-1] = '\0';
- if (strcasecmp(cell_to_use, realm_of_cell) == 0) {
- try_secondary = 1;
- secondary_instance[0] = '\0';
- }
- } else {
- primary_instance[0] = '\0';
- try_secondary = 1;
- strncpy(secondary_instance, cell_to_use,
- sizeof(secondary_instance));
- secondary_instance[sizeof(secondary_instance)-1] = '\0';
- }
-
- /*
- * Extract the session key from the ticket file and hand-frob an
- * afs style authenticator.
- */
-
- /*
- * Try to obtain AFS tickets. Because there are two valid service
- * names, we will try both, but trying the more specific first.
- *
- * afs/<cell>@<realm> i.e. allow for single name with "."
- * afs@<realm>
- */
-
- if (dflag) {
- printf("Getting tickets: %s/%s@%s\n", name,
- primary_instance, realm_of_cell);
+ if ((status = get_user_realm(context, realm_of_user))) {
+ fprintf(stderr, "%s: Couldn't determine realm of user:)",
+ progname);
+ afs_com_err(progname, status, " while getting realm");
+ return(AKLOG_KERBEROS);
}
- status = get_credv5(context, name, primary_instance, realm_of_cell,
- &v5cred);
-
- if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
- if (try_secondary) {
+ retry = 1;
+
+ while(retry) {
+
+ /* This code tries principals in the following, much debated,
+ * order:
+ *
+ * If the realm is specified on the command line we do
+ * - afs/cell@COMMAND-LINE-REALM
+ * - afs@COMMAND-LINE-REALM
+ *
+ * Otherwise, we do
+ * - afs/cell@REALM-FROM-USERS-PRINCIPAL
+ * - afs/cell@krb5_get_host_realm(db-server)
+ * Then, if krb5_get_host_realm(db-server) is non-empty
+ * - afs@ krb5_get_host_realm(db-server)
+ * Otherwise
+ * - afs/cell@ upper-case-domain-of-db-server
+ * - afs@ upper-case-domain-of-db-server
+ *
+ * In all cases, the 'afs@' variant is only tried where the
+ * cell and the realm match case-insensitively.
+ */
+
+ /* Cell on command line - use that one */
+ if (realm && realm[0]) {
+ realm_of_cell = realm;
+ status = AKLOG_TRYAGAIN;
if (dflag) {
- printf("Principal not found, trying alternate "
- "service name: %s/%s@%s\n", name,
- secondary_instance, realm_of_cell);
+ printf("We were told to authenticate to realm %s.\n",
+ realm);
}
- status = get_credv5(context, name, secondary_instance,
+ } else {
+ /* Initially, try using afs/cell@USERREALM */
+ if (dflag) {
+ printf("Trying to authenticate to user's realm %s.\n",
+ realm_of_user);
+ }
+
+ realm_of_cell = realm_of_user;
+ status = get_credv5(context, AFSKEY, cell_to_use,
realm_of_cell, &v5cred);
+
+ /* If that failed, try to determine the realm from the name of
+ * one of the DB servers */
+ if (TRYAGAIN(status)) {
+ realm_of_cell = afs_realm_of_cell(context, &ak_cellconfig,
+ FALSE);
+ if (!realm_of_cell) {
+ fprintf(stderr,
+ "%s: Couldn't figure out realm for cell %s.\n",
+ progname, cell_to_use);
+ exit(AKLOG_MISC);
+ }
+
+ if (dflag) {
+ if (realm_of_cell[0])
+ printf("We've deduced that we need to authenticate"
+ " to realm %s.\n", realm_of_cell);
+ else
+ printf("We've deduced that we need to authenticate "
+ "using referrals.\n");
+ }
+ }
}
- }
+
+ if (TRYAGAIN(status)) {
+ /* If we've got the full-princ-first option, or we're in a
+ * different realm from the cell - use the cell name as the
+ * instance */
+ if (AFS_TRY_FULL_PRINC ||
+ strcasecmp(cell_to_use, realm_of_cell)!=0) {
+ status = get_credv5(context, AFSKEY, cell_to_use,
+ realm_of_cell, &v5cred);
+
+ /* If we failed & we've got an empty realm, then try
+ * calling afs_realm_for_cell again. */
+ if (TRYAGAIN(status) && !realm_of_cell[0]) {
+ /* This time, get the realm by taking the domain
+ * component of the db server and make it upper case */
+ realm_of_cell = afs_realm_of_cell(context,
+ &ak_cellconfig, TRUE);
+ if (!realm_of_cell) {
+ fprintf(stderr,
+ "%s: Couldn't figure out realm for cell "
+ "%s.\n", progname, cell_to_use);
+ exit(AKLOG_MISC);
+ }
+ if (dflag) {
+ printf("We've deduced that we need to authenticate"
+ " to realm %s.\n", realm_of_cell);
+ }
+ }
+ status = get_credv5(context, AFSKEY, cell_to_use,
+ realm_of_cell, &v5cred);
+ }
+
+ /* If the realm and cell name match, then try without an
+ * instance, but only if realm is non-empty */
+
+ if (TRYAGAIN(status) &&
+ strcasecmp(cell_to_use, realm_of_cell) == 0) {
+ status = get_credv5(context, AFSKEY, NULL,
+ realm_of_cell, &v5cred);
+ if (!AFS_TRY_FULL_PRINC && TRYAGAIN(status)) {
+ status = get_credv5(context, AFSKEY, cell_to_use,
+ realm_of_cell, &v5cred);
+ }
+ }
+ }
+
+ /* Try to find a service principal for this cell.
+ * Some broken MIT libraries return KRB5KRB_AP_ERR_MSG_TYPE upon
+ * the first attempt, so we try twice to be sure */
- if (status) {
+ if (status == KRB5KRB_AP_ERR_MSG_TYPE && retry == 1)
+ retry++;
+ else
+ retry = 0;
+ }
+
+ if (status != 0) {
if (dflag) {
- printf("Kerberos error code returned by get_cred: %d\n",
- status);
+ printf("Kerberos error code returned by get_cred : %d\n",
+ status);
}
fprintf(stderr, "%s: Couldn't get %s AFS tickets:\n",
progname, cell_to_use);
- com_err(progname, status, "while getting AFS tickets");
+ afs_com_err(progname, status, "while getting AFS tickets");
return(AKLOG_KERBEROS);
}
+
+ /* If we've got a valid ticket, and we still don't know the realm name
+ * try to figure it out from the contents of the ticket
+ */
+#if !defined(USING_HEIMDAL) && defined(HAVE_KRB5_DECODE_TICKET)
+ if (strcmp(realm_of_cell, "") == 0) {
+ krb5_error_code code;
+ krb5_ticket *ticket;
+
+ code = krb5_decode_ticket(&v5cred->ticket, &ticket);
+
+ if (code != 0) {
+ fprintf(stderr,
+ "%s: Couldn't decode ticket to determine realm for "
+ "cell %s.\n",
+ progname, cell_to_use);
+ } else {
+ int len = realm_len(context, ticket->server);
+ /* This really shouldn't happen. */
+ if (len > REALM_SZ-1)
+ len = REALM_SZ-1;
+
+ realm_from_princ = (char *) malloc(sizeof(char) * (len+1));
+
+ strncpy(realm_from_princ, realm_data(context, ticket->server),
+ len);
+ realm_from_princ[len] = 0;
+ realm_of_cell = realm_from_princ;
+
+ krb5_free_ticket(context, ticket);
+ }
+ }
+#endif
strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
*/
if (! do524) {
+ char k4name[ANAME_SZ], k4inst[INST_SZ], k4realm[REALM_SZ];
+#ifdef HAVE_NO_KRB5_524
char *p;
int len;
+#endif
if (dflag)
printf("Using Kerberos V5 ticket natively\n");
+#ifndef HAVE_NO_KRB5_524
+ status = krb5_524_conv_principal (context, v5cred->client,
+ (char *) &k4name,
+ (char *) &k4inst,
+ (char *) &k4realm);
+ if (status) {
+ afs_com_err(progname, status, "while converting principal "
+ "to Kerberos V4 format");
+ return(AKLOG_KERBEROS);
+ }
+ strcpy (username, k4name);
+ if (k4inst[0]) {
+ strcat (username, ".");
+ strcat (username, k4inst);
+ }
+#else
len = min(get_princ_len(context, v5cred->client, 0),
- second_comp(context, v5cred->client) ?
- MAXKTCNAMELEN - 2 : MAXKTCNAMELEN - 1);
+ second_comp(context, v5cred->client) ?
+ MAXKTCNAMELEN - 2 : MAXKTCNAMELEN - 1);
strncpy(username, get_princ_str(context, v5cred->client, 0), len);
username[len] = '\0';
-
+
if (second_comp(context, v5cred->client)) {
- strcat(username, ".");
+ strcat(username, ".");
p = username + strlen(username);
len = min(get_princ_len(context, v5cred->client, 1),
MAXKTCNAMELEN - strlen(username) - 1);
strncpy(p, get_princ_str(context, v5cred->client, 1), len);
p[len] = '\0';
}
+#endif
memset(&atoken, 0, sizeof(atoken));
atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
get_cred_keylen(v5cred));
atoken.ticketLen = v5cred->ticket.length;
memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen);
+#ifndef HAVE_NO_KRB5_524
} else {
CREDENTIALS cred;
status = krb5_524_convert_creds(context, v5cred, &cred);
if (status) {
- com_err(progname, status, "while converting tickets "
+ afs_com_err(progname, status, "while converting tickets "
"to Kerberos V4 format");
return(AKLOG_KERBEROS);
}
memcpy(&atoken.sessionKey, cred.session, 8);
atoken.ticketLen = cred.ticket_st.length;
memcpy(atoken.ticket, cred.ticket_st.dat, atoken.ticketLen);
+#endif /* HAVE_NO_KRB5_524 */
}
if (!force &&
noprdb = 1;
#endif
-#ifndef WINDOWS
if (noprdb) {
-#endif
if (dflag) {
printf("Not resolving name %s to id (-noprdb set)\n",
username);
}
-#ifndef WINDOWS
}
else {
- if ((status = get_user_realm(context, realm_of_user))) {
- fprintf(stderr, "%s: Couldn't determine realm of user:)",
- progname);
- com_err(progname, status, " while getting realm");
- return(AKLOG_KERBEROS);
- }
if (strcmp(realm_of_user, realm_of_cell)) {
strcat(username, "@");
strcat(username, realm_of_user);
*/
#ifdef ALLOW_REGISTER
- if (status == 0) {
- if (viceId != ANONYMOUSID) {
-#else /* ALLOW_REGISTER */
- if ((status == 0) && (viceId != ANONYMOUSID))
-#endif /* ALLOW_REGISTER */
- sprintf (username, "AFS ID %d", (int) viceId);
-#ifdef ALLOW_REGISTER
- } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
+ if ((status == 0) && (viceId == ANONYMOUSID) &&
+ (strcmp(realm_of_user, realm_of_cell) != 0)) {
if (dflag) {
printf("doing first-time registration of %s "
"at %s\n", username, cell_to_use);
}
- id = 0;
+ viceId = 0;
strncpy(aclient.name, username, MAXKTCNAMELEN - 1);
strcpy(aclient.instance, "");
strncpy(aclient.cell, realm_of_user, MAXKTCREALMLEN - 1);
if ((status = ktc_SetToken(&aserver, &atoken, &aclient, 0))) {
- fprintf(stderr, "%s: unable to obtain tokens for cell %s "
- "(status: %d).\n", progname, cell_to_use, status);
+ afs_com_err(progname, status,
+ "while obtaining tokens for cell %s",
+ cell_to_use);
status = AKLOG_TOKEN;
}
printf("Error %d\n", status);
}
- if ((status = pr_CreateUser(username, &id))) {
+ if ((status = pr_CreateUser(username, &viceId))) {
fprintf(stderr, "%s: %s so unable to create remote PTS "
"user %s in cell %s (status: %d).\n", progname,
- error_message(status), username, cell_to_use,
+ afs_error_message(status), username, cell_to_use,
status);
+ viceId = ANONYMOUSID;
} else {
- printf("created cross-cell entry for %s at %s\n",
- username, cell_to_use);
- sprintf(username, "AFS ID %d", (int) id);
+ printf("created cross-cell entry for %s (Id %d) at %s\n",
+ username, viceId, cell_to_use);
}
}
- }
#endif /* ALLOW_REGISTER */
+ if ((status == 0) && (viceId != ANONYMOUSID)) {
+ sprintf(username, "AFS ID %d", (int) viceId);
+ }
}
-#endif /* !WINDOWS */
if (dflag) {
fprintf(stdout, "Set username to %s\n", username);
printf("Setting tokens. %s / %s @ %s \n",
aclient.name, aclient.instance, aclient.cell );
}
+#ifndef AFS_AIX51_ENV
/* on AIX 4.1.4 with AFS 3.4a+ if a write is not done before
* this routine, it will not add the token. It is not clear what
- * is going on here! So we will do the following operation
+ * is going on here! So we will do the following operation.
+ * On AIX 5, it causes the parent program to die, so we won't.
*/
write(2,"",0); /* dummy write */
-#ifndef WINDOWS
+#endif
if ((status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag))) {
- fprintf(stderr,
- "%s: unable to obtain tokens for cell %s (status: %d).\n",
- progname, cell_to_use, status);
+ afs_com_err(progname, status, "while obtaining tokens for cell %s",
+ cell_to_use);
status = AKLOG_TOKEN;
}
-#else /* WINDOWS */
- /* Note switched 2nd and 3rd args */
- if ((status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag))) {
- switch(status) {
- case KTC_INVAL:
- fprintf(stderr, "%s: Bad ticket length", progname);
- break;
- case KTC_PIOCTLFAIL:
- fprintf(stderr, "%s: Unknown error contacting AFS service",
- progname);
- break;
- case KTC_NOCELL:
- fprintf(stderr, "%s: Cell name (%s) not recognized by AFS service",
- progname, realm_of_cell);
- break;
- case KTC_NOCM:
- fprintf(stderr, "%s: AFS service is unavailable", progname);
- break;
- default:
- fprintf(stderr, "%s: Undocumented error (%d) contacting AFS service", progname, status);
- break;
- }
- status = AKLOG_TOKEN;
- }
-#endif /* !WINDOWS */
}
else
if (dflag) {
return(status);
}
-#ifndef WINDOWS /* struct ViceIoctl missing */
-
static int get_afs_mountpoint(char *file, char *mountpoint, int size)
{
#ifdef AFS_SUN_ENV
? elast_comp - last_comp : strlen(last_comp);
strncat(pathtocheck, last_comp, len);
memset(linkbuf, 0, sizeof(linkbuf));
- if (link = (readlink(pathtocheck, linkbuf,
- sizeof(linkbuf)) > 0)) {
+ if ((link = (readlink(pathtocheck, linkbuf,
+ sizeof(linkbuf)) > 0))) {
if (++symlinkcount > MAXSYMLINKS) {
fprintf(stderr, "%s: %s\n", progname, strerror(ELOOP));
exit(AKLOG_BADPATH);
return(pathtocheck);
}
-#endif /* WINDOWS */
-
#if 0
/*****************************************/
int dee_gettokens()
/*****************************************/
#endif
-#ifndef WINDOWS /* struct ViceIoctl missing */
-
static void add_hosts(char *file)
{
#ifdef AFS_SUN_ENV
}
}
-#endif /* WINDOWS */
-
-#ifndef WINDOWS /* next_path(), get_afs_mountpoint() */
-
/*
* This routine descends through a path to a directory, logging to
* every cell it encounters along the way.
return(status);
}
-#endif /* WINDOWS */
-
/* Print usage message and exit */
static void usage(void)
"[-d] [[-cell | -c] cell [-k krb_realm]] ",
"[[-p | -path] pathname]\n",
" [-zsubs] [-hosts] [-noauth] [-noprdb] [-force] [-setpag] \n"
- " [-linked] [-524]\n");
+ " [-linked]"
+#ifndef HAVE_NO_KRB5_524
+ " [-524]"
+#endif
+ "\n");
fprintf(stderr, " -d gives debugging information.\n");
fprintf(stderr, " krb_realm is the kerberos realm of a cell.\n");
fprintf(stderr, " pathname is the name of a directory to which ");
fprintf(stderr, " -force means replace identical tickets. \n");
fprintf(stderr, " -linked means if AFS node is linked, try both. \n");
fprintf(stderr, " -setpag set the AFS process authentication group.\n");
+#ifndef HAVE_NO_KRB5_524
fprintf(stderr, " -524 means use the 524 converter instead of V5 directly\n");
+#endif
fprintf(stderr, " No commandline arguments means ");
fprintf(stderr, "authenticate to the local cell.\n");
fprintf(stderr, "\n");
void aklog(int argc, char *argv[])
{
- krb5_context context;
+ krb5_context context;
int status = AKLOG_SUCCESS;
int i;
int somethingswrong = FALSE;
progname = argv[0];
krb5_init_context(&context);
-#ifndef WINDOWS
- initialize_ktc_error_table ();
-#endif
+ initialize_ktc_error_table ();
+ afs_set_com_err_hook(redirect_errors);
/* Initialize list of cells to which we have authenticated */
(void)ll_init(&authedcells);
linked++;
else if (strcmp(argv[i], "-force") == 0)
force++;
+#ifndef HAVE_NO_KRB5_524
else if (strcmp(argv[i], "-524") == 0)
do524++;
+#endif
else if (strcmp(argv[i], "-setpag") == 0)
afssetpag++;
else if (((strcmp(argv[i], "-cell") == 0) ||
}
else
usage();
+ else if ((strcmp(argv[i], "-keytab") == 0))
+ if (++i < argc) {
+ keytab = argv[i];
+ }
+ else
+ usage();
+ else if ((strcmp(argv[i], "-principal") == 0))
+ if (++i < argc) {
+ client = argv[i];
+ }
+ else
+ usage();
else if (((strcmp(argv[i], "-path") == 0) ||
(strcmp(argv[i], "-p") == 0)) && !cmode)
-#ifndef WINDOWS
if (++i < argc) {
pmode++;
strcpy(path, argv[i]);
}
else
usage();
-#else /* WINDOWS */
- {
- fprintf(stderr, "%s: path mode not supported.\n", progname);
- exit(AKLOG_MISC);
- }
-#endif /* WINDOWS */
else if (argv[i][0] == '-')
usage();
else if (!pmode && !cmode) {
if (strchr(argv[i], DIR) || (strcmp(argv[i], ".") == 0) ||
(strcmp(argv[i], "..") == 0)) {
-#ifndef WINDOWS
pmode++;
strcpy(path, argv[i]);
-#else /* WINDOWS */
- fprintf(stderr, "%s: path mode not supported.\n", progname);
- exit(AKLOG_MISC);
-#endif /* WINDOWS */
}
else {
cmode++;
memset(cell, 0, sizeof(cell));
memset(realm, 0, sizeof(realm));
}
-#ifndef WINDOWS
else if (pmode) {
/* Add this path to list of paths */
if ((cur_node = ll_add_node(&paths, ll_tail))) {
- char *new_path;
- if ((new_path = copy_string(path)))
+ char *new_path;
+ if ((new_path = strdup(path)))
ll_add_data(cur_node, new_path);
else {
fprintf(stderr, "%s: failure copying path name.\n",
pmode = FALSE;
memset(path, 0, sizeof(path));
}
-#endif /* WINDOWS */
}
/*
status = auth_to_cell(context, linkedcell2, NULL);
}
-#ifndef WINDOWS
/*
* Local hack - if the person has a file in their home
* directory called ".xlog", read that for a list of
}
}
}
-#endif /* WINDOWS */
}
else {
/* Log to all cells in the cells list first */
}
}
-#ifndef WINDOWS
/* Then, log to all paths in the paths list */
for (cur_node = paths.first; cur_node; cur_node = cur_node->next) {
if ((status = auth_to_path(context, cur_node->data)))
somethingswrong++;
}
-#endif /* WINDOWS */
/*
* If only one thing was logged to, we'll return the status
exit(status);
}
-#ifndef HAVE_ADD_TO_ERROR_TABLE
-
-#define error_table error_table_compat
-#include <afs/error_table.h>
-#undef error_table
-
-#ifndef HAVE_ADD_ERROR_TABLE
-void add_error_table (const struct error_table *);
-#endif /* !HAVE_ADD_ERROR_TABLE */
-
-void
-add_to_error_table(struct et_list *new_table)
-{
- add_error_table((struct error_table *) new_table->table);
-}
-#endif /* HAVE_ADD_TO_ERROR_TABLE */
-
static int isdir(char *path, unsigned char *val)
{
struct stat statbuf;
}
}
+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)
+ char *name, char *inst, char *realm,
+ krb5_creds **creds)
{
krb5_creds increds;
krb5_error_code r;
static krb5_principal client_principal = 0;
- memset((char *)&increds, 0, sizeof(increds));
+ if (dflag) {
+ printf("Getting tickets: %s%s%s@%s\n", name, (inst && inst[0])
+ ? "/" : "", inst ? inst : "", realm);
+ }
+
+ memset(&increds, 0, sizeof(increds));
/* ANL - instance may be ptr to a null string. Pass null then */
if ((r = krb5_build_principal(context, &increds.server,
- strlen(realm), realm,
- name,
- (inst && strlen(inst)) ? inst : (void *) NULL,
- (void *) NULL))) {
+ strlen(realm), realm,
+ name,
+ (inst && strlen(inst)) ? inst : (void *) NULL,
+ (void *) NULL))) {
return r;
}
+
if (!_krb425_ccache) {
r = krb5_cc_default(context, &_krb425_ccache);
return r;
}
if (!client_principal) {
- r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
+ if (client) {
+ r = krb5_parse_name(context, client, &client_principal);
+ } else {
+ r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
+ }
if (r)
return r;
}
-
+
increds.client = client_principal;
increds.times.endtime = 0;
- /* Ask for DES since that is what V4 understands */
+ /* Ask for DES since that is what V4 understands */
get_creds_enctype((&increds)) = ENCTYPE_DES_CBC_CRC;
-
- r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds);
-
+
+ if (keytab) {
+ int allowed_enctypes[] = {
+ ENCTYPE_DES_CBC_CRC, 0
+ };
+
+ r = get_credv5_akimpersonate(context,
+ keytab,
+ increds.server,
+ increds.client,
+ 300, ((~0U)>>1),
+ allowed_enctypes,
+ 0 /* paddress */,
+ creds /* out */);
+ } else {
+ r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds);
+ }
return r;
}
{
static krb5_principal client_principal = 0;
int i;
+ krb5_error_code r = 0;
if (!_krb425_ccache)
krb5_cc_default(context, &_krb425_ccache);
- if (!client_principal)
- krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
+ if (!client_principal) {
+ if (client) {
+ r = krb5_parse_name(context, client, &client_principal);
+ } else {
+ r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
+ }
+ if (r)
+ return r;
+ }
i = realm_len(context, client_principal);
if (i > REALM_SZ-1) i = REALM_SZ-1;
strncpy(realm,realm_data(context, client_principal), i);
realm[i] = 0;
- return(0);
+ return(r);
}