1/* 2 * $Id: kuam.c,v 1.4 2001-06-25 20:13:45 rufustfirefly Exp $ 3 * 4 * Copyright (c) 1990,1994 Regents of The University of Michigan. 5 * All Rights Reserved. See COPYRIGHT. 6 */ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif /* HAVE_CONFIG_H */ 11 12#ifdef UAM_AFSKRB 13 14#include <mit-copyright.h> 15#include <krb.h> 16#include <des.h> 17#include <prot.h> 18 19#include <stdio.h> 20#include <string.h> 21#include <errno.h> 22 23/* use the bsd time.h struct defs for PC too! */ 24#include <sys/time.h> 25#include <sys/types.h> 26 27int swap_bytes; 28 29/* 30 * krb_get_in_tkt() gets a ticket for a given principal to use a given 31 * service and stores the returned ticket and session key for future 32 * use. 33 * 34 * The "user", "instance", and "realm" arguments give the identity of 35 * the client who will use the ticket. The "service" and "sinstance" 36 * arguments give the identity of the server that the client wishes 37 * to use. (The realm of the server is the same as the Kerberos server 38 * to whom the request is sent.) The "life" argument indicates the 39 * desired lifetime of the ticket; the "key_proc" argument is a pointer 40 * to the routine used for getting the client's private key to decrypt 41 * the reply from Kerberos. The "decrypt_proc" argument is a pointer 42 * to the routine used to decrypt the reply from Kerberos; and "arg" 43 * is an argument to be passed on to the "key_proc" routine. 44 * 45 * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it 46 * returns an error code: If an AUTH_MSG_ERR_REPLY packet is returned 47 * by Kerberos, then the error code it contains is returned. Other 48 * error codes returned by this routine include INTK_PROT to indicate 49 * wrong protocol version, INTK_BADPW to indicate bad password (if 50 * decrypted ticket didn't make sense), INTK_ERR if the ticket was for 51 * the wrong server or the ticket store couldn't be initialized. 52 * 53 * The format of the message sent to Kerberos is as follows: 54 * 55 * Size Variable Field 56 * ---- -------- ----- 57 * 58 * 1 byte KRB_PROT_VERSION protocol version number 59 * 1 byte AUTH_MSG_KDC_REQUEST | message type 60 * HOST_BYTE_ORDER local byte order in lsb 61 * string user client's name 62 * string instance client's instance 63 * string realm client's realm 64 * 4 bytes tlocal.tv_sec timestamp in seconds 65 * 1 byte life desired lifetime 66 * string service service's name 67 * string sinstance service's instance 68 */ 69 70kuam_get_in_tkt(user, instance, realm, service, sinstance, life, rpkt ) 71 char *user; 72 char *instance; 73 char *realm; 74 char *service; 75 char *sinstance; 76 int life; 77 KTEXT rpkt; 78{ 79 KTEXT_ST pkt_st; 80 KTEXT pkt = &pkt_st; /* Packet to KDC */ 81 KTEXT_ST cip_st; 82 KTEXT cip = &cip_st; /* Returned Ciphertext */ 83 KTEXT_ST tkt_st; 84 KTEXT tkt = &tkt_st; /* Current ticket */ 85 unsigned char *v = pkt->dat; /* Prot vers no */ 86 unsigned char *t = (pkt->dat+1); /* Prot msg type */ 87 int msg_byte_order; 88 int kerror; 89 struct timeval t_local; 90 u_int32_t rep_err_code; 91 92 93 /* BUILD REQUEST PACKET */ 94 95 /* Set up the fixed part of the packet */ 96 *v = (unsigned char) KRB_PROT_VERSION; 97 *t = (unsigned char) AUTH_MSG_KDC_REQUEST; 98 *t |= HOST_BYTE_ORDER; 99 100 /* Now for the variable info */ 101 (void) strcpy((char *)(pkt->dat+2),user); /* aname */ 102 pkt->length = 3 + strlen(user); 103 (void) strcpy((char *)(pkt->dat+pkt->length), 104 instance); /* instance */ 105 pkt->length += 1 + strlen(instance); 106 (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */ 107 pkt->length += 1 + strlen(realm); 108 109 (void) gettimeofday(&t_local,(struct timezone *) 0); 110 /* timestamp */ 111 memcpy((pkt->dat+pkt->length), &(t_local.tv_sec), 4); 112 pkt->length += 4; 113 114 *(pkt->dat+(pkt->length)++) = (char) life; 115 (void) strcpy((char *)(pkt->dat+pkt->length),service); 116 pkt->length += 1 + strlen(service); 117 (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); 118 pkt->length += 1 + strlen(sinstance); 119 120 rpkt->length = 0; 121 122 /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */ 123 124 if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror); 125 126 /* check packet version of the returned packet */ 127 if (pkt_version(rpkt) != KRB_PROT_VERSION) 128 return(INTK_PROT); 129 130 /* Check byte order */ 131 msg_byte_order = pkt_msg_type(rpkt) & 1; 132 swap_bytes = 0; 133 if (msg_byte_order != HOST_BYTE_ORDER) { 134 swap_bytes++; 135 } 136 137 switch (pkt_msg_type(rpkt) & ~1) { 138 case AUTH_MSG_KDC_REPLY: 139 break; 140 case AUTH_MSG_ERR_REPLY: 141 memcpy(&rep_err_code,pkt_err_code(rpkt),4); 142 if (swap_bytes) swap_u_long(rep_err_code); 143 return((int)rep_err_code); 144 default: 145 return(INTK_PROT); 146 } 147 148 return( INTK_OK ); 149} 150 151kuam_set_in_tkt( user, instance, realm, service, sinstance, ptr) 152 char *user, *instance, *realm, *service, *sinstance, *ptr; 153{ 154 KTEXT_ST tkt_st; 155 KTEXT tkt = &tkt_st; 156 struct timeval t_local; 157 int lifetime, kvno, kerror; 158 int32_t kdc_time; 159 C_Block ses; 160 char s_name[ SNAME_SZ ], s_instance[ INST_SZ ]; 161 char rlm[ REALM_SZ ]; 162 163 /* extract session key */ 164 memcpy(ses, ptr, 8); 165 ptr += 8; 166 167 /* extract server's name */ 168 (void) strcpy(s_name,ptr); 169 ptr += strlen(s_name) + 1; 170 171 /* extract server's instance */ 172 (void) strcpy(s_instance,ptr); 173 ptr += strlen(s_instance) + 1; 174 175 /* extract server's realm */ 176 (void) strcpy(rlm,ptr); 177 ptr += strlen(rlm) + 1; 178 179 /* extract ticket lifetime, server key version, ticket length */ 180 /* be sure to avoid sign extension on lifetime! */ 181 lifetime = (unsigned char) ptr[0]; 182 kvno = (unsigned char) ptr[1]; 183 tkt->length = (unsigned char) ptr[2]; 184 ptr += 3; 185 186 /* extract ticket itself */ 187 memcpy( tkt->dat, ptr, tkt->length); 188 ptr += tkt->length; 189 190 if (strcmp(s_name, service) || strcmp(s_instance, sinstance) || 191 strcmp(rlm, realm)) /* not what we asked for */ 192 return(INTK_ERR); /* we need a better code here XXX */ 193 194 /* check KDC time stamp */ 195 memcpy(&kdc_time, ptr, 4); /* Time (coarse) */ 196 if (swap_bytes) swap_u_long(kdc_time); 197 198 ptr += 4; 199 200 (void) gettimeofday(&t_local,(struct timezone *) 0); 201 if (abs((int)(t_local.tv_sec - kdc_time)) > CLOCK_SKEW) { 202 return(RD_AP_TIME); /* XXX should probably be better 203 code */ 204 } 205 206 /* initialize ticket cache */ 207 if (in_tkt(user,instance) != KSUCCESS) 208 return(INTK_ERR); 209 210 /* stash ticket, session key, etc. for future use */ 211 if (kerror = save_credentials(s_name, s_instance, rlm, ses, 212 lifetime, kvno, tkt, t_local.tv_sec)) 213 return(kerror); 214 215 return(INTK_OK); 216} 217 218#endif /* UAM_AFSKRB */ 219