krb_get_in_tkt.c

来自「RADIUS协议的认证计费服务」· C语言 代码 · 共 319 行

C
319
字号
#if defined(A_KERB) || defined(M_KERB)/* * Copyright 1986, 1987, 1988 by the Massachusetts Institute * of Technology. * * For copying and distribution information, please see the file * <mit-copyright.h>. */#ifndef lintstatic char    *rcsid_krb_get_in_tkt_c ="$Id: krb_get_in_tkt.c,v 1.1.1.1 2001/08/10 20:49:28 bonze Exp $";#endif				/* lint */#include <mit-copyright.h>#include <krb.h>#include <des.h>#include <stdio.h>#include <strings.h>#include <errno.h>/* use the bsd time.h struct defs for PC too! */#include <sys/types.h>#include <sys/time.h>#include "prot.h"int             swap_bytes;/* * decrypt_tkt(): Given user, instance, realm, passwd, key_proc * and the cipher text sent from the KDC, decrypt the cipher text * using the key returned by key_proc. */static int decrypt_tkt (user, instance, realm, arg, key_proc, cipp)char           *user;char           *instance;char           *realm;char           *arg;int             (*key_proc) ();KTEXT          *cipp;{	KTEXT           cip = *cipp;	C_Block         key;	/* Key for decrypting cipher */	Key_schedule    key_s;#ifndef NOENCRYPTION	/* Attempt to decrypt it */#endif	/* generate a key */	{		register int    rc;		rc = (*key_proc) (user, instance, realm, arg, key);		if (rc)			return (rc);	}#ifndef NOENCRYPTION	key_sched (key, key_s);	pcbc_encrypt ((C_Block *) cip->dat, (C_Block *) cip->dat,		      (long) cip->length, key_s, key, 0);#endif				/* !NOENCRYPTION */	/* Get rid of all traces of key */	bzero ((char *) key, sizeof (key));	bzero ((char *) key_s, sizeof (key_s));	return (0);}/* * krb_get_in_tkt() gets a ticket for a given principal to use a given * service and stores the returned ticket and session key for future * use. * * The "user", "instance", and "realm" arguments give the identity of * the client who will use the ticket.  The "service" and "sinstance" * arguments give the identity of the server that the client wishes * to use.  (The realm of the server is the same as the Kerberos server * to whom the request is sent.)  The "life" argument indicates the * desired lifetime of the ticket; the "key_proc" argument is a pointer * to the routine used for getting the client's private key to decrypt * the reply from Kerberos.  The "decrypt_proc" argument is a pointer * to the routine used to decrypt the reply from Kerberos; and "arg" * is an argument to be passed on to the "key_proc" routine. * * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it * returns an error code:  If an AUTH_MSG_ERR_REPLY packet is returned * by Kerberos, then the error code it contains is returned.  Other * error codes returned by this routine include INTK_PROT to indicate * wrong protocol version, INTK_BADPW to indicate bad password (if * decrypted ticket didn't make sense), INTK_ERR if the ticket was for * the wrong server or the ticket store couldn't be initialized. * * The format of the message sent to Kerberos is as follows: * * Size			Variable		Field * ----			--------		----- * * 1 byte		KRB_PROT_VERSION	protocol version number * 1 byte		AUTH_MSG_KDC_REQUEST |	message type *			HOST_BYTE_ORDER		local byte order in lsb * string		user			client's name * string		instance		client's instance * string		realm			client's realm * 4 bytes		tlocal.tv_sec		timestamp in seconds * 1 byte		life			desired lifetime * string		service			service's name * string		sinstance		service's instance */krb_get_in_tkt (user, instance, realm, service, sinstance, life,		key_proc, decrypt_proc, arg)char           *user;char           *instance;char           *realm;char           *service;char           *sinstance;int             life;int             (*key_proc) ();int             (*decrypt_proc) ();char           *arg;{	KTEXT_ST        pkt_st;	KTEXT           pkt = &pkt_st;	/* Packet to KDC */	KTEXT_ST        rpkt_st;	KTEXT           rpkt = &rpkt_st;	/* Returned packet */	KTEXT_ST        cip_st;	KTEXT           cip = &cip_st;	/* Returned Ciphertext */	KTEXT_ST        tkt_st;	KTEXT           tkt = &tkt_st;	/* Current ticket */	C_Block         ses;	/* Session key for tkt */	int             kvno;	/* Kvno for session key */	unsigned char  *v = pkt->dat;	/* Prot vers no */	unsigned char  *t = (pkt->dat + 1);	/* Prot msg type */	char            s_name[SNAME_SZ];	char            s_instance[INST_SZ];	char            rlm[REALM_SZ];	int             lifetime;	int             msg_byte_order;	int             kerror;	unsigned long   exp_date;	char           *ptr;	struct timeval  t_local;	unsigned long   rep_err_code;	unsigned long   kdc_time;	/* KDC time */	/* BUILD REQUEST PACKET */	/* Set up the fixed part of the packet */	*v = (unsigned char) KRB_PROT_VERSION;	*t = (unsigned char) AUTH_MSG_KDC_REQUEST;	*t |= HOST_BYTE_ORDER;	/* Now for the variable info */	(void) strcpy ((char *) (pkt->dat + 2), user);	/* aname */	pkt->length = 3 + strlen (user);	(void) strcpy ((char *) (pkt->dat + pkt->length),		       instance);	/* instance */	pkt->length += 1 + strlen (instance);	(void) strcpy ((char *) (pkt->dat + pkt->length), realm);	/* realm */	pkt->length += 1 + strlen (realm);	(void) gettimeofday (&t_local, (struct timezone *) 0);	/* timestamp */	bcopy ((char *) &(t_local.tv_sec), (char *) (pkt->dat + pkt->length), 4);	pkt->length += 4;	*(pkt->dat + (pkt->length)++) = (char) life;	(void) strcpy ((char *) (pkt->dat + pkt->length), service);	pkt->length += 1 + strlen (service);	(void) strcpy ((char *) (pkt->dat + pkt->length), sinstance);	pkt->length += 1 + strlen (sinstance);	rpkt->length = 0;	/* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */	if (kerror = send_to_kdc (pkt, rpkt, realm))		return (kerror);	/* check packet version of the returned packet */	if (pkt_version (rpkt) != KRB_PROT_VERSION)		return (INTK_PROT);	/* Check byte order */	msg_byte_order = pkt_msg_type (rpkt) & 1;	swap_bytes = 0;	if (msg_byte_order != HOST_BYTE_ORDER)	{		swap_bytes++;	}	switch (pkt_msg_type (rpkt) & ~1)	{	    case AUTH_MSG_KDC_REPLY:		break;	    case AUTH_MSG_ERR_REPLY:		bcopy (pkt_err_code (rpkt), (char *) &rep_err_code, 4);		if (swap_bytes)			swap_u_long (rep_err_code);		/* Don't let ill formed error reply fake us out! */		/* (This is a bug in MIT release of this module) */		if ((kerror = (int) rep_err_code) == INTK_OK)			kerror = INTK_BADPW;		return (kerror);	    default:		return (INTK_PROT);	}	/* EXTRACT INFORMATION FROM RETURN PACKET */	/* get the principal's expiration date */	bcopy (pkt_x_date (rpkt), (char *) &exp_date, sizeof (exp_date));	if (swap_bytes)		swap_u_long (exp_date);	/* Extract the ciphertext */	cip->length = pkt_clen (rpkt);	/* let clen do the swap */	if ((cip->length < 0) || (cip->length > sizeof (cip->dat)))		return (INTK_ERR);	/* no appropriate error code					 * currently defined for INTK_ */	/* copy information from return packet into "cip" */	bcopy ((char *) pkt_cipher (rpkt), (char *) (cip->dat), cip->length);	/* Attempt to decrypt the reply. */	if (decrypt_proc == NULL)		decrypt_proc = decrypt_tkt;	(*decrypt_proc) (user, instance, realm, arg, key_proc, &cip);	ptr = (char *) cip->dat;	/* extract session key */	bcopy (ptr, (char *) ses, 8);	ptr += 8;	if ((strlen (ptr) + (ptr - (char *) cip->dat)) > cip->length)		return (INTK_BADPW);	/* extract server's name */	(void) strncpy (s_name, ptr, sizeof (s_name) - 1);	s_name[sizeof (s_name) - 1] = '\0';	ptr += strlen (s_name) + 1;	if ((strlen (ptr) + (ptr - (char *) cip->dat)) > cip->length)		return (INTK_BADPW);	/* extract server's instance */	(void) strncpy (s_instance, ptr, sizeof (s_instance) - 1);	s_instance[sizeof (s_instance) - 1] = '\0';	ptr += strlen (s_instance) + 1;	if ((strlen (ptr) + (ptr - (char *) cip->dat)) > cip->length)		return (INTK_BADPW);	/* extract server's realm */	(void) strncpy (rlm, ptr, sizeof (rlm));	rlm[sizeof (rlm) - 1] = '\0';	ptr += strlen (rlm) + 1;	/* extract ticket lifetime, server key version, ticket length */	/* be sure to avoid sign extension on lifetime! */	lifetime = (unsigned char) ptr[0];	kvno = (unsigned char) ptr[1];	tkt->length = (unsigned char) ptr[2];	ptr += 3;	if ((tkt->length < 0) ||		  ((tkt->length + (ptr - (char *) cip->dat)) > cip->length))		return (INTK_BADPW);	/* extract ticket itself */	bcopy (ptr, (char *) (tkt->dat), tkt->length);	ptr += tkt->length;	if (strcmp (s_name, service) || strcmp (s_instance, sinstance) ||			strcmp (rlm, realm))	/* not what we asked for */		return (INTK_ERR);	/* we need a better code here XXX */	/* check KDC time stamp */	bcopy (ptr, (char *) &kdc_time, 4);	/* Time (coarse) */	if (swap_bytes)		swap_u_long (kdc_time);	ptr += 4;	(void) gettimeofday (&t_local, (struct timezone *) 0);	if (abs ((int) (t_local.tv_sec - kdc_time)) > CLOCK_SKEW)	{		return (RD_AP_TIME);	/* XXX should probably be better code */	}	/* initialize ticket cache */	if (in_tkt (user, instance) != KSUCCESS)		return (INTK_ERR);	/* stash ticket, session key, etc. for future use */	if (kerror = save_credentials (s_name, s_instance, rlm, ses,				       lifetime, kvno, tkt, t_local.tv_sec))		return (kerror);	return (INTK_OK);}#endif				/* #if defined(A_KERB) || defined(M_KERB) */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?