Merge from vendor branch CVS:
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / krb5 / convert_creds.c
1 /*
2  * Copyright (c) 1997 - 2002 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 "krb5_locl.h"
35 RCSID("$Id: convert_creds.c,v 1.26 2003/03/18 03:11:16 lha Exp $");
36
37 #include "krb5-v4compat.h"
38
39 static krb5_error_code
40 check_ticket_flags(TicketFlags f)
41 {
42     return 0; /* maybe add some more tests here? */
43 }
44
45 /* include this here, to avoid dependencies on libkrb */
46
47 static const int _tkt_lifetimes[TKTLIFENUMFIXED] = {
48    38400,   41055,   43894,   46929,   50174,   53643,   57352,   61318,
49    65558,   70091,   74937,   80119,   85658,   91581,   97914,  104684,
50   111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
51   191077,  204289,  218415,  233517,  249664,  266926,  285383,  305116,
52   326213,  348769,  372885,  398668,  426234,  455705,  487215,  520904,
53   556921,  595430,  636601,  680618,  727680,  777995,  831789,  889303,
54   950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
55  1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
56 };
57
58 int
59 _krb5_krb_time_to_life(time_t start, time_t end)
60 {
61     int i;
62     time_t life = end - start;
63
64     if (life > MAXTKTLIFETIME || life <= 0) 
65         return 0;
66 #if 0    
67     if (krb_no_long_lifetimes) 
68         return (life + 5*60 - 1)/(5*60);
69 #endif
70     
71     if (end >= NEVERDATE)
72         return TKTLIFENOEXPIRE;
73     if (life < _tkt_lifetimes[0]) 
74         return (life + 5*60 - 1)/(5*60);
75     for (i=0; i<TKTLIFENUMFIXED; i++)
76         if (life <= _tkt_lifetimes[i])
77             return i + TKTLIFEMINFIXED;
78     return 0;
79     
80 }
81
82 time_t
83 _krb5_krb_life_to_time(int start, int life_)
84 {
85     unsigned char life = (unsigned char) life_;
86
87 #if 0    
88     if (krb_no_long_lifetimes)
89         return start + life*5*60;
90 #endif
91
92     if (life == TKTLIFENOEXPIRE)
93         return NEVERDATE;
94     if (life < TKTLIFEMINFIXED)
95         return start + life*5*60;
96     if (life > TKTLIFEMAXFIXED)
97         return start + MAXTKTLIFETIME;
98     return start + _tkt_lifetimes[life - TKTLIFEMINFIXED];
99 }
100
101
102 /* Convert the v5 credentials in `in_cred' to v4-dito in `v4creds'.
103  * This is done by sending them to the 524 function in the KDC.  If
104  * `in_cred' doesn't contain a DES session key, then a new one is
105  * gotten from the KDC and stored in the cred cache `ccache'.
106  */
107
108 krb5_error_code
109 krb524_convert_creds_kdc(krb5_context context, 
110                          krb5_creds *in_cred,
111                          struct credentials *v4creds)
112 {
113     krb5_error_code ret;
114     krb5_data reply;
115     krb5_storage *sp;
116     int32_t tmp;
117     krb5_data ticket;
118     char realm[REALM_SZ];
119     krb5_creds *v5_creds = in_cred;
120
121     ret = check_ticket_flags(v5_creds->flags.b);
122     if(ret)
123         goto out2;
124
125     {
126         krb5_krbhst_handle handle;
127
128         ret = krb5_krbhst_init(context,
129                                *krb5_princ_realm(context, 
130                                                 v5_creds->server),
131                                KRB5_KRBHST_KRB524,
132                                &handle);
133         if (ret)
134             goto out2;
135
136         ret = krb5_sendto (context,
137                            &v5_creds->ticket,
138                            handle,
139                            &reply);
140         krb5_krbhst_free(context, handle);
141         if (ret)
142             goto out2;
143     }
144     sp = krb5_storage_from_mem(reply.data, reply.length);
145     if(sp == NULL) {
146         ret = ENOMEM;
147         krb5_set_error_string (context, "malloc: out of memory");
148         goto out2;
149     }
150     krb5_ret_int32(sp, &tmp);
151     ret = tmp;
152     if(ret == 0) {
153         memset(v4creds, 0, sizeof(*v4creds));
154         ret = krb5_ret_int32(sp, &tmp);
155         if(ret)
156             goto out;
157         v4creds->kvno = tmp;
158         ret = krb5_ret_data(sp, &ticket);
159         if(ret)
160             goto out;
161         v4creds->ticket_st.length = ticket.length;
162         memcpy(v4creds->ticket_st.dat, ticket.data, ticket.length);
163         krb5_data_free(&ticket);
164         ret = krb5_524_conv_principal(context, 
165                                       v5_creds->server, 
166                                       v4creds->service, 
167                                       v4creds->instance, 
168                                       v4creds->realm);
169         if(ret)
170             goto out;
171         v4creds->issue_date = v5_creds->times.starttime;
172         v4creds->lifetime = _krb5_krb_time_to_life(v4creds->issue_date,
173                                                    v5_creds->times.endtime);
174         ret = krb5_524_conv_principal(context, v5_creds->client, 
175                                       v4creds->pname, 
176                                       v4creds->pinst, 
177                                       realm);
178         if(ret)
179             goto out;
180         memcpy(v4creds->session, v5_creds->session.keyvalue.data, 8);
181     } else {
182         krb5_set_error_string(context, "converting credentials: %s", 
183                               krb5_get_err_text(context, ret));
184     }
185 out:
186     krb5_storage_free(sp);
187     krb5_data_free(&reply);
188 out2:
189     if (v5_creds != in_cred)
190         krb5_free_creds (context, v5_creds);
191     return ret;
192 }
193
194 krb5_error_code
195 krb524_convert_creds_kdc_ccache(krb5_context context, 
196                                 krb5_ccache ccache,
197                                 krb5_creds *in_cred,
198                                 struct credentials *v4creds)
199 {
200     krb5_error_code ret;
201     krb5_creds *v5_creds = in_cred;
202     krb5_keytype keytype;
203
204     keytype = v5_creds->session.keytype;
205
206     if (keytype != ENCTYPE_DES_CBC_CRC) {
207         /* MIT krb524d doesn't like nothing but des-cbc-crc tickets,
208            so go get one */
209         krb5_creds template;
210
211         memset (&template, 0, sizeof(template));
212         template.session.keytype = ENCTYPE_DES_CBC_CRC;
213         ret = krb5_copy_principal (context, in_cred->client, &template.client);
214         if (ret) {
215             krb5_free_creds_contents (context, &template);
216             return ret;
217         }
218         ret = krb5_copy_principal (context, in_cred->server, &template.server);
219         if (ret) {
220             krb5_free_creds_contents (context, &template);
221             return ret;
222         }
223
224         ret = krb5_get_credentials (context, 0, ccache,
225                                     &template, &v5_creds);
226         krb5_free_creds_contents (context, &template);
227         if (ret)
228             return ret;
229     }
230
231     ret = krb524_convert_creds_kdc(context, v5_creds, v4creds);
232
233     if (v5_creds != in_cred)
234         krb5_free_creds (context, v5_creds);
235     return ret;
236 }