805c240f373924561f36ced25024322f79b4cfac
[openafs.git] / src / rxgk / rxgk_crkrb.c
1 /*
2  * Copyright (c) 2002 - 2004, Stockholms universitet
3  * (Stockholm University, 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 university 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /*
35  * Heimdal implementation of the rxgk wire encryption
36  */
37
38 #include "rxgk_locl.h"
39 #include <errno.h>
40
41 RCSID("$Id$");
42
43 struct _rxg_key_type {
44     char *name;
45     int enctype;
46     int blocklen;
47     int checksumlen;
48     int confounderlen;
49 };
50
51 static struct _rxg_key_type ktypes[] = {
52     { "des-cbc-crc", RXGK_CRYPTO_DES_CBC_CRC,
53       8, 4, 8,
54     },
55     { "des-cbc-md5", RXGK_CRYPTO_DES_CBC_MD5,
56       8, 24, 8,
57     }
58 };
59
60 static struct _rxg_key_type *
61 _rxg_find_enctype(int enctype)
62 {
63     struct _rxg_key_type *key;
64
65     for (key = ktypes; key->name != NULL; key++)
66         if (key->enctype == enctype)
67             return key;
68     return NULL;
69 }
70
71 int
72 rxgk_set_conn(struct rx_connection *con, int enctype, int enc)
73 {
74     struct _rxg_key_type *key;
75
76     key = _rxg_find_enctype(enctype);
77     if (key == NULL)
78         return ENOENT;
79
80     if (enc) {
81         rx_SetSecurityHeaderSize(con, key->checksumlen + key->confounderlen +
82                                  RXGK_HEADER_DATA_SIZE);
83
84         rx_SetSecurityMaxTrailerSize(con, key->blocklen);
85     } else {
86         rx_SetSecurityHeaderSize(con, 
87                                  key->checksumlen + RXGK_HEADER_DATA_SIZE);
88         rx_SetSecurityMaxTrailerSize(con, 0);
89     }
90     return 0;
91 }
92
93 /*
94  *
95  */
96
97 static int
98 uiomove_to(struct rx_packet *pkt, u_int pre, u_int off, void **p, u_int *rlen)
99 {
100     u_int len;
101     void *ptr;
102
103     len = rx_GetDataSize(pkt);
104     *rlen = len + pre;
105
106     ptr = malloc(*rlen);
107     if (ptr == NULL)
108         return ENOMEM;
109
110     *p = ptr;
111
112     ptr = (char *)ptr + pre;
113
114     if (rx_SlowReadPacket(pkt, off, len, ptr) != len) {
115         free(p);
116         *p = NULL;
117         return RXGKPACKETSHORT;
118     }
119     
120     return 0;
121 }
122
123 /*
124  *
125  */
126
127 static int
128 uiomove_from(struct rx_packet *pkt, u_int off, void *ptr, u_int len)
129 {
130     if (rx_SlowWritePacket(pkt, off, len, ptr) != len)
131         return RXGKPACKETSHORT;
132     rx_SetDataSize(pkt, len + off);
133
134     return 0;
135 }
136
137 /*
138  *
139  */
140 int
141 rxgk_prepare_packet(struct rx_packet *pkt, struct rx_connection *con,
142                     int level, key_stuff *k, end_stuff *e)
143 {
144     int ret, keyusage;
145     
146     
147
148     if (k->ks_scrypto == NULL)
149         return RXGKSEALEDINCON;
150
151     if (level == rxgk_crypt) {
152         krb5_data data;
153         struct rxgk_header_data hdr;
154         u_int len;
155         void *p;
156
157         if (rx_IsClientConn(con))
158             keyusage = RXGK_CLIENT_ENC_PACKETS;
159         else
160             keyusage = RXGK_SERVER_ENC_PACKETS;
161
162         ret = uiomove_to(pkt, RXGK_HEADER_DATA_SIZE, 
163                          rx_GetSecurityHeaderSize(con),
164                          &p, &len);
165         if (ret)
166             return ret;
167
168         rxgk_getheader(pkt, &hdr);
169         memcpy(p, &hdr, sizeof(hdr));
170
171         ret = krb5_encrypt(k->ks_context, k->ks_scrypto, 
172                            keyusage, p, len, &data);
173         if (ret) {
174             free(p);
175             return ret;
176         }
177
178         ret = uiomove_from(pkt, 0, data.data, data.length);
179
180         krb5_data_free(&data);
181         free(p);
182
183     } else if (level == rxgk_auth) {
184         if (rx_IsClientConn(con))
185             keyusage = RXGK_CLIENT_CKSUM_PACKETS;
186         else
187             keyusage = RXGK_SERVER_CKSUM_PACKETS;
188
189         abort();
190     } else
191         abort();
192
193     return ret;
194 }
195
196 /*
197  *
198  */
199 int
200 rxgk_check_packet(struct rx_packet *pkt, struct rx_connection *con,
201                   int level, key_stuff *k, end_stuff *e)
202 {
203     int ret, keyusage;
204     
205     if (k->ks_scrypto == NULL)
206         return RXGKSEALEDINCON;
207
208     ret = 0;
209
210     if (level == rxgk_crypt) {
211         krb5_data data;
212         struct rxgk_header_data hdr;
213         u_int len;
214         void *p;
215
216         if (rx_IsClientConn(con))
217             keyusage = RXGK_SERVER_ENC_PACKETS;
218         else
219             keyusage = RXGK_CLIENT_ENC_PACKETS;
220
221         ret = uiomove_to(pkt, 0, 0, &p, &len);
222         if (ret)
223             return ret;
224
225         ret = krb5_decrypt(k->ks_context, k->ks_scrypto, 
226                            keyusage, p, len, &data);
227         if (ret) {
228             free(p);
229             return ret;
230         }
231
232         ret = uiomove_from(pkt, rx_GetSecurityHeaderSize(con) - 
233                            RXGK_HEADER_DATA_SIZE,
234                            data.data, data.length);
235         if (ret == 0) {
236             rxgk_getheader(pkt, &hdr);
237             if (memcmp(&hdr, data.data, sizeof(hdr)) != 0)
238                 ret = RXGKSEALEDINCON;
239         }
240
241         krb5_data_free(&data);
242         free(p);
243     } else if (level == rxgk_auth) {
244         if (rx_IsClientConn(con))
245             keyusage = RXGK_SERVER_CKSUM_PACKETS;
246         else
247             keyusage = RXGK_CLIENT_CKSUM_PACKETS;
248
249
250         abort();
251     } else
252         abort();
253
254     return ret;
255 }