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 + -
显示快捷键?