Whamcloud - gitweb
LU-8769 lnet: removal of obsolete LNDs
[fs/lustre-release.git] / lustre / utils / gss / context_heimdal.c
1 /*
2   Copyright (c) 2004-2006 The Regents of the University of Michigan.
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8
9   1. Redistributions of source code must retain the above copyright
10      notice, this list of conditions and the following disclaimer.
11   2. Redistributions in binary form must reproduce the above copyright
12      notice, this list of conditions and the following disclaimer in the
13      documentation and/or other materials provided with the distribution.
14   3. Neither the name of the University nor the names of its
15      contributors may be used to endorse or promote products derived
16      from this software without specific prior written permission.
17
18   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32
33 #ifndef HAVE_LUCID_CONTEXT_SUPPORT
34 #ifdef HAVE_HEIMDAL
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <syslog.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <krb5.h>
42 #include <gssapi.h>     /* Must use the heimdal copy! */
43 #ifdef HAVE_COM_ERR_H
44 #include <com_err.h>
45 #endif
46
47 #ifdef _NEW_BUILD_
48 # include "lgss_utils.h"
49 #else
50 # include "err_util.h"
51 # include "gss_oids.h"
52 #endif
53 #include "write_bytes.h"
54
55 int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
56 {
57         gss_buffer_desc tmp;
58         int code = -1;
59
60         if (WRITE_BYTES(p, end, key->keytype)) goto out_err;
61         tmp.length = key->keyvalue.length;
62         tmp.value = key->keyvalue.data;
63         if (write_buffer(p, end, &tmp)) goto out_err;
64         code = 0;
65     out_err:
66         return(code);
67 }
68
69 int write_heimdal_enc_key(char **p, char *end, gss_ctx_id_t ctx)
70 {
71         krb5_keyblock enc_key, *key;
72         krb5_context context;
73         krb5_error_code ret;
74         int i;
75         char *skd, *dkd;
76         int code = -1;
77
78         if ((ret = krb5_init_context(&context))) {
79                 printerr(0, "ERROR: initializing krb5_context: %s\n",
80                         error_message(ret));
81                 goto out_err;
82         }
83
84         if ((ret = krb5_auth_con_getlocalsubkey(context,
85                                                 ctx->auth_context, &key))){
86                 printerr(0, "ERROR: getting auth_context key: %s\n",
87                         error_message(ret));
88                 goto out_err_free_context;
89         }
90
91         memset(&enc_key, 0, sizeof(enc_key));
92         enc_key.keytype = key->keytype;
93         /* XXX current kernel code only handles des-cbc-raw  (4) */
94         if (enc_key.keytype != 4) {
95                 printerr(1, "WARN: write_heimdal_enc_key: "
96                             "overriding heimdal keytype (%d => %d)\n",
97                          enc_key.keytype, 4);
98                 enc_key.keytype = 4;
99         }
100         enc_key.keyvalue.length = key->keyvalue.length;
101         if ((enc_key.keyvalue.data =
102                                 calloc(1, enc_key.keyvalue.length)) == NULL) {
103
104                 printerr(0, "ERROR: allocating memory for enc key: %s\n",
105                         error_message(ENOMEM));
106                 goto out_err_free_key;
107         }
108         skd = (char *) key->keyvalue.data;
109         dkd = (char *) enc_key.keyvalue.data;
110         for (i = 0; i < enc_key.keyvalue.length; i++)
111                 dkd[i] = skd[i] ^ 0xf0;
112         if (write_heimdal_keyblock(p, end, &enc_key)) {
113                 goto out_err_free_enckey;
114         }
115
116         code = 0;
117
118     out_err_free_enckey:
119         krb5_free_keyblock_contents(context, &enc_key);
120     out_err_free_key:
121         krb5_free_keyblock(context, key);
122     out_err_free_context:
123         krb5_free_context(context);
124     out_err:
125         printerr(2, "write_heimdal_enc_key: %s\n", code ? "FAILED" : "SUCCESS");
126         return(code);
127 }
128
129 int write_heimdal_seq_key(char **p, char *end, gss_ctx_id_t ctx)
130 {
131         krb5_keyblock *key;
132         krb5_context context;
133         krb5_error_code ret;
134         int code = -1;
135
136         if ((ret = krb5_init_context(&context))) {
137                 printerr(0, "ERROR: initializing krb5_context: %s\n",
138                         error_message(ret));
139                 goto out_err;
140         }
141
142         if ((ret = krb5_auth_con_getlocalsubkey(context,
143                                                 ctx->auth_context, &key))){
144                 printerr(0, "ERROR: getting auth_context key: %s\n",
145                         error_message(ret));
146                 goto out_err_free_context;
147         }
148
149         /* XXX current kernel code only handles des-cbc-raw  (4) */
150         if (key->keytype != 4) {
151                 printerr(1, "WARN: write_heimdal_seq_key: "
152                             "overriding heimdal keytype (%d => %d)\n",
153                          key->keytype, 4);
154                 key->keytype = 4;
155         }
156
157         if (write_heimdal_keyblock(p, end, key)) {
158                 goto out_err_free_key;
159         }
160
161         code = 0;
162
163     out_err_free_key:
164         krb5_free_keyblock(context, key);
165     out_err_free_context:
166         krb5_free_context(context);
167     out_err:
168         printerr(2, "write_heimdal_seq_key: %s\n", code ? "FAILED" : "SUCCESS");
169         return(code);
170 }
171
172 /*
173  * The following is the kernel structure that we are filling in:
174  *
175  * struct krb5_ctx {
176  *         int                     initiate;
177  *         int                     seed_init;
178  *         unsigned char           seed[16];
179  *         int                     signalg;
180  *         int                     sealalg;
181  *         struct crypto_tfm       *enc;
182  *         struct crypto_tfm       *seq;
183  *         s32                     endtime;
184  *         u32                     seq_send;
185  *         struct xdr_netobj       mech_used;
186  * };
187  *
188  * However, note that we do not send the data fields in the
189  * order they appear in the structure.  The order they are
190  * sent down in is:
191  *
192  *      initiate
193  *      seed_init
194  *      seed
195  *      signalg
196  *      sealalg
197  *      endtime
198  *      seq_send
199  *      mech_used
200  *      enc key
201  *      seq key
202  *
203  */
204
205 int
206 serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
207 {
208
209         char *p, *end;
210         static int constant_one = 1;
211         static int constant_zero = 0;
212         unsigned char fakeseed[16];
213         uint32_t algorithm;
214
215         if (!(buf->value = calloc(1, MAX_CTX_LEN)))
216                 goto out_err;
217         p = buf->value;
218         end = buf->value + MAX_CTX_LEN;
219
220
221         /* initiate:  1 => initiating 0 => accepting */
222         if (ctx->more_flags & LOCAL) {
223                 if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
224         }
225         else {
226                 if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
227         }
228
229         /* seed_init: not used by kernel code */
230         if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
231
232         /* seed: not used by kernel code */
233         memset(&fakeseed, 0, sizeof(fakeseed));
234         if (write_bytes(&p, end, &fakeseed, 16)) goto out_err;
235
236         /* signalg */
237         algorithm = 0; /* SGN_ALG_DES_MAC_MD5   XXX */
238         if (WRITE_BYTES(&p, end, algorithm)) goto out_err;
239
240         /* sealalg */
241         algorithm = 0; /* SEAL_ALG_DES          XXX */
242         if (WRITE_BYTES(&p, end, algorithm)) goto out_err;
243
244         /* endtime */
245         if (WRITE_BYTES(&p, end, ctx->lifetime)) goto out_err;
246
247         /* seq_send */
248         if (WRITE_BYTES(&p, end, ctx->auth_context->local_seqnumber))
249                 goto out_err;
250         /* mech_used */
251         if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err;
252
253         /* enc: derive the encryption key and copy it into buffer */
254         if (write_heimdal_enc_key(&p, end, ctx)) goto out_err;
255
256         /* seq: get the sequence number key and copy it into buffer */
257         if (write_heimdal_seq_key(&p, end, ctx)) goto out_err;
258
259         buf->length = p - (char *)buf->value;
260         printerr(2, "serialize_krb5_ctx: returning buffer "
261                     "with %d bytes\n", buf->length);
262
263         return 0;
264 out_err:
265         printerr(0, "ERROR: failed exporting Heimdal krb5 ctx to kernel\n");
266         if (buf->value) free(buf->value);
267         buf->length = 0;
268         return -1;
269 }
270
271 #endif  /* HAVE_HEIMDAL */
272 #endif  /* HAVE_LUCID_CONTEXT_SUPPORT */