2 * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 RCSID("$Id: get_ad_tkt.c,v 1.22 1999/12/02 16:58:41 joda Exp $");
39 * get_ad_tkt obtains a new service ticket from Kerberos, using
40 * the ticket-granting ticket which must be in the ticket file.
41 * It is typically called by krb_mk_req() when the client side
42 * of an application is creating authentication information to be
43 * sent to the server side.
45 * get_ad_tkt takes four arguments: three pointers to strings which
46 * contain the name, instance, and realm of the service for which the
47 * ticket is to be obtained; and an integer indicating the desired
48 * lifetime of the ticket.
50 * It returns an error status if the ticket couldn't be obtained,
51 * or AD_OK if all went well. The ticket is stored in the ticket
54 * The request sent to the Kerberos ticket-granting service looks
59 * TEXT original contents of authenticator+ticket
60 * pkt->dat built in krb_mk_req call
62 * 4 bytes time_ws always 0 (?)
63 * char lifetime lifetime argument passed
64 * string service service name argument
65 * string sinstance service instance arg.
67 * See "prot.h" for the reply packet layout and definitions of the
68 * extraction macros like pkt_version(), pkt_msg_type(), etc.
72 get_ad_tkt(char *service, char *sinstance, char *realm, int lifetime)
74 static KTEXT_ST pkt_st;
75 KTEXT pkt = & pkt_st; /* Packet to KDC */
76 static KTEXT_ST rpkt_st;
77 KTEXT rpkt = &rpkt_st; /* Returned packet */
80 char lrealm[REALM_SZ];
81 u_int32_t time_ws = 0;
88 * First check if we have a "real" TGT for the corresponding
89 * realm, if we don't, use ordinary inter-realm authentication.
92 kerror = krb_get_cred(KRB_TICKET_GRANTING_TICKET, realm, realm, &cr);
93 if (kerror == KSUCCESS) {
94 strlcpy(lrealm, realm, REALM_SZ);
96 kerror = krb_get_tf_realm(TKT_FILE, lrealm);
98 if (kerror != KSUCCESS)
102 * Look for the session key (and other stuff we don't need)
103 * in the ticket file for krbtgt.realm@lrealm where "realm"
104 * is the service's realm (passed in "realm" argument) and
105 * lrealm is the realm of our initial ticket. If we don't
106 * have this, we will try to get it.
109 if ((kerror = krb_get_cred(KRB_TICKET_GRANTING_TICKET,
110 realm, lrealm, &cr)) != KSUCCESS) {
112 * If realm == lrealm, we have no hope, so let's not even try.
114 if ((strncmp(realm, lrealm, REALM_SZ)) == 0)
118 get_ad_tkt(KRB_TICKET_GRANTING_TICKET,
119 realm, lrealm, lifetime)) != KSUCCESS) {
120 if (kerror == KDC_PR_UNKNOWN)
121 return(AD_INTR_RLM_NOTGT);
125 if ((kerror = krb_get_cred(KRB_TICKET_GRANTING_TICKET,
126 realm, lrealm, &cr)) != KSUCCESS)
132 * Make up a request packet to the "krbtgt.realm@lrealm".
133 * Start by calling krb_mk_req() which puts ticket+authenticator
134 * into "pkt". Then tack other stuff on the end.
137 kerror = krb_mk_req(pkt,
138 KRB_TICKET_GRANTING_TICKET,
144 p = pkt->dat + pkt->length;
145 rem = sizeof(pkt->dat) - pkt->length;
147 tmp = krb_put_int(time_ws, p, rem, 4);
153 tmp = krb_put_int(lifetime, p, rem, 1);
159 tmp = krb_put_nir(service, sinstance, NULL, p, rem);
165 pkt->length = p - pkt->dat;
168 /* Send the request to the local ticket-granting server */
169 if ((kerror = send_to_kdc(pkt, rpkt, realm))) return(kerror);
171 /* check packet version of the returned packet */
178 kerror = kdc_reply_cipher(rpkt, &cip);
179 if(kerror != KSUCCESS)
182 encrypt_ktext(&cip, &cr.session, DES_DECRYPT);
184 kerror = kdc_reply_cred(&cip, &cred);
185 if(kerror != KSUCCESS)
188 if (strcmp(cred.service, service) || strcmp(cred.instance, sinstance) ||
189 strcmp(cred.realm, realm)) /* not what we asked for */
190 return INTK_ERR; /* we need a better code here XXX */
192 krb_kdctimeofday(&tv);
193 if (abs((int)(tv.tv_sec - cred.issue_date)) > CLOCK_SKEW) {
194 return RD_AP_TIME; /* XXX should probably be better code */
198 kerror = save_credentials(cred.service, cred.instance, cred.realm,
199 cred.session, cred.lifetime, cred.kvno,
200 &cred.ticket_st, tv.tv_sec);