2 * Copyright (c) 1995, 1996, 1997, 1998 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: krb_get_in_tkt.c,v 1.30 1999/12/02 16:58:42 joda Exp $");
39 * decrypt_tkt(): Given user, instance, realm, passwd, key_proc
40 * and the cipher text sent from the KDC, decrypt the cipher text
41 * using the key returned by key_proc.
45 decrypt_tkt(const char *user,
52 des_cblock key; /* Key for decrypting cipher */
55 ret = key_proc(user, instance, realm, arg, &key);
59 encrypt_ktext(*cip, &key, DES_DECRYPT);
61 memset(&key, 0, sizeof(key));
66 * krb_get_in_tkt() gets a ticket for a given principal to use a given
67 * service and stores the returned ticket and session key for future
70 * The "user", "instance", and "realm" arguments give the identity of
71 * the client who will use the ticket. The "service" and "sinstance"
72 * arguments give the identity of the server that the client wishes
73 * to use. (The realm of the server is the same as the Kerberos server
74 * to whom the request is sent.) The "life" argument indicates the
75 * desired lifetime of the ticket; the "key_proc" argument is a pointer
76 * to the routine used for getting the client's private key to decrypt
77 * the reply from Kerberos. The "decrypt_proc" argument is a pointer
78 * to the routine used to decrypt the reply from Kerberos; and "arg"
79 * is an argument to be passed on to the "key_proc" routine.
81 * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it
82 * returns an error code: If an AUTH_MSG_ERR_REPLY packet is returned
83 * by Kerberos, then the error code it contains is returned. Other
84 * error codes returned by this routine include INTK_PROT to indicate
85 * wrong protocol version, INTK_BADPW to indicate bad password (if
86 * decrypted ticket didn't make sense), INTK_ERR if the ticket was for
87 * the wrong server or the ticket store couldn't be initialized.
89 * The format of the message sent to Kerberos is as follows:
94 * 1 byte KRB_PROT_VERSION protocol version number
95 * 1 byte AUTH_MSG_KDC_REQUEST | message type
96 * HOST_BYTE_ORDER local byte order in lsb
97 * string user client's name
98 * string instance client's instance
99 * string realm client's realm
100 * 4 bytes tlocal.tv_sec timestamp in seconds
101 * 1 byte life desired lifetime
102 * string service service's name
103 * string sinstance service's instance
107 krb_mk_as_req(const char *user,
108 const char *instance,
111 const char *sinstance,
116 KTEXT pkt = &pkt_st; /* Packet to KDC */
118 KTEXT rpkt = &rpkt_st; /* Reply from KDC */
123 /* BUILD REQUEST PACKET */
125 unsigned char *p = pkt->dat;
127 size_t rem = sizeof(pkt->dat);
129 tmp = krb_put_int(KRB_PROT_VERSION, p, rem, 1);
135 tmp = krb_put_int(AUTH_MSG_KDC_REQUEST, p, rem, 1);
141 tmp = krb_put_nir(user, instance, realm, p, rem);
147 gettimeofday(&tv, NULL);
148 tmp = krb_put_int(tv.tv_sec, p, rem, 4);
154 tmp = krb_put_int(life, p, rem, 1);
160 tmp = krb_put_nir(service, sinstance, NULL, p, rem);
166 pkt->length = p - pkt->dat;
170 /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
172 kerror = send_to_kdc(pkt, rpkt, realm);
173 if(kerror) return kerror;
174 kerror = kdc_reply_cipher(rpkt, cip);
179 krb_decode_as_rep(const char *user,
183 const char *sinstance,
185 decrypt_proc_t decrypt_proc,
193 if (decrypt_proc == NULL)
194 decrypt_tkt(user, instance, realm, arg, key_proc, &as_rep);
196 (*decrypt_proc)(user, instance, realm, arg, key_proc, &as_rep);
198 kerror = kdc_reply_cred(as_rep, cred);
199 if(kerror != KSUCCESS)
202 if (strcmp(cred->service, service) ||
203 strcmp(cred->instance, sinstance) ||
204 strcmp(cred->realm, realm)) /* not what we asked for */
205 return INTK_ERR; /* we need a better code here XXX */
208 if(krb_get_config_bool("kdc_timesync"))
209 krb_set_kdc_time_diff(cred->issue_date - now);
210 else if (abs((int)(now - cred->issue_date)) > CLOCK_SKEW)
211 return RD_AP_TIME; /* XXX should probably be better code */
217 krb_get_in_tkt(char *user, char *instance, char *realm,
218 char *service, char *sinstance, int life,
219 key_proc_t key_proc, decrypt_proc_t decrypt_proc, void *arg)
225 ret = krb_mk_as_req(user, instance, realm,
226 service, sinstance, life, &as_rep);
229 ret = krb_decode_as_rep(user, instance, realm, service, sinstance,
230 key_proc, decrypt_proc, arg, &as_rep, &cred);
234 return tf_setup(&cred, user, instance);