Change __signed to signed.
[dragonfly.git] / crypto / kerberosIV / lib / krb / krb_get_in_tkt.c
1 /*
2  * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 
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.
16  * 
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.
20  * 
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
31  * SUCH DAMAGE.
32  */
33
34 #include "krb_locl.h"
35
36 RCSID("$Id: krb_get_in_tkt.c,v 1.30 1999/12/02 16:58:42 joda Exp $");
37
38 /*
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.
42  */
43
44 static int
45 decrypt_tkt(const char *user,
46             char *instance,
47             const char *realm,
48             const void *arg,
49             key_proc_t key_proc,
50             KTEXT *cip)
51 {
52     des_cblock key;             /* Key for decrypting cipher */
53     int ret;
54
55     ret = key_proc(user, instance, realm, arg, &key);
56     if (ret != 0)
57         return ret;
58     
59     encrypt_ktext(*cip, &key, DES_DECRYPT);
60
61     memset(&key, 0, sizeof(key));
62     return 0;
63 }
64
65 /*
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
68  * use.
69  *
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.
80  *
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.
88  *
89  * The format of the message sent to Kerberos is as follows:
90  *
91  * Size                 Variable                Field
92  * ----                 --------                -----
93  *
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
104  */
105
106 int
107 krb_mk_as_req(const char *user,
108               const char *instance,
109               const char *realm, 
110               const char *service,
111               const char *sinstance,
112               int life,
113               KTEXT cip)
114 {
115     KTEXT_ST pkt_st;
116     KTEXT pkt = &pkt_st;        /* Packet to KDC */
117     KTEXT_ST rpkt_st;
118     KTEXT rpkt = &rpkt_st;      /* Reply from KDC */
119     
120     int kerror;
121     struct timeval tv;
122
123     /* BUILD REQUEST PACKET */
124
125     unsigned char *p = pkt->dat;
126     int tmp;
127     size_t rem = sizeof(pkt->dat);
128     
129     tmp = krb_put_int(KRB_PROT_VERSION, p, rem, 1);
130     if (tmp < 0)
131         return KFAILURE;
132     p += tmp;
133     rem -= tmp;
134
135     tmp = krb_put_int(AUTH_MSG_KDC_REQUEST, p, rem, 1);
136     if (tmp < 0)
137         return KFAILURE;
138     p += tmp;
139     rem -= tmp;
140
141     tmp = krb_put_nir(user, instance, realm, p, rem);
142     if (tmp < 0)
143         return KFAILURE;
144     p += tmp;
145     rem -= tmp;
146
147     gettimeofday(&tv, NULL);
148     tmp = krb_put_int(tv.tv_sec, p, rem, 4);
149     if (tmp < 0)
150         return KFAILURE;
151     p += tmp;
152     rem -= tmp;
153
154     tmp = krb_put_int(life, p, rem, 1);
155     if (tmp < 0)
156         return KFAILURE;
157     p += tmp;
158     rem -= tmp;
159
160     tmp = krb_put_nir(service, sinstance, NULL, p, rem);
161     if (tmp < 0)
162         return KFAILURE;
163     p += tmp;
164     rem -= tmp;
165
166     pkt->length = p - pkt->dat;
167
168     rpkt->length = 0;
169
170     /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
171
172     kerror = send_to_kdc(pkt, rpkt, realm);
173     if(kerror) return kerror;
174     kerror = kdc_reply_cipher(rpkt, cip);
175     return kerror;
176 }
177
178 int
179 krb_decode_as_rep(const char *user,
180                   char *instance,
181                   const char *realm,
182                   const char *service,
183                   const char *sinstance, 
184                   key_proc_t key_proc,
185                   decrypt_proc_t decrypt_proc,
186                   const void *arg,
187                   KTEXT as_rep,
188                   CREDENTIALS *cred)
189 {
190     int kerror;
191     time_t now;
192     
193     if (decrypt_proc == NULL)
194         decrypt_tkt(user, instance, realm, arg, key_proc, &as_rep);
195     else
196         (*decrypt_proc)(user, instance, realm, arg, key_proc, &as_rep);
197
198     kerror = kdc_reply_cred(as_rep, cred);
199     if(kerror != KSUCCESS)
200         return kerror;
201         
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 */
206
207     now = time(NULL);
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 */
212
213     return 0;
214 }
215
216 int
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)
220 {
221     KTEXT_ST as_rep;
222     CREDENTIALS cred;
223     int ret;
224
225     ret = krb_mk_as_req(user, instance, realm, 
226                         service, sinstance, life, &as_rep);
227     if(ret)
228         return ret;
229     ret = krb_decode_as_rep(user, instance, realm, service, sinstance, 
230                             key_proc, decrypt_proc, arg, &as_rep, &cred);
231     if(ret)
232         return ret;
233
234     return tf_setup(&cred, user, instance);
235 }