From 9dc762e8e637089b8546bd73320cea998c8496a0 Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Fri, 27 Oct 2006 00:39:15 +0000 Subject: [PATCH] k5-klog-20061026 k5 version of klog --- src/aklog/Makefile.in | 7 +- src/aklog/add_etbl.c | 19 ++ src/aklog/klog.c | 738 ++++++++++++++++++++++++++++++++++++++++++ src/aklog/skipwrap.c | 124 +++++++ 4 files changed, 886 insertions(+), 2 deletions(-) create mode 100644 src/aklog/add_etbl.c create mode 100644 src/aklog/klog.c create mode 100644 src/aklog/skipwrap.c diff --git a/src/aklog/Makefile.in b/src/aklog/Makefile.in index 769326566..19086bc61 100644 --- a/src/aklog/Makefile.in +++ b/src/aklog/Makefile.in @@ -20,7 +20,7 @@ AFSLIBS = ${TOP_LIBDIR}/libprot.a ${TOP_LIBDIR}/libauth.a \ SRCS= aklog.c aklog_main.c krb_util.c linked_list.c OBJS= aklog.o aklog_main.o krb_util.o linked_list.o -all: aklog @ASETKEY@ +all: aklog @ASETKEY@ klog aklog: ${OBJS} ${AFSLIBS} ${CC} -o $@ ${CFLAGS} ${OBJS} ${AKLIBS} ${AFSLIBS} ${XLIBS} @@ -28,6 +28,9 @@ aklog: ${OBJS} ${AFSLIBS} asetkey: asetkey.o ${AFSLIBS} ${CC} -o $@ ${CFLAGS} asetkey.o ${AKLIBS} ${AFSLIBS} ${XLIBS} +klog: klog.o skipwrap.o ${AFSLIBS} + ${CC} -o $@ ${CFLAGS} klog.o skipwrap.o ${AKLIBS} ${AFSLIBS} ${TOP_LIBDIR}/libcmd.a ${XLIBS} + # # Installation targets # @@ -51,6 +54,6 @@ dest: aklog @ASETKEY@ # Misc. targets # clean: - $(RM) -f *.o ${OBJS} aklog asetkey + $(RM) -f *.o ${OBJS} aklog asetkey klog include ../config/Makefile.version diff --git a/src/aklog/add_etbl.c b/src/aklog/add_etbl.c new file mode 100644 index 000000000..d862af3a9 --- /dev/null +++ b/src/aklog/add_etbl.c @@ -0,0 +1,19 @@ +#include +#ifndef HAVE_ADD_TO_ERROR_TABLE +#include +#include + +/* #define error_table error_table_compat */ +#include +/* #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 */ diff --git a/src/aklog/klog.c b/src/aklog/klog.c new file mode 100644 index 000000000..67d5a2972 --- /dev/null +++ b/src/aklog/klog.c @@ -0,0 +1,738 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +#include +#include + +#include +#include +#include +#ifdef AFS_AIX32_ENV +#include +#endif +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#include + +#include +#include + +#include +#include +#if 0 +#include +#endif +#include +#include +#include +#ifdef AFS_RXK5 +#include "rxk5_utilafs.h" +#endif +#include +#include +#include + +#ifdef HAVE_KRB5_CREDS_KEYBLOCK +#define USING_MIT 1 +#endif +#ifdef HAVE_KRB5_CREDS_SESSION +#define USING_HEIMDAL 1 +#endif + +#ifndef USING_HEIMDAL +extern krb5_cc_ops krb5_mcc_ops; +#endif + +#include "assert.h" + + +/* This code borrowed heavily from the previous version of log. Here is the + intro comment for that program: */ + +/* + log -- tell the Andrew Cache Manager your password + 5 June 1985 + modified + February 1986 + + Further modified in August 1987 to understand cell IDs. + + Further modified in October 2006 to understand kerberos 5. + */ + +/* Current Usage: + klog [principal [password]] [-t] [-c cellname] [-k ] + + where: + principal is of the form 'name' or 'name@cell' which provides the + cellname. See the -c option below. + password is the user's password. This form is NOT recommended for + interactive users. + -t advises klog to write a Kerberos style ticket file in /tmp. + -c identifies cellname as the cell in which authentication is to take + place. + -k identifies an alternate kerberos realm to use provide + authentication services for the cell. + */ + +#define KLOGEXIT(code) rx_Finalize(); \ + (exit(!!code)) +extern int CommandProc(struct cmd_syndesc *as, char *arock); + +static int zero_argc; +static char **zero_argv; + +static krb5_context k5context; +static struct afsconf_dir *tdir; +static int always_evil = 2; /* gcc optimizes 0 into bss. fools. */ + +int +main(int argc, char *argv[]) +{ + struct cmd_syndesc *ts; + afs_int32 code; +#ifdef AFS_AIX32_ENV + /* + * The following signal action for AIX is necessary so that in case of a + * crash (i.e. core is generated) we can include the user's data section + * in the core dump. Unfortunately, by default, only a partial core is + * generated which, in many cases, isn't too useful. + */ + struct sigaction nsa; + + sigemptyset(&nsa.sa_mask); + nsa.sa_handler = SIG_DFL; + nsa.sa_flags = SA_FULLDUMP; + sigaction(SIGABRT, &nsa, NULL); + sigaction(SIGSEGV, &nsa, NULL); +#endif + zero_argc = argc; + zero_argv = argv; + + ts = cmd_CreateSyntax(NULL, CommandProc, 0, + "obtain Kerberos authentication"); + +#define aXFLAG 0 +#define aPRINCIPAL 1 +#define aPASSWORD 2 +#define aCELL 3 +#define aKRBREALM 4 +#define aPIPE 5 +#define aSILENT 6 +#define aLIFETIME 7 +#define aSETPAG 8 +#define aTMP 9 +#define aNOPRDB 10 +#define aUNWRAP 11 +#define aK5 12 +#define aK4 13 + + cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, 0); + cmd_Seek(ts, aPRINCIPAL); + cmd_AddParm(ts, "-principal", CMD_SINGLE, CMD_OPTIONAL, "user name"); + cmd_AddParm(ts, "-password", CMD_SINGLE, CMD_OPTIONAL, "user's password"); + cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name"); + cmd_AddParm(ts, "-k", CMD_SINGLE, CMD_OPTIONAL, "krb5 realm"); + cmd_AddParm(ts, "-pipe", CMD_FLAG, CMD_OPTIONAL, + "read password from stdin"); + cmd_AddParm(ts, "-silent", CMD_FLAG, CMD_OPTIONAL, "silent operation"); + cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, + "ticket lifetime in hh[:mm[:ss]]"); + cmd_AddParm(ts, "-setpag", CMD_FLAG, CMD_OPTIONAL, + "Create a new setpag before authenticating"); + cmd_AddParm(ts, "-tmp", CMD_FLAG, CMD_OPTIONAL, + "write Kerberos-style ticket file in /tmp"); + cmd_AddParm(ts, "-noprdb", CMD_FLAG, CMD_OPTIONAL, "don't consult pt"); + cmd_AddParm(ts, "-unwrap", CMD_FLAG, CMD_OPTIONAL, "perform 524d conversion"); +#ifdef AFS_RXK5 + cmd_AddParm(ts, "-k5", CMD_FLAG, CMD_OPTIONAL, "get rxk5 credentials"); + cmd_AddParm(ts, "-k4", CMD_FLAG, CMD_OPTIONAL, "get rxkad credentials"); +#else + ++ts->nParms; /* skip -k5 */ + cmd_AddParm(ts, "-k4", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, 0); +#endif + + code = cmd_Dispatch(argc, argv); + KLOGEXIT(code); +} + +static char * +getpipepass(void) +{ + static char gpbuf[BUFSIZ]; + /* read a password from stdin, stop on \n or eof */ + register int i, tc; + memset(gpbuf, 0, sizeof(gpbuf)); + for (i = 0; i < (sizeof(gpbuf) - 1); i++) { + tc = fgetc(stdin); + if (tc == '\n' || tc == EOF) + break; + gpbuf[i] = tc; + } + return gpbuf; +} + +void +silent_errors(const char *who, + afs_int32 code, + const char *fmt, + va_list ap) +{ + /* ignore and don't print error */ +} + +#if defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size) + +#define get_princ_str(c, p, n) krb5_princ_component(c, p, n)->data +#define get_princ_len(c, p, n) krb5_princ_component(c, p, n)->length +#define num_comp(c, p) (krb5_princ_size(c, p)) +#define realm_data(c, p) krb5_princ_realm(c, p)->data +#define realm_len(c, p) krb5_princ_realm(c, p)->length + +#elif defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) + +#define get_princ_str(c, p, n) krb5_principal_get_comp_string(c, p, n) +#define get_princ_len(c, p, n) strlen(krb5_principal_get_comp_string(c, p, n)) +#define num_comp(c, p) ((p)->name.name_string.len) +#define realm_data(c, p) krb5_realm_data(krb5_principal_get_realm(c, p)) +#define realm_len(c, p) krb5_realm_length(krb5_principal_get_realm(c, p)) + +#else +#error "Must have either krb5_princ_size or krb5_principal_get_comp_string" +#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 + +static int +whoami(struct ktc_token *atoken, + struct afsconf_cell *cellconfig, + struct ktc_principal *aclient, + int *vicep) +{ + int scIndex; + int code; + int i; + struct ubik_client *ptconn = 0; + struct rx_securityClass *sc; + struct rx_connection *conns[MAXSERVERS+1]; + idlist lids[1]; + namelist lnames[1]; + char tempname[PR_MAXNAMELEN + 1]; + + memset(lnames, 0, sizeof *lnames); + memset(lids, 0, sizeof *lids); + scIndex = 2; + sc = rxkad_NewClientSecurityObject(rxkad_auth, + &atoken->sessionKey, atoken->kvno, + atoken->ticketLen, atoken->ticket); + for (i = 0; i < cellconfig->numServers; ++i) + conns[i] = rx_NewConnection(cellconfig->hostAddr[i].sin_addr.s_addr, + cellconfig->hostAddr[i].sin_port, PRSRV, sc, scIndex); + conns[i] = 0; + ptconn = 0; + if ((code = ubik_ClientInit(conns, &ptconn))) + goto Failed; + if (*aclient->instance) + snprintf (tempname, sizeof tempname, "%s.%s", + aclient->name, aclient->instance); + else + snprintf (tempname, sizeof tempname, "%s", aclient->name); + lnames->namelist_len = 1; + lnames->namelist_val = (prname *) tempname; + code = ubik_PR_NameToID(ptconn, 0, lnames, lids); + if (lids->idlist_val) { + *vicep = *lids->idlist_val; + } +Failed: + if (lids->idlist_val) free(lids->idlist_val); + if (ptconn) ubik_ClientDestroy(ptconn); + return code; +} + +static void +k5_to_k4_name(krb5_context k5context, + krb5_principal k5princ, + struct ktc_principal *ktcprinc) +{ + int i; + + switch(num_comp(k5context, k5princ)) { + default: + /* case 2: */ + i = get_princ_len(k5context, k5princ, 1); + if (i > MAXKTCNAMELEN-1) i = MAXKTCNAMELEN-1; + memcpy(ktcprinc->instance, get_princ_str(k5context, k5princ, 1), i); + /* fall through */ + case 1: + i = get_princ_len(k5context, k5princ, 0); + if (i > MAXKTCNAMELEN-1) i = MAXKTCNAMELEN-1; + memcpy(ktcprinc->name, get_princ_str(k5context, k5princ, 0), i); + /* fall through */ + case 0: + break; + } +} + +/* save and reuse password. This is necessary to make + * "direct to service" authentication work with most + * flavors of kerberos, when the afs principal has no instance. + */ +struct kp_arg { + char **pp, *pstore; +}; +krb5_error_code +klog_prompter(krb5_context context, + void *a, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) +{ + krb5_error_code code; + int i, type; +#ifndef USING_HEIMDAL + krb5_prompt_type *types; +#endif + struct kp_arg *kparg = (struct kp_arg *) a; + code = krb5_prompter_posix(context, a, name, banner, num_prompts, prompts); + if (code) return code; +#ifndef USING_HEIMDAL + if ((types = krb5_get_prompt_types(context))) +#endif + for (i = 0; i < num_prompts; ++i) { +#ifdef USING_HEIMDAL + type = prompts[i].type; +#else + type = types[i]; +#endif +#if 0 + printf ("i%d t%d <%.*s>\n", i, +type, +prompts[i].reply->length, +prompts[i].reply->data); +#endif + switch(type) { + case KRB5_PROMPT_TYPE_PASSWORD: + case KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN: + memcpy(kparg->pstore, prompts[i].reply->data, prompts[i].reply->length); + kparg->pstore[prompts[i].reply->length] = 0; + *kparg->pp = kparg->pstore; + } + } + return 0; +} + +int +CommandProc(struct cmd_syndesc *as, char *arock) +{ + krb5_principal princ = 0; + char *cell, *pname, **hrealms, *service; + char service_temp[MAXKTCREALMLEN + 20]; + char realm[MAXKTCREALMLEN]; + char lrealm[MAXKTCREALMLEN]; /* uppercase copy of local cellname */ + krb5_creds incred[1], mcred[1], *outcred = 0, *afscred; + krb5_ccache cc = 0; + krb5_get_init_creds_opt gic_opts[1]; + char *tofree, *outname; + int code; + char *what; + int i, dosetpag, evil, noprdb, id; +#ifdef AFS_RXK5 + int authtype; +#endif + krb5_data enc_part[1]; + time_t lifetime; /* requested ticket lifetime */ + krb5_prompter_fct pf = NULL; + char *pass = 0; + char *pa = 0; + struct kp_arg klog_arg[1]; + + char passwd[BUFSIZ]; + struct afsconf_cell cellconfig[1]; + + static char rn[] = "klog"; /*Routine name */ + static int Pipe = 0; /* reading from a pipe */ + static int Silent = 0; /* Don't want error messages */ + + int local; /* explicit cell is same a local one */ + int writeTicketFile = 0; /* write ticket file to /tmp */ + + char *reason; /* string describing errors */ + + service = 0; + memset(incred, 0, sizeof *incred); + /* blow away command line arguments */ + for (i = 1; i < zero_argc; i++) + memset(zero_argv[i], 0, strlen(zero_argv[i])); + zero_argc = 0; + memset(klog_arg, 0, sizeof *klog_arg); + + /* first determine quiet flag based on -silent switch */ + Silent = (as->parms[aSILENT].items ? 1 : 0); + + if (Silent) { + set_com_err_hook(silent_errors); + } + + if ((code = krb5_init_context(&k5context))) { + com_err(rn, code, "while initializing Kerberos 5 library"); + KLOGEXIT(code); + } + if ((code = rx_Init(0))) { + com_err(rn, code, "while initializing rx"); + KLOGEXIT(code); + } + initialize_U_error_table(); + initialize_krb5_error_table(); + initialize_RXK_error_table(); + initialize_KTC_error_table(); + initialize_ACFG_error_table(); + /* initialize_rx_error_table(); */ + if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) { + com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))", + rn, AFSDIR_CLIENT_ETC_DIRPATH); + KLOGEXIT(1); + } + + /* Parse remaining arguments. */ + + dosetpag = !! as->parms[aSETPAG].items; + Pipe = !! as->parms[aPIPE].items; + writeTicketFile = !! as->parms[aTMP].items; + noprdb = !! as->parms[aNOPRDB].items; + evil = (always_evil&1) || !! as->parms[aUNWRAP].items; + +#ifdef AFS_RXK5 + authtype = 0; + if (as->parms[aK5].items) + authtype |= FORCE_RXK5; + if (as->parms[aK4].items) + authtype |= FORCE_RXKAD; + if (!authtype) + authtype |= env_afs_rxk5_default(); +#endif + + cell = as->parms[aCELL].items ? cell = as->parms[aCELL].items->data : 0; + if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) { + if (cell) + com_err(rn, code, "Can't get cell information for '%s'", cell); + else + com_err(rn, code, "Can't get determine local cell!"); + KLOGEXIT(code); + } + + if (as->parms[aKRBREALM].items) { + code = krb5_set_default_realm(k5context, + (const char *) as->parms[aKRBREALM].items); + if (code) { + com_err(rn, code, "Can't make <%s> the default realm", + as->parms[aKRBREALM].items); + KLOGEXIT(code); + } + } + else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) { + com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n", + cellconfig->hostName[0], cellconfig->name); + KLOGEXIT(code); + } else { + if (hrealms && *hrealms) { + code = krb5_set_default_realm(k5context, + *hrealms); + if (code) { + com_err(rn, code, "Can't make <%s> the default realm", + *hrealms); + KLOGEXIT(code); + } + } + if (hrealms) krb5_free_host_realm(k5context, hrealms); + } + + id = getuid(); + if (as->parms[aPRINCIPAL].items) { + pname = as->parms[aPRINCIPAL].items->data; + } else { + /* No explicit name provided: use Unix uid. */ + struct passwd *pw; + pw = getpwuid(id); + if (pw == 0) { + com_err(rn, 0, + "Can't figure out your name from your user id (%d).", id); + if (!Silent) + fprintf(stderr, "%s: Try providing the user name.\n", rn); + KLOGEXIT(1); + } + pname = pw->pw_name; + } + code = krb5_parse_name(k5context, pname, &princ); + if (code) { + com_err(rn, code, "Can't parse principal <%s>", pname); + KLOGEXIT(code); + } + + if (as->parms[aPASSWORD].items) { + /* + * Current argument is the desired password string. Remember it in + * our local buffer, and zero out the argument string - anyone can + * see it there with ps! + */ + strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd)); + memset(as->parms[aPASSWORD].items->data, 0, + strlen(as->parms[aPASSWORD].items->data)); + pass = passwd; + } + + if (as->parms[aLIFETIME].items) { + char *life = as->parms[aLIFETIME].items->data; + char *sp; /* string ptr to rest of life */ + lifetime = 3600 * strtol(life, &sp, 0); /* hours */ + if (sp == life) { + bad_lifetime: + if (!Silent) + fprintf(stderr, "%s: translating '%s' to lifetime failed\n", + rn, life); + return 1; + } + if (*sp == ':') { + life = sp + 1; /* skip the colon */ + lifetime += 60 * strtol(life, &sp, 0); /* minutes */ + if (sp == life) + goto bad_lifetime; + if (*sp == ':') { + life = sp + 1; + lifetime += strtol(life, &sp, 0); /* seconds */ + if (sp == life) + goto bad_lifetime; + if (*sp) + goto bad_lifetime; + } else if (*sp) + goto bad_lifetime; + } else if (*sp) + goto bad_lifetime; + } else + lifetime = 0; + + /* Get the password if it wasn't provided. */ + if (!pass) { + if (Pipe) { + strncpy(passwd, getpipepass(), sizeof(passwd)); + pass = passwd; + } else { + pf = klog_prompter; + pa = klog_arg; + } + } + + service = 0; +#ifdef AFS_RXK5 + if (authtype & FORCE_RXK5) { + tofree = get_afs_krb5_svc_princ(cellconfig); + snprintf(service_temp, sizeof service_temp, "%s", tofree); + } else +#endif + snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name); + if (writeTicketFile) + service = 0; + else + service = service_temp; + + klog_arg->pp = &pass; + klog_arg->pstore = passwd; + /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/ + krb5_get_init_creds_opt_init(gic_opts); + for (;;) { + code = krb5_get_init_creds_password(k5context, + incred, + princ, + pass, + pf, /* prompter */ + pa, /* data */ + 0, /* start_time */ + service, /* in_tkt_service */ + gic_opts); + if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break; +#ifdef AFS_RXK5 + if (authtype & FORCE_RXK5) break; +#endif + service = "afs"; + } + memset(passwd, 0, sizeof(passwd)); + if (code) { + char *r = 0; + if (krb5_get_default_realm(k5context, &r)) + r = 0; + if (service) + com_err(rn, code, "Unable to authenticate to use %s", service); + else if (r) + com_err(rn, code, "Unable to authenticate in realm %s", r); + else + com_err(rn, code, "Unable to authenticate to use cell %s", + cellconfig->name); + if (r) free(r); + KLOGEXIT(code); + } + + if (service) { + afscred = incred; + } else { + for (;;writeTicketFile = 0) { + if (writeTicketFile) { + what = "getting default ccache"; + code = krb5_cc_default(k5context, &cc); + } else { + what = "krb5_cc_register"; + code = krb5_cc_register(k5context, &krb5_mcc_ops, FALSE); + if (code && code != KRB5_CC_TYPE_EXISTS) goto Failed; + what = "krb5_cc_resolve"; + code = krb5_cc_resolve(k5context, "MEMORY:core", &cc); + if (code) goto Failed; + } + what = "initializing ccache"; + code = krb5_cc_initialize(k5context, cc, princ); + if (code) goto Failed; + what = "writing Kerberos ticket file"; + code = krb5_cc_store_cred(k5context, cc, incred); + if (code) goto Failed; + if (writeTicketFile) + fprintf(stderr, + "Wrote ticket file to %s\n", + krb5_cc_get_name(k5context, cc)); + break; + Failed: + if (code) + com_err(rn, code, what); + if (writeTicketFile) { + if (cc) { + krb5_cc_close(k5context, cc); + cc = 0; + } + continue; + } + KLOGEXIT(code); + } + + for (service = service_temp;;service = "afs") { + memset(mcred, 0, sizeof *mcred); + mcred->client = princ; + code = krb5_parse_name(k5context, service, &mcred->server); + if (code) { + com_err(rn, code, "Unable to parse service <%s>\n", service); + KLOGEXIT(code); + } + if (tofree) { free(tofree); tofree = 0; } + if (!(code = krb5_unparse_name(k5context, mcred->server, &outname))) + tofree = outname; + else outname = service; + code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred); + krb5_free_principal(k5context, mcred->server); + if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break; +#ifdef AFS_RXK5 + if (authtype & FORCE_RXK5) break; +#endif + } + afscred = outcred; + } + if (code) { + com_err(rn, code, "Unable to get credentials to use %s", outname); + KLOGEXIT(code); + } + +#ifdef AFS_RXK5 + if (authtype & FORCE_RXK5) { + struct ktc_principal aserver[1]; + int viceid = 555; + + memset(aserver, 0, sizeof *aserver); + strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); + code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag); + if (code) { + com_err(rn, code, "Unable to store tokens for cell %s\n", + cellconfig->name); + KLOGEXIT(1); + } + } else +#endif + { + struct ktc_principal aserver[1], aclient[1]; + struct ktc_token atoken[1]; + + memset(atoken, 0, sizeof *atoken); + if (evil) { + atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY; + if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data, + afscred->ticket.length, &enc_part->data, + &enc_part->length)) { + com_err(rn, 0, "Can't unwrap %s AFS credential", + cellconfig->name); + KLOGEXIT(1); + } + } else { + atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5; + *enc_part = afscred->ticket; + } + atoken->startTime = afscred->times.starttime; + atoken->endTime = afscred->times.endtime; + memcpy(&atoken->sessionKey, get_cred_keydata(afscred), + get_cred_keylen(afscred)); + memcpy(atoken->ticket, enc_part->data, + atoken->ticketLen = enc_part->length); + memset(aserver, 0, sizeof *aserver); + strncpy(aserver->name, "afs", 4); + strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); + memset(aclient, 0, sizeof *aclient); + i = realm_len(k5context, afscred->client); + if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1; + memcpy(aclient->cell, realm_data(k5context, afscred->client), i); + if (!noprdb) { + int viceid; + k5_to_k4_name(k5context, afscred->client, aclient); + code = whoami(atoken, cellconfig, aclient, &viceid); + if (code) { + com_err(rn, code, "Can't get your viceid", cellconfig->name); + *aclient->name = 0; + } else + snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid); + } + if (!*aclient->name) + k5_to_k4_name(k5context, afscred->client, aclient); + code = ktc_SetToken(aserver, atoken, aclient, dosetpag); + if (code) { + com_err(rn, code, "Unable to store tokens for cell %s\n", + cellconfig->name); + KLOGEXIT(1); + } + } + + krb5_free_principal(k5context, princ); + krb5_free_cred_contents(k5context, incred); + if (outcred) krb5_free_creds(k5context, outcred); + if (cc) + krb5_cc_close(k5context, cc); + if (tofree) free(tofree); + + return 0; +} diff --git a/src/aklog/skipwrap.c b/src/aklog/skipwrap.c new file mode 100644 index 000000000..d920bd7d6 --- /dev/null +++ b/src/aklog/skipwrap.c @@ -0,0 +1,124 @@ + +/* + * Copyright (c) 2006 + * The Regents of the University of Michigan + * 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 University of + * Michigan 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 + * University of Michigan 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 University of Michigan as to its fitness for any + * purpose, and without warranty by the University of + * Michigan 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 University of Michigan 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 +#include +#include +#include +#include + +/* evil hack */ +#define SEQUENCE 16 +#define CONSTRUCTED 32 +#define APPLICATION 64 +#define CONTEXT_SPECIFIC 128 +static int skip_get_number(char **pp, size_t *lp, int *np) +{ + unsigned l; + int r, n, i; + char *p; + + l = *lp; + if (l < 1) { +#ifdef DEBUG + fprintf(stderr, "skip_bad_number: missing number\n"); +#endif + return -1; + } + p = *pp; + r = (unsigned char)*p; + ++p; --l; + if (r & 0x80) { + n = (r&0x7f); + if (l < n) { +#ifdef DEBUG + fprintf(stderr, "skip_bad_number: truncated number\n"); +#endif + return -1; + } + r = 0; + for (i = n; --i >= 0; ) { + r <<= 8; + r += (unsigned char)*p; + ++p; --l; + } + } + *np = r; + *pp = p; + *lp = l; + return 0; +} + +int +afs_krb5_skip_ticket_wrapper(char *tix, size_t tixlen, char **enc, size_t *enclen) +{ + char *p = tix; + size_t l = tixlen; + int code; + int num; + + if (l < 1) return -1; + if (*p != (char) (CONSTRUCTED+APPLICATION+1)) return -1; + ++p; --l; + if ((code = skip_get_number(&p, &l, &num))) return code; + if (l != num) return -1; + if (l < 1) return -1; + if (*p != (char)(CONSTRUCTED+SEQUENCE)) return -1; + ++p; --l; + if ((code = skip_get_number(&p, &l, &num))) return code; + if (l != num) return -1; + if (l < 1) return -1; + if (*p != (char)(CONSTRUCTED+CONTEXT_SPECIFIC+0)) return -1; + ++p; --l; + if ((code = skip_get_number(&p, &l, &num))) return code; + if (l < num) return -1; + l -= num; p += num; + if (l < 1) return -1; + if (*p != (char)(CONSTRUCTED+CONTEXT_SPECIFIC+1)) return -1; + ++p; --l; + if ((code = skip_get_number(&p, &l, &num))) return code; + if (l < num) return -1; + l -= num; p += num; + if (l < 1) return -1; + if (*p != (char)(CONSTRUCTED+CONTEXT_SPECIFIC+2)) return -1; + ++p; --l; + if ((code = skip_get_number(&p, &l, &num))) return code; + if (l < num) return -1; + l -= num; p += num; + if (l < 1) return -1; + if (*p != (char)(CONSTRUCTED+CONTEXT_SPECIFIC+3)) return -1; + ++p; --l; + if ((code = skip_get_number(&p, &l, &num))) return code; + if (l != num) return -1; + *enc = p; + *enclen = l; + return 0; +} -- 2.39.5