/* * decomp_tkt.c * * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute * of Technology. * * For copying and distribution information, please see the file * . */ #include "mit-copyright.h" #include "des.h" #include "krb.h" #include "prot.h" #include #include #ifdef KRB_CRYPT_DEBUG extern int krb_debug; #endif static int dcmp_tkt_int PROTOTYPE((KTEXT tkt, unsigned char *flags, char *pname, char *pinstance, char *prealm, unsigned KRB4_32 *paddress, C_Block session, int *life, unsigned KRB4_32 *time_sec, char *sname, char *sinstance, C_Block key, Key_schedule key_s, krb5_keyblock *k5key)); /* * This routine takes a ticket and pointers to the variables that * should be filled in based on the information in the ticket. It #ifndef NOENCRYPTION * decrypts the ticket using the given key, and #endif * fills in values for its arguments. * * Note: if the client realm field in the ticket is the null string, * then the "prealm" variable is filled in with the local realm (as * defined by KRB_REALM). * * If the ticket byte order is different than the host's byte order * (as indicated by the byte order bit of the "flags" field), then * the KDC timestamp "time_sec" is byte-swapped. The other fields * potentially affected by byte order, "paddress" and "session" are * not byte-swapped. * * The routine returns KFAILURE if any of the "pname", "pinstance", * or "prealm" fields is too big, otherwise it returns KSUCCESS. * * The corresponding routine to generate tickets is create_ticket. * When changes are made to this routine, the corresponding changes * should also be made to that file. * * See create_ticket.c for the format of the ticket packet. */ int decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session, life, time_sec, sname, sinstance, key, key_s) KTEXT tkt; /* The ticket to be decoded */ unsigned char *flags; /* Kerberos ticket flags */ char *pname; /* Authentication name */ char *pinstance; /* Principal's instance */ char *prealm; /* Principal's authentication domain */ unsigned KRB4_32 *paddress; /* Net address of entity * requesting ticket */ C_Block session; /* Session key inserted in ticket */ int *life; /* Lifetime of the ticket */ unsigned KRB4_32 *time_sec; /* Issue time and date */ char *sname; /* Service name */ char *sinstance; /* Service instance */ C_Block key; /* Service's secret key * (to decrypt the ticket) */ Key_schedule key_s; /* The precomputed key schedule */ { return dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, life, time_sec, sname, sinstance, key, key_s, NULL); } int decomp_tkt_krb5(tkt, flags, pname, pinstance, prealm, paddress, session, life, time_sec, sname, sinstance, k5key) KTEXT tkt; /* The ticket to be decoded */ unsigned char *flags; /* Kerberos ticket flags */ char *pname; /* Authentication name */ char *pinstance; /* Principal's instance */ char *prealm; /* Principal's authentication domain */ unsigned KRB4_32 *paddress; /* Net address of entity * requesting ticket */ C_Block session; /* Session key inserted in ticket */ int *life; /* Lifetime of the ticket */ unsigned KRB4_32 *time_sec; /* Issue time and date */ char *sname; /* Service name */ char *sinstance; /* Service instance */ krb5_keyblock *k5key; /* krb5 keyblock of service */ { C_Block key; /* placeholder; doesn't get used */ Key_schedule key_s; /* placeholder; doesn't get used */ return dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, life, time_sec, sname, sinstance, key, key_s, k5key); } static int dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, life, time_sec, sname, sinstance, key, key_s, k5key) KTEXT tkt; /* The ticket to be decoded */ unsigned char *flags; /* Kerberos ticket flags */ char *pname; /* Authentication name */ char *pinstance; /* Principal's instance */ char *prealm; /* Principal's authentication domain */ unsigned KRB4_32 *paddress; /* Net address of entity * requesting ticket */ C_Block session; /* Session key inserted in ticket */ int *life; /* Lifetime of the ticket */ unsigned KRB4_32 *time_sec; /* Issue time and date */ char *sname; /* Service name */ char *sinstance; /* Service instance */ C_Block key; /* Service's secret key * (to decrypt the ticket) */ Key_schedule key_s; /* The precomputed key schedule */ krb5_keyblock *k5key; /* krb5 keyblock of service */ { static int tkt_swap_bytes; unsigned char *uptr; char *ptr = (char *)tkt->dat; #ifndef NOENCRYPTION /* Do the decryption */ #ifdef KRB_CRYPT_DEBUG if (krb_debug) { FILE *fp; char *keybuf[BUFSIZ]; /* Avoid secret stuff in stdio buffers */ fp = fopen("/kerberos/tkt.des", "wb"); setbuf(fp, keybuf); fwrite(tkt->dat, 1, tkt->length, fp); fclose(fp); memset(keybuf, 0, sizeof(keybuf)); /* Clear the buffer */ } #endif if (k5key != NULL) { /* block locals */ krb5_enc_data in; krb5_data out; krb5_error_code ret; in.enctype = k5key->enctype; in.kvno = 0; in.ciphertext.length = tkt->length; in.ciphertext.data = tkt->dat; out.length = tkt->length; out.data = malloc(tkt->length); if (out.data == NULL) return KFAILURE; /* XXX maybe ENOMEM? */ /* XXX note the following assumes that context arg isn't used */ ret = krb5_c_decrypt(NULL, k5key, KRB5_KEYUSAGE_KDC_REP_TICKET, NULL, &in, &out); if (ret) { free(out.data); return KFAILURE; } else { memcpy(tkt->dat, out.data, out.length); memset(out.data, 0, out.length); free(out.data); } } else { pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat, (long) tkt->length,key_s,(C_Block *) key,0); } #endif /* ! NOENCRYPTION */ #ifdef KRB_CRYPT_DEBUG if (krb_debug) { FILE *fp; char *keybuf[BUFSIZ]; /* Avoid secret stuff in stdio buffers */ fp = fopen("/kerberos/tkt.clear", "wb"); setbuf(fp, keybuf); fwrite(tkt->dat, 1, tkt->length, fp); fclose(fp); memset(keybuf, 0, sizeof(keybuf)); /* Clear the buffer */ } #endif *flags = *ptr; /* get flags byte */ ptr += sizeof(*flags); tkt_swap_bytes = 0; if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1)) tkt_swap_bytes++; if (strlen(ptr) >= ANAME_SZ) return(KFAILURE); (void) strcpy(pname,ptr); /* pname */ ptr += strlen(pname) + 1; if (strlen(ptr) >= INST_SZ) return(KFAILURE); (void) strcpy(pinstance,ptr); /* instance */ ptr += strlen(pinstance) + 1; if (strlen(ptr) >= REALM_SZ) return(KFAILURE); (void) strcpy(prealm,ptr); /* realm */ ptr += strlen(prealm) + 1; /* temporary hack until realms are dealt with properly */ if (*prealm == 0) (void) strcpy(prealm,KRB_REALM); memcpy((char *)paddress, ptr, 4); /* net address */ ptr += 4; memcpy((char *)session, ptr, 8); /* session key */ ptr+= 8; #ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */ if (tkt_swap_bytes) swap_C_Block(session); #endif /* get lifetime, being certain we don't get negative lifetimes */ uptr = (unsigned char *) ptr++; *life = (int) *uptr; memcpy((char *) time_sec, ptr, 4); /* issue time */ ptr += 4; if (tkt_swap_bytes) *time_sec = krb4_swab32(*time_sec); if (strlen(ptr) >= ANAME_SZ) return KFAILURE; (void) strcpy(sname,ptr); /* service name */ ptr += 1 + strlen(sname); if (strlen (ptr) >= INST_SZ) return KFAILURE; (void) strcpy(sinstance,ptr); /* instance */ ptr += 1 + strlen(sinstance); #ifdef KRB_CRYPT_DEBUG if (krb_debug) { krb_log("service=%s.%s len(sname)=%d, len(sinstance)=%d", sname, sinstance, strlen(sname), strlen(sinstance)); krb_log("ptr - tkt->dat=%d",(char *)ptr - (char *)tkt->dat); } #endif return(KSUCCESS); }