|
|
1.1 root 1: /*
2: * $Source: /usr/src/kerberosIV/krb/RCS/get_ad_tkt.c,v $
3: * $Author: kfall $
4: *
5: * Copyright 1986, 1987, 1988 by the Massachusetts Institute
6: * of Technology.
7: *
8: * For copying and distribution information, please see the file
9: * <mit-copyright.h>.
10: */
11:
12: #ifndef lint
13: static char *rcsid_get_ad_tkt_c =
14: "$Header: /usr/src/kerberosIV/krb/RCS/get_ad_tkt.c,v 4.16 90/06/25 20:55:44 kfall Exp $";
15: #endif /* lint */
16:
17: #include <mit-copyright.h>
18: #include <des.h>
19: #include <krb.h>
20: #include <prot.h>
21: #include <strings.h>
22:
23: #include <stdio.h>
24: #include <errno.h>
25:
26: /* use the bsd time.h struct defs for PC too! */
27: #include <sys/time.h>
28: #include <sys/types.h>
29:
30: extern int krb_debug;
31:
32: struct timeval tt_local = { 0, 0 };
33:
34: int swap_bytes;
35: unsigned long rep_err_code;
36:
37: /*
38: * get_ad_tkt obtains a new service ticket from Kerberos, using
39: * the ticket-granting ticket which must be in the ticket file.
40: * It is typically called by krb_mk_req() when the client side
41: * of an application is creating authentication information to be
42: * sent to the server side.
43: *
44: * get_ad_tkt takes four arguments: three pointers to strings which
45: * contain the name, instance, and realm of the service for which the
46: * ticket is to be obtained; and an integer indicating the desired
47: * lifetime of the ticket.
48: *
49: * It returns an error status if the ticket couldn't be obtained,
50: * or AD_OK if all went well. The ticket is stored in the ticket
51: * cache.
52: *
53: * The request sent to the Kerberos ticket-granting service looks
54: * like this:
55: *
56: * pkt->dat
57: *
58: * TEXT original contents of authenticator+ticket
59: * pkt->dat built in krb_mk_req call
60: *
61: * 4 bytes time_ws always 0 (?)
62: * char lifetime lifetime argument passed
63: * string service service name argument
64: * string sinstance service instance arg.
65: *
66: * See "prot.h" for the reply packet layout and definitions of the
67: * extraction macros like pkt_version(), pkt_msg_type(), etc.
68: */
69:
70: get_ad_tkt(service,sinstance,realm,lifetime)
71: char *service;
72: char *sinstance;
73: char *realm;
74: int lifetime;
75: {
76: static KTEXT_ST pkt_st;
77: KTEXT pkt = & pkt_st; /* Packet to KDC */
78: static KTEXT_ST rpkt_st;
79: KTEXT rpkt = &rpkt_st; /* Returned packet */
80: static KTEXT_ST cip_st;
81: KTEXT cip = &cip_st; /* Returned Ciphertext */
82: static KTEXT_ST tkt_st;
83: KTEXT tkt = &tkt_st; /* Current ticket */
84: C_Block ses; /* Session key for tkt */
85: CREDENTIALS cr;
86: int kvno; /* Kvno for session key */
87: char lrealm[REALM_SZ];
88: C_Block key; /* Key for decrypting cipher */
89: Key_schedule key_s;
90: long time_ws = 0;
91:
92: char s_name[SNAME_SZ];
93: char s_instance[INST_SZ];
94: int msg_byte_order;
95: int kerror;
96: char rlm[REALM_SZ];
97: char *ptr;
98:
99: unsigned long kdc_time; /* KDC time */
100:
101: if ((kerror = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS)
102: return(kerror);
103:
104: /* Create skeleton of packet to be sent */
105: (void) gettimeofday(&tt_local,(struct timezone *) 0);
106:
107: pkt->length = 0;
108:
109: /*
110: * Look for the session key (and other stuff we don't need)
111: * in the ticket file for krbtgt.realm@lrealm where "realm"
112: * is the service's realm (passed in "realm" argument) and
113: * lrealm is the realm of our initial ticket. If we don't
114: * have this, we will try to get it.
115: */
116:
117: if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) {
118: /*
119: * If realm == lrealm, we have no hope, so let's not even try.
120: */
121: if ((strncmp(realm, lrealm, REALM_SZ)) == 0)
122: return(AD_NOTGT);
123: else{
124: if ((kerror =
125: get_ad_tkt("krbtgt",realm,lrealm,lifetime)) != KSUCCESS)
126: return(kerror);
127: if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS)
128: return(kerror);
129: }
130: }
131:
132: /*
133: * Make up a request packet to the "krbtgt.realm@lrealm".
134: * Start by calling krb_mk_req() which puts ticket+authenticator
135: * into "pkt". Then tack other stuff on the end.
136: */
137:
138: kerror = krb_mk_req(pkt,"krbtgt",realm,lrealm,0L);
139:
140: if (kerror)
141: return(AD_NOTGT);
142:
143: /* timestamp */
144: bcopy((char *) &time_ws,(char *) (pkt->dat+pkt->length),4);
145: pkt->length += 4;
146: *(pkt->dat+(pkt->length)++) = (char) lifetime;
147: (void) strcpy((char *) (pkt->dat+pkt->length),service);
148: pkt->length += 1 + strlen(service);
149: (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
150: pkt->length += 1 + strlen(sinstance);
151:
152: rpkt->length = 0;
153:
154: /* Send the request to the local ticket-granting server */
155: if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror);
156:
157: /* check packet version of the returned packet */
158: if (pkt_version(rpkt) != KRB_PROT_VERSION )
159: return(INTK_PROT);
160:
161: /* Check byte order */
162: msg_byte_order = pkt_msg_type(rpkt) & 1;
163: swap_bytes = 0;
164: if (msg_byte_order != HOST_BYTE_ORDER)
165: swap_bytes++;
166:
167: switch (pkt_msg_type(rpkt) & ~1) {
168: case AUTH_MSG_KDC_REPLY:
169: break;
170: case AUTH_MSG_ERR_REPLY:
171: bcopy(pkt_err_code(rpkt), (char *) &rep_err_code, 4);
172: if (swap_bytes)
173: swap_u_long(rep_err_code);
174: return(rep_err_code);
175:
176: default:
177: return(INTK_PROT);
178: }
179:
180: /* Extract the ciphertext */
181: cip->length = pkt_clen(rpkt); /* let clen do the swap */
182:
183: bcopy((char *) pkt_cipher(rpkt),(char *) (cip->dat),cip->length);
184:
185: #ifndef NOENCRYPTION
186: /* Attempt to decrypt it */
187:
188: key_sched(cr.session,key_s);
189: if (krb_debug) printf("About to do decryption ...");
190: pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,
191: (long) cip->length,key_s,cr.session,0);
192: #endif /* !NOENCRYPTION */
193: /* Get rid of all traces of key */
194: bzero((char *) cr.session, sizeof(key));
195: bzero((char *) key_s, sizeof(key_s));
196:
197: ptr = (char *) cip->dat;
198:
199: bcopy(ptr,(char *)ses,8);
200: ptr += 8;
201:
202: (void) strcpy(s_name,ptr);
203: ptr += strlen(s_name) + 1;
204:
205: (void) strcpy(s_instance,ptr);
206: ptr += strlen(s_instance) + 1;
207:
208: (void) strcpy(rlm,ptr);
209: ptr += strlen(rlm) + 1;
210:
211: lifetime = (unsigned long) ptr[0];
212: kvno = (unsigned long) ptr[1];
213: tkt->length = (int) ptr[2];
214: ptr += 3;
215: bcopy(ptr,(char *)(tkt->dat),tkt->length);
216: ptr += tkt->length;
217:
218: if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
219: strcmp(rlm, realm)) /* not what we asked for */
220: return(INTK_ERR); /* we need a better code here XXX */
221:
222: /* check KDC time stamp */
223: bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */
224: if (swap_bytes) swap_u_long(kdc_time);
225:
226: ptr += 4;
227:
228: (void) gettimeofday(&tt_local,(struct timezone *) 0);
229: if (abs((int)(tt_local.tv_sec - kdc_time)) > CLOCK_SKEW) {
230: return(RD_AP_TIME); /* XXX should probably be better
231: code */
232: }
233:
234: if (kerror = save_credentials(s_name,s_instance,rlm,ses,lifetime,
235: kvno,tkt,tt_local.tv_sec))
236: return(kerror);
237:
238: return(AD_OK);
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.